/* * Load precomputed DH parameters. * * To prevent "downgrade" attacks, we perform a number of checks * to verify that the DBA-generated DH parameters file contains * what we expect it to contain. */ static DH * load_dh_file(int keylength) { FILE *fp; char fnbuf[MAXPGPATH]; DH *dh = NULL; int codes; /* attempt to open file. It's not an error if it doesn't exist. */ snprintf(fnbuf, sizeof(fnbuf), "dh%d.pem", keylength); if ((fp = fopen(fnbuf, "r")) == NULL) return NULL; /* flock(fileno(fp), LOCK_SH); */ dh = PEM_read_DHparams(fp, NULL, NULL, NULL); /* flock(fileno(fp), LOCK_UN); */ fclose(fp); /* is the prime the correct size? */ if (dh != NULL && 8 * DH_size(dh) < keylength) { elog(LOG, "DH errors (%s): %d bits expected, %d bits found", fnbuf, keylength, 8 * DH_size(dh)); dh = NULL; } /* make sure the DH parameters are usable */ if (dh != NULL) { if (DH_check(dh, &codes) == 0) { elog(LOG, "DH_check error (%s): %s", fnbuf, SSLerrmessage()); return NULL; } if (codes & DH_CHECK_P_NOT_PRIME) { elog(LOG, "DH error (%s): p is not prime", fnbuf); return NULL; } if ((codes & DH_NOT_SUITABLE_GENERATOR) && (codes & DH_CHECK_P_NOT_SAFE_PRIME)) { elog(LOG, "DH error (%s): neither suitable generator or safe prime", fnbuf); return NULL; } } return dh; }
static ret_t try_read_dh_param(cherokee_config_node_t *conf, DH **dh, int bitsize) { ret_t ret; cherokee_buffer_t *buf; FILE *paramfile = NULL; cherokee_buffer_t confentry = CHEROKEE_BUF_INIT; cherokee_buffer_add_va (&confentry, "dh_param%d", bitsize); /* Read the configuration parameter */ ret = cherokee_config_node_read (conf, confentry.buf, &buf); if (ret != ret_ok) { ret = ret_ok; goto out; } /* Read the file */ paramfile = fopen (buf->buf, "r"); if (paramfile == NULL) { TRACE(ENTRIES, "Cannot open file %s\n", buf->buf); ret = ret_file_not_found; goto out; } /* Process the content */ *dh = PEM_read_DHparams (paramfile, NULL, NULL, NULL); if (*dh == NULL) { TRACE(ENTRIES, "Failed to load PEM %s\n", buf->buf); ret = ret_error; goto out; } ret = ret_ok; out: /* Clean up */ if (paramfile != NULL) { fclose (paramfile); } cherokee_buffer_mrproper (&confentry); return ret; }
/* * Load DH parameters from a PEM file. * Not thread-safe. */ DH * ssl_dh_load(const char *filename) { DH *dh; FILE *fh; if (ssl_init() == -1) return NULL; if (!(fh = fopen(filename, "r"))) { return NULL; } dh = PEM_read_DHparams(fh, NULL, NULL, NULL); fclose(fh); return dh; }
int Condor_Diffie_Hellman :: initialize() { // First, check the config file to find out where is the file // with all the parameters config(); char * dh_config = param(DH_CONFIG_FILE); FILE * fp = 0; if ( dh_config ) { if ( (fp = safe_fopen_wrapper_follow(dh_config, "r")) == NULL) { dprintf(D_ALWAYS, "Unable to open condor_dh_config file %s\n", dh_config); goto error; } dh_ = PEM_read_DHparams(fp, NULL, NULL, NULL); if (dh_ == NULL) { dprintf(D_ALWAYS, "Unable to read DH structure from the configuration file.\n"); goto error; } // Now generate private key if (DH_generate_key(dh_) == 0) { dprintf(D_ALWAYS, "Unable to generate a private key \n"); goto error; } } else { dprintf(D_ALWAYS, "The required configuration parameter CONDOR_DH_CONFIG is not specified in the condor configuration file!\n"); goto error; } fclose(fp); free(dh_config); return 1; error: if (dh_) { DH_free(dh_); dh_ = 0; } if (dh_config) { free(dh_config); } if (fp) { fclose(fp); } return 0; }
/* * Load precomputed DH parameters. * * To prevent "downgrade" attacks, we perform a number of checks * to verify that the DBA-generated DH parameters file contains * what we expect it to contain. */ static DH * load_dh_file(int keylength) { char homedir[MAXPGPATH]; char fnbuf[MAXPGPATH]; FILE *fp; DH *dh; int codes; if (!pqGetHomeDirectory(homedir, sizeof(homedir))) return NULL; /* attempt to open file. It's not an error if it doesn't exist. */ snprintf(fnbuf, sizeof(fnbuf), DHFILEPATTERN, homedir, keylength); if ((fp = fopen(fnbuf, "r")) == NULL) return NULL; /* flock(fileno(fp), LOCK_SH); */ dh = PEM_read_DHparams(fp, NULL, NULL, NULL); /* flock(fileno(fp), LOCK_UN); */ fclose(fp); /* is the prime the correct size? */ if (dh != NULL && 8 * DH_size(dh) < keylength) dh = NULL; /* make sure the DH parameters are usable */ if (dh != NULL) { if (DH_check(dh, &codes)) return NULL; if (codes & DH_CHECK_P_NOT_PRIME) return NULL; if ((codes & DH_NOT_SUITABLE_GENERATOR) && (codes & DH_CHECK_P_NOT_SAFE_PRIME)) return NULL; } return dh; }
void tls_set_dh_from_file(const char *path, int bits) { FILE *paramfile; DH **dhPtr; switch (bits) { case 512: dhPtr = &dh_512; break; case 1024: dhPtr = &dh_1024; break; default: msg_panic("Invalid DH parameters size %d, file %s", bits, path); } /* * This function is the first to set the DH parameters, but free any * prior value just in case the call sequence changes some day. */ if (*dhPtr) { DH_free(*dhPtr); *dhPtr = 0; } if ((paramfile = fopen(path, "r")) != 0) { if ((*dhPtr = PEM_read_DHparams(paramfile, 0, 0, 0)) == 0) { msg_warn("cannot load %d-bit DH parameters from file %s" " -- using compiled-in defaults", bits, path); tls_print_errors(); } (void) fclose(paramfile); /* 200411 */ } else { msg_warn("cannot load %d-bit DH parameters from file %s: %m" " -- using compiled-in defaults", bits, path); } }
static bool Load_DH_params(void) { #ifdef HAVE_LIBSSL FILE *fp; bool ret = true; if (!Conf_SSLOptions.DHFile) { Log(LOG_NOTICE, "Configuration option \"DHFile\" not set!"); return false; } fp = fopen(Conf_SSLOptions.DHFile, "r"); if (!fp) { Log(LOG_ERR, "%s: %s", Conf_SSLOptions.DHFile, strerror(errno)); return false; } dh_params = PEM_read_DHparams(fp, NULL, NULL, NULL); if (!dh_params) { Log(LOG_ERR, "%s: Failed to read SSL DH parameters!", Conf_SSLOptions.DHFile); ret = false; } fclose(fp); return ret; #endif #ifdef HAVE_LIBGNUTLS bool need_dhgenerate = true; int err; gnutls_dh_params_t tmp_dh_params; err = gnutls_dh_params_init(&tmp_dh_params); if (err < 0) { Log(LOG_ERR, "Failed to initialize SSL DH parameters: %s", gnutls_strerror(err)); return false; } if (Conf_SSLOptions.DHFile) { gnutls_datum_t dhparms; size_t size; dhparms.data = (unsigned char *) openreadclose(Conf_SSLOptions.DHFile, &size); if (dhparms.data) { dhparms.size = size; err = gnutls_dh_params_import_pkcs3(tmp_dh_params, &dhparms, GNUTLS_X509_FMT_PEM); if (err == 0) need_dhgenerate = false; else Log(LOG_ERR, "Failed to initialize SSL DH parameters: %s", gnutls_strerror(err)); memset(dhparms.data, 0, size); free(dhparms.data); } } if (need_dhgenerate) { Log(LOG_WARNING, "DHFile not set, generating %u bit DH parameters. This may take a while ...", DH_BITS); err = gnutls_dh_params_generate2(tmp_dh_params, DH_BITS); if (err < 0) { Log(LOG_ERR, "Failed to generate SSL DH parameters: %s", gnutls_strerror(err)); return false; } } dh_params = tmp_dh_params; return true; #endif }
int main(int arc, char** argv) { char* server_port = "5000"; char* server_ip = "127.0.0.1"; char* cert_file = "client.crt"; char* key_file = "client.key"; // Command Line generation of Diffie-Hellman parameters // openssl dhparam -out dh_param_2048.pem 2048 char* dh_file = "dh_param_2048_client.pem"; DH *dh_2048 = NULL; FILE *paramfile; int err; int sockfd; struct addrinfo hints; struct addrinfo *server; const SSL_METHOD *ssl_meth; SSL_CTX *ctx; /* Load encryption & hashing algorithms for the SSL program */ SSL_library_init(); /* Load the error strings for SSL & CRYPTO APIs */ SSL_load_error_strings(); /* Use SSLv3 for the connection */ ssl_meth = SSLv23_client_method(); /* Create a new context--stores configuration for SSL */ ctx = SSL_CTX_new(ssl_meth); if (!ctx) error("Error creating SSL context.\n"); printf("Setting the local certificates and keys...\n"); /* Set the local certificates and keys */ err = SSL_CTX_use_certificate_file(ctx, cert_file, SSL_FILETYPE_PEM); if (err <= 0) { ERR_print_errors_fp(stderr); fprintf(stderr, "Error setting the certificate file.\n"); goto out; } err = SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM); if (err <= 0) { ERR_print_errors_fp(stderr); fprintf(stderr, "Error setting the private key file.\n"); goto out; } /* Verify private key and public crt combination. */ if (!SSL_CTX_check_private_key(ctx)) { fprintf(stderr, "Error, private key does not match public key.\n"); goto out; } /* Set up ephemeral DH parameters. */ paramfile = fopen(dh_file, "r"); if (!paramfile) { fprintf(stderr, "Error opening Diffie-Hellman parameters.\n"); goto out; } dh_2048 = PEM_read_DHparams(paramfile, NULL, NULL, NULL); err = fclose(paramfile); if (err) { fprintf(stderr, "Error closing file stream.\n"); goto out; } if (!dh_2048) { fprintf(stderr, "Error reading Diffie-Hellman parameters.\n"); goto out; } err = SSL_CTX_set_tmp_dh(ctx, dh_2048); if (err != 1) { fprintf(stderr, "Error setting Diffie-Hellman into SSL context\n"); goto out; } /*--- Standard TCP server setup and connection ---*/ printf("Creating TCP/IP socket...\n"); { SSL *ssl; int bytes = 0; char *msg = "Hello!"; char buf[256]; memset(&buf, 0, sizeof(buf)); /* The hints struct is used to specify what kind of server info * we are looking for. */ memset(&hints, 0, sizeof hints); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; /* or SOCK_DGRAM */ /* getaddrinfo() gives us back a server address we can connect to. It actually gives us a linked list of addresses, but we'll just use the first. */ err = getaddrinfo(server_ip, server_port, &hints, &server); if (err) { fprintf(stderr, "Error getting address information.\n"); goto out; } /* Now we can create the socket and connect */ sockfd = socket(server->ai_family, server->ai_socktype, server->ai_protocol); if (sockfd == -1) { fprintf(stderr, "Error opening socket.\n"); freeaddrinfo(server); goto out; } err = connect(sockfd, server->ai_addr, server->ai_addrlen); if (err == -1) { fprintf(stderr, "Error on connect.\n"); close(sockfd); freeaddrinfo(server); goto out; } ssl = SSL_new(ctx); if (!ssl) { fprintf(stderr, "Error creating a new SSL structure.\n"); ERR_print_errors_fp(stderr); close(sockfd); freeaddrinfo(server); goto out; } SSL_set_fd(ssl, sockfd); /* set connection to SSL state */ err = SSL_connect(ssl); if (err < 1) { err = SSL_get_error(ssl,err); printf("SSL error #%d in accept.\n", err); ERR_print_errors_fp(stderr); SSL_free(ssl); close(sockfd); freeaddrinfo(server); goto out; } /* Print out connection details */ printf("SSL connection on socket %x, Version: %s, Cipher: %s\ \n", sockfd, SSL_get_version(ssl), SSL_get_cipher(ssl)); err = SSL_write(ssl, msg, strlen(msg) + 1); if (err < 0) { printf("sslerror:%d\n", SSL_get_error(ssl, err)); ERR_print_errors_fp(stderr); SSL_free(ssl); close(sockfd); freeaddrinfo(server); goto out; } while(bytes <= 0) bytes = SSL_read(ssl, buf, sizeof(buf) - 1); printf("Received: %s\n", buf); err = SSL_shutdown(ssl); if (err < 0) printf("Error in SSL shutdown\n"); else if (err == 1) printf("Client exited gracefully\n"); /* close connection & clean up */ SSL_free(ssl); close(sockfd); freeaddrinfo(server); } out: SSL_CTX_free(ctx); return 0; }
//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; }
// .. c:function:: ch_error_t ch_en_start(ch_encryption_t* enc) // :noindex: // // see: :c:func:`ch_en_start` // // .. code-block:: cpp // { ch_chirp_t* chirp = enc->chirp; A(chirp->_init == CH_CHIRP_MAGIC, "Not a ch_chirp_t*"); ch_chirp_int_t* ichirp = chirp->_; if(!_ch_en_manual_openssl) { int tmp_err; _ch_en_openssl_ref_count += 1; L( chirp, "Initializing the OpenSSL library. ch_chirp_t:%p", (void*) chirp ); tmp_err = ch_en_openssl_init(); if(tmp_err != CH_SUCCESS) { L( chirp, "Could not initialize the OpenSSL library. ch_chirp_t:%p", (void*) chirp ); return tmp_err; } } const SSL_METHOD* method = TLSv1_2_method(); if(method == NULL) { E( chirp, "Could not get the TLSv1_2_method. ch_chirp_t:%p", (void*) chirp ); return CH_TLS_ERROR; } enc->ssl_ctx = SSL_CTX_new(method); if(enc->ssl_ctx == NULL) { E( chirp, "Could create the SSL_CTX. ch_chirp_t:%p", (void*) chirp ); return CH_TLS_ERROR; } SSL_CTX_set_mode( enc->ssl_ctx, SSL_MODE_AUTO_RETRY | SSL_MODE_ENABLE_PARTIAL_WRITE ); SSL_CTX_set_options(enc->ssl_ctx, SSL_OP_NO_COMPRESSION); SSL_CTX_set_verify( enc->ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL ); SSL_CTX_set_verify_depth(enc->ssl_ctx, 5); if(SSL_CTX_load_verify_locations( enc->ssl_ctx, ichirp->config.CERT_CHAIN_PEM, NULL ) != 1) { E( chirp, "Could not set the verification certificate " "%s. ch_chirp_t:%p", ichirp->config.CERT_CHAIN_PEM, (void*) chirp ); return CH_TLS_ERROR; } if(SSL_CTX_use_certificate_chain_file( enc->ssl_ctx, ichirp->config.CERT_CHAIN_PEM ) != 1) { E( chirp, "Could not set the certificate %s. ch_chirp_t:%p", ichirp->config.CERT_CHAIN_PEM, (void*) chirp ); return CH_TLS_ERROR; } if(SSL_CTX_use_PrivateKey_file( enc->ssl_ctx, ichirp->config.CERT_CHAIN_PEM, SSL_FILETYPE_PEM ) != 1) { E( chirp, "Could not set the private key %s. ch_chirp_t:%p", ichirp->config.CERT_CHAIN_PEM, (void*) chirp ); return CH_TLS_ERROR; } if(SSL_CTX_check_private_key(enc->ssl_ctx) != 1) { E( chirp, "Private key is not valid %s. ch_chirp_t:%p", ichirp->config.CERT_CHAIN_PEM, (void*) chirp ); return CH_TLS_ERROR; } DH *dh = NULL; FILE *paramfile; paramfile = fopen(ichirp->config.DH_PARAMS_PEM, "r"); if(paramfile == NULL) { E( chirp, "Could not open the dh-params %s. ch_chirp_t:%p", ichirp->config.DH_PARAMS_PEM, (void*) chirp ); return CH_TLS_ERROR; } dh = PEM_read_DHparams(paramfile, NULL, NULL, NULL); fclose(paramfile); if(dh == NULL) { E( chirp, "Could not load the dh-params %s. ch_chirp_t:%p", ichirp->config.DH_PARAMS_PEM, (void*) chirp ); return CH_TLS_ERROR; } if(SSL_CTX_set_tmp_dh(enc->ssl_ctx, dh) != 1) { E( chirp, "Could not set the dh-params %s. ch_chirp_t:%p", ichirp->config.DH_PARAMS_PEM, (void*) chirp ); return CH_TLS_ERROR; } if(SSL_CTX_set_cipher_list( enc->ssl_ctx, "-ALL:" "DHE-DSS-AES256-GCM-SHA384:" "DHE-RSA-AES256-GCM-SHA384:" "DHE-RSA-AES256-SHA256:" "DHE-DSS-AES256-SHA256:" ) != 1) { E( chirp, "Could not set the cipher list. ch_chirp_t:%p", (void*) chirp ); return CH_TLS_ERROR; } L( chirp, "Created SSL context for chirp. ch_chirp_t:%p", (void*) chirp ); return CH_SUCCESS; }
int rb_setup_ssl_server(const char *certfile, const char *keyfile, const char *dhfile, const char *cipher_list) { const char librb_ciphers[] = "kEECDH+HIGH:kEDH+HIGH:HIGH:!aNULL"; #ifdef LRB_HAVE_TLS_SET_CURVES const char librb_curves[] = "P-521:P-384:P-256"; #endif if(certfile == NULL) { rb_lib_log("rb_setup_ssl_server: No certificate file"); return 0; } if(keyfile == NULL) keyfile = certfile; if(cipher_list == NULL) cipher_list = librb_ciphers; if (ssl_server_ctx) SSL_CTX_free(ssl_server_ctx); if (ssl_client_ctx) SSL_CTX_free(ssl_client_ctx); #ifdef LRB_HAVE_TLS_METHOD_API ssl_server_ctx = SSL_CTX_new(TLS_server_method()); ssl_client_ctx = SSL_CTX_new(TLS_client_method()); #else ssl_server_ctx = SSL_CTX_new(SSLv23_server_method()); ssl_client_ctx = SSL_CTX_new(SSLv23_client_method()); #endif if(ssl_server_ctx == NULL) { rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL server context: %s", get_ssl_error(ERR_get_error())); return 0; } if(ssl_client_ctx == NULL) { rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL client context: %s", get_ssl_error(ERR_get_error())); return 0; } #ifndef LRB_HAVE_TLS_METHOD_API SSL_CTX_set_options(ssl_server_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); SSL_CTX_set_options(ssl_client_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); #endif #ifdef SSL_OP_SINGLE_DH_USE SSL_CTX_set_options(ssl_server_ctx, SSL_OP_SINGLE_DH_USE); #endif #ifdef SSL_OP_SINGLE_ECDH_USE SSL_CTX_set_options(ssl_server_ctx, SSL_OP_SINGLE_ECDH_USE); #endif #ifdef SSL_OP_NO_TICKET SSL_CTX_set_options(ssl_server_ctx, SSL_OP_NO_TICKET); SSL_CTX_set_options(ssl_client_ctx, SSL_OP_NO_TICKET); #endif #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE SSL_CTX_set_options(ssl_server_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); #endif SSL_CTX_set_verify(ssl_server_ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, verify_accept_all_cb); SSL_CTX_set_session_cache_mode(ssl_server_ctx, SSL_SESS_CACHE_OFF); #ifdef LRB_HAVE_TLS_SET_CURVES SSL_CTX_set1_curves_list(ssl_server_ctx, librb_curves); #endif #ifdef LRB_HAVE_TLS_ECDH_AUTO SSL_CTX_set_ecdh_auto(ssl_server_ctx, 1); #endif /* * Set manual ECDHE curve on OpenSSL 1.0.0 & 1.0.1, but make sure it's actually available */ #if (OPENSSL_VERSION_NUMBER >= 0x10000000L) && (OPENSSL_VERSION_NUMBER < 0x10002000L) && !defined(OPENSSL_NO_ECDH) EC_KEY *key = EC_KEY_new_by_curve_name(NID_secp384r1); if (key) { SSL_CTX_set_tmp_ecdh(ssl_server_ctx, key); EC_KEY_free(key); } #endif SSL_CTX_set_cipher_list(ssl_server_ctx, cipher_list); SSL_CTX_set_cipher_list(ssl_client_ctx, cipher_list); if(!SSL_CTX_use_certificate_chain_file(ssl_server_ctx, certfile) || !SSL_CTX_use_certificate_chain_file(ssl_client_ctx, certfile)) { rb_lib_log("rb_setup_ssl_server: Error loading certificate file [%s]: %s", certfile, get_ssl_error(ERR_get_error())); return 0; } if(!SSL_CTX_use_PrivateKey_file(ssl_server_ctx, keyfile, SSL_FILETYPE_PEM) || !SSL_CTX_use_PrivateKey_file(ssl_client_ctx, keyfile, SSL_FILETYPE_PEM)) { rb_lib_log("rb_setup_ssl_server: Error loading keyfile [%s]: %s", keyfile, get_ssl_error(ERR_get_error())); return 0; } if(dhfile != NULL) { /* DH parameters aren't necessary, but they are nice..if they didn't pass one..that is their problem */ FILE *fp = fopen(dhfile, "r"); DH *dh = NULL; if(fp == NULL) { rb_lib_log("rb_setup_ssl_server: Error loading DH params file [%s]: %s", dhfile, strerror(errno)); } else if(PEM_read_DHparams(fp, &dh, NULL, NULL) == NULL) { rb_lib_log("rb_setup_ssl_server: Error loading DH params file [%s]: %s", dhfile, get_ssl_error(ERR_get_error())); fclose(fp); } else { SSL_CTX_set_tmp_dh(ssl_server_ctx, dh); DH_free(dh); fclose(fp); } } return 1; }
virtual void OnRehash(const std::string ¶m) { if(param != "ssl") return; Conf = new ConfigReader(ServerInstance); for(unsigned int i = 0; i < listenports.size(); i++) { ServerInstance->Config->DelIOHook(listenports[i]); } listenports.clear(); for(int i = 0; i < Conf->Enumerate("bind"); i++) { // For each <bind> tag if(((Conf->ReadValue("bind", "type", i) == "") || (Conf->ReadValue("bind", "type", i) == "clients")) && (Conf->ReadValue("bind", "ssl", i) == "openssl")) { // Get the port we're meant to be listening on with SSL unsigned int port = Conf->ReadInteger("bind", "port", i, true); if (ServerInstance->Config->AddIOHook(port, this)) { // We keep a record of which ports we're listening on with SSL listenports.push_back(port); ServerInstance->Log(DEFAULT, "m_ssl_openssl.so: Enabling SSL for port %d", port); } else { ServerInstance->Log(DEFAULT, "m_ssl_openssl.so: FAILED to enable SSL on port %d, maybe you have another ssl or similar module loaded?", port); } } } std::string confdir(CONFIG_FILE); // +1 so we the path ends with a / confdir = confdir.substr(0, confdir.find_last_of('/') + 1); cafile = Conf->ReadValue("openssl", "cafile", 0); // crlfile = Conf->ReadValue("openssl", "crlfile", 0); certfile = Conf->ReadValue("openssl", "certfile", 0); keyfile = Conf->ReadValue("openssl", "keyfile", 0); dhfile = Conf->ReadValue("openssl", "dhfile", 0); // Set all the default values needed. if(cafile == "") cafile = "ca.pem"; //if(crlfile == "") // crlfile = "crl.pem"; if(certfile == "") certfile = "cert.pem"; if(keyfile == "") keyfile = "key.pem"; if(dhfile == "") dhfile = "dhparams.pem"; // Prepend relative paths with the path to the config directory. if(cafile[0] != '/') cafile = confdir + cafile; //if(crlfile[0] != '/') // crlfile = confdir + crlfile; if(certfile[0] != '/') certfile = confdir + certfile; if(keyfile[0] != '/') keyfile = confdir + keyfile; if(dhfile[0] != '/') dhfile = confdir + dhfile; /* Load our keys and certificates*/ if(!SSL_CTX_use_certificate_chain_file(ctx, certfile.c_str())) { ServerInstance->Log(DEFAULT, "m_ssl_openssl.so: Can't read certificate file %s", certfile.c_str()); } if(!SSL_CTX_use_PrivateKey_file(ctx, keyfile.c_str(), SSL_FILETYPE_PEM)) { ServerInstance->Log(DEFAULT, "m_ssl_openssl.so: Can't read key file %s", keyfile.c_str()); } /* Load the CAs we trust*/ if(!SSL_CTX_load_verify_locations(ctx, cafile.c_str(), 0)) { ServerInstance->Log(DEFAULT, "m_ssl_openssl.so: Can't read CA list from ", cafile.c_str()); } FILE* dhpfile = fopen(dhfile.c_str(), "r"); DH* ret; if(dhpfile == NULL) { ServerInstance->Log(DEFAULT, "m_ssl_openssl.so Couldn't open DH file %s: %s", dhfile.c_str(), strerror(errno)); throw ModuleException(); } else { ret = PEM_read_DHparams(dhpfile, NULL, NULL, NULL); if(SSL_CTX_set_tmp_dh(ctx, ret) < 0) { ServerInstance->Log(DEFAULT, "m_ssl_openssl.so: Couldn't set DH parameters"); } } fclose(dhpfile); DELETE(Conf); }
inline dh_key dh_key::from_parameters(file _file, pem_passphrase_callback_type callback, void* callback_arg) { return take_ownership(PEM_read_DHparams(_file.raw(), NULL, callback, callback_arg)); }