X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fstream-ssl.c;h=c2a77a008a7840e679f9d4e68d4c3c5f80bf5930;hb=15c93f417f8dd87f1655448b7c4c59e3fb8b5aba;hp=153357cd78ea7a27eaa3d0f011455e9cc302cfa8;hpb=ba104a1e39de45a2f33da0a132a17646da1ef931;p=openvswitch diff --git a/lib/stream-ssl.c b/lib/stream-ssl.c index 153357cd..c2a77a00 100644 --- a/lib/stream-ssl.c +++ b/lib/stream-ssl.c @@ -37,7 +37,6 @@ #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" @@ -125,6 +124,10 @@ struct ssl_stream * 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(). */ @@ -265,6 +268,7 @@ new_ssl_stream(const char *name, int fd, enum session_type type, sslv->ssl = ssl; sslv->txbuf = NULL; sslv->rx_want = sslv->tx_want = SSL_NOTHING; + sslv->n_head = 0; *streamp = &sslv->stream; return 0; @@ -415,6 +419,13 @@ ssl_connect(struct stream *stream) /* 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) { @@ -426,6 +437,8 @@ ssl_connect(struct stream *stream) 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) { @@ -465,6 +478,11 @@ ssl_close(struct stream *stream) * 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); @@ -915,26 +933,6 @@ stream_ssl_is_configured(void) 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) { @@ -954,9 +952,12 @@ 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; }