/** * Create a SSL context. */ static int create(lua_State *L) { p_context ctx; LSEC_SSL_METHOD *method; method = str2method(luaL_checkstring(L, 1)); if (!method) { lua_pushnil(L); lua_pushstring(L, "invalid protocol"); return 2; } ctx = (p_context) lua_newuserdata(L, sizeof(t_context)); if (!ctx) { lua_pushnil(L); lua_pushstring(L, "error creating context"); return 2; } ctx->context = SSL_CTX_new(method); if (!ctx->context) { lua_pushnil(L); lua_pushstring(L, "error creating context"); return 2; } ctx->mode = LSEC_MODE_INVALID; luaL_getmetatable(L, "SSL:Context"); lua_setmetatable(L, -2); /* No session support */ SSL_CTX_set_session_cache_mode(ctx->context, SSL_SESS_CACHE_OFF); /* Link lua_State with the context */ SSL_CTX_set_app_data(ctx->context, (void*)L); return 1; }
static int BSslSetupVerify(SSL_CTX *pSCtx, SslServerBind const *pSSLB) { char const *pszKeyFile = pSSLB->pszKeyFile; if (pSSLB->pszCertFile != NULL) { if (SSL_CTX_use_certificate_chain_file(pSCtx, pSSLB->pszCertFile) <= 0) { ErrSetErrorCode(ERR_SSL_SETCERT, pSSLB->pszCertFile); return ERR_SSL_SETCERT; } if (pszKeyFile == NULL) pszKeyFile = pSSLB->pszCertFile; } if (pszKeyFile != NULL) { if (SSL_CTX_use_PrivateKey_file(pSCtx, pszKeyFile, SSL_FILETYPE_PEM) <= 0) { ErrSetErrorCode(ERR_SSL_SETKEY, pszKeyFile); return ERR_SSL_SETKEY; } if (!SSL_CTX_check_private_key(pSCtx)) { ErrSetErrorCode(ERR_SSL_CHECKKEY, pszKeyFile); return ERR_SSL_CHECKKEY; } } if (pSSLB->ulFlags & BSSLF_WANT_VERIFY) { int iVerMode = SSL_VERIFY_PEER; if (pSSLB->ulFlags & BSSLF_WANT_CERT) iVerMode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; SSL_CTX_set_verify(pSCtx, iVerMode, BSslCertVerifyCB); if (pSSLB->iMaxDepth > 0) SSL_CTX_set_verify_depth(pSCtx, pSSLB->iMaxDepth); SSL_CTX_set_app_data(pSCtx, pSSLB); if (pSSLB->pszCAFile != NULL || pSSLB->pszCAPath != NULL) { if (!SSL_CTX_load_verify_locations(pSCtx, pSSLB->pszCAFile, pSSLB->pszCAPath)) { ErrSetErrorCode(ERR_SSL_VERPATHS); return ERR_SSL_VERPATHS; } } else if (!SSL_CTX_set_default_verify_paths(pSCtx)) { ErrSetErrorCode(ERR_SSL_VERPATHS); return ERR_SSL_VERPATHS; } } return 0; }
int _openssl_env_init(openssl_env *env, char *engine, int server) { /* * Create an OpenSSL environment (method and context). * If ``server'' is 1, the environment is that of a SSL * server. */ const long options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION; env->meth = SSLv23_method(); env->ctx = SSL_CTX_new(env->meth); SSL_CTX_set_options(env->ctx, options); if (_options.sslciphers) { SSL_CTX_set_cipher_list(env->ctx, _options.sslciphers); } #ifdef HAVE_OPENSSL_ENGINE if (engine) { retry: if ((env->engine = ENGINE_by_id(engine)) == NULL) { fprintf(stderr,"invalid engine \"%s\"\n", engine); ENGINE_free(env->engine); engine = "openssl"; goto retry; } if (!ENGINE_set_default(env->engine, ENGINE_METHOD_ALL)) { fprintf(stderr,"can't use that engine\n"); ENGINE_free(env->engine); engine = "openssl"; goto retry; } } #endif #ifdef HAVE_OPENSSL_ENGINE SSL_CTX_set_app_data(env->ctx, env); #endif if (server) { SSL_CTX_set_options(env->ctx, SSL_OP_SINGLE_DH_USE); SSL_CTX_set_session_cache_mode(env->ctx, SSL_SESS_CACHE_OFF); SSL_CTX_set_quiet_shutdown(env->ctx, 1); } return 1; }
static SSL * open_ssl_connection (rfbClient *client, int sockfd, rfbBool anonTLS) { SSL_CTX *ssl_ctx = NULL; SSL *ssl = NULL; int n, finished = 0; BIO *sbio; ssl_ctx = SSL_CTX_new (SSLv23_client_method ()); SSL_CTX_set_default_verify_paths (ssl_ctx); SSL_CTX_set_verify (ssl_ctx, SSL_VERIFY_NONE, &ssl_verify); ssl = SSL_new (ssl_ctx); /* TODO: finetune this list, take into account anonTLS bool */ SSL_set_cipher_list(ssl, "ALL"); SSL_set_fd (ssl, sockfd); SSL_CTX_set_app_data (ssl_ctx, client); do { n = SSL_connect(ssl); if (n != 1) { if (wait_for_data(ssl, n, 1) != 1) { finished = 1; if (ssl->ctx) SSL_CTX_free (ssl->ctx); SSL_free(ssl); SSL_shutdown (ssl); return NULL; } } } while( n != 1 && finished != 1 ); return ssl; }
/** * Create a SSL context. */ static int create(lua_State *L) { p_context ctx; const char *str_method; LSEC_SSL_METHOD *method; str_method = luaL_checkstring(L, 1); method = str2method(str_method); if (!method) { lua_pushnil(L); lua_pushfstring(L, "invalid protocol (%s)", str_method); return 2; } ctx = (p_context) lua_newuserdata(L, sizeof(t_context)); if (!ctx) { lua_pushnil(L); lua_pushstring(L, "error creating context"); return 2; } memset(ctx, 0, sizeof(t_context)); ctx->context = SSL_CTX_new(method); if (!ctx->context) { lua_pushnil(L); lua_pushfstring(L, "error creating context (%s)", ERR_reason_error_string(ERR_get_error())); return 2; } ctx->mode = LSEC_MODE_INVALID; ctx->L = L; luaL_getmetatable(L, "SSL:Context"); lua_setmetatable(L, -2); /* No session support */ SSL_CTX_set_session_cache_mode(ctx->context, SSL_SESS_CACHE_OFF); /* Link LuaSec context with the OpenSSL context */ SSL_CTX_set_app_data(ctx->context, ctx); return 1; }
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; }
static void ssl_init_ctx_protocol(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp, modssl_ctx_t *mctx) { SSL_CTX *ctx = NULL; MODSSL_SSL_METHOD_CONST SSL_METHOD *method = NULL; char *cp; int protocol = mctx->protocol; /* * Create the new per-server SSL context */ if (protocol == SSL_PROTOCOL_NONE) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "No SSL protocols available [hint: SSLProtocol]"); ssl_die(); } cp = apr_pstrcat(p, (protocol & SSL_PROTOCOL_SSLV2 ? "SSLv2, " : ""), (protocol & SSL_PROTOCOL_SSLV3 ? "SSLv3, " : ""), (protocol & SSL_PROTOCOL_TLSV1 ? "TLSv1, " : ""), NULL); cp[strlen(cp)-2] = NUL; ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "Creating new SSL context (protocols: %s)", cp); if (protocol == SSL_PROTOCOL_SSLV2) { method = mctx->pkp ? SSLv2_client_method() : /* proxy */ SSLv2_server_method(); /* server */ ctx = SSL_CTX_new(method); /* only SSLv2 is left */ } else { method = mctx->pkp ? SSLv23_client_method() : /* proxy */ SSLv23_server_method(); /* server */ ctx = SSL_CTX_new(method); /* be more flexible */ } mctx->ssl_ctx = ctx; SSL_CTX_set_options(ctx, SSL_OP_ALL); if (!(protocol & SSL_PROTOCOL_SSLV2)) { SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2); } if (!(protocol & SSL_PROTOCOL_SSLV3)) { SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3); } if (!(protocol & SSL_PROTOCOL_TLSV1)) { SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1); } #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE { SSLSrvConfigRec *sc = mySrvConfig(s); if (sc->cipher_server_pref == TRUE) { SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); } } #endif SSL_CTX_set_app_data(ctx, s); /* * Configure additional context ingredients */ SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE); #ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* * Disallow a session from being resumed during a renegotiation, * so that an acceptable cipher suite can be negotiated. */ SSL_CTX_set_options(ctx, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); #endif }
static struct mailstream_ssl_data * ssl_data_new_full(int fd, time_t timeout, SSL_METHOD * method, void (* callback)(struct mailstream_ssl_context * ssl_context, void * cb_data), void * cb_data) { struct mailstream_ssl_data * ssl_data; SSL * ssl_conn; int r; SSL_CTX * tmp_ctx; struct mailstream_cancel * cancel; struct mailstream_ssl_context * ssl_context = NULL; mailstream_ssl_init(); tmp_ctx = SSL_CTX_new(method); if (tmp_ctx == NULL) goto err; if (callback != NULL) { ssl_context = mailstream_ssl_context_new(tmp_ctx, fd); callback(ssl_context, cb_data); } SSL_CTX_set_app_data(tmp_ctx, ssl_context); SSL_CTX_set_client_cert_cb(tmp_ctx, mailstream_openssl_client_cert_cb); ssl_conn = (SSL *) SSL_new(tmp_ctx); if (ssl_conn == NULL) goto free_ctx; if (SSL_set_fd(ssl_conn, fd) == 0) goto free_ssl_conn; again: r = SSL_connect(ssl_conn); switch(SSL_get_error(ssl_conn, r)) { case SSL_ERROR_WANT_READ: r = wait_SSL_connect(fd, 1, timeout); if (r < 0) goto free_ssl_conn; else goto again; break; case SSL_ERROR_WANT_WRITE: r = wait_SSL_connect(fd, 0, timeout); if (r < 0) goto free_ssl_conn; else goto again; break; } if (r <= 0) goto free_ssl_conn; cancel = mailstream_cancel_new(); if (cancel == NULL) goto free_ssl_conn; r = mailstream_prepare_fd(fd); if (r < 0) goto free_cancel; ssl_data = malloc(sizeof(* ssl_data)); if (ssl_data == NULL) goto free_cancel; ssl_data->fd = fd; ssl_data->ssl_conn = ssl_conn; ssl_data->ssl_ctx = tmp_ctx; ssl_data->cancel = cancel; mailstream_ssl_context_free(ssl_context); return ssl_data; free_cancel: mailstream_cancel_free(cancel); free_ssl_conn: SSL_free(ssl_conn); free_ctx: SSL_CTX_free(tmp_ctx); mailstream_ssl_context_free(ssl_context); err: return NULL; }
static struct mailstream_ssl_data * ssl_data_new_full(int fd, time_t timeout, const SSL_METHOD * method, void (* callback)(struct mailstream_ssl_context * ssl_context, void * cb_data), void * cb_data) { struct mailstream_ssl_data * ssl_data; SSL * ssl_conn; int r; SSL_CTX * tmp_ctx; struct mailstream_cancel * cancel; struct mailstream_ssl_context * ssl_context = NULL; #if SSL_MODE_RELEASE_BUFFERS long mode = 0; #endif mailstream_ssl_init(); tmp_ctx = SSL_CTX_new(method); if (tmp_ctx == NULL) goto err; if (callback != NULL) { ssl_context = mailstream_ssl_context_new(tmp_ctx, fd); callback(ssl_context, cb_data); } SSL_CTX_set_app_data(tmp_ctx, ssl_context); SSL_CTX_set_client_cert_cb(tmp_ctx, mailstream_openssl_client_cert_cb); ssl_conn = (SSL *) SSL_new(tmp_ctx); #if SSL_MODE_RELEASE_BUFFERS mode = SSL_get_mode(ssl_conn); SSL_set_mode(ssl_conn, mode | SSL_MODE_RELEASE_BUFFERS); #endif if (ssl_conn == NULL) goto free_ctx; #if (OPENSSL_VERSION_NUMBER >= 0x10000000L) if (ssl_context != NULL && ssl_context->server_name != NULL) { SSL_set_tlsext_host_name(ssl_conn, ssl_context->server_name); free(ssl_context->server_name); ssl_context->server_name = NULL; } #endif /* (OPENSSL_VERSION_NUMBER >= 0x10000000L) */ if (SSL_set_fd(ssl_conn, fd) == 0) goto free_ssl_conn; again: r = SSL_connect(ssl_conn); switch(SSL_get_error(ssl_conn, r)) { case SSL_ERROR_WANT_READ: r = wait_SSL_connect(fd, 1, timeout); if (r < 0) goto free_ssl_conn; else goto again; break; case SSL_ERROR_WANT_WRITE: r = wait_SSL_connect(fd, 0, timeout); if (r < 0) goto free_ssl_conn; else goto again; break; } if (r <= 0) goto free_ssl_conn; cancel = mailstream_cancel_new(); if (cancel == NULL) goto free_ssl_conn; r = mailstream_prepare_fd(fd); if (r < 0) goto free_cancel; ssl_data = malloc(sizeof(* ssl_data)); if (ssl_data == NULL) goto free_cancel; ssl_data->fd = fd; ssl_data->ssl_conn = ssl_conn; ssl_data->ssl_ctx = tmp_ctx; ssl_data->cancel = cancel; mailstream_ssl_context_free(ssl_context); return ssl_data; free_cancel: mailstream_cancel_free(cancel); free_ssl_conn: SSL_free(ssl_conn); free_ctx: SSL_CTX_free(tmp_ctx); mailstream_ssl_context_free(ssl_context); err: return NULL; }
static int openssl_ssl_ctx_new(lua_State*L) { const char* meth = luaL_optstring(L, 1, "TLSv1"); #if OPENSSL_VERSION_NUMBER >= 0x01000000L const #endif SSL_METHOD* method = NULL; const char* ciphers; SSL_CTX* ctx; if (strcmp(meth, "SSLv3") == 0) method = SSLv3_method(); /* SSLv3 */ else if (strcmp(meth, "SSLv3_server") == 0) method = SSLv3_server_method(); /* SSLv3 */ else if (strcmp(meth, "SSLv3_client") == 0) method = SSLv3_client_method(); /* SSLv3 */ else if (strcmp(meth, "SSLv23") == 0) method = SSLv23_method(); /* SSLv3 but can rollback to v2 */ else if (strcmp(meth, "SSLv23_server") == 0) method = SSLv23_server_method(); /* SSLv3 but can rollback to v2 */ else if (strcmp(meth, "SSLv23_client") == 0) method = SSLv23_client_method(); /* SSLv3 but can rollback to v2 */ else if (strcmp(meth, "TLSv1_1") == 0) method = TLSv1_1_method(); /* TLSv1.0 */ else if (strcmp(meth, "TLSv1_1_server") == 0) method = TLSv1_1_server_method(); /* TLSv1.0 */ else if (strcmp(meth, "TLSv1_1_client") == 0) method = TLSv1_1_client_method(); /* TLSv1.0 */ else if (strcmp(meth, "TLSv1_2") == 0) method = TLSv1_2_method(); /* TLSv1.0 */ else if (strcmp(meth, "TLSv1_2_server") == 0) method = TLSv1_2_server_method(); /* TLSv1.0 */ else if (strcmp(meth, "TLSv1_2_client") == 0) method = TLSv1_2_client_method(); /* TLSv1.0 */ else if (strcmp(meth, "TLSv1") == 0) method = TLSv1_method(); /* TLSv1.0 */ else if (strcmp(meth, "TLSv1_server") == 0) method = TLSv1_server_method(); /* TLSv1.0 */ else if (strcmp(meth, "TLSv1_client") == 0) method = TLSv1_client_method(); /* TLSv1.0 */ else if (strcmp(meth, "DTLSv1") == 0) method = DTLSv1_method(); /* DTLSv1.0 */ else if (strcmp(meth, "DTLSv1_server") == 0) method = DTLSv1_server_method(); /* DTLSv1.0 */ else if (strcmp(meth, "DTLSv1_client") == 0) method = DTLSv1_client_method(); /* DTLSv1.0 */ #ifndef OPENSSL_NO_SSL2 #if OPENSSL_VERSION_NUMBER < 0x10100000L else if (strcmp(meth, "SSLv2") == 0) method = SSLv2_method(); /* SSLv2 */ else if (strcmp(meth, "SSLv2_server") == 0) method = SSLv2_server_method(); /* SSLv2 */ else if (strcmp(meth, "SSLv2_client") == 0) method = SSLv2_client_method(); #endif #ifdef LOAD_SSL_CUSTOM LOAD_SSL_CUSTOM #endif #endif else luaL_error(L, "#1:%s not supported\n" "Maybe SSLv3 SSLv23 TLSv1 TLSv1_1 TLSv1_2 DTLSv1 [SSLv2], option followed by _client or _server\n", "default is SSLv3", meth); ciphers = luaL_optstring(L, 2, SSL_DEFAULT_CIPHER_LIST); ctx = SSL_CTX_new(method); if (!ctx) luaL_error(L, "#1:%s not supported\n" "Maybe SSLv3 SSLv23 TLSv1 TLSv1_1 TLSv1_2 DTLSv1 [SSLv2], option followed by _client or _server\n", "default is SSLv3", meth); openssl_newvalue(L, ctx); SSL_CTX_set_cipher_list(ctx, ciphers); PUSH_OBJECT(ctx, "openssl.ssl_ctx"); SSL_CTX_set_app_data(ctx, L); return 1; }
static CURLcode sslctxfun(CURL* curl, void* sslctx, void* parm) { SSL_CTX_set_app_data(reinterpret_cast<SSL_CTX*>(sslctx), parm); SSL_CTX_set_verify(reinterpret_cast<SSL_CTX*>(sslctx), SSL_VERIFY_PEER, certVerifyCallback); return CURLE_OK; }
/* Create and initialize an SSL configuration for a route. This configuration is used by all requests for a given route. An application can have different SSL configurations for different routes. There is also a default SSL configuration that is used when a route does not define a configuration and one for clients. */ static int configOss(MprSsl *ssl, int flags, char **errorMsg) { OpenConfig *cfg; X509_STORE *store; SSL_CTX *ctx; cchar *key; uchar resume[16]; int verifyMode; assert(ssl); if (ssl->config && !ssl->changed) { return 0; } if ((ssl->config = mprAllocObj(OpenConfig, manageOpenConfig)) == 0) { return MPR_ERR_MEMORY; } cfg = ssl->config; if ((ctx = SSL_CTX_new(SSLv23_method())) == 0) { mprLog("error openssl", 0, "Unable to create SSL context"); return MPR_ERR_CANT_INITIALIZE; } SSL_CTX_set_app_data(ctx, (void*) ssl); if (ssl->verifyPeer && !(ssl->caFile || ssl->caPath)) { *errorMsg = sfmt("Cannot verify peer due to undefined CA certificates"); SSL_CTX_free(ctx); return MPR_ERR_CANT_INITIALIZE; } /* Configure the certificates */ if (ssl->certFile) { if (setCertFile(ctx, ssl->certFile) < 0) { SSL_CTX_free(ctx); return MPR_ERR_CANT_INITIALIZE; } key = (ssl->keyFile == 0) ? ssl->certFile : ssl->keyFile; if (key) { if (setKeyFile(ctx, key) < 0) { SSL_CTX_free(ctx); return MPR_ERR_CANT_INITIALIZE; } if (!SSL_CTX_check_private_key(ctx)) { mprLog("error openssl", 0, "Check of private key file failed: %s", key); SSL_CTX_free(ctx); return MPR_ERR_CANT_INITIALIZE; } } } if (ssl->ciphers) { ssl->ciphers = mapCipherNames(ssl->ciphers); } if (!ssl->ciphers && (flags & MPR_SOCKET_SERVER)) { ssl->ciphers = sclone(OPENSSL_DEFAULT_CIPHERS); } if (ssl->ciphers) { mprLog("info openssl", 5, "Using SSL ciphers: %s", ssl->ciphers); if (SSL_CTX_set_cipher_list(ctx, ssl->ciphers) != 1) { *errorMsg = sfmt("Unable to set cipher list \"%s\"", ssl->ciphers); SSL_CTX_free(ctx); return MPR_ERR_CANT_INITIALIZE; } } verifyMode = ssl->verifyPeer ? SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT : SSL_VERIFY_NONE; if (verifyMode != SSL_VERIFY_NONE) { if (!(ssl->caFile || ssl->caPath)) { *errorMsg = sclone("No defined certificate authority file"); SSL_CTX_free(ctx); return MPR_ERR_CANT_INITIALIZE; } if ((!SSL_CTX_load_verify_locations(ctx, (char*) ssl->caFile, (char*) ssl->caPath)) || (!SSL_CTX_set_default_verify_paths(ctx))) { *errorMsg = sfmt("Unable to set certificate locations: %s: %s", ssl->caFile, ssl->caPath); SSL_CTX_free(ctx); return MPR_ERR_CANT_INITIALIZE; } if (ssl->caFile) { STACK_OF(X509_NAME) *certNames; certNames = SSL_load_client_CA_file(ssl->caFile); if (certNames) { /* 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(ctx, certNames); } } store = SSL_CTX_get_cert_store(ctx); if (ssl->revoke && !X509_STORE_load_locations(store, ssl->revoke, 0)) { mprLog("error openssl", 0, "Cannot load certificate revoke list: %s", ssl->revoke); SSL_CTX_free(ctx); return MPR_ERR_CANT_INITIALIZE; } if (flags & MPR_SOCKET_SERVER) { SSL_CTX_set_verify_depth(ctx, ssl->verifyDepth); } } /* Define callbacks */ SSL_CTX_set_verify(ctx, verifyMode, verifyPeerCertificate); if (flags & MPR_SOCKET_SERVER) { SSL_CTX_set_tlsext_servername_callback(ctx, sniHostname); } /* Configure DH parameters */ SSL_CTX_set_tmp_dh_callback(ctx, dhcallback); cfg->dhKey = getDhKey(); /* Define default OpenSSL options Ensure we generate a new private key for each connection Disable SSLv2 and SSLv3 by default -- they are insecure. */ cfg->setFlags = SSL_OP_ALL | SSL_OP_SINGLE_DH_USE | SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; #ifdef SSL_OP_NO_TLSv1 if (!(ssl->protocols & MPR_PROTO_TLSV1)) { cfg->setFlags |= SSL_OP_NO_TLSv1; } #endif #ifdef SSL_OP_NO_TLSv1_1 if (!(ssl->protocols & MPR_PROTO_TLSV1_1)) { cfg->setFlags |= SSL_OP_NO_TLSv1_1; } #endif #ifdef SSL_OP_NO_TLSv1_2 if (!(ssl->protocols & MPR_PROTO_TLSV1_2)) { cfg->setFlags |= SSL_OP_NO_TLSv1_2; } #endif #ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING cfg->setFlags |= SSL_OP_MSIE_SSLV2_RSA_PADDING; #endif #if defined(SSL_OP_NO_TICKET) /* Ticket based session reuse is enabled by default */ #if defined(ME_MPR_SSL_TICKET) if (ME_MPR_SSL_TICKET) { cfg->clearFlags |= SSL_OP_NO_TICKET; } else { cfg->setFlags |= SSL_OP_NO_TICKET; } #else cfg->clearFlags |= SSL_OP_NO_TICKET; #endif #endif #if defined(SSL_OP_NO_COMPRESSION) /* CRIME attack targets compression */ cfg->clearFlags |= SSL_OP_NO_COMPRESSION; #endif #if defined(SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION) /* Force a new session on renegotiation. Default to true. This is required when using SNI and changing context during the SSL hello */ #if defined(ME_MPR_SSL_RENEGOTIATE) if (ME_MPR_SSL_RENEGOTIATE) { cfg->clearFlags |= SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION; } else { cfg->setFlags |= SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION; } #else cfg->setFlags |= SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION; #endif #endif #if defined(SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) /* Disables a countermeasure against a SSL 3.0/TLS 1.0 protocol vulnerability affecting CBC ciphers. Defaults to true. */ #if defined(ME_MPR_SSL_EMPTY_FRAGMENTS) if (ME_MPR_SSL_EMPTY_FRAGMENTS) { /* SSL_OP_ALL disables empty fragments. Only needed for ancient browsers like IE-6 on SSL-3.0/TLS-1.0 */ cfg->clearFlags |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; } else { cfg->setFlags |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; } #else cfg->setFlags |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; #endif #endif /* Define a session reuse context */ RAND_bytes(resume, sizeof(resume)); SSL_CTX_set_session_id_context(ctx, resume, sizeof(resume)); /* Elliptic Curve initialization */ #if SSL_OP_SINGLE_ECDH_USE #ifdef SSL_CTX_set_ecdh_auto /* This is supported in OpenSSL 1.0.2 */ SSL_CTX_set_ecdh_auto(ctx, 1); #else { EC_KEY *ecdh; cchar *name; int nid; name = ME_MPR_SSL_CURVE; if ((nid = OBJ_sn2nid(name)) == 0) { *errorMsg = sfmt("Unknown curve name \"%s\"", name); SSL_CTX_free(ctx); return MPR_ERR_CANT_INITIALIZE; } if ((ecdh = EC_KEY_new_by_curve_name(nid)) == 0) { *errorMsg = sfmt("Unable to create curve \"%s\"", name); SSL_CTX_free(ctx); return MPR_ERR_CANT_INITIALIZE; } SSL_CTX_set_tmp_ecdh(ctx, ecdh); EC_KEY_free(ecdh); } #endif #endif SSL_CTX_set_mode(ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); #ifdef SSL_MODE_RELEASE_BUFFERS SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS); #endif #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE SSL_CTX_set_mode(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); #endif #if defined(ME_MPR_SSL_CACHE) /* Set the number of sessions supported. Default in OpenSSL is 20K. */ SSL_CTX_sess_set_cache_size(ctx, ME_MPR_SSL_CACHE); #else SSL_CTX_sess_set_cache_size(ctx, 1024); #endif SSL_CTX_set_options(ctx, cfg->setFlags); SSL_CTX_clear_options(ctx, cfg->clearFlags); cfg->ctx = ctx; ssl->changed = 0; ssl->config = cfg; return 0; }
int evhtp_ssl_init(evhtp * htp, evhtp_ssl_cfg * cfg) { long cache_mode; evhtp_ssl_scache_init init_cb = NULL; evhtp_ssl_scache_add add_cb = NULL; evhtp_ssl_scache_get get_cb = NULL; evhtp_ssl_scache_del del_cb = NULL; if (cfg == NULL || htp == NULL || cfg->pemfile == NULL) { return -1; } SSL_library_init(); SSL_load_error_strings(); RAND_poll(); STACK_OF(SSL_COMP) * comp_methods = SSL_COMP_get_compression_methods(); sk_SSL_COMP_zero(comp_methods); htp->ssl_cfg = cfg; htp->ssl_ctx = SSL_CTX_new(SSLv23_server_method()); #if OPENSSL_VERSION_NUMBER >= 0x10000000L SSL_CTX_set_options(htp->ssl_ctx, SSL_MODE_RELEASE_BUFFERS); SSL_CTX_set_timeout(htp->ssl_ctx, 60 * 60 * 48); #endif SSL_CTX_set_options(htp->ssl_ctx, cfg->ssl_opts); if (cfg->ciphers != NULL) { SSL_CTX_set_cipher_list(htp->ssl_ctx, cfg->ciphers); } SSL_CTX_load_verify_locations(htp->ssl_ctx, cfg->cafile, cfg->capath); X509_STORE_set_flags(SSL_CTX_get_cert_store(htp->ssl_ctx), cfg->store_flags); SSL_CTX_set_verify(htp->ssl_ctx, cfg->verify_peer, cfg->x509_verify_cb); if (cfg->x509_chk_issued_cb != NULL) { htp->ssl_ctx->cert_store->check_issued = cfg->x509_chk_issued_cb; } if (cfg->verify_depth) { SSL_CTX_set_verify_depth(htp->ssl_ctx, cfg->verify_depth); } switch (cfg->scache_type) { case evhtp_ssl_scache_type_disabled: cache_mode = SSL_SESS_CACHE_OFF; break; case evhtp_ssl_scache_type_user: cache_mode = SSL_SESS_CACHE_SERVER | SSL_SESS_CACHE_NO_INTERNAL | SSL_SESS_CACHE_NO_INTERNAL_LOOKUP; init_cb = cfg->scache_init; add_cb = cfg->scache_add; get_cb = cfg->scache_get; del_cb = cfg->scache_del; break; case evhtp_ssl_scache_type_builtin: cache_mode = SSL_SESS_CACHE_SERVER | SSL_SESS_CACHE_NO_INTERNAL | SSL_SESS_CACHE_NO_INTERNAL_LOOKUP; #if 0 init_cb = _evhtp_ssl_builtin_init; add_cb = _evhtp_ssl_builtin_add; get_cb = _evhtp_ssl_builtin_get; del_cb = _evhtp_ssl_builtin_del; #endif break; case evhtp_ssl_scache_type_internal: default: cache_mode = SSL_SESS_CACHE_SERVER; break; } /* switch */ SSL_CTX_use_certificate_file(htp->ssl_ctx, cfg->pemfile, SSL_FILETYPE_PEM); SSL_CTX_use_PrivateKey_file(htp->ssl_ctx, cfg->privfile ? cfg->privfile: cfg->pemfile, SSL_FILETYPE_PEM); SSL_CTX_set_session_id_context(htp->ssl_ctx, (const unsigned char*)&session_id_context, sizeof(session_id_context)); SSL_CTX_set_app_data(htp->ssl_ctx, htp); SSL_CTX_set_session_cache_mode(htp->ssl_ctx, cache_mode); if (cache_mode != SSL_SESS_CACHE_OFF) { SSL_CTX_sess_set_cache_size(htp->ssl_ctx, cfg->scache_size ? cfg->scache_size : 1024); if (cfg->scache_type == evhtp_ssl_scache_type_builtin || cfg->scache_type == evhtp_ssl_scache_type_user) { SSL_CTX_sess_set_new_cb(htp->ssl_ctx, _evhtp_ssl_add_scache_ent); SSL_CTX_sess_set_get_cb(htp->ssl_ctx, _evhtp_ssl_get_scache_ent); SSL_CTX_sess_set_remove_cb(htp->ssl_ctx, _evhtp_ssl_delete_scache_ent); if (cfg->scache_init) { cfg->args = (cfg->scache_init)(htp); } } } return 0; } /* evhtp_use_ssl */
int BSslBindServer(BSOCK_HANDLE hBSock, SslServerBind const *pSSLB, int (*pfEnvCB)(void *, int, void const *), void *pPrivate) { int iError; SYS_SOCKET SockFD; SSL_METHOD const *pMethod; SSL_CTX *pSCtx; SSL *pSSL; X509 *pCert; SslBindCtx *pCtx; pMethod = SSLv23_server_method(); if ((pSCtx = SSL_CTX_new((SSL_METHOD *) pMethod)) == NULL) { ErrSetErrorCode(ERR_SSLCTX_CREATE); return ERR_SSLCTX_CREATE; } SSL_CTX_set_session_cache_mode(pSCtx, SSL_SESS_CACHE_OFF); if (BSslSetupVerify(pSCtx, pSSLB) < 0) { SSL_CTX_free(pSCtx); return ErrGetErrorCode(); } if ((pSSL = SSL_new(pSCtx)) == NULL) { SSL_CTX_free(pSCtx); ErrSetErrorCode(ERR_SSL_CREATE); return ERR_SSL_CREATE; } SockFD = BSckGetAttachedSocket(hBSock); /* * We want blocking sockets during the initial SSL negotiation. */ SysBlockSocket(SockFD, 1); SSL_set_fd(pSSL, SockFD); if (SSL_accept(pSSL) == -1) { SysBlockSocket(SockFD, -1); SSL_free(pSSL); SSL_CTX_free(pSCtx); ErrSetErrorCode(ERR_SSL_ACCEPT); return ERR_SSL_ACCEPT; } SSL_CTX_set_app_data(pSCtx, NULL); /* * Client may not supply a certificate. */ iError = 0; if (pfEnvCB != NULL && (pCert = SSL_get_peer_certificate(pSSL)) != NULL) { iError = BSslEnvExport(pSCtx, pSSL, pCert, pfEnvCB, pPrivate); X509_free(pCert); } if (iError < 0 || BSslAllocCtx(&pCtx, SockFD, pSCtx, pSSL) < 0) { ErrorPush(); SysBlockSocket(SockFD, -1); SSL_free(pSSL); SSL_CTX_free(pSCtx); return ErrorPop(); } /* * Need to use non-blocking socket to implement read/write timeouts. */ SysBlockSocket(SockFD, 0); BSckSetIOops(hBSock, &pCtx->IOOps); return 0; }
/* Create and initialize an SSL configuration for a route. This configuration is used by all requests for a given route. An application can have different SSL configurations for different routes. There is also a default SSL configuration that is used when a route does not define a configuration and one for clients. */ static OpenConfig *createOpenSslConfig(MprSocket *sp) { MprSsl *ssl; OpenConfig *cfg; X509_STORE *store; SSL_CTX *context; cchar *key; uchar resume[16]; int verifyMode; ssl = sp->ssl; assert(ssl); if ((ssl->config = mprAllocObj(OpenConfig, manageOpenConfig)) == 0) { return 0; } cfg = ssl->config; if ((context = SSL_CTX_new(SSLv23_method())) == 0) { mprLog("error openssl", 0, "Unable to create SSL context"); return 0; } SSL_CTX_set_app_data(context, (void*) ssl); if (ssl->verifyPeer && !(ssl->caFile || ssl->caPath)) { sp->errorMsg = sfmt("Cannot verify peer due to undefined CA certificates"); SSL_CTX_free(context); return 0; } /* Configure the certificates */ if (ssl->certFile) { if (SSL_CTX_use_certificate_chain_file(context, ssl->certFile) <= 0) { if (SSL_CTX_use_certificate_file(context, ssl->certFile, SSL_FILETYPE_ASN1) <= 0) { mprLog("error openssl", 0, "Cannot open certificate file: %s", ssl->certFile); SSL_CTX_free(context); return 0; } } key = (ssl->keyFile == 0) ? ssl->certFile : ssl->keyFile; if (key) { if (SSL_CTX_use_PrivateKey_file(context, key, SSL_FILETYPE_PEM) <= 0) { /* attempt ASN1 for self-signed format */ if (SSL_CTX_use_PrivateKey_file(context, key, SSL_FILETYPE_ASN1) <= 0) { mprLog("error openssl", 0, "Cannot open private key file: %s", key); SSL_CTX_free(context); return 0; } } if (!SSL_CTX_check_private_key(context)) { mprLog("error openssl", 0, "Check of private key file failed: %s", key); SSL_CTX_free(context); return 0; } } } if (ssl->ciphers) { ssl->ciphers = mapCipherNames(ssl->ciphers); } if (!ssl->ciphers && (sp->flags & MPR_SOCKET_SERVER)) { ssl->ciphers = sclone(OPENSSL_DEFAULT_CIPHERS); } if (ssl->ciphers) { mprLog("info openssl", 5, "Using SSL ciphers: %s", ssl->ciphers); if (SSL_CTX_set_cipher_list(context, ssl->ciphers) != 1) { sp->errorMsg = sfmt("Unable to set cipher list \"%s\". %s", ssl->ciphers, getOssError(sp)); SSL_CTX_free(context); return 0; } } verifyMode = ssl->verifyPeer ? SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT : SSL_VERIFY_NONE; if (verifyMode != SSL_VERIFY_NONE) { if (!(ssl->caFile || ssl->caPath)) { sp->errorMsg = sclone("No defined certificate authority file"); SSL_CTX_free(context); return 0; } if ((!SSL_CTX_load_verify_locations(context, (char*) ssl->caFile, (char*) ssl->caPath)) || (!SSL_CTX_set_default_verify_paths(context))) { sp->errorMsg = sfmt("Unable to set certificate locations: %s: %s", ssl->caFile, ssl->caPath); SSL_CTX_free(context); return 0; } if (ssl->caFile) { STACK_OF(X509_NAME) *certNames; certNames = SSL_load_client_CA_file(ssl->caFile); if (certNames) { /* 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); } } store = SSL_CTX_get_cert_store(context); if (ssl->revokeList && !X509_STORE_load_locations(store, ssl->revokeList, 0)) { mprLog("error openssl", 0, "Cannot load certificate revoke list: %s", ssl->revokeList); SSL_CTX_free(context); return 0; } if (sp->flags & MPR_SOCKET_SERVER) { SSL_CTX_set_verify_depth(context, ssl->verifyDepth); } } /* Define callbacks */ SSL_CTX_set_verify(context, verifyMode, verifyPeerCertificate); /* Configure DH parameters */ SSL_CTX_set_tmp_dh_callback(context, dhcallback); cfg->dhKey = getDhKey(); /* Define default OpenSSL options */ SSL_CTX_set_options(context, SSL_OP_ALL); /* Ensure we generate a new private key for each connection */ SSL_CTX_set_options(context, SSL_OP_SINGLE_DH_USE); /* Define a session reuse context */ RAND_bytes(resume, sizeof(resume)); SSL_CTX_set_session_id_context(context, resume, sizeof(resume)); /* Elliptic Curve initialization */ #if SSL_OP_SINGLE_ECDH_USE #ifdef SSL_CTX_set_ecdh_auto SSL_CTX_set_ecdh_auto(context, 1); #else { EC_KEY *ecdh; cchar *name; int nid; name = ME_MPR_SSL_CURVE; if ((nid = OBJ_sn2nid(name)) == 0) { sp->errorMsg = sfmt("Unknown curve name \"%s\"", name); SSL_CTX_free(context); return 0; } if ((ecdh = EC_KEY_new_by_curve_name(nid)) == 0) { sp->errorMsg = sfmt("Unable to create curve \"%s\"", name); SSL_CTX_free(context); return 0; } SSL_CTX_set_options(context, SSL_OP_SINGLE_ECDH_USE); SSL_CTX_set_tmp_ecdh(context, ecdh); EC_KEY_free(ecdh); } #endif #endif SSL_CTX_set_mode(context, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); #ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING SSL_CTX_set_options(context, SSL_OP_MSIE_SSLV2_RSA_PADDING); #endif #ifdef SSL_MODE_RELEASE_BUFFERS SSL_CTX_set_mode(context, SSL_MODE_RELEASE_BUFFERS); #endif #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE SSL_CTX_set_mode(context, SSL_OP_CIPHER_SERVER_PREFERENCE); #endif /* Select the required protocols Disable SSLv2 and SSLv3 by default -- they are insecure. */ SSL_CTX_set_options(context, SSL_OP_NO_SSLv2); SSL_CTX_set_options(context, SSL_OP_NO_SSLv3); #ifdef SSL_OP_NO_TLSv1 if (!(ssl->protocols & MPR_PROTO_TLSV1)) { SSL_CTX_set_options(context, SSL_OP_NO_TLSv1); } #endif #ifdef SSL_OP_NO_TLSv1_1 if (!(ssl->protocols & MPR_PROTO_TLSV1_1)) { SSL_CTX_set_options(context, SSL_OP_NO_TLSv1_1); } #endif #ifdef SSL_OP_NO_TLSv1_2 if (!(ssl->protocols & MPR_PROTO_TLSV1_2)) { SSL_CTX_set_options(context, SSL_OP_NO_TLSv1_2); } #endif /* Options set via main.me mpr.ssl.* */ #if defined(SSL_OP_NO_TICKET) /* Ticket based session reuse is enabled by default */ #if defined(ME_MPR_SSL_TICKET) if (ME_MPR_SSL_TICKET) { SSL_CTX_clear_options(context, SSL_OP_NO_TICKET); } else { SSL_CTX_set_options(context, SSL_OP_NO_TICKET); } #else SSL_CTX_clear_options(context, SSL_OP_NO_TICKET); #endif #endif #if defined(SSL_OP_NO_COMPRESSION) /* Use of compression is not secure. Disabled by default. */ #if defined(ME_MPR_SSL_COMPRESSION) if (ME_MPR_SSL_COMPRESSION) { SSL_CTX_clear_options(context, SSL_OP_NO_COMPRESSION); } else { SSL_CTX_set_options(context, SSL_OP_NO_COMPRESSION); } #else /* CRIME attack targets compression */ SSL_CTX_clear_options(context, SSL_OP_NO_COMPRESSION); #endif #endif #if defined(SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION) /* Force a new session on renegotiation. Default to true. */ #if defined(ME_MPR_SSL_RENEGOTIATE) if (ME_MPR_SSL_RENEGOTIATE) { SSL_CTX_clear_options(context, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); } else { SSL_CTX_set_options(context, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); } #else SSL_CTX_set_options(context, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); #endif #endif #if defined(SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) /* Disables a countermeasure against a SSL 3.0/TLS 1.0 protocol vulnerability affecting CBC ciphers. Defaults to true. */ #if defined(ME_MPR_SSL_EMPTY_FRAGMENTS) if (ME_MPR_SSL_EMPTY_FRAGMENTS) { /* SSL_OP_ALL disables empty fragments. Only needed for ancient browsers like IE-6 on SSL-3.0/TLS-1.0 */ SSL_CTX_clear_options(context, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); } else { SSL_CTX_set_options(context, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); } #else SSL_CTX_set_options(context, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); #endif #endif #if defined(ME_MPR_SSL_CACHE) /* Set the number of sessions supported. Default in OpenSSL is 20K. */ SSL_CTX_sess_set_cache_size(context, ME_MPR_SSL_CACHE); #else SSL_CTX_sess_set_cache_size(context, 1024); #endif cfg->context = context; return cfg; }