static int ssl_socket_open (CONNECTION * conn) { sslsockdata *data; int maxbits; if (raw_socket_open (conn) < 0) return -1; data = (sslsockdata *) safe_calloc (1, sizeof (sslsockdata)); conn->sockdata = data; data->ctx = SSL_CTX_new (SSLv23_client_method ()); /* disable SSL protocols as needed */ if (!option(OPTTLSV1)) { SSL_CTX_set_options(data->ctx, SSL_OP_NO_TLSv1); } /* TLSv1.1/1.2 support was added in OpenSSL 1.0.1, but some OS distros such * as Fedora 17 are on OpenSSL 1.0.0. */ #ifdef SSL_OP_NO_TLSv1_1 if (!option(OPTTLSV1_1)) { SSL_CTX_set_options(data->ctx, SSL_OP_NO_TLSv1_1); } #endif #ifdef SSL_OP_NO_TLSv1_2 if (!option(OPTTLSV1_2)) { SSL_CTX_set_options(data->ctx, SSL_OP_NO_TLSv1_2); } #endif if (!option(OPTSSLV2)) { SSL_CTX_set_options(data->ctx, SSL_OP_NO_SSLv2); } if (!option(OPTSSLV3)) { SSL_CTX_set_options(data->ctx, SSL_OP_NO_SSLv3); } ssl_get_client_cert(data, conn); data->ssl = SSL_new (data->ctx); SSL_set_fd (data->ssl, conn->fd); if (ssl_negotiate(conn, data)) { mutt_socket_close (conn); return -1; } data->isopen = 1; conn->ssf = SSL_CIPHER_get_bits (SSL_get_current_cipher (data->ssl), &maxbits); return 0; }
/* mutt_ssl_starttls: Negotiate TLS over an already opened connection. * TODO: Merge this code better with ssl_socket_open. */ int mutt_ssl_starttls (CONNECTION* conn) { sslsockdata* ssldata; int maxbits; long ssl_options = 0; if (ssl_init()) goto bail; ssldata = (sslsockdata*) safe_calloc (1, sizeof (sslsockdata)); /* the ssl_use_xxx protocol options don't apply. We must use TLS in TLS. * * However, we need to be able to negotiate amongst various TLS versions, * which at present can only be done with the SSLv23_client_method; * TLSv1_client_method gives us explicitly TLSv1.0, not 1.1 or 1.2 (True as * of OpenSSL 1.0.1c) */ if (! (ssldata->ctx = SSL_CTX_new (SSLv23_client_method()))) { dprint (1, (debugfile, "mutt_ssl_starttls: Error allocating SSL_CTX\n")); goto bail_ssldata; } #ifdef SSL_OP_NO_TLSv1_2 if (!option(OPTTLSV1_2)) ssl_options |= SSL_OP_NO_TLSv1_2; #endif #ifdef SSL_OP_NO_TLSv1_1 if (!option(OPTTLSV1_1)) ssl_options |= SSL_OP_NO_TLSv1_1; #endif #ifdef SSL_OP_NO_TLSv1 if (!option(OPTTLSV1)) ssl_options |= SSL_OP_NO_TLSv1; #endif /* these are always set */ #ifdef SSL_OP_NO_SSLv3 ssl_options |= SSL_OP_NO_SSLv3; #endif #ifdef SSL_OP_NO_SSLv2 ssl_options |= SSL_OP_NO_SSLv2; #endif if (! SSL_CTX_set_options(ssldata->ctx, ssl_options)) { dprint(1, (debugfile, "mutt_ssl_starttls: Error setting options to %ld\n", ssl_options)); goto bail_ctx; } ssl_get_client_cert(ssldata, conn); if (! (ssldata->ssl = SSL_new (ssldata->ctx))) { dprint (1, (debugfile, "mutt_ssl_starttls: Error allocating SSL\n")); goto bail_ctx; } if (SSL_set_fd (ssldata->ssl, conn->fd) != 1) { dprint (1, (debugfile, "mutt_ssl_starttls: Error setting fd\n")); goto bail_ssl; } if (ssl_negotiate (conn, ssldata)) goto bail_ssl; ssldata->isopen = 1; /* hmm. watch out if we're starting TLS over any method other than raw. */ conn->sockdata = ssldata; conn->conn_read = ssl_socket_read; conn->conn_write = ssl_socket_write; conn->conn_close = tls_close; conn->ssf = SSL_CIPHER_get_bits (SSL_get_current_cipher (ssldata->ssl), &maxbits); return 0; bail_ssl: FREE (&ssldata->ssl); bail_ctx: FREE (&ssldata->ctx); bail_ssldata: FREE (&ssldata); bail: return -1; }
/** * ssl_setup - Set up SSL on the Connection * @param conn Connection * @retval 0 Success * @retval -1 Failure */ static int ssl_setup(struct Connection *conn) { struct SslSockData *ssldata = NULL; int maxbits; ssldata = mutt_mem_calloc(1, sizeof(struct SslSockData)); conn->sockdata = ssldata; ssldata->sctx = SSL_CTX_new(SSLv23_client_method()); if (!ssldata->sctx) { /* L10N: an SSL context is a data structure returned by the OpenSSL function SSL_CTX_new(). In this case it returned NULL: an error condition. */ mutt_error(_("Unable to create SSL context")); ssl_dprint_err_stack(); goto free_sasldata; } /* disable SSL protocols as needed */ #ifdef SSL_OP_NO_TLSv1_2 if (!C_SslUseTlsv12) SSL_CTX_set_options(ssldata->sctx, SSL_OP_NO_TLSv1_2); #endif #ifdef SSL_OP_NO_TLSv1_1 if (!C_SslUseTlsv11) SSL_CTX_set_options(ssldata->sctx, SSL_OP_NO_TLSv1_1); #endif #ifdef SSL_OP_NO_TLSv1 if (!C_SslUseTlsv1) SSL_CTX_set_options(ssldata->sctx, SSL_OP_NO_TLSv1); #endif if (!C_SslUseSslv3) SSL_CTX_set_options(ssldata->sctx, SSL_OP_NO_SSLv3); if (!C_SslUseSslv2) SSL_CTX_set_options(ssldata->sctx, SSL_OP_NO_SSLv2); if (C_SslUsesystemcerts) { if (!SSL_CTX_set_default_verify_paths(ssldata->sctx)) { mutt_debug(LL_DEBUG1, "Error setting default verify paths\n"); goto free_ctx; } } if (C_CertificateFile && !ssl_load_certificates(ssldata->sctx)) mutt_debug(LL_DEBUG1, "Error loading trusted certificates\n"); ssl_get_client_cert(ssldata, conn); if (C_SslCiphers) { SSL_CTX_set_cipher_list(ssldata->sctx, C_SslCiphers); } if (ssl_set_verify_partial(ssldata->sctx)) { mutt_error(_("Warning: error enabling ssl_verify_partial_chains")); } ssldata->ssl = SSL_new(ssldata->sctx); SSL_set_fd(ssldata->ssl, conn->fd); if (ssl_negotiate(conn, ssldata)) goto free_ssl; ssldata->isopen = 1; conn->ssf = SSL_CIPHER_get_bits(SSL_get_current_cipher(ssldata->ssl), &maxbits); return 0; free_ssl: SSL_free(ssldata->ssl); ssldata->ssl = 0; free_ctx: SSL_CTX_free(ssldata->sctx); ssldata->sctx = 0; free_sasldata: FREE(&ssldata); return -1; }
static int ssl_socket_open (CONNECTION * conn) { sslsockdata *data; int maxbits; if (raw_socket_open (conn) < 0) return -1; data = (sslsockdata *) safe_calloc (1, sizeof (sslsockdata)); conn->sockdata = data; if (! (data->ctx = SSL_CTX_new (SSLv23_client_method ()))) { /* L10N: an SSL context is a data structure returned by the OpenSSL * function SSL_CTX_new(). In this case it returned NULL: an * error condition. */ mutt_error (_("Unable to create SSL context")); ssl_dprint_err_stack (); mutt_socket_close (conn); return -1; } /* disable SSL protocols as needed */ if (!option(OPTTLSV1)) { SSL_CTX_set_options(data->ctx, SSL_OP_NO_TLSv1); } /* TLSv1.1/1.2 support was added in OpenSSL 1.0.1, but some OS distros such * as Fedora 17 are on OpenSSL 1.0.0. */ #ifdef SSL_OP_NO_TLSv1_1 if (!option(OPTTLSV1_1)) { SSL_CTX_set_options(data->ctx, SSL_OP_NO_TLSv1_1); } #endif #ifdef SSL_OP_NO_TLSv1_2 if (!option(OPTTLSV1_2)) { SSL_CTX_set_options(data->ctx, SSL_OP_NO_TLSv1_2); } #endif if (!option(OPTSSLV2)) { SSL_CTX_set_options(data->ctx, SSL_OP_NO_SSLv2); } if (!option(OPTSSLV3)) { SSL_CTX_set_options(data->ctx, SSL_OP_NO_SSLv3); } ssl_get_client_cert(data, conn); if (SslCiphers) { SSL_CTX_set_cipher_list (data->ctx, SslCiphers); } data->ssl = SSL_new (data->ctx); SSL_set_fd (data->ssl, conn->fd); if (ssl_negotiate(conn, data)) { mutt_socket_close (conn); return -1; } data->isopen = 1; conn->ssf = SSL_CIPHER_get_bits (SSL_get_current_cipher (data->ssl), &maxbits); return 0; }