/* * Initialize global SSL context. */ void be_tls_init(void) { struct stat buf; STACK_OF(X509_NAME) *root_cert_list = NULL; if (!SSL_context) { #if SSLEAY_VERSION_NUMBER >= 0x0907000L OPENSSL_config(NULL); #endif SSL_library_init(); SSL_load_error_strings(); /* * We use SSLv23_method() because it can negotiate use of the highest * mutually supported protocol version, while alternatives like * TLSv1_2_method() permit only one specific version. Note that we * don't actually allow SSL v2 or v3, only TLS protocols (see below). */ SSL_context = SSL_CTX_new(SSLv23_method()); if (!SSL_context) ereport(FATAL, (errmsg("could not create SSL context: %s", SSLerrmessage(ERR_get_error())))); /* * Disable OpenSSL's moving-write-buffer sanity check, because it * causes unnecessary failures in nonblocking send cases. */ SSL_CTX_set_mode(SSL_context, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); /* * Load and verify server's certificate and private key */ if (SSL_CTX_use_certificate_chain_file(SSL_context, ssl_cert_file) != 1) ereport(FATAL, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("could not load server certificate file \"%s\": %s", ssl_cert_file, SSLerrmessage(ERR_get_error())))); if (stat(ssl_key_file, &buf) != 0) ereport(FATAL, (errcode_for_file_access(), errmsg("could not access private key file \"%s\": %m", ssl_key_file))); if (!S_ISREG(buf.st_mode)) ereport(FATAL, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("private key file \"%s\" is not a regular file", ssl_key_file))); /* * Refuse to load files owned by users other than us or root. * * XXX surely we can check this on Windows somehow, too. */ #if !defined(WIN32) && !defined(__CYGWIN__) if (buf.st_uid != geteuid() && buf.st_uid != 0) ereport(FATAL, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("private key file \"%s\" must be owned by the database user or root", ssl_key_file))); #endif /* * Require no public access to key file. If the file is owned by us, * require mode 0600 or less. If owned by root, require 0640 or less * to allow read access through our gid, or a supplementary gid that * allows to read system-wide certificates. * * XXX temporarily suppress check when on Windows, because there may * not be proper support for Unix-y file permissions. Need to think * of a reasonable check to apply on Windows. (See also the data * directory permission check in postmaster.c) */ #if !defined(WIN32) && !defined(__CYGWIN__) if ((buf.st_uid == geteuid() && buf.st_mode & (S_IRWXG | S_IRWXO)) || (buf.st_uid == 0 && buf.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO))) ereport(FATAL, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("private key file \"%s\" has group or world access", ssl_key_file), errdetail("File must have permissions u=rw (0600) or less if owned by the database user, or permissions u=rw,g=r (0640) or less if owned by root."))); #endif if (SSL_CTX_use_PrivateKey_file(SSL_context, ssl_key_file, SSL_FILETYPE_PEM) != 1) ereport(FATAL, (errmsg("could not load private key file \"%s\": %s", ssl_key_file, SSLerrmessage(ERR_get_error())))); if (SSL_CTX_check_private_key(SSL_context) != 1) ereport(FATAL, (errmsg("check of private key failed: %s", SSLerrmessage(ERR_get_error())))); } /* set up ephemeral DH keys, and disallow SSL v2/v3 while at it */ SSL_CTX_set_tmp_dh_callback(SSL_context, tmp_dh_cb); SSL_CTX_set_options(SSL_context, SSL_OP_SINGLE_DH_USE | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); /* set up ephemeral ECDH keys */ initialize_ecdh(); /* set up the allowed cipher list */ if (SSL_CTX_set_cipher_list(SSL_context, SSLCipherSuites) != 1) elog(FATAL, "could not set the cipher list (no valid ciphers available)"); /* Let server choose order */ if (SSLPreferServerCiphers) SSL_CTX_set_options(SSL_context, SSL_OP_CIPHER_SERVER_PREFERENCE); /* * Load CA store, so we can verify client certificates if needed. */ if (ssl_ca_file[0]) { if (SSL_CTX_load_verify_locations(SSL_context, ssl_ca_file, NULL) != 1 || (root_cert_list = SSL_load_client_CA_file(ssl_ca_file)) == NULL) ereport(FATAL, (errmsg("could not load root certificate file \"%s\": %s", ssl_ca_file, SSLerrmessage(ERR_get_error())))); } /*---------- * Load the Certificate Revocation List (CRL). * http://searchsecurity.techtarget.com/sDefinition/0,,sid14_gci803160,00.html *---------- */ if (ssl_crl_file[0]) { X509_STORE *cvstore = SSL_CTX_get_cert_store(SSL_context); if (cvstore) { /* Set the flags to check against the complete CRL chain */ if (X509_STORE_load_locations(cvstore, ssl_crl_file, NULL) == 1) { /* OpenSSL 0.96 does not support X509_V_FLAG_CRL_CHECK */ #ifdef X509_V_FLAG_CRL_CHECK X509_STORE_set_flags(cvstore, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); #else ereport(LOG, (errmsg("SSL certificate revocation list file \"%s\" ignored", ssl_crl_file), errdetail("SSL library does not support certificate revocation lists."))); #endif } else ereport(FATAL, (errmsg("could not load SSL certificate revocation list file \"%s\": %s", ssl_crl_file, SSLerrmessage(ERR_get_error())))); } } if (ssl_ca_file[0]) { /* * Always ask for SSL client cert, but don't fail if it's not * presented. We might fail such connections later, depending on what * we find in pg_hba.conf. */ SSL_CTX_set_verify(SSL_context, (SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE), verify_cb); /* Set flag to remember CA store is successfully loaded */ ssl_loaded_verify_locations = true; /* * Tell OpenSSL to send the list of root certs we trust to clients in * CertificateRequests. This lets a client with a keystore select the * appropriate client certificate to send to us. */ SSL_CTX_set_client_CA_list(SSL_context, root_cert_list); } }
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_LINUX_SENDFILE { NETWORK_BACKEND_LINUX_SENDFILE, "linux-sendfile" }, #endif #if defined USE_FREEBSD_SENDFILE { NETWORK_BACKEND_FREEBSD_SENDFILE, "freebsd-sendfile" }, #endif #if defined USE_SOLARIS_SENDFILEV { NETWORK_BACKEND_SOLARIS_SENDFILEV, "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_is_empty(s->ssl_pemfile) && buffer_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_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_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_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))) { 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))) { log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", ERR_error_string(ERR_get_error(), NULL)); return -1; } } if (!buffer_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_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 { /* 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); dh->length = 160; if ((dh->p == NULL) || (dh->g == NULL)) { DH_free(dh); log_error_write(srv, __FILE__, __LINE__, "s", "SSL: BN_bin2bn () failed"); return -1; } } 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_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_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_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_string_buffer(b, srv->srvconf.bindhost); buffer_append_string_len(b, CONST_STR_LEN(":")); buffer_append_long(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_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; #ifdef USE_WRITEV case NETWORK_BACKEND_WRITEV: srv->network_backend_write = network_write_chunkqueue_writev; break; #endif #ifdef USE_LINUX_SENDFILE case NETWORK_BACKEND_LINUX_SENDFILE: srv->network_backend_write = network_write_chunkqueue_linuxsendfile; break; #endif #ifdef USE_FREEBSD_SENDFILE case NETWORK_BACKEND_FREEBSD_SENDFILE: srv->network_backend_write = network_write_chunkqueue_freebsdsendfile; break; #endif #ifdef USE_SOLARIS_SENDFILEV case NETWORK_BACKEND_SOLARIS_SENDFILEV: srv->network_backend_write = network_write_chunkqueue_solarissendfilev; 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; }
/* DTLS-SRTP initialization */ gint janus_dtls_srtp_init(const char* server_pem, const char* server_key) { /* FIXME First of all make OpenSSL thread safe (see note above on issue #316) */ janus_dtls_locks = g_malloc0(sizeof(*janus_dtls_locks) * CRYPTO_num_locks()); int l=0; for(l = 0; l < CRYPTO_num_locks(); l++) { janus_mutex_init(&janus_dtls_locks[l]); } CRYPTO_THREADID_set_callback(janus_dtls_cb_openssl_threadid); CRYPTO_set_locking_callback(janus_dtls_cb_openssl_lock); /* Go on and create the DTLS context */ ssl_ctx = SSL_CTX_new(DTLSv1_method()); if(!ssl_ctx) { JANUS_LOG(LOG_FATAL, "Ops, error creating DTLS context?\n"); return -1; } SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, janus_dtls_verify_callback); SSL_CTX_set_tlsext_use_srtp(ssl_ctx, "SRTP_AES128_CM_SHA1_80"); /* FIXME Should we support something else as well? */ if (!server_pem && !server_key) { JANUS_LOG(LOG_WARN, "No cert/key specified, autogenerating some...\n"); if (janus_dtls_generate_keys(&ssl_cert, &ssl_key) != 0) { JANUS_LOG(LOG_FATAL, "Error generating DTLS key/certificate\n"); return -2; } } else if (!server_pem || !server_key) { JANUS_LOG(LOG_FATAL, "DTLS certificate and key must be specified\n"); return -2; } else if (janus_dtls_load_keys(server_pem, server_key, &ssl_cert, &ssl_key) != 0) { return -3; } if(!SSL_CTX_use_certificate(ssl_ctx, ssl_cert)) { JANUS_LOG(LOG_FATAL, "Certificate error (%s)\n", ERR_reason_error_string(ERR_get_error())); return -4; } if(!SSL_CTX_use_PrivateKey(ssl_ctx, ssl_key)) { JANUS_LOG(LOG_FATAL, "Certificate key error (%s)\n", ERR_reason_error_string(ERR_get_error())); return -5; } if(!SSL_CTX_check_private_key(ssl_ctx)) { JANUS_LOG(LOG_FATAL, "Certificate check error (%s)\n", ERR_reason_error_string(ERR_get_error())); return -6; } SSL_CTX_set_read_ahead(ssl_ctx,1); unsigned int size; unsigned char fingerprint[EVP_MAX_MD_SIZE]; if(X509_digest(ssl_cert, EVP_sha256(), (unsigned char *)fingerprint, &size) == 0) { JANUS_LOG(LOG_FATAL, "Error converting X509 structure (%s)\n", ERR_reason_error_string(ERR_get_error())); return -7; } char *lfp = (char *)&local_fingerprint; unsigned int i = 0; for(i = 0; i < size; i++) { g_snprintf(lfp, 4, "%.2X:", fingerprint[i]); lfp += 3; } *(lfp-1) = 0; JANUS_LOG(LOG_INFO, "Fingerprint of our certificate: %s\n", local_fingerprint); SSL_CTX_set_cipher_list(ssl_ctx, DTLS_CIPHERS); /* Initialize libsrtp */ if(srtp_init() != err_status_ok) { JANUS_LOG(LOG_FATAL, "Ops, error setting up libsrtp?\n"); return 5; } return 0; }
/* * Initialize global SSL context. */ static void initialize_SSL(void) { struct stat buf; STACK_OF(X509_NAME) *root_cert_list = NULL; if (!SSL_context) { #if SSLEAY_VERSION_NUMBER >= 0x0907000L OPENSSL_config(NULL); #endif SSL_library_init(); SSL_load_error_strings(); SSL_context = SSL_CTX_new(SSLv23_method()); if (!SSL_context) ereport(FATAL, (errmsg("could not create SSL context: %s", SSLerrmessage()))); /* * Disable OpenSSL's moving-write-buffer sanity check, because it * causes unnecessary failures in nonblocking send cases. */ SSL_CTX_set_mode(SSL_context, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); /* * Load and verify server's certificate and private key */ if (SSL_CTX_use_certificate_chain_file(SSL_context, ssl_cert_file) != 1) ereport(FATAL, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("could not load server certificate file \"%s\": %s", ssl_cert_file, SSLerrmessage()))); if (stat(ssl_key_file, &buf) != 0) ereport(FATAL, (errcode_for_file_access(), errmsg("could not access private key file \"%s\": %m", ssl_key_file))); /* * Require no public access to key file. * * XXX temporarily suppress check when on Windows, because there may * not be proper support for Unix-y file permissions. Need to think * of a reasonable check to apply on Windows. (See also the data * directory permission check in postmaster.c) */ #if !defined(WIN32) && !defined(__CYGWIN__) if (!S_ISREG(buf.st_mode) || buf.st_mode & (S_IRWXG | S_IRWXO)) ereport(FATAL, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("private key file \"%s\" has group or world access", ssl_key_file), errdetail("Permissions should be u=rw (0600) or less."))); #endif if (SSL_CTX_use_PrivateKey_file(SSL_context, ssl_key_file, SSL_FILETYPE_PEM) != 1) ereport(FATAL, (errmsg("could not load private key file \"%s\": %s", ssl_key_file, SSLerrmessage()))); if (SSL_CTX_check_private_key(SSL_context) != 1) ereport(FATAL, (errmsg("check of private key failed: %s", SSLerrmessage()))); } /* set up ephemeral DH keys, and disallow SSL v2 while at it */ SSL_CTX_set_tmp_dh_callback(SSL_context, tmp_dh_cb); SSL_CTX_set_options(SSL_context, SSL_OP_SINGLE_DH_USE | SSL_OP_NO_SSLv2); /* set up the allowed cipher list */ if (SSL_CTX_set_cipher_list(SSL_context, SSLCipherSuites) != 1) elog(FATAL, "could not set the cipher list (no valid ciphers available)"); /* * Load CA store, so we can verify client certificates if needed. */ if (ssl_ca_file[0]) { if (SSL_CTX_load_verify_locations(SSL_context, ssl_ca_file, NULL) != 1 || (root_cert_list = SSL_load_client_CA_file(ssl_ca_file)) == NULL) ereport(FATAL, (errmsg("could not load root certificate file \"%s\": %s", ssl_ca_file, SSLerrmessage()))); } /*---------- * Load the Certificate Revocation List (CRL). * http://searchsecurity.techtarget.com/sDefinition/0,,sid14_gci803160,00.html *---------- */ if (ssl_crl_file[0]) { X509_STORE *cvstore = SSL_CTX_get_cert_store(SSL_context); if (cvstore) { /* Set the flags to check against the complete CRL chain */ if (X509_STORE_load_locations(cvstore, ssl_crl_file, NULL) == 1) { /* OpenSSL 0.96 does not support X509_V_FLAG_CRL_CHECK */ #ifdef X509_V_FLAG_CRL_CHECK X509_STORE_set_flags(cvstore, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); #else ereport(LOG, (errmsg("SSL certificate revocation list file \"%s\" ignored", ssl_crl_file), errdetail("SSL library does not support certificate revocation lists."))); #endif } else ereport(FATAL, (errmsg("could not load SSL certificate revocation list file \"%s\": %s", ssl_crl_file, SSLerrmessage()))); } } if (ssl_ca_file[0]) { /* * Always ask for SSL client cert, but don't fail if it's not * presented. We might fail such connections later, depending on what * we find in pg_hba.conf. */ SSL_CTX_set_verify(SSL_context, (SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE), verify_cb); /* Set flag to remember CA store is successfully loaded */ ssl_loaded_verify_locations = true; /* * Tell OpenSSL to send the list of root certs we trust to clients in * CertificateRequests. This lets a client with a keystore select the * appropriate client certificate to send to us. */ SSL_CTX_set_client_CA_list(SSL_context, root_cert_list); } }
int main(int argc, char **argv) { int sockfd, new_fd; socklen_t len; struct sockaddr_in my_addr, their_addr; unsigned int myport, lisnum; char buf[MAXBUF + 1]; SSL_CTX *ctx; /* 指定监听端口 */ if (argc > 1 && argv[1]) { myport = atoi(argv[1]); } else { myport = 8888; } /* 最大客户端连接数 */ if (argv[2]) { lisnum = atoi(argv[2]); } else { lisnum = 2; } /* 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); } /* 载入用户的数字证书, 此证书用来发送给客户端。证书里包含有公钥 */ if (SSL_CTX_use_certificate_file(ctx, argv[4], SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stdout); exit(1); } /* 载入用户私钥 */ if (SSL_CTX_use_PrivateKey_file(ctx, argv[5], 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); } /* 开启一个socket 监听 */ 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); /* 设置监听的IP */ if (argv[3]) { my_addr.sin_addr.s_addr = inet_addr(argv[3]); } else { /* 如果用户没有指定监听端口,则默认监听0.0.0.0(任意IP) */ 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); /* 等待客户端连上来 */ 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); } /* 基于ctx 产生一个新的SSL */ ssl = SSL_new(ctx); /* 将连接用户的socket 加入到SSL */ SSL_set_fd(ssl, new_fd); /* 建立SSL 连接 */ if (SSL_accept(ssl) == -1) { perror("accept"); close(new_fd); break; } /* 开始处理每个新连接上的数据收发 */ bzero(buf, MAXBUF + 1); strcpy(buf, "server->client"); /* 发消息给客户端 */ len = SSL_write(ssl, buf, strlen(buf)); if (len <= 0) { printf("消息'%s'发送失败!错误代码是%d,错误信息是'%s'\n", buf, errno, strerror(errno)); goto finish; } else { printf("消息'%s'发送成功,共发送了%d 个字节!\n", buf, len); } bzero(buf, MAXBUF + 1); /* 接收客户端的消息 */ len = SSL_read(ssl, buf, MAXBUF); if (len > 0) { printf("接收消息成功:'%s',共%d 个字节的数据\n", buf, len); } else { printf("消息接收失败!错误代码是%d,错误信息是'%s'\n", errno, strerror(errno)); } /* 处理每个新连接上的数据收发结束 */ finish: /* 关闭SSL 连接 */ SSL_shutdown(ssl); /* 释放SSL */ SSL_free(ssl); /* 关闭socket */ close(new_fd); } /* 关闭监听的socket */ close(sockfd); /* 释放CTX */ SSL_CTX_free(ctx); return 0; }
void main() { int err; int listen_sock; int sock; struct sockaddr_in sa_serv; struct sockaddr_in sa_cli; size_t client_len; char *str; char buffer[4096]; SSL_CTX *ctx; SSL *ssl; SSL_METHOD *meth; X509 *client_cert = NULL; short int s_port = 5555; /* inicializar la librería SSL y registrar los métodos de cifrado soportados */ SSL_library_init(); /* cargar mensajes de error que serán usados */ SSL_load_error_strings(); /* añade soporte para las versión SSL 2 y 3 */ meth = SSLv23_method(); /* crea un nuevo contexto para la utilización de la capa SSL */ ctx = SSL_CTX_new(meth); if (!ctx) { ERR_print_errors_fp(stderr); exit(1); } /* especificar el certificado que utilizará nuestra aplicación */ if (SSL_CTX_use_certificate_file(ctx, RSA_SERVER_CERT, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); exit(1); } /* clave privada de nuestra aplicación */ if (SSL_CTX_use_PrivateKey_file(ctx, RSA_SERVER_KEY, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); exit(1); } /* verifica si la clave esta asociada al certificado */ if (!SSL_CTX_check_private_key(ctx)) { fprintf(stderr,"Hay un problema con el certificado y clave privada del servidor\n"); exit(1); } /* CA utilizado para validar los certificados recibidos por la aplicación */ if (!SSL_CTX_load_verify_locations(ctx, RSA_SERVER_CA_CERT, NULL)) { ERR_print_errors_fp(stderr); exit(1); } /* garantizar que se verifica la autenticidad del otro extremo */ SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,NULL); SSL_CTX_set_verify_depth(ctx,1); listen_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); RETURN_ERR(listen_sock, "socket"); memset (&sa_serv, '\0', sizeof(sa_serv)); sa_serv.sin_family = AF_INET; sa_serv.sin_addr.s_addr = INADDR_ANY; sa_serv.sin_port = htons (s_port); err = bind(listen_sock, (struct sockaddr*)&sa_serv,sizeof(sa_serv)); RETURN_ERR(err, "bind"); err = listen(listen_sock, 5); RETURN_ERR(err, "listen"); client_len = sizeof(sa_cli); sock = accept(listen_sock, (struct sockaddr*)&sa_cli, &client_len); RETURN_ERR(sock, "accept"); close (listen_sock); char clientIpString[INET_ADDRSTRLEN]; int clientIpInt = sa_cli.sin_addr.s_addr; inet_ntop( AF_INET, &clientIpInt, clientIpString, INET_ADDRSTRLEN ); printf ("Conexion con %s en el puerto %x\n", clientIpString, sa_cli.sin_port); /* crear una estructura SSL */ ssl = SSL_new(ctx); RETURN_NULL(ssl); /* asociar la estructura SSL creada al canal de comunicación */ SSL_set_fd(ssl, sock); /* inicializará el handshake con el servidor */ err = SSL_accept(ssl); RETURN_SSL(err); printf("Cifrado elegido: %s\n", SSL_get_cipher (ssl)); /* Certificado del cliente */ client_cert = SSL_get_peer_certificate(ssl); if (client_cert != NULL) { printf ("Certificado del cliente:\n"); str = X509_NAME_oneline(X509_get_subject_name(client_cert), 0, 0); RETURN_NULL(str); printf ("\t subject: %s\n", str); free (str); str = X509_NAME_oneline(X509_get_issuer_name(client_cert), 0, 0); RETURN_NULL(str); printf ("\t issuer: %s\n", str); free (str); X509_free(client_cert); } else printf("El cliente no tiene certificado.\n"); err = SSL_read(ssl, buffer, sizeof(buffer) - 1); RETURN_SSL(err); buffer[err] = '\0'; printf ("Mensaje del cliente: %s\n", buffer); err = SSL_write(ssl, buffer, strlen(buffer)); RETURN_SSL(err); /* cerrar el canal de comunicación */ err = SSL_shutdown(ssl); RETURN_SSL(err); err = close(sock); RETURN_ERR(err, "close"); /* liberar las estructuras creadas de forma dinámica */ SSL_free(ssl); SSL_CTX_free(ctx); }
static int new_ssl_stream(const char *name, int fd, enum session_type type, enum ssl_state state, struct stream **streamp) { struct ssl_stream *sslv; SSL *ssl = NULL; int retval; /* Check for all the needful configuration. */ retval = 0; if (!private_key.read) { VLOG_ERR("Private key must be configured to use SSL"); retval = ENOPROTOOPT; } if (!certificate.read) { VLOG_ERR("Certificate must be configured to use SSL"); retval = ENOPROTOOPT; } if (!ca_cert.read && verify_peer_cert && !bootstrap_ca_cert) { VLOG_ERR("CA certificate must be configured to use SSL"); retval = ENOPROTOOPT; } if (!retval && !SSL_CTX_check_private_key(ctx)) { VLOG_ERR("Private key does not match certificate public key: %s", ERR_error_string(ERR_get_error(), NULL)); retval = ENOPROTOOPT; } if (retval) { goto error; } /* Disable Nagle. * On windows platforms, this can only be called upon TCP connected. */ if (state == STATE_SSL_CONNECTING) { setsockopt_tcp_nodelay(fd); } /* Create and configure OpenSSL stream. */ ssl = SSL_new(ctx); if (ssl == NULL) { VLOG_ERR("SSL_new: %s", ERR_error_string(ERR_get_error(), NULL)); retval = ENOPROTOOPT; goto error; } if (SSL_set_fd(ssl, fd) == 0) { VLOG_ERR("SSL_set_fd: %s", ERR_error_string(ERR_get_error(), NULL)); retval = ENOPROTOOPT; goto error; } if (!verify_peer_cert || (bootstrap_ca_cert && type == CLIENT)) { SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL); } /* Create and return the ssl_stream. */ sslv = xmalloc(sizeof *sslv); stream_init(&sslv->stream, &ssl_stream_class, EAGAIN, name); sslv->state = state; sslv->type = type; sslv->fd = fd; sslv->ssl = ssl; sslv->txbuf = NULL; sslv->rx_want = sslv->tx_want = SSL_NOTHING; sslv->session_nr = next_session_nr++; sslv->n_head = 0; if (VLOG_IS_DBG_ENABLED()) { SSL_set_msg_callback(ssl, ssl_protocol_cb); SSL_set_msg_callback_arg(ssl, sslv); } *streamp = &sslv->stream; return 0; error: if (ssl) { SSL_free(ssl); } closesocket(fd); return retval; }
/* $begin ssl init */ void ssl_init(void) { static char crypto[]="RC4-MD5"; certfile= DEFAULT_CERTFILE; SSL_load_error_strings(); SSLeay_add_ssl_algorithms(); ssl_ctx = SSL_CTX_new( SSLv23_server_method() ); if ( certfile[0] != '\0' ) if ( SSL_CTX_use_certificate_file( ssl_ctx, certfile, SSL_FILETYPE_PEM ) == 0 || SSL_CTX_use_PrivateKey_file( ssl_ctx, certfile, SSL_FILETYPE_PEM ) == 0 || SSL_CTX_check_private_key( ssl_ctx ) == 0 ) { ERR_print_errors_fp( stderr ); exit( 1 ); } if ( crypto != (char*) 0 ) { if ( SSL_CTX_set_cipher_list( ssl_ctx, crypto ) == 0 ) { ERR_print_errors_fp( stderr ); exit( 1 ); } } }
int lws_context_init_client_ssl(struct lws_context_creation_info *info, struct libwebsocket_context *context) { int error; int n; SSL_METHOD *method; if (info->provided_client_ssl_ctx) { /* use the provided OpenSSL context if given one */ context->ssl_client_ctx = info->provided_client_ssl_ctx; /* nothing for lib to delete */ context->user_supplied_ssl_ctx = 1; return 0; } if (info->port != CONTEXT_PORT_NO_LISTEN) return 0; /* basic openssl init */ SSL_library_init(); OpenSSL_add_all_algorithms(); SSL_load_error_strings(); method = (SSL_METHOD *)SSLv23_client_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; } /* create context */ context->ssl_client_ctx = SSL_CTX_new(method); if (!context->ssl_client_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; } #ifdef SSL_OP_NO_COMPRESSION SSL_CTX_set_options(context->ssl_client_ctx, SSL_OP_NO_COMPRESSION); #endif SSL_CTX_set_options(context->ssl_client_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); if (info->ssl_cipher_list) SSL_CTX_set_cipher_list(context->ssl_client_ctx, info->ssl_cipher_list); #ifdef LWS_SSL_CLIENT_USE_OS_CA_CERTS if (!(info->options & LWS_SERVER_OPTION_DISABLE_OS_CA_CERTS)) /* loads OS default CA certs */ SSL_CTX_set_default_verify_paths(context->ssl_client_ctx); #endif /* openssl init for cert verification (for client sockets) */ if (!info->ssl_ca_filepath) { if (!SSL_CTX_load_verify_locations( context->ssl_client_ctx, NULL, LWS_OPENSSL_CLIENT_CERTS)) lwsl_err( "Unable to load SSL Client certs from %s " "(set by --with-client-cert-dir= " "in configure) -- client ssl isn't " "going to work", LWS_OPENSSL_CLIENT_CERTS); } else if (!SSL_CTX_load_verify_locations( context->ssl_client_ctx, info->ssl_ca_filepath, NULL)) lwsl_err( "Unable to load SSL Client certs " "file from %s -- client ssl isn't " "going to work", info->ssl_ca_filepath); else lwsl_info("loaded ssl_ca_filepath\n"); /* * callback allowing user code to load extra verification certs * helping the client to verify server identity */ /* support for client-side certificate authentication */ if (info->ssl_cert_filepath) { n = SSL_CTX_use_certificate_chain_file( context->ssl_client_ctx, info->ssl_cert_filepath); if (n != 1) { lwsl_err("problem getting cert '%s' %lu: %s\n", info->ssl_cert_filepath, ERR_get_error(), ERR_error_string(ERR_get_error(), (char *)context->service_buffer)); return 1; } } if (info->ssl_private_key_filepath) { lws_ssl_bind_passphrase(context->ssl_client_ctx, info); /* set the private key from KeyFile */ if (SSL_CTX_use_PrivateKey_file(context->ssl_client_ctx, info->ssl_private_key_filepath, SSL_FILETYPE_PEM) != 1) { lwsl_err("use_PrivateKey_file '%s' %lu: %s\n", info->ssl_private_key_filepath, ERR_get_error(), ERR_error_string(ERR_get_error(), (char *)context->service_buffer)); return 1; } /* verify private key */ if (!SSL_CTX_check_private_key( context->ssl_client_ctx)) { lwsl_err("Private SSL key doesn't match cert\n"); return 1; } } context->protocols[0].callback(context, NULL, LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS, context->ssl_client_ctx, NULL, 0); return 0; }
int tls_ctx_load_priv_file (struct tls_root_ctx *ctx, const char *priv_key_engine, const char *priv_key_file #if ENABLE_INLINE_FILES , const char *priv_key_file_inline #endif ) { int status; SSL_CTX *ssl_ctx = NULL; BIO *in = NULL; EVP_PKEY *pkey = NULL; int ret = 1; ASSERT(NULL != ctx); ssl_ctx = ctx->ctx; #if ENABLE_INLINE_FILES if (!strcmp (priv_key_file, INLINE_FILE_TAG) && priv_key_file_inline) in = BIO_new_mem_buf ((char *)priv_key_file_inline, -1); else #endif /* ENABLE_INLINE_FILES */ in = BIO_new_file (priv_key_file, "r"); if (!in) goto end; if (priv_key_engine) { ENGINE *engine; ENGINE_load_builtin_engines(); engine = ENGINE_by_id(priv_key_engine); if (!ENGINE_init(engine)) { msg (M_WARN|M_SSL, "Cannot init engine %s", priv_key_engine); goto end; } pkey = ENGINE_load_private_key(engine, priv_key_file, UI_OpenSSL(), NULL); } else { pkey = PEM_read_bio_PrivateKey (in, NULL, ssl_ctx->default_passwd_callback, ssl_ctx->default_passwd_callback_userdata); } if (!pkey) goto end; if (!SSL_CTX_use_PrivateKey (ssl_ctx, pkey)) { #ifdef ENABLE_MANAGEMENT if (management && (ERR_GET_REASON (ERR_peek_error()) == EVP_R_BAD_DECRYPT)) management_auth_failure (management, UP_TYPE_PRIVATE_KEY, NULL); #endif msg (M_WARN|M_SSL, "Cannot load private key file %s", priv_key_file); goto end; } warn_if_group_others_accessible (priv_key_file); /* Check Private Key */ if (!SSL_CTX_check_private_key (ssl_ctx)) msg (M_SSLERR, "Private key does not match the certificate"); ret = 0; end: if (pkey) EVP_PKEY_free (pkey); if (in) BIO_free (in); return ret; }
/* * \brief Initialize OpenSSl of Verse server */ static int vs_init_ssl(VS_CTX *vs_ctx) { /* Set up the library */ SSL_library_init(); ERR_load_BIO_strings(); SSL_load_error_strings(); OpenSSL_add_all_algorithms(); /* Set up SSL context for TLS */ if( (vs_ctx->tls_ctx = SSL_CTX_new(TLSv1_server_method())) == NULL ) { v_print_log(VRS_PRINT_ERROR, "Setting up SSL_CTX failed.\n"); ERR_print_errors_fp(v_log_file()); return -1; } /* Load certificate chain file from CA */ if(vs_ctx->ca_cert_file != NULL) { if(SSL_CTX_use_certificate_chain_file(vs_ctx->tls_ctx, vs_ctx->ca_cert_file) != 1) { v_print_log(VRS_PRINT_ERROR, "TLS: Loading certificate chain file: %s failed.\n", vs_ctx->ca_cert_file); ERR_print_errors_fp(v_log_file()); return -1; } } /* Load certificate with public key for TLS */ if(SSL_CTX_use_certificate_file(vs_ctx->tls_ctx, vs_ctx->public_cert_file, SSL_FILETYPE_PEM) != 1) { v_print_log(VRS_PRINT_ERROR, "TLS: Loading certificate file: %s failed.\n", vs_ctx->public_cert_file); ERR_print_errors_fp(v_log_file()); return -1; } /* Load private key for TLS */ if(SSL_CTX_use_PrivateKey_file(vs_ctx->tls_ctx, vs_ctx->private_cert_file, SSL_FILETYPE_PEM) != 1) { v_print_log(VRS_PRINT_ERROR, "TLS: Loading private key file: %s failed.\n", vs_ctx->private_cert_file); ERR_print_errors_fp(v_log_file()); return -1; } /* Check the consistency of a private key with the corresponding * certificate loaded into ssl_ctx */ if(SSL_CTX_check_private_key(vs_ctx->tls_ctx) != 1) { v_print_log(VRS_PRINT_ERROR, "TLS: Private key does not match the certificate public key\n"); ERR_print_errors_fp(v_log_file()); return -1; } /* When CA certificate file was set, then try to load it */ if(vs_ctx->ca_cert_file != NULL) { if(SSL_CTX_load_verify_locations(vs_ctx->tls_ctx, vs_ctx->ca_cert_file, NULL) != 1) { v_print_log(VRS_PRINT_ERROR, "TLS: Loading CA certificate file: %s failed.\n", vs_ctx->ca_cert_file); ERR_print_errors_fp(v_log_file()); return -1; } } #if OPENSSL_VERSION_NUMBER>=0x10000000 /* Set up SSL context for DTLS */ if( (vs_ctx->dtls_ctx = SSL_CTX_new(DTLSv1_server_method())) == NULL ) { v_print_log(VRS_PRINT_ERROR, "Setting up SSL_CTX failed.\n"); ERR_print_errors_fp(v_log_file()); return -1; } /* Load certificate chain file from CA */ if(vs_ctx->ca_cert_file != NULL) { if(SSL_CTX_use_certificate_chain_file(vs_ctx->dtls_ctx, vs_ctx->ca_cert_file) != 1) { v_print_log(VRS_PRINT_ERROR, "DTLS: Loading certificate chain file: %s failed.\n", vs_ctx->ca_cert_file); ERR_print_errors_fp(v_log_file()); return -1; } } /* Load certificate with public key for DTLS */ if (SSL_CTX_use_certificate_file(vs_ctx->dtls_ctx, vs_ctx->public_cert_file, SSL_FILETYPE_PEM) != 1) { v_print_log(VRS_PRINT_ERROR, "DTLS: Loading certificate file: %s failed.\n", vs_ctx->public_cert_file); ERR_print_errors_fp(v_log_file()); return -1; } /* Load private key for DTLS */ if(SSL_CTX_use_PrivateKey_file(vs_ctx->dtls_ctx, vs_ctx->private_cert_file, SSL_FILETYPE_PEM) != 1) { v_print_log(VRS_PRINT_ERROR, "DTLS: Loading private key file: %s failed.\n", vs_ctx->private_cert_file); ERR_print_errors_fp(v_log_file()); return -1; } /* Check the consistency of a private key with the corresponding * certificate loaded into ssl_ctx */ if(SSL_CTX_check_private_key(vs_ctx->dtls_ctx) != 1) { v_print_log(VRS_PRINT_ERROR, "DTLS: Private key does not match the certificate public key\n"); ERR_print_errors_fp(v_log_file()); return -1; } /* When CA certificate file was set, then try to load it */ if(vs_ctx->ca_cert_file != NULL) { if(SSL_CTX_load_verify_locations(vs_ctx->dtls_ctx, vs_ctx->ca_cert_file, NULL) != 1) { v_print_log(VRS_PRINT_ERROR, "DTLS: Loading CA certificate file: %s failed.\n", vs_ctx->ca_cert_file); ERR_print_errors_fp(v_log_file()); return -1; } } /* Set up callback functions for DTLS cookie */ SSL_CTX_set_cookie_generate_cb(vs_ctx->dtls_ctx, vs_dtls_generate_cookie); SSL_CTX_set_cookie_verify_cb(vs_ctx->dtls_ctx, vs_dtls_verify_cookie); /* Accept all cipher including NULL cipher (testing) */ if( SSL_CTX_set_cipher_list(vs_ctx->dtls_ctx, "ALL:NULL:eNULL:aNULL") == 0) { v_print_log(VRS_PRINT_ERROR, "Setting ciphers for DTLS failed.\n"); ERR_print_errors_fp(v_log_file()); return 0; } /* DTLS require this */ SSL_CTX_set_read_ahead(vs_ctx->dtls_ctx, 1); #else vs_ctx->dtls_ctx = NULL; #endif return 1; }
int tls_ctx_load_pkcs12(struct tls_root_ctx *ctx, const char *pkcs12_file, #if ENABLE_INLINE_FILES const char *pkcs12_file_inline, #endif /* ENABLE_INLINE_FILES */ bool load_ca_file ) { FILE *fp; EVP_PKEY *pkey; X509 *cert; STACK_OF(X509) *ca = NULL; PKCS12 *p12; int i; char password[256]; ASSERT(NULL != ctx); #if ENABLE_INLINE_FILES if (!strcmp (pkcs12_file, INLINE_FILE_TAG) && pkcs12_file_inline) { BIO *b64 = BIO_new(BIO_f_base64()); BIO *bio = BIO_new_mem_buf((void *) pkcs12_file_inline, (int) strlen(pkcs12_file_inline)); ASSERT(b64 && bio); BIO_push(b64, bio); p12 = d2i_PKCS12_bio(b64, NULL); if (!p12) msg(M_SSLERR, "Error reading inline PKCS#12 file"); BIO_free(b64); BIO_free(bio); } else #endif { /* Load the PKCS #12 file */ if (!(fp = platform_fopen(pkcs12_file, "rb"))) msg(M_SSLERR, "Error opening file %s", pkcs12_file); p12 = d2i_PKCS12_fp(fp, NULL); fclose(fp); if (!p12) msg(M_SSLERR, "Error reading PKCS#12 file %s", pkcs12_file); } /* Parse the PKCS #12 file */ if (!PKCS12_parse(p12, "", &pkey, &cert, &ca)) { pem_password_callback (password, sizeof(password) - 1, 0, NULL); /* Reparse the PKCS #12 file with password */ ca = NULL; if (!PKCS12_parse(p12, password, &pkey, &cert, &ca)) { #ifdef ENABLE_MANAGEMENT if (management && (ERR_GET_REASON (ERR_peek_error()) == PKCS12_R_MAC_VERIFY_FAILURE)) management_auth_failure (management, UP_TYPE_PRIVATE_KEY, NULL); #endif PKCS12_free(p12); return 1; } } PKCS12_free(p12); /* Load Certificate */ if (!SSL_CTX_use_certificate (ctx->ctx, cert)) msg (M_SSLERR, "Cannot use certificate"); /* Load Private Key */ if (!SSL_CTX_use_PrivateKey (ctx->ctx, pkey)) msg (M_SSLERR, "Cannot use private key"); warn_if_group_others_accessible (pkcs12_file); /* Check Private Key */ if (!SSL_CTX_check_private_key (ctx->ctx)) msg (M_SSLERR, "Private key does not match the certificate"); /* Set Certificate Verification chain */ if (load_ca_file) { if (ca && sk_X509_num(ca)) { for (i = 0; i < sk_X509_num(ca); i++) { if (!X509_STORE_add_cert(ctx->ctx->cert_store,sk_X509_value(ca, i))) msg (M_SSLERR, "Cannot add certificate to certificate chain (X509_STORE_add_cert)"); if (!SSL_CTX_add_client_CA(ctx->ctx, sk_X509_value(ca, i))) msg (M_SSLERR, "Cannot add certificate to client CA list (SSL_CTX_add_client_CA)"); } } } return 0; }
static int check_key(lua_State *L) { SSL_CTX *ctx = lsec_checkcontext(L, 1); lua_pushboolean(L, SSL_CTX_check_private_key(ctx)); return 1; }
SSL_CTX* swSSL_get_context(int method, char *cert_file, char *key_file) { if (!openssl_init) { swSSL_init(); } SSL_CTX *ssl_context = SSL_CTX_new(swSSL_get_method(method)); if (ssl_context == NULL) { ERR_print_errors_fp(stderr); return NULL; } SSL_CTX_set_options(ssl_context, SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG); SSL_CTX_set_options(ssl_context, SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER); SSL_CTX_set_options(ssl_context, SSL_OP_MSIE_SSLV2_RSA_PADDING); SSL_CTX_set_options(ssl_context, SSL_OP_SSLEAY_080_CLIENT_DH_BUG); SSL_CTX_set_options(ssl_context, SSL_OP_TLS_D5_BUG); SSL_CTX_set_options(ssl_context, SSL_OP_TLS_BLOCK_PADDING_BUG); SSL_CTX_set_options(ssl_context, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); SSL_CTX_set_options(ssl_context, SSL_OP_SINGLE_DH_USE); if (cert_file) { /* * set the local certificate from CertFile */ if (SSL_CTX_use_certificate_file(ssl_context, cert_file, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); return NULL; } /* * if the crt file have many certificate entry ,means certificate chain * we need call this function */ if (SSL_CTX_use_certificate_chain_file(ssl_context, cert_file) <= 0) { ERR_print_errors_fp(stderr); return NULL; } /* * set the private key from KeyFile (may be the same as CertFile) */ if (SSL_CTX_use_PrivateKey_file(ssl_context, key_file, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); return NULL; } /* * verify private key */ if (!SSL_CTX_check_private_key(ssl_context)) { swWarn("Private key does not match the public certificate"); return NULL; } } return ssl_context; }
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; } 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_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>\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_verb(0, "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_verb(0, "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_verb(0, "SSL CA file(%s)/path(%s) error\n", cfg->cafile, cfg->capath); } } ast_verb(0, "SSL certificate ok\n"); return 1; #endif }
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_WOLFSSL #ifdef USE_OLD_CYASSL lwsl_notice(" Compiled with CyaSSL support\n"); #else lwsl_notice(" Compiled with wolfSSL support\n"); #endif #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) { int verify_options = SSL_VERIFY_PEER; if (!(info->options & LWS_SERVER_OPTION_PEER_CERT_NOT_REQUIRED)) verify_options |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; SSL_CTX_set_session_id_context(context->ssl_ctx, (unsigned char *)context, sizeof(void *)); /* absolutely require the client cert */ SSL_CTX_set_verify(context->ssl_ctx, verify_options, 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; }
/** Create a new TLS context for use with Tor TLS handshakes. * <b>identity</b> should be set to the identity key used to sign the * certificate, and <b>nickname</b> set to the nickname to use. * * You can call this function multiple times. Each time you call it, * it generates new certificates; all new connections will use * the new SSL context. */ int tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime) { crypto_pk_env_t *rsa = NULL; EVP_PKEY *pkey = NULL; tor_tls_context_t *result = NULL; X509 *cert = NULL, *idcert = NULL; char *nickname = NULL, *nn2 = NULL; tor_tls_init(); nickname = crypto_random_hostname(8, 20, "www.", ".net"); nn2 = crypto_random_hostname(8, 20, "www.", ".net"); /* Generate short-term RSA key. */ if (!(rsa = crypto_new_pk_env())) goto error; if (crypto_pk_generate_key(rsa)<0) goto error; /* Create certificate signed by identity key. */ cert = tor_tls_create_certificate(rsa, identity, nickname, nn2, key_lifetime); /* Create self-signed certificate for identity key. */ idcert = tor_tls_create_certificate(identity, identity, nn2, nn2, IDENTITY_CERT_LIFETIME); if (!cert || !idcert) { log(LOG_WARN, LD_CRYPTO, "Error creating certificate"); goto error; } result = tor_malloc_zero(sizeof(tor_tls_context_t)); result->refcnt = 1; result->my_cert = X509_dup(cert); result->my_id_cert = X509_dup(idcert); result->key = crypto_pk_dup_key(rsa); #ifdef EVERYONE_HAS_AES /* Tell OpenSSL to only use TLS1 */ if (!(result->ctx = SSL_CTX_new(TLSv1_method()))) goto error; #else /* Tell OpenSSL to use SSL3 or TLS1 but not SSL2. */ if (!(result->ctx = SSL_CTX_new(SSLv23_method()))) goto error; SSL_CTX_set_options(result->ctx, SSL_OP_NO_SSLv2); #endif SSL_CTX_set_options(result->ctx, SSL_OP_SINGLE_DH_USE); #ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION SSL_CTX_set_options(result->ctx, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); #endif /* Don't actually allow compression; it uses ram and time, but the data * we transmit is all encrypted anyway. */ if (result->ctx->comp_methods) result->ctx->comp_methods = NULL; #ifdef SSL_MODE_RELEASE_BUFFERS SSL_CTX_set_mode(result->ctx, SSL_MODE_RELEASE_BUFFERS); #endif if (cert && !SSL_CTX_use_certificate(result->ctx,cert)) goto error; X509_free(cert); /* We just added a reference to cert. */ cert=NULL; if (idcert) { X509_STORE *s = SSL_CTX_get_cert_store(result->ctx); tor_assert(s); X509_STORE_add_cert(s, idcert); X509_free(idcert); /* The context now owns the reference to idcert */ idcert = NULL; } SSL_CTX_set_session_cache_mode(result->ctx, SSL_SESS_CACHE_OFF); tor_assert(rsa); if (!(pkey = _crypto_pk_env_get_evp_pkey(rsa,1))) goto error; if (!SSL_CTX_use_PrivateKey(result->ctx, pkey)) goto error; EVP_PKEY_free(pkey); pkey = NULL; if (!SSL_CTX_check_private_key(result->ctx)) goto error; { crypto_dh_env_t *dh = crypto_dh_new(); SSL_CTX_set_tmp_dh(result->ctx, _crypto_dh_env_get_dh(dh)); crypto_dh_free(dh); } SSL_CTX_set_verify(result->ctx, SSL_VERIFY_PEER, always_accept_verify_cb); /* let us realloc bufs that we're writing from */ SSL_CTX_set_mode(result->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); /* Free the old context if one exists. */ if (global_tls_context) { /* This is safe even if there are open connections: OpenSSL does * reference counting with SSL and SSL_CTX objects. */ tor_tls_context_decref(global_tls_context); } global_tls_context = result; if (rsa) crypto_free_pk_env(rsa); tor_free(nickname); tor_free(nn2); return 0; error: tls_log_errors(NULL, LOG_WARN, "creating TLS context"); tor_free(nickname); tor_free(nn2); if (pkey) EVP_PKEY_free(pkey); if (rsa) crypto_free_pk_env(rsa); if (result) tor_tls_context_decref(result); if (cert) X509_free(cert); if (idcert) X509_free(idcert); return -1; }
/* * This function initialize one web_server handler */ int web_server_init(struct web_server *server,int port,const char *logfile,int flags) { #ifdef WIN32 unsigned long t=IOC_INOUT; WSADATA WSAinfo; WSAStartup(2,&WSAinfo); // Damn w32 sockets #endif current_web_server=server; server->port=port; server->conffile=NULL; server->mimefile=NULL; server->weblog=NULL; server->usessl=0; server->flags=flags; server->dataconf=""; if((flags & WS_USEEXTCONF) == WS_USEEXTCONF) { if(!(web_server_setup(server,logfile))) { #ifdef WIN32 WSACleanup(); #endif return 0; }; _logfile=server->weblog; // Set current log stream web_log("%s using config file %s\n",_libwebserver_version,logfile); }; // Create a listen socket port 'port' and listen addr (0) (all interfaces) server->socket=__ILWS_listensocket((short)server->port,0); if(server->socket==-1) { LWSERR(LE_NET); #ifdef WIN32 WSACleanup(); #endif return 0; }; #ifdef WIN32 ioctlsocket(server->socket,FIONBIO,&t); //non blocking sockets for win32 #else fcntl(server->socket,F_SETFL,O_NONBLOCK); #endif // Setup FILE structure of logfile if(logfile!=NULL && !((flags & WS_USEEXTCONF) == WS_USEEXTCONF)) { server->logfile=__ILWS_malloc(strlen(logfile)+1); memcpy(server->logfile,logfile,strlen(logfile)); server->logfile[strlen(logfile)]=0; server->weblog=open_weblog(logfile); // Create File stream for log }; web_log("\n[%s] Server started at port %d (%s)\n",__ILWS_date(time(NULL),"%d/%b/%Y:%H:%M:%S %z"),server->port,_libwebserver_version); // Setup Flags // openssl #ifdef HAVE_OPENSSL if((server->flags & WS_USESSL) == WS_USESSL) { web_log("[%s] (FLAG) Using SSL in connections\n",__ILWS_date(time(NULL),"%d/%b/%Y:%H:%M:%S %z")); web_log(" +-- %s certificate file\n",server->cert_file); SSL_load_error_strings(); SSLeay_add_ssl_algorithms(); server->ctx=SSL_CTX_new (SSLv23_server_method()); if (SSL_CTX_use_certificate_file(server->ctx, server->cert_file, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); exit(3); } if (SSL_CTX_use_PrivateKey_file(server->ctx, server->cert_file, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); exit(4); } if (SSL_CTX_check_private_key(server->ctx)<= 0) { ERR_print_errors_fp(stderr); exit(4); }; server->usessl=1; }; #endif if((server->flags & WS_LOCAL) == WS_LOCAL) { web_log("[%s] (FLAG) Accepting only local connections\n",__ILWS_date(time(NULL),"%d/%b/%Y:%H:%M:%S %z")); }; server->client=__ILWS_init_client_list(); // Initializate client list server->gethandler=__ILWS_init_handler_list(); // Initializate handlers list web_server_addhandler(server,"* /libwebserver.gif",_web_server_logo,0,NULL); // Add logo default handler #ifndef WIN32 signal(SIGPIPE,SIG_IGN); #endif return 1; }
void initAuthenticated ( std::string key_file, std::string cert_file, std::string chain_file) { initCommon (); SSL_CTX* const ssl = m_context.native_handle (); bool cert_set = false; if (! cert_file.empty ()) { boost::system::error_code error; m_context.use_certificate_file ( cert_file, boost::asio::ssl::context::pem, error); if (error) { beast::FatalError ("Problem with SSL certificate file.", __FILE__, __LINE__); } cert_set = true; } if (! chain_file.empty ()) { // VFALCO Replace fopen() with RAII FILE* f = fopen (chain_file.c_str (), "r"); if (!f) { beast::FatalError ("Problem opening SSL chain file.", __FILE__, __LINE__); } try { for (;;) { X509* const x = PEM_read_X509 (f, NULL, NULL, NULL); if (x == nullptr) break; if (! cert_set) { if (SSL_CTX_use_certificate (ssl, x) != 1) beast::FatalError ("Problem retrieving SSL certificate from chain file.", __FILE__, __LINE__); cert_set = true; } else if (SSL_CTX_add_extra_chain_cert (ssl, x) != 1) { X509_free (x); beast::FatalError ("Problem adding SSL chain certificate.", __FILE__, __LINE__); } } fclose (f); } catch (...) { fclose (f); beast::FatalError ("Reading the SSL chain file generated an exception.", __FILE__, __LINE__); } } if (! key_file.empty ()) { boost::system::error_code error; m_context.use_private_key_file (key_file, boost::asio::ssl::context::pem, error); if (error) { beast::FatalError ("Problem using the SSL private key file.", __FILE__, __LINE__); } } if (SSL_CTX_check_private_key (ssl) != 1) { beast::FatalError ("Invalid key in SSL private key file.", __FILE__, __LINE__); } }
SSL_CTX * sslctx_client_setup(const SSL_METHOD *method, _netsnmpTLSBaseData *tlsbase) { netsnmp_cert *id_cert, *peer_cert; SSL_CTX *the_ctx; /*********************************************************************** * Set up the client context */ the_ctx = SSL_CTX_new(NETSNMP_REMOVE_CONST(SSL_METHOD *, method)); if (!the_ctx) { snmp_log(LOG_ERR, "ack: %p\n", the_ctx); LOGANDDIE("can't create a new context"); } SSL_CTX_set_read_ahead (the_ctx, 1); /* Required for DTLS */ SSL_CTX_set_verify(the_ctx, SSL_VERIFY_PEER| SSL_VERIFY_FAIL_IF_NO_PEER_CERT| SSL_VERIFY_CLIENT_ONCE, &verify_callback); if (tlsbase->our_identity) { DEBUGMSGTL(("sslctx_client", "looking for local id: %s\n", tlsbase->our_identity)); id_cert = netsnmp_cert_find(NS_CERT_IDENTITY, NS_CERTKEY_MULTIPLE, tlsbase->our_identity); } else { DEBUGMSGTL(("sslctx_client", "looking for default local id: %s\n", tlsbase->our_identity)); id_cert = netsnmp_cert_find(NS_CERT_IDENTITY, NS_CERTKEY_DEFAULT, NULL); } if (!id_cert) LOGANDDIE ("error finding client identity keys"); if (!id_cert->key || !id_cert->key->okey) LOGANDDIE("failed to load private key"); DEBUGMSGTL(("sslctx_client", "using public key: %s\n", id_cert->info.filename)); DEBUGMSGTL(("sslctx_client", "using private key: %s\n", id_cert->key->info.filename)); if (SSL_CTX_use_certificate(the_ctx, id_cert->ocert) <= 0) LOGANDDIE("failed to set the certificate to use"); if (SSL_CTX_use_PrivateKey(the_ctx, id_cert->key->okey) <= 0) LOGANDDIE("failed to set the private key to use"); if (!SSL_CTX_check_private_key(the_ctx)) LOGANDDIE("public and private keys incompatible"); if (tlsbase->their_identity) peer_cert = netsnmp_cert_find(NS_CERT_REMOTE_PEER, NS_CERTKEY_MULTIPLE, tlsbase->their_identity); else peer_cert = netsnmp_cert_find(NS_CERT_REMOTE_PEER, NS_CERTKEY_DEFAULT, NULL); if (peer_cert) { DEBUGMSGTL(("sslctx_client", "server's expected public key: %s\n", peer_cert ? peer_cert->info.filename : "none")); /* Trust the expected certificate */ if (netsnmp_cert_trust_ca(the_ctx, peer_cert) != SNMPERR_SUCCESS) LOGANDDIE ("failed to set verify paths"); } /* trust a certificate (possibly a CA) aspecifically passed in */ if (tlsbase->trust_cert) { if (!_trust_this_cert(the_ctx, tlsbase->trust_cert)) return 0; } return _sslctx_common_setup(the_ctx, tlsbase); }
void main () { int err; int listen_sd; int sd; struct sockaddr_in sa_serv; struct sockaddr_in sa_cli; size_t client_len; SSL_CTX* ctx; SSL* ssl; X509* client_cert; char* str; char buf [4096]; SSL_METHOD *meth; /* SSL preliminaries. We keep the certificate and key with the context. */ SSL_load_error_strings(); SSLeay_add_ssl_algorithms(); meth = SSLv23_server_method(); ctx = SSL_CTX_new (meth); if (!ctx) { ERR_print_errors_fp(stderr); exit(2); } if (SSL_CTX_use_certificate_file(ctx, CERTF, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); exit(3); } if (SSL_CTX_use_PrivateKey_file(ctx, KEYF, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); exit(4); } if (!SSL_CTX_check_private_key(ctx)) { fprintf(stderr,"Private key does not match the certificate public key\n"); exit(5); } /* ----------------------------------------------- */ /* Prepare TCP socket for receiving connections */ listen_sd = socket (AF_INET, SOCK_STREAM, 0); CHK_ERR(listen_sd, "socket"); memset (&sa_serv, '\0', sizeof(sa_serv)); sa_serv.sin_family = AF_INET; sa_serv.sin_addr.s_addr = INADDR_ANY; sa_serv.sin_port = htons (1111); /* Server Port number */ err = bind(listen_sd, (struct sockaddr*) &sa_serv, sizeof (sa_serv)); CHK_ERR(err, "bind"); /* Receive a TCP connection. */ err = listen (listen_sd, 5); CHK_ERR(err, "listen"); client_len = sizeof(sa_cli); sd = accept (listen_sd, (struct sockaddr*) &sa_cli, &client_len); CHK_ERR(sd, "accept"); close (listen_sd); printf ("Connection from %lx, port %x\n", sa_cli.sin_addr.s_addr, sa_cli.sin_port); /* ----------------------------------------------- */ /* TCP connection is ready. Do server side SSL. */ ssl = SSL_new (ctx); CHK_NULL(ssl); SSL_set_fd (ssl, sd); err = SSL_accept (ssl); CHK_SSL(err); /* Get the cipher - opt */ printf ("SSL connection using %s\n", SSL_get_cipher (ssl)); /* Get client's certificate (note: beware of dynamic allocation) - opt */ client_cert = SSL_get_peer_certificate (ssl); if (client_cert != NULL) { printf ("Client certificate:\n"); str = X509_NAME_oneline (X509_get_subject_name (client_cert), 0, 0); CHK_NULL(str); printf ("\t subject: %s\n", str); OPENSSL_free (str); str = X509_NAME_oneline (X509_get_issuer_name (client_cert), 0, 0); CHK_NULL(str); printf ("\t issuer: %s\n", str); OPENSSL_free (str); /* We could do all sorts of certificate verification stuff here before deallocating the certificate. */ X509_free (client_cert); } else printf ("Client does not have certificate.\n"); /* DATA EXCHANGE - Receive message and send reply. */ err = SSL_read (ssl, buf, sizeof(buf) - 1); CHK_SSL(err); buf[err] = '\0'; printf ("Got %d chars:'%s'\n", err, buf); err = SSL_write (ssl, "I hear you.", strlen("I hear you.")); CHK_SSL(err); /* Clean up. */ close (sd); SSL_free (ssl); SSL_CTX_free (ctx); }
void libwebsock_bind_ssl_real(libwebsock_context *ctx, char *listen_host, char *port, char *keyfile, char *certfile, char *chainfile) { struct addrinfo hints, *servinfo, *p; struct event *listener_event; libwebsock_ssl_event_data *evdata; int sockfd, yes = 1; SSL_CTX *ssl_ctx; evdata = (libwebsock_ssl_event_data *) lws_calloc(sizeof(libwebsock_ssl_event_data)); if (!ctx->ssl_init) { SSL_library_init(); SSL_load_error_strings(); OpenSSL_add_all_algorithms(); ctx->ssl_init = 1; } ssl_ctx = SSL_CTX_new(SSLv23_server_method()); if (!ssl_ctx) { ERR_print_errors_fp(stderr); exit(1); } if (chainfile != NULL) { if (SSL_CTX_load_verify_locations(ssl_ctx, chainfile, NULL) <= 0) { ERR_print_errors_fp(stderr); exit(1); } } if (SSL_CTX_use_certificate_file(ssl_ctx, certfile, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); exit(1); } if (SSL_CTX_use_PrivateKey_file(ssl_ctx, keyfile, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); exit(1); } if (!SSL_CTX_check_private_key(ssl_ctx)) { fprintf(stderr, "Private key does not match the certificate public key.\n"); exit(1); } memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; if ((getaddrinfo(listen_host, port, &hints, &servinfo)) != 0) { fprintf(stderr, "getaddrinfo failed during libwebsock_bind.\n"); lws_free(ctx); exit(-1); } for (p = servinfo; p != NULL; p = p->ai_next) { if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { perror("socket"); continue; } if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { perror("setsockopt"); lws_free(ctx); exit(-1); } if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) { perror("bind"); close(sockfd); continue; } break; } if (p == NULL) { fprintf(stderr, "Failed to bind to address and port. Exiting.\n"); lws_free(ctx); exit(-1); } freeaddrinfo(servinfo); if (listen(sockfd, LISTEN_BACKLOG) == -1) { perror("listen"); exit(-1); } evdata->ssl_ctx = ssl_ctx; evdata->ctx = ctx; listener_event = event_new(ctx->base, sockfd, EV_READ | EV_PERSIST, libwebsock_handle_accept_ssl, (void *) evdata); event_add(listener_event, NULL); }
extern "C" int32_t CryptoNative_SslCtxCheckPrivateKey(SSL_CTX* ctx) { return SSL_CTX_check_private_key(ctx); }
int main(int argc, char *argv[]) { char *port = NULL; BIO *in = NULL; BIO *ssl_bio, *tmp; SSL_CTX *ctx; char buf[512]; int ret = 1, i; if (argc <= 1) port = "*:4433"; else port = argv[1]; ctx = SSL_CTX_new(TLS_server_method()); if (!SSL_CTX_use_certificate_chain_file(ctx, CERT_FILE)) goto err; if (!SSL_CTX_use_PrivateKey_file(ctx, CERT_FILE, SSL_FILETYPE_PEM)) goto err; if (!SSL_CTX_check_private_key(ctx)) 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); /* Arrange to leave server loop on interrupt */ sigsetup(); 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; while (!done) { 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) goto err; fwrite(buf, 1, i, stdout); fflush(stdout); } ret = 0; err: if (ret) { ERR_print_errors_fp(stderr); } BIO_free(in); exit(ret); return (!ret); }
static SSL_CTX *tlscreatectx(uint8_t type, struct tls *conf) { SSL_CTX *ctx = NULL; unsigned long error; switch (type) { #ifdef RADPROT_TLS case RAD_TLS: ctx = SSL_CTX_new(TLSv1_method()); break; #endif #ifdef RADPROT_DTLS case RAD_DTLS: ctx = SSL_CTX_new(DTLSv1_method()); SSL_CTX_set_read_ahead(ctx, 1); break; #endif } if (!ctx) { debug(DBG_ERR, "tlscreatectx: Error initialising SSL/TLS in TLS context %s", conf->name); while ((error = ERR_get_error())) debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL)); return NULL; } #ifdef DEBUG SSL_CTX_set_info_callback(ctx, ssl_info_callback); #endif if (conf->certkeypwd) { SSL_CTX_set_default_passwd_cb_userdata(ctx, conf->certkeypwd); SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_cb); } if (conf->certfile || conf->certkeyfile) { if (!SSL_CTX_use_certificate_chain_file(ctx, conf->certfile) || !SSL_CTX_use_PrivateKey_file(ctx, conf->certkeyfile, SSL_FILETYPE_PEM) || !SSL_CTX_check_private_key(ctx)) { while ((error = ERR_get_error())) debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL)); debug(DBG_ERR, "tlscreatectx: Error initialising SSL/TLS (certfile issues) in TLS context %s", conf->name); SSL_CTX_free(ctx); return NULL; } } if (conf->policyoids) { if (!conf->vpm) { conf->vpm = createverifyparams(conf->policyoids); if (!conf->vpm) { debug(DBG_ERR, "tlscreatectx: Failed to add policyOIDs in TLS context %s", conf->name); SSL_CTX_free(ctx); return NULL; } } } if (conf->cacertfile != NULL || conf->cacertpath != NULL) if (!tlsaddcacrl(ctx, conf)) { if (conf->vpm) { X509_VERIFY_PARAM_free(conf->vpm); conf->vpm = NULL; } SSL_CTX_free(ctx); return NULL; } debug(DBG_DBG, "tlscreatectx: created TLS context %s", conf->name); return ctx; }
SSL_Connection *ssl_connect(const char *host, int port, const char *certfile, const char *keyfile, const char *capath) { int err; SSL_Connection *sslcon = NULL; sslcon = (SSL_Connection *)malloc(sizeof(SSL_Connection)); if(sslcon == NULL) { printf("Could not allocate memory for SSL Connection"); exit(1); } /* Load encryption & hashing algorithms for the SSL program */ SSL_library_init(); /* Load the error strings for SSL & CRYPTO APIs */ SSL_load_error_strings(); /* Create an SSL_METHOD structure (choose an SSL/TLS protocol version) */ sslcon->meth = SSLv3_method(); /* Create an SSL_CTX structure */ sslcon->ctx = SSL_CTX_new(sslcon->meth); if(!sslcon->ctx) { syslog (LOG_NOTICE,"Could not get SSL Context\n"); exit(1); } /* Load the CA from the Path */ if(SSL_CTX_load_verify_locations(sslcon->ctx,NULL, "./Certs") <= 0) { /* Handle failed load here */ syslog (LOG_NOTICE,"ERR Failed to set CA location...\n"); ERR_print_errors_fp(stderr); exit(1); } /* Load the client certificate into the SSL_CTX structure */ if (SSL_CTX_use_certificate_file(sslcon->ctx, certfile, SSL_FILETYPE_PEM) <= 0) { syslog (LOG_NOTICE,"ERR Cannot use Certificate File %s \n", certfile); ERR_print_errors_fp(stderr); exit(1); } /* Load the private-key corresponding to the client certificate */ if (SSL_CTX_use_PrivateKey_file(sslcon->ctx, keyfile, SSL_FILETYPE_PEM) <= 0) { syslog (LOG_NOTICE,"ERR Cannot use Private Key %s\n", keyfile); ERR_print_errors_fp(stderr); exit(1); } /* Check if the client certificate and private-key matches */ if (!SSL_CTX_check_private_key(sslcon->ctx)) { syslog (LOG_NOTICE, "ERR Private key does not match the certificate public key\n"); exit(1); } /* Set up a TCP socket */ sslcon->sock = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); if(sslcon->sock == -1) { syslog (LOG_NOTICE, "ERR Could not get Socket\n"); exit(1); } memset (&sslcon->server_addr, '\0', sizeof(sslcon->server_addr)); sslcon->server_addr.sin_family = AF_INET; sslcon->server_addr.sin_port = htons(port); /* Server Port number */ sslcon->host_info = gethostbyname(host); if(sslcon->host_info) { /* Take the first IP */ struct in_addr *address = (struct in_addr*)sslcon->host_info->h_addr_list[0]; sslcon->server_addr.sin_addr.s_addr = inet_addr(inet_ntoa(*address)); /* Server IP */ } else { syslog (LOG_NOTICE, "Could not resolve hostname %s\n", host); return NULL; } /* Establish a TCP/IP connection to the SSL client */ err = connect(sslcon->sock, (struct sockaddr*) &sslcon->server_addr, sizeof(sslcon->server_addr)); if(err == -1) { syslog (LOG_NOTICE, "ERR Could not connect\n"); exit(1); } /* An SSL structure is created */ sslcon->ssl = SSL_new(sslcon->ctx); if(!sslcon->ssl) { syslog (LOG_NOTICE, "ERR Could not get SSL Socket\n"); exit(1); } /* Assign the socket into the SSL structure (SSL and socket without BIO) */ SSL_set_fd(sslcon->ssl, sslcon->sock); /* Perform SSL Handshake on the SSL client */ err = SSL_connect(sslcon->ssl); if(err <= 0) { syslog (LOG_NOTICE, "ERR Could not connect to SSL Server\n"); exit(1); } return sslcon; }
/** * Generate a new ssl connection * @return ssl connection container */ ssl_connection *new_ssl_connection(char *clientpemfile, int sslversion) { ssl_connection *ssl; if (!ssl_initialized) start_ssl(); NEW(ssl); ssl->socket_bio = NULL; ssl->handler = NULL; ssl->cert = NULL; ssl->cipher = NULL; ssl->socket = 0; ssl->next = NULL; ssl->accepted = FALSE; ssl->cert_md5 = NULL; ssl->cert_md5_len = 0; ssl->clientpemfile = clientpemfile ? Str_dup(clientpemfile) : NULL; switch (sslversion) { case SSL_VERSION_SSLV2: #ifdef OPENSSL_NO_SSL2 LogError("SSLv2 is not allowed - use TLS\n"); goto sslerror; #else #ifdef OPENSSL_FIPS if (FIPS_mode()) { LogError("SSLv2 is not allowed in FIPS mode - use TLS\n"); goto sslerror; } else #endif ssl->method = SSLv2_client_method(); #endif break; case SSL_VERSION_SSLV3: #ifdef OPENSSL_FIPS if (FIPS_mode()) { LogError("SSLv3 is not allowed in FIPS mode - use TLS\n"); goto sslerror; } else #endif ssl->method = SSLv3_client_method(); break; case SSL_VERSION_TLSV1: ssl->method = TLSv1_client_method(); break; #ifdef HAVE_TLSV1_1 case SSL_VERSION_TLSV11: ssl->method = TLSv1_1_client_method(); break; #endif #ifdef HAVE_TLSV1_2 case SSL_VERSION_TLSV12: ssl->method = TLSv1_2_client_method(); break; #endif case SSL_VERSION_AUTO: default: ssl->method = SSLv23_client_method(); break; } if (!ssl->method) { LogError("Cannot initialize SSL method -- %s\n", SSLERROR); goto sslerror; } if (!(ssl->ctx = SSL_CTX_new(ssl->method))) { LogError("Cannot initialize SSL client certificate handler -- %s\n", SSLERROR); goto sslerror; } if (sslversion == SSL_VERSION_AUTO) SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); if (ssl->clientpemfile) { if (SSL_CTX_use_certificate_chain_file(ssl->ctx, ssl->clientpemfile) <= 0) { LogError("Cannot initialize SSL client certificate -- %s\n", SSLERROR); goto sslerror; } if (SSL_CTX_use_PrivateKey_file(ssl->ctx, ssl->clientpemfile, SSL_FILETYPE_PEM) <= 0) { LogError("Cannot initialize SSL client private key -- %s\n", SSLERROR); goto sslerror; } if (!SSL_CTX_check_private_key(ssl->ctx)) { LogError("Private key does not match the certificate public key -- %s\n", SSLERROR); goto sslerror; } } return ssl; sslerror: delete_ssl_socket(ssl); return NULL; }
static int tls_drv_control(ErlDrvData handle, unsigned int command, char *buf, int len, char **rbuf, int rlen) { tls_data *d = (tls_data *)handle; int res; int size; ErlDrvBinary *b; X509 *cert; unsigned int flags = command; command &= 0xffff; ERR_clear_error(); switch (command) { case SET_CERTIFICATE_FILE_ACCEPT: case SET_CERTIFICATE_FILE_CONNECT: { time_t mtime = 0; SSL_CTX *ssl_ctx = hash_table_lookup(buf, &mtime); if (is_key_file_modified(buf, &mtime) || ssl_ctx == NULL) { SSL_CTX *ctx; hash_table_insert(buf, mtime, NULL); ctx = SSL_CTX_new(SSLv23_method()); die_unless(ctx, "SSL_CTX_new failed"); res = SSL_CTX_use_certificate_chain_file(ctx, buf); die_unless(res > 0, "SSL_CTX_use_certificate_file failed"); res = SSL_CTX_use_PrivateKey_file(ctx, buf, SSL_FILETYPE_PEM); die_unless(res > 0, "SSL_CTX_use_PrivateKey_file failed"); res = SSL_CTX_check_private_key(ctx); die_unless(res > 0, "SSL_CTX_check_private_key failed"); SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); SSL_CTX_set_default_verify_paths(ctx); #ifdef SSL_MODE_RELEASE_BUFFERS SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS); #endif /* SSL_CTX_load_verify_locations(ctx, "/etc/ejabberd/ca_certificates.pem", NULL); */ /* SSL_CTX_load_verify_locations(ctx, NULL, "/etc/ejabberd/ca_certs/"); */ /* This IF is commented to allow verification in all cases: */ /* if (command == SET_CERTIFICATE_FILE_ACCEPT) */ /* { */ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE, verify_callback); /* } */ ssl_ctx = ctx; hash_table_insert(buf, mtime, ssl_ctx); } d->ssl = SSL_new(ssl_ctx); die_unless(d->ssl, "SSL_new failed"); if (flags & VERIFY_NONE) SSL_set_verify(d->ssl, SSL_VERIFY_NONE, verify_callback); d->bio_read = BIO_new(BIO_s_mem()); d->bio_write = BIO_new(BIO_s_mem()); SSL_set_bio(d->ssl, d->bio_read, d->bio_write); if (command == SET_CERTIFICATE_FILE_ACCEPT) { SSL_set_options(d->ssl, SSL_OP_NO_TICKET); SSL_set_accept_state(d->ssl); } else { SSL_set_options(d->ssl, SSL_OP_NO_SSLv2|SSL_OP_NO_TICKET); SSL_set_connect_state(d->ssl); } break; } case SET_ENCRYPTED_INPUT: die_unless(d->ssl, "SSL not initialized"); BIO_write(d->bio_read, buf, len); break; case SET_DECRYPTED_OUTPUT: die_unless(d->ssl, "SSL not initialized"); res = SSL_write(d->ssl, buf, len); if (res <= 0) { res = SSL_get_error(d->ssl, res); if (res == SSL_ERROR_WANT_READ || res == SSL_ERROR_WANT_WRITE) { b = driver_alloc_binary(1); b->orig_bytes[0] = 2; *rbuf = (char *)b; return 1; } else { die_unless(0, "SSL_write failed"); } } break; case GET_ENCRYPTED_OUTPUT: die_unless(d->ssl, "SSL not initialized"); size = BIO_ctrl_pending(d->bio_write) + 1; b = driver_alloc_binary(size); b->orig_bytes[0] = 0; BIO_read(d->bio_write, b->orig_bytes + 1, size - 1); *rbuf = (char *)b; return size; case GET_DECRYPTED_INPUT: if (!SSL_is_init_finished(d->ssl)) { res = SSL_do_handshake(d->ssl); if (res <= 0) die_unless(SSL_get_error(d->ssl, res) == SSL_ERROR_WANT_READ, "SSL_do_handshake failed"); } else { size = BUF_SIZE + 1; rlen = 1; b = driver_alloc_binary(size); b->orig_bytes[0] = 0; while ((res = SSL_read(d->ssl, b->orig_bytes + rlen, BUF_SIZE)) > 0) { //printf("%d bytes of decrypted data read from state machine\r\n",res); rlen += res; size += BUF_SIZE; b = driver_realloc_binary(b, size); } if (res < 0) { int err = SSL_get_error(d->ssl, res); if (err == SSL_ERROR_WANT_READ) { //printf("SSL_read wants more data\r\n"); //return 0; } // TODO } b = driver_realloc_binary(b, rlen); *rbuf = (char *)b; return rlen; } break; case GET_PEER_CERTIFICATE: cert = SSL_get_peer_certificate(d->ssl); if (cert == NULL) { b = driver_alloc_binary(1); b->orig_bytes[0] = 1; *rbuf = (char *)b; return 1; } else { unsigned char *tmp_buf; rlen = i2d_X509(cert, NULL); if (rlen >= 0) { rlen++; b = driver_alloc_binary(rlen); b->orig_bytes[0] = 0; tmp_buf = (unsigned char *)&b->orig_bytes[1]; i2d_X509(cert, &tmp_buf); X509_free(cert); *rbuf = (char *)b; return rlen; } else X509_free(cert); } break; case GET_VERIFY_RESULT: b = driver_alloc_binary(1); b->orig_bytes[0] = SSL_get_verify_result(d->ssl); *rbuf = (char *)b; return 1; break; } b = driver_alloc_binary(1); b->orig_bytes[0] = 0; *rbuf = (char *)b; return 1; }
static int tls_init_context(tls_t *tls, tls_issues_t const *ti) { int verify; static int random_loaded; ONCE_INIT(tls_init_once); if (!random_loaded) { random_loaded = 1; if (ti->randFile && !RAND_load_file(ti->randFile, 1024 * 1024)) { if (ti->configured > 1) { SU_DEBUG_3(("%s: cannot open randFile %s\n", "tls_init_context", ti->randFile)); tls_log_errors(3, "tls_init_context", 0); } /* errno = EIO; */ /* return -1; */ } } #if HAVE_SIGPIPE /* Avoid possible SIGPIPE when sending close_notify */ signal(SIGPIPE, SIG_IGN); #endif if (tls->ctx == NULL) { const SSL_METHOD *meth; /* meth = SSLv3_method(); */ /* meth = SSLv23_method(); */ if (ti->version) meth = TLSv1_method(); else meth = SSLv23_method(); tls->ctx = SSL_CTX_new((SSL_METHOD*)meth); } if (tls->ctx == NULL) { tls_log_errors(1, "tls_init_context", 0); errno = EIO; return -1; } /* Set callback if we have a passphrase */ if (ti->passphrase != NULL) { SSL_CTX_set_default_passwd_cb(tls->ctx, passwd_cb); SSL_CTX_set_default_passwd_cb_userdata(tls->ctx, (void *)ti); } if (!SSL_CTX_use_certificate_file(tls->ctx, ti->cert, SSL_FILETYPE_PEM)) { if (ti->configured > 0) { SU_DEBUG_1(("%s: invalid local certificate: %s\n", "tls_init_context", ti->cert)); tls_log_errors(3, "tls_init_context", 0); #if require_client_certificate errno = EIO; return -1; #endif } } if (!SSL_CTX_use_PrivateKey_file(tls->ctx, ti->key, SSL_FILETYPE_PEM)) { if (ti->configured > 0) { SU_DEBUG_1(("%s: invalid private key: %s\n", "tls_init_context", ti->key)); tls_log_errors(3, "tls_init_context(key)", 0); #if require_client_certificate errno = EIO; return -1; #endif } } if (!SSL_CTX_check_private_key(tls->ctx)) { if (ti->configured > 0) { SU_DEBUG_1(("%s: private key does not match the certificate public key\n", "tls_init_context")); } #if require_client_certificate errno = EIO; return -1; #endif } if (!SSL_CTX_load_verify_locations(tls->ctx, ti->CAfile, ti->CApath)) { SU_DEBUG_1(("%s: error loading CA list: %s\n", "tls_init_context", ti->CAfile)); if (ti->configured > 0) tls_log_errors(3, "tls_init_context(CA)", 0); errno = EIO; return -1; } /* corresponds to (enum tport_tls_verify_policy) */ tls->verify_incoming = (ti->policy & 0x1) ? 1 : 0; tls->verify_outgoing = (ti->policy & 0x2) ? 1 : 0; tls->verify_subj_in = (ti->policy & 0x4) ? tls->verify_incoming : 0; tls->verify_subj_out = (ti->policy & 0x8) ? tls->verify_outgoing : 0; tls->verify_date = (ti->verify_date) ? 1 : 0; if (tls->verify_incoming) verify = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT; else verify = SSL_VERIFY_NONE; SSL_CTX_set_verify_depth(tls->ctx, ti->verify_depth); SSL_CTX_set_verify(tls->ctx, verify, tls_verify_cb); if (!SSL_CTX_set_cipher_list(tls->ctx, ti->cipher)) { SU_DEBUG_1(("%s: error setting cipher list\n", "tls_init_context")); tls_log_errors(3, "tls_init_context", 0); errno = EIO; return -1; } return 0; }
int main(int argc, char **argv) { int sockfd = 0; int on = 1; struct sockaddr_in6 listen_addr = { AF_INET6, htons(20220), 0, IN6ADDR_ANY_INIT, 0 }; size_t addr_size = sizeof(struct sockaddr_in6); fd_set fds[2]; int result, flags; int idx, res = 0; struct timeval timeout; struct sigaction act, oact; #ifdef WITH_DTLS SSL_CTX *ctx; memset(ssl_peer_storage, 0, sizeof(ssl_peer_storage)); SSL_load_error_strings(); SSL_library_init(); ctx = SSL_CTX_new(DTLSv1_server_method()); SSL_CTX_set_cipher_list(ctx, "ALL"); SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); res = SSL_CTX_use_certificate_file(ctx, SERVER_CERT_PEM, SSL_FILETYPE_PEM); if (res != 1) { fprintf(stderr, "cannot read server certificate from file '%s' (%s)\n", SERVER_CERT_PEM, ERR_error_string(res,NULL)); goto end; } res = SSL_CTX_use_PrivateKey_file(ctx, SERVER_KEY_PEM, SSL_FILETYPE_PEM); if (res != 1) { fprintf(stderr, "cannot read server key from file '%s' (%s)\n", SERVER_KEY_PEM, ERR_error_string(res,NULL)); goto end; } res = SSL_CTX_check_private_key (ctx); if (res != 1) { fprintf(stderr, "invalid private key\n"); goto end; } res = SSL_CTX_load_verify_locations(ctx, CA_CERT_PEM, NULL); if (res != 1) { fprintf(stderr, "cannot read ca file '%s'\n", CA_CERT_PEM); goto end; } /* Client has to authenticate */ /* Client has to authenticate */ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, NULL); SSL_CTX_set_read_ahead(ctx, 1); /* disable read-ahead */ SSL_CTX_set_cookie_generate_cb(ctx, generate_cookie); SSL_CTX_set_cookie_verify_cb(ctx, verify_cookie); SSL_CTX_use_psk_identity_hint(ctx, "Enter password for CoAP-Gateway"); SSL_CTX_set_psk_server_callback(ctx, psk_server_callback); SSL_CTX_set_info_callback(ctx, info_callback); #endif sockfd = socket(listen_addr.sin6_family, SOCK_DGRAM, 0); if ( sockfd < 0 ) { perror("socket"); return -1; } if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) ) < 0) perror("setsockopt SO_REUSEADDR"); flags = fcntl(sockfd, F_GETFL, 0); if (flags < 0 || fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) < 0) { perror("fcntl"); return -1; } on = 1; if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on) ) < 0) { perror("setsockopt IPV6_PKTINFO"); } if (bind (sockfd, (const struct sockaddr *)&listen_addr, addr_size) < 0) { perror("bind"); res = -2; goto end; } act.sa_handler = handle_sigint; sigemptyset(&act.sa_mask); act.sa_flags = 0; sigaction(SIGINT, &act, &oact); while (!quit) { FD_ZERO(&fds[READ]); FD_ZERO(&fds[WRITE]); FD_SET(sockfd, &fds[READ]); timeout.tv_sec = 1; timeout.tv_usec = 0; result = select( FD_SETSIZE, &fds[READ], &fds[WRITE], 0, &timeout); if (result < 0) { /* error */ if (errno != EINTR) perror("select"); } else if (result > 0) { /* read from socket */ if ( FD_ISSET( sockfd, &fds[READ]) ) { _read(ctx, sockfd); /* read received data */ } else if ( FD_ISSET( sockfd, &fds[WRITE]) ) { /* write to socket */ _write(ctx, sockfd); /* write data */ } } else { /* timeout */ check_timeout(); } remove_closed(); } end: #ifdef WITH_DTLS for (idx = 0; idx < MAX_SSL_PEERS; idx++) { if (ssl_peer_storage[idx] && ssl_peer_storage[idx]->ssl) { if (ssl_peer_storage[idx]->state == PEER_ST_ESTABLISHED) SSL_shutdown(ssl_peer_storage[idx]->ssl); SSL_free(ssl_peer_storage[idx]->ssl); } } SSL_CTX_free(ctx); #endif close(sockfd); /* don't care if we close stdin at this point */ return res; }