wi_string_t * wi_socket_cipher_name(wi_socket_t *socket) { #ifdef HAVE_OPENSSL_SSL_H return wi_string_with_cstring(SSL_get_cipher_name(socket->ssl)); #else return NULL; #endif }
const char* io_strio(struct io *io) { static char buf[128]; char ssl[128]; ssl[0] = '\0'; #ifdef IO_SSL if (io->ssl) { (void)snprintf(ssl, sizeof ssl, " ssl=%s:%s:%d", SSL_get_version(io->ssl), SSL_get_cipher_name(io->ssl), SSL_get_cipher_bits(io->ssl, NULL)); } #endif if (io->iobuf == NULL) (void)snprintf(buf, sizeof buf, "<io:%p fd=%d to=%d fl=%s%s>", io, io->sock, io->timeout, io_strflags(io->flags), ssl); else (void)snprintf(buf, sizeof buf, "<io:%p fd=%d to=%d fl=%s%s ib=%zu ob=%zu>", io, io->sock, io->timeout, io_strflags(io->flags), ssl, io_pending(io), io_queued(io)); return (buf); }
unsigned char * get_ssl_connection_cipher(struct socket *socket) { ssl_t *ssl = socket->ssl; struct string str; if (!init_string(&str)) return NULL; #ifdef USE_OPENSSL add_format_to_string(&str, "%ld-bit %s %s", SSL_get_cipher_bits(ssl, NULL), SSL_get_cipher_version(ssl), SSL_get_cipher_name(ssl)); #elif defined(CONFIG_GNUTLS) /* XXX: How to get other relevant parameters? */ add_format_to_string(&str, "%s - %s - %s - %s - %s (compr: %s)", gnutls_protocol_get_name(gnutls_protocol_get_version(*ssl)), gnutls_kx_get_name(gnutls_kx_get(*ssl)), gnutls_cipher_get_name(gnutls_cipher_get(*ssl)), gnutls_mac_get_name(gnutls_mac_get(*ssl)), gnutls_certificate_type_get_name(gnutls_certificate_type_get(*ssl)), gnutls_compression_get_name(gnutls_compression_get(*ssl))); #endif return str.source; }
/** * Callback used for debugging */ static void sslLogCallback(const SSL *ssl, int where, int ret) { const char *retstr = ""; int should_log = 1; /* Ignore low-level SSL stuff */ if (where & SSL_CB_ALERT) { should_log = 1; } if (where == SSL_CB_HANDSHAKE_START || where == SSL_CB_HANDSHAKE_DONE) { should_log = 1; } if ((where & SSL_CB_EXIT) && ret == 0) { should_log = 1; } if (!should_log) { return; } retstr = SSL_alert_type_string(ret); printf("ST(0x%x). %s. R(0x%x)%s\n", where, SSL_state_string_long(ssl), ret, retstr); if (where == SSL_CB_HANDSHAKE_DONE) { printf("Using SSL version %s. Cipher=%s\n", SSL_get_version(ssl), SSL_get_cipher_name(ssl)); } }
static void __apn_ssl_info_callback(const SSL *ssl, int where, int ret) { apn_ctx_t *ctx = SSL_CTX_get_ex_data(ssl->ctx, 0); if (!ctx) { return; } if (where & SSL_CB_LOOP) { apn_log(ctx, APN_LOG_LEVEL_INFO, "ssl: %s:%s:%s", (where & SSL_ST_CONNECT) ? "connect" : "undef", SSL_state_string_long(ssl), SSL_get_cipher_name(ssl)); } else if (where & SSL_CB_EXIT) { apn_log(ctx, APN_LOG_LEVEL_INFO, "ssl: %s:%s", (where & SSL_ST_CONNECT) ? "connect" : "undef", SSL_state_string_long(ssl)); } else if (where & SSL_CB_ALERT) { apn_log(ctx, APN_LOG_LEVEL_INFO, "ssl: alert %s:%s", (where & SSL_CB_READ) ? "read" : "write", SSL_state_string_long(ssl), SSL_alert_desc_string_long(ret)); } else if (where & SSL_CB_HANDSHAKE_START) { apn_log(ctx, APN_LOG_LEVEL_INFO, "ssl: handshake started %s:%s:%s", (where & SSL_CB_READ) ? "read" : "write", SSL_state_string_long(ssl), SSL_alert_desc_string_long(ret)); } else if (where & SSL_CB_HANDSHAKE_DONE) { apn_log(ctx, APN_LOG_LEVEL_INFO, "ssl: handshake done %s:%s:%s", (where & SSL_CB_READ) ? "read" : "write", SSL_state_string_long(ssl), SSL_alert_desc_string_long(ret)); } else { apn_log(ctx, APN_LOG_LEVEL_INFO, "ssl: state %s:%s:%s", SSL_state_string_long(ssl), SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret)); } }
std::string SSLSocket::getEncryptionInfo() const noexcept { if (!ssl) return Util::emptyString; string cipher = SSL_get_cipher_name(ssl); string protocol = SSL_get_version(ssl); return protocol + " / " + cipher; }
bool OpenSSLBase::handshake() { doTLSOperation( TLSHandshake ); if( !m_secure ) return true; int res = SSL_get_verify_result( m_ssl ); if( res != X509_V_OK ) m_certInfo.status = CertInvalid; else m_certInfo.status = CertOk; X509* peer = SSL_get_peer_certificate( m_ssl ); if( peer ) { char peer_CN[256]; X509_NAME_get_text_by_NID( X509_get_issuer_name( peer ), NID_commonName, peer_CN, sizeof( peer_CN ) ); m_certInfo.issuer = peer_CN; X509_NAME_get_text_by_NID( X509_get_subject_name( peer ), NID_commonName, peer_CN, sizeof( peer_CN ) ); m_certInfo.server = peer_CN; m_certInfo.date_from = openSSLTime2UnixTime( (char*) (peer->cert_info->validity->notBefore->data) ); m_certInfo.date_to = openSSLTime2UnixTime( (char*) (peer->cert_info->validity->notAfter->data) ); std::string p( peer_CN ); std::transform( p.begin(), p.end(), p.begin(), tolower ); if( p != m_server ) m_certInfo.status |= CertWrongPeer; if( ASN1_UTCTIME_cmp_time_t( X509_get_notBefore( peer ), time( 0 ) ) != -1 ) m_certInfo.status |= CertNotActive; if( ASN1_UTCTIME_cmp_time_t( X509_get_notAfter( peer ), time( 0 ) ) != 1 ) m_certInfo.status |= CertExpired; } else { m_certInfo.status = CertInvalid; } const char* tmp; tmp = SSL_get_cipher_name( m_ssl ); if( tmp ) m_certInfo.cipher = tmp; tmp = SSL_get_cipher_version( m_ssl ); if( tmp ) m_certInfo.protocol = tmp; tmp = SSL_COMP_get_name( SSL_get_current_compression( m_ssl ) ); if( tmp ) m_certInfo.compression = tmp; m_valid = true; m_handler->handleHandshakeResult( this, true, m_certInfo ); return true; }
const char* irc_get_ssl_ciphers_used(irc_session_t *session) { const char *ciphers_used = "None"; if (session->ssl != NULL) { ciphers_used = SSL_get_cipher_name(session->ssl); } return ciphers_used; }
const char * ssl_to_text(const SSL *ssl) { static char buf[256]; (void)snprintf(buf, sizeof buf, "version=%s, cipher=%s, bits=%d", SSL_get_cipher_version(ssl), SSL_get_cipher_name(ssl), SSL_get_cipher_bits(ssl, NULL)); return (buf); }
/** wrapper around SSL_connect, using SSL return convention. * It will also log critical errors and certificate debugging info. * @param c - tcp connection with tls (extra_data must be a filled * tcp_extra_data structure). The state must be S_TLS_CONNECTING. * @param error set to the error reason (SSL_ERROR_*). * Note that it can be SSL_ERROR_NONE while the return is < 0 * ("internal" error, not at the SSL level, see below). * @return >=1 on success, 0 and <0 on error. 0 means the underlying SSL * connection was closed/shutdown. < 0 is returned for any * SSL_ERROR (including WANT_READ or WANT_WRITE), but also * for internal non SSL related errors (in this case -2 is * returned and error==SSL_ERROR_NONE). * */ int tls_connect(struct tcp_connection *c, int* error) { SSL *ssl; int ret; X509* cert; struct tls_extra_data* tls_c; int tls_log; *error = SSL_ERROR_NONE; tls_c=(struct tls_extra_data*)c->extra_data; ssl=tls_c->ssl; if (unlikely(tls_c->state != S_TLS_CONNECTING)) { BUG("Invalid connection state %d (bug in TLS code)\n", tls_c->state); goto err; } ret = SSL_connect(ssl); if (unlikely(ret == 1)) { DBG("TLS connect successful\n"); tls_c->state = S_TLS_ESTABLISHED; tls_log = cfg_get(tls, tls_cfg, log); LOG(tls_log, "tls_connect: new connection to %s:%d using %s %s %d\n", ip_addr2a(&c->rcv.src_ip), c->rcv.src_port, SSL_get_cipher_version(ssl), SSL_get_cipher_name(ssl), SSL_get_cipher_bits(ssl, 0) ); LOG(tls_log, "tls_connect: sending socket: %s:%d \n", ip_addr2a(&c->rcv.dst_ip), c->rcv.dst_port ); cert = SSL_get_peer_certificate(ssl); if (cert != 0) { tls_dump_cert_info("tls_connect: server certificate", cert); if (SSL_get_verify_result(ssl) != X509_V_OK) { LOG(tls_log, "WARNING: tls_connect: server certificate " "verification failed!!!\n"); tls_dump_verification_failure(SSL_get_verify_result(ssl)); } X509_free(cert); } else { /* this should not happen, servers always present a cert */ LOG(tls_log, "tls_connect: server did not " "present a certificate\n"); } tls_run_event_routes(c); } else { /* 0 or < 0 */ *error = SSL_get_error(ssl, ret); } return ret; err: /* internal non openssl related errors */ return -2; }
CipherInfo TCPConnection::GetCipherInfo() { if (!is_ssl_) { throw std::logic_error("Session is not SSL/TLS. Cipher info cannot be retrieved."); } auto ssl_handle = ssl_socket_.native_handle(); AnsiString name = SSL_get_cipher_name(ssl_handle); AnsiString version = SSL_get_version(ssl_handle); int bits = SSL_get_cipher_bits(ssl_handle, 0); return CipherInfo(name, version, bits); }
/** wrapper around SSL_accept, usin SSL return convention. * It will also log critical errors and certificate debugging info. * @param c - tcp connection with tls (extra_data must be a filled * tcp_extra_data structure). The state must be S_TLS_ACCEPTING. * @param error set to the error reason (SSL_ERROR_*). * Note that it can be SSL_ERROR_NONE while the return is < 0 * ("internal" error, not at the SSL level, see below). * @return >=1 on success, 0 and <0 on error. 0 means the underlying SSL * connection was closed/shutdown. < 0 is returned for any * SSL_ERROR (including WANT_READ or WANT_WRITE), but also * for internal non SSL related errors (in this case -2 is * returned and error==SSL_ERROR_NONE). * */ int tls_accept(struct tcp_connection *c, int* error) { int ret; SSL *ssl; X509* cert; struct tls_extra_data* tls_c; int tls_log; *error = SSL_ERROR_NONE; tls_c=(struct tls_extra_data*)c->extra_data; ssl=tls_c->ssl; if (unlikely(tls_c->state != S_TLS_ACCEPTING)) { BUG("Invalid connection state %d (bug in TLS code)\n", tls_c->state); goto err; } ret = SSL_accept(ssl); if (unlikely(ret == 1)) { DBG("TLS accept successful\n"); tls_c->state = S_TLS_ESTABLISHED; tls_log = cfg_get(tls, tls_cfg, log); LOG(tls_log, "tls_accept: new connection from %s:%d using %s %s %d\n", ip_addr2a(&c->rcv.src_ip), c->rcv.src_port, SSL_get_cipher_version(ssl), SSL_get_cipher_name(ssl), SSL_get_cipher_bits(ssl, 0) ); LOG(tls_log, "tls_accept: local socket: %s:%d\n", ip_addr2a(&c->rcv.dst_ip), c->rcv.dst_port ); cert = SSL_get_peer_certificate(ssl); if (cert != 0) { tls_dump_cert_info("tls_accept: client certificate", cert); if (SSL_get_verify_result(ssl) != X509_V_OK) { LOG(tls_log, "WARNING: tls_accept: client certificate " "verification failed!!!\n"); tls_dump_verification_failure(SSL_get_verify_result(ssl)); } X509_free(cert); } else { LOG(tls_log, "tls_accept: client did not present a certificate\n"); } } else { /* ret == 0 or < 0 */ *error = SSL_get_error(ssl, ret); } return ret; err: /* internal non openssl related errors */ return -2; }
/* ssl_negotiate: After SSL state has been initialised, attempt to negotiate * SSL over the wire, including certificate checks. */ static int ssl_negotiate (CONNECTION *conn, sslsockdata* ssldata) { int err; const char* errmsg; #if OPENSSL_VERSION_NUMBER >= 0x00906000L /* This only exists in 0.9.6 and above. Without it we may get interrupted * reads or writes. Bummer. */ SSL_set_mode (ssldata->ssl, SSL_MODE_AUTO_RETRY); #endif if ((err = SSL_connect (ssldata->ssl)) != 1) { switch (SSL_get_error (ssldata->ssl, err)) { case SSL_ERROR_SYSCALL: errmsg = _("I/O error"); break; case SSL_ERROR_SSL: errmsg = ERR_error_string (ERR_get_error (), NULL); break; default: errmsg = _("unknown error"); } mutt_error (_("SSL failed: %s"), errmsg); mutt_sleep (1); return -1; } ssldata->cert = SSL_get_peer_certificate (ssldata->ssl); if (!ssldata->cert) { mutt_error (_("Unable to get certificate from peer")); mutt_sleep (1); return -1; } if (!ssl_check_certificate (conn, ssldata)) return -1; mutt_message (_("%s connection using %s (%s)"), SSL_get_version(ssldata->ssl), SSL_get_cipher_version (ssldata->ssl), SSL_get_cipher_name (ssldata->ssl)); mutt_sleep (0); return 0; }
/* ssl_negotiate: After SSL state has been initialized, attempt to negotiate * SSL over the wire, including certificate checks. */ static int ssl_negotiate (CONNECTION *conn, sslsockdata* ssldata) { int err; const char* errmsg; SSL_set_mode (ssldata->ssl, SSL_MODE_AUTO_RETRY); if ((err = SSL_connect (ssldata->ssl)) != 1) { switch (SSL_get_error (ssldata->ssl, err)) { case SSL_ERROR_SYSCALL: errmsg = _("I/O error"); break; case SSL_ERROR_SSL: errmsg = ERR_error_string (ERR_get_error (), NULL); break; default: errmsg = _("unknown error"); } mutt_error (_("SSL failed: %s"), errmsg); mutt_sleep (1); return -1; } ssldata->cert = SSL_get_peer_certificate (ssldata->ssl); if (!ssldata->cert) { mutt_error (_("Unable to get certificate from peer")); mutt_sleep (1); return -1; } if (!ssl_check_certificate (conn, ssldata)) return -1; /* L10N: %1$s is version (e.g. "TLSv1.2") %2$s is cipher_version (e.g. "TLSv1/SSLv3") %3$s is cipher_name (e.g. "ECDHE-RSA-AES128-GCM-SHA256") */ mutt_message (_("%s connection using %s (%s)"), SSL_get_version(ssldata->ssl), SSL_get_cipher_version (ssldata->ssl), SSL_get_cipher_name (ssldata->ssl)); mutt_sleep (0); return 0; }
int verify_ssl_cipher(SSL *ssl) { unsigned char *cipher; #ifdef HAVE_SSLV2_CLIENT_METHOD if (SSL_get_ssl_method(ssl) == SSLv2_client_method()) return S_INSECURE_CIPHER; #endif #ifdef HAVE_SSLV3_CLIENT_METHOD if (SSL_get_ssl_method(ssl) == SSLv3_client_method()) return S_INSECURE_CIPHER; #endif if (SSL_get_cipher_bits(ssl, NULL) < 112) return S_INSECURE_CIPHER; cipher = cast_uchar SSL_get_cipher_name(ssl); if (cipher && strstr(cast_const_char cipher, "RC4-")) return S_INSECURE_CIPHER; return 0; }
void SSL_CTX_info_callback(const SSL* ssl, int where, int ret) { FUNC_ENTRY; if (where & SSL_CB_LOOP) { Log(TRACE_PROTOCOL, 1, "SSL state %s:%s:%s", (where & SSL_ST_CONNECT) ? "connect" : (where & SSL_ST_ACCEPT) ? "accept" : "undef", SSL_state_string_long(ssl), SSL_get_cipher_name(ssl)); } else if (where & SSL_CB_EXIT) { Log(TRACE_PROTOCOL, 1, "SSL %s:%s", (where & SSL_ST_CONNECT) ? "connect" : (where & SSL_ST_ACCEPT) ? "accept" : "undef", SSL_state_string_long(ssl)); } else if (where & SSL_CB_ALERT) { Log(TRACE_PROTOCOL, 1, "SSL alert %s:%s:%s", (where & SSL_CB_READ) ? "read" : "write", SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret)); } else if (where & SSL_CB_HANDSHAKE_START) { Log(TRACE_PROTOCOL, 1, "SSL handshake started %s:%s:%s", (where & SSL_CB_READ) ? "read" : "write", SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret)); } else if (where & SSL_CB_HANDSHAKE_DONE) { Log(TRACE_PROTOCOL, 1, "SSL handshake done %s:%s:%s", (where & SSL_CB_READ) ? "read" : "write", SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret)); Log(TRACE_PROTOCOL, 1, "SSL certificate verification: %s", SSL_get_verify_result_string(SSL_get_verify_result(ssl))); } else { Log(TRACE_PROTOCOL, 1, "SSL state %s:%s:%s", SSL_state_string_long(ssl), SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret)); } FUNC_EXIT; }
int ssl_session_vars(SSL *ssl) { char *x; SSL_SESSION *session; int n; int m; const SSL_CIPHER *cipher; unsigned char u; unsigned char c; if (!env_str("SSL_PROTOCOL",SSL_get_version(ssl))) return 0; session = SSL_get_session(ssl); x = session->session_id; n = session->session_id_length; if (!stralloc_ready(&btemp,2 * n)) return 0; btemp.len = 2 * n; while (n--) { u = x[n]; c = '0' + (u & 15); if (c > '0' + 9) c += 'a' - '0' - 10; btemp.s[2 * n + 1] = c; u >>= 4; c = '0' + (u & 15); if (c > '0' + 9) c += 'a' - '0' - 10; btemp.s[2 * n] = c; } if (!env_val("SSL_SESSION_ID",btemp.s,btemp.len)) return 0; if (!env_str("SSL_CIPHER",SSL_get_cipher_name(ssl))) return 0; cipher = SSL_get_current_cipher(ssl); if (!cipher) return 0; n = SSL_CIPHER_get_bits(cipher,&m); if (!env_str("SSL_CIPHER_EXPORT",n < 56 ? "true" : "false")) return 0; if (!env_val("SSL_CIPHER_USEKEYSIZE",strnum,fmt_ulong(strnum,n))) return 0; if (!env_val("SSL_CIPHER_ALGKEYSIZE",strnum,fmt_ulong(strnum,m))) return 0; if (!env_str("SSL_VERSION_INTERFACE","ucspi-ssl")) return 0; if (!env_str("SSL_VERSION_LIBRARY",OPENSSL_VERSION_TEXT)) return 0; return 1; }
/** * We directly initiate a TLS handshake with the server. If the server is old * version (does not speak TLS) the connection will be denied. * @note the socket file descriptor in #conn_info must be connected and *not* * non-blocking * @return -1 in case of error */ int TLSTry(ConnectionInfo *conn_info) { /* SSL Context might not be initialised up to now due to lack of keys, as * they might be generated as part of the policy (e.g. failsafe.cf). */ if (!TLSClientInitialize()) { return -1; } assert(SSLCLIENTCONTEXT != NULL && PRIVKEY != NULL && PUBKEY != NULL); ConnectionInfoSetSSL(conn_info, SSL_new(SSLCLIENTCONTEXT)); SSL *ssl = ConnectionInfoSSL(conn_info); if (ssl == NULL) { Log(LOG_LEVEL_ERR, "SSL_new: %s", ERR_reason_error_string(ERR_get_error())); return -1; } /* Pass conn_info inside the ssl struct for TLSVerifyCallback(). */ SSL_set_ex_data(ssl, CONNECTIONINFO_SSL_IDX, conn_info); /* Initiate the TLS handshake over the already open TCP socket. */ SSL_set_fd(ssl, ConnectionInfoSocket(conn_info)); int ret = SSL_connect(ssl); if (ret <= 0) { TLSLogError(ssl, LOG_LEVEL_ERR, "Failed to establish TLS connection", ret); return -1; } Log(LOG_LEVEL_VERBOSE, "TLS cipher negotiated: %s, %s", SSL_get_cipher_name(ssl), SSL_get_cipher_version(ssl)); Log(LOG_LEVEL_VERBOSE, "TLS session established, checking trust..."); return 0; }
/** * We directly initiate a TLS handshake with the server. If the server is old * version (does not speak TLS) the connection will be denied. * @note the socket file descriptor in #conn_info must be connected and *not* * non-blocking * @return -1 in case of error */ int TLSTry(ConnectionInfo *conn_info) { if (PRIVKEY == NULL || PUBKEY == NULL) { Log(LOG_LEVEL_ERR, "No public/private key pair is loaded," " please create one using cf-key"); return -1; } assert(SSLCLIENTCONTEXT != NULL); conn_info->ssl = SSL_new(SSLCLIENTCONTEXT); if (conn_info->ssl == NULL) { Log(LOG_LEVEL_ERR, "SSL_new: %s", TLSErrorString(ERR_get_error())); return -1; } /* Pass conn_info inside the ssl struct for TLSVerifyCallback(). */ SSL_set_ex_data(conn_info->ssl, CONNECTIONINFO_SSL_IDX, conn_info); /* Initiate the TLS handshake over the already open TCP socket. */ SSL_set_fd(conn_info->ssl, conn_info->sd); int ret = SSL_connect(conn_info->ssl); if (ret <= 0) { TLSLogError(conn_info->ssl, LOG_LEVEL_ERR, "Failed to establish TLS connection", ret); return -1; } Log(LOG_LEVEL_VERBOSE, "TLS version negotiated: %8s; Cipher: %s,%s", SSL_get_version(conn_info->ssl), SSL_get_cipher_name(conn_info->ssl), SSL_get_cipher_version(conn_info->ssl)); Log(LOG_LEVEL_VERBOSE, "TLS session established, checking trust..."); return 0; }
const char * ssl_to_text(const SSL *ssl) { static char buf[256]; static char description[128]; char *tls_version = NULL; /* * SSL_get_cipher_version() does not know about the exact TLS version... * you have to pick it up from second field of the SSL cipher description ! */ SSL_CIPHER_description(SSL_get_current_cipher(ssl), description, sizeof description); tls_version = strchr(description, ' ') + 1; tls_version[strcspn(tls_version, " ")] = '\0'; (void)snprintf(buf, sizeof buf, "version=%s (%s), cipher=%s, bits=%d", SSL_get_cipher_version(ssl), tls_version, SSL_get_cipher_name(ssl), SSL_get_cipher_bits(ssl, NULL)); return (buf); }
bool SSLConnection::doOpen() { if (!did_init) return false; ctx = SSL_CTX_new (SSLv23_client_method ()); /* disable SSL protocols as needed */ if (!UseTLS1) { SSL_CTX_set_options (ctx, SSL_OP_NO_TLSv1); } if (!UseSSL3) { SSL_CTX_set_options (ctx, SSL_OP_NO_SSLv3); } if (!UseTLS1 && !UseSSL3) return false; getClientCert (); ssl = SSL_new (ctx); SSL_set_fd (ssl,fd); if (!negotiate ()) return false; int maxbits; ssf = SSL_CIPHER_get_bits (SSL_get_current_cipher (ssl),&maxbits); buffer_t msg; buffer_init(&msg); buffer_add_str(&msg,_("SSL/TLS connection using "),-1); buffer_add_str(&msg,SSL_get_cipher_version(ssl),-1); buffer_add_str(&msg," (",2); buffer_add_str(&msg,SSL_get_cipher_name(ssl),-1); buffer_add_ch(&msg,')'); displayProgress.emit(&msg); buffer_free(&msg); return true; }
const char *ma_tls_get_cipher(MARIADB_TLS *ctls) { if (!ctls || !ctls->ssl) return NULL; return SSL_get_cipher_name(ctls->ssl); }
static int ssl_do(struct st_VioSSLFd *ptr, Vio *vio, long timeout, ssl_handshake_func_t func, unsigned long *ssl_errno_holder) { int r; SSL *ssl; my_socket sd= mysql_socket_getfd(vio->mysql_socket); DBUG_ENTER("ssl_do"); DBUG_PRINT("enter", ("ptr: 0x%lx, sd: %d ctx: 0x%lx", (long) ptr, sd, (long) ptr->ssl_context)); if (!(ssl= SSL_new(ptr->ssl_context))) { DBUG_PRINT("error", ("SSL_new failure")); *ssl_errno_holder= ERR_get_error(); DBUG_RETURN(1); } DBUG_PRINT("info", ("ssl: 0x%lx timeout: %ld", (long) ssl, timeout)); SSL_clear(ssl); SSL_SESSION_set_timeout(SSL_get_session(ssl), timeout); SSL_set_fd(ssl, sd); #ifndef HAVE_YASSL SSL_set_options(ssl, SSL_OP_NO_COMPRESSION); #endif /* Since yaSSL does not support non-blocking send operations, use special transport functions that properly handles non-blocking sockets. These functions emulate the behavior of blocking I/O operations by waiting for I/O to become available. */ #ifdef HAVE_YASSL /* Set first argument of the transport functions. */ yaSSL_transport_set_ptr(ssl, vio); /* Set functions to use in order to send and receive data. */ yaSSL_transport_set_recv_function(ssl, yassl_recv); yaSSL_transport_set_send_function(ssl, yassl_send); #endif if ((r= ssl_handshake_loop(vio, ssl, func, ssl_errno_holder)) < 1) { DBUG_PRINT("error", ("SSL_connect/accept failure")); SSL_free(ssl); DBUG_RETURN(1); } /* Connection succeeded. Install new function handlers, change type, set sd to the fd used when connecting and set pointer to the SSL structure */ if (vio_reset(vio, VIO_TYPE_SSL, SSL_get_fd(ssl), ssl, 0)) DBUG_RETURN(1); #ifndef DBUG_OFF { /* Print some info about the peer */ X509 *cert; char buf[512]; DBUG_PRINT("info",("SSL connection succeeded")); DBUG_PRINT("info",("Using cipher: '%s'" , SSL_get_cipher_name(ssl))); if ((cert= SSL_get_peer_certificate (ssl))) { DBUG_PRINT("info",("Peer certificate:")); X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); DBUG_PRINT("info",("\t subject: '%s'", buf)); X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf)); DBUG_PRINT("info",("\t issuer: '%s'", buf)); X509_free(cert); } else DBUG_PRINT("info",("Peer does not have certificate.")); if (SSL_get_shared_ciphers(ssl, buf, sizeof(buf))) { DBUG_PRINT("info",("shared_ciphers: '%s'", buf)); } else DBUG_PRINT("info",("no shared ciphers!")); } #endif DBUG_RETURN(0); }
void http_got_header(struct connection *c, struct read_buffer *rb) { int cf; int state = c->state != S_PROC ? S_GETH : S_PROC; unsigned char *head; unsigned char *cookie, *ch; int a, h, version; unsigned char *d; struct cache_entry *e; struct http_connection_info *info; unsigned char *host = upcase(c->url[0]) != 'P' ? c->url : get_url_data(c->url); set_timeout(c); info = c->info; if (rb->close == 2) { unsigned char *h; if (!c->tries && (h = get_host_name(host))) { if (info->bl_flags & BL_NO_CHARSET) { del_blacklist_entry(h, BL_NO_CHARSET); } else { add_blacklist_entry(h, BL_NO_CHARSET); c->tries = -1; } mem_free(h); } setcstate(c, S_CANT_READ); retry_connection(c); return; } rb->close = 0; again: if ((a = get_header(rb)) == -1) { setcstate(c, S_HTTP_ERROR); abort_connection(c); return; } if (!a) { read_from_socket(c, c->sock1, rb, http_got_header); setcstate(c, state); return; } if (a != -2) { head = mem_alloc(a + 1); memcpy(head, rb->data, a); head[a] = 0; kill_buffer_data(rb, a); } else { head = stracpy("HTTP/0.9 200 OK\r\nContent-Type: text/html\r\n\r\n"); } if (get_http_code(head, &h, &version) || h == 101) { mem_free(head); setcstate(c, S_HTTP_ERROR); abort_connection(c); return; } if (check_http_server_bugs(host, c->info, head) && is_connection_restartable(c)) { mem_free(head); setcstate(c, S_RESTART); retry_connection(c); return; } ch = head; while ((cookie = parse_http_header(ch, "Set-Cookie", &ch))) { unsigned char *host = upcase(c->url[0]) != 'P' ? c->url : get_url_data(c->url); set_cookie(NULL, host, cookie); mem_free(cookie); } if (h == 100) { mem_free(head); state = S_PROC; goto again; } if (h < 200) { mem_free(head); setcstate(c, S_HTTP_ERROR); abort_connection(c); return; } if (h == 204) { mem_free(head); setcstate(c, S_HTTP_204); http_end_request(c, 0); return; } if (h == 304) { mem_free(head); setcstate(c, S_OK); http_end_request(c, 1); return; } if ((h == 500 || h == 502 || h == 503 || h == 504) && http_bugs.retry_internal_errors && is_connection_restartable(c)) { /* !!! FIXME: wait some time ... */ mem_free(head); setcstate(c, S_RESTART); retry_connection(c); return; } if (!c->cache && get_cache_entry(c->url, &c->cache)) { mem_free(head); setcstate(c, S_OUT_OF_MEM); abort_connection(c); return; } e = c->cache; e->http_code = h; if (e->head) mem_free(e->head); e->head = head; if ((d = parse_http_header(head, "Expires", NULL))) { time_t t = parse_http_date(d); if (t && e->expire_time != 1) e->expire_time = t; mem_free(d); } if ((d = parse_http_header(head, "Pragma", NULL))) { if (!casecmp(d, "no-cache", 8)) e->expire_time = 1; mem_free(d); } if ((d = parse_http_header(head, "Cache-Control", NULL))) { char *f = d; while (1) { while (*f && (*f == ' ' || *f == ',')) f++; if (!*f) break; if (!casecmp(f, "no-cache", 8) || !casecmp(f, "must-revalidate", 15)) { e->expire_time = 1; } if (!casecmp(f, "max-age=", 8)) { if (e->expire_time != 1) e->expire_time = time(NULL) + atoi(f + 8); } while (*f && *f != ',') f++; } mem_free(d); } #ifdef HAVE_SSL if (c->ssl) { int l = 0; if (e->ssl_info) mem_free(e->ssl_info); e->ssl_info = init_str(); add_num_to_str(&e->ssl_info, &l, SSL_get_cipher_bits(c->ssl, NULL)); add_to_str(&e->ssl_info, &l, "-bit "); add_to_str(&e->ssl_info, &l, SSL_get_cipher_version(c->ssl)); add_to_str(&e->ssl_info, &l, " "); add_to_str(&e->ssl_info, &l, (unsigned char *)SSL_get_cipher_name(c->ssl)); } #endif if (e->redirect) mem_free(e->redirect), e->redirect = NULL; if (h == 301 || h == 302 || h == 303 || h == 307) { if ((h == 302 || h == 307) && !e->expire_time) e->expire_time = 1; if ((d = parse_http_header(e->head, "Location", NULL))) { unsigned char *user, *ins; unsigned char *newuser, *newpassword; if (!parse_url(d, NULL, &user, NULL, NULL, NULL, &ins, NULL, NULL, NULL, NULL, NULL, NULL) && !user && ins && (newuser = get_user_name(host))) { if (*newuser) { int ins_off = ins - d; newpassword = get_pass(host); if (!newpassword) newpassword = stracpy(""); add_to_strn(&newuser, ":"); add_to_strn(&newuser, newpassword); add_to_strn(&newuser, "@"); extend_str(&d, strlen(newuser)); ins = d + ins_off; memmove(ins + strlen(newuser), ins, strlen(ins) + 1); memcpy(ins, newuser, strlen(newuser)); mem_free(newpassword); } mem_free(newuser); } if (e->redirect) mem_free(e->redirect); e->redirect = d; e->redirect_get = h == 303; } } if (!e->expire_time && strchr(c->url, POST_CHAR)) e->expire_time = 1; info->close = 0; info->length = -1; info->version = version; if ((d = parse_http_header(e->head, "Connection", NULL)) || (d = parse_http_header(e->head, "Proxy-Connection", NULL))) { if (!strcasecmp(d, "close")) info->close = 1; mem_free(d); } else if (version < 11) info->close = 1; cf = c->from; c->from = 0; if ((d = parse_http_header(e->head, "Content-Range", NULL))) { if (strlen(d) > 6) { d[5] = 0; if (!(strcasecmp(d, "bytes")) && d[6] >= '0' && d[6] <= '9') { #if defined(HAVE_STRTOLL) long long f = strtoll(d + 6, NULL, 10); #elif defined(HAVE_STRTOQ) longlong f = strtoq(d + 6, NULL, 10); #else long f = strtol(d + 6, NULL, 10); if (f == MAXLONG) f = -1; #endif if (f >= 0 && (off_t)f >= 0 && (off_t)f == f) c->from = f; } } mem_free(d); } if (cf && !c->from && !c->unrestartable) c->unrestartable = 1; if (c->from > cf || c->from < 0) { setcstate(c, S_HTTP_ERROR); abort_connection(c); return; } if ((d = parse_http_header(e->head, "Content-Length", NULL))) { unsigned char *ep; #if defined(HAVE_STRTOLL) long long l = strtoll(d, (char **)(void *)&ep, 10); #elif defined(HAVE_STRTOQ) longlong l = strtoq(d, (char **)(void *)&ep, 10); #else long l = strtol(d, (char **)(void *)&ep, 10); if (l == MAXLONG) l = -1; #endif if (!*ep && l >= 0 && (off_t)l >= 0 && (off_t)l == l) { if (!info->close || version >= 11) info->length = l; if (c->from + l >= 0) c->est_length = c->from + l; } mem_free(d); } if ((d = parse_http_header(e->head, "Accept-Ranges", NULL))) { if (!strcasecmp(d, "none") && !c->unrestartable) c->unrestartable = 1; mem_free(d); } else { if (!c->unrestartable && !c->from) c->unrestartable = 1; } if (info->bl_flags & BL_NO_RANGE && !c->unrestartable) c->unrestartable = 1; if ((d = parse_http_header(e->head, "Transfer-Encoding", NULL))) { if (!strcasecmp(d, "chunked")) { info->length = -2; info->chunk_remaining = -1; } mem_free(d); } if (!info->close && info->length == -1) info->close = 1; if ((d = parse_http_header(e->head, "Last-Modified", NULL))) { if (e->last_modified && strcasecmp(e->last_modified, d)) { delete_entry_content(e); if (c->from) { c->from = 0; mem_free(d); setcstate(c, S_MODIFIED); retry_connection(c); return; } } if (!e->last_modified) e->last_modified = d; else mem_free(d); } if (!e->last_modified && (d = parse_http_header(e->head, "Date", NULL))) e->last_modified = d; if (info->length == -1 || (version < 11 && info->close)) rb->close = 1; read_http_data(c, rb); }
const char *h2o_socket_get_ssl_cipher(h2o_socket_t *sock) { return sock->ssl != NULL ? SSL_get_cipher_name(sock->ssl->ssl) : NULL; }
const char * eventer_ssl_get_current_cipher(eventer_ssl_ctx_t *ctx) { return SSL_get_cipher_name(ctx->ssl); }
void wr_connect(char *host, int port, char *login, char *password) { SHA_CTX c; static unsigned char hex[] = "0123456789abcdef"; unsigned char sha[SHA_DIGEST_LENGTH]; struct hostent *hp; int i, on = 1; /* disconnect active socket */ if(wr_socket >= 0) wr_close(); /* reset current working directory */ strlcpy(wr_files_cwd, "/", sizeof(wr_files_cwd)); /* copy values */ wr_port = port; if(port != 2000) snprintf(wr_host, sizeof(wr_host), "%s:%d", host, port); else strlcpy(wr_host, host, sizeof(wr_host)); strlcpy(wr_login, login, sizeof(wr_login)); strlcpy(wr_password, password, sizeof(wr_password)); /* log */ wr_printf_prefix("Connecting to %s...\n", wr_host); /* create new socket */ wr_socket = socket(AF_INET, SOCK_STREAM, 0); if(wr_socket < 0) { wr_printf_prefix("Could not create a socket: %s\n", strerror(errno)); wr_close(); return; } /* set socket options */ if(setsockopt(wr_socket, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0) { wr_printf_prefix("Could not set socket options: %s\n", strerror(errno)); wr_close(); return; } /* init address */ memset(&wr_addr, 0, sizeof(wr_addr)); wr_addr.sin_family = AF_INET; wr_addr.sin_port = htons(port); if(!inet_aton(host, &wr_addr.sin_addr)) { hp = gethostbyname(host); if(!hp) { wr_printf_prefix("Could not resolve hostname %s: %s\n", host, hstrerror(h_errno)); wr_close(); return; } memcpy(&wr_addr.sin_addr, hp->h_addr, sizeof(wr_addr.sin_addr)); } /* connect TCP socket */ if(connect(wr_socket, (struct sockaddr *) &wr_addr, sizeof(wr_addr)) < 0) { wr_printf_prefix("Could not connect to %s: %s\n", host, strerror(errno)); wr_close(); return; } /* create SSL context */ wr_ssl_ctx = SSL_CTX_new(TLSv1_client_method()); if(!wr_ssl_ctx) { wr_printf_prefix("Could not create SSL context: %s\n", ERR_reason_error_string(ERR_get_error())); wr_close(); return; } if(SSL_CTX_set_cipher_list(wr_ssl_ctx, "ALL") != 1) { wr_printf_prefix("Could not set SSL cipher list: %s\n", ERR_reason_error_string(ERR_get_error())); wr_close(); return; } /* create SSL socket */ wr_ssl = SSL_new(wr_ssl_ctx); if(!wr_ssl) { wr_printf_prefix("Could not create SSL socket: %s\n", ERR_reason_error_string(ERR_get_error())); wr_close(); return; } if(SSL_set_fd(wr_ssl, wr_socket) != 1) { wr_printf_prefix("Could not set SSL file descriptor: %s\n", ERR_reason_error_string(ERR_get_error())); wr_close(); return; } if(SSL_connect(wr_ssl) != 1) { wr_printf_prefix("Could not connect to %s via SSL: %s\n", host, ERR_reason_error_string(ERR_get_error())); wr_close(); return; } /* log */ wr_printf_prefix("Connected using %s/%s/%u bits, logging in...\n", SSL_get_cipher_version(wr_ssl), SSL_get_cipher_name(wr_ssl), SSL_get_cipher_bits(wr_ssl, NULL)); /* send initial login */ wr_send_command("HELLO%s", WR_MESSAGE_SEPARATOR); /* hash the password */ memset(wr_password_sha, 0, sizeof(wr_password_sha)); if(strlen(wr_password) > 0) { SHA1_Init(&c); SHA1_Update(&c, (unsigned char *) wr_password, strlen(wr_password)); SHA1_Final(sha, &c); /* map into hexademical characters */ for(i = 0; i < SHA_DIGEST_LENGTH; i++) { wr_password_sha[i+i] = hex[sha[i] >> 4]; wr_password_sha[i+i+1] = hex[sha[i] & 0x0F]; } wr_password_sha[i+i] = '\0'; }
static int ssl_do(struct st_VioSSLFd *ptr, Vio *vio, long timeout, int (*connect_accept_func)(SSL*), unsigned long *errptr) { int r; SSL *ssl; my_bool unused; my_bool was_blocking; DBUG_ENTER("ssl_do"); DBUG_PRINT("enter", ("ptr: 0x%lx, sd: %d ctx: 0x%lx", (long) ptr, vio->sd, (long) ptr->ssl_context)); /* Set socket to blocking if not already set */ vio_blocking(vio, 1, &was_blocking); if (!(ssl= SSL_new(ptr->ssl_context))) { DBUG_PRINT("error", ("SSL_new failure")); *errptr= ERR_get_error(); vio_blocking(vio, was_blocking, &unused); DBUG_RETURN(1); } DBUG_PRINT("info", ("ssl: 0x%lx timeout: %ld", (long) ssl, timeout)); SSL_clear(ssl); SSL_SESSION_set_timeout(SSL_get_session(ssl), timeout); SSL_set_fd(ssl, vio->sd); #if !defined(HAVE_YASSL) && defined(SSL_OP_NO_COMPRESSION) SSL_set_options(ssl, SSL_OP_NO_COMPRESSION); #endif if ((r= connect_accept_func(ssl)) < 1) { DBUG_PRINT("error", ("SSL_connect/accept failure")); *errptr= SSL_get_error(ssl, r); SSL_free(ssl); vio_blocking(vio, was_blocking, &unused); DBUG_RETURN(1); } /* Connection succeeded. Install new function handlers, change type, set sd to the fd used when connecting and set pointer to the SSL structure */ vio_reset(vio, VIO_TYPE_SSL, SSL_get_fd(ssl), 0, 0); vio->ssl_arg= (void*)ssl; #ifndef DBUG_OFF { /* Print some info about the peer */ X509 *cert; char buf[512]; DBUG_PRINT("info",("SSL connection succeeded")); DBUG_PRINT("info",("Using cipher: '%s'" , SSL_get_cipher_name(ssl))); if ((cert= SSL_get_peer_certificate (ssl))) { DBUG_PRINT("info",("Peer certificate:")); X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); DBUG_PRINT("info",("\t subject: '%s'", buf)); X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf)); DBUG_PRINT("info",("\t issuer: '%s'", buf)); X509_free(cert); } else DBUG_PRINT("info",("Peer does not have certificate.")); if (SSL_get_shared_ciphers(ssl, buf, sizeof(buf))) { DBUG_PRINT("info",("shared_ciphers: '%s'", buf)); } else DBUG_PRINT("info",("no shared ciphers!")); } #endif DBUG_RETURN(0); }
/** * @brief Accept a TLS connection and authenticate and identify. * @note Various fields in #conn are set, like username and keyhash. */ int ServerTLSSessionEstablish(ServerConnectionState *conn) { int ret; if (ConnectionInfoConnectionStatus(conn->conn_info) != CF_CONNECTION_ESTABLISHED) { assert(ConnectionInfoSSL(conn->conn_info) == NULL); SSL *ssl = SSL_new(SSLSERVERCONTEXT); if (ssl == NULL) { Log(LOG_LEVEL_ERR, "SSL_new: %s", TLSErrorString(ERR_get_error())); return -1; } ConnectionInfoSetSSL(conn->conn_info, ssl); /* Pass conn_info inside the ssl struct for TLSVerifyCallback(). */ SSL_set_ex_data(ssl, CONNECTIONINFO_SSL_IDX, conn->conn_info); /* Now we are letting OpenSSL take over the open socket. */ SSL_set_fd(ssl, ConnectionInfoSocket(conn->conn_info)); ret = SSL_accept(ssl); if (ret <= 0) { TLSLogError(ssl, LOG_LEVEL_ERR, "Failed to accept TLS connection", ret); return -1; } Log(LOG_LEVEL_VERBOSE, "TLS cipher negotiated: %s, %s", SSL_get_cipher_name(ssl), SSL_get_cipher_version(ssl)); Log(LOG_LEVEL_VERBOSE, "TLS session established, checking trust..."); /* Send/Receive "CFE_v%d" version string, agree on version, receive identity (username) of peer. */ char username[sizeof(conn->username)] = ""; bool b = ServerIdentificationDialog(conn->conn_info, username, sizeof(username)); if (b != true) { return -1; } /* We *now* (maybe a bit late) verify the key that the client sent us in * the TLS handshake, since we need the username to do so. TODO in the * future store keys irrelevant of username, so that we can match them * before IDENTIFY. */ ret = TLSVerifyPeer(conn->conn_info, conn->ipaddr, username); if (ret == -1) /* error */ { return -1; } if (ret == 1) /* trusted key */ { Log(LOG_LEVEL_VERBOSE, "%s: Client is TRUSTED, public key MATCHES stored one.", KeyPrintableHash(ConnectionInfoKey(conn->conn_info))); } if (ret == 0) /* untrusted key */ { if ((SV.trustkeylist != NULL) && (IsMatchItemIn(SV.trustkeylist, conn->ipaddr))) { Log(LOG_LEVEL_VERBOSE, "Peer was found in \"trustkeysfrom\" list"); Log(LOG_LEVEL_NOTICE, "Trusting new key: %s", KeyPrintableHash(ConnectionInfoKey(conn->conn_info))); SavePublicKey(username, KeyPrintableHash(conn->conn_info->remote_key), KeyRSA(ConnectionInfoKey(conn->conn_info))); } else { Log(LOG_LEVEL_NOTICE, "TRUST FAILED, peer presented an untrusted key, dropping connection!"); Log(LOG_LEVEL_VERBOSE, "Add peer to \"trustkeysfrom\" if you really want to start trusting this new key."); return -1; } } /* All checks succeeded, set conn->uid (conn->sid for Windows) * according to the received USERNAME identity. */ SetConnIdentity(conn, username); /* No CAUTH, SAUTH in non-classic protocol. */ conn->user_data_set = 1; conn->rsa_auth = 1; LastSaw1(conn->ipaddr, KeyPrintableHash(ConnectionInfoKey(conn->conn_info)), LAST_SEEN_ROLE_ACCEPT); ServerSendWelcome(conn); } return 1; }
/****************************************************************************** ****************************************************************************** ** Higher Level SSL_CTX Wrappers ** ****************************************************************************** ******************************************************************************/ static void log_callback(const SSL *ssl, int where, int ret) { const char *retstr = ""; int should_log = 0; lcbio_SOCKET *sock = SSL_get_app_data(ssl); /* Ignore low-level SSL stuff */ if (where & SSL_CB_ALERT) { should_log = 1; } if (where == SSL_CB_HANDSHAKE_START || where == SSL_CB_HANDSHAKE_DONE) { should_log = 1; } if ((where & SSL_CB_EXIT) && ret == 0) { should_log = 1; } if (!should_log) { return; } retstr = SSL_alert_type_string(ret); lcb_log(LOGARGS(ssl, LCB_LOG_TRACE), "sock=%p: ST(0x%x). %s. R(0x%x)%s", (void*)sock, where, SSL_state_string_long(ssl), ret, retstr); if (where == SSL_CB_HANDSHAKE_DONE) { lcb_log(LOGARGS(ssl, LCB_LOG_DEBUG), "sock=%p. Using SSL version %s. Cipher=%s", (void*)sock, SSL_get_version(ssl), SSL_get_cipher_name(ssl)); } }