static int __ssl_setup(struct ast_tls_config *cfg, int client) { #ifndef DO_SSL cfg->enabled = 0; return 0; #else if (!cfg->enabled) return 0; /* Get rid of an old SSL_CTX since we're about to * allocate a new one */ if (cfg->ssl_ctx) { SSL_CTX_free(cfg->ssl_ctx); cfg->ssl_ctx = NULL; } if (client) { #ifndef OPENSSL_NO_SSL2 if (ast_test_flag(&cfg->flags, AST_SSL_SSLV2_CLIENT)) { cfg->ssl_ctx = SSL_CTX_new(SSLv2_client_method()); } else #endif if (ast_test_flag(&cfg->flags, AST_SSL_SSLV3_CLIENT)) { cfg->ssl_ctx = SSL_CTX_new(SSLv3_client_method()); } else if (ast_test_flag(&cfg->flags, AST_SSL_TLSV1_CLIENT)) { cfg->ssl_ctx = SSL_CTX_new(TLSv1_client_method()); } else { /* SSLv23_client_method() sends SSLv2, this was the original * default for ssl clients before the option was given to * pick what protocol a client should use. In order not * to break expected behavior it remains the default. */ cfg->ssl_ctx = SSL_CTX_new(SSLv23_client_method()); } } else { /* SSLv23_server_method() supports TLSv1, SSLv2, and SSLv3 inbound connections. */ cfg->ssl_ctx = SSL_CTX_new(SSLv23_server_method()); } if (!cfg->ssl_ctx) { ast_debug(1, "Sorry, SSL_CTX_new call returned null...\n"); cfg->enabled = 0; return 0; } if (!ast_strlen_zero(cfg->certfile)) { char *tmpprivate = ast_strlen_zero(cfg->pvtfile) ? cfg->certfile : cfg->pvtfile; if (SSL_CTX_use_certificate_file(cfg->ssl_ctx, cfg->certfile, SSL_FILETYPE_PEM) == 0) { if (!client) { /* Clients don't need a certificate, but if its setup we can use it */ ast_verb(0, "SSL error loading cert file. <%s>", cfg->certfile); cfg->enabled = 0; SSL_CTX_free(cfg->ssl_ctx); cfg->ssl_ctx = NULL; return 0; } } if ((SSL_CTX_use_PrivateKey_file(cfg->ssl_ctx, tmpprivate, SSL_FILETYPE_PEM) == 0) || (SSL_CTX_check_private_key(cfg->ssl_ctx) == 0 )) { if (!client) { /* Clients don't need a private key, but if its setup we can use it */ ast_verb(0, "SSL error loading private key file. <%s>", tmpprivate); cfg->enabled = 0; SSL_CTX_free(cfg->ssl_ctx); cfg->ssl_ctx = NULL; return 0; } } } if (!ast_strlen_zero(cfg->cipher)) { if (SSL_CTX_set_cipher_list(cfg->ssl_ctx, cfg->cipher) == 0 ) { if (!client) { ast_verb(0, "SSL cipher error <%s>", cfg->cipher); cfg->enabled = 0; SSL_CTX_free(cfg->ssl_ctx); cfg->ssl_ctx = NULL; return 0; } } } if (!ast_strlen_zero(cfg->cafile) || !ast_strlen_zero(cfg->capath)) { if (SSL_CTX_load_verify_locations(cfg->ssl_ctx, S_OR(cfg->cafile, NULL), S_OR(cfg->capath,NULL)) == 0) ast_verb(0, "SSL CA file(%s)/path(%s) error\n", cfg->cafile, cfg->capath); } ast_verb(0, "SSL certificate ok\n"); return 1; #endif }
static int __ssl_setup(struct ast_tls_config *cfg, int client) { #ifndef DO_SSL cfg->enabled = 0; return 0; #else int disable_ssl = 0; if (!cfg->enabled) { return 0; } /* Get rid of an old SSL_CTX since we're about to * allocate a new one */ if (cfg->ssl_ctx) { SSL_CTX_free(cfg->ssl_ctx); cfg->ssl_ctx = NULL; } if (client) { #ifndef OPENSSL_NO_SSL2 if (ast_test_flag(&cfg->flags, AST_SSL_SSLV2_CLIENT)) { ast_log(LOG_WARNING, "Usage of SSLv2 is discouraged due to known vulnerabilities. Please use 'tlsv1' or leave the TLS method unspecified!\n"); cfg->ssl_ctx = SSL_CTX_new(SSLv2_client_method()); } else #endif #ifndef OPENSSL_NO_SSL3_METHOD if (ast_test_flag(&cfg->flags, AST_SSL_SSLV3_CLIENT)) { ast_log(LOG_WARNING, "Usage of SSLv3 is discouraged due to known vulnerabilities. Please use 'tlsv1' or leave the TLS method unspecified!\n"); cfg->ssl_ctx = SSL_CTX_new(SSLv3_client_method()); } else #endif if (ast_test_flag(&cfg->flags, AST_SSL_TLSV1_CLIENT)) { cfg->ssl_ctx = SSL_CTX_new(TLSv1_client_method()); } else { disable_ssl = 1; cfg->ssl_ctx = SSL_CTX_new(SSLv23_client_method()); } } else { disable_ssl = 1; cfg->ssl_ctx = SSL_CTX_new(SSLv23_server_method()); } if (!cfg->ssl_ctx) { ast_debug(1, "Sorry, SSL_CTX_new call returned null...\n"); cfg->enabled = 0; return 0; } /* Due to the POODLE vulnerability, completely disable * SSLv2 and SSLv3 if we are not explicitly told to use * them. SSLv23_*_method supports TLSv1+. */ if (disable_ssl) { long ssl_opts; ssl_opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; SSL_CTX_set_options(cfg->ssl_ctx, ssl_opts); } SSL_CTX_set_verify(cfg->ssl_ctx, ast_test_flag(&cfg->flags, AST_SSL_VERIFY_CLIENT) ? SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT : SSL_VERIFY_NONE, NULL); if (!ast_strlen_zero(cfg->certfile)) { char *tmpprivate = ast_strlen_zero(cfg->pvtfile) ? cfg->certfile : cfg->pvtfile; if (SSL_CTX_use_certificate_chain_file(cfg->ssl_ctx, cfg->certfile) == 0) { if (!client) { /* Clients don't need a certificate, but if its setup we can use it */ ast_log(LOG_ERROR, "TLS/SSL error loading cert file. <%s>\n", cfg->certfile); cfg->enabled = 0; SSL_CTX_free(cfg->ssl_ctx); cfg->ssl_ctx = NULL; return 0; } } if ((SSL_CTX_use_PrivateKey_file(cfg->ssl_ctx, tmpprivate, SSL_FILETYPE_PEM) == 0) || (SSL_CTX_check_private_key(cfg->ssl_ctx) == 0 )) { if (!client) { /* Clients don't need a private key, but if its setup we can use it */ ast_log(LOG_ERROR, "TLS/SSL error loading private key file. <%s>\n", tmpprivate); cfg->enabled = 0; SSL_CTX_free(cfg->ssl_ctx); cfg->ssl_ctx = NULL; return 0; } } } if (!ast_strlen_zero(cfg->cipher)) { if (SSL_CTX_set_cipher_list(cfg->ssl_ctx, cfg->cipher) == 0 ) { if (!client) { ast_log(LOG_ERROR, "TLS/SSL cipher error <%s>\n", cfg->cipher); cfg->enabled = 0; SSL_CTX_free(cfg->ssl_ctx); cfg->ssl_ctx = NULL; return 0; } } } if (!ast_strlen_zero(cfg->cafile) || !ast_strlen_zero(cfg->capath)) { if (SSL_CTX_load_verify_locations(cfg->ssl_ctx, S_OR(cfg->cafile, NULL), S_OR(cfg->capath,NULL)) == 0) { ast_log(LOG_ERROR, "TLS/SSL CA file(%s)/path(%s) error\n", cfg->cafile, cfg->capath); } } #ifdef HAVE_OPENSSL_EC if (!ast_strlen_zero(cfg->pvtfile)) { BIO *bio = BIO_new_file(cfg->pvtfile, "r"); if (bio != NULL) { DH *dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); if (dh != NULL) { if (SSL_CTX_set_tmp_dh(cfg->ssl_ctx, dh)) { long options = SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_SINGLE_DH_USE | SSL_OP_SINGLE_ECDH_USE; options = SSL_CTX_set_options(cfg->ssl_ctx, options); ast_verb(2, "TLS/SSL DH initialized, PFS cipher-suites enabled\n"); } DH_free(dh); } BIO_free(bio); } } #ifndef SSL_CTRL_SET_ECDH_AUTO #define SSL_CTRL_SET_ECDH_AUTO 94 #endif /* SSL_CTX_set_ecdh_auto(cfg->ssl_ctx, on); requires OpenSSL 1.0.2 which wraps: */ if (SSL_CTX_ctrl(cfg->ssl_ctx, SSL_CTRL_SET_ECDH_AUTO, 1, NULL)) { ast_verb(2, "TLS/SSL ECDH initialized (automatic), faster PFS ciphers enabled\n"); } else { /* enables AES-128 ciphers, to get AES-256 use NID_secp384r1 */ EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); if (ecdh != NULL) { if (SSL_CTX_set_tmp_ecdh(cfg->ssl_ctx, ecdh)) { ast_verb(2, "TLS/SSL ECDH initialized (secp256r1), faster PFS cipher-suites enabled\n"); } EC_KEY_free(ecdh); } } #endif /* #ifdef HAVE_OPENSSL_EC */ ast_verb(2, "TLS/SSL certificate ok\n"); /* We should log which one that is ok. This message doesn't really make sense in production use */ return 1; #endif }
int rb_init_ssl(void) { int ret = 1; char libratbox_data[] = "libratbox data"; const char libratbox_ciphers[] = "kEECDH+HIGH:kEDH+HIGH:HIGH:!RC4:!aNULL"; SSL_load_error_strings(); SSL_library_init(); libratbox_index = SSL_get_ex_new_index(0, libratbox_data, NULL, NULL, NULL); #if defined(LIBRESSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x10100000L) ssl_server_ctx = SSL_CTX_new(SSLv23_server_method()); #else ssl_server_ctx = SSL_CTX_new(TLS_server_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())); ret = 0; } long server_options = SSL_CTX_get_options(ssl_server_ctx); #if defined(LIBRESSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x10100000L) server_options |= SSL_OP_NO_SSLv2; server_options |= SSL_OP_NO_SSLv3; #endif #ifdef SSL_OP_SINGLE_DH_USE server_options |= SSL_OP_SINGLE_DH_USE; #endif #ifdef SSL_OP_SINGLE_ECDH_USE server_options |= SSL_OP_SINGLE_ECDH_USE; #endif #ifdef SSL_OP_NO_TICKET server_options |= SSL_OP_NO_TICKET; #endif server_options |= SSL_OP_CIPHER_SERVER_PREFERENCE; SSL_CTX_set_options(ssl_server_ctx, server_options); 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); SSL_CTX_set_cipher_list(ssl_server_ctx, libratbox_ciphers); /* Set ECDHE on OpenSSL 1.00+, but make sure it's actually available because redhat are dicks and bastardise their OpenSSL for stupid reasons... */ #if (OPENSSL_VERSION_NUMBER >= 0x10000000L) && defined(NID_secp384r1) 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 #if defined(LIBRESSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x10100000L) ssl_client_ctx = SSL_CTX_new(TLSv1_client_method()); #else ssl_client_ctx = SSL_CTX_new(TLS_client_method()); #endif if(ssl_client_ctx == NULL) { rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL client context: %s", get_ssl_error(ERR_get_error())); ret = 0; } #ifdef SSL_OP_NO_TICKET SSL_CTX_set_options(ssl_client_ctx, SSL_OP_NO_TICKET); #endif SSL_CTX_set_cipher_list(ssl_client_ctx, libratbox_ciphers); return ret; }
int ssl_server_init(char* ca_file, char *crt_file, char *key_file, char *dhp_file, char *ssl_cipher_list) { static const char *ssl_ctx_id = "httpd"; long ssl_options; if (!crt_file || !f_exists(crt_file)) { httpd_log("%s: Server certificate (%s) is not found!", SYSLOG_ID_SSL, crt_file); httpd_log("Please manual build the certificate via \"%s\" script.", "https-cert.sh"); return -1; } if (!key_file || !f_exists(key_file)) { httpd_log("%s: Server private key (%s) is not found!", SYSLOG_ID_SSL, key_file); httpd_log("Please manual build the certificate via \"%s\" script.", "https-cert.sh"); return -1; } SSL_load_error_strings(); SSL_library_init(); ssl_ctx = SSL_CTX_new(SSLv23_server_method()); if (!ssl_ctx) { httpd_log("%s: Unable to create SSL context!", SYSLOG_ID_SSL); return -1; } ssl_options = SSL_OP_ALL | SSL_OP_NO_COMPRESSION | SSL_OP_NO_SSLv2 | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION; SSL_CTX_set_options(ssl_ctx, ssl_options); SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_NONE, NULL); if (ssl_cipher_list && strlen(ssl_cipher_list) > 2) { if (SSL_CTX_set_cipher_list(ssl_ctx, ssl_cipher_list) != 1) { httpd_log("%s: Cannot set SSL cipher list (%s)!", SYSLOG_ID_SSL, ssl_cipher_list); } else { SSL_CTX_set_options(ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); } } if (ca_file && f_exists(ca_file)) { if (SSL_CTX_load_verify_locations(ssl_ctx, ca_file, NULL) != 1) { httpd_log("%s: Cannot load CA certificate (%s)!", SYSLOG_ID_SSL, ca_file); } } if (SSL_CTX_use_certificate_file(ssl_ctx, crt_file, SSL_FILETYPE_PEM) != 1) { httpd_log("%s: Cannot load server certificate (%s)!", SYSLOG_ID_SSL, crt_file); ssl_server_uninit(); return 1; } if (SSL_CTX_use_PrivateKey_file(ssl_ctx, key_file, SSL_FILETYPE_PEM) != 1) { httpd_log("%s: Cannot load server private key (%s)!", SYSLOG_ID_SSL, key_file); ssl_server_uninit(); return 1; } if (SSL_CTX_check_private_key(ssl_ctx) != 1) { httpd_log("%s: Private key does not match the certificate!", SYSLOG_ID_SSL); ssl_server_uninit(); return 1; } if (dhp_file && f_exists(dhp_file)) { /* DH parameters from file */ BIO *bio = BIO_new_file(dhp_file, "r"); if (bio) { DH *dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); BIO_free(bio); if (dh) { SSL_CTX_set_tmp_dh(ssl_ctx, dh); SSL_CTX_set_options(ssl_ctx, SSL_OP_SINGLE_DH_USE); DH_free(dh); } else { httpd_log("%s: Cannot load DH parameters (%s)!", SYSLOG_ID_SSL, dhp_file); } } } else { /* Default DH parameters from RFC5114 */ DH *dh = DH_new(); if (dh) { dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL); dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL); dh->length = 160; if (dh->p && dh->g) { SSL_CTX_set_tmp_dh(ssl_ctx, dh); SSL_CTX_set_options(ssl_ctx, SSL_OP_SINGLE_DH_USE); } DH_free(dh); } } SSL_CTX_set_default_read_ahead(ssl_ctx, 1); SSL_CTX_set_session_cache_mode(ssl_ctx, SSL_SESS_CACHE_SERVER); SSL_CTX_set_session_id_context(ssl_ctx, (unsigned char *)ssl_ctx_id, strlen(ssl_ctx_id)); SSL_CTX_sess_set_cache_size(ssl_ctx, 10); SSL_CTX_set_info_callback(ssl_ctx, http_ssl_info_cb); return 0; }
int main(int argc, char *argv[]) { char *port = "*:4433"; BIO *in=NULL; BIO *ssl_bio,*tmp; SSL_CTX *ctx; SSL_CONF_CTX *cctx = NULL; CONF *conf = NULL; STACK_OF(CONF_VALUE) *sect = NULL; CONF_VALUE *cnf; long errline = -1; char buf[512]; int ret=1,i; SSL_load_error_strings(); /* Add ciphers and message digests */ OpenSSL_add_ssl_algorithms(); conf = NCONF_new(NULL); if (NCONF_load(conf, "accept.cnf", &errline) <= 0) { if (errline <= 0) fprintf(stderr, "Error processing config file\n"); else fprintf(stderr, "Error on line %ld\n", errline); goto err; } sect = NCONF_get_section(conf, "default"); if (sect == NULL) { fprintf(stderr, "Error retrieving default section\n"); goto err; } ctx=SSL_CTX_new(SSLv23_server_method()); cctx = SSL_CONF_CTX_new(); SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SERVER); SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CERTIFICATE); SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_FILE); SSL_CONF_CTX_set_ssl_ctx(cctx, ctx); for (i = 0; i < sk_CONF_VALUE_num(sect); i++) { int rv; cnf = sk_CONF_VALUE_value(sect, i); rv = SSL_CONF_cmd(cctx, cnf->name, cnf->value); if (rv > 0) continue; if (rv != -2) { fprintf(stderr, "Error processing %s = %s\n", cnf->name, cnf->value); ERR_print_errors_fp(stderr); goto err; } if (!strcmp(cnf->name, "Port")) { port = cnf->value; } else { fprintf(stderr, "Unknown configuration option %s\n", cnf->name); goto err; } } if (!SSL_CONF_CTX_finish(cctx)) { fprintf(stderr, "Finish error\n"); ERR_print_errors_fp(stderr); goto err; } /* Setup server side SSL bio */ ssl_bio=BIO_new_ssl(ctx,0); if ((in=BIO_new_accept(port)) == NULL) goto err; /* This means that when a new connection is accepted on 'in', * The ssl_bio will be 'duplicated' and have the new socket * BIO push into it. Basically it means the SSL BIO will be * automatically setup */ BIO_set_accept_bios(in,ssl_bio); again: /* The first call will setup the accept socket, and the second * will get a socket. In this loop, the first actual accept * will occur in the BIO_read() function. */ if (BIO_do_accept(in) <= 0) goto err; for (;;) { i=BIO_read(in,buf,512); if (i == 0) { /* If we have finished, remove the underlying * BIO stack so the next time we call any function * for this BIO, it will attempt to do an * accept */ printf("Done\n"); tmp=BIO_pop(in); BIO_free_all(tmp); goto again; } if (i < 0) { if (BIO_should_retry(in)) continue; goto err; } fwrite(buf,1,i,stdout); fflush(stdout); } ret=0; err: if (ret) { ERR_print_errors_fp(stderr); } if (in != NULL) BIO_free(in); exit(ret); return(!ret); }
static Ecore_Con_Ssl_Error _ecore_con_ssl_server_prepare_openssl(Ecore_Con_Server *svr, int ssl_type) { long options; int dh = 0; if (ssl_type & ECORE_CON_USE_SSL2) return ECORE_CON_SSL_ERROR_SSL2_NOT_SUPPORTED; switch (ssl_type) { case ECORE_CON_USE_SSL3: case ECORE_CON_USE_SSL3 | ECORE_CON_LOAD_CERT: if (!svr->created) SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl_ctx = SSL_CTX_new(SSLv3_client_method()))); else SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl_ctx = SSL_CTX_new(SSLv3_server_method()))); break; case ECORE_CON_USE_TLS: case ECORE_CON_USE_TLS | ECORE_CON_LOAD_CERT: if (!svr->created) SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl_ctx = SSL_CTX_new(TLSv1_client_method()))); else SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl_ctx = SSL_CTX_new(TLSv1_server_method()))); break; case ECORE_CON_USE_MIXED: case ECORE_CON_USE_MIXED | ECORE_CON_LOAD_CERT: if (!svr->created) SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl_ctx = SSL_CTX_new(SSLv23_client_method()))); else SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl_ctx = SSL_CTX_new(SSLv23_server_method()))); options = SSL_CTX_get_options(svr->ssl_ctx); SSL_CTX_set_options(svr->ssl_ctx, options | SSL_OP_NO_SSLv2 | SSL_OP_SINGLE_DH_USE); break; default: return ECORE_CON_SSL_ERROR_NONE; } if ((!svr->use_cert) && svr->created) { DH *dh_params; INF("Generating DH params"); SSL_ERROR_CHECK_GOTO_ERROR(!(dh_params = DH_new())); SSL_ERROR_CHECK_GOTO_ERROR(!DH_generate_parameters_ex(dh_params, 1024, DH_GENERATOR_5, NULL)); SSL_ERROR_CHECK_GOTO_ERROR(!DH_check(dh_params, &dh)); SSL_ERROR_CHECK_GOTO_ERROR((dh & DH_CHECK_P_NOT_PRIME) || (dh & DH_CHECK_P_NOT_SAFE_PRIME)); SSL_ERROR_CHECK_GOTO_ERROR(!DH_generate_key(dh_params)); SSL_ERROR_CHECK_GOTO_ERROR(!SSL_CTX_set_tmp_dh(svr->ssl_ctx, dh_params)); DH_free(dh_params); INF("DH params successfully generated and applied!"); SSL_ERROR_CHECK_GOTO_ERROR(!SSL_CTX_set_cipher_list(svr->ssl_ctx, "aNULL:!eNULL:!LOW:!EXPORT:@STRENGTH")); } else if (!svr->use_cert) SSL_ERROR_CHECK_GOTO_ERROR(!SSL_CTX_set_cipher_list(svr->ssl_ctx, "aNULL:!eNULL:!LOW:!EXPORT:!ECDH:RSA:AES:!PSK:@STRENGTH")); return ECORE_CON_SSL_ERROR_NONE; error: if (dh) { if (dh & DH_CHECK_P_NOT_PRIME) ERR("openssl error: dh_params could not generate a prime!"); else ERR("openssl error: dh_params could not generate a safe prime!"); } else _openssl_print_errors(); _ecore_con_ssl_server_shutdown_openssl(svr); return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED; }
int InitSSLStuff(void) { dbg("Enabling SSL security system\n"); #ifdef INET6 if ((server_ssl = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP)) == -1) { DIE("NO_CREATE_SOCKET"); return 0; } #else if ((server_ssl = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1){ dbg("Couldn't create socket for ssl\n"); DIE("NO_CREATE_SOCKET"); return 0; } #endif /*INET6*/ /* server socket is nonblocking */ if (fcntl(server_ssl, F_SETFL, NOBLOCK) == -1){ dbg("%s, %i:Couldn't fcntl\n", __FILE__, __LINE__); DIE("NO_FCNTL"); return 0; } if ((setsockopt(server_ssl, SOL_SOCKET, SO_REUSEADDR, (void *) &sock_opt, sizeof(sock_opt))) == -1){ dbg("%s, %i:Couldn't sockopt\n", __FILE__,__LINE__); DIE("NO_SETSOCKOPT"); return 0; } /* internet socket */ #ifdef INET6 server_sockaddr.sin6_family = AF_INET6; memcpy(&server_sockaddr.sin6_addr,&in6addr_any,sizeof(in6addr_any)); server_sockaddr.sin6_port = htons(ssl_server_port); #else server_sockaddr.sin_family = AF_INET; server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); server_sockaddr.sin_port = htons(ssl_server_port); #endif if (bind(server_ssl, (struct sockaddr *) &server_sockaddr, sizeof(server_sockaddr)) == -1){ dbg("Couldn't bind ssl to port %d\n", ntohs(server_sockaddr.sin_port)); DIE("NO_BIND"); return 0; } /* listen: large number just in case your kernel is nicely tweaked */ if (listen(server_ssl, backlog) == -1){ DIE("NO_LISTEN"); return 0; } if (server_ssl > max_fd) max_fd = server_ssl; /*Init all of the ssl stuff*/ // i don't know why this line is commented out... i found it like that - damion may-02 /* SSL_load_error_strings();*/ SSLeay_add_ssl_algorithms(); meth = SSLv23_server_method(); if(meth == NULL){ ERR_print_errors_fp(stderr); dbg("Couldn't create the SSL method\n"); DIE("NO_SSL"); return 0; } ctx = SSL_CTX_new(meth); if(!ctx){ dbg("Couldn't create a connection context\n"); ERR_print_errors_fp(stderr); DIE("NO_SSL"); return 0; } if (SSL_CTX_use_certificate_file(ctx, SSL_CERTF, SSL_FILETYPE_PEM) <= 0) { dbg("Failure reading SSL certificate file: %s\n",SSL_CERTF); close(server_ssl); return 0; } dbg("Loaded SSL certificate file: %s\n",SSL_CERTF); if (SSL_CTX_use_PrivateKey_file(ctx, SSL_KEYF, SSL_FILETYPE_PEM) <= 0) { dbg("Failure reading private key file: %s\n",SSL_KEYF); close(server_ssl); return 0; } dbg("Opened private key file: %s\n",SSL_KEYF); if (!SSL_CTX_check_private_key(ctx)) { dbg("Private key does not match the certificate public key\n"); close(server_ssl); return 0; } /*load and check that the key files are appropriate.*/ dbg("SSL security system enabled\n"); return 1; }
/*主线程处理函数*/ void mainThread() { int reuse=1; int i=0; signal(SIGPIPE,receivePipBroken); /*------------------------SSL--------------------------------*/ // SSL *ssl; char pwd[100]; char* temp; /* SSL 库初始化 */ SSL_library_init(); /* 载入所有 SSL 算法 */ OpenSSL_add_all_algorithms(); /* 载入所有 SSL 错误消息 */ SSL_load_error_strings(); /* 以 SSL V2 和 V3 标准兼容方式产生一个 SSL_CTX ,即 SSL Content Text */ ctx = SSL_CTX_new(SSLv23_server_method()); /* 也可以用 SSLv2_server_method() 或 SSLv3_server_method() 单独表示 V2 或 V3标准 */ if (ctx == NULL) { ERR_print_errors_fp(stdout); exit(1); } /* 载入用户的数字证书, 此证书用来发送给客户端。 证书里包含有公钥 */ getcwd(pwd,100); if(strlen(pwd)==1) pwd[0]='\0'; if (SSL_CTX_use_certificate_file(ctx, temp=strcat(pwd,"/cacert.pem"), SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stdout); exit(1); } /* 载入用户私钥 */ getcwd(pwd,100); if(strlen(pwd)==1) pwd[0]='\0'; if (SSL_CTX_use_PrivateKey_file(ctx, temp=strcat(pwd,"/privkey.pem"), SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stdout); exit(1); } /* 检查用户私钥是否正确 */ if (!SSL_CTX_check_private_key(ctx)) { ERR_print_errors_fp(stdout); exit(1); } /*------------------------SSL--------------------------------*/ if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0) { fprintf(stderr,"\033[33mSocket error:%s\033[0m\n\a",strerror(errno)); exit(-1); } bzero(&server_addr,sizeof(struct sockaddr_in)); server_addr.sin_family=AF_INET; server_addr.sin_addr.s_addr=htonl(INADDR_ANY); server_addr.sin_port=htons(portnumber); setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(int)); if(bind(sockfd,(struct sockaddr*)(&server_addr),sizeof(struct sockaddr))<0) { fprintf(stderr,"\033[33mBind error:%s\033[0m\n\a",strerror(errno)); exit(1); } if(listen(sockfd, MaxClientNum)==-1) { fprintf(stderr,"\033[33mListen error:%s\033[0m\n\a",strerror(errno)); exit(1); } CreateThreadPool(); /*创建线程池*/ while(1) { if(IsExit==1) /*判断是否退出服务器*/ { int i; printf("\033[31m\nclosing server\n\033[0m"); for(i = 0;i < 60; i += 10) { printf("\033[31m.\033[0m"); fflush(stdout); usleep(100000); } printf("\033[31m\nserver closed\n\033[0m"); pthread_exit(0); } if(IsRun == 1) /*判断服务器是否正常运行*/ { if((new_fd = accept(sockfd,(struct sockaddr *)(&client_addr),&sin_size)) == -1) { perror("accept error!"); exit(-1); } tempsockfd=new_fd; strcpy(clientIP,inet_ntoa(client_addr.sin_addr)); /*保存当前连接客服端IP*/ // if((pthread_create(&id,NULL,(void *)process,&new_fd)) != 0) // { // printf("\033[33mCreate thread error!\033[0m\n"); // } // MoveToBusy(ThreadIdleId[]); pthread_cond_signal(&pthreadCond); // printf("11111111111111111111111111\n"); } } close(sockfd); /* 释放 CTX Start*/ SSL_CTX_free(ctx); /* 释放 CTX End*/ pthread_join(id,NULL); }
LWS_VISIBLE int lws_context_init_server_ssl(struct lws_context_creation_info *info, struct lws_vhost *vhost) { struct lws_context *context = vhost->context; struct lws wsi; unsigned long error; int n; if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT)) { vhost->use_ssl = 0; return 0; } /* * If he is giving a cert filepath, take it as a sign he wants to use * it on this vhost. User code can leave the cert filepath NULL and * set the LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX option itself, in * which case he's expected to set up the cert himself at * LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS, which * provides the vhost SSL_CTX * in the user parameter. */ if (info->ssl_cert_filepath) info->options |= LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX; if (info->port != CONTEXT_PORT_NO_LISTEN) { vhost->use_ssl = lws_check_opt(info->options, LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX); if (vhost->use_ssl && info->ssl_cipher_list) lwsl_notice(" SSL ciphers: '%s'\n", info->ssl_cipher_list); if (vhost->use_ssl) lwsl_notice(" Using SSL mode\n"); else lwsl_notice(" Using non-SSL mode\n"); } /* * give him a fake wsi with context + vhost set, so he can use * lws_get_context() in the callback */ memset(&wsi, 0, sizeof(wsi)); wsi.vhost = vhost; wsi.context = context; (void)n; (void)error; /* * Firefox insists on SSLv23 not SSLv3 * Konq disables SSLv2 by default now, SSLv23 works * * SSLv23_server_method() is the openssl method for "allow all TLS * versions", compared to e.g. TLSv1_2_server_method() which only allows * tlsv1.2. Unwanted versions must be disabled using SSL_CTX_set_options() */ #if !defined(LWS_WITH_MBEDTLS) { SSL_METHOD *method; method = (SSL_METHOD *)SSLv23_server_method(); if (!method) { error = ERR_get_error(); lwsl_err("problem creating ssl method %lu: %s\n", error, ERR_error_string(error, (char *)context->pt[0].serv_buf)); return 1; } vhost->ssl_ctx = SSL_CTX_new(method); /* create context */ if (!vhost->ssl_ctx) { error = ERR_get_error(); lwsl_err("problem creating ssl context %lu: %s\n", error, ERR_error_string(error, (char *)context->pt[0].serv_buf)); return 1; } } #else { const SSL_METHOD *method = TLSv1_2_server_method(); vhost->ssl_ctx = SSL_CTX_new(method); /* create context */ if (!vhost->ssl_ctx) { lwsl_err("problem creating ssl context\n"); return 1; } } #endif #if !defined(LWS_WITH_MBEDTLS) /* associate the lws context with the SSL_CTX */ SSL_CTX_set_ex_data(vhost->ssl_ctx, openssl_SSL_CTX_private_data_index, (char *)vhost->context); /* Disable SSLv2 and SSLv3 */ SSL_CTX_set_options(vhost->ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); #ifdef SSL_OP_NO_COMPRESSION SSL_CTX_set_options(vhost->ssl_ctx, SSL_OP_NO_COMPRESSION); #endif SSL_CTX_set_options(vhost->ssl_ctx, SSL_OP_SINGLE_DH_USE); SSL_CTX_set_options(vhost->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); if (info->ssl_cipher_list) SSL_CTX_set_cipher_list(vhost->ssl_ctx, info->ssl_cipher_list); #endif /* as a server, are we requiring clients to identify themselves? */ if (lws_check_opt(info->options, LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT)) { int verify_options = SSL_VERIFY_PEER; if (!lws_check_opt(info->options, LWS_SERVER_OPTION_PEER_CERT_NOT_REQUIRED)) verify_options |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; #if !defined(LWS_WITH_MBEDTLS) SSL_CTX_set_session_id_context(vhost->ssl_ctx, (unsigned char *)context, sizeof(void *)); /* absolutely require the client cert */ SSL_CTX_set_verify(vhost->ssl_ctx, verify_options, OpenSSL_verify_callback); #endif } #if !defined(LWS_WITH_MBEDTLS) && !defined(OPENSSL_NO_TLSEXT) SSL_CTX_set_tlsext_servername_callback(vhost->ssl_ctx, lws_ssl_server_name_cb); SSL_CTX_set_tlsext_servername_arg(vhost->ssl_ctx, context); #endif /* * give user code a chance to load certs into the server * allowing it to verify incoming client certs */ #if !defined(LWS_WITH_MBEDTLS) if (info->ssl_ca_filepath && !SSL_CTX_load_verify_locations(vhost->ssl_ctx, info->ssl_ca_filepath, NULL)) { lwsl_err("%s: SSL_CTX_load_verify_locations unhappy\n", __func__); } #endif if (vhost->use_ssl) { if (lws_context_ssl_init_ecdh_curve(info, vhost)) return -1; vhost->protocols[0].callback(&wsi, LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS, vhost->ssl_ctx, NULL, 0); } if (lws_check_opt(info->options, LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT)) /* Normally SSL listener rejects non-ssl, optionally allow */ vhost->allow_non_ssl_on_ssl_port = 1; if (info->ssl_options_set) SSL_CTX_set_options(vhost->ssl_ctx, info->ssl_options_set); /* SSL_clear_options introduced in 0.9.8m */ #if !defined(LWS_WITH_MBEDTLS) #if (OPENSSL_VERSION_NUMBER >= 0x009080df) && !defined(USE_WOLFSSL) if (info->ssl_options_clear) SSL_CTX_clear_options(vhost->ssl_ctx, info->ssl_options_clear); #endif #endif lwsl_info(" SSL options 0x%lX\n", SSL_CTX_get_options(vhost->ssl_ctx)); if (vhost->use_ssl && info->ssl_cert_filepath) { /* * The user code can choose to either pass the cert and * key filepaths using the info members like this, or it can * leave them NULL; force the vhost SSL_CTX init using the info * options flag LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX; and * set up the cert himself using the user callback * LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS, which * happened just above and has the vhost SSL_CTX * in the user * parameter. */ #if !defined(LWS_WITH_MBEDTLS) /* set the local certificate from CertFile */ n = SSL_CTX_use_certificate_chain_file(vhost->ssl_ctx, info->ssl_cert_filepath); if (n != 1) { error = ERR_get_error(); lwsl_err("problem getting cert '%s' %lu: %s\n", info->ssl_cert_filepath, error, ERR_error_string(error, (char *)context->pt[0].serv_buf)); return 1; } lws_ssl_bind_passphrase(vhost->ssl_ctx, info); #else uint8_t *p; lws_filepos_t flen; int err; if (alloc_pem_to_der_file(vhost->context, info->ssl_cert_filepath, &p, &flen)) { lwsl_err("couldn't find cert file %s\n", info->ssl_cert_filepath); return 1; } err = SSL_CTX_use_certificate_ASN1(vhost->ssl_ctx, flen, p); if (!err) { lwsl_err("Problem loading cert\n"); return 1; } #if !defined(LWS_WITH_ESP32) free(p); p = NULL; #endif if (info->ssl_private_key_filepath) { if (alloc_pem_to_der_file(vhost->context, info->ssl_private_key_filepath, &p, &flen)) { lwsl_err("couldn't find cert file %s\n", info->ssl_cert_filepath); return 1; } err = SSL_CTX_use_PrivateKey_ASN1(0, vhost->ssl_ctx, p, flen); if (!err) { lwsl_err("Problem loading key\n"); return 1; } } #if !defined(LWS_WITH_ESP32) free(p); p = NULL; #endif #endif if (info->ssl_private_key_filepath != NULL) { #if !defined(LWS_WITH_MBEDTLS) /* set the private key from KeyFile */ if (SSL_CTX_use_PrivateKey_file(vhost->ssl_ctx, info->ssl_private_key_filepath, SSL_FILETYPE_PEM) != 1) { error = ERR_get_error(); lwsl_err("ssl problem getting key '%s' %lu: %s\n", info->ssl_private_key_filepath, error, ERR_error_string(error, (char *)context->pt[0].serv_buf)); return 1; } #endif } else if (vhost->protocols[0].callback(&wsi, LWS_CALLBACK_OPENSSL_CONTEXT_REQUIRES_PRIVATE_KEY, vhost->ssl_ctx, NULL, 0)) { lwsl_err("ssl private key not set\n"); return 1; } #if !defined(LWS_WITH_MBEDTLS) /* verify private key */ if (!SSL_CTX_check_private_key(vhost->ssl_ctx)) { lwsl_err("Private SSL key doesn't match cert\n"); return 1; } #endif } if (vhost->use_ssl) { if (lws_context_ssl_init_ecdh(vhost)) return 1; /* * SSL is happy and has a cert it's content with * If we're supporting HTTP2, initialize that */ lws_context_init_http2_ssl(vhost); } return 0; }
int main(int argc, char **argv) { int sockfd, new_fd, fd; socklen_t len; struct sockaddr_in my_addr, their_addr; unsigned int myport, lisnum; char buf[MAXBUF + 1]; char new_fileName[50]="./testfile/"; SSL_CTX *ctx; mode_t mode; char pwd[100]; char* temp; mkdir("./testfile",mode); if (argv[1]) myport = atoi(argv[1]); else { myport = 7838; argv[2]=argv[3]=NULL; } if (argv[2]) lisnum = atoi(argv[2]); else { lisnum = 2; argv[3]=NULL; } SSL_library_init(); OpenSSL_add_all_algorithms(); SSL_load_error_strings(); ctx = SSL_CTX_new(SSLv23_server_method()); if (ctx == NULL) { ERR_print_errors_fp(stdout); exit(1); } /* load certificate */ getcwd(pwd,100); if(strlen(pwd)==1) pwd[0]='\0'; if (SSL_CTX_use_certificate_file(ctx, temp=strcat(pwd,"/ca.pem"), SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stdout); exit(1); } /* load private key */ getcwd(pwd,100); if(strlen(pwd)==1) pwd[0]='\0'; if (SSL_CTX_use_PrivateKey_file(ctx, temp=strcat(pwd,"/privkey.pem"), SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stdout); exit(1); } if (!SSL_CTX_check_private_key(ctx)) { ERR_print_errors_fp(stdout); exit(1); } if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } else printf("socket created\n"); bzero(&my_addr, sizeof(my_addr)); my_addr.sin_family = PF_INET; my_addr.sin_port = htons(myport); if (argv[3]) my_addr.sin_addr.s_addr = inet_addr(argv[3]); else my_addr.sin_addr.s_addr = INADDR_ANY; if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) == -1) { perror("bind"); exit(1); } else printf("binded\n"); if (listen(sockfd, lisnum) == -1) { perror("listen"); exit(1); } else printf("begin listen\n"); while (1) { SSL *ssl; len = sizeof(struct sockaddr); /* connection from clients */ if ((new_fd = accept(sockfd, (struct sockaddr *) &their_addr, &len)) == -1) { perror("accept"); exit(errno); } else { printf("server: got connection from %s, port %d, socket %d\n", inet_ntoa(their_addr.sin_addr), ntohs(their_addr.sin_port), new_fd); //ShowCerts(ssl); } ssl = SSL_new(ctx); SSL_set_fd(ssl, new_fd); if (SSL_accept(ssl) == -1) { perror("accept"); close(new_fd); break; } ShowCerts(ssl); while(1) { bzero(buf, MAXBUF + 1); len = SSL_read(ssl, buf, MAXBUF); if(len == 0) { printf("Receive Complete !\n"); break; } else if(len < 0) { printf("Failure to receive message ! Error code is %d,Error messages are '%s'\n", errno, strerror(errno)); exit(1); } printf("Received: %s \n",buf); SSL_write(ssl, buf, strlen(buf)); } close(fd); SSL_shutdown(ssl); SSL_free(ssl); close(new_fd); } close(sockfd); SSL_CTX_free(ctx); return 0; }
static apr_status_t init_ssl_context(serv_ctx_t *serv_ctx, const char *keyfile, const char **certfiles, const char *client_cn) { ssl_context_t *ssl_ctx = apr_pcalloc(serv_ctx->pool, sizeof(*ssl_ctx)); serv_ctx->ssl_ctx = ssl_ctx; serv_ctx->client_cn = client_cn; serv_ctx->bio_read_status = APR_SUCCESS; /* Init OpenSSL globally */ if (!init_done) { CRYPTO_malloc_init(); ERR_load_crypto_strings(); SSL_load_error_strings(); SSL_library_init(); OpenSSL_add_all_algorithms(); init_done = 1; } /* Init this connection */ if (!ssl_ctx->ctx) { X509_STORE *store; const char *certfile; int i; int rv; ssl_ctx->ctx = SSL_CTX_new(SSLv23_server_method()); SSL_CTX_set_default_passwd_cb(ssl_ctx->ctx, pem_passwd_cb); rv = SSL_CTX_use_PrivateKey_file(ssl_ctx->ctx, keyfile, SSL_FILETYPE_PEM); if (rv != 1) { fprintf(stderr, "Cannot load private key from file '%s'\n", keyfile); exit(1); } /* Set server certificate, add ca certificates if provided. */ certfile = certfiles[0]; rv = SSL_CTX_use_certificate_file(ssl_ctx->ctx, certfile, SSL_FILETYPE_PEM); if (rv != 1) { fprintf(stderr, "Cannot load certficate from file '%s'\n", keyfile); exit(1); } i = 1; certfile = certfiles[i++]; store = SSL_CTX_get_cert_store(ssl_ctx->ctx); while(certfile) { FILE *fp = fopen(certfile, "r"); if (fp) { X509 *ssl_cert = PEM_read_X509(fp, NULL, NULL, NULL); fclose(fp); SSL_CTX_add_extra_chain_cert(ssl_ctx->ctx, ssl_cert); X509_STORE_add_cert(store, ssl_cert); } certfile = certfiles[i++]; } /* This makes the server send a client certificate request during handshake. The client certificate is optional (most tests don't send one) by default, but mandatory if client_cn was specified. */ SSL_CTX_set_verify(ssl_ctx->ctx, SSL_VERIFY_PEER, validate_client_certificate); SSL_CTX_set_mode(ssl_ctx->ctx, SSL_MODE_ENABLE_PARTIAL_WRITE); ssl_ctx->bio = BIO_new(&bio_apr_socket_method); ssl_ctx->bio->ptr = serv_ctx; init_ssl(serv_ctx); } return APR_SUCCESS; }
boolean tls_accept(rdpTls* tls, const char* cert_file, const char* privatekey_file) { CryptoCert cert; int connection_status; tls->ctx = SSL_CTX_new(SSLv23_server_method()); if (tls->ctx == NULL) { printf("SSL_CTX_new failed\n"); return false; } /* * We only want SSLv3 and TLSv1, so disable SSLv2. * SSLv3 is used by, eg. Microsoft RDC for Mac OS X. */ SSL_CTX_set_options(tls->ctx, SSL_OP_NO_SSLv2); if (SSL_CTX_use_RSAPrivateKey_file(tls->ctx, privatekey_file, SSL_FILETYPE_PEM) <= 0) { printf("SSL_CTX_use_RSAPrivateKey_file failed\n"); return false; } tls->ssl = SSL_new(tls->ctx); if (tls->ssl == NULL) { printf("SSL_new failed\n"); return false; } if (SSL_use_certificate_file(tls->ssl, cert_file, SSL_FILETYPE_PEM) <= 0) { printf("SSL_use_certificate_file failed\n"); return false; } cert = tls_get_certificate(tls, false); if (cert == NULL) { printf("tls_connect: tls_get_certificate failed to return the server certificate.\n"); return false; } if (!crypto_cert_get_public_key(cert, &tls->public_key)) { printf("tls_connect: crypto_cert_get_public_key failed to return the server public key.\n"); tls_free_certificate(cert); return false; } if (SSL_set_fd(tls->ssl, tls->sockfd) < 1) { printf("SSL_set_fd failed\n"); return false; } connection_status = SSL_accept(tls->ssl); if (connection_status <= 0) { if (tls_print_error("SSL_accept", tls->ssl, connection_status)) return false; } printf("TLS connection accepted\n"); return true; }
SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ciphers, char *client_ca) { SSL_CTX *ctx = SSL_CTX_new(SSLv23_server_method()); if (!ctx) { uwsgi_log("[uwsgi-ssl] unable to initialize context \"%s\"\n", name); return NULL; } // this part is taken from nginx and stud, removing unneeded functionality // stud (for me) has made the best choice on choosing DH approach long ssloptions = SSL_OP_NO_SSLv2 | SSL_OP_ALL | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION; // disable compression (if possibile) #ifdef SSL_OP_NO_COMPRESSION ssloptions |= SSL_OP_NO_COMPRESSION; #endif // release/reuse buffers as soon as possibile #ifdef SSL_MODE_RELEASE_BUFFERS SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS); #endif if (SSL_CTX_use_certificate_chain_file(ctx, crt) <= 0) { uwsgi_log("[uwsgi-ssl] unable to assign certificate %s for context \"%s\"\n", crt, name); SSL_CTX_free(ctx); return NULL; } // this part is based from stud BIO *bio = BIO_new_file(crt, "r"); if (bio) { DH *dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); BIO_free(bio); if (dh) { SSL_CTX_set_tmp_dh(ctx, dh); DH_free(dh); #if OPENSSL_VERSION_NUMBER >= 0x0090800fL #ifndef OPENSSL_NO_ECDH #ifdef NID_X9_62_prime256v1 EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); SSL_CTX_set_tmp_ecdh(ctx, ecdh); EC_KEY_free(ecdh); #endif #endif #endif } } if (SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM) <= 0) { uwsgi_log("[uwsgi-ssl] unable to assign key %s for context \"%s\"\n", key, name); SSL_CTX_free(ctx); return NULL; } // if ciphers are specified, prefer server ciphers if (ciphers && strlen(ciphers) > 0) { if (SSL_CTX_set_cipher_list(ctx, ciphers) == 0) { uwsgi_log("[uwsgi-ssl] unable to set requested ciphers (%s) for context \"%s\"\n", ciphers, name); SSL_CTX_free(ctx); return NULL; } ssloptions |= SSL_OP_CIPHER_SERVER_PREFERENCE; } // set session context (if possibile), this is required for client certificate authentication if (name) { SSL_CTX_set_session_id_context(ctx, (unsigned char *) name, strlen(name)); } if (client_ca) { if (client_ca[0] == '!') { SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, uwsgi_ssl_verify_callback); client_ca++; } else { SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, uwsgi_ssl_verify_callback); } // in the future we should allow to set the verify depth SSL_CTX_set_verify_depth(ctx, 1); if (SSL_CTX_load_verify_locations(ctx, client_ca, NULL) == 0) { uwsgi_log("[uwsgi-ssl] unable to set ssl verify locations (%s) for context \"%s\"\n", client_ca, name); SSL_CTX_free(ctx); return NULL; } STACK_OF(X509_NAME) * list = SSL_load_client_CA_file(client_ca); if (!list) { uwsgi_log("unable to load client CA certificate (%s) for context \"%s\"\n", client_ca, name); SSL_CTX_free(ctx); return NULL; } SSL_CTX_set_client_CA_list(ctx, list); } SSL_CTX_set_info_callback(ctx, uwsgi_ssl_info_cb); #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME SSL_CTX_set_tlsext_servername_callback(ctx, uwsgi_sni_cb); #endif // disable session caching by default SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); if (uwsgi.ssl_sessions_use_cache) { // we need to early initialize locking and caching uwsgi_setup_locking(); uwsgi_cache_create_all(); uwsgi.ssl_sessions_cache = uwsgi_cache_by_name(uwsgi.ssl_sessions_use_cache); if (!uwsgi.ssl_sessions_cache) { // check for default cache if (!strcmp(uwsgi.ssl_sessions_use_cache, "true") && uwsgi.caches) { uwsgi.ssl_sessions_cache = uwsgi.caches; } else { uwsgi_log("unable to find cache \"%s\"\n", uwsgi.ssl_sessions_use_cache ? uwsgi.ssl_sessions_use_cache : "default"); exit(1); } } if (!uwsgi.ssl_sessions_cache->max_items) { uwsgi_log("you have to enable uWSGI cache to use it as SSL session store !!!\n"); exit(1); } if (uwsgi.ssl_sessions_cache->blocksize < 4096) { uwsgi_log("cache blocksize for SSL session store must be at least 4096 bytes\n"); exit(1); } SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER| SSL_SESS_CACHE_NO_INTERNAL| SSL_SESS_CACHE_NO_AUTO_CLEAR); #ifdef SSL_OP_NO_TICKET ssloptions |= SSL_OP_NO_TICKET; #endif // just for fun SSL_CTX_sess_set_cache_size(ctx, 0); // set the callback for ssl sessions SSL_CTX_sess_set_new_cb(ctx, uwsgi_ssl_session_new_cb); SSL_CTX_sess_set_get_cb(ctx, uwsgi_ssl_session_get_cb); SSL_CTX_sess_set_remove_cb(ctx, uwsgi_ssl_session_remove_cb); } SSL_CTX_set_timeout(ctx, uwsgi.ssl_sessions_timeout); SSL_CTX_set_options(ctx, ssloptions); return ctx; }
LWS_VISIBLE int lws_context_init_server_ssl(struct lws_context_creation_info *info, struct libwebsocket_context *context) { SSL_METHOD *method; int error; int n; if (info->port != CONTEXT_PORT_NO_LISTEN) { context->use_ssl = info->ssl_cert_filepath != NULL; #ifdef USE_CYASSL lwsl_notice(" Compiled with CYASSL support\n"); #else lwsl_notice(" Compiled with OpenSSL support\n"); #endif if (info->ssl_cipher_list) lwsl_notice(" SSL ciphers: '%s'\n", info->ssl_cipher_list); if (context->use_ssl) lwsl_notice(" Using SSL mode\n"); else lwsl_notice(" Using non-SSL mode\n"); } /* basic openssl init */ SSL_library_init(); OpenSSL_add_all_algorithms(); SSL_load_error_strings(); openssl_websocket_private_data_index = SSL_get_ex_new_index(0, "libwebsockets", NULL, NULL, NULL); /* * Firefox insists on SSLv23 not SSLv3 * Konq disables SSLv2 by default now, SSLv23 works * * SSLv23_server_method() is the openssl method for "allow all TLS * versions", compared to e.g. TLSv1_2_server_method() which only allows * tlsv1.2. Unwanted versions must be disabled using SSL_CTX_set_options() */ method = (SSL_METHOD *)SSLv23_server_method(); if (!method) { error = ERR_get_error(); lwsl_err("problem creating ssl method %lu: %s\n", error, ERR_error_string(error, (char *)context->service_buffer)); return 1; } context->ssl_ctx = SSL_CTX_new(method); /* create context */ if (!context->ssl_ctx) { error = ERR_get_error(); lwsl_err("problem creating ssl context %lu: %s\n", error, ERR_error_string(error, (char *)context->service_buffer)); return 1; } /* Disable SSLv2 and SSLv3 */ SSL_CTX_set_options(context->ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); #ifdef SSL_OP_NO_COMPRESSION SSL_CTX_set_options(context->ssl_ctx, SSL_OP_NO_COMPRESSION); #endif SSL_CTX_set_options(context->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); if (info->ssl_cipher_list) SSL_CTX_set_cipher_list(context->ssl_ctx, info->ssl_cipher_list); /* as a server, are we requiring clients to identify themselves? */ if (info->options & LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT) { /* absolutely require the client cert */ /* * Must set session-id when using a client certificate, or * ssl fails with a fatal error and the error code isn't * helpful. It's a session caching issue. * The session ID must be unique per session, that's the only * constraint on what you set it to. So, just use the context * address as the session ID. */ SSL_CTX_set_session_id_context(context->ssl_ctx, (const unsigned char *)&context, sizeof(context)); /* * Kludge for Katena: Don't fail if there is no peer cert. * FIX: Give that an API. */ SSL_CTX_set_verify(context->ssl_ctx, SSL_VERIFY_PEER /* | SSL_VERIFY_FAIL_IF_NO_PEER_CERT */, OpenSSL_verify_callback); /* * give user code a chance to load certs into the server * allowing it to verify incoming client certs */ context->protocols[0].callback(context, NULL, LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS, context->ssl_ctx, NULL, 0); } if (info->options & LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT) { /* Normally SSL listener rejects non-ssl, optionally allow */ context->allow_non_ssl_on_ssl_port = 1; } if (context->use_ssl) { /* openssl init for server sockets */ /* set the local certificate from CertFile */ n = SSL_CTX_use_certificate_chain_file(context->ssl_ctx, info->ssl_cert_filepath); if (n != 1) { error = ERR_get_error(); lwsl_err("problem getting cert '%s' %lu: %s\n", info->ssl_cert_filepath, error, ERR_error_string(error, (char *)context->service_buffer)); return 1; } lws_ssl_bind_passphrase(context->ssl_ctx, info); if (info->ssl_private_key_filepath != NULL) { /* set the private key from KeyFile */ if (SSL_CTX_use_PrivateKey_file(context->ssl_ctx, info->ssl_private_key_filepath, SSL_FILETYPE_PEM) != 1) { error = ERR_get_error(); lwsl_err("ssl problem getting key '%s' %lu: %s\n", info->ssl_private_key_filepath, error, ERR_error_string(error, (char *)context->service_buffer)); return 1; } } else { if (context->protocols[0].callback(context, NULL, LWS_CALLBACK_OPENSSL_CONTEXT_REQUIRES_PRIVATE_KEY, context->ssl_ctx, NULL, 0)) { lwsl_err("ssl private key not set\n"); return 1; } } /* verify private key */ if (!SSL_CTX_check_private_key(context->ssl_ctx)) { lwsl_err("Private SSL key doesn't match cert\n"); return 1; } /* * SSL is happy and has a cert it's content with * If we're supporting HTTP2, initialize that */ lws_context_init_http2_ssl(context); } return 0; }
PUBLIC int sslOpen() { RandBuf randBuf; trace(7, "Initializing SSL"); randBuf.now = time(0); randBuf.pid = getpid(); RAND_seed((void*) &randBuf, sizeof(randBuf)); #if BIT_UNIX_LIKE trace(6, "OpenSsl: Before calling RAND_load_file"); RAND_load_file("/dev/urandom", 256); trace(6, "OpenSsl: After calling RAND_load_file"); #endif CRYPTO_malloc_init(); #if !BIT_WIN_LIKE OpenSSL_add_all_algorithms(); #endif SSL_library_init(); SSL_load_error_strings(); SSLeay_add_ssl_algorithms(); if ((sslctx = SSL_CTX_new(SSLv23_server_method())) == 0) { error("Unable to create SSL context"); return -1; } /* Set the client certificate verification locations */ if (*BIT_GOAHEAD_CA) { if ((!SSL_CTX_load_verify_locations(sslctx, BIT_GOAHEAD_CA, NULL)) || (!SSL_CTX_set_default_verify_paths(sslctx))) { error("Unable to read cert verification locations"); sslClose(); return -1; } } /* Set the server certificate and key files */ if (*BIT_GOAHEAD_KEY && sslSetKeyFile(BIT_GOAHEAD_KEY) < 0) { sslClose(); return -1; } if (*BIT_GOAHEAD_CERTIFICATE && sslSetCertFile(BIT_GOAHEAD_CERTIFICATE) < 0) { sslClose(); return -1; } SSL_CTX_set_tmp_rsa_callback(sslctx, rsaCallback); #if VERIFY_CLIENT if (verifyPeer) { SSL_CTX_set_verify(context, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verifyX509Certificate); #if FUTURE && KEEP SSL_CTX_set_verify_depth(context, VERIFY_DEPTH); #endif } else { SSL_CTX_set_verify(sslctx, SSL_VERIFY_NONE, verifyX509Certificate); } #else SSL_CTX_set_verify(sslctx, SSL_VERIFY_NONE, verifyX509Certificate); #endif /* Set the certificate authority list for the client */ if (BIT_GOAHEAD_CA && *BIT_GOAHEAD_CA) { SSL_CTX_set_client_CA_list(sslctx, SSL_load_client_CA_file(BIT_GOAHEAD_CA)); } SSL_CTX_set_cipher_list(sslctx, BIT_GOAHEAD_CIPHERS); SSL_CTX_set_options(sslctx, SSL_OP_ALL); SSL_CTX_sess_set_cache_size(sslctx, 128); #ifdef SSL_OP_NO_TICKET SSL_CTX_set_options(sslctx, SSL_OP_NO_TICKET); #endif #ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION SSL_CTX_set_options(sslctx, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); #endif SSL_CTX_set_mode(sslctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY); SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv2); /* Ensure we generate a new private key for each connection */ SSL_CTX_set_options(sslctx, SSL_OP_SINGLE_DH_USE); return 0; }
/* Open the SSL module */ PUBLIC int sslOpen() { RandBuf randBuf; X509_STORE *store; uchar resume[16]; char *ciphers; trace(7, "Initializing SSL"); randBuf.now = time(0); randBuf.pid = getpid(); RAND_seed((void*) &randBuf, sizeof(randBuf)); #if ME_UNIX_LIKE trace(6, "OpenSsl: Before calling RAND_load_file"); RAND_load_file("/dev/urandom", 256); trace(6, "OpenSsl: After calling RAND_load_file"); #endif CRYPTO_malloc_init(); #if !ME_WIN_LIKE OpenSSL_add_all_algorithms(); #endif SSL_library_init(); SSL_load_error_strings(); SSLeay_add_ssl_algorithms(); if ((sslctx = SSL_CTX_new(SSLv23_server_method())) == 0) { error("Unable to create SSL context"); return -1; } /* Set the server certificate and key files */ if (*ME_GOAHEAD_SSL_KEY && sslSetKeyFile(ME_GOAHEAD_SSL_KEY) < 0) { sslClose(); return -1; } if (*ME_GOAHEAD_SSL_CERTIFICATE && sslSetCertFile(ME_GOAHEAD_SSL_CERTIFICATE) < 0) { sslClose(); return -1; } if (ME_GOAHEAD_SSL_VERIFY_PEER) { SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verifyClientCertificate); SSL_CTX_set_verify_depth(sslctx, VERIFY_DEPTH); } else { SSL_CTX_set_verify(sslctx, SSL_VERIFY_NONE, verifyClientCertificate); } /* Set the client certificate verification locations */ if (ME_GOAHEAD_SSL_AUTHORITY && *ME_GOAHEAD_SSL_AUTHORITY) { if ((!SSL_CTX_load_verify_locations(sslctx, ME_GOAHEAD_SSL_AUTHORITY, NULL)) || (!SSL_CTX_set_default_verify_paths(sslctx))) { error("Unable to read cert verification locations"); sslClose(); return -1; } /* Define the list of CA certificates to send to the client before they send their client certificate for validation */ SSL_CTX_set_client_CA_list(sslctx, SSL_load_client_CA_file(ME_GOAHEAD_SSL_AUTHORITY)); } if (ME_GOAHEAD_SSL_REVOKE && *ME_GOAHEAD_SSL_REVOKE) { store = SSL_CTX_get_cert_store(sslctx); if (!X509_STORE_load_locations(store, ME_GOAHEAD_SSL_REVOKE, 0)) { error("Cannot load certificate revoke list: %s", ME_GOAHEAD_SSL_REVOKE); sslClose(); return -1; } } /* Configure DH parameters */ dhKey = getDhKey(); SSL_CTX_set_tmp_dh_callback(sslctx, dhcallback); /* Configure cipher suite */ if (ME_GOAHEAD_SSL_CIPHERS && *ME_GOAHEAD_SSL_CIPHERS) { ciphers = ME_GOAHEAD_SSL_CIPHERS; } else { ciphers = OPENSSL_DEFAULT_CIPHERS; } ciphers = mapCipherNames(ciphers); trace(5, "Using OpenSSL ciphers: %s", ciphers); if (SSL_CTX_set_cipher_list(sslctx, ciphers) != 1) { error("Unable to set cipher list \"%s\"", ciphers); sslClose(); wfree(ciphers); return -1; } wfree(ciphers); /* Define default OpenSSL options */ SSL_CTX_set_options(sslctx, SSL_OP_ALL); /* Ensure we generate a new private key for each connection */ SSL_CTX_set_options(sslctx, SSL_OP_SINGLE_DH_USE); /* Define a session reuse context */ RAND_bytes(resume, sizeof(resume)); SSL_CTX_set_session_id_context(sslctx, resume, sizeof(resume)); /* Elliptic Curve initialization */ #if SSL_OP_SINGLE_ECDH_USE #ifdef SSL_CTX_set_ecdh_auto SSL_CTX_set_ecdh_auto(sslctx, 1); #else { EC_KEY *ecdh; cchar *name; int nid; name = ME_GOAHEAD_SSL_CURVE; if ((nid = OBJ_sn2nid(name)) == 0) { error("Unknown curve name \"%s\"", name); sslClose(); return -1; } if ((ecdh = EC_KEY_new_by_curve_name(nid)) == 0) { error("Unable to create curve \"%s\"", name); sslClose(); return -1; } SSL_CTX_set_options(sslctx, SSL_OP_SINGLE_ECDH_USE); SSL_CTX_set_tmp_ecdh(sslctx, ecdh); EC_KEY_free(ecdh); } #endif #endif SSL_CTX_set_mode(sslctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); #ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING SSL_CTX_set_options(sslctx, SSL_OP_MSIE_SSLV2_RSA_PADDING); #endif #ifdef SSL_MODE_RELEASE_BUFFERS SSL_CTX_set_mode(sslctx, SSL_MODE_RELEASE_BUFFERS); #endif #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE SSL_CTX_set_mode(sslctx, SSL_OP_CIPHER_SERVER_PREFERENCE); #endif /* Select the required protocols Disable both SSLv2 and SSLv3 by default - they are insecure */ SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv2); SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv3); #if defined(SSL_OP_NO_TLSv1) && ME_GOAHEAD_SSL_NO_V1 SSL_CTX_set_options(sslctx, SSL_OP_NO_TLSv1); #endif #if defined(SSL_OP_NO_TLSv1_1) && ME_GOAHEAD_SSL_NO_V1_1 SSL_CTX_set_options(sslctx, SSL_OP_NO_TLSv1_1); #endif #if defined(SSL_OP_NO_TLSv1_2) && ME_GOAHEAD_SSL_NO_V1_2 SSL_CTX_set_options(sslctx, SSL_OP_NO_TLSv1_2); #endif #if defined(SSL_OP_NO_TICKET) /* Ticket based session reuse is enabled by default */ #if defined(ME_GOAHEAD_SSL_TICKET) if (ME_GOAHEAD_SSL_TICKET) { SSL_CTX_clear_options(sslctx, SSL_OP_NO_TICKET); } else { SSL_CTX_set_options(sslctx, SSL_OP_NO_TICKET); } #else SSL_CTX_clear_options(sslctx, SSL_OP_NO_TICKET); #endif #endif #if defined(SSL_OP_NO_COMPRESSION) /* CRIME attack targets compression */ SSL_CTX_clear_options(sslctx, SSL_OP_NO_COMPRESSION); #endif #if defined(SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) /* Disables a countermeasure against a SSL 3.0/TLS 1.0 protocol vulnerability affecting CBC ciphers. Defaults to true. */ #if defined(ME_GOAHEAD_SSL_EMPTY_FRAGMENTS) if (ME_GOAHEAD_SSL_EMPTY_FRAGMENTS) { /* SSL_OP_ALL disables empty fragments. Only needed for ancient browsers like IE-6 on SSL-3.0/TLS-1.0 */ SSL_CTX_clear_options(sslctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); } else { SSL_CTX_set_options(sslctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); } #else SSL_CTX_set_options(sslctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); #endif #endif #if defined(ME_GOAHEAD_SSL_CACHE) /* Set the number of sessions supported. Default in OpenSSL is 20K. */ SSL_CTX_sess_set_cache_size(sslctx, ME_GOAHEAD_SSL_CACHE); #else SSL_CTX_sess_set_cache_size(sslctx, 256); #endif return 0; }
/* * This starts a minimal TLS server that only does a * handshake and then closes the connection. This is * strictly used to test TLS session negotiation * behavior with EST. */ static void us1060_start_tls_server (char *cipherstring) { BIO *conn; BIO *listener; BIO *berr; char h_p[25]; SSL *ssl; SSL_CTX *ssl_ctx = NULL; int nid, rv; EC_KEY *ecdh = NULL; berr = BIO_new_fp(stderr, BIO_NOCLOSE); ssl_ctx = SSL_CTX_new(SSLv23_server_method()); if (!ssl_ctx) { printf("Failed to create SSL context\n"); ERR_print_errors(berr); return; } SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY); if (SSL_CTX_use_certificate_chain_file(ssl_ctx, US1060_RSA_CERT) != 1) { printf("Failed to load server certificate\n"); ERR_print_errors(berr); return; } if (SSL_CTX_use_PrivateKey_file(ssl_ctx, US1060_RSA_KEY, SSL_FILETYPE_PEM) != 1) { printf("Failed to load server private key\n"); ERR_print_errors(berr); return; } SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_SINGLE_ECDH_USE | SSL_OP_SINGLE_DH_USE | SSL_OP_NO_TICKET); nid = OBJ_sn2nid("prime256v1"); ecdh = EC_KEY_new_by_curve_name(nid); if (ecdh == NULL) { printf("Failed to retreive ECDH curve\n"); ERR_print_errors(berr); return; } SSL_CTX_set_tmp_ecdh(ssl_ctx, ecdh); EC_KEY_free(ecdh); if (SSL_CTX_set_cipher_list(ssl_ctx, cipherstring) != 1) { printf("Failed to set server cipher list\n"); ERR_print_errors(berr); return; } SSL_CTX_set_srp_username_callback(ssl_ctx, us1060_srp_cb); sprintf(h_p, "%s:%d", US1060_SERVER_IP, US1060_TLS_PORT); listener = BIO_new_accept(h_p); if (listener == NULL) { printf("IP connection failed\n"); return; } BIO_set_bind_mode(listener, BIO_BIND_REUSEADDR); /* * The first call to do_accept binds the socket */ if (BIO_do_accept(listener) <= 0) { printf("TCP bind failed\n"); BIO_free_all(listener); return; } /* * The second call to do_accept waits for a new * connection request on the listener. * Note that we are in blocking mode for this socket */ if (BIO_do_accept(listener) <= 0) { printf("TCP accept failed\n"); BIO_free_all(listener); return; } conn = BIO_pop(listener); ssl = SSL_new(ssl_ctx); SSL_set_bio(ssl, conn, conn); /* * Now that we have everything ready, let's start waiting for * a client to contact us. Normally we might using a pthread * or some other construct to avoid blocking on the main * thread while waiting for an incoming connection. This * code is simply a contrived example, we will wait on the * main thread for an incoming connection. */ rv = SSL_accept(ssl); if (rv <= 0) { printf("\nFailed to complete TLS handshake %d\n", rv); ERR_print_errors(berr); } SSL_shutdown(ssl); SSL_free(ssl); SSL_CTX_free(ssl_ctx); BIO_free(berr); (void)BIO_reset(listener); BIO_free_all(listener); pthread_exit(0); }
/* basic openssl init */ SSL_library_init(); OpenSSL_add_all_algorithms(); SSL_load_error_strings(); openssl_websocket_private_data_index = SSL_get_ex_new_index(0, "libwebsockets", NULL, NULL, NULL); /* * Firefox insists on SSLv23 not SSLv3 * Konq disables SSLv2 by default now, SSLv23 works */ method = (SSL_METHOD *)SSLv23_server_method(); if (!method) { error = ERR_get_error(); lwsl_err("problem creating ssl method %lu: %s\n", error, ERR_error_string(error, (char *)context->service_buffer)); return 1; } context->ssl_ctx = SSL_CTX_new(method); /* create context */ if (!context->ssl_ctx) { error = ERR_get_error(); lwsl_err("problem creating ssl context %lu: %s\n", error, ERR_error_string(error, (char *)context->service_buffer)); return 1; }
static int tport_ws_init_primary_secure(tport_primary_t *pri, tp_name_t tpn[1], su_addrinfo_t *ai, tagi_t const *tags, char const **return_culprit) { tport_ws_primary_t *wspri = (tport_ws_primary_t *)pri; const char *cert = "/ssl.pem"; const char *key = "/ssl.pem"; char *homedir; char *tbf = NULL; su_home_t autohome[SU_HOME_AUTO_SIZE(1024)]; char const *path = NULL; int ret = -1; su_home_auto(autohome, sizeof autohome); tl_gets(tags, TPTAG_CERTIFICATE_REF(path), TAG_END()); if (!path) { homedir = getenv("HOME"); if (!homedir) homedir = ""; path = tbf = su_sprintf(autohome, "%s/.sip/auth", homedir); } if (path) { key = su_sprintf(autohome, "%s/%s", path, "wss.key"); if (access(key, R_OK) != 0) key = NULL; cert = su_sprintf(autohome, "%s/%s", path, "wss.crt"); if (access(cert, R_OK) != 0) cert = NULL; if ( !key ) key = su_sprintf(autohome, "%s/%s", path, "wss.pem"); if ( !cert ) cert = su_sprintf(autohome, "%s/%s", path, "wss.pem"); if (access(key, R_OK) != 0) key = NULL; if (access(cert, R_OK) != 0) cert = NULL; } init_ssl(); // OpenSSL_add_all_algorithms(); /* load & register cryptos */ // SSL_load_error_strings(); /* load all error messages */ wspri->ssl_method = SSLv23_server_method(); /* create server instance */ wspri->ssl_ctx = SSL_CTX_new((SSL_METHOD *)wspri->ssl_method); /* create context */ SSL_CTX_sess_set_remove_cb(wspri->ssl_ctx, NULL); wspri->ws_secure = 1; if ( !wspri->ssl_ctx ) goto done; /* set the local certificate from CertFile */ SSL_CTX_use_certificate_file(wspri->ssl_ctx, cert, SSL_FILETYPE_PEM); /* set the private key from KeyFile */ SSL_CTX_use_PrivateKey_file(wspri->ssl_ctx, key, SSL_FILETYPE_PEM); /* verify private key */ if ( !SSL_CTX_check_private_key(wspri->ssl_ctx) ) { goto done; } SSL_CTX_set_cipher_list(wspri->ssl_ctx, "HIGH:!DSS:!aNULL@STRENGTH"); ret = tport_ws_init_primary(pri, tpn, ai, tags, return_culprit); done: su_home_zap(autohome); return ret; }
static int _tnet_transport_ssl_init(tnet_transport_t* transport) { if (!transport){ TSK_DEBUG_ERROR("Invalid parameter"); return -1; } #if HAVE_OPENSSL { tnet_socket_type_t type = tnet_transport_get_type(transport); tsk_bool_t is_tls = (TNET_SOCKET_TYPE_IS_TLS(type) || TNET_SOCKET_TYPE_IS_WSS(type)); tsk_bool_t is_dtls = transport->dtls.enabled/* TNET_SOCKET_TYPE_IS_DTLS(type)*/; // DTLS-RTP, not raw DTLS if (is_dtls && !tnet_dtls_is_supported()){ TSK_DEBUG_ERROR("Requesting to create DTLS transport but source code not built with support for this feature"); return -1; } if (is_tls && !tnet_tls_is_supported()){ TSK_DEBUG_ERROR("Requesting to create TLS transport but source code not built with support for this feature"); return -1; } if ((transport->tls.enabled = is_tls)){ if (!transport->tls.ctx_client && !(transport->tls.ctx_client = SSL_CTX_new(SSLv23_client_method()))){ TSK_DEBUG_ERROR("Failed to create SSL client context"); return -2; } if (!transport->tls.ctx_server && !(transport->tls.ctx_server = SSL_CTX_new(SSLv23_server_method()))){ TSK_DEBUG_ERROR("Failed to create SSL server context"); return -3; } SSL_CTX_set_mode(transport->tls.ctx_client, SSL_MODE_AUTO_RETRY); SSL_CTX_set_mode(transport->tls.ctx_server, SSL_MODE_AUTO_RETRY); SSL_CTX_set_verify(transport->tls.ctx_server, SSL_VERIFY_NONE, tsk_null); // to be updated by tnet_transport_tls_set_certs() SSL_CTX_set_verify(transport->tls.ctx_client, SSL_VERIFY_NONE, tsk_null); // to be updated by tnet_transport_tls_set_certs() if (SSL_CTX_set_cipher_list(transport->tls.ctx_client, TNET_CIPHER_LIST) <= 0 || SSL_CTX_set_cipher_list(transport->tls.ctx_server, TNET_CIPHER_LIST) <= 0){ TSK_DEBUG_ERROR("SSL_CTX_set_cipher_list failed [%s]", ERR_error_string(ERR_get_error(), tsk_null)); return -4; } } #if HAVE_OPENSSL_DTLS if ((transport->dtls.enabled = is_dtls)){ if (!transport->dtls.ctx && !(transport->dtls.ctx = SSL_CTX_new(DTLSv1_method()))){ TSK_DEBUG_ERROR("Failed to create DTLSv1 context"); TSK_OBJECT_SAFE_FREE(transport); return -5; } SSL_CTX_set_read_ahead(transport->dtls.ctx, 1); // SSL_CTX_set_options(transport->dtls.ctx, SSL_OP_ALL); // SSL_CTX_set_mode(transport->dtls.ctx, SSL_MODE_AUTO_RETRY); SSL_CTX_set_verify(transport->dtls.ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, tsk_null); // to be updated by tnet_transport_tls_set_certs() if (SSL_CTX_set_cipher_list(transport->dtls.ctx, TNET_CIPHER_LIST) <= 0){ TSK_DEBUG_ERROR("SSL_CTX_set_cipher_list failed [%s]", ERR_error_string(ERR_get_error(), tsk_null)); return -6; } //!\ This is required even if the local transport is TCP/TLS because the relayed (TURN) transport could be UDP // Up to the DTLS socket to set the default MTU value SSL_CTX_set_options(transport->dtls.ctx, SSL_OP_NO_QUERY_MTU); SSL_CTX_ctrl(transport->dtls.ctx, SSL_CTRL_SET_MTU, TNET_DTLS_MTU - 28, NULL); transport->dtls.activated = tsk_true; } #endif /* HAVE_OPENSSL_DTLS */ } #endif /* HAVE_OPENSSL */ return 0; }
bud_error_t bud_config_new_ssl_ctx(bud_config_t* config, bud_context_t* context) { SSL_CTX* ctx; bud_error_t err; int options; /* Choose method, tlsv1_2 by default */ if (config->frontend.method == NULL) { if (strcmp(config->frontend.security, "tls1.1") == 0) config->frontend.method = TLSv1_1_server_method(); else if (strcmp(config->frontend.security, "tls1.0") == 0) config->frontend.method = TLSv1_server_method(); else if (strcmp(config->frontend.security, "tls1.2") == 0) config->frontend.method = TLSv1_2_server_method(); else if (strcmp(config->frontend.security, "ssl3") == 0) config->frontend.method = SSLv3_server_method(); else config->frontend.method = SSLv23_server_method(); } ctx = SSL_CTX_new(config->frontend.method); if (ctx == NULL) return bud_error_str(kBudErrNoMem, "SSL_CTX"); SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER | SSL_SESS_CACHE_NO_INTERNAL | SSL_SESS_CACHE_NO_AUTO_CLEAR); if (context->ciphers != NULL) SSL_CTX_set_cipher_list(ctx, context->ciphers); else if (config->frontend.ciphers != NULL) SSL_CTX_set_cipher_list(ctx, config->frontend.ciphers); /* Disable SSL2 */ options = SSL_OP_NO_SSLv2 | SSL_OP_ALL; if (!config->frontend.ssl3) options |= SSL_OP_NO_SSLv3; if (config->frontend.server_preference) options |= SSL_OP_CIPHER_SERVER_PREFERENCE; SSL_CTX_set_options(ctx, options); #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB if (config->context_count != 0) { SSL_CTX_set_tlsext_servername_callback(ctx, bud_config_select_sni_context); SSL_CTX_set_tlsext_servername_arg(ctx, config); } #endif /* SSL_CTRL_SET_TLSEXT_SERVERNAME_CB */ #ifdef OPENSSL_NPN_NEGOTIATED context->npn_line = bud_config_encode_npn(config, context->npn, &context->npn_line_len, &err); if (!bud_is_ok(err)) goto fatal; if (context->npn_line != NULL) { SSL_CTX_set_next_protos_advertised_cb(ctx, bud_config_advertise_next_proto, context); } #else /* !OPENSSL_NPN_NEGOTIATED */ err = bud_error(kBudErrNPNNotSupported); goto fatal; #endif /* OPENSSL_NPN_NEGOTIATED */ SSL_CTX_set_tlsext_status_cb(ctx, bud_client_stapling_cb); context->ctx = ctx; return bud_ok(); fatal: SSL_CTX_free(ctx); return err; }
SSL_CTX * tls_server_setup( int authlevel, const char *caFile, const char *caDir, const char *cert, const char *privatekey, const char *ciphers ) { SSL_CTX *ssl_ctx; int ssl_mode = 0; static unsigned char dh4096_p[ ] = { 0x91, 0x6B, 0xA1, 0x6D, 0xC7, 0xE7, 0x1C, 0x21, 0x69, 0xCE, 0x7C, 0x3D, 0x72, 0x28, 0x01, 0x56, 0xAE, 0x71, 0xFE, 0xEF, 0x29, 0x4B, 0xDC, 0xD1, 0x23, 0x37, 0x9E, 0xA5, 0x80, 0x45, 0xEF, 0x51, 0x7A, 0x65, 0x77, 0x41, 0x90, 0x5D, 0xEA, 0xAB, 0x52, 0x39, 0xF0, 0xE1, 0xA9, 0x77, 0xA1, 0xCD, 0x14, 0xB1, 0x8B, 0x07, 0x4F, 0xC5, 0x44, 0xD9, 0x2F, 0x7A, 0x74, 0xFD, 0xBB, 0xEA, 0x6C, 0x4A, 0x22, 0xD0, 0x78, 0xCA, 0xCF, 0x51, 0x04, 0x0E, 0x88, 0x44, 0x65, 0x41, 0xD9, 0x10, 0x6A, 0x11, 0x66, 0x21, 0x0E, 0xE7, 0x9B, 0x39, 0x36, 0xF6, 0x59, 0x15, 0x83, 0xFB, 0x57, 0x51, 0x02, 0xE2, 0x95, 0xBE, 0x85, 0xDA, 0x78, 0x40, 0xC1, 0x9A, 0x0A, 0xE6, 0x43, 0x95, 0xD8, 0x7A, 0x30, 0x50, 0x15, 0x9F, 0x37, 0x5E, 0xAA, 0x27, 0x50, 0xA4, 0x15, 0x1C, 0x6E, 0xFE, 0x3B, 0xA5, 0xD9, 0xF6, 0x0F, 0xE3, 0xA5, 0xFF, 0xE7, 0xDA, 0xD9, 0x68, 0x64, 0x40, 0xF3, 0x54, 0x32, 0x84, 0xF3, 0x12, 0xC4, 0xD3, 0x77, 0x25, 0x00, 0x60, 0x0D, 0x95, 0xEA, 0x16, 0xE0, 0x51, 0x91, 0x8F, 0xF4, 0x40, 0x1B, 0x8A, 0x2D, 0x84, 0x0E, 0xAC, 0x53, 0x58, 0x08, 0x4E, 0x52, 0xC8, 0xE4, 0x6E, 0xA1, 0xCB, 0xA6, 0xF8, 0x3B, 0xE0, 0x1F, 0x35, 0xA6, 0x37, 0x6A, 0x62, 0x61, 0xDE, 0x6D, 0x5A, 0x70, 0x70, 0x71, 0xC9, 0x24, 0x41, 0x70, 0x7C, 0xCD, 0x3F, 0xD9, 0x38, 0xDB, 0x7B, 0x26, 0xFA, 0xB5, 0x6B, 0xAC, 0xF0, 0x2D, 0x45, 0xD8, 0x55, 0x68, 0xCB, 0x89, 0x04, 0x1F, 0xA0, 0xAD, 0x6F, 0xCB, 0x05, 0x04, 0xB3, 0x26, 0xF4, 0x53, 0x02, 0x9E, 0xB8, 0x76, 0x8D, 0xC6, 0xE8, 0x12, 0x24, 0x38, 0x4E, 0x46, 0x27, 0x30, 0xAE, 0x55, 0x1A, 0xD0, 0xDB, 0xCE, 0x4C, 0x35, 0xFA, 0x7D, 0x9D, 0x40, 0x3E, 0x66, 0x7A, 0xBA, 0xEA, 0x78, 0x6C, 0x6E, 0x47, 0x81, 0xBD, 0xB0, 0x57, 0x5D, 0x1C, 0x94, 0xCC, 0x4F, 0x08, 0xF3, 0x5E, 0xB1, 0x6E, 0x0B, 0xD5, 0x55, 0x45, 0x3F, 0x8B, 0xFD, 0x01, 0x4E, 0x01, 0x21, 0x34, 0x20, 0xA8, 0x49, 0xB0, 0x75, 0x40, 0xB4, 0x55, 0x17, 0x3A, 0x55, 0x1E, 0xBA, 0xF2, 0x31, 0x1D, 0x89, 0x81, 0x7A, 0xB3, 0x87, 0xC9, 0xFB, 0xBB, 0x8A, 0x26, 0x66, 0x99, 0x19, 0x7E, 0x3C, 0xB1, 0x6A, 0x9A, 0x4A, 0xDC, 0xE9, 0x3C, 0xF0, 0x7C, 0x29, 0xC9, 0xA1, 0xE1, 0x78, 0x3A, 0x73, 0x8F, 0xEF, 0x2B, 0x33, 0xDF, 0x0C, 0x53, 0xCE, 0x98, 0x91, 0x7C, 0xE3, 0xC9, 0xE2, 0x26, 0xD8, 0x2F, 0x1A, 0x69, 0xCA, 0xB8, 0x64, 0x3B, 0x43, 0x38, 0xBB, 0xFA, 0x89, 0x59, 0xE0, 0x3C, 0xDA, 0xED, 0x93, 0x65, 0x8B, 0x12, 0xED, 0xDB, 0x6F, 0x8F, 0xC5, 0xFE, 0x9C, 0xEB, 0x88, 0xD2, 0xAB, 0x89, 0xAF, 0xAF, 0x60, 0xFF, 0xFC, 0x40, 0x69, 0x3C, 0xD0, 0x22, 0x02, 0xB8, 0x2C, 0x1D, 0x9A, 0x26, 0x19, 0x33, 0xCB, 0x5A, 0x9D, 0x91, 0xDD, 0x05, 0x39, 0x68, 0xBA, 0x15, 0x2B, 0x14, 0xFD, 0x5D, 0xB8, 0x87, 0x90, 0xAF, 0xAA, 0x5F, 0x54, 0xC7, 0x43, 0x04, 0xF4, 0xE1, 0x49, 0x91, 0x42, 0x27, 0x23, 0xCC, 0x5A, 0xFC, 0xF1, 0xA6, 0x2A, 0x39, 0x19, 0xC1, 0x31, 0xBF, 0xE5, 0x89, 0x8C, 0x48, 0xA7, 0xCE, 0x0E, 0x67, 0x18, 0xA1, 0x07, 0x8E, 0xBD, 0xFE, 0x2A, 0x9F, 0xF0, 0xA3, 0x19, 0xAA, 0xBC, 0xD7, 0x6D, 0x43, 0x1C, 0x3D, 0x31, 0xBA, 0x9B, 0xD4, 0xF7, 0xDF, 0x2C, 0x7F, 0x37, 0x7B, 0xD9, 0x7B, 0xDE, 0x62, 0x5C, 0xDE, 0x21, 0x38, 0x4D, 0xB7, 0x4A, 0x45, 0x04, 0x7D, 0x76, 0x4A, 0x93, 0xFE, 0x8E, 0x49, 0x04, 0xD0, 0xAD, 0x99, 0xCD, 0xF0, 0x86, 0x24, 0x5E, 0x73, }; static unsigned char dh4096_g[ ] = { 0x02, }; DH *dh = NULL; /* OpenSSL 1.1.0 added auto-init */ #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) SSL_load_error_strings(); SSL_library_init(); #endif /* OpenSSL < 1.1.0 */ if (( ssl_ctx = SSL_CTX_new( SSLv23_server_method())) == NULL ) { syslog( LOG_ERR, "Liberror: tls_server_setup SSL_CTX_new: %s", ERR_error_string( ERR_get_error(), NULL )); return( NULL ); } if (( dh = DH_new( )) == NULL ) { syslog( LOG_ERR, "Liberror: tls_server_setup DH_new: %s", ERR_error_string( ERR_get_error(), NULL )); goto error; } #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) if ( DH_set0_pqg( dh, BN_bin2bn( dh4096_p, sizeof( dh4096_p ), NULL ), NULL, BN_bin2bn( dh4096_g, sizeof( dh4096_g ), NULL )) != 1 ) { syslog( LOG_ERR, "Liberror: tls_server_setup DH_set0_pqg: %s", ERR_error_string( ERR_get_error(), NULL )); } #else dh->p = BN_bin2bn( dh4096_p, sizeof( dh4096_p ), NULL ); dh->g = BN_bin2bn( dh4096_g, sizeof( dh4096_g ), NULL ); if (( dh->p == NULL ) || ( dh->g == NULL )) { syslog( LOG_ERR, "Liberror: tls_server_setup BN_bin2bn: %s", ERR_error_string( ERR_get_error(), NULL )); goto error; } #endif /* OpenSSL 1.1.0 */ if ( SSL_CTX_set_tmp_dh( ssl_ctx, dh ) != 1 ) { syslog( LOG_ERR, "Liberror: tls_server_setup SSL_CTX_set_tmp_dh: %s", ERR_error_string( ERR_get_error(), NULL )); goto error; } /* Disable SSLv2 and SSLv3, prefer server cipher ordering */ SSL_CTX_set_options( ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_CIPHER_SERVER_PREFERENCE ); if ( ciphers == NULL ) { SSL_CTX_set_cipher_list( ssl_ctx, "EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:" "RSA+AES256:DH+CHACHA20:DH+AES128:DH+AES256:!MD5" ); } else { SSL_CTX_set_cipher_list( ssl_ctx, ciphers ); } if ( SSL_CTX_use_PrivateKey_file( ssl_ctx, privatekey, SSL_FILETYPE_PEM ) != 1 ) { syslog( LOG_ERR, "Liberror: tls_server_setup " "SSL_CTX_use_PrivateKey_file: %s: %s", privatekey, ERR_error_string( ERR_get_error(), NULL )); goto error; } if ( SSL_CTX_use_certificate_chain_file( ssl_ctx, cert ) != 1 ) { syslog( LOG_ERR, "Liberror: tls_server_setup " "SSL_CTX_use_certificate_chain_file: %s: %s", cert, ERR_error_string( ERR_get_error(), NULL )); goto error; } /* Verify that private key matches cert */ if ( SSL_CTX_check_private_key( ssl_ctx ) != 1 ) { syslog( LOG_ERR, "Liberror: tls_server_setup " "SSL_CTX_check_private_key: %s", ERR_error_string( ERR_get_error(), NULL )); goto error; } /* Load CA */ if ( caFile != NULL ) { if ( SSL_CTX_load_verify_locations( ssl_ctx, caFile, NULL ) != 1 ) { syslog( LOG_ERR, "Liberror: tls_server_setup " "SSL_CTX_load_verify_locations: %s: %s", caFile, ERR_error_string( ERR_get_error(), NULL )); goto error; } } if ( caDir != NULL ) { if ( SSL_CTX_load_verify_locations( ssl_ctx, NULL, caDir ) != 1 ) { syslog( LOG_ERR, "Liberror: tls_server_setup " "SSL_CTX_load_verify_locations: %s: %s", caDir, ERR_error_string( ERR_get_error(), NULL )); goto error; } } /* Set level of security expecations */ if ( authlevel <= 1 ) { ssl_mode = SSL_VERIFY_NONE; } else { /* authlevel == 2 */ ssl_mode = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT; } SSL_CTX_set_verify( ssl_ctx, ssl_mode, NULL ); #ifndef OPENSSL_NO_ECDH /* Do not reuse the same ECDH key pair */ SSL_CTX_set_options(ssl_ctx, SSL_OP_SINGLE_ECDH_USE); #if defined(OPENSSL_IS_BORINGSSL) || (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)) /* OpenSSL >= 1.1.0 automatically enables automatic handling of parameter * selection and makes SSL_CTX_set_ecdh_auto a noop, so we don't want * to do anything. */ #elif OPENSSL_VERSION_NUMBER >= 0x10002000L /* OpenSSL >= 1.0.2 automatically handles parameter selection */ SSL_CTX_set_ecdh_auto(ssl_ctx, 1); #elif OPENSSL_VERSION_NUMBER >= 0x10000000L /* Manually select the curve. This selection is compliant with RFC 6460 * when AES-256 cipher suites are in use, but noncompliant when AES-128 * cipher suites are used. Oh, well. */ EC_KEY *ecdh; if (( ecdh = EC_KEY_new_by_curve_name( NID_secp384r1 )) != NULL ) { SSL_CTX_set_tmp_ecdh(ssl_ctx, ecdh); EC_KEY_free(ecdh); } else { syslog( LOG_ERR, "Liberror: tls_server_setup EC_KEY_new failed: %s", ERR_error_string( ERR_get_error(), NULL )); } #endif /* openssl 1.0 - 1.0.1 */ #endif /* OPENSSL_NO_ECDH */ return( ssl_ctx ); error: SSL_CTX_free( ssl_ctx ); if ( dh != NULL ) { DH_free( dh ); } return( NULL ); }
int network_init(server *srv) { buffer *b; size_t i, j; network_backend_t backend; #if OPENSSL_VERSION_NUMBER >= 0x0090800fL #ifndef OPENSSL_NO_ECDH EC_KEY *ecdh; int nid; #endif #endif #ifdef USE_OPENSSL # ifndef OPENSSL_NO_DH DH *dh; # endif BIO *bio; /* 1024-bit MODP Group with 160-bit prime order subgroup (RFC5114) * -----BEGIN DH PARAMETERS----- * MIIBDAKBgQCxC4+WoIDgHd6S3l6uXVTsUsmfvPsGo8aaap3KUtI7YWBz4oZ1oj0Y * mDjvHi7mUsAT7LSuqQYRIySXXDzUm4O/rMvdfZDEvXCYSI6cIZpzck7/1vrlZEc4 * +qMaT/VbzMChUa9fDci0vUW/N982XBpl5oz9p21NpwjfH7K8LkpDcQKBgQCk0cvV * w/00EmdlpELvuZkF+BBN0lisUH/WQGz/FCZtMSZv6h5cQVZLd35pD1UE8hMWAhe0 * sBuIal6RVH+eJ0n01/vX07mpLuGQnQ0iY/gKdqaiTAh6CR9THb8KAWm2oorWYqTR * jnOvoy13nVkY0IvIhY9Nzvl8KiSFXm7rIrOy5QICAKA= * -----END DH PARAMETERS----- */ static const unsigned char dh1024_p[]={ 0xB1,0x0B,0x8F,0x96,0xA0,0x80,0xE0,0x1D,0xDE,0x92,0xDE,0x5E, 0xAE,0x5D,0x54,0xEC,0x52,0xC9,0x9F,0xBC,0xFB,0x06,0xA3,0xC6, 0x9A,0x6A,0x9D,0xCA,0x52,0xD2,0x3B,0x61,0x60,0x73,0xE2,0x86, 0x75,0xA2,0x3D,0x18,0x98,0x38,0xEF,0x1E,0x2E,0xE6,0x52,0xC0, 0x13,0xEC,0xB4,0xAE,0xA9,0x06,0x11,0x23,0x24,0x97,0x5C,0x3C, 0xD4,0x9B,0x83,0xBF,0xAC,0xCB,0xDD,0x7D,0x90,0xC4,0xBD,0x70, 0x98,0x48,0x8E,0x9C,0x21,0x9A,0x73,0x72,0x4E,0xFF,0xD6,0xFA, 0xE5,0x64,0x47,0x38,0xFA,0xA3,0x1A,0x4F,0xF5,0x5B,0xCC,0xC0, 0xA1,0x51,0xAF,0x5F,0x0D,0xC8,0xB4,0xBD,0x45,0xBF,0x37,0xDF, 0x36,0x5C,0x1A,0x65,0xE6,0x8C,0xFD,0xA7,0x6D,0x4D,0xA7,0x08, 0xDF,0x1F,0xB2,0xBC,0x2E,0x4A,0x43,0x71, }; static const unsigned char dh1024_g[]={ 0xA4,0xD1,0xCB,0xD5,0xC3,0xFD,0x34,0x12,0x67,0x65,0xA4,0x42, 0xEF,0xB9,0x99,0x05,0xF8,0x10,0x4D,0xD2,0x58,0xAC,0x50,0x7F, 0xD6,0x40,0x6C,0xFF,0x14,0x26,0x6D,0x31,0x26,0x6F,0xEA,0x1E, 0x5C,0x41,0x56,0x4B,0x77,0x7E,0x69,0x0F,0x55,0x04,0xF2,0x13, 0x16,0x02,0x17,0xB4,0xB0,0x1B,0x88,0x6A,0x5E,0x91,0x54,0x7F, 0x9E,0x27,0x49,0xF4,0xD7,0xFB,0xD7,0xD3,0xB9,0xA9,0x2E,0xE1, 0x90,0x9D,0x0D,0x22,0x63,0xF8,0x0A,0x76,0xA6,0xA2,0x4C,0x08, 0x7A,0x09,0x1F,0x53,0x1D,0xBF,0x0A,0x01,0x69,0xB6,0xA2,0x8A, 0xD6,0x62,0xA4,0xD1,0x8E,0x73,0xAF,0xA3,0x2D,0x77,0x9D,0x59, 0x18,0xD0,0x8B,0xC8,0x85,0x8F,0x4D,0xCE,0xF9,0x7C,0x2A,0x24, 0x85,0x5E,0x6E,0xEB,0x22,0xB3,0xB2,0xE5, }; #endif struct nb_map { network_backend_t nb; const char *name; } network_backends[] = { /* lowest id wins */ #if defined USE_SENDFILE { NETWORK_BACKEND_SENDFILE, "sendfile" }, #endif #if defined USE_LINUX_SENDFILE { NETWORK_BACKEND_SENDFILE, "linux-sendfile" }, #endif #if defined USE_FREEBSD_SENDFILE { NETWORK_BACKEND_SENDFILE, "freebsd-sendfile" }, #endif #if defined USE_SOLARIS_SENDFILEV { NETWORK_BACKEND_SENDFILE, "solaris-sendfilev" }, #endif #if defined USE_WRITEV { NETWORK_BACKEND_WRITEV, "writev" }, #endif { NETWORK_BACKEND_WRITE, "write" }, { NETWORK_BACKEND_UNSET, NULL } }; #ifdef USE_OPENSSL /* load SSL certificates */ for (i = 0; i < srv->config_context->used; i++) { specific_config *s = srv->config_storage[i]; #ifndef SSL_OP_NO_COMPRESSION # define SSL_OP_NO_COMPRESSION 0 #endif long ssloptions = SSL_OP_ALL | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_NO_COMPRESSION; if (buffer_string_is_empty(s->ssl_pemfile) && buffer_string_is_empty(s->ssl_ca_file)) continue; if (srv->ssl_is_init == 0) { SSL_load_error_strings(); SSL_library_init(); OpenSSL_add_all_algorithms(); srv->ssl_is_init = 1; if (0 == RAND_status()) { log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", "not enough entropy in the pool"); return -1; } } if (!buffer_string_is_empty(s->ssl_pemfile)) { #ifdef OPENSSL_NO_TLSEXT data_config *dc = (data_config *)srv->config_context->data[i]; if (COMP_HTTP_HOST == dc->comp) { log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", "can't use ssl.pemfile with $HTTP[\"host\"], openssl version does not support TLS extensions"); return -1; } #endif if (network_openssl_load_pemfile(srv, i)) return -1; } if (!buffer_string_is_empty(s->ssl_ca_file)) { s->ssl_ca_file_cert_names = SSL_load_client_CA_file(s->ssl_ca_file->ptr); if (NULL == s->ssl_ca_file_cert_names) { log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file); } } if (buffer_string_is_empty(s->ssl_pemfile) || !s->ssl_enabled) continue; if (NULL == (s->ssl_ctx = SSL_CTX_new(SSLv23_server_method()))) { log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", ERR_error_string(ERR_get_error(), NULL)); return -1; } /* completely useless identifier; required for client cert verification to work with sessions */ if (0 == SSL_CTX_set_session_id_context(s->ssl_ctx, (const unsigned char*) CONST_STR_LEN("lighttpd"))) { log_error_write(srv, __FILE__, __LINE__, "ss:s", "SSL:", "failed to set session context", ERR_error_string(ERR_get_error(), NULL)); return -1; } if (s->ssl_empty_fragments) { #ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS ssloptions &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; #else ssloptions &= ~0x00000800L; /* hardcode constant */ log_error_write(srv, __FILE__, __LINE__, "ss", "WARNING: SSL:", "'insert empty fragments' not supported by the openssl version used to compile lighttpd with"); #endif } SSL_CTX_set_options(s->ssl_ctx, ssloptions); SSL_CTX_set_info_callback(s->ssl_ctx, ssl_info_callback); if (!s->ssl_use_sslv2) { /* disable SSLv2 */ if ((SSL_OP_NO_SSLv2 & SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_SSLv2)) != SSL_OP_NO_SSLv2) { log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", ERR_error_string(ERR_get_error(), NULL)); return -1; } } if (!s->ssl_use_sslv3) { /* disable SSLv3 */ if ((SSL_OP_NO_SSLv3 & SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_SSLv3)) != SSL_OP_NO_SSLv3) { log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", ERR_error_string(ERR_get_error(), NULL)); return -1; } } if (!buffer_string_is_empty(s->ssl_cipher_list)) { /* Disable support for low encryption ciphers */ if (SSL_CTX_set_cipher_list(s->ssl_ctx, s->ssl_cipher_list->ptr) != 1) { log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", ERR_error_string(ERR_get_error(), NULL)); return -1; } if (s->ssl_honor_cipher_order) { SSL_CTX_set_options(s->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); } } #ifndef OPENSSL_NO_DH /* Support for Diffie-Hellman key exchange */ if (!buffer_string_is_empty(s->ssl_dh_file)) { /* DH parameters from file */ bio = BIO_new_file((char *) s->ssl_dh_file->ptr, "r"); if (bio == NULL) { log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: Unable to open file", s->ssl_dh_file->ptr); return -1; } dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); BIO_free(bio); if (dh == NULL) { log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: PEM_read_bio_DHparams failed", s->ssl_dh_file->ptr); return -1; } } else { BIGNUM *dh_p, *dh_g; /* Default DH parameters from RFC5114 */ dh = DH_new(); if (dh == NULL) { log_error_write(srv, __FILE__, __LINE__, "s", "SSL: DH_new () failed"); return -1; } dh_p = BN_bin2bn(dh1024_p,sizeof(dh1024_p), NULL); dh_g = BN_bin2bn(dh1024_g,sizeof(dh1024_g), NULL); if ((dh_p == NULL) || (dh_g == NULL)) { DH_free(dh); log_error_write(srv, __FILE__, __LINE__, "s", "SSL: BN_bin2bn () failed"); return -1; } #if OPENSSL_VERSION_NUMBER < 0x10100000L \ || defined(LIBRESSL_VERSION_NUMBER) dh->p = dh_p; dh->g = dh_g; dh->length = 160; #else DH_set0_pqg(dh, dh_p, NULL, dh_g); DH_set_length(dh, 160); #endif } SSL_CTX_set_tmp_dh(s->ssl_ctx,dh); SSL_CTX_set_options(s->ssl_ctx,SSL_OP_SINGLE_DH_USE); DH_free(dh); #else if (!buffer_string_is_empty(s->ssl_dh_file)) { log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: openssl compiled without DH support, can't load parameters from", s->ssl_dh_file->ptr); } #endif #if OPENSSL_VERSION_NUMBER >= 0x0090800fL #ifndef OPENSSL_NO_ECDH /* Support for Elliptic-Curve Diffie-Hellman key exchange */ if (!buffer_string_is_empty(s->ssl_ec_curve)) { /* OpenSSL only supports the "named curves" from RFC 4492, section 5.1.1. */ nid = OBJ_sn2nid((char *) s->ssl_ec_curve->ptr); if (nid == 0) { log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: Unknown curve name", s->ssl_ec_curve->ptr); return -1; } } else { /* Default curve */ nid = OBJ_sn2nid("prime256v1"); } ecdh = EC_KEY_new_by_curve_name(nid); if (ecdh == NULL) { log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: Unable to create curve", s->ssl_ec_curve->ptr); return -1; } SSL_CTX_set_tmp_ecdh(s->ssl_ctx,ecdh); SSL_CTX_set_options(s->ssl_ctx,SSL_OP_SINGLE_ECDH_USE); EC_KEY_free(ecdh); #endif #endif /* load all ssl.ca-files specified in the config into each SSL_CTX to be prepared for SNI */ for (j = 0; j < srv->config_context->used; j++) { specific_config *s1 = srv->config_storage[j]; if (!buffer_string_is_empty(s1->ssl_ca_file)) { if (1 != SSL_CTX_load_verify_locations(s->ssl_ctx, s1->ssl_ca_file->ptr, NULL)) { log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", ERR_error_string(ERR_get_error(), NULL), s1->ssl_ca_file); return -1; } } } if (s->ssl_verifyclient) { if (NULL == s->ssl_ca_file_cert_names) { log_error_write(srv, __FILE__, __LINE__, "s", "SSL: You specified ssl.verifyclient.activate but no ca_file" ); return -1; } SSL_CTX_set_client_CA_list(s->ssl_ctx, SSL_dup_CA_list(s->ssl_ca_file_cert_names)); SSL_CTX_set_verify( s->ssl_ctx, SSL_VERIFY_PEER | (s->ssl_verifyclient_enforce ? SSL_VERIFY_FAIL_IF_NO_PEER_CERT : 0), NULL ); SSL_CTX_set_verify_depth(s->ssl_ctx, s->ssl_verifyclient_depth); } if (SSL_CTX_use_certificate(s->ssl_ctx, s->ssl_pemfile_x509) < 0) { log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile); return -1; } if (SSL_CTX_use_PrivateKey(s->ssl_ctx, s->ssl_pemfile_pkey) < 0) { log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile); return -1; } if (SSL_CTX_check_private_key(s->ssl_ctx) != 1) { log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:", "Private key does not match the certificate public key, reason:", ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile); return -1; } SSL_CTX_set_default_read_ahead(s->ssl_ctx, 1); SSL_CTX_set_mode(s->ssl_ctx, SSL_CTX_get_mode(s->ssl_ctx) | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); # ifndef OPENSSL_NO_TLSEXT if (!SSL_CTX_set_tlsext_servername_callback(s->ssl_ctx, network_ssl_servername_callback) || !SSL_CTX_set_tlsext_servername_arg(s->ssl_ctx, srv)) { log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", "failed to initialize TLS servername callback, openssl library does not support TLS servername extension"); return -1; } # endif } #endif b = buffer_init(); buffer_copy_buffer(b, srv->srvconf.bindhost); buffer_append_string_len(b, CONST_STR_LEN(":")); buffer_append_int(b, srv->srvconf.port); if (0 != network_server_init(srv, b, srv->config_storage[0])) { buffer_free(b); return -1; } buffer_free(b); #ifdef USE_OPENSSL srv->network_ssl_backend_write = network_write_chunkqueue_openssl; #endif /* get a usefull default */ backend = network_backends[0].nb; /* match name against known types */ if (!buffer_string_is_empty(srv->srvconf.network_backend)) { for (i = 0; network_backends[i].name; i++) { /**/ if (buffer_is_equal_string(srv->srvconf.network_backend, network_backends[i].name, strlen(network_backends[i].name))) { backend = network_backends[i].nb; break; } } if (NULL == network_backends[i].name) { /* we don't know it */ log_error_write(srv, __FILE__, __LINE__, "sb", "server.network-backend has a unknown value:", srv->srvconf.network_backend); return -1; } } switch(backend) { case NETWORK_BACKEND_WRITE: srv->network_backend_write = network_write_chunkqueue_write; break; #if defined(USE_WRITEV) case NETWORK_BACKEND_WRITEV: srv->network_backend_write = network_write_chunkqueue_writev; break; #endif #if defined(USE_SENDFILE) case NETWORK_BACKEND_SENDFILE: srv->network_backend_write = network_write_chunkqueue_sendfile; break; #endif default: return -1; } /* check for $SERVER["socket"] */ for (i = 1; i < srv->config_context->used; i++) { data_config *dc = (data_config *)srv->config_context->data[i]; specific_config *s = srv->config_storage[i]; /* not our stage */ if (COMP_SERVER_SOCKET != dc->comp) continue; if (dc->cond != CONFIG_COND_EQ) continue; /* check if we already know this socket, * if yes, don't init it */ for (j = 0; j < srv->srv_sockets.used; j++) { if (buffer_is_equal(srv->srv_sockets.ptr[j]->srv_token, dc->string)) { break; } } if (j == srv->srv_sockets.used) { if (0 != network_server_init(srv, dc->string, s)) return -1; } } return 0; }
/** Initialize the SSL context. * \return pointer to SSL context object. */ SSL_CTX * ssl_init(char *private_key_file, char *ca_file, int req_client_cert) { const SSL_METHOD *meth; /* If this const gives you a warning, you're using an old version of OpenSSL. Walker, this means you! */ /* uint8_t context[128]; */ DH *dh; unsigned int reps = 1; if (!bio_err) { if (!SSL_library_init()) return NULL; SSL_load_error_strings(); /* Error write context */ bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); } lock_file(stderr); fputs("Seeding OpenSSL random number pool.\n", stderr); unlock_file(stderr); while (!RAND_status()) { /* At this point, a system with /dev/urandom or a EGD file in the usual places will have enough entropy. Otherwise, be lazy and use random numbers until it's satisfied. */ uint32_t gibberish[4]; int n; /* sfmt_fill_array32 requires a much larger array. */ for (n = 0; n < 4; n++) gibberish[n] = sfmt_genrand_uint32(&rand_state); RAND_seed(gibberish, sizeof gibberish); reps += 1; } lock_file(stderr); fprintf(stderr, "Seeded after %u %s.\n", reps, reps > 1 ? "cycles" : "cycle"); unlock_file(stderr); /* Set up SIGPIPE handler here? */ /* Create context */ meth = SSLv23_server_method(); ctx = SSL_CTX_new(meth); /* Load keys/certs */ if (private_key_file && *private_key_file) { if (!SSL_CTX_use_certificate_chain_file(ctx, private_key_file)) { ssl_errordump ("Unable to load server certificate - only anonymous ciphers supported."); } if (!SSL_CTX_use_PrivateKey_file(ctx, private_key_file, SSL_FILETYPE_PEM)) { ssl_errordump ("Unable to load private key - only anonymous ciphers supported."); } } /* Load trusted CAs */ if (ca_file && *ca_file) { if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) { ssl_errordump("Unable to load CA certificates"); } else { if (req_client_cert) SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, client_verify_callback); else SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, client_verify_callback); #if (OPENSSL_VERSION_NUMBER < 0x0090600fL) SSL_CTX_set_verify_depth(ctx, 1); #endif } } SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE | SSL_OP_ALL); SSL_CTX_set_mode(ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); /* Set up DH callback */ dh = get_dh1024(); SSL_CTX_set_tmp_dh(ctx, dh); /* The above function makes a private copy of this */ DH_free(dh); /* Set the cipher list to the usual default list, except that * we'll allow anonymous diffie-hellman, too. */ SSL_CTX_set_cipher_list(ctx, "ALL:ADH:RC4+RSA:+SSLv2:@STRENGTH"); /* Set up session cache if we can */ /* strncpy((char *) context, MUDNAME, 128); SSL_CTX_set_session_id_context(ctx, context, strlen(context)); */ return ctx; }
void context_init(void) { /* init SSL */ int i; #if SSLEAY_VERSION_NUMBER >= 0x00907000L /* Load all bundled ENGINEs into memory and make them visible */ ENGINE_load_builtin_engines(); /* Register all of them for every algorithm they collectively implement */ ENGINE_register_all_complete(); #endif if(!init_prng()) log(LOG_INFO, "PRNG seeded successfully"); SSLeay_add_ssl_algorithms(); SSL_load_error_strings(); if(options.option.client) { ctx=SSL_CTX_new(SSLv3_client_method()); } else { /* Server mode */ ctx=SSL_CTX_new(SSLv23_server_method()); #ifndef NO_RSA SSL_CTX_set_tmp_rsa_callback(ctx, tmp_rsa_cb); #endif /* NO_RSA */ if(init_dh()) log(LOG_WARNING, "Diffie-Hellman initialization failed"); } if(options.ssl_options) { log(LOG_DEBUG, "Configuration SSL options: 0x%08lX", options.ssl_options); log(LOG_DEBUG, "SSL options set: 0x%08lX", SSL_CTX_set_options(ctx, options.ssl_options)); } #if SSLEAY_VERSION_NUMBER >= 0x00906000L SSL_CTX_set_mode(ctx, SSL_MODE_ENABLE_PARTIAL_WRITE|SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); #endif /* OpenSSL-0.9.6 */ SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_BOTH); SSL_CTX_set_timeout(ctx, options.session_timeout); if(options.option.cert) { if(!SSL_CTX_use_certificate_chain_file(ctx, options.cert)) { log(LOG_ERR, "Error reading certificate file: %s", options.cert); sslerror("SSL_CTX_use_certificate_chain_file"); exit(1); } log(LOG_DEBUG, "Certificate: %s", options.cert); log(LOG_DEBUG, "Key file: %s", options.key); #ifdef USE_WIN32 SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_cb); #endif for(i=0; i<3; i++) { #ifdef NO_RSA if(SSL_CTX_use_PrivateKey_file(ctx, options.key, SSL_FILETYPE_PEM)) #else /* NO_RSA */ if(SSL_CTX_use_RSAPrivateKey_file(ctx, options.key, SSL_FILETYPE_PEM)) #endif /* NO_RSA */ break; if(i<2 && ERR_GET_REASON(ERR_peek_error())==EVP_R_BAD_DECRYPT) { sslerror_stack(); /* dump the error stack */ log(LOG_ERR, "Wrong pass phrase: retrying"); continue; } #ifdef NO_RSA sslerror("SSL_CTX_use_PrivateKey_file"); #else /* NO_RSA */ sslerror("SSL_CTX_use_RSAPrivateKey_file"); #endif /* NO_RSA */ exit(1); } if(!SSL_CTX_check_private_key(ctx)) { sslerror("Private key does not match the certificate"); exit(1); } } verify_init(); /* Initialize certificate verification */ SSL_CTX_set_info_callback(ctx, info_callback); if(options.cipher_list) { if (!SSL_CTX_set_cipher_list(ctx, options.cipher_list)) { sslerror("SSL_CTX_set_cipher_list"); exit(1); } } }
/** * Initializes a ssl connection for server use. * @param pemfilename Filename for the key/cert file * @return An ssl connection, or NULL if an error occured. */ ssl_server_connection *init_ssl_server (char *pemfile, char *clientpemfile) { #ifdef HAVE_OPENSSL ssl_server_connection *ssl_server = new_ssl_server_connection(pemfile, clientpemfile); ASSERT(pemfile); if (!ssl_initilized) { start_ssl(); } if ((ssl_server->method= SSLv23_server_method()) == NULL ) { handle_ssl_error("init_ssl_server()"); log("%s: init_ssl_server (): Cannot initialize the SSL method!\n", prog); goto sslerror; } if ((ssl_server->ctx= SSL_CTX_new(ssl_server->method)) == NULL ) { handle_ssl_error("init_ssl_server()"); log("%s: init_ssl_server (): Cannot initialize SSL server" " certificate handler!\n" , prog); goto sslerror; } if (SSL_CTX_use_certificate_file(ssl_server->ctx, pemfile, SSL_FILETYPE_PEM) <= 0) { handle_ssl_error("init_ssl_server()"); log("%s: init_ssl_server(): Cannot initialize SSL server" " certificate!\n", prog); goto sslerror; } if (SSL_CTX_use_PrivateKey_file(ssl_server->ctx, pemfile, SSL_FILETYPE_PEM) <= 0) { handle_ssl_error("init_ssl_server()"); log("%s: init_ssl_server(): Cannot initialize SSL server" " private key!\n", prog); goto sslerror; } if (!SSL_CTX_check_private_key(ssl_server->ctx)) { handle_ssl_error("init_ssl_server()"); log("%s: init_ssl_server(): The private key does not match the" " certificate public key!\n", prog); goto sslerror; } /* * We need this to force transmission of client certs */ if (!verify_init(ssl_server)) { handle_ssl_error("init_ssl_server()"); log("%s: init_ssl_server(): Verification engine was not" " properly initilized!\n", prog); goto sslerror; } if (ssl_server->clientpemfile != NULL) { verify_info(ssl_server); } return ssl_server; sslerror: cleanup_ssl_server_socket(ssl_server); return NULL; #else return NULL; #endif }
static int openssl_ssl_ctx_new(lua_State*L) { const char* meth = luaL_optstring(L, 1, "TLSv1"); #if OPENSSL_VERSION_NUMBER >= 0x01000000L const #endif SSL_METHOD* method = NULL; const char* ciphers; SSL_CTX* ctx; if (strcmp(meth, "SSLv3") == 0) method = SSLv3_method(); /* SSLv3 */ else if (strcmp(meth, "SSLv3_server") == 0) method = SSLv3_server_method(); /* SSLv3 */ else if (strcmp(meth, "SSLv3_client") == 0) method = SSLv3_client_method(); /* SSLv3 */ else if (strcmp(meth, "SSLv23") == 0) method = SSLv23_method(); /* SSLv3 but can rollback to v2 */ else if (strcmp(meth, "SSLv23_server") == 0) method = SSLv23_server_method(); /* SSLv3 but can rollback to v2 */ else if (strcmp(meth, "SSLv23_client") == 0) method = SSLv23_client_method(); /* SSLv3 but can rollback to v2 */ else if (strcmp(meth, "TLSv1_1") == 0) method = TLSv1_1_method(); /* TLSv1.0 */ else if (strcmp(meth, "TLSv1_1_server") == 0) method = TLSv1_1_server_method(); /* TLSv1.0 */ else if (strcmp(meth, "TLSv1_1_client") == 0) method = TLSv1_1_client_method(); /* TLSv1.0 */ else if (strcmp(meth, "TLSv1_2") == 0) method = TLSv1_2_method(); /* TLSv1.0 */ else if (strcmp(meth, "TLSv1_2_server") == 0) method = TLSv1_2_server_method(); /* TLSv1.0 */ else if (strcmp(meth, "TLSv1_2_client") == 0) method = TLSv1_2_client_method(); /* TLSv1.0 */ else if (strcmp(meth, "TLSv1") == 0) method = TLSv1_method(); /* TLSv1.0 */ else if (strcmp(meth, "TLSv1_server") == 0) method = TLSv1_server_method(); /* TLSv1.0 */ else if (strcmp(meth, "TLSv1_client") == 0) method = TLSv1_client_method(); /* TLSv1.0 */ else if (strcmp(meth, "DTLSv1") == 0) method = DTLSv1_method(); /* DTLSv1.0 */ else if (strcmp(meth, "DTLSv1_server") == 0) method = DTLSv1_server_method(); /* DTLSv1.0 */ else if (strcmp(meth, "DTLSv1_client") == 0) method = DTLSv1_client_method(); /* DTLSv1.0 */ #ifndef OPENSSL_NO_SSL2 #if OPENSSL_VERSION_NUMBER < 0x10100000L else if (strcmp(meth, "SSLv2") == 0) method = SSLv2_method(); /* SSLv2 */ else if (strcmp(meth, "SSLv2_server") == 0) method = SSLv2_server_method(); /* SSLv2 */ else if (strcmp(meth, "SSLv2_client") == 0) method = SSLv2_client_method(); #endif #ifdef LOAD_SSL_CUSTOM LOAD_SSL_CUSTOM #endif #endif else luaL_error(L, "#1:%s not supported\n" "Maybe SSLv3 SSLv23 TLSv1 TLSv1_1 TLSv1_2 DTLSv1 [SSLv2], option followed by _client or _server\n", "default is SSLv3", meth); ciphers = luaL_optstring(L, 2, SSL_DEFAULT_CIPHER_LIST); ctx = SSL_CTX_new(method); if (!ctx) luaL_error(L, "#1:%s not supported\n" "Maybe SSLv3 SSLv23 TLSv1 TLSv1_1 TLSv1_2 DTLSv1 [SSLv2], option followed by _client or _server\n", "default is SSLv3", meth); openssl_newvalue(L, ctx); SSL_CTX_set_cipher_list(ctx, ciphers); PUSH_OBJECT(ctx, "openssl.ssl_ctx"); SSL_CTX_set_app_data(ctx, L); return 1; }
int MAIN(int argc, char **argv) { int ret = 1, i; int verbose = 0, Verbose = 0; const char **pp; const char *p; int badops = 0; SSL_CTX *ctx = NULL; SSL *ssl = NULL; char *ciphers = NULL; const SSL_METHOD *meth = NULL; STACK_OF(SSL_CIPHER) *sk; char buf[512]; BIO *STDout = NULL; meth = SSLv23_server_method(); apps_startup(); if (bio_err == NULL) bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); STDout = BIO_new_fp(stdout, BIO_NOCLOSE); #ifdef OPENSSL_SYS_VMS { BIO *tmpbio = BIO_new(BIO_f_linebuffer()); STDout = BIO_push(tmpbio, STDout); } #endif if (!load_config(bio_err, NULL)) goto end; argc--; argv++; while (argc >= 1) { if (strcmp(*argv, "-v") == 0) verbose = 1; else if (strcmp(*argv, "-V") == 0) verbose = Verbose = 1; #ifndef OPENSSL_NO_SSL2 else if (strcmp(*argv, "-ssl2") == 0) meth = SSLv2_client_method(); #endif #ifndef OPENSSL_NO_SSL3 else if (strcmp(*argv, "-ssl3") == 0) meth = SSLv3_client_method(); #endif #ifndef OPENSSL_NO_TLS1 else if (strcmp(*argv, "-tls1") == 0) meth = TLSv1_client_method(); #endif else if ((strncmp(*argv, "-h", 2) == 0) || (strcmp(*argv, "-?") == 0)) { badops = 1; break; } else { ciphers = *argv; } argc--; argv++; } if (badops) { for (pp = ciphers_usage; (*pp != NULL); pp++) BIO_printf(bio_err, "%s", *pp); goto end; } OpenSSL_add_ssl_algorithms(); ctx = SSL_CTX_new(meth); if (ctx == NULL) goto err; if (ciphers != NULL) { if (!SSL_CTX_set_cipher_list(ctx, ciphers)) { BIO_printf(bio_err, "Error in cipher list\n"); goto err; } } ssl = SSL_new(ctx); if (ssl == NULL) goto err; if (!verbose) { for (i = 0;; i++) { p = SSL_get_cipher_list(ssl, i); if (p == NULL) break; if (i != 0) BIO_printf(STDout, ":"); BIO_printf(STDout, "%s", p); } BIO_printf(STDout, "\n"); } else { /* verbose */ sk = SSL_get_ciphers(ssl); for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) { SSL_CIPHER *c; c = sk_SSL_CIPHER_value(sk, i); if (Verbose) { unsigned long id = c->id; int id0 = (int)(id >> 24); int id1 = (int)((id >> 16) & 0xffL); int id2 = (int)((id >> 8) & 0xffL); int id3 = (int)(id & 0xffL); if ((id & 0xff000000L) == 0x02000000L) { /* SSL2 cipher */ BIO_printf(STDout, " 0x%02X,0x%02X,0x%02X - ", id1, id2, id3); } else if ((id & 0xff000000L) == 0x03000000L) { /* SSL3 cipher */ BIO_printf(STDout, " 0x%02X,0x%02X - ", id2, id3); } else { /* whatever */ BIO_printf(STDout, "0x%02X,0x%02X,0x%02X,0x%02X - ", id0, id1, id2, id3); } } BIO_puts(STDout, SSL_CIPHER_description(c, buf, sizeof buf)); } } ret = 0; if (0) { err: SSL_load_error_strings(); ERR_print_errors(bio_err); } end: if (ctx != NULL) SSL_CTX_free(ctx); if (ssl != NULL) SSL_free(ssl); if (STDout != NULL) BIO_free_all(STDout); apps_shutdown(); OPENSSL_EXIT(ret); }
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 SSL_METHOD *method; const int fd = mowgli_vio_getfd(vio); vio->error.op = MOWGLI_VIO_ERR_OP_LISTEN; switch (connection->settings.ssl_version) { case MOWGLI_VIO_SSLFLAGS_SSLV2: method = SSLv23_server_method(); break; case MOWGLI_VIO_SSLFLAGS_SSLV3: method = SSLv3_server_method(); break; case MOWGLI_VIO_SSLFLAGS_TLSV10: case MOWGLI_VIO_SSLFLAGS_TLSV11: case MOWGLI_VIO_SSLFLAGS_TLSV12: method = TLSv1_server_method(); break; default: /* Compat method */ method = SSLv23_server_method(); } connection->ssl_context = SSL_CTX_new((SSL_METHOD *) method); if (connection->ssl_context == NULL) return mowgli_vio_err_sslerrcode(vio, ERR_get_error()); 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); 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; }
ctx * ctx_init(const char *tls, const char *enc, const char *dec) { AUTO(EVP_PKEY, prv); AUTO(FILE, file); AUTO(ctx, ctx); if (tls == NULL || enc == NULL || dec == NULL) return NULL; ctx = OPENSSL_malloc(sizeof(*ctx)); if (ctx == NULL) return NULL; memset(ctx, 0, sizeof(*ctx)); ctx->ctx = SSL_CTX_new(SSLv23_server_method()); if (ctx->ctx == NULL) return NULL; if (SSL_CTX_use_certificate_chain_file(ctx->ctx, tls) <= 0) return NULL; prv = load_prv(tls); if (prv == NULL) return NULL; if (SSL_CTX_use_PrivateKey(ctx->ctx, prv) <= 0) return NULL; file = fopen(enc, "r"); if (file == NULL) return NULL; ctx->crt = sk_X509_new_null(); if (ctx->crt == NULL) return NULL; if (!deo_load(file, ctx->crt)) return NULL; ctx->dec = load_decryption_certs_keys(dec); if (ctx->dec == NULL) return NULL; /* Check to ensure that the TLS connection key is not also listed * in the decryption keys. This prevents an attack where, upon * misconfiguration, this service could be used to decrypt its own * traffic. */ for (int i = 0; i < sk_X509_INFO_num(ctx->dec); i++) { X509_INFO *info = sk_X509_INFO_value(ctx->dec, i); if (info->x_pkey == NULL) continue; if (EVP_PKEY_cmp(prv, info->x_pkey->dec_pkey) == 1) { fprintf(stderr, "TLS private key is exposed!\n"); return NULL; } } return STEAL(ctx); }