ret_t cherokee_cryptor_libssl_find_vserver (SSL *ssl, cherokee_server_t *srv, cherokee_buffer_t *servername, cherokee_connection_t *conn) { ret_t ret; cherokee_virtual_server_t *vsrv = NULL; SSL_CTX *ctx; /* Try to match the connection to a server */ ret = cherokee_server_get_vserver(srv, servername, conn, &vsrv); if ((ret != ret_ok) || (vsrv == NULL)) { LOG_ERROR (CHEROKEE_ERROR_SSL_SRV_MATCH, servername->buf); return ret_error; } TRACE (ENTRIES, "Setting new TLS context. Virtual host='%s'\n", vsrv->name.buf); /* Check whether the Virtual Server supports TLS */ if ((vsrv->cryptor == NULL) || (CRYPTOR_VSRV_SSL(vsrv->cryptor)->context == NULL)) { TRACE (ENTRIES, "Virtual server '%s' does not support SSL\n", servername->buf); return ret_error; } /* Set the new SSL context */ ctx = SSL_set_SSL_CTX (ssl, CRYPTOR_VSRV_SSL(vsrv->cryptor)->context); if (ctx != CRYPTOR_VSRV_SSL(vsrv->cryptor)->context) { LOG_ERROR (CHEROKEE_ERROR_SSL_CHANGE_CTX, servername->buf); } /* SSL_set_SSL_CTX() only change certificates. We need to * changes more options by hand. */ SSL_set_options(ssl, SSL_CTX_get_options(ssl->ctx)); if ((SSL_get_verify_mode(ssl) == SSL_VERIFY_NONE) || (SSL_num_renegotiations(ssl) == 0)) { SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ssl->ctx), SSL_CTX_get_verify_callback(ssl->ctx)); } return ret_ok; }
/* Server certificate name check, logic adapted from libcurl */ static int _SSL_check_server_cert(SSL *ssl, const char *hostname) { X509 *cert; X509_NAME *subject; const GENERAL_NAME *altname; STACK_OF(GENERAL_NAME) *altnames; ASN1_STRING *tmp; int i, n, match = -1; const char *p; if (SSL_get_verify_mode(ssl) == SSL_VERIFY_NONE || (cert = SSL_get_peer_certificate(ssl)) == NULL) { return (1); } /* Check subjectAltName */ if ((altnames = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL)) != NULL) { n = sk_GENERAL_NAME_num(altnames); for (i = 0; i < n && match != 1; i++) { altname = sk_GENERAL_NAME_value(altnames, i); p = (char *)ASN1_STRING_data(altname->d.ia5); if (altname->type == GEN_DNS) { match = (ASN1_STRING_length(altname->d.ia5) == strlen(p) && match_pattern(hostname, p)); } } GENERAL_NAMES_free(altnames); } /* No subjectAltName, try CN */ if (match == -1 && (subject = X509_get_subject_name(cert)) != NULL) { for (i = -1; (n = X509_NAME_get_index_by_NID(subject, NID_commonName, i)) >= 0; ) { i = n; } if (i >= 0) { if ((tmp = X509_NAME_ENTRY_get_data( X509_NAME_get_entry(subject, i))) != NULL && ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) { p = (char *)ASN1_STRING_data(tmp); match = (ASN1_STRING_length(tmp) == strlen(p) && match_pattern(hostname, p)); } } } X509_free(cert); return (match > 0); }
static int ssl_connect(struct vconn *vconn) { struct ssl_vconn *sslv = ssl_vconn_cast(vconn); int retval; switch (sslv->state) { case STATE_TCP_CONNECTING: retval = check_connection_completion(sslv->fd); if (retval) { return retval; } sslv->state = STATE_SSL_CONNECTING; /* Fall through. */ case STATE_SSL_CONNECTING: retval = (sslv->type == CLIENT ? SSL_connect(sslv->ssl) : SSL_accept(sslv->ssl)); if (retval != 1) { int error = SSL_get_error(sslv->ssl, retval); if (retval < 0 && ssl_wants_io(error)) { return EAGAIN; } else { int unused; interpret_ssl_error((sslv->type == CLIENT ? "SSL_connect" : "SSL_accept"), retval, error, &unused); shutdown(sslv->fd, SHUT_RDWR); return EPROTO; } } else if (bootstrap_ca_cert) { return do_ca_cert_bootstrap(vconn); } else if ((SSL_get_verify_mode(sslv->ssl) & (SSL_VERIFY_NONE | SSL_VERIFY_PEER)) != SSL_VERIFY_PEER) { /* Two or more SSL connections completed at the same time while we * were in bootstrap mode. Only one of these can finish the * bootstrap successfully. The other one(s) must be rejected * because they were not verified against the bootstrapped CA * certificate. (Alternatively we could verify them against the CA * certificate, but that's more trouble than it's worth. These * connections will succeed the next time they retry, assuming that * they have a certificate against the correct CA.) */ VLOG_ERR("rejecting SSL connection during bootstrap race window"); return EPROTO; } else { return 0; } } NOT_REACHED(); }
/* Check server certificate verification, after a connection is established. We * check first that a certificate was even offered, then call * SSL_get_verify_result to get the overall status of verification. (Just * calling SSL_get_verify_result is not enough because that function returns * X509_V_OK when 0 certificates are presented.) If the verification mode of the * SSL object is SSL_VERIFY_NONE, or if OpenSSL is disabled, this function * always returns true. */ int nsi_ssl_post_connect_verify(const nsock_iod nsockiod) { struct niod *iod = (struct niod *)nsockiod; assert(iod->ssl != NULL); if (SSL_get_verify_mode(iod->ssl) != SSL_VERIFY_NONE) { X509 *cert; cert = SSL_get_peer_certificate(iod->ssl); if (cert == NULL) /* No certificate presented. */ return 0; X509_free(cert); if (SSL_get_verify_result(iod->ssl) != X509_V_OK) /* Something wrong with verification. */ return 0; } return 1; }
Bool StartSSLClientSession(NETFILE *fp, const char *hostname) { X509 *cert; Bool id_ok = FALSE; if (SSL_connect(fp->net.ssl) <= 0){ SSL_Error(_d("SSL_connect failure:\n %s\n"), GetSSLErrorString()); return FALSE; } if ((cert = SSL_get_peer_certificate(fp->net.ssl)) != NULL){ fp->peer_cert = cert; id_ok = CheckHostnameInCertificate(cert, hostname); if (id_ok != TRUE){ SSL_Error(_d("The hostname does not match %s.\n"), hostname); if (SSL_get_verify_mode(fp->net.ssl) & SSL_VERIFY_PEER){ return FALSE; } } } return TRUE; }
static int ssl_connect(struct stream *stream) { struct ssl_stream *sslv = ssl_stream_cast(stream); int retval; switch (sslv->state) { case STATE_TCP_CONNECTING: retval = check_connection_completion(sslv->fd); if (retval) { return retval; } sslv->state = STATE_SSL_CONNECTING; setsockopt_tcp_nodelay(sslv->fd); /* 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 negotiation 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) { int error = SSL_get_error(sslv->ssl, retval); if (retval < 0 && ssl_wants_io(error)) { return EAGAIN; } else { int unused; 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) { return do_ca_cert_bootstrap(stream); } else if (verify_peer_cert && ((SSL_get_verify_mode(sslv->ssl) & (SSL_VERIFY_NONE | SSL_VERIFY_PEER)) != SSL_VERIFY_PEER)) { /* Two or more SSL connections completed at the same time while we * were in bootstrap mode. Only one of these can finish the * bootstrap successfully. The other one(s) must be rejected * because they were not verified against the bootstrapped CA * certificate. (Alternatively we could verify them against the CA * certificate, but that's more trouble than it's worth. These * connections will succeed the next time they retry, assuming that * they have a certificate against the correct CA.) */ VLOG_INFO("rejecting SSL connection during bootstrap race window"); return EPROTO; } else { return 0; } } OVS_NOT_REACHED(); }
static int openssl_ssl_get(lua_State*L) { SSL* s = CHECK_OBJECT(1, SSL, "openssl.ssl"); int i; int top = lua_gettop(L); for (i = 2; i <= top; i++) { const char* what = luaL_checklstring(L, i, NULL); if (strcmp(what, "fd") == 0) { lua_pushinteger(L, SSL_get_fd(s)); } else if (strcmp(what, "rfd") == 0) { lua_pushinteger(L, SSL_get_rfd(s)); } else if (strcmp(what, "wfd") == 0) { lua_pushinteger(L, SSL_get_wfd(s)); } else if (strcmp(what, "client_CA_list") == 0) { STACK_OF(X509_NAME)* sn = SSL_get_client_CA_list(s); PUSH_OBJECT(sn, "openssl.sk_x509_name"); } else if (strcmp(what, "read_ahead") == 0) { lua_pushboolean(L, SSL_get_read_ahead(s)); } else if (strcmp(what, "shared_ciphers") == 0) { char buf[LUAL_BUFFERSIZE] = {0}; lua_pushstring(L, SSL_get_shared_ciphers(s, buf, sizeof(buf))); } else if (strcmp(what, "cipher_list") == 0) { //TODO FIX lua_pushstring(L, SSL_get_cipher_list(s, 0)); } else if (strcmp(what, "verify_mode") == 0) { //FIX lua_pushinteger(L, SSL_get_verify_mode(s)); } else if (strcmp(what, "verify_depth") == 0) { lua_pushinteger(L, SSL_get_verify_depth(s)); } else if (strcmp(what, "state_string") == 0) { lua_pushstring(L, SSL_state_string(s)); } else if (strcmp(what, "state_string_long") == 0) { lua_pushstring(L, SSL_state_string_long(s)); } else if (strcmp(what, "rstate_string") == 0) { lua_pushstring(L, SSL_rstate_string(s)); } else if (strcmp(what, "rstate_string_long") == 0) { lua_pushstring(L, SSL_rstate_string_long(s)); } else if (strcmp(what, "version") == 0) { lua_pushstring(L, SSL_get_version(s)); } else if (strcmp(what, "iversion") == 0) { lua_pushinteger(L, SSL_version(s)); } else if (strcmp(what, "default_timeout") == 0) { lua_pushinteger(L, SSL_get_default_timeout(s)); } else if (strcmp(what, "certificate") == 0) { X509* cert = SSL_get_certificate(s); PUSH_OBJECT(cert, "openssl.x509"); } else if (strcmp(what, "verify_result") == 0) { long l = SSL_get_verify_result(s); lua_pushinteger(L, l); } else if (strcmp(what, "version") == 0) { lua_pushstring(L, SSL_get_version(s)); } else if (strcmp(what, "state") == 0) { lua_pushinteger(L, SSL_state(s)); } else if (strcmp(what, "hostname") == 0) { lua_pushstring(L, SSL_get_servername(s, TLSEXT_NAMETYPE_host_name)); } else luaL_argerror(L, i, "can't understant"); } return top - 1; }
int SSLConnection::getVerifyMode() const { return SSL_get_verify_mode(m_ssl); }