#include "packets.h"
#include "poll-loop.h"
#include "socket-util.h"
-#include "socket-util.h"
#include "util.h"
#include "stream-provider.h"
#include "stream.h"
* deadlock and livelock situations above.
*/
int rx_want, tx_want;
+
+ /* A few bytes of header data in case SSL negotation fails. */
+ uint8_t head[2];
+ short int n_head;
};
/* SSL context created by ssl_init(). */
sslv->ssl = ssl;
sslv->txbuf = NULL;
sslv->rx_want = sslv->tx_want = SSL_NOTHING;
+ sslv->n_head = 0;
*streamp = &sslv->stream;
return 0;
/* Fall through. */
case STATE_SSL_CONNECTING:
+ /* Capture the first few bytes of received data so that we can guess
+ * what kind of funny data we've been sent if SSL negotation fails. */
+ if (sslv->n_head <= 0) {
+ sslv->n_head = recv(sslv->fd, sslv->head, sizeof sslv->head,
+ MSG_PEEK);
+ }
+
retval = (sslv->type == CLIENT
? SSL_connect(sslv->ssl) : SSL_accept(sslv->ssl));
if (retval != 1) {
interpret_ssl_error((sslv->type == CLIENT ? "SSL_connect"
: "SSL_accept"), retval, error, &unused);
shutdown(sslv->fd, SHUT_RDWR);
+ stream_report_content(sslv->head, sslv->n_head, STREAM_SSL,
+ THIS_MODULE, stream_get_name(stream));
return EPROTO;
}
} else if (bootstrap_ca_cert) {
* background. */
SSL_shutdown(sslv->ssl);
+ /* SSL_shutdown() might have signaled an error, in which case we need to
+ * flush it out of the OpenSSL error queue or the next OpenSSL operation
+ * will falsely signal an error. */
+ ERR_clear_error();
+
SSL_free(sslv->ssl);
close(sslv->fd);
free(sslv);
return private_key.file_name || certificate.file_name || ca_cert.file_name;
}
-static void
-get_mtime(const char *file_name, struct timespec *mtime)
-{
- struct stat s;
-
- if (!stat(file_name, &s)) {
- mtime->tv_sec = s.st_mtime;
-
-#if HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
- mtime->tv_nsec = s.st_mtim.tv_nsec;
-#elif HAVE_STRUCT_STAT_ST_MTIMENSEC
- mtime->tv_nsec = s.st_mtimensec;
-#else
- mtime->tv_nsec = 0;
-#endif
- } else {
- mtime->tv_sec = mtime->tv_nsec = 0;
- }
-}
-
static bool
update_ssl_config(struct ssl_config_file *config, const char *file_name)
{
return false;
}
+ /* Update 'config'. */
config->mtime = mtime;
- free(config->file_name);
- config->file_name = xstrdup(file_name);
+ if (file_name != config->file_name) {
+ free(config->file_name);
+ config->file_name = xstrdup(file_name);
+ }
return true;
}