int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx) { /* See if any certificates are missing private keys */ size_t i; CERT *c = NULL; if (cctx->ctx) c = cctx->ctx->cert; else if (cctx->ssl) c = cctx->ssl->cert; if (c && cctx->flags & SSL_CONF_FLAG_REQUIRE_PRIVATE) { for (i = 0; i < SSL_PKEY_NUM; i++) { const char *p = cctx->cert_filename[i]; /* * If missing private key try to load one from certificate file */ if (p && !c->pkeys[i].privatekey) { if (!cmd_PrivateKey(cctx, p)) return 0; } } } if (cctx->canames) { if (cctx->ssl) SSL_set_client_CA_list(cctx->ssl, cctx->canames); else if (cctx->ctx) SSL_CTX_set_client_CA_list(cctx->ctx, cctx->canames); else sk_X509_NAME_pop_free(cctx->canames, X509_NAME_free); cctx->canames = NULL; } return 1; }
void SecuredServerSession::verifyPeer(const std::string &caFile) { if (!caFile.empty()) { auto certs = SSL_load_client_CA_file(caFile.c_str()); if (!certs) throw std::runtime_error(ERR_error_string(ERR_get_error(), nullptr)); SSL_set_client_CA_list(m_SSL, certs); } SSL_set_verify(m_SSL, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_CLIENT_ONCE, &verify_callback); SSL_set_verify_depth(m_SSL, 10); m_renegotiate = true; }
static int network_ssl_servername_callback(SSL *ssl, int *al, server *srv) { const char *servername; connection *con = (connection *) SSL_get_app_data(ssl); UNUSED(al); buffer_copy_string(con->uri.scheme, "https"); if (NULL == (servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) { #if 0 /* this "error" just means the client didn't support it */ log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", "failed to get TLS server name"); #endif return SSL_TLSEXT_ERR_NOACK; } buffer_copy_string(con->tlsext_server_name, servername); buffer_to_lower(con->tlsext_server_name); /* Sometimes this is still set, confusing COMP_HTTP_HOST */ buffer_reset(con->uri.authority); config_cond_cache_reset(srv, con); config_setup_connection(srv, con); con->conditional_is_valid[COMP_SERVER_SOCKET] = 1; con->conditional_is_valid[COMP_HTTP_SCHEME] = 1; con->conditional_is_valid[COMP_HTTP_HOST] = 1; config_patch_connection(srv, con); if (NULL == con->conf.ssl_pemfile_x509 || NULL == con->conf.ssl_pemfile_pkey) { /* x509/pkey available <=> pemfile was set <=> pemfile got patched: so this should never happen, unless you nest $SERVER["socket"] */ log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", "no certificate/private key for TLS server name", con->tlsext_server_name); return SSL_TLSEXT_ERR_ALERT_FATAL; } /* first set certificate! setting private key checks whether certificate matches it */ if (!SSL_use_certificate(ssl, con->conf.ssl_pemfile_x509)) { log_error_write(srv, __FILE__, __LINE__, "ssb:s", "SSL:", "failed to set certificate for TLS server name", con->tlsext_server_name, ERR_error_string(ERR_get_error(), NULL)); return SSL_TLSEXT_ERR_ALERT_FATAL; } if (!SSL_use_PrivateKey(ssl, con->conf.ssl_pemfile_pkey)) { log_error_write(srv, __FILE__, __LINE__, "ssb:s", "SSL:", "failed to set private key for TLS server name", con->tlsext_server_name, ERR_error_string(ERR_get_error(), NULL)); return SSL_TLSEXT_ERR_ALERT_FATAL; } if (con->conf.ssl_verifyclient) { if (NULL == con->conf.ssl_ca_file_cert_names) { log_error_write(srv, __FILE__, __LINE__, "ssb:s", "SSL:", "can't verify client without ssl.ca-file for TLS server name", con->tlsext_server_name, ERR_error_string(ERR_get_error(), NULL)); return SSL_TLSEXT_ERR_ALERT_FATAL; } SSL_set_client_CA_list(ssl, SSL_dup_CA_list(con->conf.ssl_ca_file_cert_names)); /* forcing verification here is really not that useful - a client could just connect without SNI */ SSL_set_verify( ssl, SSL_VERIFY_PEER | (con->conf.ssl_verifyclient_enforce ? SSL_VERIFY_FAIL_IF_NO_PEER_CERT : 0), NULL ); SSL_set_verify_depth(ssl, con->conf.ssl_verifyclient_depth); } else { SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL); } return SSL_TLSEXT_ERR_OK; }