int SslOcspStapling::config(const XmlNode *pNode, SSL_CTX *pSSL, const char *pCAFile, char *pachCert) { setCertFile(pachCert); if (pCAFile) setCAFile(pCAFile); setRespMaxAge(ConfigCtx::getCurConfigCtx()->getLongValue(pNode, "ocspRespMaxAge", 60, 360000, 3600)); const char *pResponder = pNode->getChildValue("ocspResponder"); if (pResponder) setOcspResponder(pResponder); if (init(pSSL) == -1) { LS_ERROR(ConfigCtx::getCurConfigCtx(), "OCSP Stapling can't be enabled [%s].", getStaplingErrMsg()); return LS_FAIL; } return 0; }
/** * @desc Private constructor that uses IOSocket private constructor * @throw Const char *e * @param fd File descriptor of previously accepted socket * @param keyfile File to read key from * @param certfile File to read cert from */ IOSocketSSL::IOSocketSSL( const int &fd, const char *keyfile, const char *certfile) : IOSocket(fd) { TRACE_CALL(); setKeyFile(keyfile); setCertFile(certfile); init_internals(true); }
/** * @throw Const char *e * @param sock_t Socket Type * @param host Host to connect/bind to * @param port Port to connect/bind to * @param keyfile Keyfile to read private key from * @param certfile File to read certificate from */ IOSocketSSL::IOSocketSSL( const socket_type sock_t, const char *host, const int port, const char *keyfile, const char *certfile) : IOSocket(sock_t, host, port) { TRACE_CALL(); setKeyFile(keyfile); setCertFile(certfile); init_internals(); }
/* 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; }