SSL_CTX *SSLSocket::sslCreateCtx(bool client, bool verify, const char *CAfile, const char *CRTfile, const char *KEYfile, void *passwd) { SSL_CTX *sctx = SSL_CTX_new(client ? SSLv23_client_method() : SSLv23_server_method()); if (sctx == NULL) { throw SSLSocketException ( "Could not create SSL context." ); } else { // Generate a new DH key during each handshake SSL_CTX_set_options(sctx, SSL_OP_SINGLE_DH_USE); // The verification contextof certificates is activated if (verify) SSL_CTX_set_verify(sctx, SSL_VERIFY_PEER, NULL); // Sets the password of the private key SSL_CTX_set_default_passwd_cb_userdata(sctx, passwd); if (!client) { int s_server_session_id_context = 1; SSL_CTX_set_session_id_context(sctx, (const unsigned char*) &s_server_session_id_context, sizeof(s_server_session_id_context)); } if (SSL_CTX_load_verify_locations(sctx, CAfile, NULL) == 0) { throw CertificateException ( "CA file could not be loaded." ); } if (SSL_CTX_use_certificate_file(sctx, CRTfile, SSL_FILETYPE_PEM) == 0) { ERR_print_errors_fp(stderr); throw CertificateException ( "CRT file could not be loaded." ); } if (SSL_CTX_use_PrivateKey_file(sctx, KEYfile, SSL_FILETYPE_PEM) == 0) { throw CertificateException ( "KEY file could not be loaded." ); } } return sctx; }
/* static */ void BSecureSocket::Private::_CreateContext() { sContext = SSL_CTX_new(SSLv23_method()); // Disable legacy protocols. They have known vulnerabilities. SSL_CTX_set_options(sContext, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); // Don't bother us with ERROR_WANT_READ. SSL_CTX_set_mode(sContext, SSL_MODE_AUTO_RETRY); // Setup certificate verification BPath certificateStore; find_directory(B_SYSTEM_DATA_DIRECTORY, &certificateStore); certificateStore.Append("ssl/CARootCertificates.pem"); // TODO we may want to add a non-packaged certificate directory? // (would make it possible to store user-added certificate exceptions // there) SSL_CTX_load_verify_locations(sContext, certificateStore.Path(), NULL); SSL_CTX_set_verify(sContext, SSL_VERIFY_PEER, VerifyCallback); // OpenSSL 1.0.2 and later: use the alternate "trusted first" algorithm to validate certificate // chains. This makes the validation stop as soon as a recognized certificate is found in the // chain, instead of validating the whole chain, then seeing if the root certificate is known. #ifdef X509_V_FLAG_TRUSTED_FIRST X509_VERIFY_PARAM* verifyParam = X509_VERIFY_PARAM_new(); X509_VERIFY_PARAM_set_flags(verifyParam, X509_V_FLAG_TRUSTED_FIRST); SSL_CTX_set1_param(sContext, verifyParam); // TODO we need to free this after freeing the SSL context (which we currently never do) // X509_VERIFY_PARAM_free(verifyParam); #endif // Get an unique index number for storing application data in SSL // structs. We will store a pointer to the BSecureSocket class there. sDataIndex = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL); }
SSL_CTX * setup_server_ctx(void) { SSL_CTX * ctx; ctx = SSL_CTX_new(SSLv23_method()); if (SSL_CTX_load_verify_locations(ctx, CAFILE, CADIR) != 1) int_error("Error loading CA file and/or directory"); if (SSL_CTX_set_default_verify_paths(ctx) != 1) int_error("Error loading default CA file and/or directory"); if (SSL_CTX_use_certificate_chain_file(ctx, CERTFILE) != 1) int_error("Error loading certificate from file"); if (SSL_CTX_use_PrivateKey_file(ctx, CERTFILE, SSL_FILETYPE_PEM) != 1) int_error("Error loading private key from file"); // a client cert is required. SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_callback); SSL_CTX_set_verify_depth(ctx, 4); // SSL_OP_SINGLE_DH_USE causes the private part of the DH key exchange // to be recomputed for each client connecting. SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_SINGLE_DH_USE); SSL_CTX_set_tmp_dh_callback(ctx, tmp_dh_callback); if (SSL_CTX_set_cipher_list(ctx, CIPHER_LIST) != 1) int_error("Error setting cipher list (no valid ciphers)"); return ctx; }
SSL_CTX * initialize_ctx(char ask_compression) { if (!bio_err) { SSL_library_init(); SSL_load_error_strings(); ERR_load_crypto_strings(); /* error write context */ bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); } /* create context */ const SSL_METHOD *meth = SSLv23_method(); SSL_CTX *ctx = SSL_CTX_new(meth); #ifdef SSL_OP_NO_COMPRESSION if (!ask_compression) SSL_CTX_set_options(ctx, SSL_OP_NO_COMPRESSION); #endif return ctx; }
void ssl_set_ecdh_curve(SSL_CTX *ctx, const char *curve) { int nid; EC_KEY *ecdh; if (curve == NULL) curve = SSL_ECDH_CURVE; if ((nid = OBJ_sn2nid(curve)) == 0) { ssl_error("ssl_set_ecdh_curve"); fatal("ssl_set_ecdh_curve: unknown curve name " SSL_ECDH_CURVE); } if ((ecdh = EC_KEY_new_by_curve_name(nid)) == NULL) { ssl_error("ssl_set_ecdh_curve"); fatal("ssl_set_ecdh_curve: unable to create curve " SSL_ECDH_CURVE); } SSL_CTX_set_tmp_ecdh(ctx, ecdh); SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE); EC_KEY_free(ecdh); }
void tls_ctx_set_options (struct tls_root_ctx *ctx, unsigned int ssl_flags) { ASSERT(NULL != ctx); SSL_CTX_set_session_cache_mode (ctx->ctx, SSL_SESS_CACHE_OFF); SSL_CTX_set_options (ctx->ctx, SSL_OP_SINGLE_DH_USE); SSL_CTX_set_default_passwd_cb (ctx->ctx, pem_password_callback); /* Require peer certificate verification */ #if P2MP_SERVER if (ssl_flags & SSLF_CLIENT_CERT_NOT_REQUIRED) { msg (M_WARN, "WARNING: POTENTIALLY DANGEROUS OPTION " "--client-cert-not-required may accept clients which do not present " "a certificate"); } else #endif SSL_CTX_set_verify (ctx->ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_callback); SSL_CTX_set_info_callback (ctx->ctx, info_callback); }
static void init_openssl(struct module *module) { unsigned char f_randfile[PATH_MAX]; /* In a nutshell, on OS's without a /dev/urandom, the OpenSSL library * cannot initialize the PRNG and so every attempt to use SSL fails. * It's actually an OpenSSL FAQ, and according to them, it's up to the * application coders to seed the RNG. -- William Yodlowsky */ if (RAND_egd(RAND_file_name(f_randfile, sizeof(f_randfile))) < 0) { /* Not an EGD, so read and write to it */ if (RAND_load_file(f_randfile, -1)) RAND_write_file(f_randfile); } SSLeay_add_ssl_algorithms(); context = SSL_CTX_new(SSLv23_client_method()); SSL_CTX_set_options(context, SSL_OP_ALL); SSL_CTX_set_default_verify_paths(context); socket_SSL_ex_data_idx = SSL_get_ex_new_index(0, NULL, NULL, socket_SSL_ex_data_dup, NULL); }
int SSLContext::initDH( const char * pFile ) { DH *pDH = NULL; if ( pFile ) { BIO *bio; if ((bio = BIO_new_file(pFile, "r")) != NULL) { pDH = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); BIO_free(bio); } } if ( !pDH ) { pDH = getTmpDhParam(); if ( !pDH ) return -1; } SSL_CTX_set_tmp_dh( m_pCtx, pDH ); if ( pDH != s_pDH1024 ) DH_free( pDH ); SSL_CTX_set_options( m_pCtx, SSL_OP_SINGLE_DH_USE); return 0; }
static int lws_context_ssl_init_ecdh_curve(struct lws_context_creation_info *info, struct lws_vhost *vhost) { #if defined(LWS_HAVE_OPENSSL_ECDH_H) && !defined(LWS_WITH_MBEDTLS) EC_KEY *ecdh; int ecdh_nid; const char *ecdh_curve = "prime256v1"; if (info->ecdh_curve) ecdh_curve = info->ecdh_curve; ecdh_nid = OBJ_sn2nid(ecdh_curve); if (NID_undef == ecdh_nid) { lwsl_err("SSL: Unknown curve name '%s'", ecdh_curve); return 1; } ecdh = EC_KEY_new_by_curve_name(ecdh_nid); if (NULL == ecdh) { lwsl_err("SSL: Unable to create curve '%s'", ecdh_curve); return 1; } SSL_CTX_set_tmp_ecdh(vhost->ssl_ctx, ecdh); EC_KEY_free(ecdh); SSL_CTX_set_options(vhost->ssl_ctx, SSL_OP_SINGLE_ECDH_USE); lwsl_notice(" SSL ECDH curve '%s'\n", ecdh_curve); #else #if !defined(LWS_WITH_MBEDTLS) lwsl_notice(" OpenSSL doesn't support ECDH\n"); #endif #endif return 0; }
Node::Node(int recvLength, int prePadding, int postPadding, bool useDefaultLoop) { nodeData = new NodeData; nodeData->recvBufferMemoryBlock = new char[recvLength]; nodeData->recvBuffer = nodeData->recvBufferMemoryBlock + prePadding; nodeData->recvLength = recvLength - prePadding - postPadding; nodeData->tid = pthread_self(); loop = Loop::createLoop(useDefaultLoop); // each node has a context nodeData->netContext = new Context(); nodeData->loop = loop; nodeData->asyncMutex = &asyncMutex; int indices = NodeData::getMemoryBlockIndex(NodeData::preAllocMaxSize) + 1; nodeData->preAlloc = new char*[indices]; for (int i = 0; i < indices; i++) { nodeData->preAlloc[i] = nullptr; } nodeData->clientContext = SSL_CTX_new(SSLv23_client_method()); SSL_CTX_set_options(nodeData->clientContext, SSL_OP_NO_SSLv3); }
void SecureSocket::initContext(bool server) { SSL_library_init(); const SSL_METHOD* method; // load & register all cryptos, etc. OpenSSL_add_all_algorithms(); // load all error messages SSL_load_error_strings(); if (CLOG->getFilter() >= kINFO) { showSecureLibInfo(); } // SSLv23_method uses TLSv1, with the ability to fall back to SSLv3 if (server) { method = SSLv23_server_method(); } else { method = SSLv23_client_method(); } // create new context from method SSL_METHOD* m = const_cast<SSL_METHOD*>(method); m_ssl->m_context = SSL_CTX_new(m); // drop SSLv3 support SSL_CTX_set_options(m_ssl->m_context, SSL_OP_NO_SSLv3); if (m_ssl->m_context == NULL) { showError(); } }
static void tls_init_options(void) { static int passes; # ifdef SSL_OP_CIPHER_SERVER_PREFERENCE SSL_CTX_set_options(tls_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); # endif # ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION SSL_CTX_set_options(tls_ctx, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); # endif SSL_CTX_set_options(tls_ctx, SSL_OP_NO_SSLv2); SSL_CTX_set_options(tls_ctx, SSL_OP_NO_SSLv3); # ifdef SSL_OP_NO_TLSv1 SSL_CTX_set_options(tls_ctx, SSL_OP_NO_TLSv1); # endif # ifdef SSL_OP_NO_TLSv1_1 SSL_CTX_set_options(tls_ctx, SSL_OP_NO_TLSv1_1); # endif # ifdef SSL_OP_NO_TLSv1_2 SSL_CTX_clear_options(tls_ctx, SSL_OP_NO_TLSv1_2); # endif # ifdef SSL_OP_NO_TLSv1_3 SSL_CTX_clear_options(tls_ctx, SSL_OP_NO_TLSv1_3); # endif if (tlsciphersuite != NULL) { if (SSL_CTX_set_cipher_list(tls_ctx, tlsciphersuite) != 1) { logfile(LOG_ERR, MSG_TLS_CIPHER_FAILED, tlsciphersuite); _EXIT(EXIT_FAILURE); } } SSL_CTX_set_info_callback(tls_ctx, ssl_info_cb); if (passes == 0) { SSL_CTX_set_tlsext_servername_callback(tls_ctx, ssl_servername_cb); passes++; } SSL_CTX_set_verify_depth(tls_ctx, MAX_CERTIFICATE_DEPTH); }
int context_init(SERVICE_OPTIONS *section) { /* init SSL context */ /* create SSL context */ if(section->option.client) section->ctx=SSL_CTX_new(section->client_method); else /* server mode */ section->ctx=SSL_CTX_new(section->server_method); if(!section->ctx) { sslerror("SSL_CTX_new"); return 1; /* FAILED */ } SSL_CTX_set_ex_data(section->ctx, index_opt, section); /* for callbacks */ /* load certificate and private key to be verified by the peer server */ #if !defined(OPENSSL_NO_ENGINE) && OPENSSL_VERSION_NUMBER>=0x0090809fL /* SSL_CTX_set_client_cert_engine() was introduced in OpenSSL 0.9.8i */ if(section->option.client && section->engine) { if(SSL_CTX_set_client_cert_engine(section->ctx, section->engine)) s_log(LOG_INFO, "Client certificate engine (%s) enabled", ENGINE_get_id(section->engine)); else /* no client certificate functionality in this engine */ sslerror("SSL_CTX_set_client_cert_engine"); /* ignore error */ } #endif if(auth_init(section)) return 1; /* FAILED */ /* initialize verification of the peer server certificate */ if(verify_init(section)) return 1; /* FAILED */ /* initialize DH/ECDH server mode */ if(!section->option.client) { #ifndef OPENSSL_NO_TLSEXT SSL_CTX_set_tlsext_servername_arg(section->ctx, section); SSL_CTX_set_tlsext_servername_callback(section->ctx, servername_cb); #endif /* OPENSSL_NO_TLSEXT */ #ifndef OPENSSL_NO_DH dh_init(section); /* ignore the result (errors are not critical) */ #endif /* OPENSSL_NO_DH */ #ifndef OPENSSL_NO_ECDH ecdh_init(section); /* ignore the result (errors are not critical) */ #endif /* OPENSSL_NO_ECDH */ } /* setup session cache */ if(!section->option.client) { unsigned servname_len=(unsigned)strlen(section->servname); if(servname_len>SSL_MAX_SSL_SESSION_ID_LENGTH) servname_len=SSL_MAX_SSL_SESSION_ID_LENGTH; if(!SSL_CTX_set_session_id_context(section->ctx, (unsigned char *)section->servname, servname_len)) { sslerror("SSL_CTX_set_session_id_context"); return 1; /* FAILED */ } } #ifdef SSL_SESS_CACHE_NO_INTERNAL_STORE /* the default cache mode is just SSL_SESS_CACHE_SERVER */ SSL_CTX_set_session_cache_mode(section->ctx, SSL_SESS_CACHE_SERVER|SSL_SESS_CACHE_NO_INTERNAL_STORE); #endif SSL_CTX_sess_set_cache_size(section->ctx, section->session_size); SSL_CTX_set_timeout(section->ctx, section->session_timeout); SSL_CTX_sess_set_new_cb(section->ctx, sess_new_cb); SSL_CTX_sess_set_get_cb(section->ctx, sess_get_cb); SSL_CTX_sess_set_remove_cb(section->ctx, sess_remove_cb); /* set info callback */ SSL_CTX_set_info_callback(section->ctx, info_callback); /* ciphers, options, mode */ if(section->cipher_list) if(!SSL_CTX_set_cipher_list(section->ctx, section->cipher_list)) { sslerror("SSL_CTX_set_cipher_list"); return 1; /* FAILED */ } SSL_CTX_set_options(section->ctx, (SSL_OPTIONS_TYPE)(section->ssl_options_set)); #if OPENSSL_VERSION_NUMBER>=0x009080dfL SSL_CTX_clear_options(section->ctx, (SSL_OPTIONS_TYPE)(section->ssl_options_clear)); s_log(LOG_DEBUG, "SSL options: 0x%08lX (+0x%08lX, -0x%08lX)", SSL_CTX_get_options(section->ctx), section->ssl_options_set, section->ssl_options_clear); #else /* OpenSSL older than 0.9.8m */ s_log(LOG_DEBUG, "SSL options: 0x%08lX (+0x%08lX)", SSL_CTX_get_options(section->ctx), section->ssl_options_set); #endif /* OpenSSL 0.9.8m or later */ /* initialize OpenSSL CONF options */ if(conf_init(section)) return 1; /* FAILED */ #ifdef SSL_MODE_RELEASE_BUFFERS SSL_CTX_set_mode(section->ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_RELEASE_BUFFERS); #else SSL_CTX_set_mode(section->ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); #endif return 0; /* 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; }
int openconnect_open_https(struct openconnect_info *vpninfo) { method_const SSL_METHOD *ssl3_method; SSL *https_ssl; BIO *https_bio; int ssl_sock; int err; if (vpninfo->https_ssl) return 0; if (vpninfo->peer_cert) { X509_free(vpninfo->peer_cert); vpninfo->peer_cert = NULL; } ssl_sock = connect_https_socket(vpninfo); if (ssl_sock < 0) return ssl_sock; ssl3_method = TLSv1_client_method(); if (!vpninfo->https_ctx) { vpninfo->https_ctx = SSL_CTX_new(ssl3_method); /* Some servers (or their firewalls) really don't like seeing extensions. */ #ifdef SSL_OP_NO_TICKET SSL_CTX_set_options(vpninfo->https_ctx, SSL_OP_NO_TICKET); #endif if (vpninfo->cert) { err = load_certificate(vpninfo); if (err) { vpn_progress(vpninfo, PRG_ERR, _("Loading certificate failed. Aborting.\n")); SSL_CTX_free(vpninfo->https_ctx); vpninfo->https_ctx = NULL; close(ssl_sock); return err; } check_certificate_expiry(vpninfo); } /* We just want to do: SSL_CTX_set_purpose(vpninfo->https_ctx, X509_PURPOSE_ANY); ... but it doesn't work with OpenSSL < 0.9.8k because of problems with inheritance (fixed in v1.1.4.6 of crypto/x509/x509_vpm.c) so we have to play silly buggers instead. This trick doesn't work _either_ in < 0.9.7 but I don't know of _any_ workaround which will, and can't be bothered to find out either. */ #if OPENSSL_VERSION_NUMBER >= 0x00908000 SSL_CTX_set_cert_verify_callback(vpninfo->https_ctx, ssl_app_verify_callback, NULL); #endif SSL_CTX_set_default_verify_paths(vpninfo->https_ctx); #ifdef ANDROID_KEYSTORE if (vpninfo->cafile && !strncmp(vpninfo->cafile, "keystore:", 9)) { STACK_OF(X509_INFO) *stack; X509_STORE *store; X509_INFO *info; BIO *b = BIO_from_keystore(vpninfo, vpninfo->cafile); if (!b) { SSL_CTX_free(vpninfo->https_ctx); vpninfo->https_ctx = NULL; close(ssl_sock); return -EINVAL; } stack = PEM_X509_INFO_read_bio(b, NULL, NULL, NULL); BIO_free(b); if (!stack) { vpn_progress(vpninfo, PRG_ERR, _("Failed to read certs from CA file '%s'\n"), vpninfo->cafile); openconnect_report_ssl_errors(vpninfo); SSL_CTX_free(vpninfo->https_ctx); vpninfo->https_ctx = NULL; close(ssl_sock); return -ENOENT; } store = SSL_CTX_get_cert_store(vpninfo->https_ctx); while ((info = sk_X509_INFO_pop(stack))) { if (info->x509) X509_STORE_add_cert(store, info->x509); if (info->crl) X509_STORE_add_crl(store, info->crl); X509_INFO_free(info); } sk_X509_INFO_free(stack); } else #endif if (vpninfo->cafile) { if (!SSL_CTX_load_verify_locations(vpninfo->https_ctx, vpninfo->cafile, NULL)) { vpn_progress(vpninfo, PRG_ERR, _("Failed to open CA file '%s'\n"), vpninfo->cafile); openconnect_report_ssl_errors(vpninfo); SSL_CTX_free(vpninfo->https_ctx); vpninfo->https_ctx = NULL; close(ssl_sock); return -EINVAL; } } } https_ssl = SSL_new(vpninfo->https_ctx); workaround_openssl_certchain_bug(vpninfo, https_ssl); https_bio = BIO_new_socket(ssl_sock, BIO_NOCLOSE); BIO_set_nbio(https_bio, 1); SSL_set_bio(https_ssl, https_bio, https_bio); vpn_progress(vpninfo, PRG_INFO, _("SSL negotiation with %s\n"), vpninfo->hostname); while ((err = SSL_connect(https_ssl)) <= 0) { fd_set wr_set, rd_set; int maxfd = ssl_sock; FD_ZERO(&wr_set); FD_ZERO(&rd_set); err = SSL_get_error(https_ssl, err); if (err == SSL_ERROR_WANT_READ) FD_SET(ssl_sock, &rd_set); else if (err == SSL_ERROR_WANT_WRITE) FD_SET(ssl_sock, &wr_set); else { vpn_progress(vpninfo, PRG_ERR, _("SSL connection failure\n")); openconnect_report_ssl_errors(vpninfo); SSL_free(https_ssl); close(ssl_sock); return -EINVAL; } cmd_fd_set(vpninfo, &rd_set, &maxfd); select(maxfd + 1, &rd_set, &wr_set, NULL, NULL); if (is_cancel_pending(vpninfo, &rd_set)) { vpn_progress(vpninfo, PRG_ERR, _("SSL connection cancelled\n")); SSL_free(https_ssl); close(ssl_sock); return -EINVAL; } } if (verify_peer(vpninfo, https_ssl)) { SSL_free(https_ssl); close(ssl_sock); return -EINVAL; } vpninfo->ssl_fd = ssl_sock; vpninfo->https_ssl = https_ssl; /* Stash this now, because it might not be available later if the server has disconnected. */ vpninfo->peer_cert = SSL_get_peer_certificate(vpninfo->https_ssl); vpn_progress(vpninfo, PRG_INFO, _("Connected to HTTPS on %s\n"), vpninfo->hostname); return 0; }
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_value(conf->early_data, prev->early_data, 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_size_value(conf->buffer_size, prev->buffer_size, NGX_SSL_BUFSIZE); 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_ptr_value(conf->certificates, prev->certificates, NULL); ngx_conf_merge_ptr_value(conf->certificate_keys, prev->certificate_keys, NULL); 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->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->certificates == NULL) { 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_keys == NULL) { 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; } if (conf->certificate_keys->nelts < conf->certificates->nelts) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined " "for certificate \"%V\" and " "the \"ssl\" directive in %s:%ui", ((ngx_str_t *) conf->certificates->elts) + conf->certificates->nelts - 1, conf->file, conf->line); return NGX_CONF_ERROR; } } else { if (conf->certificates == NULL) { return NGX_CONF_OK; } if (conf->certificate_keys == NULL || conf->certificate_keys->nelts < conf->certificates->nelts) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined " "for certificate \"%V\"", ((ngx_str_t *) conf->certificates->elts) + conf->certificates->nelts - 1); 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) { ngx_ssl_cleanup_ctx(&conf->ssl); return NGX_CONF_ERROR; } cln->handler = ngx_ssl_cleanup_ctx; cln->data = &conf->ssl; #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_application_layer_protocol_negotiation SSL_CTX_set_alpn_select_cb(conf->ssl.ctx, ngx_http_ssl_alpn_select, NULL); #endif #ifdef TLSEXT_TYPE_next_proto_neg SSL_CTX_set_next_protos_advertised_cb(conf->ssl.ctx, ngx_http_ssl_npn_advertised, NULL); #endif if (ngx_http_ssl_compile_certificates(cf, conf) != NGX_OK) { return NGX_CONF_ERROR; } if (conf->certificate_values) { #ifdef SSL_R_CERT_CB_ERROR /* install callback to lookup certificates */ SSL_CTX_set_cert_cb(conf->ssl.ctx, ngx_http_ssl_certificate, conf); #else ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "variables in " "\"ssl_certificate\" and \"ssl_certificate_key\" " "directives are not supported on this platform"); return NGX_CONF_ERROR; #endif } else { /* configure certificates */ if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates, conf->certificate_keys, conf->passwords) != NGX_OK) { return NGX_CONF_ERROR; } } if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers, conf->prefer_server_ciphers) != NGX_OK) { return NGX_CONF_ERROR; } conf->ssl.buffer_size = conf->buffer_size; 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 (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->certificates, 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; } 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; } } if (ngx_ssl_early_data(cf, &conf->ssl, conf->early_data) != NGX_OK) { return NGX_CONF_ERROR; } return NGX_CONF_OK; }
/* SSL ************************************************************************/ long HsOpenSSL_SSL_CTX_set_options(SSL_CTX* ctx, long options) { return SSL_CTX_set_options(ctx, options); }
bool SSLSocket::setupCrypto(SSLSocket *session /* = NULL */) { if (m_data->m_handle) { raise_warning("SSL/TLS already set-up for this stream"); return false; } /* need to do slightly different things, based on client/server method, * so lets remember which method was selected */ #if OPENSSL_VERSION_NUMBER < 0x00909000L SSL_METHOD *smethod; #else const SSL_METHOD *smethod; #endif switch (m_data->m_method) { case CryptoMethod::ClientSSLv23: m_data->m_client = true; smethod = SSLv23_client_method(); break; case CryptoMethod::ClientSSLv3: m_data->m_client = true; smethod = SSLv3_client_method(); break; case CryptoMethod::ClientTLS: m_data->m_client = true; smethod = TLSv1_client_method(); break; case CryptoMethod::ServerSSLv23: m_data->m_client = false; smethod = SSLv23_server_method(); break; case CryptoMethod::ServerSSLv3: m_data->m_client = false; smethod = SSLv3_server_method(); break; /* SSLv2 protocol might be disabled in the OpenSSL library */ #ifndef OPENSSL_NO_SSL2 case CryptoMethod::ClientSSLv2: m_data->m_client = true; smethod = SSLv2_client_method(); break; case CryptoMethod::ServerSSLv2: m_data->m_client = false; smethod = SSLv2_server_method(); break; #else case CryptoMethod::ClientSSLv2: case CryptoMethod::ServerSSLv2: raise_warning("OpenSSL library does not support SSL2 protocol"); return false; break; #endif case CryptoMethod::ServerTLS: m_data->m_client = false; smethod = TLSv1_server_method(); break; default: return false; } SSL_CTX *ctx = SSL_CTX_new(smethod); if (ctx == nullptr) { raise_warning("failed to create an SSL context"); return false; } SSL_CTX_set_options(ctx, SSL_OP_ALL); m_data->m_handle = createSSL(ctx); if (m_data->m_handle == nullptr) { raise_warning("failed to create an SSL handle"); SSL_CTX_free(ctx); return false; } if (!SSL_set_fd(m_data->m_handle, getFd())) { handleError(0, true); } if (session) { SSL_copy_session_id(m_data->m_handle, session->m_data->m_handle); } return true; }
int redisSslCreate(redisContext *c, const char *capath, const char *certpath, const char *keypath, const char *servername) { assert(!c->ssl); c->ssl = calloc(1, sizeof(*c->ssl)); static int isInit = 0; if (!isInit) { isInit = 1; SSL_library_init(); initOpensslLocks(); } redisSsl *s = c->ssl; s->ctx = SSL_CTX_new(SSLv23_client_method()); SSL_CTX_set_info_callback(s->ctx, sslLogCallback); SSL_CTX_set_mode(s->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); SSL_CTX_set_options(s->ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); SSL_CTX_set_verify(s->ctx, SSL_VERIFY_PEER, NULL); if ((certpath != NULL && keypath == NULL) || (keypath != NULL && certpath == NULL)) { __redisSetError(c, REDIS_ERR, "certpath and keypath must be specified together"); return REDIS_ERR; } if (capath) { if (!SSL_CTX_load_verify_locations(s->ctx, capath, NULL)) { __redisSetError(c, REDIS_ERR, "Invalid CA certificate"); return REDIS_ERR; } } if (certpath) { if (!SSL_CTX_use_certificate_chain_file(s->ctx, certpath)) { __redisSetError(c, REDIS_ERR, "Invalid client certificate"); return REDIS_ERR; } if (!SSL_CTX_use_PrivateKey_file(s->ctx, keypath, SSL_FILETYPE_PEM)) { __redisSetError(c, REDIS_ERR, "Invalid client key"); return REDIS_ERR; } } s->ssl = SSL_new(s->ctx); if (!s->ssl) { __redisSetError(c, REDIS_ERR, "Couldn't create new SSL instance"); return REDIS_ERR; } if (servername) { if (!SSL_set_tlsext_host_name(s->ssl, servername)) { __redisSetError(c, REDIS_ERR, "Couldn't set server name indication"); return REDIS_ERR; } } SSL_set_fd(s->ssl, c->fd); SSL_set_connect_state(s->ssl); c->flags |= REDIS_SSL; int rv = SSL_connect(c->ssl->ssl); if (rv == 1) { return REDIS_OK; } rv = SSL_get_error(s->ssl, rv); if (((c->flags & REDIS_BLOCK) == 0) && (rv == SSL_ERROR_WANT_READ || rv == SSL_ERROR_WANT_WRITE)) { return REDIS_OK; } if (c->err == 0) { __redisSetError(c, REDIS_ERR_IO, "SSL_connect() failed"); } return REDIS_ERR; }
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; ngx_pool_cleanup_t *cln; ngx_conf_merge_value(conf->enable, prev->enable, 0); ngx_conf_merge_value(conf->starttls, prev->starttls, NGX_MAIL_STARTTLS_OFF); if (conf->enable == 0 && conf->starttls == NGX_MAIL_STARTTLS_OFF) { return NGX_CONF_OK; } 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_SSLv2|NGX_SSL_SSLv3|NGX_SSL_TLSv1)); ngx_conf_merge_str_value(conf->certificate, prev->certificate, NGX_DEFLAUT_CERTIFICATE); ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, NGX_DEFLAUT_CERTIFICATE_KEY); ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFLAUT_CIPHERS); conf->ssl.log = cf->log; 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); } } #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE if (conf->prefer_server_ciphers) { SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); } #endif if (ngx_ssl_generate_rsa512_key(&conf->ssl) != 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; }
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; }
SslContext_t::SslContext_t (bool is_server, const string &privkeyfile, const string &certchainfile): pCtx (NULL), PrivateKey (NULL), Certificate (NULL) { /* TODO: the usage of the specified private-key and cert-chain filenames only applies to * client-side connections at this point. Server connections currently use the default materials. * That needs to be fixed asap. * Also, in this implementation, server-side connections use statically defined X-509 defaults. * One thing I'm really not clear on is whether or not you have to explicitly free X509 and EVP_PKEY * objects when we call our destructor, or whether just calling SSL_CTX_free is enough. */ if (!bLibraryInitialized) { bLibraryInitialized = true; SSL_library_init(); OpenSSL_add_ssl_algorithms(); OpenSSL_add_all_algorithms(); SSL_load_error_strings(); ERR_load_crypto_strings(); InitializeDefaultCredentials(); } bIsServer = is_server; pCtx = SSL_CTX_new (is_server ? SSLv23_server_method() : SSLv23_client_method()); if (!pCtx) throw std::runtime_error ("no SSL context"); SSL_CTX_set_options (pCtx, SSL_OP_ALL); //SSL_CTX_set_options (pCtx, (SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3)); #ifdef SSL_MODE_RELEASE_BUFFERS SSL_CTX_set_mode (pCtx, SSL_MODE_RELEASE_BUFFERS); #endif if (is_server) { // The SSL_CTX calls here do NOT allocate memory. int e; if (privkeyfile.length() > 0) e = SSL_CTX_use_PrivateKey_file (pCtx, privkeyfile.c_str(), SSL_FILETYPE_PEM); else e = SSL_CTX_use_PrivateKey (pCtx, DefaultPrivateKey); if (e <= 0) ERR_print_errors_fp(stderr); assert (e > 0); if (certchainfile.length() > 0) e = SSL_CTX_use_certificate_chain_file (pCtx, certchainfile.c_str()); else e = SSL_CTX_use_certificate (pCtx, DefaultCertificate); if (e <= 0) ERR_print_errors_fp(stderr); assert (e > 0); } SSL_CTX_set_cipher_list (pCtx, "ALL:!ADH:!LOW:!EXP:!DES-CBC3-SHA:@STRENGTH"); if (is_server) { SSL_CTX_sess_set_cache_size (pCtx, 128); SSL_CTX_set_session_id_context (pCtx, (unsigned char*)"eventmachine", 12); } else { int e; if (privkeyfile.length() > 0) { e = SSL_CTX_use_PrivateKey_file (pCtx, privkeyfile.c_str(), SSL_FILETYPE_PEM); if (e <= 0) ERR_print_errors_fp(stderr); assert (e > 0); } if (certchainfile.length() > 0) { e = SSL_CTX_use_certificate_chain_file (pCtx, certchainfile.c_str()); if (e <= 0) ERR_print_errors_fp(stderr); assert (e > 0); } } }
void SSLHandler::init(const SecurityProperties& securityProperties) { if(isSSLEnabled) { this->securityProperties = securityProperties; if(securityProperties.alpnEnabled && securityProperties.alpnProtoList.size()>0) { for(int pn=0;pn<(int)securityProperties.alpnProtoList.size();pn++) { string protoname = securityProperties.alpnProtoList.at(pn); vector<unsigned char> res = vector<unsigned char>(1 + protoname.length()); unsigned char* p = res.data(); *p++ = protoname.length(); memcpy(p, protoname.c_str(), protoname.length()); advertisedProtos.push_back(res); } } string sslConfsettings = "Server setup with SSL enabled, CERTFILE = "; sslConfsettings.append(securityProperties.cert_file); sslConfsettings.append(", KEYFILE = "); sslConfsettings.append(securityProperties.key_file); sslConfsettings.append(", PASSWORD = "******", DHFILE = "); sslConfsettings.append(securityProperties.dh_file); sslConfsettings.append(", CA_LIST = "); sslConfsettings.append(securityProperties.ca_list); sslConfsettings.append(", ISDH_PARAMS = "); //sslConfsettings.append(CastUtil::lexical_cast<string>(securityProperties.isDHParams)); //sslConfsettings.append(", CLIENT_SEC_LEVEL = "); //sslConfsettings.append(CastUtil::lexical_cast<string>(securityProperties.client_auth)); logger << sslConfsettings << endl; /* Build our SSL context*/ ctx = SSLCommon::initialize_ctx(true); pass = (char*)securityProperties.sec_password.c_str(); SSL_CTX_set_default_passwd_cb(ctx, SSLHandler::password_cb); SSL_CTX_set_options(ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION | SSL_OP_SINGLE_DH_USE | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_TICKET | SSL_OP_CIPHER_SERVER_PREFERENCE); SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS); if(securityProperties.isDHParams) { SSLCommon::load_dh_params(ctx,(char*)securityProperties.dh_file.c_str()); } else { SSLCommon::load_ecdh_params(ctx); } const unsigned char sid_ctx[] = "Ffead"; SSL_CTX_set_session_id_context(ctx, sid_ctx, sizeof(sid_ctx) - 1); SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER); /*SSL_CTX_set_session_id_context(ctx, (const unsigned char*)&s_server_session_id_context, sizeof s_server_session_id_context); */ /* Set our cipher list */ if(SSLCommon::ciphers!=""){ SSL_CTX_set_cipher_list(ctx, SSLCommon::ciphers.c_str()); } SSLCommon::loadCerts(ctx, (char*)securityProperties.cert_file.c_str(), (char*)securityProperties.key_file.c_str(), securityProperties.ca_list, true); if(securityProperties.client_auth==2) { /* Set to require peer (client) certificate verification */ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); /* Set the verification depth to 1 */ #if (OPENSSL_VERSION_NUMBER < 0x00905100L) SSL_CTX_set_verify_depth(ctx,1); #endif } else if(securityProperties.client_auth==1) { /* Set to require peer (client) certificate verification */ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); /* Set the verification depth to 1 */ #if (OPENSSL_VERSION_NUMBER < 0x00905100L) SSL_CTX_set_verify_depth(ctx,1); #endif } else { SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); } #if OPENSSL_VERSION_NUMBER >= 0x10002000L if(securityProperties.alpnEnabled) { for (int var = 0; var < (int)advertisedProtos.size(); ++var) { SSL_CTX_set_next_protos_advertised_cb(ctx, SSLHandler::next_proto_cb, &(advertisedProtos.at(var))); } // ALPN selection callback SSL_CTX_set_alpn_select_cb(ctx, SSLHandler::alpn_select_proto_cb, NULL); } #endif // OPENSSL_VERSION_NUMBER >= 0x10002000L } }
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); }
SSL_CTX *setup_ssl_listen(void) { const SSL_METHOD *method; if (sslctx) goto done; SSL_library_init(); OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); SSL_load_error_strings(); /* RAND_status initializes the random number generator through a variety of platform-dependent methods, then returns 1 if there is enough entropy or 0 otherwise. This seems to be a good platform-independent way of seeding the generator, as well as of refusing to continue without enough entropy. */ if (!RAND_status()) bye("Failed to seed OpenSSL PRNG (RAND_status returned false)."); if (!(method = SSLv23_server_method())) bye("SSLv23_server_method(): %s.", ERR_error_string(ERR_get_error(), NULL)); if (!(sslctx = SSL_CTX_new(method))) bye("SSL_CTX_new(): %s.", ERR_error_string(ERR_get_error(), NULL)); SSL_CTX_set_options(sslctx, SSL_OP_ALL | SSL_OP_NO_SSLv2); /* Secure ciphers list taken from Nsock. */ if (!SSL_CTX_set_cipher_list(sslctx, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH")) bye("Unable to set OpenSSL cipher list: %s", ERR_error_string(ERR_get_error(), NULL)); if (o.sslcert == NULL && o.sslkey == NULL) { X509 *cert; EVP_PKEY *key; char digest_buf[SHA1_STRING_LENGTH + 1]; if (o.verbose) loguser("Generating a temporary %d-bit RSA key. Use --ssl-key and --ssl-cert to use a permanent one.\n", DEFAULT_KEY_BITS); if (ssl_gen_cert(&cert, &key) == 0) bye("ssl_gen_cert(): %s.", ERR_error_string(ERR_get_error(), NULL)); if (o.verbose) { char *fp; fp = ssl_cert_fp_str_sha1(cert, digest_buf, sizeof(digest_buf)); ncat_assert(fp == digest_buf); loguser("SHA-1 fingerprint: %s\n", digest_buf); } if (SSL_CTX_use_certificate(sslctx, cert) != 1) bye("SSL_CTX_use_certificate(): %s.", ERR_error_string(ERR_get_error(), NULL)); if (SSL_CTX_use_PrivateKey(sslctx, key) != 1) bye("SSL_CTX_use_PrivateKey(): %s.", ERR_error_string(ERR_get_error(), NULL)); X509_free(cert); EVP_PKEY_free(key); } else { if (o.sslcert == NULL || o.sslkey == NULL) bye("The --ssl-key and --ssl-cert options must be used together."); if (SSL_CTX_use_certificate_chain_file(sslctx, o.sslcert) != 1) bye("SSL_CTX_use_certificate_chain_file(): %s.", ERR_error_string(ERR_get_error(), NULL)); if (SSL_CTX_use_PrivateKey_file(sslctx, o.sslkey, SSL_FILETYPE_PEM) != 1) bye("SSL_CTX_use_Privatekey_file(): %s.", ERR_error_string(ERR_get_error(), NULL)); } done: return sslctx; }
int MAIN(int argc, char **argv) { int off=0; SSL *con=NULL,*con2=NULL; X509_STORE *store = NULL; int s,k,width,state=0; char *cbuf=NULL,*sbuf=NULL,*mbuf=NULL; int cbuf_len,cbuf_off; int sbuf_len,sbuf_off; fd_set readfds,writefds; short port=PORT; int full_log=1; char *host=SSL_HOST_NAME; char *cert_file=NULL,*key_file=NULL; int cert_format = FORMAT_PEM, key_format = FORMAT_PEM; char *passarg = NULL, *pass = NULL; X509 *cert = NULL; EVP_PKEY *key = NULL; char *CApath=NULL,*CAfile=NULL,*cipher=NULL; int reconnect=0,badop=0,verify=SSL_VERIFY_NONE,bugs=0; int crlf=0; int write_tty,read_tty,write_ssl,read_ssl,tty_on,ssl_pending; SSL_CTX *ctx=NULL; int ret=1,in_init=1,i,nbio_test=0; int starttls_proto = PROTO_OFF; int prexit = 0, vflags = 0; SSL_METHOD *meth=NULL; #ifdef sock_type #undef sock_type #endif int sock_type=SOCK_STREAM; BIO *sbio; char *inrand=NULL; int mbuf_len=0; #ifndef OPENSSL_NO_ENGINE char *engine_id=NULL; ENGINE *e=NULL; #endif #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE) struct timeval tv; #endif struct sockaddr peer; int peerlen = sizeof(peer); int enable_timeouts = 0 ; long mtu = 0; #if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3) meth=SSLv23_client_method(); #elif !defined(OPENSSL_NO_SSL3) meth=SSLv3_client_method(); #elif !defined(OPENSSL_NO_SSL2) meth=SSLv2_client_method(); #endif apps_startup(); c_Pause=0; c_quiet=0; c_ign_eof=0; c_debug=0; c_msg=0; c_showcerts=0; if (bio_err == NULL) bio_err=BIO_new_fp(stderr,BIO_NOCLOSE); if (!load_config(bio_err, NULL)) goto end; if ( ((cbuf=OPENSSL_malloc(BUFSIZZ)) == NULL) || ((sbuf=OPENSSL_malloc(BUFSIZZ)) == NULL) || ((mbuf=OPENSSL_malloc(BUFSIZZ)) == NULL)) { BIO_printf(bio_err,"out of memory\n"); goto end; } verify_depth=0; verify_error=X509_V_OK; #ifdef FIONBIO c_nbio=0; #endif argc--; argv++; while (argc >= 1) { if (strcmp(*argv,"-host") == 0) { if (--argc < 1) goto bad; host= *(++argv); } else if (strcmp(*argv,"-port") == 0) { if (--argc < 1) goto bad; port=atoi(*(++argv)); if (port == 0) goto bad; } else if (strcmp(*argv,"-connect") == 0) { if (--argc < 1) goto bad; if (!extract_host_port(*(++argv),&host,NULL,&port)) goto bad; } else if (strcmp(*argv,"-verify") == 0) { verify=SSL_VERIFY_PEER; if (--argc < 1) goto bad; verify_depth=atoi(*(++argv)); BIO_printf(bio_err,"verify depth is %d\n",verify_depth); } else if (strcmp(*argv,"-cert") == 0) { if (--argc < 1) goto bad; cert_file= *(++argv); } else if (strcmp(*argv,"-certform") == 0) { if (--argc < 1) goto bad; cert_format = str2fmt(*(++argv)); } else if (strcmp(*argv,"-crl_check") == 0) vflags |= X509_V_FLAG_CRL_CHECK; else if (strcmp(*argv,"-crl_check_all") == 0) vflags |= X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL; else if (strcmp(*argv,"-prexit") == 0) prexit=1; else if (strcmp(*argv,"-crlf") == 0) crlf=1; else if (strcmp(*argv,"-quiet") == 0) { c_quiet=1; c_ign_eof=1; } else if (strcmp(*argv,"-ign_eof") == 0) c_ign_eof=1; else if (strcmp(*argv,"-pause") == 0) c_Pause=1; else if (strcmp(*argv,"-debug") == 0) c_debug=1; #ifdef WATT32 else if (strcmp(*argv,"-wdebug") == 0) dbug_init(); #endif else if (strcmp(*argv,"-msg") == 0) c_msg=1; else if (strcmp(*argv,"-showcerts") == 0) c_showcerts=1; else if (strcmp(*argv,"-nbio_test") == 0) nbio_test=1; else if (strcmp(*argv,"-state") == 0) state=1; #ifndef OPENSSL_NO_SSL2 else if (strcmp(*argv,"-ssl2") == 0) meth=SSLv2_client_method(); #endif #ifndef OPENSSL_NO_SSL3 else if (strcmp(*argv,"-ssl3") == 0) meth=SSLv3_client_method(); #endif #ifndef OPENSSL_NO_TLS1 else if (strcmp(*argv,"-tls1") == 0) meth=TLSv1_client_method(); #endif #ifndef OPENSSL_NO_DTLS1 else if (strcmp(*argv,"-dtls1") == 0) { meth=DTLSv1_client_method(); sock_type=SOCK_DGRAM; } else if (strcmp(*argv,"-timeout") == 0) enable_timeouts=1; else if (strcmp(*argv,"-mtu") == 0) { if (--argc < 1) goto bad; mtu = atol(*(++argv)); } #endif else if (strcmp(*argv,"-bugs") == 0) bugs=1; else if (strcmp(*argv,"-keyform") == 0) { if (--argc < 1) goto bad; key_format = str2fmt(*(++argv)); } else if (strcmp(*argv,"-pass") == 0) { if (--argc < 1) goto bad; passarg = *(++argv); } else if (strcmp(*argv,"-key") == 0) { if (--argc < 1) goto bad; key_file= *(++argv); } else if (strcmp(*argv,"-reconnect") == 0) { reconnect=5; } 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,"-no_tls1") == 0) off|=SSL_OP_NO_TLSv1; else if (strcmp(*argv,"-no_ssl3") == 0) off|=SSL_OP_NO_SSLv3; else if (strcmp(*argv,"-no_ssl2") == 0) off|=SSL_OP_NO_SSLv2; else if (strcmp(*argv,"-serverpref") == 0) off|=SSL_OP_CIPHER_SERVER_PREFERENCE; else if (strcmp(*argv,"-cipher") == 0) { if (--argc < 1) goto bad; cipher= *(++argv); } #ifdef FIONBIO else if (strcmp(*argv,"-nbio") == 0) { c_nbio=1; } #endif else if (strcmp(*argv,"-starttls") == 0) { if (--argc < 1) goto bad; ++argv; if (strcmp(*argv,"smtp") == 0) starttls_proto = PROTO_SMTP; else if (strcmp(*argv,"pop3") == 0) starttls_proto = PROTO_POP3; else if (strcmp(*argv,"imap") == 0) starttls_proto = PROTO_IMAP; else if (strcmp(*argv,"ftp") == 0) starttls_proto = PROTO_FTP; else goto bad; } #ifndef OPENSSL_NO_ENGINE else if (strcmp(*argv,"-engine") == 0) { if (--argc < 1) goto bad; engine_id = *(++argv); } #endif else if (strcmp(*argv,"-rand") == 0) { if (--argc < 1) goto bad; inrand= *(++argv); } else { BIO_printf(bio_err,"unknown option %s\n",*argv); badop=1; break; } argc--; argv++; } if (badop) { bad: sc_usage(); goto end; } OpenSSL_add_ssl_algorithms(); SSL_load_error_strings(); #ifndef OPENSSL_NO_ENGINE e = setup_engine(bio_err, engine_id, 1); #endif if (!app_passwd(bio_err, passarg, NULL, &pass, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } if (key_file == NULL) key_file = cert_file; if (key_file) { key = load_key(bio_err, key_file, key_format, 0, pass, e, "client certificate private key file"); if (!key) { ERR_print_errors(bio_err); goto end; } } if (cert_file) { cert = load_cert(bio_err,cert_file,cert_format, NULL, e, "client certificate file"); if (!cert) { ERR_print_errors(bio_err); goto end; } } if (!app_RAND_load_file(NULL, bio_err, 1) && inrand == NULL && !RAND_status()) { BIO_printf(bio_err,"warning, not much extra random data, consider using the -rand option\n"); } if (inrand != NULL) BIO_printf(bio_err,"%ld semi-random bytes loaded\n", app_RAND_load_files(inrand)); if (bio_c_out == NULL) { if (c_quiet && !c_debug && !c_msg) { bio_c_out=BIO_new(BIO_s_null()); } else { if (bio_c_out == NULL) bio_c_out=BIO_new_fp(stdout,BIO_NOCLOSE); } } ctx=SSL_CTX_new(meth); if (ctx == NULL) { ERR_print_errors(bio_err); goto end; } if (bugs) SSL_CTX_set_options(ctx,SSL_OP_ALL|off); else SSL_CTX_set_options(ctx,off); /* DTLS: partial reads end up discarding unread UDP bytes :-( * Setting read ahead solves this problem. */ if (sock_type == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx, 1); if (state) SSL_CTX_set_info_callback(ctx,apps_ssl_info_callback); if (cipher != NULL) if(!SSL_CTX_set_cipher_list(ctx,cipher)) { BIO_printf(bio_err,"error setting cipher list\n"); ERR_print_errors(bio_err); goto end; } #if 0 else SSL_CTX_set_cipher_list(ctx,getenv("SSL_CIPHER")); #endif SSL_CTX_set_verify(ctx,verify,verify_callback); if (!set_cert_key_stuff(ctx,cert,key)) goto end; if ((!SSL_CTX_load_verify_locations(ctx,CAfile,CApath)) || (!SSL_CTX_set_default_verify_paths(ctx))) { /* BIO_printf(bio_err,"error setting default verify locations\n"); */ ERR_print_errors(bio_err); /* goto end; */ } store = SSL_CTX_get_cert_store(ctx); X509_STORE_set_flags(store, vflags); con=SSL_new(ctx); #ifndef OPENSSL_NO_KRB5 if (con && (con->kssl_ctx = kssl_ctx_new()) != NULL) { kssl_ctx_setstring(con->kssl_ctx, KSSL_SERVER, host); } #endif /* OPENSSL_NO_KRB5 */ /* SSL_set_cipher_list(con,"RC4-MD5"); */ re_start: if (init_client(&s,host,port,sock_type) == 0) { BIO_printf(bio_err,"connect:errno=%d\n",get_last_socket_error()); SHUTDOWN(s); goto end; } BIO_printf(bio_c_out,"CONNECTED(%08X)\n",s); #ifdef FIONBIO if (c_nbio) { unsigned long l=1; BIO_printf(bio_c_out,"turning on non blocking io\n"); if (BIO_socket_ioctl(s,FIONBIO,&l) < 0) { ERR_print_errors(bio_err); goto end; } } #endif if (c_Pause & 0x01) con->debug=1; if ( SSL_version(con) == DTLS1_VERSION) { struct timeval timeout; sbio=BIO_new_dgram(s,BIO_NOCLOSE); if (getsockname(s, &peer, (void *)&peerlen) < 0) { BIO_printf(bio_err, "getsockname:errno=%d\n", get_last_socket_error()); SHUTDOWN(s); goto end; } (void)BIO_ctrl_set_connected(sbio, 1, &peer); if ( enable_timeouts) { timeout.tv_sec = 0; timeout.tv_usec = DGRAM_RCV_TIMEOUT; BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); timeout.tv_sec = 0; timeout.tv_usec = DGRAM_SND_TIMEOUT; BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, &timeout); } if ( mtu > 0) { SSL_set_options(con, SSL_OP_NO_QUERY_MTU); SSL_set_mtu(con, mtu); } else /* want to do MTU discovery */ BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL); } else sbio=BIO_new_socket(s,BIO_NOCLOSE); if (nbio_test) { BIO *test; test=BIO_new(BIO_f_nbio_test()); sbio=BIO_push(test,sbio); } if (c_debug) { con->debug=1; BIO_set_callback(sbio,bio_dump_callback); BIO_set_callback_arg(sbio,(char *)bio_c_out); } if (c_msg) { SSL_set_msg_callback(con, msg_cb); SSL_set_msg_callback_arg(con, bio_c_out); } SSL_set_bio(con,sbio,sbio); SSL_set_connect_state(con); /* ok, lets connect */ width=SSL_get_fd(con)+1; read_tty=1; write_tty=0; tty_on=0; read_ssl=1; write_ssl=1; cbuf_len=0; cbuf_off=0; sbuf_len=0; sbuf_off=0; /* This is an ugly hack that does a lot of assumptions */ /* We do have to handle multi-line responses which may come in a single packet or not. We therefore have to use BIO_gets() which does need a buffering BIO. So during the initial chitchat we do push a buffering BIO into the chain that is removed again later on to not disturb the rest of the s_client operation. */ if (starttls_proto == PROTO_SMTP) { int foundit=0; BIO *fbio = BIO_new(BIO_f_buffer()); BIO_push(fbio, sbio); /* wait for multi-line response to end from SMTP */ do { mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ); } while (mbuf_len>3 && mbuf[3]=='-'); /* STARTTLS command requires EHLO... */ BIO_printf(fbio,"EHLO openssl.client.net\r\n"); (void)BIO_flush(fbio); /* wait for multi-line response to end EHLO SMTP response */ do { mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ); if (strstr(mbuf,"STARTTLS")) foundit=1; } while (mbuf_len>3 && mbuf[3]=='-'); (void)BIO_flush(fbio); BIO_pop(fbio); BIO_free(fbio); if (!foundit) BIO_printf(bio_err, "didn't found starttls in server response," " try anyway...\n"); BIO_printf(sbio,"STARTTLS\r\n"); BIO_read(sbio,sbuf,BUFSIZZ); } else if (starttls_proto == PROTO_POP3) { BIO_read(sbio,mbuf,BUFSIZZ); BIO_printf(sbio,"STLS\r\n"); BIO_read(sbio,sbuf,BUFSIZZ); } else if (starttls_proto == PROTO_IMAP) { int foundit=0; BIO *fbio = BIO_new(BIO_f_buffer()); BIO_push(fbio, sbio); BIO_gets(fbio,mbuf,BUFSIZZ); /* STARTTLS command requires CAPABILITY... */ BIO_printf(fbio,". CAPABILITY\r\n"); (void)BIO_flush(fbio); /* wait for multi-line CAPABILITY response */ do { mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ); if (strstr(mbuf,"STARTTLS")) foundit=1; } while (mbuf_len>3 && mbuf[0]!='.'); (void)BIO_flush(fbio); BIO_pop(fbio); BIO_free(fbio); if (!foundit) BIO_printf(bio_err, "didn't found STARTTLS in server response," " try anyway...\n"); BIO_printf(sbio,". STARTTLS\r\n"); BIO_read(sbio,sbuf,BUFSIZZ); } else if (starttls_proto == PROTO_FTP) { BIO *fbio = BIO_new(BIO_f_buffer()); BIO_push(fbio, sbio); /* wait for multi-line response to end from FTP */ do { mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ); } while (mbuf_len>3 && mbuf[3]=='-'); (void)BIO_flush(fbio); BIO_pop(fbio); BIO_free(fbio); BIO_printf(sbio,"AUTH TLS\r\n"); BIO_read(sbio,sbuf,BUFSIZZ); } for (;;) { FD_ZERO(&readfds); FD_ZERO(&writefds); if (SSL_in_init(con) && !SSL_total_renegotiations(con)) { in_init=1; tty_on=0; } else { tty_on=1; if (in_init) { in_init=0; print_stuff(bio_c_out,con,full_log); if (full_log > 0) full_log--; if (starttls_proto) { BIO_printf(bio_err,"%s",mbuf); /* We don't need to know any more */ starttls_proto = PROTO_OFF; } if (reconnect) { reconnect--; BIO_printf(bio_c_out,"drop connection and then reconnect\n"); SSL_shutdown(con); SSL_set_connect_state(con); SHUTDOWN(SSL_get_fd(con)); goto re_start; } } } ssl_pending = read_ssl && SSL_pending(con); if (!ssl_pending) { #if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_NETWARE) if (tty_on) { if (read_tty) FD_SET(fileno(stdin),&readfds); if (write_tty) FD_SET(fileno(stdout),&writefds); } if (read_ssl) FD_SET(SSL_get_fd(con),&readfds); if (write_ssl) FD_SET(SSL_get_fd(con),&writefds); #else if(!tty_on || !write_tty) { if (read_ssl) FD_SET(SSL_get_fd(con),&readfds); if (write_ssl) FD_SET(SSL_get_fd(con),&writefds); } #endif /* printf("mode tty(%d %d%d) ssl(%d%d)\n", tty_on,read_tty,write_tty,read_ssl,write_ssl);*/ /* Note: under VMS with SOCKETSHR the second parameter * is currently of type (int *) whereas under other * systems it is (void *) if you don't have a cast it * will choke the compiler: if you do have a cast then * you can either go for (int *) or (void *). */ #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) /* Under Windows/DOS we make the assumption that we can * always write to the tty: therefore if we need to * write to the tty we just fall through. Otherwise * we timeout the select every second and see if there * are any keypresses. Note: this is a hack, in a proper * Windows application we wouldn't do this. */ i=0; if(!write_tty) { if(read_tty) { tv.tv_sec = 1; tv.tv_usec = 0; i=select(width,(void *)&readfds,(void *)&writefds, NULL,&tv); #if defined(OPENSSL_SYS_WINCE) || defined(OPENSSL_SYS_MSDOS) if(!i && (!_kbhit() || !read_tty) ) continue; #else if(!i && (!((_kbhit()) || (WAIT_OBJECT_0 == WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), 0))) || !read_tty) ) continue; #endif } else i=select(width,(void *)&readfds,(void *)&writefds, NULL,NULL); } #elif defined(OPENSSL_SYS_NETWARE) if(!write_tty) { if(read_tty) { tv.tv_sec = 1; tv.tv_usec = 0; i=select(width,(void *)&readfds,(void *)&writefds, NULL,&tv); } else i=select(width,(void *)&readfds,(void *)&writefds, NULL,NULL); } #else i=select(width,(void *)&readfds,(void *)&writefds, NULL,NULL); #endif if ( i < 0) { BIO_printf(bio_err,"bad select %d\n", get_last_socket_error()); goto shut; /* goto end; */ } } if (!ssl_pending && FD_ISSET(SSL_get_fd(con),&writefds)) { k=SSL_write(con,&(cbuf[cbuf_off]), (unsigned int)cbuf_len); switch (SSL_get_error(con,k)) { case SSL_ERROR_NONE: cbuf_off+=k; cbuf_len-=k; if (k <= 0) goto end; /* we have done a write(con,NULL,0); */ if (cbuf_len <= 0) { read_tty=1; write_ssl=0; } else /* if (cbuf_len > 0) */ { read_tty=0; write_ssl=1; } break; case SSL_ERROR_WANT_WRITE: BIO_printf(bio_c_out,"write W BLOCK\n"); write_ssl=1; read_tty=0; break; case SSL_ERROR_WANT_READ: BIO_printf(bio_c_out,"write R BLOCK\n"); write_tty=0; read_ssl=1; write_ssl=0; break; case SSL_ERROR_WANT_X509_LOOKUP: BIO_printf(bio_c_out,"write X BLOCK\n"); break; case SSL_ERROR_ZERO_RETURN: if (cbuf_len != 0) { BIO_printf(bio_c_out,"shutdown\n"); goto shut; } else { read_tty=1; write_ssl=0; break; } case SSL_ERROR_SYSCALL: if ((k != 0) || (cbuf_len != 0)) { BIO_printf(bio_err,"write:errno=%d\n", get_last_socket_error()); goto shut; } else { read_tty=1; write_ssl=0; } break; case SSL_ERROR_SSL: ERR_print_errors(bio_err); goto shut; } } #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE) /* Assume Windows/DOS can always write */ else if (!ssl_pending && write_tty) #else else if (!ssl_pending && FD_ISSET(fileno(stdout),&writefds)) #endif { #ifdef CHARSET_EBCDIC ascii2ebcdic(&(sbuf[sbuf_off]),&(sbuf[sbuf_off]),sbuf_len); #endif i=write(fileno(stdout),&(sbuf[sbuf_off]),sbuf_len); if (i <= 0) { BIO_printf(bio_c_out,"DONE\n"); goto shut; /* goto end; */ } sbuf_len-=i;; sbuf_off+=i; if (sbuf_len <= 0) { read_ssl=1; write_tty=0; } } else if (ssl_pending || FD_ISSET(SSL_get_fd(con),&readfds)) { #ifdef RENEG { static int iiii; if (++iiii == 52) { SSL_renegotiate(con); iiii=0; } } #endif #if 1 k=SSL_read(con,sbuf,1024 /* BUFSIZZ */ ); #else /* Demo for pending and peek :-) */ k=SSL_read(con,sbuf,16); { char zbuf[10240]; printf("read=%d pending=%d peek=%d\n",k,SSL_pending(con),SSL_peek(con,zbuf,10240)); } #endif switch (SSL_get_error(con,k)) { case SSL_ERROR_NONE: if (k <= 0) goto end; sbuf_off=0; sbuf_len=k; read_ssl=0; write_tty=1; break; case SSL_ERROR_WANT_WRITE: BIO_printf(bio_c_out,"read W BLOCK\n"); write_ssl=1; read_tty=0; break; case SSL_ERROR_WANT_READ: BIO_printf(bio_c_out,"read R BLOCK\n"); write_tty=0; read_ssl=1; if ((read_tty == 0) && (write_ssl == 0)) write_ssl=1; break; case SSL_ERROR_WANT_X509_LOOKUP: BIO_printf(bio_c_out,"read X BLOCK\n"); break; case SSL_ERROR_SYSCALL: BIO_printf(bio_err,"read:errno=%d\n",get_last_socket_error()); goto shut; case SSL_ERROR_ZERO_RETURN: BIO_printf(bio_c_out,"closed\n"); goto shut; case SSL_ERROR_SSL: ERR_print_errors(bio_err); goto shut; /* break; */ } } #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) #if defined(OPENSSL_SYS_WINCE) || defined(OPENSSL_SYS_MSDOS) else if (_kbhit()) #else else if ((_kbhit()) || (WAIT_OBJECT_0 == WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), 0))) #endif #elif defined (OPENSSL_SYS_NETWARE) else if (_kbhit()) #else else if (FD_ISSET(fileno(stdin),&readfds)) #endif { if (crlf) { int j, lf_num; i=read(fileno(stdin),cbuf,BUFSIZZ/2); lf_num = 0; /* both loops are skipped when i <= 0 */ for (j = 0; j < i; j++) if (cbuf[j] == '\n') lf_num++; for (j = i-1; j >= 0; j--) { cbuf[j+lf_num] = cbuf[j]; if (cbuf[j] == '\n') { lf_num--; i++; cbuf[j+lf_num] = '\r'; } } assert(lf_num == 0); } else i=read(fileno(stdin),cbuf,BUFSIZZ); if ((!c_ign_eof) && ((i <= 0) || (cbuf[0] == 'Q'))) { BIO_printf(bio_err,"DONE\n"); goto shut; } if ((!c_ign_eof) && (cbuf[0] == 'R')) { BIO_printf(bio_err,"RENEGOTIATING\n"); SSL_renegotiate(con); cbuf_len=0; } else { cbuf_len=i; cbuf_off=0; #ifdef CHARSET_EBCDIC ebcdic2ascii(cbuf, cbuf, i); #endif } write_ssl=1; read_tty=0; } } shut: SSL_shutdown(con); SHUTDOWN(SSL_get_fd(con)); ret=0; end: if(prexit) print_stuff(bio_c_out,con,1); if (con != NULL) SSL_free(con); if (con2 != NULL) SSL_free(con2); if (ctx != NULL) SSL_CTX_free(ctx); if (cert) X509_free(cert); if (key) EVP_PKEY_free(key); if (pass) OPENSSL_free(pass); if (cbuf != NULL) { OPENSSL_cleanse(cbuf,BUFSIZZ); OPENSSL_free(cbuf); } if (sbuf != NULL) { OPENSSL_cleanse(sbuf,BUFSIZZ); OPENSSL_free(sbuf); } if (mbuf != NULL) { OPENSSL_cleanse(mbuf,BUFSIZZ); OPENSSL_free(mbuf); } if (bio_c_out != NULL) { BIO_free(bio_c_out); bio_c_out=NULL; } apps_shutdown(); OPENSSL_EXIT(ret); }
/* Create a socket and connect it to 'ip' on port 'port'. * Returns -1 on failure (ip is NULL, socket creation/connection error) * Returns sock number on success. */ int _mosquitto_socket_connect(struct mosquitto *mosq, const char *host, uint16_t port, const char *bind_address, bool blocking) { mosq_sock_t sock = INVALID_SOCKET; int rc; #ifdef WITH_TLS int ret; BIO *bio; #endif if(!mosq || !host || !port) return MOSQ_ERR_INVAL; rc = _mosquitto_try_connect(mosq, host, port, &sock, bind_address, blocking); if(rc > 0) return rc; #ifdef WITH_TLS if(mosq->tls_cafile || mosq->tls_capath || mosq->tls_psk){ #if OPENSSL_VERSION_NUMBER >= 0x10001000L if(!mosq->tls_version || !strcmp(mosq->tls_version, "tlsv1.2")){ mosq->ssl_ctx = SSL_CTX_new(TLSv1_2_client_method()); }else if(!strcmp(mosq->tls_version, "tlsv1.1")){ mosq->ssl_ctx = SSL_CTX_new(TLSv1_1_client_method()); }else if(!strcmp(mosq->tls_version, "tlsv1")){ mosq->ssl_ctx = SSL_CTX_new(TLSv1_client_method()); }else{ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Protocol %s not supported.", mosq->tls_version); COMPAT_CLOSE(sock); return MOSQ_ERR_INVAL; } #else if(!mosq->tls_version || !strcmp(mosq->tls_version, "tlsv1")){ mosq->ssl_ctx = SSL_CTX_new(TLSv1_client_method()); }else{ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Protocol %s not supported.", mosq->tls_version); COMPAT_CLOSE(sock); return MOSQ_ERR_INVAL; } #endif if(!mosq->ssl_ctx){ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to create TLS context."); COMPAT_CLOSE(sock); return MOSQ_ERR_TLS; } #if OPENSSL_VERSION_NUMBER >= 0x10000000 /* Disable compression */ SSL_CTX_set_options(mosq->ssl_ctx, SSL_OP_NO_COMPRESSION); #endif #ifdef SSL_MODE_RELEASE_BUFFERS /* Use even less memory per SSL connection. */ SSL_CTX_set_mode(mosq->ssl_ctx, SSL_MODE_RELEASE_BUFFERS); #endif if(mosq->tls_ciphers){ ret = SSL_CTX_set_cipher_list(mosq->ssl_ctx, mosq->tls_ciphers); if(ret == 0){ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to set TLS ciphers. Check cipher list \"%s\".", mosq->tls_ciphers); COMPAT_CLOSE(sock); return MOSQ_ERR_TLS; } } if(mosq->tls_cafile || mosq->tls_capath){ ret = SSL_CTX_load_verify_locations(mosq->ssl_ctx, mosq->tls_cafile, mosq->tls_capath); if(ret == 0){ #ifdef WITH_BROKER if(mosq->tls_cafile && mosq->tls_capath){ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_cafile \"%s\" and bridge_capath \"%s\".", mosq->tls_cafile, mosq->tls_capath); }else if(mosq->tls_cafile){ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_cafile \"%s\".", mosq->tls_cafile); }else{ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_capath \"%s\".", mosq->tls_capath); } #else if(mosq->tls_cafile && mosq->tls_capath){ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check cafile \"%s\" and capath \"%s\".", mosq->tls_cafile, mosq->tls_capath); }else if(mosq->tls_cafile){ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check cafile \"%s\".", mosq->tls_cafile); }else{ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check capath \"%s\".", mosq->tls_capath); } #endif COMPAT_CLOSE(sock); return MOSQ_ERR_TLS; } if(mosq->tls_cert_reqs == 0){ SSL_CTX_set_verify(mosq->ssl_ctx, SSL_VERIFY_NONE, NULL); }else{ SSL_CTX_set_verify(mosq->ssl_ctx, SSL_VERIFY_PEER, _mosquitto_server_certificate_verify); } if(mosq->tls_pw_callback){ SSL_CTX_set_default_passwd_cb(mosq->ssl_ctx, mosq->tls_pw_callback); SSL_CTX_set_default_passwd_cb_userdata(mosq->ssl_ctx, mosq); } if(mosq->tls_certfile){ ret = SSL_CTX_use_certificate_chain_file(mosq->ssl_ctx, mosq->tls_certfile); if(ret != 1){ #ifdef WITH_BROKER _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load client certificate, check bridge_certfile \"%s\".", mosq->tls_certfile); #else _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load client certificate \"%s\".", mosq->tls_certfile); #endif COMPAT_CLOSE(sock); return MOSQ_ERR_TLS; } } if(mosq->tls_keyfile){ ret = SSL_CTX_use_PrivateKey_file(mosq->ssl_ctx, mosq->tls_keyfile, SSL_FILETYPE_PEM); if(ret != 1){ #ifdef WITH_BROKER _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load client key file, check bridge_keyfile \"%s\".", mosq->tls_keyfile); #else _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load client key file \"%s\".", mosq->tls_keyfile); #endif COMPAT_CLOSE(sock); return MOSQ_ERR_TLS; } ret = SSL_CTX_check_private_key(mosq->ssl_ctx); if(ret != 1){ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Client certificate/key are inconsistent."); COMPAT_CLOSE(sock); return MOSQ_ERR_TLS; } } #ifdef REAL_WITH_TLS_PSK }else if(mosq->tls_psk){ SSL_CTX_set_psk_client_callback(mosq->ssl_ctx, psk_client_callback); #endif } mosq->ssl = SSL_new(mosq->ssl_ctx); if(!mosq->ssl){ COMPAT_CLOSE(sock); return MOSQ_ERR_TLS; } SSL_set_ex_data(mosq->ssl, tls_ex_index_mosq, mosq); bio = BIO_new_socket(sock, BIO_NOCLOSE); if(!bio){ COMPAT_CLOSE(sock); return MOSQ_ERR_TLS; } SSL_set_bio(mosq->ssl, bio, bio); mosq->sock = sock; if(mosquitto__socket_connect_tls(mosq)){ return MOSQ_ERR_TLS; } } #endif mosq->sock = sock; return rc; }
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_uint_value(conf->verify, prev->verify, 0); ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1); ngx_conf_merge_ptr_value(conf->certificates, prev->certificates, NULL); ngx_conf_merge_ptr_value(conf->certificate_keys, prev->certificate_keys, NULL); 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->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); conf->ssl.log = cf->log; if (conf->certificates == NULL) { return NGX_CONF_OK; } if (conf->certificate_keys == NULL || conf->certificate_keys->nelts < conf->certificates->nelts) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined " "for certificate \"%V\"", ((ngx_str_t *) conf->certificates->elts) + conf->certificates->nelts - 1); 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_certificates(cf, &conf->ssl, conf->certificates, conf->certificate_keys, conf->passwords) != NGX_OK) { return NGX_CONF_ERROR; } if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers, conf->prefer_server_ciphers) != NGX_OK) { 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 (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; }
int s_time_main(int argc, char **argv) { char buf[1024 * 8]; SSL *scon = NULL; SSL_CTX *ctx = NULL; const SSL_METHOD *meth = NULL; char *CApath = NULL, *CAfile = NULL, *cipher = NULL, *ciphersuites = NULL; char *www_path = NULL; char *host = SSL_CONNECT_NAME, *certfile = NULL, *keyfile = NULL, *prog; double totalTime = 0.0; int noCApath = 0, noCAfile = 0; int maxtime = SECONDS, nConn = 0, perform = 3, ret = 1, i, st_bugs = 0; long bytes_read = 0, finishtime = 0; OPTION_CHOICE o; int max_version = 0, ver, buf_len; size_t buf_size; meth = TLS_client_method(); prog = opt_init(argc, argv, s_time_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { case OPT_EOF: case OPT_ERR: opthelp: BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); goto end; case OPT_HELP: opt_help(s_time_options); ret = 0; goto end; case OPT_CONNECT: host = opt_arg(); break; case OPT_REUSE: perform = 2; break; case OPT_NEW: perform = 1; break; case OPT_VERIFY: if (!opt_int(opt_arg(), &verify_args.depth)) goto opthelp; BIO_printf(bio_err, "%s: verify depth is %d\n", prog, verify_args.depth); break; case OPT_CERT: certfile = opt_arg(); break; case OPT_NAMEOPT: if (!set_nameopt(opt_arg())) goto end; break; case OPT_KEY: keyfile = opt_arg(); break; case OPT_CAPATH: CApath = opt_arg(); break; case OPT_CAFILE: CAfile = opt_arg(); break; case OPT_NOCAPATH: noCApath = 1; break; case OPT_NOCAFILE: noCAfile = 1; break; case OPT_CIPHER: cipher = opt_arg(); break; case OPT_CIPHERSUITES: ciphersuites = opt_arg(); break; case OPT_BUGS: st_bugs = 1; break; case OPT_TIME: if (!opt_int(opt_arg(), &maxtime)) goto opthelp; break; case OPT_WWW: www_path = opt_arg(); buf_size = strlen(www_path) + fmt_http_get_cmd_size; if (buf_size > sizeof(buf)) { BIO_printf(bio_err, "%s: -www option is too long\n", prog); goto end; } break; case OPT_SSL3: max_version = SSL3_VERSION; break; } } argc = opt_num_rest(); if (argc != 0) goto opthelp; if (cipher == NULL) cipher = getenv("SSL_CIPHER"); if ((ctx = SSL_CTX_new(meth)) == NULL) goto end; SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); SSL_CTX_set_quiet_shutdown(ctx, 1); if (SSL_CTX_set_max_proto_version(ctx, max_version) == 0) goto end; if (st_bugs) SSL_CTX_set_options(ctx, SSL_OP_ALL); if (cipher != NULL && !SSL_CTX_set_cipher_list(ctx, cipher)) goto end; if (ciphersuites != NULL && !SSL_CTX_set_ciphersuites(ctx, ciphersuites)) goto end; if (!set_cert_stuff(ctx, certfile, keyfile)) goto end; if (!ctx_set_verify_locations(ctx, CAfile, CApath, noCAfile, noCApath)) { ERR_print_errors(bio_err); goto end; } if (!(perform & 1)) goto next; printf("Collecting connection statistics for %d seconds\n", maxtime); /* Loop and time how long it takes to make connections */ bytes_read = 0; finishtime = (long)time(NULL) + maxtime; tm_Time_F(START); for (;;) { if (finishtime < (long)time(NULL)) break; if ((scon = doConnection(NULL, host, ctx)) == NULL) goto end; if (www_path != NULL) { buf_len = BIO_snprintf(buf, sizeof(buf), fmt_http_get_cmd, www_path); if (buf_len <= 0 || SSL_write(scon, buf, buf_len) <= 0) goto end; while ((i = SSL_read(scon, buf, sizeof(buf))) > 0) bytes_read += i; } SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); BIO_closesocket(SSL_get_fd(scon)); nConn += 1; if (SSL_session_reused(scon)) { ver = 'r'; } else { ver = SSL_version(scon); if (ver == TLS1_VERSION) ver = 't'; else if (ver == SSL3_VERSION) ver = '3'; else ver = '*'; } fputc(ver, stdout); fflush(stdout); SSL_free(scon); scon = NULL; } totalTime += tm_Time_F(STOP); /* Add the time for this iteration */ i = (int)((long)time(NULL) - finishtime + maxtime); printf ("\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n", nConn, totalTime, ((double)nConn / totalTime), bytes_read); printf ("%d connections in %ld real seconds, %ld bytes read per connection\n", nConn, (long)time(NULL) - finishtime + maxtime, bytes_read / nConn); /* * Now loop and time connections using the same session id over and over */ next: if (!(perform & 2)) goto end; printf("\n\nNow timing with session id reuse.\n"); /* Get an SSL object so we can reuse the session id */ if ((scon = doConnection(NULL, host, ctx)) == NULL) { BIO_printf(bio_err, "Unable to get connection\n"); goto end; } if (www_path != NULL) { buf_len = BIO_snprintf(buf, sizeof(buf), fmt_http_get_cmd, www_path); if (buf_len <= 0 || SSL_write(scon, buf, buf_len) <= 0) goto end; while ((i = SSL_read(scon, buf, sizeof(buf))) > 0) continue; } SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); BIO_closesocket(SSL_get_fd(scon)); nConn = 0; totalTime = 0.0; finishtime = (long)time(NULL) + maxtime; printf("starting\n"); bytes_read = 0; tm_Time_F(START); for (;;) { if (finishtime < (long)time(NULL)) break; if ((doConnection(scon, host, ctx)) == NULL) goto end; if (www_path != NULL) { buf_len = BIO_snprintf(buf, sizeof(buf), fmt_http_get_cmd, www_path); if (buf_len <= 0 || SSL_write(scon, buf, buf_len) <= 0) goto end; while ((i = SSL_read(scon, buf, sizeof(buf))) > 0) bytes_read += i; } SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); BIO_closesocket(SSL_get_fd(scon)); nConn += 1; if (SSL_session_reused(scon)) { ver = 'r'; } else { ver = SSL_version(scon); if (ver == TLS1_VERSION) ver = 't'; else if (ver == SSL3_VERSION) ver = '3'; else ver = '*'; } fputc(ver, stdout); fflush(stdout); } totalTime += tm_Time_F(STOP); /* Add the time for this iteration */ printf ("\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n", nConn, totalTime, ((double)nConn / totalTime), bytes_read); printf ("%d connections in %ld real seconds, %ld bytes read per connection\n", nConn, (long)time(NULL) - finishtime + maxtime, bytes_read / nConn); ret = 0; end: SSL_free(scon); SSL_CTX_free(ctx); return ret; }