int SSL_CTX_build_cert_chain(SSL_CTX* ssl_ctx, X509** certs, int count) { int i; for (i = count - 1; i >= 0; --i) if (!SSL_CTX_add_extra_chain_cert(ssl_ctx, certs[i])) { write_out(PRINT_ERROR, "Unable to build certificate chain."); write_raise_level(); print_ssl_error_stack(PRINT_ERROR); write_lower_level(); return 0; } return 1; }
void shutdown_ssl(SSL* ssl, int sockfd, BIO* rbio, BIO* wbio) { int err; write_out(PRINT_INFO, "Attempting to gracefully shutdown TLS socket."); for (;;) { err = SSL_shutdown(ssl); if (err < 0) { err = SSL_get_error(ssl, err); switch (err) { case SSL_ERROR_WANT_WRITE: put_bio_data(sockfd, rbio, 0, 0); break; case SSL_ERROR_WANT_READ: send_bio_data(sockfd, wbio, 0, 0); if (put_bio_data(sockfd, rbio, 0, 0) <= 0) goto for_break; break; default: write_out(PRINT_WARNING, "Error in TLS shutdown!"); write_raise_level(); write_out(PRINT_ERROR, "TLS error: %d", SSL_get_error(ssl, err)); print_ssl_error_stack(PRINT_ERROR); write_lower_level(); } } else if (err == 1) break; } for_break: ; }
//SSL_CTX* init_ssl_server_ctx(const SSL_METHOD* method, const char* server_cert, const char* server_priv_key, const char* dh_params, const char* ecdh_curve, const char* ecdsa_cert, const char* ecdsa_privkey, int check_client) SSL_CTX* init_ssl_server_ctx(const SSL_METHOD* method, X509* server_cert, EVP_PKEY* server_priv_key, const char* dh_params, const char* ecdh_curve, X509* ecdsa_cert, EVP_PKEY* ecdsa_privkey, X509* root_cert) { SSL_CTX* ssl_ctx = 0; DH* dh = 0; EC_KEY* ecdh = 0; FILE* param_file = 0; X509_STORE* x509_store; int nid; //make ssl context if (!(ssl_ctx = SSL_CTX_new(method))) { write_out(PRINT_ERROR, "Unable to initialize OpenSSL."); write_raise_level(); print_ssl_error_stack(PRINT_ERROR); write_lower_level(); goto error_die; } //disable renegotiation to ensure a fresh start SSL_CTX_set_session_cache_mode(ssl_ctx, SSL_SESS_CACHE_OFF); SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_NO_TICKET); if (server_cert && server_priv_key) { //load rsa certs //if (SSL_CTX_use_certificate_file(ssl_ctx, server_cert, SSL_FILETYPE_PEM) != 1) if (SSL_CTX_use_certificate(ssl_ctx, server_cert) != 1) { write_out(PRINT_ERROR, "Unable to load RSA certificate."); write_raise_level(); print_ssl_error_stack(PRINT_ERROR); write_lower_level(); goto error_die; } if (SSL_CTX_use_PrivateKey(ssl_ctx, server_priv_key) != 1) { write_out(PRINT_ERROR, "Unable to load RSA private key."); write_raise_level(); print_ssl_error_stack(PRINT_ERROR); write_lower_level(); goto error_die; } if (!SSL_CTX_check_private_key(ssl_ctx)) { write_out(PRINT_ERROR, "RSA Certificate and private key do not match!"); goto error_die; } } if (dh_params) { //load dh params param_file = fopen(dh_params, "rb"); if (!param_file) { write_out(PRINT_ERROR, "DH Parameter file could not be read: %s", dh_params); } dh = PEM_read_DHparams(param_file, 0, 0, 0); if (!dh) { write_out(PRINT_ERROR, "DH Parameters could not be loaded!"); write_raise_level(); print_ssl_error_stack(PRINT_ERROR); write_lower_level(); goto error_die; } fclose(param_file); param_file = 0; if (SSL_CTX_set_tmp_dh(ssl_ctx, dh) != 1) { write_out(PRINT_ERROR, "DH Parameters could not be set!"); write_raise_level(); print_ssl_error_stack(PRINT_ERROR); write_lower_level(); goto error_die; } DH_free(dh); dh = 0; } if (ecdh_curve) { //load ecdh params if ((nid = OBJ_sn2nid(ecdh_curve)) == NID_undef) { write_out(PRINT_ERROR, "Unable to find elliptic curve %s.", ecdh_curve); goto error_die; } if ((ecdh = EC_KEY_new_by_curve_name(nid)) == 0) { write_out(PRINT_ERROR, "Unable to create elliptic curve %s.", ecdh_curve); goto error_die; } if (SSL_CTX_set_tmp_ecdh(ssl_ctx, ecdh) != 1) { write_out(PRINT_ERROR, "ECDH Parameters could not be set!"); write_raise_level(); print_ssl_error_stack(PRINT_ERROR); write_lower_level(); goto error_die; } EC_KEY_free(ecdh); ecdh = 0; } if (ecdsa_cert && ecdsa_privkey) { //load ecdsa certs //if (SSL_CTX_use_certificate_file(ssl_ctx, ecdsa_cert, SSL_FILETYPE_PEM) != 1) if (SSL_CTX_use_certificate(ssl_ctx, ecdsa_cert) != 1) { write_out(PRINT_ERROR, "Unable to load ECDSA certificate."); write_raise_level(); print_ssl_error_stack(PRINT_ERROR); write_lower_level(); goto error_die; } //if (SSL_CTX_use_PrivateKey_file(ssl_ctx, ecdsa_privkey, SSL_FILETYPE_PEM) != 1) if (SSL_CTX_use_PrivateKey(ssl_ctx, ecdsa_privkey) != 1) { write_out(PRINT_ERROR, "Unable to load ECDSA private key."); write_raise_level(); print_ssl_error_stack(PRINT_ERROR); write_lower_level(); goto error_die; } if (!SSL_CTX_check_private_key(ssl_ctx)) { write_out(PRINT_ERROR, "ECDSA Certificate and private key do not match!"); goto error_die; } } //setup the root_cert for verification if (root_cert) { x509_store = SSL_CTX_get_cert_store(ssl_ctx); X509_STORE_add_cert(x509_store, root_cert); } return ssl_ctx; error_die: if (ssl_ctx) SSL_CTX_free(ssl_ctx); if (param_file) fclose(param_file); if (dh) DH_free(dh); if (ecdh) EC_KEY_free(ecdh); return 0; }
int do_handshake(int sockfd, SSL* ssl, BIO* rbio, BIO* wbio, MUTATOR in_mut, void* in_state, MUTATOR out_mut, void* out_state) { int err; SSL_set_accept_state(ssl); write_out(PRINT_INFO, "Starting TLS handshake..."); write_raise_level(); while (!SSL_is_init_finished(ssl)) { //write_out(PRINT_INFO, "SSL_accept"); err = SSL_accept(ssl); if (err <= 0) { err = SSL_get_error(ssl, err); switch (err) { case SSL_ERROR_WANT_READ: //grab handshake info in the BIO and send it out to the client if there is any if (!send_bio_data(sockfd, wbio, out_mut, out_state)) { write_out(PRINT_ERROR, "TLS handshake error while sending data!"); write_lower_level(); return HANDSHAKE_UNSUCCESSFUL; } if (!put_bio_data(sockfd, rbio, in_mut, in_state)) { write_out(PRINT_ERROR, "TLS handshake error while recv'ing data!"); write_lower_level(); return HANDSHAKE_UNSUCCESSFUL; } break; case SSL_ERROR_SSL: if (ERR_peek_error() == 0x1408C095) { write_out(PRINT_ERROR, "Bad TLS finished digest."); write_lower_level(); return HANDSHAKE_BAD_DIGEST; } default: write_out(PRINT_ERROR, "TLS accept error: %d", err); print_ssl_error_stack(PRINT_ERROR); write_lower_level(); return HANDSHAKE_UNSUCCESSFUL; } } } //send the final encrypted handshake if (!send_bio_data(sockfd, wbio, out_mut, out_state)) { write_out(PRINT_ERROR, "TLS handshake error while sending data!"); write_lower_level(); return 0; } write_out(PRINT_INFO, "TLS handshake complete."); write_lower_level(); return HANDSHAKE_SUCCESSFUL; }
int irc_dcc_accept(irc_session_t * session, irc_dcc_t dccid, void * ctx, irc_dcc_callback_t callback) { irc_dcc_session_t * dcc = libirc_find_dcc_session(session, dccid, 1); if (!dcc) return 1; if (dcc->state != LIBIRC_STATE_INIT) { session->lasterror = LIBIRC_ERR_STATE; libirc_mutex_unlock(&session->mutex_dcc); return 1; } dcc->cb = callback; dcc->ctx = ctx; DBG_OK("going to socket_connect!"); // Initiate the connect if (socket_connect(&dcc->sock, (struct sockaddr *) &dcc->remote_addr, sizeof (dcc->remote_addr))) { libirc_dcc_destroy_nolock(session, dccid); libirc_mutex_unlock(&session->mutex_dcc); session->lasterror = LIBIRC_ERR_CONNECT; return 1; } #ifdef ENABLE_SSL if (dcc->ssl == 1) { DBG_OK("using ssl!"); while (1) { int err = SSL_connect(dcc->ssl_ctx); if (err <= 0) { int ssl_err = SSL_get_error(dcc->ssl_ctx, err); if (ssl_err == SSL_ERROR_WANT_READ || ssl_err == SSL_ERROR_WANT_WRITE) { continue; } else { print_ssl_error_stack(); session->lasterror = LIBIRC_ERR_CONNECT; return 1; } } DBG_OK("ssl_connect succeded!"); break; } const char *ciphers_used = "None"; ciphers_used = SSL_get_cipher_name(dcc->ssl_ctx); logprintf(LOG_INFO, "using cipher suite: %s for dcc connection", ciphers_used); } #endif DBG_OK("connect succeded2!"); dcc->state = LIBIRC_STATE_CONNECTING; #ifdef ENABLE_SSL if (dcc->ssl) { dcc->state = LIBIRC_STATE_CONNECTED; } #endif libirc_mutex_unlock(&session->mutex_dcc); return 0; }