bool OpenSSLServer::privateInit() { SSL_CTX_set_tmp_rsa_callback( m_ctx, tmp_rsa_callback ); SSL_CTX_set_tmp_dh_callback( m_ctx, tmp_dh_callback ); SSL_CTX_set_options( m_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE ); return true; }
int swSSL_server_set_cipher(SSL_CTX* ssl_context, swSSL_config *cfg) { #ifndef TLS1_2_VERSION return SW_OK; #endif SSL_CTX_set_read_ahead(ssl_context, 1); if (strlen(cfg->ciphers) > 0) { if (SSL_CTX_set_cipher_list(ssl_context, cfg->ciphers) == 0) { swWarn("SSL_CTX_set_cipher_list(\"%s\") failed", cfg->ciphers); return SW_ERR; } if (cfg->prefer_server_ciphers) { SSL_CTX_set_options(ssl_context, SSL_OP_CIPHER_SERVER_PREFERENCE); } } #ifndef LIBRESSL_VERSION_NUMBER SSL_CTX_set_tmp_rsa_callback(ssl_context, swSSL_rsa512_key_callback); #endif if (strlen(cfg->ecdh_curve) > 0) { swSSL_set_dhparam(ssl_context); swSSL_set_ecdh_curve(ssl_context); } return SW_OK; }
bool OpenSSLServer::privateInit() { SSL_CTX_set_tmp_rsa_callback( m_ctx, tmp_rsa_callback ); SSL_CTX_set_tmp_dh_callback( m_ctx, tmp_dh_callback ); SSL_CTX_set_tmp_ecdh( m_ctx, EC_KEY_new_by_curve_name( NID_sect163r2 ) ); SSL_CTX_set_options( m_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE ); return true; }
void TLSContext::LoadCertificate() { if (!certificate.empty()) { if (SSL_CTX_use_certificate_chain_file(context, certificate.c_str()) != 1 || SSL_CTX_use_PrivateKey_file( context, certificate.c_str(), SSL_FILETYPE_PEM) != 1 || SSL_CTX_check_private_key(context) != 1) throw TLSProtocolError(); } SSL_CTX_set_tmp_rsa_callback(context, TempRSACallback); }
static void ssl_init_ctx_callbacks(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp, modssl_ctx_t *mctx) { SSL_CTX *ctx = mctx->ssl_ctx; SSL_CTX_set_tmp_rsa_callback(ctx, ssl_callback_TmpRSA); SSL_CTX_set_tmp_dh_callback(ctx, ssl_callback_TmpDH); SSL_CTX_set_info_callback(ctx, ssl_callback_Info); }
void tls_ctx_server_new(struct tls_root_ctx *ctx) { ASSERT(NULL != ctx); ctx->ctx = SSL_CTX_new (TLSv1_server_method ()); if (ctx->ctx == NULL) msg (M_SSLERR, "SSL_CTX_new TLSv1_server_method"); SSL_CTX_set_tmp_rsa_callback (ctx->ctx, tmp_rsa_cb); }
static void ssl_init_ctx_callbacks(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp, modssl_ctx_t *mctx) { SSL_CTX *ctx = mctx->ssl_ctx; SSL_CTX_set_tmp_rsa_callback(ctx, ssl_callback_TmpRSA); SSL_CTX_set_tmp_dh_callback(ctx, ssl_callback_TmpDH); if (s->loglevel >= APLOG_DEBUG) { /* this callback only logs if LogLevel >= info */ SSL_CTX_set_info_callback(ctx, ssl_callback_LogTracingState); } }
void tls_ctx_server_new(struct tls_root_ctx *ctx, unsigned int ssl_flags) { const int tls_version_max = (ssl_flags >> SSLF_TLS_VERSION_MAX_SHIFT) & SSLF_TLS_VERSION_MAX_MASK; ASSERT(NULL != ctx); if (tls_version_max == TLS_VER_1_0) ctx->ctx = SSL_CTX_new (TLSv1_server_method ()); else ctx->ctx = SSL_CTX_new (SSLv23_server_method ()); if (ctx->ctx == NULL) msg (M_SSLERR, "SSL_CTX_new SSLv23_server_method"); SSL_CTX_set_tmp_rsa_callback (ctx->ctx, tmp_rsa_cb); }
int swSSL_server_config(SSL_CTX* ssl_context, swSSL_config *cfg) { #ifndef TLS1_2_VERSION return SW_OK; #endif SSL_CTX_set_read_ahead(ssl_context, 1); #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation SSL_CTX_set_alpn_select_cb(ssl_context, swSSL_alpn_advertised, cfg); #endif #ifdef TLSEXT_TYPE_next_proto_neg SSL_CTX_set_next_protos_advertised_cb(ssl_context, swSSL_npn_advertised, cfg); #endif if (SSL_CTX_set_cipher_list(ssl_context, cfg->ciphers) == 0) { swWarn("SSL_CTX_set_cipher_list(\"%s\") failed", SW_SSL_CIPHER_LIST); return SW_ERR; } if (cfg->prefer_server_ciphers) { SSL_CTX_set_options(ssl_context, SSL_OP_CIPHER_SERVER_PREFERENCE); } #ifndef LIBRESSL_VERSION_NUMBER SSL_CTX_set_tmp_rsa_callback(ssl_context, swSSL_rsa512_key_callback); #endif swSSL_set_dhparam(ssl_context); swSSL_set_ecdh_curve(ssl_context); if (cfg->http) { SSL_CTX_set_session_id_context(ssl_context, (const unsigned char *) "HTTP", strlen("HTTP")); SSL_CTX_set_session_cache_mode(ssl_context, SSL_SESS_CACHE_SERVER); SSL_CTX_sess_set_cache_size(ssl_context, 1); } return SW_OK; }
static SSL_CTX *initialise_ssl_ctx(int server_mode, const char *engine_id, const char *CAfile, const char *cert, const char *key, const char *dcert, const char *dkey, const char *cipher_list, const char *dh_file, const char *dh_special, int tmp_rsa, int ctx_options, int out_state, int out_verify, int verify_mode, unsigned int verify_depth) { SSL_CTX *ctx = NULL, *ret = NULL; const SSL_METHOD *meth; ENGINE *e = NULL; OpenSSL_add_ssl_algorithms(); SSL_load_error_strings(); meth = (server_mode ? SSLv23_server_method() : SSLv23_client_method()); if (meth == NULL) goto err; if (engine_id) { ENGINE_load_builtin_engines(); if ((e = ENGINE_by_id(engine_id)) == NULL) { fprintf(stderr, "Error obtaining '%s' engine, openssl " "errors follow\n", engine_id); goto err; } if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) { fprintf(stderr, "Error assigning '%s' engine, openssl " "errors follow\n", engine_id); goto err; } ENGINE_free(e); } if ((ctx = SSL_CTX_new(meth)) == NULL) goto err; /* cacert */ if (CAfile) { if (!X509_STORE_load_locations(SSL_CTX_get_cert_store(ctx), CAfile, NULL)) { fprintf(stderr, "Error loading CA cert(s) in '%s'\n", CAfile); goto err; } fprintf(stderr, "Info, operating with CA cert(s) in '%s'\n", CAfile); } else fprintf(stderr, "Info, operating without a CA cert(-list)\n"); if (!SSL_CTX_set_default_verify_paths(ctx)) { fprintf(stderr, "Error setting default verify paths\n"); goto err; } /* cert and key */ if ((cert || key) && !ctx_set_cert(ctx, cert, key)) goto err; /* dcert and dkey */ if ((dcert || dkey) && !ctx_set_cert(ctx, dcert, dkey)) goto err; /* temporary RSA key generation */ if (tmp_rsa) SSL_CTX_set_tmp_rsa_callback(ctx, cb_generate_tmp_rsa); /* cipher_list */ if (cipher_list) { if (!SSL_CTX_set_cipher_list(ctx, cipher_list)) { fprintf(stderr, "Error setting cipher list '%s'\n", cipher_list); goto err; } fprintf(stderr, "Info, set cipher list '%s'\n", cipher_list); } else fprintf(stderr, "Info, operating with default cipher list\n"); /* dh_file & dh_special */ if ((dh_file || dh_special) && !ctx_set_dh(ctx, dh_file, dh_special)) goto err; /* ctx_options */ SSL_CTX_set_options(ctx, ctx_options); /* out_state (output of SSL handshake states to screen). */ if (out_state) cb_ssl_info_set_output(stderr); /* out_verify */ if (out_verify > 0) { cb_ssl_verify_set_output(stderr); cb_ssl_verify_set_level(out_verify); } /* verify_depth */ cb_ssl_verify_set_depth(verify_depth); /* Success! (includes setting verify_mode) */ SSL_CTX_set_info_callback(ctx, cb_ssl_info); SSL_CTX_set_verify(ctx, verify_mode, cb_ssl_verify); ret = ctx; err: if (!ret) { ERR_print_errors_fp(stderr); if (ctx) SSL_CTX_free(ctx); } return ret; }
/* * initialize a new TLS context */ static int tlso_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server ) { tlso_ctx *ctx = (tlso_ctx *)lo->ldo_tls_ctx; int i; if ( is_server ) { SSL_CTX_set_session_id_context( ctx, (const unsigned char *) "OpenLDAP", sizeof("OpenLDAP")-1 ); } #ifdef SSL_OP_NO_TLSv1 #ifdef SSL_OP_NO_TLSv1_1 #ifdef SSL_OP_NO_TLSv1_2 if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_TLS1_2) SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2 ); else #endif if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_TLS1_1) SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 ); else #endif if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_TLS1_0) SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1); else #endif if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_SSL3 ) SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 ); else if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_SSL2 ) SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 ); if ( lo->ldo_tls_ciphersuite && !SSL_CTX_set_cipher_list( ctx, lt->lt_ciphersuite ) ) { Debug( LDAP_DEBUG_ANY, "TLS: could not set cipher list %s.\n", lo->ldo_tls_ciphersuite, 0, 0 ); tlso_report_error(); return -1; } if (lo->ldo_tls_cacertfile != NULL || lo->ldo_tls_cacertdir != NULL) { if ( !SSL_CTX_load_verify_locations( ctx, lt->lt_cacertfile, lt->lt_cacertdir ) || !SSL_CTX_set_default_verify_paths( ctx ) ) { Debug( LDAP_DEBUG_ANY, "TLS: " "could not load verify locations (file:`%s',dir:`%s').\n", lo->ldo_tls_cacertfile ? lo->ldo_tls_cacertfile : "", lo->ldo_tls_cacertdir ? lo->ldo_tls_cacertdir : "", 0 ); tlso_report_error(); return -1; } if ( is_server ) { STACK_OF(X509_NAME) *calist; /* List of CA names to send to a client */ calist = tlso_ca_list( lt->lt_cacertfile, lt->lt_cacertdir ); if ( !calist ) { Debug( LDAP_DEBUG_ANY, "TLS: " "could not load client CA list (file:`%s',dir:`%s').\n", lo->ldo_tls_cacertfile ? lo->ldo_tls_cacertfile : "", lo->ldo_tls_cacertdir ? lo->ldo_tls_cacertdir : "", 0 ); tlso_report_error(); return -1; } SSL_CTX_set_client_CA_list( ctx, calist ); } } if ( lo->ldo_tls_certfile && !SSL_CTX_use_certificate_file( ctx, lt->lt_certfile, SSL_FILETYPE_PEM ) ) { Debug( LDAP_DEBUG_ANY, "TLS: could not use certificate `%s'.\n", lo->ldo_tls_certfile,0,0); tlso_report_error(); return -1; } /* Key validity is checked automatically if cert has already been set */ if ( lo->ldo_tls_keyfile && !SSL_CTX_use_PrivateKey_file( ctx, lt->lt_keyfile, SSL_FILETYPE_PEM ) ) { Debug( LDAP_DEBUG_ANY, "TLS: could not use key file `%s'.\n", lo->ldo_tls_keyfile,0,0); tlso_report_error(); return -1; } if ( lo->ldo_tls_dhfile ) { DH *dh = NULL; BIO *bio; dhplist *p; if (( bio=BIO_new_file( lt->lt_dhfile,"r" )) == NULL ) { Debug( LDAP_DEBUG_ANY, "TLS: could not use DH parameters file `%s'.\n", lo->ldo_tls_dhfile,0,0); tlso_report_error(); return -1; } while (( dh=PEM_read_bio_DHparams( bio, NULL, NULL, NULL ))) { p = LDAP_MALLOC( sizeof(dhplist) ); if ( p != NULL ) { p->keylength = DH_size( dh ) * 8; p->param = dh; p->next = tlso_dhparams; tlso_dhparams = p; } } BIO_free( bio ); } if ( tlso_opt_trace ) { SSL_CTX_set_info_callback( ctx, tlso_info_cb ); } i = SSL_VERIFY_NONE; if ( lo->ldo_tls_require_cert ) { i = SSL_VERIFY_PEER; if ( lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_DEMAND || lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_HARD ) { i |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; } } SSL_CTX_set_verify( ctx, i, lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_ALLOW ? tlso_verify_ok : tlso_verify_cb ); SSL_CTX_set_tmp_rsa_callback( ctx, tlso_tmp_rsa_cb ); if ( lo->ldo_tls_dhfile ) { SSL_CTX_set_tmp_dh_callback( ctx, tlso_tmp_dh_cb ); } #ifdef HAVE_OPENSSL_CRL if ( lo->ldo_tls_crlcheck ) { X509_STORE *x509_s = SSL_CTX_get_cert_store( ctx ); if ( lo->ldo_tls_crlcheck == LDAP_OPT_X_TLS_CRL_PEER ) { X509_STORE_set_flags( x509_s, X509_V_FLAG_CRL_CHECK ); } else if ( lo->ldo_tls_crlcheck == LDAP_OPT_X_TLS_CRL_ALL ) { X509_STORE_set_flags( x509_s, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL ); } } #endif return 0; }
/* * initialize a new TLS context */ static int tlso_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server ) { tlso_ctx *ctx = (tlso_ctx *)lo->ldo_tls_ctx; int i; if ( is_server ) { SSL_CTX_set_session_id_context( ctx, (const unsigned char *) "OpenLDAP", sizeof("OpenLDAP")-1 ); } #ifdef SSL_OP_NO_TLSv1 #ifdef SSL_OP_NO_TLSv1_1 #ifdef SSL_OP_NO_TLSv1_2 if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_TLS1_2) SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2 ); else #endif if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_TLS1_1) SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 ); else #endif if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_TLS1_0) SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1); else #endif if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_SSL3 ) SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 ); else if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_SSL2 ) SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 ); if ( lo->ldo_tls_ciphersuite && !SSL_CTX_set_cipher_list( ctx, lt->lt_ciphersuite ) ) { Debug( LDAP_DEBUG_ANY, "TLS: could not set cipher list %s.\n", lo->ldo_tls_ciphersuite, 0, 0 ); tlso_report_error(); return -1; } if (lo->ldo_tls_cacertfile != NULL || lo->ldo_tls_cacertdir != NULL) { if ( !SSL_CTX_load_verify_locations( ctx, lt->lt_cacertfile, lt->lt_cacertdir ) || !SSL_CTX_set_default_verify_paths( ctx ) ) { Debug( LDAP_DEBUG_ANY, "TLS: " "could not load verify locations (file:`%s',dir:`%s').\n", lo->ldo_tls_cacertfile ? lo->ldo_tls_cacertfile : "", lo->ldo_tls_cacertdir ? lo->ldo_tls_cacertdir : "", 0 ); tlso_report_error(); return -1; } if ( is_server ) { STACK_OF(X509_NAME) *calist; /* List of CA names to send to a client */ calist = tlso_ca_list( lt->lt_cacertfile, lt->lt_cacertdir ); if ( !calist ) { Debug( LDAP_DEBUG_ANY, "TLS: " "could not load client CA list (file:`%s',dir:`%s').\n", lo->ldo_tls_cacertfile ? lo->ldo_tls_cacertfile : "", lo->ldo_tls_cacertdir ? lo->ldo_tls_cacertdir : "", 0 ); tlso_report_error(); return -1; } SSL_CTX_set_client_CA_list( ctx, calist ); } } if ( lo->ldo_tls_certfile && !SSL_CTX_use_certificate_file( ctx, lt->lt_certfile, SSL_FILETYPE_PEM ) ) { Debug( LDAP_DEBUG_ANY, "TLS: could not use certificate `%s'.\n", lo->ldo_tls_certfile,0,0); tlso_report_error(); return -1; } /* Key validity is checked automatically if cert has already been set */ if ( lo->ldo_tls_keyfile && !SSL_CTX_use_PrivateKey_file( ctx, lt->lt_keyfile, SSL_FILETYPE_PEM ) ) { Debug( LDAP_DEBUG_ANY, "TLS: could not use key file `%s'.\n", lo->ldo_tls_keyfile,0,0); tlso_report_error(); return -1; } if ( is_server && lo->ldo_tls_dhfile ) { DH *dh; BIO *bio; if (( bio=BIO_new_file( lt->lt_dhfile,"r" )) == NULL ) { Debug( LDAP_DEBUG_ANY, "TLS: could not use DH parameters file `%s'.\n", lo->ldo_tls_dhfile,0,0); tlso_report_error(); return -1; } if (!( dh=PEM_read_bio_DHparams( bio, NULL, NULL, NULL ))) { Debug( LDAP_DEBUG_ANY, "TLS: could not read DH parameters file `%s'.\n", lo->ldo_tls_dhfile,0,0); tlso_report_error(); BIO_free( bio ); return -1; } BIO_free( bio ); SSL_CTX_set_tmp_dh( ctx, dh ); SSL_CTX_set_options( ctx, SSL_OP_SINGLE_DH_USE ); DH_free( dh ); } if ( is_server && lo->ldo_tls_ecname ) { #ifdef OPENSSL_NO_EC Debug( LDAP_DEBUG_ANY, "TLS: Elliptic Curves not supported.\n", 0,0,0 ); return -1; #else EC_KEY *ecdh; int nid = OBJ_sn2nid( lt->lt_ecname ); if ( nid == NID_undef ) { Debug( LDAP_DEBUG_ANY, "TLS: could not use EC name `%s'.\n", lo->ldo_tls_ecname,0,0); tlso_report_error(); return -1; } ecdh = EC_KEY_new_by_curve_name( nid ); if ( ecdh == NULL ) { Debug( LDAP_DEBUG_ANY, "TLS: could not generate key for EC name `%s'.\n", lo->ldo_tls_ecname,0,0); tlso_report_error(); return -1; } SSL_CTX_set_tmp_ecdh( ctx, ecdh ); SSL_CTX_set_options( ctx, SSL_OP_SINGLE_ECDH_USE ); EC_KEY_free( ecdh ); #endif } if ( tlso_opt_trace ) { SSL_CTX_set_info_callback( ctx, tlso_info_cb ); } i = SSL_VERIFY_NONE; if ( lo->ldo_tls_require_cert ) { i = SSL_VERIFY_PEER; if ( lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_DEMAND || lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_HARD ) { i |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; } } SSL_CTX_set_verify( ctx, i, lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_ALLOW ? tlso_verify_ok : tlso_verify_cb ); #if OPENSSL_VERSION_NUMBER < 0x10100000 SSL_CTX_set_tmp_rsa_callback( ctx, tlso_tmp_rsa_cb ); #endif #ifdef HAVE_OPENSSL_CRL if ( lo->ldo_tls_crlcheck ) { X509_STORE *x509_s = SSL_CTX_get_cert_store( ctx ); if ( lo->ldo_tls_crlcheck == LDAP_OPT_X_TLS_CRL_PEER ) { X509_STORE_set_flags( x509_s, X509_V_FLAG_CRL_CHECK ); } else if ( lo->ldo_tls_crlcheck == LDAP_OPT_X_TLS_CRL_ALL ) { X509_STORE_set_flags( x509_s, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL ); } } #endif return 0; }
static int openssl_ssl_ctx_set_tmp(lua_State *L) { SSL_CTX* ctx = CHECK_OBJECT(1, SSL_CTX, "openssl.ssl_ctx"); static const char* which[] = { "dh", "rsa", "ecdh", NULL }; int nwhich = luaL_checkoption(L, 2, NULL, which); int ret = 0; if (lua_isfunction(L, 3)) { lua_pushvalue(L, 3); ret = 1; switch (nwhich) { case 0: openssl_setvalue(L, ctx, "tmp_dh_callback"); SSL_CTX_set_tmp_dh_callback(ctx, tmp_dh_callback); break; case 1: openssl_setvalue(L, ctx, "tmp_rsa_callback"); SSL_CTX_set_tmp_rsa_callback(ctx, tmp_rsa_callback); break; case 2: { luaL_argcheck(L, lua_isstring(L, 4), 4, "must supply curve name"); openssl_setvalue(L, ctx, "tmp_ecdh_callback"); SSL_CTX_set_tmp_ecdh_callback(ctx, tmp_ecdh_callback); lua_pushvalue(L, 4); openssl_setvalue(L, ctx, "curve"); } break; } } else if (lua_isstring(L, 3)) { BIO* bio = load_bio_object(L, 3); switch (nwhich) { case 0: { DH* dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); if (dh) ret = SSL_CTX_set_tmp_dh(ctx, dh); else luaL_error(L, "generate new tmp dh fail"); } break; case 1: { RSA* rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL); if (rsa) ret = SSL_CTX_set_tmp_rsa(ctx, rsa); else luaL_error(L, "generate new tmp rsa fail"); } break; case 2: { int nid = NID_undef; EC_KEY* ec = PEM_read_bio_ECPrivateKey(bio, NULL, NULL, NULL); if (ec == NULL) { nid = OBJ_txt2nid(lua_tostring(L, 3)); if (nid != NID_undef) ec = EC_KEY_new_by_curve_name(nid); } if (ec) ret = SSL_CTX_set_tmp_ecdh(ctx, ec); else luaL_error(L, "generate new tmp ec_key fail"); } break; } BIO_free(bio); } else if (lua_isuserdata(L, 3)) { luaL_argerror(L, 3, "userdata arg NYI"); } else luaL_argerror(L, 3, "should be tmp key callback function or pem string or key object"); return openssl_pushresult(L, ret); }
void context_init(void) { /* init SSL */ int i; #if SSLEAY_VERSION_NUMBER >= 0x00907000L /* Load all bundled ENGINEs into memory and make them visible */ ENGINE_load_builtin_engines(); /* Register all of them for every algorithm they collectively implement */ ENGINE_register_all_complete(); #endif if(!init_prng()) log(LOG_INFO, "PRNG seeded successfully"); SSLeay_add_ssl_algorithms(); SSL_load_error_strings(); if(options.option.client) { ctx=SSL_CTX_new(SSLv3_client_method()); } else { /* Server mode */ ctx=SSL_CTX_new(SSLv23_server_method()); #ifndef NO_RSA SSL_CTX_set_tmp_rsa_callback(ctx, tmp_rsa_cb); #endif /* NO_RSA */ if(init_dh()) log(LOG_WARNING, "Diffie-Hellman initialization failed"); } if(options.ssl_options) { log(LOG_DEBUG, "Configuration SSL options: 0x%08lX", options.ssl_options); log(LOG_DEBUG, "SSL options set: 0x%08lX", SSL_CTX_set_options(ctx, options.ssl_options)); } #if SSLEAY_VERSION_NUMBER >= 0x00906000L SSL_CTX_set_mode(ctx, SSL_MODE_ENABLE_PARTIAL_WRITE|SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); #endif /* OpenSSL-0.9.6 */ SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_BOTH); SSL_CTX_set_timeout(ctx, options.session_timeout); if(options.option.cert) { if(!SSL_CTX_use_certificate_chain_file(ctx, options.cert)) { log(LOG_ERR, "Error reading certificate file: %s", options.cert); sslerror("SSL_CTX_use_certificate_chain_file"); exit(1); } log(LOG_DEBUG, "Certificate: %s", options.cert); log(LOG_DEBUG, "Key file: %s", options.key); #ifdef USE_WIN32 SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_cb); #endif for(i=0; i<3; i++) { #ifdef NO_RSA if(SSL_CTX_use_PrivateKey_file(ctx, options.key, SSL_FILETYPE_PEM)) #else /* NO_RSA */ if(SSL_CTX_use_RSAPrivateKey_file(ctx, options.key, SSL_FILETYPE_PEM)) #endif /* NO_RSA */ break; if(i<2 && ERR_GET_REASON(ERR_peek_error())==EVP_R_BAD_DECRYPT) { sslerror_stack(); /* dump the error stack */ log(LOG_ERR, "Wrong pass phrase: retrying"); continue; } #ifdef NO_RSA sslerror("SSL_CTX_use_PrivateKey_file"); #else /* NO_RSA */ sslerror("SSL_CTX_use_RSAPrivateKey_file"); #endif /* NO_RSA */ exit(1); } if(!SSL_CTX_check_private_key(ctx)) { sslerror("Private key does not match the certificate"); exit(1); } } verify_init(); /* Initialize certificate verification */ SSL_CTX_set_info_callback(ctx, info_callback); if(options.cipher_list) { if (!SSL_CTX_set_cipher_list(ctx, options.cipher_list)) { sslerror("SSL_CTX_set_cipher_list"); exit(1); } } }
PUBLIC int sslOpen() { RandBuf randBuf; trace(7, "Initializing SSL"); randBuf.now = time(0); randBuf.pid = getpid(); RAND_seed((void*) &randBuf, sizeof(randBuf)); #if BIT_UNIX_LIKE trace(6, "OpenSsl: Before calling RAND_load_file"); RAND_load_file("/dev/urandom", 256); trace(6, "OpenSsl: After calling RAND_load_file"); #endif CRYPTO_malloc_init(); #if !BIT_WIN_LIKE OpenSSL_add_all_algorithms(); #endif SSL_library_init(); SSL_load_error_strings(); SSLeay_add_ssl_algorithms(); if ((sslctx = SSL_CTX_new(SSLv23_server_method())) == 0) { error("Unable to create SSL context"); return -1; } /* Set the client certificate verification locations */ if (*BIT_GOAHEAD_CA) { if ((!SSL_CTX_load_verify_locations(sslctx, BIT_GOAHEAD_CA, NULL)) || (!SSL_CTX_set_default_verify_paths(sslctx))) { error("Unable to read cert verification locations"); sslClose(); return -1; } } /* Set the server certificate and key files */ if (*BIT_GOAHEAD_KEY && sslSetKeyFile(BIT_GOAHEAD_KEY) < 0) { sslClose(); return -1; } if (*BIT_GOAHEAD_CERTIFICATE && sslSetCertFile(BIT_GOAHEAD_CERTIFICATE) < 0) { sslClose(); return -1; } SSL_CTX_set_tmp_rsa_callback(sslctx, rsaCallback); #if VERIFY_CLIENT if (verifyPeer) { SSL_CTX_set_verify(context, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verifyX509Certificate); #if FUTURE && KEEP SSL_CTX_set_verify_depth(context, VERIFY_DEPTH); #endif } else { SSL_CTX_set_verify(sslctx, SSL_VERIFY_NONE, verifyX509Certificate); } #else SSL_CTX_set_verify(sslctx, SSL_VERIFY_NONE, verifyX509Certificate); #endif /* Set the certificate authority list for the client */ if (BIT_GOAHEAD_CA && *BIT_GOAHEAD_CA) { SSL_CTX_set_client_CA_list(sslctx, SSL_load_client_CA_file(BIT_GOAHEAD_CA)); } SSL_CTX_set_cipher_list(sslctx, BIT_GOAHEAD_CIPHERS); SSL_CTX_set_options(sslctx, SSL_OP_ALL); SSL_CTX_sess_set_cache_size(sslctx, 128); #ifdef SSL_OP_NO_TICKET SSL_CTX_set_options(sslctx, SSL_OP_NO_TICKET); #endif #ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION SSL_CTX_set_options(sslctx, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); #endif SSL_CTX_set_mode(sslctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY); SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv2); /* Ensure we generate a new private key for each connection */ SSL_CTX_set_options(sslctx, SSL_OP_SINGLE_DH_USE); return 0; }
static char * ngx_tcp_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) { ngx_tcp_ssl_srv_conf_t *prev = parent; ngx_tcp_ssl_srv_conf_t *conf = child; ngx_pool_cleanup_t *cln; ngx_conf_merge_value(conf->enable, prev->enable, 0); ngx_conf_merge_value(conf->session_timeout, prev->session_timeout, 300); ngx_conf_merge_value(conf->prefer_server_ciphers, prev->prefer_server_ciphers, 0); ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols, (NGX_CONF_BITMASK_SET|NGX_SSL_SSLv3|NGX_SSL_TLSv1|NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2)); ngx_conf_merge_uint_value(conf->verify, prev->verify, 0); ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1); ngx_conf_merge_str_value(conf->certificate, prev->certificate, ""); ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, ""); //ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL); ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, ""); ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve, NGX_DEFAULT_ECDH_CURVE); ngx_conf_merge_str_value(conf->client_certificate, prev->client_certificate, ""); ngx_conf_merge_str_value(conf->crl, prev->crl, ""); ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS); conf->ssl.log = cf->log; if (conf->enable) { if (conf->certificate.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate\" is defined for " "the \"ssl\" directive in %s:%ui", conf->file, conf->line); return NGX_CONF_ERROR; } if (conf->certificate_key.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined for " "the \"ssl\" directive in %s:%ui", conf->file, conf->line); return NGX_CONF_ERROR; } } else { if (conf->certificate.len == 0) { return NGX_CONF_OK; } if (conf->certificate_key.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined " "for certificate \"%V\"", &conf->certificate); return NGX_CONF_ERROR; } } if (ngx_ssl_create(&conf->ssl, conf->protocols, conf) != NGX_OK) { return NGX_CONF_ERROR; } cln = ngx_pool_cleanup_add(cf->pool, 0); if (cln == NULL) { return NGX_CONF_ERROR; } cln->handler = ngx_ssl_cleanup_ctx; cln->data = &conf->ssl; //#if defined(tengine_version) // ngx_str_t pass_phrase_dialog = ngx_string("builtin"); // ngx_str_t ngx_tcp_ssl_unknown_server_name = ngx_string("unknown"); // // ngx_tcp_core_srv_conf_t *cscf; // ngx_http_ssl_pphrase_dialog_conf_t dialog; // // cscf = ngx_tcp_conf_get_module_srv_conf(cf, ngx_tcp_core_module); // dialog.ssl = &conf->ssl; // dialog.type = &pass_phrase_dialog; // if (cscf->server_name.len != 0) { // dialog.server_name = &cscf->server_name; // } else { // dialog.server_name = &ngx_tcp_ssl_unknown_server_name; // } // // if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate, // &conf->certificate_key, &dialog) // != NGX_OK) // { // return NGX_CONF_ERROR; // } //#else //#if defined(nginx_version) && nginx_version >= 1007003 // if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate, // &conf->certificate_key, conf->passwords) //#else if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate, &conf->certificate_key) //#endif != NGX_OK) { return NGX_CONF_ERROR; } //#endif if (SSL_CTX_set_cipher_list(conf->ssl.ctx, (const char *) conf->ciphers.data) == 0) { ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, "SSL_CTX_set_cipher_list(\"%V\") failed", &conf->ciphers); } if (conf->verify) { if (conf->client_certificate.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no ssl_client_certificate for ssl_client_verify"); return NGX_CONF_ERROR; } if (ngx_tcp_ssl_client_certificate(cf, &conf->ssl, &conf->client_certificate, conf->verify_depth, conf->verify == 2 ? 1 : 0) != NGX_OK) { return NGX_CONF_ERROR; } if (ngx_ssl_crl(cf, &conf->ssl, &conf->crl) != NGX_OK) { return NGX_CONF_ERROR; } } if (conf->prefer_server_ciphers) { SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); } /* a temporary 512-bit RSA key is required for export versions of MSIE */ //#if defined(nginx_version) && nginx_version >= 1000006 SSL_CTX_set_tmp_rsa_callback(conf->ssl.ctx, ngx_ssl_rsa512_key_callback); //#else // if (ngx_ssl_generate_rsa512_key(&conf->ssl) != NGX_OK) { // return NGX_CONF_ERROR; // } //#endif if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) { return NGX_CONF_ERROR; } ngx_conf_merge_value(conf->builtin_session_cache, prev->builtin_session_cache, NGX_SSL_NONE_SCACHE); if (conf->shm_zone == NULL) { conf->shm_zone = prev->shm_zone; } if (ngx_ssl_session_cache(&conf->ssl, &ngx_tcp_ssl_sess_id_ctx, conf->builtin_session_cache, conf->shm_zone, conf->session_timeout) != NGX_OK) { return NGX_CONF_ERROR; } return NGX_CONF_OK; }
int main(int argc, char *argv[]) { char *CApath=NULL,*CAfile=NULL; int badop=0; int bio_pair=0; int force=0; int tls1=0,ssl2=0,ssl3=0,ret=1; int client_auth=0; int server_auth=0,i; int app_verify=0; char *server_cert=TEST_SERVER_CERT; char *server_key=NULL; char *client_cert=TEST_CLIENT_CERT; char *client_key=NULL; SSL_CTX *s_ctx=NULL; SSL_CTX *c_ctx=NULL; SSL_METHOD *meth=NULL; SSL *c_ssl,*s_ssl; int number=1,reuse=0; long bytes=1L; #ifndef OPENSSL_NO_DH DH *dh; int dhe1024 = 0, dhe1024dsa = 0; #endif int no_dhe = 0; int print_time = 0; clock_t s_time = 0, c_time = 0; int comp = 0; COMP_METHOD *cm = NULL; verbose = 0; debug = 0; cipher = 0; bio_err=BIO_new_fp(stderr,BIO_NOCLOSE); CRYPTO_set_locking_callback(lock_dbg_cb); /* enable memory leak checking unless explicitly disabled */ if (!((getenv("OPENSSL_DEBUG_MEMORY") != NULL) && (0 == strcmp(getenv("OPENSSL_DEBUG_MEMORY"), "off")))) { CRYPTO_malloc_debug_init(); CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL); } else { /* OPENSSL_DEBUG_MEMORY=off */ CRYPTO_set_mem_debug_functions(0, 0, 0, 0, 0); } CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); RAND_seed(rnd_seed, sizeof rnd_seed); bio_stdout=BIO_new_fp(stdout,BIO_NOCLOSE); argc--; argv++; while (argc >= 1) { if (strcmp(*argv,"-server_auth") == 0) server_auth=1; else if (strcmp(*argv,"-client_auth") == 0) client_auth=1; else if (strcmp(*argv,"-v") == 0) verbose=1; else if (strcmp(*argv,"-d") == 0) debug=1; else if (strcmp(*argv,"-reuse") == 0) reuse=1; else if (strcmp(*argv,"-dhe1024") == 0) { #ifndef OPENSSL_NO_DH dhe1024=1; #else fprintf(stderr,"ignoring -dhe1024, since I'm compiled without DH\n"); #endif } else if (strcmp(*argv,"-dhe1024dsa") == 0) { #ifndef OPENSSL_NO_DH dhe1024dsa=1; #else fprintf(stderr,"ignoring -dhe1024, since I'm compiled without DH\n"); #endif } else if (strcmp(*argv,"-no_dhe") == 0) no_dhe=1; else if (strcmp(*argv,"-ssl2") == 0) ssl2=1; else if (strcmp(*argv,"-tls1") == 0) tls1=1; else if (strcmp(*argv,"-ssl3") == 0) ssl3=1; else if (strncmp(*argv,"-num",4) == 0) { if (--argc < 1) goto bad; number= atoi(*(++argv)); if (number == 0) number=1; } else if (strcmp(*argv,"-bytes") == 0) { if (--argc < 1) goto bad; bytes= atol(*(++argv)); if (bytes == 0L) bytes=1L; i=strlen(argv[0]); if (argv[0][i-1] == 'k') bytes*=1024L; if (argv[0][i-1] == 'm') bytes*=1024L*1024L; } else if (strcmp(*argv,"-cert") == 0) { if (--argc < 1) goto bad; server_cert= *(++argv); } else if (strcmp(*argv,"-s_cert") == 0) { if (--argc < 1) goto bad; server_cert= *(++argv); } else if (strcmp(*argv,"-key") == 0) { if (--argc < 1) goto bad; server_key= *(++argv); } else if (strcmp(*argv,"-s_key") == 0) { if (--argc < 1) goto bad; server_key= *(++argv); } else if (strcmp(*argv,"-c_cert") == 0) { if (--argc < 1) goto bad; client_cert= *(++argv); } else if (strcmp(*argv,"-c_key") == 0) { if (--argc < 1) goto bad; client_key= *(++argv); } else if (strcmp(*argv,"-cipher") == 0) { if (--argc < 1) goto bad; cipher= *(++argv); } else if (strcmp(*argv,"-CApath") == 0) { if (--argc < 1) goto bad; CApath= *(++argv); } else if (strcmp(*argv,"-CAfile") == 0) { if (--argc < 1) goto bad; CAfile= *(++argv); } else if (strcmp(*argv,"-bio_pair") == 0) { bio_pair = 1; } else if (strcmp(*argv,"-f") == 0) { force = 1; } else if (strcmp(*argv,"-time") == 0) { print_time = 1; } else if (strcmp(*argv,"-zlib") == 0) { comp = COMP_ZLIB; } else if (strcmp(*argv,"-rle") == 0) { comp = COMP_RLE; } else if (strcmp(*argv,"-app_verify") == 0) { app_verify = 1; } else { fprintf(stderr,"unknown option %s\n",*argv); badop=1; break; } argc--; argv++; } if (badop) { bad: sv_usage(); goto end; } if (!ssl2 && !ssl3 && !tls1 && number > 1 && !reuse && !force) { fprintf(stderr, "This case cannot work. Use -f to perform " "the test anyway (and\n-d to see what happens), " "or add one of -ssl2, -ssl3, -tls1, -reuse\n" "to avoid protocol mismatch.\n"); EXIT(1); } if (print_time) { if (!bio_pair) { fprintf(stderr, "Using BIO pair (-bio_pair)\n"); bio_pair = 1; } if (number < 50 && !force) fprintf(stderr, "Warning: For accurate timings, use more connections (e.g. -num 1000)\n"); } /* if (cipher == NULL) cipher=getenv("SSL_CIPHER"); */ SSL_library_init(); SSL_load_error_strings(); if (comp == COMP_ZLIB) cm = COMP_zlib(); if (comp == COMP_RLE) cm = COMP_rle(); if (cm != NULL) { if (cm->type != NID_undef) SSL_COMP_add_compression_method(comp, cm); else { fprintf(stderr, "Warning: %s compression not supported\n", (comp == COMP_RLE ? "rle" : (comp == COMP_ZLIB ? "zlib" : "unknown"))); ERR_print_errors_fp(stderr); } } #if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3) if (ssl2) meth=SSLv2_method(); else if (tls1) meth=TLSv1_method(); else if (ssl3) meth=SSLv3_method(); else meth=SSLv23_method(); #else #ifdef OPENSSL_NO_SSL2 meth=SSLv3_method(); #else meth=SSLv2_method(); #endif #endif c_ctx=SSL_CTX_new(meth); s_ctx=SSL_CTX_new(meth); if ((c_ctx == NULL) || (s_ctx == NULL)) { ERR_print_errors(bio_err); goto end; } if (cipher != NULL) { SSL_CTX_set_cipher_list(c_ctx,cipher); SSL_CTX_set_cipher_list(s_ctx,cipher); } #ifndef OPENSSL_NO_DH if (!no_dhe) { if (dhe1024dsa) { /* use SSL_OP_SINGLE_DH_USE to avoid small subgroup attacks */ SSL_CTX_set_options(s_ctx, SSL_OP_SINGLE_DH_USE); dh=get_dh1024dsa(); } else if (dhe1024) dh=get_dh1024(); else dh=get_dh512(); SSL_CTX_set_tmp_dh(s_ctx,dh); DH_free(dh); } #else (void)no_dhe; #endif #ifndef OPENSSL_NO_RSA SSL_CTX_set_tmp_rsa_callback(s_ctx,tmp_rsa_cb); #endif if (!SSL_CTX_use_certificate_file(s_ctx,server_cert,SSL_FILETYPE_PEM)) { ERR_print_errors(bio_err); } else if (!SSL_CTX_use_PrivateKey_file(s_ctx, (server_key?server_key:server_cert), SSL_FILETYPE_PEM)) { ERR_print_errors(bio_err); goto end; } if (client_auth) { SSL_CTX_use_certificate_file(c_ctx,client_cert, SSL_FILETYPE_PEM); SSL_CTX_use_PrivateKey_file(c_ctx, (client_key?client_key:client_cert), SSL_FILETYPE_PEM); } if ( (!SSL_CTX_load_verify_locations(s_ctx,CAfile,CApath)) || (!SSL_CTX_set_default_verify_paths(s_ctx)) || (!SSL_CTX_load_verify_locations(c_ctx,CAfile,CApath)) || (!SSL_CTX_set_default_verify_paths(c_ctx))) { /* fprintf(stderr,"SSL_load_verify_locations\n"); */ ERR_print_errors(bio_err); /* goto end; */ } if (client_auth) { BIO_printf(bio_err,"client authentication\n"); SSL_CTX_set_verify(s_ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_callback); if (app_verify) { SSL_CTX_set_cert_verify_callback(s_ctx, app_verify_callback, app_verify_arg); } } if (server_auth) { BIO_printf(bio_err,"server authentication\n"); SSL_CTX_set_verify(c_ctx,SSL_VERIFY_PEER, verify_callback); if (app_verify) { SSL_CTX_set_cert_verify_callback(s_ctx, app_verify_callback, app_verify_arg); } } { int session_id_context = 0; SSL_CTX_set_session_id_context(s_ctx, (void *)&session_id_context, sizeof session_id_context); } c_ssl=SSL_new(c_ctx); s_ssl=SSL_new(s_ctx); #ifndef OPENSSL_NO_KRB5 if (c_ssl && c_ssl->kssl_ctx) { char localhost[MAXHOSTNAMELEN+2]; if (gethostname(localhost, sizeof localhost-1) == 0) { localhost[sizeof localhost-1]='\0'; if(strlen(localhost) == sizeof localhost-1) { BIO_printf(bio_err,"localhost name too long\n"); goto end; } kssl_ctx_setstring(c_ssl->kssl_ctx, KSSL_SERVER, localhost); } } #endif /* OPENSSL_NO_KRB5 */ for (i=0; i<number; i++) { if (!reuse) SSL_set_session(c_ssl,NULL); if (bio_pair) ret=doit_biopair(s_ssl,c_ssl,bytes,&s_time,&c_time); else ret=doit(s_ssl,c_ssl,bytes); } if (!verbose) { print_details(c_ssl, ""); } if ((number > 1) || (bytes > 1L)) BIO_printf(bio_stdout, "%d handshakes of %ld bytes done\n",number,bytes); if (print_time) { #ifdef CLOCKS_PER_SEC /* "To determine the time in seconds, the value returned * by the clock function should be divided by the value * of the macro CLOCKS_PER_SEC." * -- ISO/IEC 9899 */ BIO_printf(bio_stdout, "Approximate total server time: %6.2f s\n" "Approximate total client time: %6.2f s\n", (double)s_time/CLOCKS_PER_SEC, (double)c_time/CLOCKS_PER_SEC); #else /* "`CLOCKS_PER_SEC' undeclared (first use this function)" * -- cc on NeXTstep/OpenStep */ BIO_printf(bio_stdout, "Approximate total server time: %6.2f units\n" "Approximate total client time: %6.2f units\n", (double)s_time, (double)c_time); #endif } SSL_free(s_ssl); SSL_free(c_ssl); end: if (s_ctx != NULL) SSL_CTX_free(s_ctx); if (c_ctx != NULL) SSL_CTX_free(c_ctx); if (bio_stdout != NULL) BIO_free(bio_stdout); #ifndef OPENSSL_NO_RSA free_tmp_rsa(); #endif #ifndef OPENSSL_NO_ENGINE ENGINE_cleanup(); #endif CRYPTO_cleanup_all_ex_data(); ERR_free_strings(); ERR_remove_state(0); EVP_cleanup(); CRYPTO_mem_leaks(bio_err); if (bio_err != NULL) BIO_free(bio_err); EXIT(ret); }
static char * ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) { ngx_stream_ssl_conf_t *prev = parent; ngx_stream_ssl_conf_t *conf = child; ngx_pool_cleanup_t *cln; ngx_conf_merge_msec_value(conf->handshake_timeout, prev->handshake_timeout, 60000); ngx_conf_merge_value(conf->session_timeout, prev->session_timeout, 300); ngx_conf_merge_value(conf->prefer_server_ciphers, prev->prefer_server_ciphers, 0); ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols, (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1 |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2)); ngx_conf_merge_str_value(conf->certificate, prev->certificate, ""); ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, ""); ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL); ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, ""); ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve, NGX_DEFAULT_ECDH_CURVE); ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS); conf->ssl.log = cf->log; if (conf->certificate.len == 0) { return NGX_CONF_OK; } if (conf->certificate_key.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined " "for certificate \"%V\"", &conf->certificate); return NGX_CONF_ERROR; } if (ngx_ssl_create(&conf->ssl, conf->protocols, NULL) != NGX_OK) { return NGX_CONF_ERROR; } cln = ngx_pool_cleanup_add(cf->pool, 0); if (cln == NULL) { return NGX_CONF_ERROR; } cln->handler = ngx_ssl_cleanup_ctx; cln->data = &conf->ssl; if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate, &conf->certificate_key, conf->passwords) != NGX_OK) { return NGX_CONF_ERROR; } if (SSL_CTX_set_cipher_list(conf->ssl.ctx, (const char *) conf->ciphers.data) == 0) { ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, "SSL_CTX_set_cipher_list(\"%V\") failed", &conf->ciphers); return NGX_CONF_ERROR; } if (conf->prefer_server_ciphers) { SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); } #ifndef LIBRESSL_VERSION_NUMBER SSL_CTX_set_tmp_rsa_callback(conf->ssl.ctx, ngx_ssl_rsa512_key_callback); #endif if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) { return NGX_CONF_ERROR; } if (ngx_ssl_ecdh_curve(cf, &conf->ssl, &conf->ecdh_curve) != NGX_OK) { return NGX_CONF_ERROR; } ngx_conf_merge_value(conf->builtin_session_cache, prev->builtin_session_cache, NGX_SSL_NONE_SCACHE); if (conf->shm_zone == NULL) { conf->shm_zone = prev->shm_zone; } if (ngx_ssl_session_cache(&conf->ssl, &ngx_stream_ssl_sess_id_ctx, conf->builtin_session_cache, conf->shm_zone, conf->session_timeout) != NGX_OK) { return NGX_CONF_ERROR; } ngx_conf_merge_value(conf->session_tickets, prev->session_tickets, 1); #ifdef SSL_OP_NO_TICKET if (!conf->session_tickets) { SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_NO_TICKET); } #endif ngx_conf_merge_ptr_value(conf->session_ticket_keys, prev->session_ticket_keys, NULL); if (ngx_ssl_session_ticket_keys(cf, &conf->ssl, conf->session_ticket_keys) != NGX_OK) { return NGX_CONF_ERROR; } return NGX_CONF_OK; }
static char * ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) { ngx_http_ssl_srv_conf_t *prev = parent; ngx_http_ssl_srv_conf_t *conf = child; ngx_pool_cleanup_t *cln; if (conf->enable == NGX_CONF_UNSET) { if (prev->enable == NGX_CONF_UNSET) { conf->enable = 0; } else { conf->enable = prev->enable; conf->file = prev->file; conf->line = prev->line; } } ngx_conf_merge_value(conf->session_timeout, prev->session_timeout, 300); ngx_conf_merge_value(conf->prefer_server_ciphers, prev->prefer_server_ciphers, 0); ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols, (NGX_CONF_BITMASK_SET|NGX_SSL_SSLv3|NGX_SSL_TLSv1 |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2)); ngx_conf_merge_uint_value(conf->verify, prev->verify, 0); ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1); ngx_conf_merge_str_value(conf->certificate, prev->certificate, ""); ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, ""); ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, ""); ngx_conf_merge_str_value(conf->client_certificate, prev->client_certificate, ""); ngx_conf_merge_str_value(conf->trusted_certificate, prev->trusted_certificate, ""); ngx_conf_merge_str_value(conf->crl, prev->crl, ""); ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve, NGX_DEFAULT_ECDH_CURVE); ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS); ngx_conf_merge_value(conf->stapling, prev->stapling, 0); ngx_conf_merge_value(conf->stapling_verify, prev->stapling_verify, 0); ngx_conf_merge_str_value(conf->stapling_file, prev->stapling_file, ""); ngx_conf_merge_str_value(conf->stapling_responder, prev->stapling_responder, ""); conf->ssl.log = cf->log; if (conf->enable) { if (conf->certificate.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate\" is defined for " "the \"ssl\" directive in %s:%ui", conf->file, conf->line); return NGX_CONF_ERROR; } if (conf->certificate_key.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined for " "the \"ssl\" directive in %s:%ui", conf->file, conf->line); return NGX_CONF_ERROR; } } else { if (conf->certificate.len == 0) { return NGX_CONF_OK; } if (conf->certificate_key.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined " "for certificate \"%V\"", &conf->certificate); return NGX_CONF_ERROR; } } if (ngx_ssl_create(&conf->ssl, conf->protocols, conf) != NGX_OK) { return NGX_CONF_ERROR; } #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME if (SSL_CTX_set_tlsext_servername_callback(conf->ssl.ctx, ngx_http_ssl_servername) == 0) { ngx_log_error(NGX_LOG_WARN, cf->log, 0, "nginx was built with SNI support, however, now it is linked " "dynamically to an OpenSSL library which has no tlsext support, " "therefore SNI is not available"); } #endif #ifdef TLSEXT_TYPE_next_proto_neg SSL_CTX_set_next_protos_advertised_cb(conf->ssl.ctx, ngx_http_ssl_npn_advertised, NULL); #endif cln = ngx_pool_cleanup_add(cf->pool, 0); if (cln == NULL) { return NGX_CONF_ERROR; } cln->handler = ngx_ssl_cleanup_ctx; cln->data = &conf->ssl; if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate, &conf->certificate_key) != NGX_OK) { return NGX_CONF_ERROR; } if (SSL_CTX_set_cipher_list(conf->ssl.ctx, (const char *) conf->ciphers.data) == 0) { ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, "SSL_CTX_set_cipher_list(\"%V\") failed", &conf->ciphers); return NGX_CONF_ERROR; } if (conf->verify) { if (conf->client_certificate.len == 0 && conf->verify != 3) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no ssl_client_certificate for ssl_client_verify"); return NGX_CONF_ERROR; } if (ngx_ssl_client_certificate(cf, &conf->ssl, &conf->client_certificate, conf->verify_depth) != NGX_OK) { return NGX_CONF_ERROR; } } if (ngx_ssl_trusted_certificate(cf, &conf->ssl, &conf->trusted_certificate, conf->verify_depth) != NGX_OK) { return NGX_CONF_ERROR; } if (ngx_ssl_crl(cf, &conf->ssl, &conf->crl) != NGX_OK) { return NGX_CONF_ERROR; } if (conf->prefer_server_ciphers) { SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); } /* a temporary 512-bit RSA key is required for export versions of MSIE */ SSL_CTX_set_tmp_rsa_callback(conf->ssl.ctx, ngx_ssl_rsa512_key_callback); if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) { return NGX_CONF_ERROR; } if (ngx_ssl_ecdh_curve(cf, &conf->ssl, &conf->ecdh_curve) != NGX_OK) { return NGX_CONF_ERROR; } ngx_conf_merge_value(conf->builtin_session_cache, prev->builtin_session_cache, NGX_SSL_NONE_SCACHE); if (conf->shm_zone == NULL) { conf->shm_zone = prev->shm_zone; } if (ngx_ssl_session_cache(&conf->ssl, &ngx_http_ssl_sess_id_ctx, conf->builtin_session_cache, conf->shm_zone, conf->session_timeout) != NGX_OK) { return NGX_CONF_ERROR; } if (conf->stapling) { if (ngx_ssl_stapling(cf, &conf->ssl, &conf->stapling_file, &conf->stapling_responder, conf->stapling_verify) != NGX_OK) { return NGX_CONF_ERROR; } } return NGX_CONF_OK; }
TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props) { SSL_CTX *server_ctx; long off = 0; int verify_flags = SSL_VERIFY_NONE; int cachable; int protomask; TLS_APPL_STATE *app_ctx; const EVP_MD *md_alg; unsigned int md_len; if (props->log_level >= 2) msg_info("initializing the server-side TLS engine"); /* * Load (mostly cipher related) TLS-library internal main.cf parameters. */ tls_param_init(); /* * Detect mismatch between compile-time headers and run-time library. */ tls_check_version(); /* * Initialize the OpenSSL library by the book! To start with, we must * initialize the algorithms. We want cleartext error messages instead of * just error codes, so we load the error_strings. */ SSL_load_error_strings(); OpenSSL_add_ssl_algorithms(); /* * First validate the protocols. If these are invalid, we can't continue. */ protomask = tls_protocol_mask(props->protocols); if (protomask == TLS_PROTOCOL_INVALID) { /* tls_protocol_mask() logs no warning. */ msg_warn("Invalid TLS protocol list \"%s\": disabling TLS support", props->protocols); return (0); } /* * Create an application data index for SSL objects, so that we can * attach TLScontext information; this information is needed inside * tls_verify_certificate_callback(). */ if (TLScontext_index < 0) { if ((TLScontext_index = SSL_get_ex_new_index(0, 0, 0, 0, 0)) < 0) { msg_warn("Cannot allocate SSL application data index: " "disabling TLS support"); return (0); } } /* * Register SHA-2 digests, if implemented and not already registered. * Improves interoperability with clients and servers that prematurely * deploy SHA-2 certificates. */ #if defined(LN_sha256) && defined(NID_sha256) && !defined(OPENSSL_NO_SHA256) if (!EVP_get_digestbyname(LN_sha224)) EVP_add_digest(EVP_sha224()); if (!EVP_get_digestbyname(LN_sha256)) EVP_add_digest(EVP_sha256()); #endif #if defined(LN_sha512) && defined(NID_sha512) && !defined(OPENSSL_NO_SHA512) if (!EVP_get_digestbyname(LN_sha384)) EVP_add_digest(EVP_sha384()); if (!EVP_get_digestbyname(LN_sha512)) EVP_add_digest(EVP_sha512()); #endif /* * If the administrator specifies an unsupported digest algorithm, fail * now, rather than in the middle of a TLS handshake. */ if ((md_alg = EVP_get_digestbyname(props->fpt_dgst)) == 0) { msg_warn("Digest algorithm \"%s\" not found: disabling TLS support", props->fpt_dgst); return (0); } /* * Sanity check: Newer shared libraries may use larger digests. */ if ((md_len = EVP_MD_size(md_alg)) > EVP_MAX_MD_SIZE) { msg_warn("Digest algorithm \"%s\" output size %u too large:" " disabling TLS support", props->fpt_dgst, md_len); return (0); } /* * Initialize the PRNG (Pseudo Random Number Generator) with some seed * from external and internal sources. Don't enable TLS without some real * entropy. */ if (tls_ext_seed(var_tls_daemon_rand_bytes) < 0) { msg_warn("no entropy for TLS key generation: disabling TLS support"); return (0); } tls_int_seed(); /* * The SSL/TLS specifications require the client to send a message in the * oldest specification it understands with the highest level it * understands in the message. Netscape communicator can still * communicate with SSLv2 servers, so it sends out a SSLv2 client hello. * To deal with it, our server must be SSLv2 aware (even if we don't like * SSLv2), so we need to have the SSLv23 server here. If we want to limit * the protocol level, we can add an option to not use SSLv2/v3/TLSv1 * later. */ ERR_clear_error(); if ((server_ctx = SSL_CTX_new(SSLv23_server_method())) == 0) { msg_warn("cannot allocate server SSL_CTX: disabling TLS support"); tls_print_errors(); return (0); } /* * See the verify callback in tls_verify.c */ SSL_CTX_set_verify_depth(server_ctx, props->verifydepth + 1); /* * Protocol work-arounds, OpenSSL version dependent. */ #ifdef SSL_OP_NO_TICKET off |= SSL_OP_NO_TICKET; #endif off |= tls_bug_bits(); SSL_CTX_set_options(server_ctx, off); /* * Global protocol selection. */ if (protomask != 0) SSL_CTX_set_options(server_ctx, ((protomask & TLS_PROTOCOL_TLSv1) ? SSL_OP_NO_TLSv1 : 0L) | ((protomask & TLS_PROTOCOL_TLSv1_1) ? SSL_OP_NO_TLSv1_1 : 0L) | ((protomask & TLS_PROTOCOL_TLSv1_2) ? SSL_OP_NO_TLSv1_2 : 0L) | ((protomask & TLS_PROTOCOL_SSLv3) ? SSL_OP_NO_SSLv3 : 0L) | ((protomask & TLS_PROTOCOL_SSLv2) ? SSL_OP_NO_SSLv2 : 0L)); #if OPENSSL_VERSION_NUMBER >= 0x0090700fL /* * Some sites may want to give the client less rope. On the other hand, * this could trigger inter-operability issues, the client should not * offer ciphers it implements poorly, but this hasn't stopped some * vendors from getting it wrong. * * XXX: Given OpenSSL's security history, nobody should still be using * 0.9.7, let alone 0.9.6 or earlier. Warning added to TLS_README.html. */ if (var_tls_preempt_clist) SSL_CTX_set_options(server_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); #endif /* * Set the call-back routine to debug handshake progress. */ if (props->log_level >= 2) SSL_CTX_set_info_callback(server_ctx, tls_info_callback); /* * Load the CA public key certificates for both the server cert and for * the verification of client certificates. As provided by OpenSSL we * support two types of CA certificate handling: One possibility is to * add all CA certificates to one large CAfile, the other possibility is * a directory pointed to by CApath, containing separate files for each * CA with softlinks named after the hash values of the certificate. The * first alternative has the advantage that the file is opened and read * at startup time, so that you don't have the hassle to maintain another * copy of the CApath directory for chroot-jail. */ if (tls_set_ca_certificate_info(server_ctx, props->CAfile, props->CApath) < 0) { /* tls_set_ca_certificate_info() already logs a warning. */ SSL_CTX_free(server_ctx); /* 200411 */ return (0); } /* * Load the server public key certificate and private key from file and * check whether the cert matches the key. We can use RSA certificates * ("cert") DSA certificates ("dcert") or ECDSA certificates ("eccert"). * All three can be made available at the same time. The CA certificates * for all three are handled in the same setup already finished. Which * one is used depends on the cipher negotiated (that is: the first * cipher listed by the client which does match the server). A client * with RSA only (e.g. Netscape) will use the RSA certificate only. A * client with openssl-library will use RSA first if not especially * changed in the cipher setup. */ if (tls_set_my_certificate_key_info(server_ctx, props->cert_file, props->key_file, props->dcert_file, props->dkey_file, props->eccert_file, props->eckey_file) < 0) { /* tls_set_my_certificate_key_info() already logs a warning. */ SSL_CTX_free(server_ctx); /* 200411 */ return (0); } /* * According to the OpenSSL documentation, temporary RSA key is needed * export ciphers are in use. We have to provide one, so well, we just do * it. */ SSL_CTX_set_tmp_rsa_callback(server_ctx, tls_tmp_rsa_cb); /* * Diffie-Hellman key generation parameters can either be loaded from * files (preferred) or taken from compiled in values. First, set the * callback that will select the values when requested, then load the * (possibly) available DH parameters from files. We are generous with * the error handling, since we do have default values compiled in, so we * will not abort but just log the error message. */ SSL_CTX_set_tmp_dh_callback(server_ctx, tls_tmp_dh_cb); if (*props->dh1024_param_file != 0) tls_set_dh_from_file(props->dh1024_param_file, 1024); if (*props->dh512_param_file != 0) tls_set_dh_from_file(props->dh512_param_file, 512); /* * Enable EECDH if available, errors are not fatal, we just keep going * with any remaining key-exchange algorithms. */ (void) tls_set_eecdh_curve(server_ctx, props->eecdh_grade); /* * If we want to check client certificates, we have to indicate it in * advance. By now we only allow to decide on a global basis. If we want * to allow certificate based relaying, we must ask the client to provide * one with SSL_VERIFY_PEER. The client now can decide, whether it * provides one or not. We can enforce a failure of the negotiation with * SSL_VERIFY_FAIL_IF_NO_PEER_CERT, if we do not allow a connection * without one. In the "server hello" following the initialization by the * "client hello" the server must provide a list of CAs it is willing to * accept. Some clever clients will then select one from the list of * available certificates matching these CAs. Netscape Communicator will * present the list of certificates for selecting the one to be sent, or * it will issue a warning, if there is no certificate matching the * available CAs. * * With regard to the purpose of the certificate for relaying, we might like * a later negotiation, maybe relaying would already be allowed for other * reasons, but this would involve severe changes in the internal postfix * logic, so we have to live with it the way it is. */ if (props->ask_ccert) verify_flags = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE; SSL_CTX_set_verify(server_ctx, verify_flags, tls_verify_certificate_callback); if (*props->CAfile) SSL_CTX_set_client_CA_list(server_ctx, SSL_load_client_CA_file(props->CAfile)); /* * Initialize our own TLS server handle, before diving into the details * of TLS session cache management. */ app_ctx = tls_alloc_app_context(server_ctx); /* * The session cache is implemented by the tlsmgr(8) server. * * XXX 200502 Surprise: when OpenSSL purges an entry from the in-memory * cache, it also attempts to purge the entry from the on-disk cache. * This is undesirable, especially when we set the in-memory cache size * to 1. For this reason we don't allow OpenSSL to purge on-disk cache * entries, and leave it up to the tlsmgr process instead. Found by * Victor Duchovni. */ if (tls_mgr_policy(props->cache_type, &cachable) != TLS_MGR_STAT_OK) cachable = 0; if (cachable || props->set_sessid) { /* * Initialize the session cache. * * With a large number of concurrent smtpd(8) processes, it is not a * good idea to cache multiple large session objects in each process. * We set the internal cache size to 1, and don't register a * "remove_cb" so as to avoid deleting good sessions from the * external cache prematurely (when the internal cache is full, * OpenSSL removes sessions from the external cache also)! * * This makes SSL_CTX_remove_session() not useful for flushing broken * sessions from the external cache, so we must delete them directly * (not via a callback). * * Set a session id context to identify to what type of server process * created a session. In our case, the context is simply the name of * the mail system: "Postfix/TLS". */ SSL_CTX_sess_set_cache_size(server_ctx, 1); SSL_CTX_set_session_id_context(server_ctx, (void *) &server_session_id_context, sizeof(server_session_id_context)); SSL_CTX_set_session_cache_mode(server_ctx, SSL_SESS_CACHE_SERVER | SSL_SESS_CACHE_NO_AUTO_CLEAR); if (cachable) { app_ctx->cache_type = mystrdup(props->cache_type); SSL_CTX_sess_set_get_cb(server_ctx, get_server_session_cb); SSL_CTX_sess_set_new_cb(server_ctx, new_server_session_cb); } /* * OpenSSL ignores timed-out sessions. We need to set the internal * cache timeout at least as high as the external cache timeout. This * applies even if no internal cache is used. */ SSL_CTX_set_timeout(server_ctx, props->scache_timeout); } else { /* * If we have no external cache, disable all caching. No use wasting * server memory resources with sessions they are unlikely to be able * to reuse. */ SSL_CTX_set_session_cache_mode(server_ctx, SSL_SESS_CACHE_OFF); } return (app_ctx); }
static char * ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) { ngx_mail_ssl_conf_t *prev = parent; ngx_mail_ssl_conf_t *conf = child; char *mode; ngx_pool_cleanup_t *cln; ngx_conf_merge_value(conf->enable, prev->enable, 0); ngx_conf_merge_uint_value(conf->starttls, prev->starttls, NGX_MAIL_STARTTLS_OFF); ngx_conf_merge_value(conf->session_timeout, prev->session_timeout, 300); ngx_conf_merge_value(conf->prefer_server_ciphers, prev->prefer_server_ciphers, 0); ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols, (NGX_CONF_BITMASK_SET|NGX_SSL_SSLv3|NGX_SSL_TLSv1)); ngx_conf_merge_str_value(conf->certificate, prev->certificate, ""); ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, ""); ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, ""); ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve, NGX_DEFAULT_ECDH_CURVE); ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS); conf->ssl.log = cf->log; if (conf->enable) { mode = "ssl"; } else if (conf->starttls != NGX_MAIL_STARTTLS_OFF) { mode = "starttls"; } else { mode = ""; } if (*mode) { if (conf->certificate.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate\" is defined for " "the \"%s\" directive in %s:%ui", mode, conf->file, conf->line); return NGX_CONF_ERROR; } if (conf->certificate_key.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined for " "the \"%s\" directive in %s:%ui", mode, conf->file, conf->line); return NGX_CONF_ERROR; } } else { if (conf->certificate.len == 0) { return NGX_CONF_OK; } if (conf->certificate_key.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined " "for certificate \"%V\"", &conf->certificate); return NGX_CONF_ERROR; } } if (ngx_ssl_create(&conf->ssl, conf->protocols, NULL) != NGX_OK) { return NGX_CONF_ERROR; } cln = ngx_pool_cleanup_add(cf->pool, 0); if (cln == NULL) { return NGX_CONF_ERROR; } cln->handler = ngx_ssl_cleanup_ctx; cln->data = &conf->ssl; if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate, &conf->certificate_key) != NGX_OK) { return NGX_CONF_ERROR; } if (conf->ciphers.len) { if (SSL_CTX_set_cipher_list(conf->ssl.ctx, (const char *) conf->ciphers.data) == 0) { ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, "SSL_CTX_set_cipher_list(\"%V\") failed", &conf->ciphers); } } if (conf->prefer_server_ciphers) { SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); } SSL_CTX_set_tmp_rsa_callback(conf->ssl.ctx, ngx_ssl_rsa512_key_callback); if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) { return NGX_CONF_ERROR; } ngx_conf_merge_value(conf->builtin_session_cache, prev->builtin_session_cache, NGX_SSL_NONE_SCACHE); if (conf->shm_zone == NULL) { conf->shm_zone = prev->shm_zone; } if (ngx_ssl_session_cache(&conf->ssl, &ngx_mail_ssl_sess_id_ctx, conf->builtin_session_cache, conf->shm_zone, conf->session_timeout) != NGX_OK) { return NGX_CONF_ERROR; } return NGX_CONF_OK; }
int MaOpenSslConfig::start() { const SSL_METHOD *meth; char *hostName; if (keyFile == 0) { mprError(MPR_L, MPR_LOG, "OpenSSL: Cant start SSL: missing key file"); return MPR_ERR_CANT_INITIALIZE; } if (certFile == 0) { mprError(MPR_L, MPR_LOG, "OpenSSL: Cant start SSL: missing certificate file"); return MPR_ERR_CANT_INITIALIZE; } // // Depending on the order in the configuration file, we may get called // by sslModule::start() before OpenSslModule::start has run. So we // must initialize here. // openSslModule->start(); hostName = host->getName(); if (protocols == MPR_HTTP_PROTO_SSLV2) { meth = SSLv2_server_method(); } else { meth = SSLv23_server_method(); } context = SSL_CTX_new(meth); mprAssert(context); if (context == 0) { mprError(MPR_L, MPR_LOG, "OpenSSL: Unable to create SSL context"); return MPR_ERR_CANT_CREATE; } SSL_CTX_set_app_data(context, (void*) this); SSL_CTX_set_quiet_shutdown(context, 1); SSL_CTX_sess_set_cache_size(context, 512); // // Configure the certificate for this host // if (configureCertificates(context, keyFile, certFile) != 0) { SSL_CTX_free(context); context = 0; return MPR_ERR_CANT_INITIALIZE; } mprLog(4, "SSL: %s: Using ciphers %s\n", hostName, ciphers); SSL_CTX_set_cipher_list(context, ciphers); // // Configure the client verification certificate locations // if (verifyClient) { if (caFile == 0 && caPath == 0) { mprError(MPR_L, MPR_LOG, "OpenSSL: Must define CA certificates if using client verification"); SSL_CTX_free(context); context = 0; return MPR_ERR_BAD_STATE; } if (caFile || caPath) { if ((!SSL_CTX_load_verify_locations(context, caFile, caPath)) || (!SSL_CTX_set_default_verify_paths(context))) { mprError(MPR_L, MPR_LOG, "OpenSSL: Unable to set certificate locations"); SSL_CTX_free(context); context = 0; return MPR_ERR_CANT_ACCESS; } if (caFile) { STACK_OF(X509_NAME) *certNames; certNames = SSL_load_client_CA_file(caFile); if (certNames == 0) { } else { // // Define the list of CA certificates to send to the client // before they send their client certificate for validation // SSL_CTX_set_client_CA_list(context, certNames); } } } mprLog(4, "SSL: %s: is verifying client connections\n", hostName); if (caFile) { mprLog(4, "SSL: %s: Using certificates from %s\n", hostName, caFile); } else if (caPath) { mprLog(4, "SSL: %s: Using certificates from directory %s\n", hostName, caPath); } SSL_CTX_set_verify(context, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verifyX509Certificate); SSL_CTX_set_verify_depth(context, verifyDepth); } else { SSL_CTX_set_verify(context, SSL_VERIFY_NONE, verifyX509Certificate); } // // Define callbacks // SSL_CTX_set_tmp_rsa_callback(context, rsaCallback); SSL_CTX_set_tmp_dh_callback(context, dhCallback); // // Enable all buggy client work-arounds // SSL_CTX_set_options(context, SSL_OP_ALL); #ifdef SSL_OP_NO_TICKET SSL_CTX_set_options(context, SSL_OP_NO_TICKET); #endif #ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION SSL_CTX_set_options(context, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); #endif SSL_CTX_set_mode(context, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY); // // Select the required protocols // SSL_CTX_set_options(context, SSL_OP_NO_SSLv2); if (!(protocols & MPR_HTTP_PROTO_SSLV3)) { SSL_CTX_set_options(context, SSL_OP_NO_SSLv3); mprLog(4, "SSL: %s: Disabling SSLv3\n", hostName); } if (!(protocols & MPR_HTTP_PROTO_TLSV1)) { SSL_CTX_set_options(context, SSL_OP_NO_TLSv1); mprLog(4, "SSL: %s: Disabling TLSv1\n", hostName); } // // Ensure we generate a new private key for each connection // SSL_CTX_set_options(context, SSL_OP_SINGLE_DH_USE); // // Pre-generate some keys that are slow to compute // rsaKey512 = RSA_generate_key(512, RSA_F4, 0, 0); rsaKey1024 = RSA_generate_key(1024, RSA_F4, 0, 0); dhKey512 = get_dh512(); dhKey1024 = get_dh1024(); return 0; }
TLS_APPL_STATE *tls_client_create(const TLS_CLIENT_INIT_PROPS *props) { const char *myname = "tls_client_create"; long off = 0; int cachable; SSL_CTX *client_ctx; TLS_APPL_STATE *app_ctx; /* * The SSL/TLS specifications require the client to send a message in the * oldest specification it understands with the highest level it * understands in the message. RFC2487 is only specified for TLSv1, but * we want to be as compatible as possible, so we will start off with a * SSLv2 greeting allowing the best we can offer: TLSv1. We can restrict * this with the options setting later, anyhow. */ ERR_clear_error(); if ((client_ctx = SSL_CTX_new(SSLv23_client_method())) == 0) { acl_msg_warn("%s: cannot allocate client SSL_CTX: disabling TLS support", myname); tls_print_errors(); return (0); } /* * See the verify callback in tls_verify.c */ SSL_CTX_set_verify_depth(client_ctx, props->verifydepth + 1); /* * Protocol selection is destination dependent, so we delay the protocol * selection options to the per-session SSL object. */ off |= tls_bug_bits(); SSL_CTX_set_options(client_ctx, off); /* * Set the call-back routine for verbose logging. */ if (props->log_level >= 2) SSL_CTX_set_info_callback(client_ctx, tls_info_callback); /* * Load the CA public key certificates for both the client cert and for * the verification of server certificates. As provided by OpenSSL we * support two types of CA certificate handling: One possibility is to * add all CA certificates to one large CAfile, the other possibility is * a directory pointed to by CApath, containing separate files for each * CA with softlinks named after the hash values of the certificate. The * first alternative has the advantage that the file is opened and read * at startup time, so that you don't have the hassle to maintain another * copy of the CApath directory for chroot-jail. */ if (tls_set_ca_certificate_info(client_ctx, props->CAfile, props->CApath) < 0) { /* tls_set_ca_certificate_info() already logs a warning. */ SSL_CTX_free(client_ctx); /* 200411 */ return (0); } /* * We do not need a client certificate, so the certificates are only * loaded (and checked) if supplied. A clever client would handle * multiple client certificates and decide based on the list of * acceptable CAs, sent by the server, which certificate to submit. * OpenSSL does however not do this and also has no call-back hooks to * easily implement it. * * Load the client public key certificate and private key from file and * check whether the cert matches the key. We can use RSA certificates * ("cert") DSA certificates ("dcert") or ECDSA certificates ("eccert"). * All three can be made available at the same time. The CA certificates * for all three are handled in the same setup already finished. Which * one is used depends on the cipher negotiated (that is: the first * cipher listed by the client which does match the server). The client * certificate is presented after the server chooses the session cipher, * so we will just present the right cert for the chosen cipher (if it * uses certificates). */ if (tls_set_my_certificate_key_info(client_ctx, props->cert_file, props->key_file, props->dcert_file, props->dkey_file, props->eccert_file, props->eckey_file) < 0) { /* tls_set_my_certificate_key_info() already logs a warning. */ SSL_CTX_free(client_ctx); /* 200411 */ return (0); } /* * According to the OpenSSL documentation, temporary RSA key is needed * export ciphers are in use. We have to provide one, so well, we just do * it. */ SSL_CTX_set_tmp_rsa_callback(client_ctx, tls_tmp_rsa_cb); /* * Finally, the setup for the server certificate checking, done "by the * book". */ SSL_CTX_set_verify(client_ctx, SSL_VERIFY_NONE, tls_verify_certificate_callback); /* * Initialize the session cache. * * Since the client does not search an internal cache, we simply disable it. * It is only useful for expiring old sessions, but we do that in the * tlsmgr(8). * * This makes SSL_CTX_remove_session() not useful for flushing broken * sessions from the external cache, so we must delete them directly (not * via a callback). */ if (props->cache_type == 0 || tls_mgr_policy(props->cache_type, &cachable) != TLS_MGR_STAT_OK) cachable = 0; /* * Allocate an application context, and populate with mandatory protocol * and cipher data. */ app_ctx = tls_alloc_app_context(client_ctx); /* * The external session cache is implemented by the tlsmgr(8) process. */ if (cachable) { app_ctx->cache_type = acl_mystrdup(props->cache_type); /* * OpenSSL does not use callbacks to load sessions from a client * cache, so we must invoke that function directly. Apparently, * OpenSSL does not provide a way to pass session names from here to * call-back routines that do session lookup. * * OpenSSL can, however, automatically save newly created sessions for * us by callback (we create the session name in the call-back * function). * * XXX gcc 2.95 can't compile #ifdef .. #endif in the expansion of * SSL_SESS_CACHE_CLIENT | SSL_SESS_CACHE_NO_INTERNAL_STORE | * SSL_SESS_CACHE_NO_AUTO_CLEAR. */ #ifndef SSL_SESS_CACHE_NO_INTERNAL_STORE #define SSL_SESS_CACHE_NO_INTERNAL_STORE 0 #endif SSL_CTX_set_session_cache_mode(client_ctx, SSL_SESS_CACHE_CLIENT | SSL_SESS_CACHE_NO_AUTO_CLEAR | SSL_SESS_CACHE_NO_INTERNAL_STORE); SSL_CTX_sess_set_new_cb(client_ctx, new_client_session_cb); } return (app_ctx); }
TLS_APPL_STATE *tls_client_init(const TLS_CLIENT_INIT_PROPS *props) { long off = 0; int cachable; int scache_timeout; SSL_CTX *client_ctx; TLS_APPL_STATE *app_ctx; int log_mask; /* * Convert user loglevel to internal logmask. */ log_mask = tls_log_mask(props->log_param, props->log_level); if (log_mask & TLS_LOG_VERBOSE) msg_info("initializing the client-side TLS engine"); /* * Load (mostly cipher related) TLS-library internal main.cf parameters. */ tls_param_init(); /* * Detect mismatch between compile-time headers and run-time library. */ tls_check_version(); /* * Initialize the OpenSSL library by the book! To start with, we must * initialize the algorithms. We want cleartext error messages instead of * just error codes, so we load the error_strings. */ SSL_load_error_strings(); OpenSSL_add_ssl_algorithms(); /* * Create an application data index for SSL objects, so that we can * attach TLScontext information; this information is needed inside * tls_verify_certificate_callback(). */ if (TLScontext_index < 0) { if ((TLScontext_index = SSL_get_ex_new_index(0, 0, 0, 0, 0)) < 0) { msg_warn("Cannot allocate SSL application data index: " "disabling TLS support"); return (0); } } /* * If the administrator specifies an unsupported digest algorithm, fail * now, rather than in the middle of a TLS handshake. */ if (!tls_validate_digest(props->mdalg)) { msg_warn("disabling TLS support"); return (0); } /* * Initialize the PRNG (Pseudo Random Number Generator) with some seed * from external and internal sources. Don't enable TLS without some real * entropy. */ if (tls_ext_seed(var_tls_daemon_rand_bytes) < 0) { msg_warn("no entropy for TLS key generation: disabling TLS support"); return (0); } tls_int_seed(); /* * The SSL/TLS specifications require the client to send a message in the * oldest specification it understands with the highest level it * understands in the message. RFC2487 is only specified for TLSv1, but * we want to be as compatible as possible, so we will start off with a * SSLv2 greeting allowing the best we can offer: TLSv1. We can restrict * this with the options setting later, anyhow. */ ERR_clear_error(); if ((client_ctx = SSL_CTX_new(SSLv23_client_method())) == 0) { msg_warn("cannot allocate client SSL_CTX: disabling TLS support"); tls_print_errors(); return (0); } /* * See the verify callback in tls_verify.c */ SSL_CTX_set_verify_depth(client_ctx, props->verifydepth + 1); /* * Protocol selection is destination dependent, so we delay the protocol * selection options to the per-session SSL object. */ off |= tls_bug_bits(); SSL_CTX_set_options(client_ctx, off); /* * Set the call-back routine for verbose logging. */ if (log_mask & TLS_LOG_DEBUG) SSL_CTX_set_info_callback(client_ctx, tls_info_callback); /* * Load the CA public key certificates for both the client cert and for * the verification of server certificates. As provided by OpenSSL we * support two types of CA certificate handling: One possibility is to * add all CA certificates to one large CAfile, the other possibility is * a directory pointed to by CApath, containing separate files for each * CA with softlinks named after the hash values of the certificate. The * first alternative has the advantage that the file is opened and read * at startup time, so that you don't have the hassle to maintain another * copy of the CApath directory for chroot-jail. */ if (tls_set_ca_certificate_info(client_ctx, props->CAfile, props->CApath) < 0) { /* tls_set_ca_certificate_info() already logs a warning. */ SSL_CTX_free(client_ctx); /* 200411 */ return (0); } /* * We do not need a client certificate, so the certificates are only * loaded (and checked) if supplied. A clever client would handle * multiple client certificates and decide based on the list of * acceptable CAs, sent by the server, which certificate to submit. * OpenSSL does however not do this and also has no call-back hooks to * easily implement it. * * Load the client public key certificate and private key from file and * check whether the cert matches the key. We can use RSA certificates * ("cert") DSA certificates ("dcert") or ECDSA certificates ("eccert"). * All three can be made available at the same time. The CA certificates * for all three are handled in the same setup already finished. Which * one is used depends on the cipher negotiated (that is: the first * cipher listed by the client which does match the server). The client * certificate is presented after the server chooses the session cipher, * so we will just present the right cert for the chosen cipher (if it * uses certificates). */ if (tls_set_my_certificate_key_info(client_ctx, props->cert_file, props->key_file, props->dcert_file, props->dkey_file, props->eccert_file, props->eckey_file) < 0) { /* tls_set_my_certificate_key_info() already logs a warning. */ SSL_CTX_free(client_ctx); /* 200411 */ return (0); } /* * According to the OpenSSL documentation, temporary RSA key is needed * export ciphers are in use. We have to provide one, so well, we just do * it. */ SSL_CTX_set_tmp_rsa_callback(client_ctx, tls_tmp_rsa_cb); /* * Finally, the setup for the server certificate checking, done "by the * book". */ SSL_CTX_set_verify(client_ctx, SSL_VERIFY_NONE, tls_verify_certificate_callback); /* * Initialize the session cache. * * Since the client does not search an internal cache, we simply disable it. * It is only useful for expiring old sessions, but we do that in the * tlsmgr(8). * * This makes SSL_CTX_remove_session() not useful for flushing broken * sessions from the external cache, so we must delete them directly (not * via a callback). */ if (tls_mgr_policy(props->cache_type, &cachable, &scache_timeout) != TLS_MGR_STAT_OK) scache_timeout = 0; if (scache_timeout <= 0) cachable = 0; /* * Allocate an application context, and populate with mandatory protocol * and cipher data. */ app_ctx = tls_alloc_app_context(client_ctx, log_mask); /* * The external session cache is implemented by the tlsmgr(8) process. */ if (cachable) { app_ctx->cache_type = mystrdup(props->cache_type); /* * OpenSSL does not use callbacks to load sessions from a client * cache, so we must invoke that function directly. Apparently, * OpenSSL does not provide a way to pass session names from here to * call-back routines that do session lookup. * * OpenSSL can, however, automatically save newly created sessions for * us by callback (we create the session name in the call-back * function). * * XXX gcc 2.95 can't compile #ifdef .. #endif in the expansion of * SSL_SESS_CACHE_CLIENT | SSL_SESS_CACHE_NO_INTERNAL_STORE | * SSL_SESS_CACHE_NO_AUTO_CLEAR. */ #ifndef SSL_SESS_CACHE_NO_INTERNAL_STORE #define SSL_SESS_CACHE_NO_INTERNAL_STORE 0 #endif SSL_CTX_set_session_cache_mode(client_ctx, SSL_SESS_CACHE_CLIENT | SSL_SESS_CACHE_NO_INTERNAL_STORE | SSL_SESS_CACHE_NO_AUTO_CLEAR); SSL_CTX_sess_set_new_cb(client_ctx, new_client_session_cb); /* * OpenSSL ignores timed-out sessions. We need to set the internal * cache timeout at least as high as the external cache timeout. This * applies even if no internal cache is used. We set the session to * twice the cache lifetime. This way a session always lasts longer * than its lifetime in the cache. */ SSL_CTX_set_timeout(client_ctx, 2 * scache_timeout); } return (app_ctx); }
/* * Start up the SSL Context for the application, and start a listen on the * SSL port (usually 443, and defined by SSL_PORT) * Return 0 on success, -1 on failure. */ int websSSLOpen() { char *certFile, *keyFile, *CApath, *CAfile; SSL_METHOD *meth; /* * Install and initialize the SSL library */ apps_startup(); printf("ssl.c: SSL: Initializing SSL\n"); SSL_load_error_strings(); SSLeay_add_ssl_algorithms(); /* * Important! Enable both SSL versions 2 and 3 */ meth = SSLv23_server_method(); sslctx = SSL_CTX_new(meth); if (sslctx == NULL) { printf("SSL: Unable to create SSL context!\n"); return -1; } /* * Adjust some SSL Context variables */ SSL_CTX_set_quiet_shutdown(sslctx, 1); SSL_CTX_set_options(sslctx, 0); SSL_CTX_sess_set_cache_size(sslctx, 128); /* * Set the certificate verification locations */ CApath = DEFAULT_CA_PATH; CAfile = DEFAULT_CA_FILE; if ((!SSL_CTX_load_verify_locations(sslctx, CAfile, CApath)) || (!SSL_CTX_set_default_verify_paths(sslctx))) { printf("SSL: Unable to set cert verification locations!\n"); websSSLClose(); return -1; } /* * Setting up certificates for the SSL server. * Set the certificate and key files for the SSL context. */ certFile = DEFAULT_CERT_FILE; keyFile = NULL; if (websSSLSetCertStuff(sslctx, certFile, keyFile) != 0) { websSSLClose(); return -1; } /* * Set the RSA callback for the SSL context */ SSL_CTX_set_tmp_rsa_callback(sslctx, websSSLTempRSACallback); /* * Set the verification callback for the SSL context */ SSL_CTX_set_verify(sslctx, SSL_VERIFY_NONE, websSSLVerifyCallback); /* * Set the certificate authority list for the client */ SSL_CTX_set_client_CA_list(sslctx, SSL_load_client_CA_file(CAfile)); /* * Open the socket */ sslListenSock = socketOpenConnection(NULL, SSL_PORT, websSSLAccept, SOCKET_BLOCK); if (sslListenSock < 0) { trace(2, T("SSL: Unable to open SSL socket on port <%d>!\n"), SSL_PORT); return -1; } return 0; }