/*************************************************************************** * nsock_ssl.c -- This contains functions that relate somewhat exclusively * * to SSL (over TCP) support in nsock. Where SSL support is incidental, * * it is often in other files where code can be more easily shared between * * the SSL and NonSSL paths. * * * ***********************IMPORTANT NSOCK LICENSE TERMS*********************** * * * The nsock parallel socket event library is (C) 1999-2013 Insecure.Com * * LLC This library is free software; you may redistribute and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; Version 2. This guarantees * * your right to use, modify, and redistribute this software under certain * * conditions. If this license is unacceptable to you, Insecure.Com LLC * * may be willing to sell alternative licenses (contact * * sales@insecure.com ). * * * * As a special exception to the GPL terms, Insecure.Com LLC grants * * permission to link the code of this program with any version of the * * OpenSSL library which is distributed under a license identical to that * * listed in the included docs/licenses/OpenSSL.txt file, and distribute * * linked combinations including the two. You must obey the GNU GPL in all * * respects for all of the code used other than OpenSSL. If you modify * * this file, you may extend this exception to your version of the file, * * but you are not obligated to do so. * * * * If you received these files with a written license agreement stating * * terms other than the (GPL) terms above, then that alternative license * * agreement takes precedence over this comment. * * * * Source is provided to this software because we believe users have a * * right to know exactly what a program is going to do before they run it. * * This also allows you to audit the software for security holes. * * * * Source code also allows you to port Nmap to new platforms, fix bugs, * * and add new features. You are highly encouraged to send your changes * * to the dev@nmap.org mailing list for possible incorporation into the * * main distribution. By sending these changes to Fyodor or one of the * * Insecure.Org development mailing lists, or checking them into the Nmap * * source code repository, it is understood (unless you specify otherwise) * * that you are offering the Nmap Project (Insecure.Com LLC) the * * unlimited, non-exclusive right to reuse, modify, and relicense the * * code. Nmap will always be available Open Source, but this is important * * because the inability to relicense code has caused devastating problems * * for other Free Software projects (such as KDE and NASM). We also * * occasionally relicense the code to third parties as discussed above. * * If you wish to specify special license conditions of your * * contributions, just say so when you send them. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License v2.0 for more details * * (http://www.gnu.org/licenses/gpl-2.0.html). * * * ***************************************************************************/ /* $Id$ */ #include "nsock.h" #include "nsock_internal.h" #include "nsock_ssl.h" #include "netutils.h" #if HAVE_OPENSSL /* Disallow anonymous ciphers (Diffie-Hellman key agreement), low bit-strength * ciphers, export-crippled ciphers, and MD5. Prefer ciphers in decreasing order * of key size. The cipher list is taken from the book Network Security with * OpenSSL. To see exactly what ciphers are enabled, use the command * openssl ciphers -v '...' * where ... is the string below. */ #define CIPHERS_SECURE "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH" /* This list of ciphers is for speed and compatibility, not security. Any cipher * is accepted, and the list is sorted by speed based on Brian Hatch's * (bri@ifokr.org) tests on an Pentium 686 against the ciphers listed. */ #define CIPHERS_FAST "RC4-SHA:RC4-MD5:NULL-SHA:EXP-DES-CBC-SHA:EXP-EDH-RSA-DES-CBC-SHA:EXP-RC4-MD5:NULL-MD5:EDH-RSA-DES-CBC-SHA:EXP-RC2-CBC-MD5:EDH-RSA-DES-CBC3-SHA:EXP-ADH-RC4-MD5:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:EXP-ADH-DES-CBC-SHA:ADH-AES256-SHA:ADH-DES-CBC-SHA:ADH-RC4-MD5:AES256-SHA:DES-CBC-SHA:DES-CBC3-SHA:ADH-DES-CBC3-SHA:AES128-SHA:ADH-AES128-SHA:eNULL:ALL" extern struct timeval nsock_tod; # ifndef OPENSSL_NO_NEXTPROTONEG int kMaxProtocolsLength = 256; /* Support for Next Protocol Negotiation. Most part of this code is taken * from the openssl source code ('apps/apps.c' and 'apps/s_client.c') */ /* Parses a comma separated list of strings into a string * in a format suitable for passing to SSL_select_next_proto: a vector of 8-bit, * length prefixed byte strings (the length byte itself is not included in * the length and no byte string may be truncated). * * outlen: (output) set to the length of the resulting buffer on success. * in: a NUL terminated string like "abc,def,ghi" * * returns: a malloced buffer or NULL on failure. */ static unsigned char* tls_nextprotoneg_parse_protocols(unsigned short *outlen, const char *in) { size_t len; unsigned char *out; size_t i, start = 0; len = strlen(in); if (len >= kMaxProtocolsLength) return NULL; out = OPENSSL_malloc(strlen(in) + 1); if (!out) { return NULL; } for (i = 0; i <= len; ++i) { if (i == len || in[i] == ',') { if (i - start > 255) { OPENSSL_free(out); return NULL; } out[start] = i - start; start = i + 1; } else { out[i+1] = in[i]; } } *outlen = len + 1; return out; } /* This is called by OpenSSL during the handshake. If the server supports NPN, * selects a protocol from the list that the server provides. */ static int select_next_proto_cb(SSL *s, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg) { struct tls_nextprotoneg_ctx *ctx = arg; ctx->status = SSL_select_next_proto( out, outlen, in, inlen, ctx->protocols, ctx->protocols_length); return SSL_TLSEXT_ERR_OK; } # endif /* ndef OPENSSL_NO_NEXTPROTONEG */ /* Create an SSL_CTX and do initialization that is common to nsp_ssl_init and * nsp_ssl_init_max_speed. */ static SSL_CTX *ssl_init_common() { SSL_CTX *ctx; SSL_load_error_strings(); SSL_library_init(); ctx = SSL_CTX_new(SSLv23_client_method()); if (!ctx) { fatal("OpenSSL failed to create a new SSL_CTX: %s", ERR_error_string(ERR_get_error(), NULL)); } /* Our SSL* will always have the SSL_SESSION* inside it, so we neither need to * use nor waste memory for the session cache. (Use '1' because '0' means * 'infinite'.) */ SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF|SSL_SESS_CACHE_NO_AUTO_CLEAR); SSL_CTX_sess_set_cache_size(ctx, 1); SSL_CTX_set_timeout(ctx, 3600); /* pretty unnecessary */ return ctx; } nsock_ssl_ctx nsp_ssl_nextprotoneg(nsock_event nse, nsock_ssl_ctx sslctx, const char *client_protocol_list) { SSL_CTX *ctx = (SSL_CTX*)sslctx; if (ctx == NULL) { ctx = ssl_init_common(); } #ifndef OPENSSL_NO_NEXTPROTONEG struct tls_nextprotoneg_ctx *nextprotoneg_ctx; nextprotoneg_ctx = &(nse->sslinfo.tls_nextprotoneg); nextprotoneg_ctx->enabled = 1; nextprotoneg_ctx->status = OPENSSL_NPN_UNSUPPORTED; nextprotoneg_ctx->protocols = tls_nextprotoneg_parse_protocols( &(nextprotoneg_ctx->protocols_length), client_protocol_list); SSL_CTX_set_next_proto_select_cb( ctx, select_next_proto_cb, nextprotoneg_ctx); #endif return ctx; } /* Initializes an Nsock pool to create SSL connections. This sets an internal * SSL_CTX, which is like a template that sets options for all connections that * are made from it. The connections made from this context will use only secure * ciphers but no server certificate verification is done. Returns the SSL_CTX * so you can set your own options. */ nsock_ssl_ctx nsp_ssl_init(nsock_pool ms_pool) { struct npool *ms = (struct npool *)ms_pool; char rndbuf[128]; if (ms->sslctx == NULL) ms->sslctx = ssl_init_common(); /* get_random_bytes may or may not provide high-quality randomness. Add it to * the entropy pool without increasing the entropy estimate (third argument of * RAND_add is 0). We rely on OpenSSL's entropy gathering, called implicitly * by RAND_status, to give us what we need, or else bail out if it fails. */ get_random_bytes(rndbuf, sizeof(rndbuf)); RAND_add(rndbuf, sizeof(rndbuf), 0); if (!RAND_status()) fatal("nsp_ssl_init: Failed to seed OpenSSL PRNG (RAND_status returned false)."); /* By default, do no server certificate verification. To enable it, do * something like: * SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); * * on the SSL_CTX returned. If you do, it is then up to the application to * load trusted certificates with SSL_CTX_load_verify_locations or * SSL_CTX_set_default_verify_paths, or else every connection will fail. It * is also up to the application to do any further checks such as domain name * validation. */ SSL_CTX_set_verify(ms->sslctx, SSL_VERIFY_NONE, NULL); /* SSL_OP_ALL sets bug-compatibility for pretty much everything. * SSL_OP_NO_SSLv2 disables the less-secure SSLv2 while allowing us to use the * SSLv2-compatible SSLv23_client_method. */ SSL_CTX_set_options(ms->sslctx, SSL_OP_ALL|SSL_OP_NO_SSLv2); if (!SSL_CTX_set_cipher_list(ms->sslctx, CIPHERS_SECURE)) { fatal("Unable to set OpenSSL cipher list: %s", ERR_error_string(ERR_get_error(), NULL)); } return ms->sslctx; } /* Initializes an Nsock pool to create SSL connections that emphasize speed over * security. Insecure ciphers are used when they are faster and no certificate * verification is done. Returns the SSL_CTX so you can set your own options. */ nsock_ssl_ctx nsp_ssl_init_max_speed(nsock_pool ms_pool) { struct npool *ms = (struct npool *)ms_pool; char rndbuf[128]; if (ms->sslctx == NULL) ms->sslctx = ssl_init_common(); /* get_random_bytes may or may not provide high-quality randomness. */ get_random_bytes(rndbuf, sizeof(rndbuf)); RAND_seed(rndbuf, sizeof(rndbuf)); SSL_CTX_set_verify(ms->sslctx, SSL_VERIFY_NONE, NULL); SSL_CTX_set_options(ms->sslctx, SSL_OP_ALL); if (!SSL_CTX_set_cipher_list(ms->sslctx, CIPHERS_FAST)) { fatal("Unable to set OpenSSL cipher list: %s", ERR_error_string(ERR_get_error(), NULL)); } return ms->sslctx; } /* Check server certificate verification, after a connection is established. We * check first that a certificate was even offered, then call * SSL_get_verify_result to get the overall status of verification. (Just * calling SSL_get_verify_result is not enough because that function returns * X509_V_OK when 0 certificates are presented.) If the verification mode of the * SSL object is SSL_VERIFY_NONE, or if OpenSSL is disabled, this function * always returns true. */ int nsi_ssl_post_connect_verify(const nsock_iod nsockiod) { struct niod *iod = (struct niod *)nsockiod; assert(iod->ssl != NULL); if (SSL_get_verify_mode(iod->ssl) != SSL_VERIFY_NONE) { X509 *cert; cert = SSL_get_peer_certificate(iod->ssl); if (cert == NULL) /* No certificate presented. */ return 0; X509_free(cert); if (SSL_get_verify_result(iod->ssl) != X509_V_OK) /* Something wrong with verification. */ return 0; } return 1; } #else /* NOT HAVE_OPENSSL */ nsock_ssl_ctx nsp_ssl_init(nsock_pool ms_pool) { fatal("%s called with no OpenSSL support", __func__); } nsock_ssl_ctx nsp_ssl_init_max_speed(nsock_pool ms_pool) { fatal("%s called with no OpenSSL support", __func__); } int nsi_ssl_post_connect_verify(const nsock_iod nsockiod) { return 1; } #endif