/* {{{ proto string connect() Connection apple apple_push service */ PHP_METHOD(apple_push, init) { zend_class_entry * _this_ce; zval * _this_zval = NULL; const char * x = NULL; int x_len = 0; const char * y = NULL; int y_len = 0; BIO *bio; SSL_CTX *ssl_ctx; SSL_library_init(); char *certificate_dir,*passphraseStr,*gatewayurl; zval *certificate = zend_read_static_property(apple_push_ce_ptr, ZEND_STRL("certificate"), sizeof ("certificate")); spprintf(&certificate_dir, 0, "%s", Z_STRVAL_P(certificate)); zval *passphrase = zend_read_static_property(apple_push_ce_ptr, ZEND_STRL("passphrase"), sizeof ("passphrase")); spprintf(&passphraseStr, 0, "%s", Z_STRVAL_P(passphrase)); zval *gateway = zend_read_static_property(apple_push_ce_ptr, ZEND_STRL("gateway"), sizeof ("gateway")); spprintf(&gatewayurl, 0, "%s", Z_STRVAL_P(gateway)); ssl_ctx = SSL_CTX_new(SSLv23_method()); if (ssl_ctx == NULL) { zend_throw_exception_ex(apple_push_ce_ptr, 0 TSRMLS_CC, "SSL_INIT_FAIL", 2 TSRMLS_CC); return ; } if (SSL_CTX_use_certificate_chain_file(ssl_ctx, certificate_dir) != 1) { zend_throw_exception_ex(apple_push_ce_ptr, 0 TSRMLS_CC, "CERTIFICATE_NOT_FOUNT", 2 TSRMLS_CC); return ; } SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx,passphraseStr); if (SSL_CTX_use_PrivateKey_file(ssl_ctx, certificate_dir, SSL_FILETYPE_PEM) != 1) { zend_throw_exception_ex(apple_push_ce_ptr, 0 TSRMLS_CC, "CERTIFICATE_PASSWORD_FAIL", 2 TSRMLS_CC); return ; } bio = BIO_new_connect(gatewayurl); if(!bio) { zend_throw_exception_ex(apple_push_ce_ptr, 0 TSRMLS_CC, "SSL_CONNECT_FAIL", 2 TSRMLS_CC); return ; } if (BIO_do_connect(bio) <= 0) { zend_throw_exception_ex(apple_push_ce_ptr, 0 TSRMLS_CC, "SSL_CONNECT_FAIL", 2 TSRMLS_CC); return ; } if (!(ssl = SSL_new(ssl_ctx))) { zend_throw_exception_ex(apple_push_ce_ptr, 0 TSRMLS_CC, "SSL_CONNECT_FAIL", 2 TSRMLS_CC); return ; } SSL_set_bio(ssl, bio, bio); if (SSL_connect(ssl) <= 0) { zend_throw_exception_ex(apple_push_ce_ptr, 0 TSRMLS_CC, "SSL_CONNECT_FAIL", 2 TSRMLS_CC); return ; } RETURN_TRUE; }
static int build_ssl_ctx(void) { SSL_DATA *ssl; /* Library initialization */ SSL_library_init(); SSL_load_error_strings(); bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); if (!check_data->ssl) ssl = (SSL_DATA *) MALLOC(sizeof (ssl_data)); else ssl = check_data->ssl; /* Initialize SSL context for SSL v2/3 */ ssl->meth = SSLv23_method(); ssl->ctx = SSL_CTX_new(ssl->meth); /* return for autogen context */ if (!check_data->ssl) { check_data->ssl = ssl; goto end; } /* Load our keys and certificates */ if (check_data->ssl->keyfile) if (! (SSL_CTX_use_certificate_chain_file (ssl->ctx, check_data->ssl->keyfile))) { log_message(LOG_INFO, "SSL error : Cant load certificate file..."); return 0; } /* Handle password callback using userdata ssl */ if (check_data->ssl->password) { SSL_CTX_set_default_passwd_cb_userdata(ssl->ctx, check_data->ssl); SSL_CTX_set_default_passwd_cb(ssl->ctx, password_cb); } if (check_data->ssl->keyfile) if (! (SSL_CTX_use_PrivateKey_file (ssl->ctx, check_data->ssl->keyfile, SSL_FILETYPE_PEM))) { log_message(LOG_INFO, "SSL error : Cant load key file..."); return 0; } /* Load the CAs we trust */ if (check_data->ssl->cafile) if (! (SSL_CTX_load_verify_locations (ssl->ctx, check_data->ssl->cafile, 0))) { log_message(LOG_INFO, "SSL error : Cant load CA file..."); return 0; } end: #if (OPENSSL_VERSION_NUMBER < 0x00905100L) SSL_CTX_set_verify_depth(ssl->ctx, 1); #endif return 1; }
SSL *SSLSocket::createSSL(SSL_CTX *ctx) { ERR_clear_error(); /* look at options in the stream and set appropriate verification flags */ if (m_context["verify_peer"].toBoolean()) { /* turn on verification callback */ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback); /* CA stuff */ String cafile = m_context["cafile"]; String capath = m_context["capath"]; if (!cafile.empty() || !capath.empty()) { if (!SSL_CTX_load_verify_locations(ctx, cafile.data(), capath.data())) { raise_warning("Unable to set verify locations `%s' `%s'", cafile.data(), capath.data()); return NULL; } } int64 depth = m_context["verify_depth"].toInt64(); if (depth) { SSL_CTX_set_verify_depth(ctx, depth); } } else { SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); } /* callback for the passphrase (for localcert) */ if (!m_context["passphrase"].toString().empty()) { SSL_CTX_set_default_passwd_cb_userdata(ctx, this); SSL_CTX_set_default_passwd_cb(ctx, passwd_callback); } String cipherlist = m_context["ciphers"].toString(); if (cipherlist.empty()) { cipherlist = "DEFAULT"; } SSL_CTX_set_cipher_list(ctx, cipherlist.data()); String certfile = m_context["local_cert"].toString(); if (!certfile.empty()) { String resolved_path_buff = File::TranslatePath(certfile); if (!resolved_path_buff.empty()) { /* a certificate to use for authentication */ if (SSL_CTX_use_certificate_chain_file(ctx, resolved_path_buff.data()) != 1) { raise_warning("Unable to set local cert chain file `%s'; Check " "that your cafile/capath settings include details of " "your certificate and its issuer", certfile.data()); return NULL; } if (SSL_CTX_use_PrivateKey_file(ctx, resolved_path_buff.data(), SSL_FILETYPE_PEM) != 1) { raise_warning("Unable to set private key file `%s'", resolved_path_buff.data()); return NULL; } SSL *tmpssl = SSL_new(ctx); X509 *cert = SSL_get_certificate(tmpssl); if (cert) { EVP_PKEY *key = X509_get_pubkey(cert); EVP_PKEY_copy_parameters(key, SSL_get_privatekey(tmpssl)); EVP_PKEY_free(key); } SSL_free(tmpssl); if (!SSL_CTX_check_private_key(ctx)) { raise_warning("Private key does not match certificate!"); } } } SSL *ssl = SSL_new(ctx); if (ssl) { SSL_set_ex_data(ssl, GetSSLExDataIndex(), this); /* map SSL => stream */ } return ssl; }
int CSSLClient::SSLConnect(SWL_socket_t sockfd, bool bVerifyPeer, const char *pHost, const char *pCertFile, \ const char *pPriteKeyFile, const char *pCAPath, const char *pCAFile, const char *pPassWd) { s_Lock.Lock(); if (!s_bHasInitial) { printf("ssl not initial\n"); s_Lock.UnLock(); return -1; } s_Lock.UnLock(); if (pCertFile!=NULL && pPriteKeyFile!=NULL) { if (pCAPath) { if(SSL_CTX_load_verify_locations(s_SSLCTX, pCAFile, NULL) <= 0) { printf("Failed to set CA location...\n"); return -1; } } if (SSL_CTX_use_certificate_file(s_SSLCTX, pCertFile, SSL_FILETYPE_PEM) <= 0) { printf("%s %s %d failed\n", __FILE__, __FUNCTION__, __LINE__); int errNum = ERR_get_error(); printf("%s:%s:%d, ssl connect error:%s\n", __FUNCTION__, __FILE__, __LINE__, ERR_reason_error_string(errNum)); printf("%s:%s:%d, error function=%s\n", __FUNCTION__, __FILE__, __LINE__, ERR_func_error_string(errNum)); return -1; } if (pPassWd) { SSL_CTX_set_default_passwd_cb_userdata(s_SSLCTX, (void*)pPassWd); } if (SSL_CTX_use_PrivateKey_file(s_SSLCTX, pPriteKeyFile, SSL_FILETYPE_PEM) <= 0) { printf("%s %s %d failed\n", __FILE__, __FUNCTION__, __LINE__); int errNum = ERR_get_error(); printf("%s:%s:%d, ssl connect error:%s\n", __FUNCTION__, __FILE__, __LINE__, ERR_reason_error_string(errNum)); printf("%s:%s:%d, error function=%s\n", __FUNCTION__, __FILE__, __LINE__, ERR_func_error_string(errNum)); return -1; } if (!SSL_CTX_check_private_key(s_SSLCTX)) { printf("%s %s %d failed\n", __FILE__, __FUNCTION__, __LINE__); int errNum = ERR_get_error(); printf("%s:%s:%d, ssl connect error:%s\n", __FUNCTION__, __FILE__, __LINE__, ERR_reason_error_string(errNum)); printf("%s:%s:%d, error function=%s\n", __FUNCTION__, __FILE__, __LINE__, ERR_func_error_string(errNum)); return -1; } } if (NULL == m_pSSL) { if (bVerifyPeer) { SSL_CTX_set_verify(s_SSLCTX, SSL_VERIFY_PEER, VerifyCallBack); } m_pSSL = SSL_new(s_SSLCTX); if (NULL == m_pSSL) { printf("ssl new err\n"); return -1; } } if (1 != SSL_set_fd(m_pSSL, sockfd)) { int errNum = ERR_get_error(); printf("%s:%s:%d, ssl connect error:%s\n", __FUNCTION__, __FILE__, __LINE__, ERR_reason_error_string(errNum)); printf("%s:%s:%d, error function=%s\n", __FUNCTION__, __FILE__, __LINE__, ERR_func_error_string(errNum)); return -1; } SSL_set_connect_state(m_pSSL); unsigned long reTry = 0; int ret = 0, err = 0; while(reTry++ < SSL_SOCKET_CONNECT_RETRIES) { if((ret = SSL_connect(m_pSSL)) == 1) { break; } err = SSL_get_error(m_pSSL, ret); if(SSL_ERROR_WANT_CONNECT == err || SSL_ERROR_WANT_READ == err || SSL_ERROR_WANT_WRITE == err) { PUB_Sleep(10); // wait a while } else { printf("SSL_connect Err : %d\n", err); int errNum = ERR_get_error(); printf("%s:%s:%d, ssl connect error:%s\n", __FUNCTION__, __FILE__, __LINE__, ERR_reason_error_string(errNum)); printf("%s:%s:%d, error function=%s\n", __FUNCTION__, __FILE__, __LINE__, ERR_func_error_string(errNum)); FreeRsource(); return -1; } } if (reTry >= SSL_SOCKET_CONNECT_RETRIES) { printf("reTry >= SSL_SOCKET_CONNECT_RETRIES\n"); FreeRsource(); return -1; } if (pHost) { if (PostConnectCheck(m_pSSL, pHost) < 0) { return -1; } } return 0; }
BOOL CSSLContext::LoadCertAndKey(SSL_CTX* sslCtx, int iVerifyMode, LPCTSTR lpszPemCertFile, LPCTSTR lpszPemKeyFile, LPCTSTR lpszKeyPasswod, LPCTSTR lpszCAPemCertFileOrPath) { USES_CONVERSION; if(lpszCAPemCertFileOrPath != nullptr) { LPCTSTR lpszCAPemCertFile = nullptr; LPCTSTR lpszCAPemCertPath = nullptr; if(!ATLPath::FileExists(lpszCAPemCertFileOrPath)) { ::SetLastError(ERROR_FILE_NOT_FOUND); return FALSE; } if(!ATLPath::IsDirectory(lpszCAPemCertFileOrPath)) lpszCAPemCertFile = lpszCAPemCertFileOrPath; else lpszCAPemCertPath = lpszCAPemCertFileOrPath; if(!SSL_CTX_load_verify_locations(sslCtx, T2CA(lpszCAPemCertFile), T2CA(lpszCAPemCertPath))) { ::SetLastError(ERROR_INVALID_DATA); return FALSE; } if(!SSL_CTX_set_default_verify_paths(sslCtx)) { ::SetLastError(ERROR_FUNCTION_FAILED); return FALSE; } if(m_enSessionMode == SSL_SM_SERVER && iVerifyMode & SSL_VM_PEER) { STACK_OF(X509_NAME)* caCertNames = SSL_load_client_CA_file(T2CA(lpszCAPemCertFileOrPath)); if(caCertNames == nullptr) { ::SetLastError(ERROR_EMPTY); return FALSE; } SSL_CTX_set_client_CA_list(sslCtx, caCertNames); } } if(lpszPemCertFile != nullptr) { if( !ATLPath::FileExists(lpszPemCertFile) || ATLPath::IsDirectory(lpszPemCertFile) ) { ::SetLastError(ERROR_FILE_NOT_FOUND); return FALSE; } if( lpszPemKeyFile == nullptr || !ATLPath::FileExists(lpszPemKeyFile) || ATLPath::IsDirectory(lpszPemKeyFile) ) { ::SetLastError(ERROR_FILE_NOT_FOUND); return FALSE; } if(lpszKeyPasswod != nullptr) SSL_CTX_set_default_passwd_cb_userdata(sslCtx, (void*)T2CA(lpszKeyPasswod)); if(!SSL_CTX_use_PrivateKey_file(sslCtx, T2CA(lpszPemKeyFile), SSL_FILETYPE_PEM)) { ::SetLastError(ERROR_INVALID_PASSWORD); return FALSE; } if(!SSL_CTX_use_certificate_chain_file(sslCtx, T2CA(lpszPemCertFile))) { ::SetLastError(ERROR_INVALID_DATA); return FALSE; } if(!SSL_CTX_check_private_key(sslCtx)) { ::SetLastError(ERROR_INVALID_ACCESS); return FALSE; } } return TRUE; }
BOOL connect_ssl(int sockfd, const char* ca_crt_root, const char* ca_crt_client, const char* ca_password, const char* ca_key_client, SSL** pp_ssl, SSL_CTX** pp_ssl_ctx) { SSL_METHOD* meth = NULL; #if OPENSSL_VERSION_NUMBER >= 0x010100000L meth = (SSL_METHOD*)TLS_client_method(); #else meth = (SSL_METHOD*)SSLv23_client_method(); #endif /* OPENSSL_VERSION_NUMBER */ *pp_ssl_ctx = SSL_CTX_new(meth); if(!*pp_ssl_ctx) { CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME); uTrace.Write(Trace_Error, "SSL_CTX_new: %s\n", ERR_error_string(ERR_get_error(),NULL)); goto clean_ssl3; } if(ca_crt_root && ca_crt_client && ca_password && ca_key_client) { SSL_CTX_load_verify_locations(*pp_ssl_ctx, ca_crt_root, NULL); if(SSL_CTX_use_certificate_file(*pp_ssl_ctx, ca_crt_client, SSL_FILETYPE_PEM) <= 0) { CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME); uTrace.Write(Trace_Error, "SSL_CTX_use_certificate_file: %s", ERR_error_string(ERR_get_error(),NULL)); goto clean_ssl2; } SSL_CTX_set_default_passwd_cb_userdata(*pp_ssl_ctx, (char*)ca_password); if(SSL_CTX_use_PrivateKey_file(*pp_ssl_ctx, ca_key_client, SSL_FILETYPE_PEM) <= 0) { CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME); uTrace.Write(Trace_Error, "SSL_CTX_use_certificate_file: %s", ERR_error_string(ERR_get_error(),NULL)); goto clean_ssl2; } if(!SSL_CTX_check_private_key(*pp_ssl_ctx)) { CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME); uTrace.Write(Trace_Error, "SSL_CTX_use_certificate_file: %s", ERR_error_string(ERR_get_error(),NULL)); goto clean_ssl2; } } *pp_ssl = SSL_new(*pp_ssl_ctx); if(!*pp_ssl) { CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME); uTrace.Write(Trace_Error, "SSL_new: %s\n", ERR_error_string(ERR_get_error(),NULL)); goto clean_ssl2; } if(SSL_set_fd(*pp_ssl, sockfd) <= 0) { CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME); uTrace.Write(Trace_Error, "SSL_set_fd: %s\n", ERR_error_string(ERR_get_error(),NULL)); goto clean_ssl1; } if(SSL_connect(*pp_ssl) <= 0) { CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME); uTrace.Write(Trace_Error, "SSL_connect: %s\n", ERR_error_string(ERR_get_error(),NULL)); goto clean_ssl1; } return TRUE; clean_ssl1: if(*pp_ssl) { SSL_free(*pp_ssl); *pp_ssl = NULL; } clean_ssl2: if(*pp_ssl_ctx) { SSL_CTX_free(*pp_ssl_ctx); *pp_ssl_ctx = NULL; } clean_ssl3: return FALSE; }
SSL_CTX * tls_init(srv_t * srv) { char path[_POSIX_PATH_MAX]; SSL_CTX *ctx; int r; char errorstr[1024]; unsigned long e; SSL_library_init(); SSL_load_error_strings(); /* basic set up */ OpenSSL_add_ssl_algorithms(); /* * Create a TLS context */ if (!(ctx = SSL_CTX_new(SSLv23_method()))) { LOG(SPOCP_ERR) traceLog(LOG_ERR,"Error allocation SSL_CTX"); return 0; } LOG(SPOCP_DEBUG) traceLog(LOG_DEBUG,"Do we have enough randomness ??"); if (!RAND_status()) { /* * load entropy from files */ add_entropy(srv->SslEntropyFile); add_entropy(RAND_file_name(path, sizeof(path))); /* * load entropy from egd sockets */ #ifdef HAVE_RAND_EGD add_entropy(getenv("EGDSOCKET")); snprintf(path, sizeof(path), "%s/.entropy", NONULL(Homedir)); add_entropy(path); add_entropy("/tmp/entropy"); #endif /* * shuffle $RANDFILE (or ~/.rnd if unset) */ RAND_write_file(RAND_file_name(path, sizeof(path))); if (!RAND_status()) { LOG(SPOCP_ERR) traceLog(LOG_ERR, "Failed to find enough entropy on your system"); return 0; } } /* * Initialize with DH parameters if supplied */ if (srv->dhFile) { if (init_dh(ctx, (unsigned char *) srv->dhFile) == FALSE) { LOG(SPOCP_ERR) traceLog(LOG_ERR,"Error initializing DH"); SSL_CTX_free(ctx); return 0; } else LOG(SPOCP_ERR) traceLog(LOG_ERR,"Initializing DH OK"); } /* * and a RSA key too */ if (generate_eph_rsa_key(ctx, 512) == FALSE) { LOG(SPOCP_ERR) traceLog(LOG_ERR,"Error initializing RSA key"); SSL_CTX_free(ctx); return 0; } else LOG(SPOCP_ERR) traceLog(LOG_ERR,"Initializing RSA key OK"); /* * Set up certificates and keys */ if (srv->certificateFile != NULL) { LOG(SPOCP_INFO) traceLog(LOG_INFO,"Reading Certificate File"); if (!SSL_CTX_use_certificate_chain_file (ctx, srv->certificateFile)) { LOG(SPOCP_ERR) traceLog(LOG_ERR,"Error in SSL_CTX_use_certificate_file"); SSL_CTX_free(ctx); return 0; } } if (srv->privateKey != NULL) { if (srv->passwd) { SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *) srv-> passwd); SSL_CTX_set_default_passwd_cb(ctx, password_cb); } LOG(SPOCP_INFO) traceLog(LOG_INFO,"Reading Private Key File"); r = SSL_CTX_use_PrivateKey_file(ctx, srv->privateKey, SSL_FILETYPE_PEM); if (r == 0) { e = ERR_get_error(); ERR_error_string_n(e, errorstr, 1024); LOG(SPOCP_ERR) traceLog(LOG_ERR,"Error in SSL_CTX_use_PrivateKey_file"); LOG(SPOCP_ERR) traceLog(LOG_ERR,"%s", errorstr); SSL_CTX_free(ctx); return 0; } } if (srv->caList != NULL) { LOG(SPOCP_INFO) traceLog(LOG_INFO,"Reading Trusted CAs File"); if (!SSL_CTX_load_verify_locations(ctx, srv->caList, 0)) { LOG(SPOCP_ERR) traceLog(LOG_ERR,"Error in SSL_CTX_load_verify_locations"); SSL_CTX_free(ctx); return 0; } } if (srv->clientcert == NONE) SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, verify_callback_ok); else { int i = SSL_VERIFY_PEER; if (srv->clientcert == HARD) i |= SSL_VERIFY_CLIENT_ONCE; SSL_CTX_set_verify(ctx, i, verify_callback); } SSL_CTX_set_verify_depth(ctx, srv->sslverifydepth); SSL_CTX_set_options(ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2); if (SSL_CTX_set_cipher_list(ctx, CIPHER_LIST) != 1) { LOG(SPOCP_ERR) traceLog(LOG_ERR,"No valid ciphers in cipherlist"); SSL_CTX_free(ctx); return 0; } LOG(SPOCP_DEBUG) traceLog(LOG_DEBUG,"Initialised TLS"); return ctx; }
IoSecureServer *IoSecureServer_proto(void *state) { initSSL(); IoObject *self = IoObject_new(state); IoObject_tag_(self, IoSecureServer_newTag(state)); IoObject_setDataPointer_(self, (SecureServerData *)calloc(1, sizeof(SecureServerData))); SSL_CTX *ctx = SSL_CTX_new(TLSv1_server_method()); DATA(self)->ssl_ctx = ctx; SSL_CTX_set_default_passwd_cb(ctx, IoSecureSockets_Password_Callback); SSL_CTX_set_default_passwd_cb_userdata(ctx, self); SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, IoSecureSockets_Verify_Callback); #ifdef DTLS_IMPLEMENTED IoObject_setSlot_to_(self, IOSYMBOL("supportsDTLS"), IOTRUE(self)); #else IoObject_setSlot_to_(self, IOSYMBOL("supportsDTLS"), IOFALSE(self)); #endif //doc SecureServer supportsDTLS Returns true if server supports DTLS, false otherwise. IoState_registerProtoWithFunc_((IoState *)state, self, IoSecureServer_proto); { IoMethodTable methodTable[] = { {"setKeyFile", IoSecureServer_setKeyFile}, //doc SecureServer setKeyFile(path) Sets the key file. Returns self. {"setCertFile", IoSecureServer_setCertFile}, //doc SecureServer setCertFile(path) Sets the certificate file. Returns self. {"setCAFile", IoSecureServer_setCAFile}, //doc SecureServer setCAFile(path) Sets the CA file. Returns self. {"setCRLFile", IoSecureServer_setCRLFile}, //doc SecureServer setCRLFile(path) Sets the CRL file. Returns self. {"useTLS", IoSecureServer_useTLS}, //doc SecureServer useTLS Returns useTLS value. {"useDTLS", IoSecureServer_useDTLS}, //doc SecureServer useDTLS Returns useDTLS value. {"setRequiresClientCertificate", IoSecureServer_setRequiresClientCertificate}, //doc SecureServer setRequiresClientCertificate(aBool) Sets the requires client certificate attribute. Returns self. {"tlsWrap", IoSecureServer_tlsWrap}, //doc SecureServer tlsWrap Returns tlsWrap value. #ifdef DTLS_IMPLEMENTED {"dtlsWrap", IoSecureServer_dtlsWrap}, //doc SecureServer dtlsWrap Returns dtlsWrap value. {"udpRecvIP", IoSecureServer_udpRecvIP}, //doc SecureServer udpRecvIP Returns udpRecvIP value. {"dispatchUdp", IoSecureServer_dispatchUDP}, //doc SecureServer dispatchUdp Returns dispatchUdp value. #endif {NULL, NULL} }; IoObject_addMethodTable_(self, methodTable); } return self; }
static int tls_init_context(tls_t *tls, tls_issues_t const *ti) { int verify; static int random_loaded; ONCE_INIT(tls_init_once); if (!random_loaded) { random_loaded = 1; if (ti->randFile && !RAND_load_file(ti->randFile, 1024 * 1024)) { if (ti->configured > 1) { SU_DEBUG_3(("%s: cannot open randFile %s\n", "tls_init_context", ti->randFile)); tls_log_errors(3, "tls_init_context", 0); } /* errno = EIO; */ /* return -1; */ } } #if HAVE_SIGPIPE /* Avoid possible SIGPIPE when sending close_notify */ signal(SIGPIPE, SIG_IGN); #endif if (tls->ctx == NULL) { const SSL_METHOD *meth; /* meth = SSLv3_method(); */ /* meth = SSLv23_method(); */ if (ti->version) meth = TLSv1_method(); else meth = SSLv23_method(); tls->ctx = SSL_CTX_new((SSL_METHOD*)meth); } if (tls->ctx == NULL) { tls_log_errors(1, "tls_init_context", 0); errno = EIO; return -1; } /* Set callback if we have a passphrase */ if (ti->passphrase != NULL) { SSL_CTX_set_default_passwd_cb(tls->ctx, passwd_cb); SSL_CTX_set_default_passwd_cb_userdata(tls->ctx, (void *)ti); } if (!SSL_CTX_use_certificate_file(tls->ctx, ti->cert, SSL_FILETYPE_PEM)) { if (ti->configured > 0) { SU_DEBUG_1(("%s: invalid local certificate: %s\n", "tls_init_context", ti->cert)); tls_log_errors(3, "tls_init_context", 0); #if require_client_certificate errno = EIO; return -1; #endif } } if (!SSL_CTX_use_PrivateKey_file(tls->ctx, ti->key, SSL_FILETYPE_PEM)) { if (ti->configured > 0) { SU_DEBUG_1(("%s: invalid private key: %s\n", "tls_init_context", ti->key)); tls_log_errors(3, "tls_init_context(key)", 0); #if require_client_certificate errno = EIO; return -1; #endif } } if (!SSL_CTX_check_private_key(tls->ctx)) { if (ti->configured > 0) { SU_DEBUG_1(("%s: private key does not match the certificate public key\n", "tls_init_context")); } #if require_client_certificate errno = EIO; return -1; #endif } if (!SSL_CTX_load_verify_locations(tls->ctx, ti->CAfile, ti->CApath)) { SU_DEBUG_1(("%s: error loading CA list: %s\n", "tls_init_context", ti->CAfile)); if (ti->configured > 0) tls_log_errors(3, "tls_init_context(CA)", 0); errno = EIO; return -1; } /* corresponds to (enum tport_tls_verify_policy) */ tls->verify_incoming = (ti->policy & 0x1) ? 1 : 0; tls->verify_outgoing = (ti->policy & 0x2) ? 1 : 0; tls->verify_subj_in = (ti->policy & 0x4) ? tls->verify_incoming : 0; tls->verify_subj_out = (ti->policy & 0x8) ? tls->verify_outgoing : 0; tls->verify_date = (ti->verify_date) ? 1 : 0; if (tls->verify_incoming) verify = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT; else verify = SSL_VERIFY_NONE; SSL_CTX_set_verify_depth(tls->ctx, ti->verify_depth); SSL_CTX_set_verify(tls->ctx, verify, tls_verify_cb); if (!SSL_CTX_set_cipher_list(tls->ctx, ti->cipher)) { SU_DEBUG_1(("%s: error setting cipher list\n", "tls_init_context")); tls_log_errors(3, "tls_init_context", 0); errno = EIO; return -1; } return 0; }
/** * Once per rd_kafka_t handle initialization of OpenSSL * * Locality: application thread * * NOTE: rd_kafka_wrlock() MUST be held */ int rd_kafka_transport_ssl_ctx_init (rd_kafka_t *rk, char *errstr, size_t errstr_size) { int r; SSL_CTX *ctx; call_once(&rd_kafka_ssl_init_once, rd_kafka_transport_ssl_init); ctx = SSL_CTX_new(SSLv23_client_method()); if (!ctx) goto fail; /* Key file password callback */ SSL_CTX_set_default_passwd_cb(ctx, rd_kafka_transport_ssl_passwd_cb); SSL_CTX_set_default_passwd_cb_userdata(ctx, rk); /* Ciphers */ if (rk->rk_conf.ssl.cipher_suites) { rd_kafka_dbg(rk, SECURITY, "SSL", "Setting cipher list: %s", rk->rk_conf.ssl.cipher_suites); if (!SSL_CTX_set_cipher_list(ctx, rk->rk_conf.ssl.cipher_suites)) { rd_snprintf(errstr, errstr_size, "No recognized ciphers"); goto fail; } } if (rk->rk_conf.ssl.ca_location) { /* CA certificate location, either file or directory. */ int is_dir = rd_kafka_path_is_dir(rk->rk_conf.ssl.ca_location); rd_kafka_dbg(rk, SECURITY, "SSL", "Loading CA certificate(s) from %s %s", is_dir ? "directory":"file", rk->rk_conf.ssl.ca_location); r = SSL_CTX_load_verify_locations(ctx, !is_dir ? rk->rk_conf.ssl. ca_location : NULL, is_dir ? rk->rk_conf.ssl. ca_location : NULL); if (r != 1) goto fail; } if (rk->rk_conf.ssl.cert_location) { rd_kafka_dbg(rk, SECURITY, "SSL", "Loading certificate from file %s", rk->rk_conf.ssl.cert_location); r = SSL_CTX_use_certificate_chain_file(ctx, rk->rk_conf.ssl.cert_location); if (r != 1) goto fail; } if (rk->rk_conf.ssl.key_location) { rd_kafka_dbg(rk, SECURITY, "SSL", "Loading private key file from %s", rk->rk_conf.ssl.key_location); r = SSL_CTX_use_PrivateKey_file(ctx, rk->rk_conf.ssl.key_location, SSL_FILETYPE_PEM); if (r != 1) goto fail; } SSL_CTX_set_mode(ctx, SSL_MODE_ENABLE_PARTIAL_WRITE); rk->rk_conf.ssl.ctx = ctx; return 0; fail: rd_kafka_ssl_error(rk, NULL, errstr, errstr_size); SSL_CTX_free(ctx); return -1; }
static SSL_CTX *tlscreatectx(uint8_t type, struct tls *conf) { SSL_CTX *ctx = NULL; unsigned long error; switch (type) { #ifdef RADPROT_TLS case RAD_TLS: ctx = SSL_CTX_new(TLSv1_method()); break; #endif #ifdef RADPROT_DTLS case RAD_DTLS: ctx = SSL_CTX_new(DTLSv1_method()); SSL_CTX_set_read_ahead(ctx, 1); break; #endif } if (!ctx) { debug(DBG_ERR, "tlscreatectx: Error initialising SSL/TLS in TLS context %s", conf->name); while ((error = ERR_get_error())) debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL)); return NULL; } #ifdef DEBUG SSL_CTX_set_info_callback(ctx, ssl_info_callback); #endif if (conf->certkeypwd) { SSL_CTX_set_default_passwd_cb_userdata(ctx, conf->certkeypwd); SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_cb); } if (conf->certfile || conf->certkeyfile) { if (!SSL_CTX_use_certificate_chain_file(ctx, conf->certfile) || !SSL_CTX_use_PrivateKey_file(ctx, conf->certkeyfile, SSL_FILETYPE_PEM) || !SSL_CTX_check_private_key(ctx)) { while ((error = ERR_get_error())) debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL)); debug(DBG_ERR, "tlscreatectx: Error initialising SSL/TLS (certfile issues) in TLS context %s", conf->name); SSL_CTX_free(ctx); return NULL; } } if (conf->policyoids) { if (!conf->vpm) { conf->vpm = createverifyparams(conf->policyoids); if (!conf->vpm) { debug(DBG_ERR, "tlscreatectx: Failed to add policyOIDs in TLS context %s", conf->name); SSL_CTX_free(ctx); return NULL; } } } if (conf->cacertfile != NULL || conf->cacertpath != NULL) if (!tlsaddcacrl(ctx, conf)) { if (conf->vpm) { X509_VERIFY_PARAM_free(conf->vpm); conf->vpm = NULL; } SSL_CTX_free(ctx); return NULL; } debug(DBG_DBG, "tlscreatectx: created TLS context %s", conf->name); return ctx; }
int mowgli_vio_openssl_default_listen(mowgli_vio_t *vio, int backlog) { return_val_if_fail(vio, -255); mowgli_ssl_connection_t *connection = vio->privdata; const int fd = mowgli_vio_getfd(vio); vio->error.op = MOWGLI_VIO_ERR_OP_LISTEN; #ifndef MOWGLI_HAVE_OPENSSL_TLS_METHOD_API connection->ssl_context = SSL_CTX_new(SSLv23_server_method()); #else connection->ssl_context = SSL_CTX_new(TLS_server_method()); #endif if (connection->ssl_context == NULL) return mowgli_vio_err_sslerrcode(vio, ERR_get_error()); #ifndef MOWGLI_HAVE_OPENSSL_TLS_METHOD_API # ifdef SSL_OP_NO_SSLv2 SSL_CTX_set_options(connection->ssl_context, SSL_OP_NO_SSLv2); # endif # ifdef SSL_OP_NO_SSLv3 SSL_CTX_set_options(connection->ssl_context, SSL_OP_NO_SSLv3); # endif #endif connection->ssl_handle = SSL_new(connection->ssl_context); if (connection->ssl_handle == NULL) return mowgli_vio_err_sslerrcode(vio, ERR_get_error()); SSL_set_accept_state(connection->ssl_handle); SSL_CTX_set_options(connection->ssl_context, SSL_OP_SINGLE_DH_USE); #ifdef OPENSSL_EC_AVAILABLE # ifdef MOWGLI_HAVE_OPENSSL_ECDH_AUTO SSL_CTX_set_ecdh_auto(connection->ssl_context, 1); # else EC_KEY *ec_key_p256 = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); if (ec_key_p256 != NULL) { SSL_CTX_set_tmp_ecdh(connection->ssl_context, ec_key_p256); EC_KEY_free(ec_key_p256); ec_key_p256 = NULL; } # endif # ifdef SSL_OP_SINGLE_ECDH_USE SSL_CTX_set_options(connection->ssl_context, SSL_OP_SINGLE_ECDH_USE); # endif #endif if (connection->settings.password_func) { SSL_CTX_set_default_passwd_cb(connection->ssl_context, connection->settings.password_func); SSL_CTX_set_default_passwd_cb_userdata(connection->ssl_context, vio->userdata); } if (SSL_CTX_use_certificate_file(connection->ssl_context, connection->settings.cert_path, SSL_FILETYPE_PEM) != 1) return mowgli_vio_err_sslerrcode(vio, ERR_get_error()); if (SSL_CTX_use_PrivateKey_file(connection->ssl_context, connection->settings.privatekey_path, SSL_FILETYPE_PEM) != 1) return mowgli_vio_err_sslerrcode(vio, ERR_get_error()); if (listen(fd, backlog) != 0) return mowgli_vio_err_errcode(vio, strerror, errno); if (!SSL_set_fd(connection->ssl_handle, fd)) return mowgli_vio_err_sslerrcode(vio, ERR_get_error()); mowgli_vio_setflag(vio, MOWGLI_VIO_FLAGS_ISSERVER, true); vio->error.op = MOWGLI_VIO_ERR_OP_NONE; return 0; }
int main(int argc, char **argv) { SSL_library_init(); SSL_load_error_strings(); BIO * bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); /* Set up a SIGPIPE handler */ signal(SIGPIPE, SIG_IGN); /* Create our context*/ SSL_CTX * ctx = SSL_CTX_new(SSLv23_method()); /* Load our keys and certificates*/ if(!(SSL_CTX_use_certificate_chain_file(ctx, "ftests/fixtures/rdpproxy-cert.pem"))) { BIO_printf(bio_err, "Can't read certificate file\n"); ERR_print_errors(bio_err); exit(0); } SSL_CTX_set_default_passwd_cb(ctx, password_cb0); SSL_CTX_set_default_passwd_cb_userdata(ctx, const_cast<char *>("inquisition")); if(!(SSL_CTX_use_PrivateKey_file(ctx, "ftests/fixtures/rdpproxy-key.pem", SSL_FILETYPE_PEM))) { BIO_printf(bio_err,"Can't read key file\n"); ERR_print_errors(bio_err); exit(0); } DH *ret=nullptr; BIO *bio; if ((bio=BIO_new_file("ftests/fixtures/dh1024.pem","r")) == nullptr){ BIO_printf(bio_err,"Couldn't open DH file\n"); ERR_print_errors(bio_err); exit(0); } ret=PEM_read_bio_DHparams(bio, nullptr, nullptr, nullptr); BIO_free(bio); if(SSL_CTX_set_tmp_dh(ctx, ret)<0) { BIO_printf(bio_err,"Couldn't set DH parameters\n"); ERR_print_errors(bio_err); exit(0); } union { struct sockaddr s; struct sockaddr_storage ss; struct sockaddr_in s4; struct sockaddr_in6 s6; } ucs; memset(&ucs, 0, sizeof(ucs)); int val=1; int sock = socket(AF_INET, SOCK_STREAM,0); if(sock < 0) { fprintf(stderr, "Failed to make socket\n"); exit(0); } memset(&ucs.s4, 0, sizeof(ucs)); ucs.s4.sin_addr.s_addr = INADDR_ANY; ucs.s4.sin_family = AF_INET; ucs.s4.sin_port = htons(4433); setsockopt(sock,SOL_SOCKET,SO_REUSEADDR, &val,sizeof(val)); int bind_res = bind(sock,&ucs.s, sizeof(ucs)); if(bind_res < 0){ fprintf(stderr, "Failed to bind\n"); exit(0); } listen(sock,5); while(1){ int s = accept(sock,nullptr,nullptr); if(s < 0){ fprintf(stderr,"Problem accepting\n"); exit(0); } pid_t pid = fork(); if(pid){ close(s); } else { rdp_serve(ctx, s, bio_err); exit(0); } } SSL_CTX_free(ctx); exit(0); }
bool TLS_SOCKET_CLASS::openSslInitialize() // DESCRIPTION : Called to initialize the OpenSSL library for this session. // PRECONDITIONS : // POSTCONDITIONS : // EXCEPTIONS : // NOTES : //<<=========================================================================== { int verify_mode; long ssl_options; openSslM_ptr = OPENSSL_CLASS::getInstance(); if (openSslM_ptr == NULL) { if (loggerM_ptr) { loggerM_ptr->text(LOG_ERROR, 1, "OpenSSL library not initialized when initializing Secure Socket"); } return false; } // setup the connection factory for this session if (tlsVersionM == TLS_VERSION_TLSv1) { ctxM_ptr = SSL_CTX_new(TLSv1_method()); } else if (tlsVersionM == TLS_VERSION_SSLv3) { ctxM_ptr = SSL_CTX_new(SSLv3_method()); } else { ctxM_ptr = SSL_CTX_new(SSLv23_method()); } if (ctxM_ptr == NULL) { openSslError("initializing connection factory"); return false; } SSL_CTX_set_default_passwd_cb(ctxM_ptr, OPENSSL_CLASS::openSslPasswordCallback); char *password = new char[certificateFilePasswordM.length() + 1]; // create a buffer to store the password // this is freed in the destructor strcpy(password, certificateFilePasswordM.c_str()); SSL_CTX_set_default_passwd_cb_userdata(ctxM_ptr, (void *)password); if (SSL_CTX_load_verify_locations(ctxM_ptr, certificateFilenameM.c_str(), NULL) != 1) { openSslError("loading trusted certificate file"); } SSL_CTX_set_client_CA_list(ctxM_ptr, SSL_load_client_CA_file(certificateFilenameM.c_str())); ERR_clear_error(); // the last call leaves an error in the stack if (!readCredentials(ctxM_ptr)) { openSslError("loading credentials"); } if (checkRemoteCertificateM) { verify_mode = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT; } else { verify_mode = SSL_VERIFY_NONE; } SSL_CTX_set_verify(ctxM_ptr, verify_mode, openSslVerifyCallback); if ((loggerM_ptr != NULL) && ((loggerM_ptr->getLogMask() & LOG_DEBUG) != 0)) { SSL_CTX_set_msg_callback(ctxM_ptr, openSslMsgCallback); // the 'this' pointer needed by openSslMsgCallback and openSslVerfyCallback must be set by // SSL_set_msg_callback_arg for each SSL created } ssl_options = SSL_OP_ALL | SSL_OP_SINGLE_DH_USE; if (tlsVersionM.find(TLS_VERSION_SSLv2) == string::npos) { ssl_options |= SSL_OP_NO_SSLv2; } if (tlsVersionM.find(TLS_VERSION_SSLv3) == string::npos) { ssl_options |= SSL_OP_NO_SSLv3; } if (tlsVersionM.find(TLS_VERSION_TLSv1) == string::npos) { ssl_options |= SSL_OP_NO_TLSv1; } SSL_CTX_set_options(ctxM_ptr, ssl_options); SSL_CTX_set_timeout(ctxM_ptr, tlsCacheTimeoutM); SSL_CTX_set_session_id_context(ctxM_ptr, (const unsigned char *)"DVT", 3); if (cacheTlsSessionsM) { SSL_CTX_set_session_cache_mode(ctxM_ptr, SSL_SESS_CACHE_BOTH); } else { SSL_CTX_set_session_cache_mode(ctxM_ptr, SSL_SESS_CACHE_OFF); } SSL_CTX_set_tmp_dh_callback(ctxM_ptr, OPENSSL_CLASS::tmpDhCallback); if (SSL_CTX_set_cipher_list(ctxM_ptr, cipherListM.c_str()) != 1) { openSslError("initializing cipher list (no valid ciphers)"); } return true; }
/* 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) { int sock = INVALID_SOCKET; #ifndef WIN32 int opt; #endif struct addrinfo hints; struct addrinfo *ainfo, *rp; int s; #ifdef WIN32 uint32_t val = 1; #endif #ifdef WITH_TLS int ret; BIO *bio; #endif if(!mosq || !host || !port) return MOSQ_ERR_INVAL; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = PF_UNSPEC; hints.ai_flags = AI_ADDRCONFIG; hints.ai_socktype = SOCK_STREAM; s = getaddrinfo(host, NULL, &hints, &ainfo); if(s) return MOSQ_ERR_UNKNOWN; for(rp = ainfo; rp != NULL; rp = rp->ai_next){ sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if(sock == INVALID_SOCKET) continue; if(rp->ai_family == PF_INET){ ((struct sockaddr_in *)rp->ai_addr)->sin_port = htons(port); }else if(rp->ai_family == PF_INET6){ ((struct sockaddr_in6 *)rp->ai_addr)->sin6_port = htons(port); }else{ continue; } if(connect(sock, rp->ai_addr, rp->ai_addrlen) != -1){ break; } #ifdef WIN32 errno = WSAGetLastError(); #endif COMPAT_CLOSE(sock); } if(!rp){ return MOSQ_ERR_ERRNO; } freeaddrinfo(ainfo); /* Set non-blocking */ #ifndef WIN32 opt = fcntl(sock, F_GETFL, 0); if(opt == -1 || fcntl(sock, F_SETFL, opt | O_NONBLOCK) == -1){ #ifdef WITH_TLS if(mosq->ssl){ SSL_shutdown(mosq->ssl); SSL_free(mosq->ssl); mosq->ssl = NULL; } if(mosq->ssl_ctx){ SSL_CTX_free(mosq->ssl_ctx); mosq->ssl_ctx = NULL; } #endif COMPAT_CLOSE(sock); return MOSQ_ERR_ERRNO; } #else if(ioctlsocket(sock, FIONBIO, &val)){ errno = WSAGetLastError(); #ifdef WITH_TLS if(mosq->ssl){ SSL_shutdown(mosq->ssl); SSL_free(mosq->ssl); mosq->ssl = NULL; } if(mosq->ssl_ctx){ SSL_CTX_free(mosq->ssl_ctx); mosq->ssl_ctx = NULL; } #endif COMPAT_CLOSE(sock); return MOSQ_ERR_ERRNO; } #endif #ifdef WITH_TLS if(mosq->tls_cafile || mosq->tls_capath || mosq->tls_psk){ if(!mosq->tls_version || !strcmp(mosq->tls_version, "tlsv1")){ mosq->ssl_ctx = SSL_CTX_new(TLSv1_client_method()); if(!mosq->ssl_ctx){ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to create TLS context."); COMPAT_CLOSE(sock); return MOSQ_ERR_TLS; } }else{ COMPAT_CLOSE(sock); return MOSQ_ERR_INVAL; } 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, NULL); } 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_file(mosq->ssl_ctx, mosq->tls_certfile, SSL_FILETYPE_PEM); 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 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); ret = SSL_connect(mosq->ssl); if(ret != 1){ ret = SSL_get_error(mosq->ssl, ret); if(ret == SSL_ERROR_WANT_READ){ mosq->want_read = true; }else if(ret == SSL_ERROR_WANT_WRITE){ mosq->want_write = true; }else{ COMPAT_CLOSE(sock); return MOSQ_ERR_TLS; } } } #endif mosq->sock = sock; return MOSQ_ERR_SUCCESS; }
int SSLSocket_createContext(networkHandles* net, MQTTClient_SSLOptions* opts) { int rc = 1; char* ciphers = NULL; FUNC_ENTRY; if (net->ctx == NULL) if ((net->ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) /* SSLv23 for compatibility with SSLv2, SSLv3 and TLSv1 */ { SSLSocket_error("SSL_CTX_new", NULL, net->socket, rc); goto exit; } if (opts->keyStore) { if ((rc = SSL_CTX_use_certificate_chain_file(net->ctx, opts->keyStore)) != 1) { SSLSocket_error("SSL_CTX_use_certificate_chain_file", NULL, net->socket, rc); goto free_ctx; /*If we can't load the certificate (chain) file then loading the privatekey won't work either as it needs a matching cert already loaded */ } if (opts->privateKey == NULL) opts->privateKey = opts->keyStore; /* the privateKey can be included in the keyStore */ if (opts->privateKeyPassword != NULL) { SSL_CTX_set_default_passwd_cb(net->ctx, pem_passwd_cb); SSL_CTX_set_default_passwd_cb_userdata(net->ctx, (void*)opts->privateKeyPassword); } /* support for ASN.1 == DER format? DER can contain only one certificate? */ if ((rc = SSL_CTX_use_PrivateKey_file(net->ctx, opts->privateKey, SSL_FILETYPE_PEM)) != 1) { SSLSocket_error("SSL_CTX_use_PrivateKey_file", NULL, net->socket, rc); goto free_ctx; } } if (opts->trustStore) { if ((rc = SSL_CTX_load_verify_locations(net->ctx, opts->trustStore, NULL)) != 1) { SSLSocket_error("SSL_CTX_load_verify_locations", NULL, net->socket, rc); goto free_ctx; } } else if ((rc = SSL_CTX_set_default_verify_paths(net->ctx)) != 1) { SSLSocket_error("SSL_CTX_set_default_verify_paths", NULL, net->socket, rc); goto free_ctx; } if (opts->enabledCipherSuites == NULL) ciphers = "DEFAULT"; else ciphers = opts->enabledCipherSuites; if ((rc = SSL_CTX_set_cipher_list(net->ctx, ciphers)) != 1) { SSLSocket_error("SSL_CTX_set_cipher_list", NULL, net->socket, rc); goto free_ctx; } SSL_CTX_set_mode(net->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); goto exit; free_ctx: SSL_CTX_free(net->ctx); net->ctx = NULL; exit: FUNC_EXIT_RC(rc); return rc; }
static void setup_ssl(tcptest_t *item) { static int ssl_init_complete = 0; struct servent *sp; char portinfo[100]; X509 *peercert; char *certcn, *certstart, *certend; int err; strbuffer_t *sslinfo; char msglin[2048]; item->sslrunning = 1; if (!ssl_init_complete) { /* Setup entropy */ if (RAND_status() != 1) { char path[PATH_MAX]; /* Path for the random file */ /* load entropy from files */ RAND_load_file(RAND_file_name(path, sizeof (path)), -1); /* load entropy from egd sockets */ RAND_egd("/var/run/egd-pool"); RAND_egd("/dev/egd-pool"); RAND_egd("/etc/egd-pool"); RAND_egd("/var/spool/prngd/pool"); /* shuffle $RANDFILE (or ~/.rnd if unset) */ RAND_write_file(RAND_file_name(path, sizeof (path))); if (RAND_status() != 1) { errprintf("Failed to find enough entropy on your system"); item->errcode = CONTEST_ESSL; return; } } SSL_load_error_strings(); SSL_library_init(); ssl_init_complete = 1; } if (item->sslctx == NULL) { switch (item->ssloptions->sslversion) { case SSLVERSION_V2: item->sslctx = SSL_CTX_new(SSLv2_client_method()); break; case SSLVERSION_V3: item->sslctx = SSL_CTX_new(SSLv3_client_method()); break; case SSLVERSION_TLS1: item->sslctx = SSL_CTX_new(TLSv1_client_method()); break; default: item->sslctx = SSL_CTX_new(SSLv23_client_method()); break; } if (!item->sslctx) { char sslerrmsg[256]; ERR_error_string(ERR_get_error(), sslerrmsg); errprintf("Cannot create SSL context - IP %s, service %s: %s\n", inet_ntoa(item->addr.sin_addr), item->svcinfo->svcname, sslerrmsg); item->sslrunning = 0; item->errcode = CONTEST_ESSL; return; } /* Workaround SSL bugs */ SSL_CTX_set_options(item->sslctx, SSL_OP_ALL); SSL_CTX_set_quiet_shutdown(item->sslctx, 1); /* Limit set of ciphers, if user wants to */ if (item->ssloptions->cipherlist) SSL_CTX_set_cipher_list(item->sslctx, item->ssloptions->cipherlist); if (item->ssloptions->clientcert) { int status; char certfn[PATH_MAX]; SSL_CTX_set_default_passwd_cb(item->sslctx, cert_password_cb); SSL_CTX_set_default_passwd_cb_userdata(item->sslctx, item); sprintf(certfn, "%s/certs/%s", xgetenv("XYMONHOME"), item->ssloptions->clientcert); status = SSL_CTX_use_certificate_chain_file(item->sslctx, certfn); if (status == 1) { status = SSL_CTX_use_PrivateKey_file(item->sslctx, certfn, SSL_FILETYPE_PEM); } if (status != 1) { char sslerrmsg[256]; ERR_error_string(ERR_get_error(), sslerrmsg); errprintf("Cannot load SSL client certificate/key %s: %s\n", item->ssloptions->clientcert, sslerrmsg); item->sslrunning = 0; item->errcode = CONTEST_ESSL; return; } } } if (item->ssldata == NULL) { item->ssldata = SSL_new(item->sslctx); if (!item->ssldata) { char sslerrmsg[256]; ERR_error_string(ERR_get_error(), sslerrmsg); errprintf("SSL_new failed - IP %s, service %s: %s\n", inet_ntoa(item->addr.sin_addr), item->svcinfo->svcname, sslerrmsg); item->sslrunning = 0; SSL_CTX_free(item->sslctx); item->errcode = CONTEST_ESSL; return; } /* Verify that the client certificate is working */ if (item->ssloptions->clientcert) { X509 *x509; x509 = SSL_get_certificate(item->ssldata); if(x509 != NULL) { EVP_PKEY *pktmp = X509_get_pubkey(x509); EVP_PKEY_copy_parameters(pktmp,SSL_get_privatekey(item->ssldata)); EVP_PKEY_free(pktmp); } if (!SSL_CTX_check_private_key(item->sslctx)) { errprintf("Private/public key mismatch for certificate %s\n", item->ssloptions->clientcert); item->sslrunning = 0; item->errcode = CONTEST_ESSL; return; } } /* SSL setup is done. Now attach the socket FD to the SSL protocol handler */ if (SSL_set_fd(item->ssldata, item->fd) != 1) { char sslerrmsg[256]; ERR_error_string(ERR_get_error(), sslerrmsg); errprintf("Could not initiate SSL on connection - IP %s, service %s: %s\n", inet_ntoa(item->addr.sin_addr), item->svcinfo->svcname, sslerrmsg); item->sslrunning = 0; SSL_free(item->ssldata); SSL_CTX_free(item->sslctx); item->errcode = CONTEST_ESSL; return; } } sp = getservbyport(item->addr.sin_port, "tcp"); if (sp) { sprintf(portinfo, "%s (%d/tcp)", sp->s_name, item->addr.sin_port); } else { sprintf(portinfo, "%d/tcp", item->addr.sin_port); } if ((err = SSL_connect(item->ssldata)) != 1) { char sslerrmsg[256]; switch (SSL_get_error (item->ssldata, err)) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: item->sslrunning = SSLSETUP_PENDING; break; case SSL_ERROR_SYSCALL: ERR_error_string(ERR_get_error(), sslerrmsg); /* Filter out the bogus SSL error */ if (strstr(sslerrmsg, "error:00000000:") == NULL) { errprintf("IO error in SSL_connect to %s on host %s: %s\n", portinfo, inet_ntoa(item->addr.sin_addr), sslerrmsg); } item->errcode = CONTEST_ESSL; item->sslrunning = 0; SSL_free(item->ssldata); SSL_CTX_free(item->sslctx); break; case SSL_ERROR_SSL: ERR_error_string(ERR_get_error(), sslerrmsg); errprintf("Unspecified SSL error in SSL_connect to %s on host %s: %s\n", portinfo, inet_ntoa(item->addr.sin_addr), sslerrmsg); item->errcode = CONTEST_ESSL; item->sslrunning = 0; SSL_free(item->ssldata); SSL_CTX_free(item->sslctx); break; default: ERR_error_string(ERR_get_error(), sslerrmsg); errprintf("Unknown error %d in SSL_connect to %s on host %s: %s\n", err, portinfo, inet_ntoa(item->addr.sin_addr), sslerrmsg); item->errcode = CONTEST_ESSL; item->sslrunning = 0; SSL_free(item->ssldata); SSL_CTX_free(item->sslctx); break; } return; } /* If we get this far, the SSL handshake has completed. So grab the certificate */ peercert = SSL_get_peer_certificate(item->ssldata); if (!peercert) { errprintf("Cannot get peer certificate for %s on host %s\n", portinfo, inet_ntoa(item->addr.sin_addr)); item->errcode = CONTEST_ESSL; item->sslrunning = 0; SSL_free(item->ssldata); SSL_CTX_free(item->sslctx); return; } sslinfo = newstrbuffer(0); certcn = X509_NAME_oneline(X509_get_subject_name(peercert), NULL, 0); certstart = strdup(xymon_ASN1_UTCTIME(X509_get_notBefore(peercert))); certend = strdup(xymon_ASN1_UTCTIME(X509_get_notAfter(peercert))); snprintf(msglin, sizeof(msglin), "Server certificate:\n\tsubject:%s\n\tstart date: %s\n\texpire date:%s\n", certcn, certstart, certend); addtobuffer(sslinfo, msglin); item->certsubject = strdup(certcn); item->certexpires = sslcert_expiretime(certend); xfree(certcn); xfree(certstart); xfree(certend); X509_free(peercert); /* We list the available ciphers in the SSL cert data */ { int i; STACK_OF(SSL_CIPHER) *sk; addtobuffer(sslinfo, "\nAvailable ciphers:\n"); sk = SSL_get_ciphers(item->ssldata); for (i=0; i<sk_SSL_CIPHER_num(sk); i++) { int b1, b2; char *cph; b1 = SSL_CIPHER_get_bits(sk_SSL_CIPHER_value(sk,i), &b2); cph = SSL_CIPHER_get_name(sk_SSL_CIPHER_value(sk,i)); snprintf(msglin, sizeof(msglin), "Cipher %d: %s (%d bits)\n", i, cph, b1); addtobuffer(sslinfo, msglin); if ((item->mincipherbits == 0) || (b1 < item->mincipherbits)) item->mincipherbits = b1; } } item->certinfo = grabstrbuffer(sslinfo); }
apn_return apn_ssl_connect(apn_ctx_t *const ctx) { assert(ctx); SSL_CTX *ssl_ctx = NULL; if (NULL == (ssl_ctx = SSL_CTX_new(TLSv1_client_method()))) { apn_log(ctx, APN_LOG_LEVEL_ERROR, "Could not initialize SSL context: %s", ERR_error_string(ERR_get_error(), NULL)); return APN_ERROR; } SSL_CTX_set_ex_data(ssl_ctx, 0, ctx); SSL_CTX_set_info_callback(ssl_ctx, __apn_ssl_info_callback); X509 *cert = NULL; if (ctx->pkcs12_file && ctx->pkcs12_pass) { FILE *pkcs12_file = NULL; #ifdef _WIN32 fopen_s(&pkcs12_file, ctx->pkcs12_file, "r"); #else pkcs12_file = fopen(ctx->pkcs12_file, "r"); #endif if (!pkcs12_file) { char *error = apn_error_string(errno); apn_log(ctx, APN_LOG_LEVEL_ERROR, "Unable to open file %s: %s (errno: %d)", ctx->pkcs12_file, error, errno); free(error); SSL_CTX_free(ssl_ctx); errno = APN_ERR_UNABLE_TO_USE_SPECIFIED_PKCS12; return APN_ERROR; } PKCS12 *pkcs12_cert = NULL; d2i_PKCS12_fp(pkcs12_file, &pkcs12_cert); fclose(pkcs12_file); EVP_PKEY *private_key = NULL; if (!PKCS12_parse(pkcs12_cert, ctx->pkcs12_pass, &private_key, &cert, NULL)) { apn_log(ctx, APN_LOG_LEVEL_ERROR, "Unable to use specified PKCS#12 file: %s", ERR_error_string(ERR_get_error(), NULL)); PKCS12_free(pkcs12_cert); SSL_CTX_free(ssl_ctx); errno = APN_ERR_UNABLE_TO_USE_SPECIFIED_PKCS12; return APN_ERROR; } PKCS12_free(pkcs12_cert); if (!SSL_CTX_use_certificate(ssl_ctx, cert)) { apn_log(ctx, APN_LOG_LEVEL_ERROR, "Unable to use specified PKCS#12 file: %s", ERR_error_string(ERR_get_error(), NULL)); X509_free(cert); EVP_PKEY_free(private_key); SSL_CTX_free(ssl_ctx); errno = APN_ERR_UNABLE_TO_USE_SPECIFIED_PKCS12; return APN_ERROR; } if (!SSL_CTX_use_PrivateKey(ssl_ctx, private_key)) { apn_log(ctx, APN_LOG_LEVEL_ERROR, "Unable to use specified PKCS#12 file: %s", ERR_error_string(ERR_get_error(), NULL)); X509_free(cert); EVP_PKEY_free(private_key); SSL_CTX_free(ssl_ctx); errno = APN_ERR_UNABLE_TO_USE_SPECIFIED_PKCS12; return APN_ERROR; } EVP_PKEY_free(private_key); } else { FILE *cert_file = NULL; #ifdef _WIN32 fopen_s(&cert_file, ctx->certificate_file, "r"); #else cert_file = fopen(ctx->certificate_file, "r"); #endif if (!cert_file) { char *error = apn_error_string(errno); apn_log(ctx, APN_LOG_LEVEL_ERROR, "Unable to open file %s: %s (errno: %d)", ctx->pkcs12_file, error, errno); free(error); X509_free(cert); SSL_CTX_free(ssl_ctx); errno = APN_ERR_UNABLE_TO_USE_SPECIFIED_CERTIFICATE; return APN_ERROR; } cert = PEM_read_X509(cert_file, NULL, NULL, NULL); if (!cert) { apn_log(ctx, APN_LOG_LEVEL_ERROR, "Unable to use specified certificate: %s", ERR_error_string(ERR_get_error(), NULL)); SSL_CTX_free(ssl_ctx); fclose(cert_file); errno = APN_ERR_UNABLE_TO_USE_SPECIFIED_CERTIFICATE; return EXIT_FAILURE; } fclose(cert_file); if (!SSL_CTX_use_certificate(ssl_ctx, cert)) { apn_log(ctx, APN_LOG_LEVEL_ERROR, "Unable to use specified certificate: %s", ERR_error_string(ERR_get_error(), NULL)); X509_free(cert); SSL_CTX_free(ssl_ctx); errno = APN_ERR_UNABLE_TO_USE_SPECIFIED_CERTIFICATE; return APN_ERROR; } SSL_CTX_set_default_passwd_cb(ssl_ctx, __apn_ssl_password_callback); char *password = NULL; if (ctx->private_key_pass) { password = apn_strndup(ctx->private_key_pass, strlen(ctx->private_key_pass)); if (!password) { X509_free(cert); SSL_CTX_free(ssl_ctx); return APN_ERROR; } SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, password); } else { SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, NULL); } if (!SSL_CTX_use_PrivateKey_file(ssl_ctx, ctx->private_key_file, SSL_FILETYPE_PEM)) { apn_log(ctx, APN_LOG_LEVEL_ERROR, "Unable to use specified private key: %s", ERR_error_string(ERR_get_error(), NULL)); apn_strfree(&password); X509_free(cert); SSL_CTX_free(ssl_ctx); errno = APN_ERR_UNABLE_TO_USE_SPECIFIED_PRIVATE_KEY; return APN_ERROR; } apn_strfree(&password); if (!SSL_CTX_check_private_key(ssl_ctx)) { apn_log(ctx, APN_LOG_LEVEL_ERROR, "Unable to use specified private key: %s", ERR_error_string(ERR_get_error(), NULL)); errno = APN_ERR_UNABLE_TO_USE_SPECIFIED_PRIVATE_KEY; X509_free(cert); SSL_CTX_free(ssl_ctx); return APN_ERROR; } } if(cert) { char *subject = __apn_cert_subject_string(cert); apn_log(ctx, APN_LOG_LEVEL_INFO, "Local certificate subject: %s", subject); char *issuer = __apn_cert_issuer_string(cert); apn_log(ctx, APN_LOG_LEVEL_INFO, "Local certificate issuer: %s", issuer); free(subject); free(issuer); char *cn = __apn_cert_subject_value_by_nib(cert, __APN_X509_ENTRY_CN); X509_free(cert); if(cn) { uint8_t invalid_cert = 0; if(apn_mode(ctx) == APN_MODE_PRODUCTION && 0 != strncmp("Apple Production", cn, 16)) { invalid_cert = 1; apn_log(ctx, APN_LOG_LEVEL_ERROR, "Invalid certificate. You are using a PRODUCTION mode, but certificate was created for usage in SANDBOX"); } else if (apn_mode(ctx) == APN_MODE_SANDBOX && 0 != strncmp("Apple Development", cn, 17)) { invalid_cert = 1; apn_log(ctx, APN_LOG_LEVEL_ERROR, "Invalid certificate. You are using a SANDBOX mode, but certificate was created for usage in PRODUCTION"); } free(cn); if(1 == invalid_cert) { SSL_CTX_free(ssl_ctx); errno = APN_ERR_UNABLE_TO_USE_SPECIFIED_CERTIFICATE; return APN_ERROR; } } } ctx->ssl = SSL_new(ssl_ctx); SSL_CTX_free(ssl_ctx); if (!ctx->ssl) { apn_log(ctx, APN_LOG_LEVEL_ERROR, "Could not initialize SSL"); errno = APN_ERR_UNABLE_TO_ESTABLISH_SSL_CONNECTION; return APN_ERROR; } int ret = 0; if (-1 == (ret = SSL_set_fd(ctx->ssl, ctx->sock))) { apn_log(ctx, APN_LOG_LEVEL_ERROR, "Unable to attach socket to SSL: SSL_set_fd() failed (%d)", SSL_get_error(ctx->ssl, ret)); errno = APN_ERR_UNABLE_TO_ESTABLISH_SSL_CONNECTION; return APN_ERROR; } if (1 > (ret = SSL_connect(ctx->ssl))) { char *error = apn_error_string(errno); apn_log(ctx, APN_LOG_LEVEL_ERROR, "Could not initialize SSL connection: SSL_connect() failed: %s, %s (errno: %d):", ERR_error_string((unsigned long) SSL_get_error(ctx->ssl, ret), NULL), error, errno); free(error); return APN_ERROR; } apn_log(ctx, APN_LOG_LEVEL_INFO, "SSL connection has been established"); X509 *remote_cert = SSL_get_peer_certificate(ctx->ssl); if (remote_cert) { char *subject = __apn_cert_subject_string(remote_cert); apn_log(ctx, APN_LOG_LEVEL_INFO, "Remote certificate subject: %s", subject); char *issuer = __apn_cert_issuer_string(remote_cert); apn_log(ctx, APN_LOG_LEVEL_INFO, "Remote certificate issuer: %s", issuer); free(subject); free(issuer); X509_free(remote_cert); } return APN_SUCCESS; }
BOOL create_ssl(int sockfd, const char* ca_crt_root, const char* ca_crt_server, const char* ca_password, const char* ca_key_server, BOOL enableclientcacheck, SSL** pp_ssl, SSL_CTX** pp_ssl_ctx) { int ssl_rc = -1; BOOL b_ssl_accepted; X509* client_cert; SSL_METHOD* meth = NULL; #if OPENSSL_VERSION_NUMBER >= 0x010100000L meth = (SSL_METHOD*)TLS_server_method(); #else meth = (SSL_METHOD*)SSLv23_server_method(); #endif /* OPENSSL_VERSION_NUMBER */ *pp_ssl_ctx = SSL_CTX_new(meth); if(!*pp_ssl_ctx) { CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME); uTrace.Write(Trace_Error, "SSL_CTX_use_certificate_file: %s", ERR_error_string(ERR_get_error(),NULL)); goto clean_ssl3; } if(enableclientcacheck) { SSL_CTX_set_verify(*pp_ssl_ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); SSL_CTX_set_verify_depth(*pp_ssl_ctx, 4); } SSL_CTX_load_verify_locations(*pp_ssl_ctx, ca_crt_root, NULL); if(SSL_CTX_use_certificate_file(*pp_ssl_ctx, ca_crt_server, SSL_FILETYPE_PEM) <= 0) { CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME); uTrace.Write(Trace_Error, "SSL_CTX_use_certificate_file: %s", ERR_error_string(ERR_get_error(),NULL)); goto clean_ssl3; } SSL_CTX_set_default_passwd_cb_userdata(*pp_ssl_ctx, (char*)ca_password); if(SSL_CTX_use_PrivateKey_file(*pp_ssl_ctx, ca_key_server, SSL_FILETYPE_PEM) <= 0) { CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME); uTrace.Write(Trace_Error, "SSL_CTX_use_certificate_file: %s", ERR_error_string(ERR_get_error(),NULL)); goto clean_ssl3; } if(!SSL_CTX_check_private_key(*pp_ssl_ctx)) { CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME); uTrace.Write(Trace_Error, "SSL_CTX_use_certificate_file: %s", ERR_error_string(ERR_get_error(),NULL)); goto clean_ssl3; } ssl_rc = SSL_CTX_set_cipher_list(*pp_ssl_ctx, "ALL"); if(ssl_rc == 0) { CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME); uTrace.Write(Trace_Error, "SSL_CTX_set_cipher_list: %s", ERR_error_string(ERR_get_error(),NULL)); goto clean_ssl3; } SSL_CTX_set_mode(*pp_ssl_ctx, SSL_MODE_AUTO_RETRY); *pp_ssl = SSL_new(*pp_ssl_ctx); if(!*pp_ssl) { CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME); uTrace.Write(Trace_Error, "SSL_new: %s", ERR_error_string(ERR_get_error(),NULL)); goto clean_ssl2; } ssl_rc = SSL_set_fd(*pp_ssl, sockfd); if(ssl_rc == 0) { CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME); uTrace.Write(Trace_Error, "SSL_set_fd: %s", ERR_error_string(ERR_get_error(),NULL)); goto clean_ssl2; } ssl_rc = SSL_set_cipher_list(*pp_ssl, "ALL"); if(ssl_rc == 0) { CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME); uTrace.Write(Trace_Error, "SSL_set_cipher_list: %s", ERR_error_string(ERR_get_error(),NULL)); goto clean_ssl2; } ssl_rc = SSL_accept(*pp_ssl); if(ssl_rc < 0) { CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME); uTrace.Write(Trace_Error, "SSL_accept: %s", ERR_error_string(ERR_get_error(),NULL)); goto clean_ssl2; } else if(ssl_rc = 0) { goto clean_ssl1; } b_ssl_accepted = TRUE; if(enableclientcacheck) { ssl_rc = SSL_get_verify_result(*pp_ssl); if(ssl_rc != X509_V_OK) { CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME); uTrace.Write(Trace_Error, "SSL_get_verify_result: %s", ERR_error_string(ERR_get_error(),NULL)); goto clean_ssl1; } } if(enableclientcacheck) { X509* client_cert; client_cert = SSL_get_peer_certificate(*pp_ssl); if (client_cert != NULL) { X509_free (client_cert); } else { CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME); uTrace.Write(Trace_Error, "SSL_get_peer_certificate: %s", ERR_error_string(ERR_get_error(),NULL)); goto clean_ssl1; } } return TRUE; clean_ssl1: if(*pp_ssl && b_ssl_accepted) { SSL_shutdown(*pp_ssl); b_ssl_accepted = FALSE; } clean_ssl2: if(*pp_ssl) { SSL_free(*pp_ssl); *pp_ssl = NULL; } clean_ssl3: if(*pp_ssl_ctx) { SSL_CTX_free(*pp_ssl_ctx); *pp_ssl_ctx = NULL; } return FALSE; }
retcode_t tb_initSSL(Socket_t S, enum ssl_mode mode, // SSL_CLIENT | SSL_SERVER ssl_meth_t method, // SSL1 | SSL2 | SSL3 | TLS1 char * CA_path, char * CA_file, char * cert, char * pwd, char * cipher) { SSL_METHOD * meth; sock_ssl_t m; tb_info("tb_initSSL in\n"); if(!TB_VALID(S, TB_SOCKET)) { set_tb_errno(TB_ERR_INVALID_TB_OBJECT); return TB_ERR; } if(XSock(S)->ssl != NULL ) { tb_warn("tb_initSSL: Socket_t allready SSL initialized\n"); set_tb_errno(TB_ERR_ALLREADY); return TB_ERR; } m = tb_xcalloc(1, sizeof(struct sock_ssl)); XSock(S)->ssl = m; m->ssl_method = method; m->mode = method; if( CA_path ) m->CA_path = tb_xstrdup(CA_path); if( CA_file ) m->CA_file = tb_xstrdup(CA_file); if( cert ) m->cert = tb_xstrdup(cert); if( pwd ) m->pwd = tb_xstrdup(pwd); if( cipher ) m->cipher = tb_xstrdup(cipher); __tb_init_SSL_once(); switch (m->ssl_method) { case 1: meth = (mode == SSL_CLIENT) ? SSLv23_client_method() : SSLv23_server_method(); break; case 2: meth = (mode == SSL_CLIENT) ? SSLv2_client_method() : SSLv2_server_method(); break; case 3: meth = (mode == SSL_CLIENT) ? SSLv3_client_method() : SSLv3_server_method(); break; case 4: meth = (mode == SSL_CLIENT) ? TLSv1_client_method() : TLSv1_server_method(); break; default: meth = NULL; goto err; } if (!(m->ctx = SSL_CTX_new(meth))) { tb_warn("tb_initSSL: Cannot create new SSL context\n"); ERR_print_errors_fp(stderr); XSock(S)->status = TB_BROKEN; return TB_ERR; } if(tb_errorlevel == TB_DEBUG) SSL_CTX_set_info_callback(m->ctx,info_cb); if(m->pwd) { SSL_CTX_set_default_passwd_cb(m->ctx, pass_cb); SSL_CTX_set_default_passwd_cb_userdata(m->ctx, S); } if(m->cert ) { if(SSL_CTX_use_certificate_file(m->ctx, m->cert, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); goto err; } if (SSL_CTX_use_PrivateKey_file(m->ctx, m->cert, SSL_FILETYPE_PEM) <= 0) { tb_error("tb_initSSL: Unable to get private key from '%s'\n", m->cert); ERR_print_errors_fp(stderr); goto err; } tb_info("privkey loaded\n"); if (!SSL_CTX_check_private_key(m->ctx)) { tb_error("tb_initSSL: Private key does not match the certificate public key\n"); goto err; } tb_info("tb_initSSL: privkey validated\n"); tb_info("tb_initSSL: certificate loaded\n"); } if(mode == SSL_CLIENT) { SSL_CTX_set_session_cache_mode(m->ctx, SSL_SESS_CACHE_CLIENT); } else { SSL_CTX_set_session_cache_mode(m->ctx, SSL_SESS_CACHE_SERVER); SSL_CTX_set_session_id_context(m->ctx, "try this one", 12); } if(m->CA_file || m->CA_path) { tb_info("tb_initSSL: loading CAs ...\n"); if(!SSL_CTX_load_verify_locations(m->ctx, m->CA_file, m->CA_path)) { XSock(S)->status = TB_BROKEN; tb_warn("tb_initSSL: Cannot load verify locations %s and %s\n", m->CA_file, m->CA_path); ERR_print_errors_fp(stderr); goto err; } tb_info("tb_initSSL: CA <%s/%s> loaded\n", m->CA_path, m->CA_file); SSL_CTX_set_verify(m->ctx, SSL_VERIFY_PEER, verify_cb); SSL_CTX_set_default_verify_paths(m->ctx); } /* Create and configure SSL connection. */ if (!(m->cx = (SSL *)SSL_new(m->ctx))) { tb_warn("tb_initSSL: Cannot create new SSL context\n"); ERR_print_errors_fp(stderr); goto err; } tb_info("tb_initSSL: ssl ctx initialized\n"); /* Use OpenSSL ciphers -v to see the cipher strings and their SSL * versions, key exchange, authentication, encryption, and message * digest algorithms, and key length restrictions. See the OpenSSL * for the syntax to combine ciphers, e.g. !SSLv2:RC4-MD5:RC4-SHA. * If you don't specify anything, you get the same as "DEFAULT", which * means "ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP". */ if(m->cipher) { if(!SSL_CTX_set_cipher_list(m->ctx, m->cipher)) { tb_warn("tb_inittSSL: Cannot use cipher list %s\n", m->cipher); goto err; } tb_info("tb_initSSL: cipher set to <%s>\n", m->cipher); } tb_info("tb_initSSL out\n"); return TB_OK; err: // fixme: context not totally freed (CA_path, pwd ...) SSL_CTX_free(m->ctx); m->ctx = NULL; XSock(S)->status = TB_BROKEN; return TB_ERR; }
MMGConnectionError MMGSSLConnection::OpenConnection(void) { // If already connected, bye bye if (this->IsConnected()) return MMGConnectionError::MMGAlreadyConnected; // Create a SSL context this->_sslCtx = SSL_CTX_new(this->_sslMethod); if (NULL == this->_sslCtx) { MMG_ERRLOG("[!] Failed to create a SSL context\n"); return MMGConnectionError::MMGSSLContextCreateFail; } // Load the client certificate into the SSL context if (SSL_CTX_use_certificate_file(this->_sslCtx, this->_certFile.c_str(), SSL_FILETYPE_PEM) <= 0) { MMG_ERRLOG("[!] Cannot use certificate file <%s>\n", this->_certFile.c_str()); ERR_print_errors_fp(stderr); return MMGConnectionError::MMGSSLInvalidCertificateFile; } // Load the private-key corresponding to the client certificate if (!this->_keyPassword.empty()) SSL_CTX_set_default_passwd_cb_userdata(this->_sslCtx, (void*)this->_keyPassword.c_str()); if (SSL_CTX_use_PrivateKey_file(this->_sslCtx, this->_keyFile.c_str(), SSL_FILETYPE_PEM) <= 0) { MMG_ERRLOG("[!] Cannot use private key file <%s>\n", this->_keyFile.c_str()); ERR_print_errors_fp(stderr); return MMGConnectionError::MMGSSLInvalidPrivateKeyFile; } // Load the CA if (SSL_CTX_load_verify_locations(this->_sslCtx, NULL, this->_certsPath.c_str()) <= 0) { MMG_ERRLOG("[!] Failed to set CA location...\n"); ERR_print_errors_fp(stderr); return MMGConnectionError::MMGSSLInvalidCALocation; } // Check if the client certificate and private-key matches if (!SSL_CTX_check_private_key(this->_sslCtx)) { MMG_ERRLOG("[!] Private key does not match the certificate public key\n"); return MMGConnectionError::MMGSSLInvalidPrivateKeyPair; } // Set up a TCP socket this->_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (-1 == this->_socket) { MMG_ERRLOG("[!] Failed to create socket\n"); return MMGConnectionError::MMGSocketError; } memset(&this->_addr, 0x00, sizeof(this->_addr)); this->_addr.sin_family = AF_INET; this->_addr.sin_port = htons(this->_port); this->_hostent = gethostbyname(this->_hostname.c_str()); if (this->_hostent) { // Take the first IP struct in_addr* address = (struct in_addr*)this->_hostent->h_addr_list[0]; this->_addr.sin_addr.s_addr = inet_addr(inet_ntoa(*address)); } else { MMG_ERRLOG("Could not resolve hostname %s\n", this->_hostname.c_str()); return MMGConnectionError::MMGHostError; } // Establish a TCP/IP connection to the SSL client int err = connect(this->_socket, (struct sockaddr*)&this->_addr, sizeof(this->_addr)); if (-1 == err) { MMG_ERRLOG("Could not connect\n"); return MMGConnectionError::MMGConnectError; } // Create a SSL structure this->_ssl = SSL_new(this->_sslCtx); if (NULL == this->_ssl) { MMG_ERRLOG("Could not get SSL Socket\n"); return MMGConnectionError::MMGSSLError; } // Assign the socket into the SSL structure (SSL and socket without BIO) SSL_set_fd(this->_ssl, this->_socket); // Perform SSL Handshake on the SSL client err = SSL_connect(this->_ssl); if (err <= 0) { MMG_ERRLOG("Could not connect to SSL Server\n"); return MMGConnectionError::MMGSSLConnectError; } return MMGConnectionError::MMGNoError; }
/** * Allocate a new TLS context * * @param tlsp Pointer to allocated TLS context * @param method TLS method * @param keyfile Optional private key file * @param pwd Optional password * * @return 0 if success, otherwise errorcode */ int tls_alloc(struct tls **tlsp, enum tls_method method, const char *keyfile, const char *pwd) { struct tls *tls; int r, err; if (!tlsp) return EINVAL; tls = mem_zalloc(sizeof(*tls), destructor); if (!tls) return ENOMEM; if (!tlsg.up) { #ifdef SIGPIPE /* Set up a SIGPIPE handler */ (void)signal(SIGPIPE, sigpipe_handle); #endif SSL_library_init(); tlsg.up = true; } if (tlsg.tlsc++ == 0) { DEBUG_INFO("error strings loaded\n"); SSL_load_error_strings(); } switch (method) { case TLS_METHOD_SSLV23: tls->ctx = SSL_CTX_new(SSLv23_method()); break; #ifdef USE_OPENSSL_DTLS case TLS_METHOD_DTLSV1: tls->ctx = SSL_CTX_new(DTLSv1_method()); break; #endif default: DEBUG_WARNING("tls method %d not supported\n", method); err = ENOSYS; goto out; } if (!tls->ctx) { err = ENOMEM; goto out; } #if (OPENSSL_VERSION_NUMBER < 0x00905100L) SSL_CTX_set_verify_depth(tls->ctx, 1); #endif if (method == TLS_METHOD_DTLSV1) { SSL_CTX_set_read_ahead(tls->ctx, 1); } /* Load our keys and certificates */ if (keyfile) { if (pwd) { err = str_dup(&tls->pass, pwd); if (err) goto out; SSL_CTX_set_default_passwd_cb(tls->ctx, password_cb); SSL_CTX_set_default_passwd_cb_userdata(tls->ctx, tls); } r = SSL_CTX_use_certificate_chain_file(tls->ctx, keyfile); if (r <= 0) { DEBUG_WARNING("Can't read certificate file: %s (%d)\n", keyfile, r); err = EINVAL; goto out; } r = SSL_CTX_use_PrivateKey_file(tls->ctx, keyfile, SSL_FILETYPE_PEM); if (r <= 0) { DEBUG_WARNING("Can't read key file: %s (%d)\n", keyfile, r); err = EINVAL; goto out; } } err = 0; out: if (err) mem_deref(tls); else *tlsp = tls; return err; }
static int cert_stuff( struct connectdata *conn, SSL_CTX* ctx, char *cert_file, const char *cert_type, char *key_file, const char *key_type ) { struct SessionHandle *data = conn->data; int file_type; if ( cert_file != NULL ) { SSL *ssl; X509 *x509; if ( data->set.key_passwd ) { #ifndef HAVE_USERDATA_IN_PWD_CALLBACK /* * If password has been given, we store that in the global * area (*shudder*) for a while: */ size_t len = strlen( data->set.key_passwd ); if ( len < sizeof( global_passwd ) ) { memcpy( global_passwd, data->set.key_passwd, len + 1 ); } #else /* * We set the password in the callback userdata */ SSL_CTX_set_default_passwd_cb_userdata( ctx, data->set.key_passwd ); #endif /* Set passwd callback: */ SSL_CTX_set_default_passwd_cb( ctx, passwd_callback ); } file_type = do_file_type( cert_type ); #define SSL_CLIENT_CERT_ERR \ "unable to use client certificate (no key found or wrong pass phrase?)" switch ( file_type ) { case SSL_FILETYPE_PEM: /* SSL_CTX_use_certificate_chain_file() only works on PEM files */ if ( SSL_CTX_use_certificate_chain_file( ctx, cert_file ) != 1 ) { failf( data, SSL_CLIENT_CERT_ERR ); return 0; } break; case SSL_FILETYPE_ASN1: /* SSL_CTX_use_certificate_file() works with either PEM or ASN1, but we use the case above for PEM so this can only be performed with ASN1 files. */ if ( SSL_CTX_use_certificate_file( ctx, cert_file, file_type ) != 1 ) { failf( data, SSL_CLIENT_CERT_ERR ); return 0; } break; case SSL_FILETYPE_ENGINE: failf( data, "file type ENG for certificate not implemented" ); return 0; default: failf( data, "not supported file type '%s' for certificate", cert_type ); return 0; } file_type = do_file_type( key_type ); switch ( file_type ) { case SSL_FILETYPE_PEM: if ( key_file == NULL ) { /* cert & key can only be in PEM case in the same file */ key_file = cert_file; } case SSL_FILETYPE_ASN1: if ( SSL_CTX_use_PrivateKey_file( ctx, key_file, file_type ) != 1 ) { failf( data, "unable to set private key file: '%s' type %s\n", key_file, key_type ? key_type : "PEM" ); return 0; } break; case SSL_FILETYPE_ENGINE: #ifdef HAVE_OPENSSL_ENGINE_H { /* XXXX still needs some work */ EVP_PKEY *priv_key = NULL; if ( conn && conn->data && conn->data->engine ) { #ifdef HAVE_ENGINE_LOAD_FOUR_ARGS UI_METHOD *ui_method = UI_OpenSSL(); #endif if ( !key_file || !key_file[0] ) { failf( data, "no key set to load from crypto engine\n" ); return 0; } /* the typecast below was added to please mingw32 */ priv_key = (EVP_PKEY *) ENGINE_load_private_key( conn->data->engine,key_file, #ifdef HAVE_ENGINE_LOAD_FOUR_ARGS ui_method, #endif data->set.key_passwd ); if ( !priv_key ) { failf( data, "failed to load private key from crypto engine\n" ); return 0; } if ( SSL_CTX_use_PrivateKey( ctx, priv_key ) != 1 ) { failf( data, "unable to set private key\n" ); EVP_PKEY_free( priv_key ); return 0; } EVP_PKEY_free( priv_key ); /* we don't need the handle any more... */ } else { failf( data, "crypto engine not set, can't load private key\n" ); return 0; } } break; #else failf( data, "file type ENG for private key not supported\n" ); return 0; #endif default: failf( data, "not supported file type for private key\n" ); return 0; } ssl = SSL_new( ctx ); x509 = SSL_get_certificate( ssl ); /* This version was provided by Evan Jordan and is supposed to not leak memory as the previous version: */ if ( x509 != NULL ) { EVP_PKEY *pktmp = X509_get_pubkey( x509 ); EVP_PKEY_copy_parameters( pktmp,SSL_get_privatekey( ssl ) ); EVP_PKEY_free( pktmp ); } SSL_free( ssl ); /* If we are using DSA, we can copy the parameters from * the private key */ /* Now we know that a key and cert have been set against * the SSL context */ if ( !SSL_CTX_check_private_key( ctx ) ) { failf( data, "Private key does not match the certificate public key" ); return( 0 ); } #ifndef HAVE_USERDATA_IN_PWD_CALLBACK /* erase it now */ memset( global_passwd, 0, sizeof( global_passwd ) ); #endif } return( 1 ); }
gboolean fbConnSpecInitTLS( fbConnSpec_t *spec, gboolean passive, GError **err) { const SSL_METHOD *tlsmeth = NULL; SSL_CTX *ssl_ctx = NULL; gboolean ok = TRUE; /* Initialize the library and error strings */ SSL_library_init(); SSL_load_error_strings(); /* * Select a TLS method based on passivity and transport. * Shortcircuit on no TLS initialization necessary for sockets. */ switch (spec->transport) { #if FB_ENABLE_SCTP case FB_SCTP: #endif case FB_TCP: case FB_UDP: return TRUE; #if HAVE_OPENSSL_DTLS_SCTP case FB_DTLS_SCTP: tlsmeth = passive ? DTLSv1_server_method() : DTLSv1_client_method(); break; #endif case FB_TLS_TCP: tlsmeth = passive ? TLSv1_server_method() : TLSv1_client_method(); break; #if HAVE_OPENSSL_DTLS case FB_DTLS_UDP: tlsmeth = passive ? DTLSv1_server_method() : DTLSv1_client_method(); break; #endif default: g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IMPL, "Unsupported TLS method."); return FALSE; } /* Verify we have all the files we need */ g_assert(spec->ssl_ca_file); g_assert(spec->ssl_cert_file); g_assert(spec->ssl_key_file); /* nuke the old context if there is one */ if (spec->vssl_ctx) { SSL_CTX_free((SSL_CTX *)spec->vssl_ctx); spec->vssl_ctx = NULL; } /* create an SSL_CTX object */ ssl_ctx = SSL_CTX_new(tlsmeth); if (!ssl_ctx) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "Cannot create SSL context: %s", ERR_error_string(ERR_get_error(), NULL)); while (ERR_get_error()); ok = FALSE; goto end; } /* Set up password callback */ SSL_CTX_set_default_passwd_cb(ssl_ctx, fbConnSpecGetTLSPassword); SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, spec->ssl_key_pass); /* Load CA certificate */ if (SSL_CTX_load_verify_locations(ssl_ctx, spec->ssl_ca_file, NULL) != 1) { ok = FALSE; g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "Failed to load certificate authority file %s: %s", spec->ssl_ca_file, ERR_error_string(ERR_get_error(), NULL)); while (ERR_get_error()); goto end; } /* Load certificate */ if (SSL_CTX_use_certificate_chain_file(ssl_ctx, spec->ssl_cert_file) != 1) { ok = FALSE; g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "Failed to load certificate file %s: %s", spec->ssl_cert_file, ERR_error_string(ERR_get_error(), NULL)); while (ERR_get_error()); goto end; } /* Load private key */ if (SSL_CTX_use_PrivateKey_file(ssl_ctx, spec->ssl_key_file, SSL_FILETYPE_PEM) != 1) { ok = FALSE; g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "Failed to load private key file %s: %s", spec->ssl_key_file, ERR_error_string(ERR_get_error(), NULL)); while (ERR_get_error()); goto end; } /* Require verification */ SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, fbConnSpecVerifyTLSCert); /* Stash SSL context in specifier */ spec->vssl_ctx = ssl_ctx; end: /* free incomplete SSL context */ if (!ok) SSL_CTX_free(ssl_ctx); return ok; }
/* 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) { int sock = INVALID_SOCKET; int rc; #ifdef WITH_TLS int ret; BIO *bio; #endif if(!mosq || !host || !port) return MOSQ_ERR_INVAL; #ifdef WITH_TLS if(mosq->tls_cafile || mosq->tls_capath || mosq->tls_psk){ blocking = true; } #endif rc = _mosquitto_try_connect(host, port, &sock, bind_address, blocking); if(rc != MOSQ_ERR_SUCCESS) 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); ret = SSL_connect(mosq->ssl); if(ret != 1){ ret = SSL_get_error(mosq->ssl, ret); if(ret == SSL_ERROR_WANT_READ){ mosq->want_read = true; }else if(ret == SSL_ERROR_WANT_WRITE){ mosq->want_write = true; }else{ COMPAT_CLOSE(sock); return MOSQ_ERR_TLS; } } } #endif mosq->sock = sock; return MOSQ_ERR_SUCCESS; }
bool SSLSocket::Initialize() { //Initializing OpenSSL SSL_load_error_strings(); SSL_library_init(); OpenSSL_add_all_algorithms(); //Initializing SSL context and SSL method in this case I use SSLv23_client_method (Negotiate highest available SSL / TLS version) sslContext = SSL_CTX_new(SSLv23_client_method()); if (sslContext == nullptr) { LOGI("SSL_CTX_new error"); LOGI("%s\n", ERR_error_string(ERR_get_error(), NULL)); return false; } //Configure SSL_CTX //Load the certificateAuthority (trustStore) if (NetworkSecurityOptions::certificateAuthority.empty() != SSL_SUCCESS) { if (!SSL_CTX_load_verify_locations(sslContext, NetworkSecurityOptions::certificateAuthority.c_str(), nullptr)) { LOGI("SSL_CTX_load_verify_locations error"); LOGI("%s\n", ERR_error_string(ERR_get_error(), NULL)); SSL_CTX_free(sslContext); sslContext = nullptr; return false; } } else if (SSL_CTX_set_default_verify_paths(sslContext) != SSL_SUCCESS) { LOGI("SSL_CTX_set_default_verify_paths error"); LOGI("%s\n", ERR_error_string(ERR_get_error(), NULL)); SSL_CTX_free(sslContext); sslContext = nullptr; return false; } //Load the client's certificate (keyStore) if (!NetworkSecurityOptions::clientCertificate.empty()) { if (SSL_CTX_use_certificate_file(sslContext, NetworkSecurityOptions::clientCertificate.c_str(), SSL_FILETYPE_PEM) != SSL_SUCCESS) { LOGI("SSL_CTX_use_certificate_file error"); LOGI("%s\n", ERR_error_string(ERR_get_error(), NULL)); SSL_CTX_free(sslContext); sslContext = nullptr; return false; } std::string clientPrivateKey; if (NetworkSecurityOptions::clientPrivateKey.empty()) { clientPrivateKey = NetworkSecurityOptions::clientCertificate; //The client's private key is in client certificate } else { clientPrivateKey = NetworkSecurityOptions::clientPrivateKey; //Load client's private key if it is not included in client's certificate (keyStore) } //Load private key password if it's exist //Note you should call these function before calling SSL_CTX_use_PrivateKey_file if (!NetworkSecurityOptions::clientPrivateKeyPassword.empty()) { SSL_CTX_set_default_passwd_cb(sslContext, PemPasswordCallback); SSL_CTX_set_default_passwd_cb_userdata(sslContext, (void*)NetworkSecurityOptions::clientPrivateKeyPassword.c_str()); } if (SSL_CTX_use_PrivateKey_file(sslContext, clientPrivateKey.c_str(), SSL_FILETYPE_PEM) != SSL_SUCCESS) { LOGI("SSL_CTX_use_PrivateKey_file error"); LOGI("%s\n", ERR_error_string(ERR_get_error(), NULL)); SSL_CTX_free(sslContext); sslContext = nullptr; return false; } } // Set list of cipher if (SSL_CTX_set_cipher_list(sslContext, "DEFAULT") != SSL_SUCCESS) { LOGI("SSL_CTX_set_cipher_list error"); LOGI("%s\n", ERR_error_string(ERR_get_error(), NULL)); SSL_CTX_free(sslContext); sslContext = nullptr; return false; } SSL_CTX_set_mode(sslContext, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE); if (NetworkSecurityOptions::enableServerCertificate) { SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER, nullptr); SSL_CTX_set_verify_depth(sslContext, 1); } ssl = SSL_new(sslContext); if (ssl == nullptr) { LOGI("SSL_new error"); LOGI("%s\n", ERR_error_string(ERR_get_error(), NULL)); SSL_CTX_free(sslContext); sslContext = nullptr; return false; } return true; }
int tnet_transport_tls_set_certs(tnet_transport_handle_t *handle, const char* ca, const char* pbk, const char* pvk, tsk_bool_t verify) { tnet_transport_t *transport = handle; static const char* ssl_password = tsk_null; if (!transport) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } tsk_strupdate(&transport->tls.ca, ca); tsk_strupdate(&transport->tls.pvk, pvk); tsk_strupdate(&transport->tls.pbk, pbk); transport->tls.verify = verify; #if HAVE_OPENSSL { int32_t i, ret; SSL_CTX* contexts[3] = { tsk_null }; /* init DTLS/TLS contexts */ if ((ret = _tnet_transport_ssl_init(transport))){ return ret; } if (transport->tls.enabled){ contexts[0] = transport->tls.ctx_client; contexts[1] = transport->tls.ctx_server; } if (transport->dtls.enabled){ contexts[2] = transport->dtls.ctx; /* Reset fingerprints */ memset(transport->dtls.fingerprints, 0, sizeof(transport->dtls.fingerprints)); } for (i = 0; i < sizeof(contexts) / sizeof(contexts[0]); ++i){ if (!contexts[i]){ continue; } SSL_CTX_set_verify(contexts[i], transport->tls.verify ? (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT) : SSL_VERIFY_NONE, tsk_null); if (!tsk_strnullORempty(transport->tls.pbk) || !tsk_strnullORempty(transport->tls.pvk) || !tsk_strnullORempty(transport->tls.ca)){ /* Sets Public key (cert) */ if (!tsk_strnullORempty(transport->tls.pbk) && (ret = SSL_CTX_use_certificate_file(contexts[i], transport->tls.pbk, SSL_FILETYPE_PEM)) != 1) { TSK_DEBUG_ERROR("SSL_CTX_use_certificate_file failed [%d,%s]", ret, ERR_error_string(ERR_get_error(), tsk_null)); return -3; } /*Sets the password of the private key*/ if (!tsk_strnullORempty(ssl_password)){ SSL_CTX_set_default_passwd_cb_userdata(contexts[i], (void*)ssl_password); } /* Sets Private key (cert) */ if (!tsk_strnullORempty(transport->tls.pvk) && (ret = SSL_CTX_use_PrivateKey_file(contexts[i], transport->tls.pvk, SSL_FILETYPE_PEM)) != 1) { TSK_DEBUG_ERROR("SSL_CTX_use_PrivateKey_file failed [%d,%s]", ret, ERR_error_string(ERR_get_error(), tsk_null)); return -4; } /* Checks private key */ if (!tsk_strnullORempty(transport->tls.pvk) && SSL_CTX_check_private_key(contexts[i]) == 0) { TSK_DEBUG_ERROR("SSL_CTX_check_private_key failed [%d,%s]", ret, ERR_error_string(ERR_get_error(), tsk_null)); return -5; } /* Sets trusted CAs and CA file */ if (!tsk_strnullORempty(transport->tls.ca) && (ret = SSL_CTX_load_verify_locations(contexts[i], transport->tls.ca, /*tlsdir_cas*/tsk_null)) != 1) { TSK_DEBUG_ERROR("SSL_CTX_load_verify_locations failed [%d, %s]", ret, ERR_error_string(ERR_get_error(), tsk_null)); return -5; } } } } #endif /* HAVE_OPENSSL */ return 0; }
static int ma_tls_set_certs(MYSQL *mysql) { char *certfile= mysql->options.ssl_cert, *keyfile= mysql->options.ssl_key; /* add cipher */ if ((mysql->options.ssl_cipher && mysql->options.ssl_cipher[0] != 0) && SSL_CTX_set_cipher_list(SSL_context, mysql->options.ssl_cipher) == 0) goto error; /* ca_file and ca_path */ if (SSL_CTX_load_verify_locations(SSL_context, mysql->options.ssl_ca, mysql->options.ssl_capath) == 0) { if (mysql->options.ssl_ca || mysql->options.ssl_capath) goto error; if (SSL_CTX_set_default_verify_paths(SSL_context) == 0) goto error; } if (keyfile && !certfile) certfile= keyfile; if (certfile && !keyfile) keyfile= certfile; /* set cert */ if (certfile && certfile[0] != 0) if (SSL_CTX_use_certificate_file(SSL_context, certfile, SSL_FILETYPE_PEM) != 1) goto error; /* If the private key file is encrypted, we need to register a callback function * for providing password. */ if (OPT_HAS_EXT_VAL(mysql, tls_pw)) { SSL_CTX_set_default_passwd_cb_userdata(SSL_context, (void *)mysql->options.extension->tls_pw); SSL_CTX_set_default_passwd_cb(SSL_context, ma_tls_get_password); } if (keyfile && keyfile[0]) { if (SSL_CTX_use_PrivateKey_file(SSL_context, keyfile, SSL_FILETYPE_PEM) != 1) { unsigned long err= ERR_peek_error(); if (!(ERR_GET_LIB(err) == ERR_LIB_X509 && ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE)) goto error; } } if (OPT_HAS_EXT_VAL(mysql, tls_pw)) { SSL_CTX_set_default_passwd_cb_userdata(SSL_context, NULL); SSL_CTX_set_default_passwd_cb(SSL_context, NULL); } /* verify key */ if (certfile && !SSL_CTX_check_private_key(SSL_context)) goto error; if (mysql->options.extension && (mysql->options.extension->ssl_crl || mysql->options.extension->ssl_crlpath)) { X509_STORE *certstore; if ((certstore= SSL_CTX_get_cert_store(SSL_context))) { if (X509_STORE_load_locations(certstore, mysql->options.extension->ssl_crl, mysql->options.extension->ssl_crlpath) == 0) goto error; X509_STORE_set_flags(certstore, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); } } return 0; error: ma_tls_set_error(mysql); return 1; }
int sslctx_init() { #if 0 BIO *bio = NULL; X509 *cert = NULL; STACK_OF(X509) *ca = NULL; EVP_PKEY *pkey =NULL; PKCS12* p12 = NULL; X509_STORE *store =NULL; int error_code =0; #endif int ret =0; print_client_cert(CERT_PATH); //registers the libssl error strings SSL_load_error_strings(); //registers the available SSL/TLS ciphers and digests SSL_library_init(); //creates a new SSL_CTX object as framework to establish TLS/SSL g_sslctx = SSL_CTX_new(SSLv23_client_method()); if(g_sslctx == NULL){ ret = -1; goto end; } //passwd is supplied to protect the private key,when you want to read key SSL_CTX_set_default_passwd_cb_userdata(g_sslctx,"1111"); //set cipher ,when handshake client will send the cipher list to server SSL_CTX_set_cipher_list(g_sslctx,"HIGH:MEDIA:LOW:!DH"); //SSL_CTX_set_cipher_list(g_sslctx,"AES128-SHA"); //set verify ,when recive the server certificate and verify it //and verify_cb function will deal the result of verification SSL_CTX_set_verify(g_sslctx, SSL_VERIFY_PEER, verify_cb); //sets the maximum depth for the certificate chain verification that shall //be allowed for ctx SSL_CTX_set_verify_depth(g_sslctx, 10); //load the certificate for verify server certificate, CA file usually load SSL_CTX_load_verify_locations(g_sslctx,CAFILE, NULL); //load user certificate,this cert will be send to server for server verify if(SSL_CTX_use_certificate_file(g_sslctx,CERT_PATH,SSL_FILETYPE_PEM) <= 0){ printf("certificate file error!\n"); ret = -1; goto end; } //load user private key if(SSL_CTX_use_PrivateKey_file(g_sslctx,KEY_PATH,SSL_FILETYPE_PEM) <= 0){ printf("privatekey file error!\n"); ret = -1; goto end; } if(!SSL_CTX_check_private_key(g_sslctx)){ printf("Check private key failed!\n"); ret = -1; goto end; } end: return ret; }
SSL *SSL_new_from_context(SSL_CTX *ctx, stream *stream) /* {{{ */ { zval **val = NULL; char *cafile = NULL; char *capath = NULL; char *certfile = NULL; char *cipherlist = NULL; int ok = 1; ERR_clear_error(); /* look at context options in the stream and set appropriate verification flags */ if (GET_VER_OPT("verify_peer") && zval_is_true(*val)) { /* turn on verification callback */ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback); /* CA stuff */ GET_VER_OPT_STRING("cafile", cafile); GET_VER_OPT_STRING("capath", capath); if (cafile || capath) { if (!SSL_CTX_load_verify_locations(ctx, cafile, capath)) { error_docref(NULL, E_WARNING, "Unable to set verify locations `%s' `%s'", cafile, capath); return NULL; } } if (GET_VER_OPT("verify_depth")) { convert_to_long_ex(val); SSL_CTX_set_verify_depth(ctx, Z_LVAL_PP(val)); } } else { SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); } /* callback for the passphrase (for localcert) */ if (GET_VER_OPT("passphrase")) { SSL_CTX_set_default_passwd_cb_userdata(ctx, stream); SSL_CTX_set_default_passwd_cb(ctx, passwd_callback); } GET_VER_OPT_STRING("ciphers", cipherlist); if (!cipherlist) { cipherlist = "DEFAULT"; } if (SSL_CTX_set_cipher_list(ctx, cipherlist) != 1) { return NULL; } GET_VER_OPT_STRING("local_cert", certfile); if (certfile) { X509 *cert = NULL; EVP_PKEY *key = NULL; SSL *tmpssl; char resolved_path_buff[MAXPATHLEN]; const char * private_key = NULL; if (VCWD_REALPATH(certfile, resolved_path_buff)) { /* a certificate to use for authentication */ if (SSL_CTX_use_certificate_chain_file(ctx, resolved_path_buff) != 1) { error_docref(NULL, E_WARNING, "Unable to set local cert chain file `%s'; Check that your cafile/capath settings include details of your certificate and its issuer", certfile); return NULL; } GET_VER_OPT_STRING("local_pk", private_key); if (private_key) { char resolved_path_buff_pk[MAXPATHLEN]; if (VCWD_REALPATH(private_key, resolved_path_buff_pk)) { if (SSL_CTX_use_PrivateKey_file(ctx, resolved_path_buff_pk, SSL_FILETYPE_PEM) != 1) { error_docref(NULL, E_WARNING, "Unable to set private key file `%s'", resolved_path_buff_pk); return NULL; } } } else { if (SSL_CTX_use_PrivateKey_file(ctx, resolved_path_buff, SSL_FILETYPE_PEM) != 1) { error_docref(NULL, E_WARNING, "Unable to set private key file `%s'", resolved_path_buff); return NULL; } } tmpssl = SSL_new(ctx); cert = SSL_get_certificate(tmpssl); if (cert) { key = X509_get_pubkey(cert); EVP_PKEY_copy_parameters(key, SSL_get_privatekey(tmpssl)); EVP_PKEY_free(key); } SSL_free(tmpssl); if (!SSL_CTX_check_private_key(ctx)) { error_docref(NULL, E_WARNING, "Private key does not match certificate!"); } } } if (ok) { SSL *ssl = SSL_new(ctx); if (ssl) { /* map SSL => stream */ SSL_set_ex_data(ssl, ssl_stream_data_index, stream); } return ssl; } return NULL; }