int TlsInit( char* cacertPath )
{
    e_TlsError    vl_Error;
    char a_DefaultCertPath[] = DEFAULT_CERT_PATH;
    char *p_CertToUse;

    DEBUG_LOG_PRINT_LEV2(("TlsInit : Entry"));

    SSL_load_error_strings();
    SSL_library_init();

    gp_SSL_CTX = SSL_CTX_new(TLSv1_method());
    if( NULL == gp_SSL_CTX )
    {
        DEBUG_LOG_PRINT_LEV2(("SSL_CTX_new returned NULL!\n"));
         return FALSE;
    }
    if ( SSL_CTX_set_cipher_list(gp_SSL_CTX, DEFAULT_CIPHER_LIST ) != 1 )
    {
        DEBUG_LOG_PRINT_LEV2(("SSL_CTX_set_cipher_list returned NULL!\n"));
        SSL_CTX_free(gp_SSL_CTX);
        return FALSE;  // ERROR selecting SUPL cipher list
    }
    SSL_CTX_set_info_callback(gp_SSL_CTX, Tls_openssl_info_callback);
#ifdef AGPS_DISABLE_TLS_CA_CERT_VERIFY
    /* In this mode, even if a CA cert is not found, a secure connection is established */
    SSL_CTX_set_verify( gp_SSL_CTX , SSL_VERIFY_NONE , NULL );
#else
    /* If a CA cert is not found matching the server certificate, the handshake is shutdown */
    SSL_CTX_set_verify( gp_SSL_CTX , SSL_VERIFY_PEER , Tls_openssl_certificate_verify_callback );
#endif


    p_CertToUse = ( cacertPath == NULL ) ? a_DefaultCertPath : cacertPath;

    DEBUG_LOG_PRINT_LEV2(("TlsInit : Certificate %s\n" , p_CertToUse));

    if( SSL_CTX_load_verify_locations(gp_SSL_CTX, p_CertToUse ,NULL) != 1 )
    {
        DEBUG_LOG_PRINT_LEV2(("SSL_CTX_load_verify_locations failed!\n"));
         return FALSE;
    }
    DEBUG_LOG_PRINT_LEV2(("SSL_CTX_get_options : %ld" , SSL_CTX_get_options( gp_SSL_CTX ) ));
    SSL_CTX_set_options( gp_SSL_CTX,SSL_OP_NO_TICKET|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3) ;
    DEBUG_LOG_PRINT_LEV2(("SSL_CTX_get_options : %ld" , SSL_CTX_get_options( gp_SSL_CTX ) ));

    DEBUG_LOG_PRINT_LEV2(("TlsInit : Exit"));
    return TRUE;
}
Exemple #2
0
/* Select the appropriate server CTX.
 * Returns SSL_TLSEXT_ERR_OK if a match was found.
 * If |ignore| is 1, returns SSL_TLSEXT_ERR_NOACK on mismatch.
 * Otherwise, returns SSL_TLSEXT_ERR_ALERT_FATAL on mismatch.
 * An empty SNI extension also returns SSL_TSLEXT_ERR_NOACK.
 */
static int select_server_ctx(SSL *s, void *arg, int ignore)
{
    const char *servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name);
    HANDSHAKE_EX_DATA *ex_data =
        (HANDSHAKE_EX_DATA*)(SSL_get_ex_data(s, ex_data_idx));

    if (servername == NULL) {
        ex_data->servername = SSL_TEST_SERVERNAME_SERVER1;
        return SSL_TLSEXT_ERR_NOACK;
    }

    if (strcmp(servername, "server2") == 0) {
        SSL_CTX *new_ctx = (SSL_CTX*)arg;
        SSL_set_SSL_CTX(s, new_ctx);
        /*
         * Copy over all the SSL_CTX options - reasonable behavior
         * allows testing of cases where the options between two
         * contexts differ/conflict
         */
        SSL_clear_options(s, 0xFFFFFFFFL);
        SSL_set_options(s, SSL_CTX_get_options(new_ctx));

        ex_data->servername = SSL_TEST_SERVERNAME_SERVER2;
        return SSL_TLSEXT_ERR_OK;
    } else if (strcmp(servername, "server1") == 0) {
        ex_data->servername = SSL_TEST_SERVERNAME_SERVER1;
        return SSL_TLSEXT_ERR_OK;
    } else if (ignore) {
        ex_data->servername = SSL_TEST_SERVERNAME_SERVER1;
        return SSL_TLSEXT_ERR_NOACK;
    } else {
        /* Don't set an explicit alert, to test library defaults. */
        return SSL_TLSEXT_ERR_ALERT_FATAL;
    }
}
Exemple #3
0
/* OpenSSL < 0.9.8m does not have SSL_CTX_clear_options() */
long HsOpenSSL_SSL_CTX_clear_options(SSL_CTX* ctx, long options) {
#if defined(SSL_CTX_clear_options)
    return SSL_CTX_clear_options(ctx, options);
#else
    long tmp = SSL_CTX_get_options(ctx);
    return SSL_CTX_set_options(ctx, tmp & ~options);
#endif
}
CURLcode curl_tls_workarounds_cb(CURL *curl, void *sslctx, void *parm) {
  // Check to see if workarounds are enabled.
  if (RuntimeOption::TLSDisableTLS1_2) {
    SSL_CTX* ctx = (SSL_CTX*)sslctx;
    SSL_CTX_set_options(ctx, SSL_CTX_get_options (ctx) | SSL_OP_NO_TLSv1_2);
  }
  return CURLE_OK;
}
Exemple #5
0
static int checksslv2(int test, int sslv2)
{
    int options;
    if (test == TEST_SSL_CTX) {
        options = SSL_CTX_get_options(ctx);
    } else {
        options = SSL_get_options(ssl);
    }
    return ((options & SSL_OP_NO_SSLv2) == 0) ^ (sslv2 == SSLV2OFF);
}
Exemple #6
0
static int openssl_ssl_ctx_options(lua_State*L)
{
  SSL_CTX* ctx = CHECK_OBJECT(1, SSL_CTX, "openssl.ssl_ctx");
  long options = 0;
  int ret;
  int i;
  if (!lua_isnoneornil(L, 2))
  {
    int top = lua_gettop(L);
    int clear = lua_isboolean(L, 2) ? lua_toboolean(L, 2) : 0;
    i = lua_isboolean(L, 2) ? 3 : 2;
    for (; i <= top; i++)
    {
      if (lua_isnumber(L, i))
        options |= (long)luaL_checkinteger(L, i);
      else
      {
        const char* s = luaL_checkstring(L, i);
        int j;
        for (j = 0; ssl_options[j].name; j++)
        {
          LuaL_Enum e = ssl_options[j];
          if (strcasecmp(s, e.name))
          {
            options |= e.val;
            break;
          }
        }
      }
    }


    if (clear != 0)
      options = SSL_CTX_clear_options(ctx, options);
    else
      options = SSL_CTX_set_options(ctx, options);
  }
  else
    options = SSL_CTX_get_options(ctx);

  lua_newtable(L);
  ret = 0;
  for (i = 0; ssl_options[i].name; i++)
  {
    LuaL_Enum e = ssl_options[i];
    if (options && e.val)
    {
      lua_pushstring(L, e.name);
      ret++;
      lua_rawseti(L, -2, ret);
    }
  }
  return 1;
}
Exemple #7
0
ret_t
cherokee_cryptor_libssl_find_vserver (SSL *ssl,
				      cherokee_server_t     *srv,
				      cherokee_buffer_t     *servername,
				      cherokee_connection_t *conn)
{
	ret_t                      ret;
	cherokee_virtual_server_t *vsrv = NULL;
	SSL_CTX                   *ctx;

	/* Try to match the connection to a server
	 */

	ret = cherokee_server_get_vserver(srv, servername, conn, &vsrv);
	if ((ret != ret_ok) || (vsrv == NULL)) {
		LOG_ERROR (CHEROKEE_ERROR_SSL_SRV_MATCH, servername->buf);
		return ret_error;
	}

	TRACE (ENTRIES, "Setting new TLS context. Virtual host='%s'\n",
	       vsrv->name.buf);

	/* Check whether the Virtual Server supports TLS
	 */
	if ((vsrv->cryptor == NULL) ||
	    (CRYPTOR_VSRV_SSL(vsrv->cryptor)->context == NULL))
	{
		TRACE (ENTRIES, "Virtual server '%s' does not support SSL\n", servername->buf);
		return ret_error;
	}

	/* Set the new SSL context
	 */
	ctx = SSL_set_SSL_CTX (ssl, CRYPTOR_VSRV_SSL(vsrv->cryptor)->context);
	if (ctx != CRYPTOR_VSRV_SSL(vsrv->cryptor)->context) {
		LOG_ERROR (CHEROKEE_ERROR_SSL_CHANGE_CTX, servername->buf);
	}

	/* SSL_set_SSL_CTX() only change certificates. We need to
	 * changes more options by hand.
	 */
	SSL_set_options(ssl, SSL_CTX_get_options(ssl->ctx));

	if ((SSL_get_verify_mode(ssl) == SSL_VERIFY_NONE) ||
	    (SSL_num_renegotiations(ssl) == 0)) {

		SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ssl->ctx),
		               SSL_CTX_get_verify_callback(ssl->ctx));
	}

	return ret_ok;
}
CURLcode curl_tls_workarounds_cb(CURL* /*curl*/, void* sslctx, void* /*parm*/) {
  // Check to see if workarounds are enabled.
  SSL_CTX* ctx = (SSL_CTX*)sslctx;
  if (RuntimeOption::TLSDisableTLS1_2) {
#ifdef SSL_OP_NO_TLSv1_2
    SSL_CTX_set_options(ctx, SSL_CTX_get_options (ctx) | SSL_OP_NO_TLSv1_2);
#else
    raise_notice("TLSDisableTLS1_2 enabled, but this version of "
                 "SSL does not support that option");
#endif
  }
  if (!RuntimeOption::TLSClientCipherSpec.empty()) {
    SSL_CTX_set_cipher_list(ctx, RuntimeOption::TLSClientCipherSpec.c_str());
  }
  return CURLE_OK;
}
Exemple #9
0
static void get_ssl_certificate (ice_config_t *config)
{
    ssl_ok = 0;
    do
    {
        long ssl_opts;

        ssl_ctx = NULL;
        if (config->cert_file == NULL)
            break;

        ssl_ctx = SSL_CTX_new (SSLv23_server_method());
        ssl_opts = SSL_CTX_get_options (ssl_ctx);
        SSL_CTX_set_options (ssl_ctx, ssl_opts|SSL_OP_NO_SSLv2);

        if (SSL_CTX_use_certificate_chain_file (ssl_ctx, config->cert_file) <= 0)
        {
            WARN1 ("Invalid cert file %s", config->cert_file);
            break;
        }
        if (SSL_CTX_use_PrivateKey_file (ssl_ctx, config->cert_file, SSL_FILETYPE_PEM) <= 0)
        {
            WARN1 ("Invalid private key file %s", config->cert_file);
            break;
        }
        if (!SSL_CTX_check_private_key (ssl_ctx))
        {
            ERROR1 ("Invalid %s - Private key does not match cert public key", config->cert_file);
            break;
        }
        if (SSL_CTX_set_cipher_list(ssl_ctx, config->cipher_list) <= 0)
        {
            WARN1 ("Invalid cipher list: %s", config->cipher_list);
        }
        ssl_ok = 1;
        INFO1 ("SSL certificate found at %s", config->cert_file);
        INFO1 ("SSL using ciphers %s", config->cipher_list);
        return;
    } while (0);
    if (ssl_ctx)
    {
        WARN2 ("failed to load cert %s (%s)", config->cert_file, ERR_reason_error_string (ERR_peek_last_error()));
        SSL_CTX_free (ssl_ctx);
        ssl_ctx = NULL;
    }
    INFO0 ("No SSL capability on any configured ports");
}
Exemple #10
0
static void get_ssl_certificate (ice_config_t *config)
{
    SSL_METHOD *method;
    long ssl_opts;
    ssl_ok = 0;

    SSL_load_error_strings();                /* readable error messages */
    SSL_library_init();                      /* initialize library */

    method = SSLv23_server_method();
    ssl_ctx = SSL_CTX_new (method);
    ssl_opts = SSL_CTX_get_options (ssl_ctx);
    SSL_CTX_set_options (ssl_ctx, ssl_opts|SSL_OP_NO_SSLv2);

    do
    {
        if (config->cert_file == NULL)
            break;
        if (SSL_CTX_use_certificate_chain_file (ssl_ctx, config->cert_file) <= 0)
        {
            WARN1 ("Invalid cert file %s", config->cert_file);
            break;
        }
        if (SSL_CTX_use_PrivateKey_file (ssl_ctx, config->cert_file, SSL_FILETYPE_PEM) <= 0)
        {
            WARN1 ("Invalid private key file %s", config->cert_file);
            break;
        }
        if (!SSL_CTX_check_private_key (ssl_ctx))
        {
            ERROR1 ("Invalid %s - Private key does not match cert public key", config->cert_file);
            break;
        }
        if (SSL_CTX_set_cipher_list(ssl_ctx, config->cipher_list) <= 0) 
        { 
            WARN1 ("Invalid cipher list: %s", config->cipher_list); 
        } 
        ssl_ok = 1;
        INFO1 ("SSL certificate found at %s", config->cert_file);
        INFO1 ("SSL using ciphers %s", config->cipher_list); 
        return;
    } while (0);
    INFO0 ("No SSL capability on any configured ports");
}
Exemple #11
0
int
rb_init_ssl(void)
{
	int ret = 1;
	char librb_data[] = "librb data";
	const char librb_ciphers[] = "kEECDH+HIGH:kEDH+HIGH:HIGH:!RC4:!aNULL";
	SSL_load_error_strings();
	SSL_library_init();
	librb_index = SSL_get_ex_new_index(0, librb_data, NULL, NULL, NULL);

#ifndef LRB_HAVE_TLS_METHOD_API
	ssl_server_ctx = SSL_CTX_new(SSLv23_server_method());
#else
	ssl_server_ctx = SSL_CTX_new(TLS_server_method());
#endif

	if(ssl_server_ctx == NULL)
	{
		rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL server context: %s",
			   get_ssl_error(ERR_get_error()));
		ret = 0;
	}

	long server_options = SSL_CTX_get_options(ssl_server_ctx);

#ifndef LRB_HAVE_TLS_METHOD_API
	server_options |= SSL_OP_NO_SSLv2;
	server_options |= SSL_OP_NO_SSLv3;
#endif

#ifdef SSL_OP_SINGLE_DH_USE
	server_options |= SSL_OP_SINGLE_DH_USE;
#endif

#ifdef SSL_OP_SINGLE_ECDH_USE
	server_options |= SSL_OP_SINGLE_ECDH_USE;
#endif

#ifdef SSL_OP_NO_TICKET
	server_options |= SSL_OP_NO_TICKET;
#endif

	server_options |= SSL_OP_CIPHER_SERVER_PREFERENCE;

	SSL_CTX_set_options(ssl_server_ctx, server_options);
	SSL_CTX_set_verify(ssl_server_ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, verify_accept_all_cb);
	SSL_CTX_set_session_cache_mode(ssl_server_ctx, SSL_SESS_CACHE_OFF);
	SSL_CTX_set_cipher_list(ssl_server_ctx, librb_ciphers);

	/* Set ECDHE on OpenSSL 1.00+, but make sure it's actually available
	 * (it's not by default on Solaris or Red Hat... f**k Red Hat and Oracle)
	 */
	#if (OPENSSL_VERSION_NUMBER >= 0x10000000L) && !defined(OPENSSL_NO_ECDH)
		EC_KEY *key = EC_KEY_new_by_curve_name(NID_secp384r1);
		if (key) {
			SSL_CTX_set_tmp_ecdh(ssl_server_ctx, key);
			EC_KEY_free(key);
		}
	#endif

#ifndef LRB_HAVE_TLS_METHOD_API
	ssl_client_ctx = SSL_CTX_new(SSLv23_client_method());
#else
	ssl_client_ctx = SSL_CTX_new(TLS_client_method());
#endif

	if(ssl_client_ctx == NULL)
	{
		rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL client context: %s",
			   get_ssl_error(ERR_get_error()));
		ret = 0;
	}

#ifndef LRB_HAVE_TLS_METHOD_API
	SSL_CTX_set_options(ssl_client_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
#endif

#ifdef SSL_OP_NO_TICKET
	SSL_CTX_set_options(ssl_client_ctx, SSL_OP_NO_TICKET);
#endif

	SSL_CTX_set_cipher_list(ssl_client_ctx, librb_ciphers);

	return ret;
}
Exemple #12
0
int context_init(SERVICE_OPTIONS *section) { /* init SSL context */
    /* create SSL context */
    if(section->option.client)
        section->ctx=SSL_CTX_new(section->client_method);
    else /* server mode */
        section->ctx=SSL_CTX_new(section->server_method);
    if(!section->ctx) {
        sslerror("SSL_CTX_new");
        return 1; /* FAILED */
    }
    SSL_CTX_set_ex_data(section->ctx, index_opt, section); /* for callbacks */

    /* load certificate and private key to be verified by the peer server */
#if !defined(OPENSSL_NO_ENGINE) && OPENSSL_VERSION_NUMBER>=0x0090809fL
    /* SSL_CTX_set_client_cert_engine() was introduced in OpenSSL 0.9.8i */
    if(section->option.client && section->engine) {
        if(SSL_CTX_set_client_cert_engine(section->ctx, section->engine))
            s_log(LOG_INFO, "Client certificate engine (%s) enabled",
                ENGINE_get_id(section->engine));
        else /* no client certificate functionality in this engine */
            sslerror("SSL_CTX_set_client_cert_engine"); /* ignore error */
    }
#endif
    if(auth_init(section))
        return 1; /* FAILED */

    /* initialize verification of the peer server certificate */
    if(verify_init(section))
        return 1; /* FAILED */

    /* initialize DH/ECDH server mode */
    if(!section->option.client) {
#ifndef OPENSSL_NO_TLSEXT
        SSL_CTX_set_tlsext_servername_arg(section->ctx, section);
        SSL_CTX_set_tlsext_servername_callback(section->ctx, servername_cb);
#endif /* OPENSSL_NO_TLSEXT */
#ifndef OPENSSL_NO_DH
        dh_init(section); /* ignore the result (errors are not critical) */
#endif /* OPENSSL_NO_DH */
#ifndef OPENSSL_NO_ECDH
        ecdh_init(section); /* ignore the result (errors are not critical) */
#endif /* OPENSSL_NO_ECDH */
    }

    /* setup session cache */
    if(!section->option.client) {
        unsigned servname_len=(unsigned)strlen(section->servname);
        if(servname_len>SSL_MAX_SSL_SESSION_ID_LENGTH)
            servname_len=SSL_MAX_SSL_SESSION_ID_LENGTH;
        if(!SSL_CTX_set_session_id_context(section->ctx,
                (unsigned char *)section->servname, servname_len)) {
            sslerror("SSL_CTX_set_session_id_context");
            return 1; /* FAILED */
        }
    }
#ifdef SSL_SESS_CACHE_NO_INTERNAL_STORE
    /* the default cache mode is just SSL_SESS_CACHE_SERVER */
    SSL_CTX_set_session_cache_mode(section->ctx,
        SSL_SESS_CACHE_SERVER|SSL_SESS_CACHE_NO_INTERNAL_STORE);
#endif
    SSL_CTX_sess_set_cache_size(section->ctx, section->session_size);
    SSL_CTX_set_timeout(section->ctx, section->session_timeout);
    SSL_CTX_sess_set_new_cb(section->ctx, sess_new_cb);
    SSL_CTX_sess_set_get_cb(section->ctx, sess_get_cb);
    SSL_CTX_sess_set_remove_cb(section->ctx, sess_remove_cb);

    /* set info callback */
    SSL_CTX_set_info_callback(section->ctx, info_callback);

    /* ciphers, options, mode */
    if(section->cipher_list)
        if(!SSL_CTX_set_cipher_list(section->ctx, section->cipher_list)) {
            sslerror("SSL_CTX_set_cipher_list");
            return 1; /* FAILED */
        }
    SSL_CTX_set_options(section->ctx,
        (SSL_OPTIONS_TYPE)(section->ssl_options_set));
#if OPENSSL_VERSION_NUMBER>=0x009080dfL
    SSL_CTX_clear_options(section->ctx,
        (SSL_OPTIONS_TYPE)(section->ssl_options_clear));
    s_log(LOG_DEBUG, "SSL options: 0x%08lX (+0x%08lX, -0x%08lX)",
        SSL_CTX_get_options(section->ctx),
        section->ssl_options_set, section->ssl_options_clear);
#else /* OpenSSL older than 0.9.8m */
    s_log(LOG_DEBUG, "SSL options: 0x%08lX (+0x%08lX)",
        SSL_CTX_get_options(section->ctx),
        section->ssl_options_set);
#endif /* OpenSSL 0.9.8m or later */

    /* initialize OpenSSL CONF options */
    if(conf_init(section))
        return 1; /* FAILED */

#ifdef SSL_MODE_RELEASE_BUFFERS
    SSL_CTX_set_mode(section->ctx,
        SSL_MODE_ENABLE_PARTIAL_WRITE |
        SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
        SSL_MODE_RELEASE_BUFFERS);
#else
    SSL_CTX_set_mode(section->ctx,
        SSL_MODE_ENABLE_PARTIAL_WRITE |
        SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
#endif
    return 0; /* OK */
}
Exemple #13
0
long SSL_CTX_get_options_shim(SSL_CTX *ctx) {
    return SSL_CTX_get_options(ctx);
}
Exemple #14
0
rb_ssl_ctx *
rb_setup_ssl_server(const char *cacert, const char *cert, const char *keyfile, const char *dhfile,
		    const char *ssl_cipher_list, const char *named_curve, rb_tls_ver_t tls_min_ver)
{
        const char *libratbox_data = "libratbox tls session";
	const char *ciphers = "kEECDH+HIGH:kEDH+HIGH:HIGH:!RC4:!aNULL";
	unsigned long err;
	rb_ssl_ctx *sctx; 
	long tls_opts;
	sctx = rb_malloc(sizeof(rb_ssl_ctx));
	sctx->refcount = 1;
	sctx->ssl_ctx = SSL_CTX_new(SSLv23_server_method());
	if(sctx->ssl_ctx == NULL)
	{
		rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL server context: %s",
			   ERR_error_string(ERR_get_error(), NULL));
		rb_free(sctx);
		return NULL;
	}

	tls_opts = SSL_CTX_get_options(sctx->ssl_ctx);
	/* Disable SSLv2, make the client use our settings */
	tls_opts |= SSL_OP_NO_SSLv2 | SSL_OP_NO_COMPRESSION | SSL_OP_CIPHER_SERVER_PREFERENCE;
	switch(tls_min_ver)
	{
		case RB_TLS_VER_SSL3: /* we default to SSLv3..sadly */
			break;
			
		case RB_TLS_VER_TLS1:
#ifdef SSL_OP_NO_SSLv3
			tls_opts |= SSL_OP_NO_SSLv3;
#endif
			break;
		case RB_TLS_VER_TLS1_1:
#ifdef SSL_OP_NO_TLSv1
			tls_opts |= SSL_OP_NO_TLSv1;
#endif
			break;

		case RB_TLS_VER_TLS1_2:
#ifdef SSL_OP_NO_TLSv1
			tls_opts |= SSL_OP_NO_TLSv1;
#endif
#ifdef SSL_OP_NO_TLSv1_1
			tls_opts |= SSL_OP_NO_TLSv1_1;
#endif
			break;
		case RB_TLS_VER_LAST:
			break;
	}

#ifdef SSL_OP_SINGLE_DH_USE
	tls_opts |= SSL_OP_SINGLE_DH_USE;
#endif

#ifdef SSL_OP_SINGLE_ECDH_USE
	tls_opts |= SSL_OP_SINGLE_ECDH_USE;
#endif

#ifdef SSL_OP_NO_TICKET
	tls_opts |= SSL_OP_NO_TICKET;
#endif

	SSL_CTX_set_options(sctx->ssl_ctx, tls_opts);


	if(ssl_cipher_list != NULL)
		ciphers = ssl_cipher_list;

	if(!SSL_CTX_set_cipher_list(sctx->ssl_ctx, ciphers))
	{
		rb_lib_log("rb_setup_ssl_server: Error setting ssl_cipher_list=\"%s\": %s",
			   ciphers, ERR_error_string(ERR_get_error(), NULL));
		goto cleanup;;
	}


	if(cert == NULL)
	{
		rb_lib_log("rb_setup_ssl_server: No certificate file");
		goto cleanup;
	}
	if(!SSL_CTX_use_certificate_chain_file(sctx->ssl_ctx, cert))
	{
		err = ERR_get_error();
		rb_lib_log("rb_setup_ssl_server: Error loading certificate file [%s]: %s", cert,
			   ERR_error_string(err, NULL));
		goto cleanup;
	}
	
	if(cacert != NULL)
	{
		if (!SSL_CTX_load_verify_locations(sctx->ssl_ctx, cacert, NULL)) 
		{
			err = ERR_get_error();
			rb_lib_log("rb_setup_ssl_server: Error loading CA file [%s]: %s", cacert, ERR_error_string(err, NULL));
			goto cleanup;
		}
	}

	if(keyfile == NULL)
	{
		rb_lib_log("rb_setup_ssl_server: No key file");
		goto cleanup;
	}


	if(!SSL_CTX_use_PrivateKey_file(sctx->ssl_ctx, keyfile, SSL_FILETYPE_PEM))
	{
		err = ERR_get_error();
		rb_lib_log("rb_setup_ssl_server: Error loading keyfile [%s]: %s", keyfile,
			   ERR_error_string(err, NULL));
		goto cleanup;;
	}


	if(dhfile != NULL)
	{
		/* DH parameters aren't necessary, but they are nice..if they didn't pass one..that is their problem */
		BIO *bio = BIO_new_file(dhfile, "r");
		if(bio != NULL)
		{
			DH *dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
			if(dh == NULL)
			{
				err = ERR_get_error();
				rb_lib_log
					("rb_setup_ssl_server: Error loading DH params file [%s]: %s",
					 dhfile, ERR_error_string(err, NULL));
				BIO_free(bio);
				goto cleanup;
			}
			BIO_free(bio);
			SSL_CTX_set_tmp_dh(sctx->ssl_ctx, dh);
			DH_free(dh);
		}
		else
		{
			err = ERR_get_error();
			rb_lib_log("rb_setup_ssl_server: Error loading DH params file [%s]: %s",
				   dhfile, ERR_error_string(err, NULL));
			goto cleanup;	  
		}
	}

#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
#ifndef OPENSSL_NO_ECDH
	
	if(named_curve != NULL)
	{
		int nid;
		EC_KEY *ecdh;
		
		nid = OBJ_sn2nid(named_curve);
		if(nid == 0)
		{
			err = ERR_get_error();
			rb_lib_log("rb_setup_ssl_server: Unknown curve named [%s]: %s", named_curve, ERR_error_string(err, NULL));
			goto cleanup;
		}
		
		ecdh = EC_KEY_new_by_curve_name(nid);
		if(ecdh == NULL)
		{
			err = ERR_get_error();
			rb_lib_log("rb_setup_ssl_server: Curve creation failed for [%s]: %s", named_curve, ERR_error_string(err, NULL));
			goto cleanup;
		}
		SSL_CTX_set_options(sctx->ssl_ctx, SSL_OP_SINGLE_ECDH_USE);
		SSL_CTX_set_tmp_ecdh(sctx->ssl_ctx, ecdh);
		EC_KEY_free(ecdh);
	}
#endif
#endif
	SSL_CTX_set_verify(sctx->ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, verify_accept_all_cb);
	SSL_CTX_set_session_id_context(sctx->ssl_ctx, (const unsigned char *)libratbox_data, strlen(libratbox_data));
	return sctx;

cleanup:
	SSL_CTX_free(sctx->ssl_ctx);
	rb_free(sctx);
	return NULL;
		
	
}
Exemple #15
0
int
rb_init_ssl(void)
{
	int ret = 1;
	char libratbox_data[] = "libratbox data";
	const char libratbox_ciphers[] = "kEECDH+HIGH:kEDH+HIGH:HIGH:!RC4:!aNULL";
	SSL_load_error_strings();
	SSL_library_init();
	libratbox_index = SSL_get_ex_new_index(0, libratbox_data, NULL, NULL, NULL);

#if defined(LIBRESSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x10100000L)
	ssl_server_ctx = SSL_CTX_new(SSLv23_server_method());
#else
	ssl_server_ctx = SSL_CTX_new(TLS_server_method());
#endif

	if(ssl_server_ctx == NULL)
	{
		rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL server context: %s",
			   get_ssl_error(ERR_get_error()));
		ret = 0;
	}

	long server_options = SSL_CTX_get_options(ssl_server_ctx);

#if defined(LIBRESSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x10100000L)
	server_options |= SSL_OP_NO_SSLv2;
	server_options |= SSL_OP_NO_SSLv3;
#endif

#ifdef SSL_OP_SINGLE_DH_USE
	server_options |= SSL_OP_SINGLE_DH_USE;
#endif

#ifdef SSL_OP_SINGLE_ECDH_USE
	server_options |= SSL_OP_SINGLE_ECDH_USE;
#endif

#ifdef SSL_OP_NO_TICKET
	server_options |= SSL_OP_NO_TICKET;
#endif

	server_options |= SSL_OP_CIPHER_SERVER_PREFERENCE;

	SSL_CTX_set_options(ssl_server_ctx, server_options);
	SSL_CTX_set_verify(ssl_server_ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, verify_accept_all_cb);
	SSL_CTX_set_session_cache_mode(ssl_server_ctx, SSL_SESS_CACHE_OFF);
	SSL_CTX_set_cipher_list(ssl_server_ctx, libratbox_ciphers);

	/* Set ECDHE on OpenSSL 1.00+, but make sure it's actually available because redhat are dicks
	   and bastardise their OpenSSL for stupid reasons... */
	#if (OPENSSL_VERSION_NUMBER >= 0x10000000L) && defined(NID_secp384r1)
		EC_KEY *key = EC_KEY_new_by_curve_name(NID_secp384r1);
		if (key) {
			SSL_CTX_set_tmp_ecdh(ssl_server_ctx, key);
			EC_KEY_free(key);
		}
	#endif

#if defined(LIBRESSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x10100000L)
	ssl_client_ctx = SSL_CTX_new(TLSv1_client_method());
#else
	ssl_client_ctx = SSL_CTX_new(TLS_client_method());
#endif

	if(ssl_client_ctx == NULL)
	{
		rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL client context: %s",
			   get_ssl_error(ERR_get_error()));
		ret = 0;
	}

#ifdef SSL_OP_NO_TICKET
	SSL_CTX_set_options(ssl_client_ctx, SSL_OP_NO_TICKET);
#endif

	SSL_CTX_set_cipher_list(ssl_client_ctx, libratbox_ciphers);

	return ret;
}
Exemple #16
0
static int ssl_servername_cb(SSL *cnx, int *al, void *arg)
{
    CertResult  result;
    const char *sni_name;

    (void) al;
    (void) arg;
    if ((sni_name = SSL_get_servername(cnx, TLSEXT_NAMETYPE_host_name))
        == NULL || *sni_name == 0 || validate_sni_name(sni_name) != 0) {
        return SSL_TLSEXT_ERR_NOACK;
    }
    logfile(LOG_INFO, "SNI: [%s]", sni_name);
    if (chrooted != 0 || loggedin != 0) {
        return SSL_TLSEXT_ERR_NOACK;
    }
    if (use_extcert == 0) {
        return SSL_TLSEXT_ERR_OK;
    }
    memset(&result, 0, sizeof result);
    tls_extcert_get(&result, sni_name);
    if (result.cert_ok != 1) {
        die(400, LOG_ERR, "Cert handler not ready");
    }
    if (result.action == CERT_ACTION_DENY) {
        die(400, LOG_INFO, MSG_LOGOUT);
    }
    if (result.action == CERT_ACTION_DEFAULT) {
        return SSL_TLSEXT_ERR_OK;
    }
    if (result.cert_file == NULL) {
        if (result.action == CERT_ACTION_STRICT) {
            die(400, LOG_ERR, "Missing certificate");
        } else {
            return SSL_TLSEXT_ERR_OK;
        }
    }
    if (result.key_file == NULL) {
        result.key_file = result.cert_file;
    }
    SSL_CTX_free(tls_ctx);
    tls_ctx = NULL;
    if (tls_create_new_context(result.cert_file, result.key_file) != 0) {
        if (result.action != CERT_ACTION_FALLBACK) {
            die(400, LOG_ERR, "Invalid certificate");
        }
        if (tls_create_new_context(cert_file, key_file) != 0) {
            die(400, LOG_ERR, "SSL error");
        }
    }
    if ((client_sni_name = strdup(sni_name)) == NULL) {
        die_mem();
    }
    if (tls_cnx != NULL) {
        const long ctx_options = SSL_CTX_get_options(tls_ctx);
        SSL_set_SSL_CTX(tls_cnx, tls_ctx);
# ifdef SSL_CTRL_CLEAR_OPTIONS
        SSL_clear_options(tls_cnx,
                          SSL_get_options(tls_cnx) & ~ctx_options);
# endif
        SSL_set_options(tls_cnx, ctx_options);
    }
    if (tls_data_cnx != NULL) {
        const long ctx_options = SSL_CTX_get_options(tls_ctx);
        SSL_set_SSL_CTX(tls_data_cnx, tls_ctx);
# ifdef SSL_CTRL_CLEAR_OPTIONS
        SSL_clear_options(tls_data_cnx,
                          SSL_get_options(tls_cnx) & ~ctx_options);
# endif
        SSL_set_options(tls_data_cnx, ctx_options);
    }
    return SSL_TLSEXT_ERR_OK;
}
Exemple #17
0
static Ecore_Con_Ssl_Error
_ecore_con_ssl_server_prepare_openssl(Ecore_Con_Server *svr,
                                      int               ssl_type)
{
   long options;
   int dh = 0;

   if (ssl_type & ECORE_CON_USE_SSL2)
     return ECORE_CON_SSL_ERROR_SSL2_NOT_SUPPORTED;

   switch (ssl_type)
     {
      case ECORE_CON_USE_SSL3:
      case ECORE_CON_USE_SSL3 | ECORE_CON_LOAD_CERT:
        if (!svr->created)
          SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl_ctx = SSL_CTX_new(SSLv3_client_method())));
        else
          SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl_ctx = SSL_CTX_new(SSLv3_server_method())));
        break;

      case ECORE_CON_USE_TLS:
      case ECORE_CON_USE_TLS | ECORE_CON_LOAD_CERT:
        if (!svr->created)
          SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl_ctx = SSL_CTX_new(TLSv1_client_method())));
        else
          SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl_ctx = SSL_CTX_new(TLSv1_server_method())));
        break;

      case ECORE_CON_USE_MIXED:
      case ECORE_CON_USE_MIXED | ECORE_CON_LOAD_CERT:
        if (!svr->created)
          SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl_ctx = SSL_CTX_new(SSLv23_client_method())));
        else
          SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl_ctx = SSL_CTX_new(SSLv23_server_method())));
        options = SSL_CTX_get_options(svr->ssl_ctx);
        SSL_CTX_set_options(svr->ssl_ctx, options | SSL_OP_NO_SSLv2 | SSL_OP_SINGLE_DH_USE);
        break;

      default:
        return ECORE_CON_SSL_ERROR_NONE;
     }

   if ((!svr->use_cert) && svr->created)
     {
        DH *dh_params;
        INF("Generating DH params");
        SSL_ERROR_CHECK_GOTO_ERROR(!(dh_params = DH_new()));
        SSL_ERROR_CHECK_GOTO_ERROR(!DH_generate_parameters_ex(dh_params, 1024, DH_GENERATOR_5, NULL));
        SSL_ERROR_CHECK_GOTO_ERROR(!DH_check(dh_params, &dh));
        SSL_ERROR_CHECK_GOTO_ERROR((dh & DH_CHECK_P_NOT_PRIME) || (dh & DH_CHECK_P_NOT_SAFE_PRIME));
        SSL_ERROR_CHECK_GOTO_ERROR(!DH_generate_key(dh_params));
        SSL_ERROR_CHECK_GOTO_ERROR(!SSL_CTX_set_tmp_dh(svr->ssl_ctx, dh_params));
        DH_free(dh_params);
        INF("DH params successfully generated and applied!");
        SSL_ERROR_CHECK_GOTO_ERROR(!SSL_CTX_set_cipher_list(svr->ssl_ctx, "aNULL:!eNULL:!LOW:!EXPORT:@STRENGTH"));
     }
   else if (!svr->use_cert)
     SSL_ERROR_CHECK_GOTO_ERROR(!SSL_CTX_set_cipher_list(svr->ssl_ctx, "aNULL:!eNULL:!LOW:!EXPORT:!ECDH:RSA:AES:!PSK:@STRENGTH"));

   return ECORE_CON_SSL_ERROR_NONE;

error:
   if (dh)
     {
        if (dh & DH_CHECK_P_NOT_PRIME)
          ERR("openssl error: dh_params could not generate a prime!");
        else
          ERR("openssl error: dh_params could not generate a safe prime!");
     }
   else
     _openssl_print_errors();
   _ecore_con_ssl_server_shutdown_openssl(svr);
   return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
}
Exemple #18
0
LWS_VISIBLE int
lws_context_init_server_ssl(struct lws_context_creation_info *info,
			    struct lws_vhost *vhost)
{
	struct lws_context *context = vhost->context;
	struct lws wsi;
	unsigned long error;
	int n;

	if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT)) {
		vhost->use_ssl = 0;
		return 0;
	}

	/*
	 * If he is giving a cert filepath, take it as a sign he wants to use
	 * it on this vhost.  User code can leave the cert filepath NULL and
	 * set the LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX option itself, in
	 * which case he's expected to set up the cert himself at
	 * LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS, which
	 * provides the vhost SSL_CTX * in the user parameter.
	 */
	if (info->ssl_cert_filepath)
		info->options |= LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX;

	if (info->port != CONTEXT_PORT_NO_LISTEN) {

		vhost->use_ssl = lws_check_opt(info->options,
					LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX);

		if (vhost->use_ssl && info->ssl_cipher_list)
			lwsl_notice(" SSL ciphers: '%s'\n", info->ssl_cipher_list);

		if (vhost->use_ssl)
			lwsl_notice(" Using SSL mode\n");
		else
			lwsl_notice(" Using non-SSL mode\n");
	}

	/*
	 * give him a fake wsi with context + vhost set, so he can use
	 * lws_get_context() in the callback
	 */
	memset(&wsi, 0, sizeof(wsi));
	wsi.vhost = vhost;
	wsi.context = context;

	(void)n;
	(void)error;

	/*
	 * Firefox insists on SSLv23 not SSLv3
	 * Konq disables SSLv2 by default now, SSLv23 works
	 *
	 * SSLv23_server_method() is the openssl method for "allow all TLS
	 * versions", compared to e.g. TLSv1_2_server_method() which only allows
	 * tlsv1.2. Unwanted versions must be disabled using SSL_CTX_set_options()
	 */
#if !defined(LWS_WITH_MBEDTLS)
	{
		SSL_METHOD *method;

		method = (SSL_METHOD *)SSLv23_server_method();
		if (!method) {
			error = ERR_get_error();
			lwsl_err("problem creating ssl method %lu: %s\n",
					error, ERR_error_string(error,
					      (char *)context->pt[0].serv_buf));
			return 1;
		}
		vhost->ssl_ctx = SSL_CTX_new(method);	/* create context */
		if (!vhost->ssl_ctx) {
			error = ERR_get_error();
			lwsl_err("problem creating ssl context %lu: %s\n",
					error, ERR_error_string(error,
					      (char *)context->pt[0].serv_buf));
			return 1;
		}
	}
#else
	{
		const SSL_METHOD *method = TLSv1_2_server_method();

		vhost->ssl_ctx = SSL_CTX_new(method);	/* create context */
		if (!vhost->ssl_ctx) {
			lwsl_err("problem creating ssl context\n");
			return 1;
		}

	}
#endif
#if !defined(LWS_WITH_MBEDTLS)

	/* associate the lws context with the SSL_CTX */

	SSL_CTX_set_ex_data(vhost->ssl_ctx,
			openssl_SSL_CTX_private_data_index, (char *)vhost->context);
	/* Disable SSLv2 and SSLv3 */
	SSL_CTX_set_options(vhost->ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
#ifdef SSL_OP_NO_COMPRESSION
	SSL_CTX_set_options(vhost->ssl_ctx, SSL_OP_NO_COMPRESSION);
#endif
	SSL_CTX_set_options(vhost->ssl_ctx, SSL_OP_SINGLE_DH_USE);
	SSL_CTX_set_options(vhost->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);

	if (info->ssl_cipher_list)
		SSL_CTX_set_cipher_list(vhost->ssl_ctx,
						info->ssl_cipher_list);
#endif

	/* as a server, are we requiring clients to identify themselves? */

	if (lws_check_opt(info->options,
			  LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT)) {
		int verify_options = SSL_VERIFY_PEER;

		if (!lws_check_opt(info->options,
				   LWS_SERVER_OPTION_PEER_CERT_NOT_REQUIRED))
			verify_options |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;

#if !defined(LWS_WITH_MBEDTLS)
		SSL_CTX_set_session_id_context(vhost->ssl_ctx,
				(unsigned char *)context, sizeof(void *));

		/* absolutely require the client cert */

		SSL_CTX_set_verify(vhost->ssl_ctx,
		       verify_options, OpenSSL_verify_callback);
#endif
	}

#if !defined(LWS_WITH_MBEDTLS) && !defined(OPENSSL_NO_TLSEXT)
	SSL_CTX_set_tlsext_servername_callback(vhost->ssl_ctx,
					       lws_ssl_server_name_cb);
	SSL_CTX_set_tlsext_servername_arg(vhost->ssl_ctx, context);
#endif

	/*
	 * give user code a chance to load certs into the server
	 * allowing it to verify incoming client certs
	 */
#if !defined(LWS_WITH_MBEDTLS)
	if (info->ssl_ca_filepath &&
	    !SSL_CTX_load_verify_locations(vhost->ssl_ctx,
					   info->ssl_ca_filepath, NULL)) {
		lwsl_err("%s: SSL_CTX_load_verify_locations unhappy\n", __func__);
	}
#endif
	if (vhost->use_ssl) {
		if (lws_context_ssl_init_ecdh_curve(info, vhost))
			return -1;

		vhost->protocols[0].callback(&wsi,
			LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS,
			vhost->ssl_ctx, NULL, 0);
	}

	if (lws_check_opt(info->options, LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT))
		/* Normally SSL listener rejects non-ssl, optionally allow */
		vhost->allow_non_ssl_on_ssl_port = 1;

	if (info->ssl_options_set)
		SSL_CTX_set_options(vhost->ssl_ctx, info->ssl_options_set);

/* SSL_clear_options introduced in 0.9.8m */
#if !defined(LWS_WITH_MBEDTLS)
#if (OPENSSL_VERSION_NUMBER >= 0x009080df) && !defined(USE_WOLFSSL)
	if (info->ssl_options_clear)
		SSL_CTX_clear_options(vhost->ssl_ctx, info->ssl_options_clear);
#endif
#endif

	lwsl_info(" SSL options 0x%lX\n", SSL_CTX_get_options(vhost->ssl_ctx));

	if (vhost->use_ssl && info->ssl_cert_filepath) {
		/*
		 * The user code can choose to either pass the cert and
		 * key filepaths using the info members like this, or it can
		 * leave them NULL; force the vhost SSL_CTX init using the info
		 * options flag LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX; and
		 * set up the cert himself using the user callback
		 * LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS, which
		 * happened just above and has the vhost SSL_CTX * in the user
		 * parameter.
		 */
#if !defined(LWS_WITH_MBEDTLS)
		/* set the local certificate from CertFile */
		n = SSL_CTX_use_certificate_chain_file(vhost->ssl_ctx,
					info->ssl_cert_filepath);
		if (n != 1) {
			error = ERR_get_error();
			lwsl_err("problem getting cert '%s' %lu: %s\n",
				info->ssl_cert_filepath,
				error,
				ERR_error_string(error,
					      (char *)context->pt[0].serv_buf));
			return 1;
		}
		lws_ssl_bind_passphrase(vhost->ssl_ctx, info);
#else
		uint8_t *p;
		lws_filepos_t flen;
		int err;

		if (alloc_pem_to_der_file(vhost->context, info->ssl_cert_filepath, &p,
				                &flen)) {
			lwsl_err("couldn't find cert file %s\n",
				 info->ssl_cert_filepath);

			return 1;
		}
		err = SSL_CTX_use_certificate_ASN1(vhost->ssl_ctx, flen, p);
		if (!err) {
			lwsl_err("Problem loading cert\n");
			return 1;
		}
#if !defined(LWS_WITH_ESP32)
		free(p);
		p = NULL;
#endif

		if (info->ssl_private_key_filepath) {
			if (alloc_pem_to_der_file(vhost->context,
				       info->ssl_private_key_filepath, &p, &flen)) {
				lwsl_err("couldn't find cert file %s\n",
					 info->ssl_cert_filepath);

				return 1;
			}
			err = SSL_CTX_use_PrivateKey_ASN1(0, vhost->ssl_ctx, p, flen);
			if (!err) {
				lwsl_err("Problem loading key\n");

				return 1;
			}
		}

#if !defined(LWS_WITH_ESP32)
		free(p);
		p = NULL;
#endif
#endif
		if (info->ssl_private_key_filepath != NULL) {
#if !defined(LWS_WITH_MBEDTLS)
			/* set the private key from KeyFile */
			if (SSL_CTX_use_PrivateKey_file(vhost->ssl_ctx,
				     info->ssl_private_key_filepath,
						       SSL_FILETYPE_PEM) != 1) {
				error = ERR_get_error();
				lwsl_err("ssl problem getting key '%s' %lu: %s\n",
					 info->ssl_private_key_filepath, error,
					 ERR_error_string(error,
					      (char *)context->pt[0].serv_buf));
				return 1;
			}
#endif
		} else
			if (vhost->protocols[0].callback(&wsi,
				LWS_CALLBACK_OPENSSL_CONTEXT_REQUIRES_PRIVATE_KEY,
				vhost->ssl_ctx, NULL, 0)) {
				lwsl_err("ssl private key not set\n");

				return 1;
			}
#if !defined(LWS_WITH_MBEDTLS)
		/* verify private key */
		if (!SSL_CTX_check_private_key(vhost->ssl_ctx)) {
			lwsl_err("Private SSL key doesn't match cert\n");
			return 1;
		}
#endif
	}
	if (vhost->use_ssl) {
		if (lws_context_ssl_init_ecdh(vhost))
			return 1;

		/*
		 * SSL is happy and has a cert it's content with
		 * If we're supporting HTTP2, initialize that
		 */
		lws_context_init_http2_ssl(vhost);
	}

	return 0;
}
long SslContext::getOptions()
{
    return SSL_CTX_get_options(m_pCtx);
}
Exemple #20
0
/*
 * this may now get called after the vhost creation, when certs become
 * available.
 */
int
lws_tls_server_certs_load(struct lws_vhost *vhost, struct lws *wsi,
			  const char *cert, const char *private_key,
			  const char *mem_cert, size_t mem_cert_len,
			  const char *mem_privkey, size_t mem_privkey_len)
{
#if !defined(OPENSSL_NO_EC)
	const char *ecdh_curve = "prime256v1";
#if !defined(LWS_WITH_BORINGSSL) && defined(LWS_HAVE_SSL_EXTRA_CHAIN_CERTS)
	STACK_OF(X509) *extra_certs = NULL;
#endif
	EC_KEY *ecdh, *EC_key = NULL;
	EVP_PKEY *pkey;
	X509 *x = NULL;
	int ecdh_nid;
	int KeyType;
#endif
	unsigned long error;
	lws_filepos_t flen;
	uint8_t *p;
	int ret;

	int n = lws_tls_generic_cert_checks(vhost, cert, private_key), m;

	(void)ret;

	if (!cert && !private_key)
		n = LWS_TLS_EXTANT_ALTERNATIVE;

	if (n == LWS_TLS_EXTANT_NO && (!mem_cert || !mem_privkey))
		return 0;
	if (n == LWS_TLS_EXTANT_NO)
		n = LWS_TLS_EXTANT_ALTERNATIVE;

	if (n == LWS_TLS_EXTANT_ALTERNATIVE && (!mem_cert || !mem_privkey))
		return 1; /* no alternative */

	if (n == LWS_TLS_EXTANT_ALTERNATIVE) {

#if OPENSSL_VERSION_NUMBER >= 0x10100000L

		/*
		 * Although we have prepared update certs, we no longer have
		 * the rights to read our own cert + key we saved.
		 *
		 * If we were passed copies in memory buffers, use those
		 * in favour of the filepaths we normally want.
		 */
		cert = NULL;
		private_key = NULL;
	}

	/*
	 * use the multi-cert interface for backwards compatibility in the
	 * both simple files case
	 */

	if (n != LWS_TLS_EXTANT_ALTERNATIVE && cert) {

		/* set the local certificate from CertFile */
		m = SSL_CTX_use_certificate_chain_file(vhost->tls.ssl_ctx, cert);
		if (m != 1) {
			error = ERR_get_error();
			lwsl_err("problem getting cert '%s' %lu: %s\n",
				 cert, error, ERR_error_string(error,
				       (char *)vhost->context->pt[0].serv_buf));

			return 1;
		}

		if (private_key) {
			/* set the private key from KeyFile */
			if (SSL_CTX_use_PrivateKey_file(vhost->tls.ssl_ctx, private_key,
							SSL_FILETYPE_PEM) != 1) {
				error = ERR_get_error();
				lwsl_err("ssl problem getting key '%s' %lu: %s\n",
					 private_key, error,
					 ERR_error_string(error,
					      (char *)vhost->context->pt[0].serv_buf));
				return 1;
			}
		} else {
			if (vhost->protocols[0].callback(wsi,
				      LWS_CALLBACK_OPENSSL_CONTEXT_REQUIRES_PRIVATE_KEY,
							 vhost->tls.ssl_ctx, NULL, 0)) {
				lwsl_err("ssl private key not set\n");

				return 1;
			}
		}

		return 0;
	}

	/* otherwise allow for DER or PEM, file or memory image */

	if (lws_tls_alloc_pem_to_der_file(vhost->context, cert, mem_cert,
					  mem_cert_len, &p, &flen)) {
		lwsl_err("%s: couldn't read cert file\n", __func__);

		return 1;
	}

#if !defined(USE_WOLFSSL)
	ret = SSL_CTX_use_certificate_ASN1(vhost->tls.ssl_ctx, (int)flen, p);
#else
	ret = wolfSSL_CTX_use_certificate_buffer(vhost->tls.ssl_ctx,
						 (uint8_t *)p, (int)flen,
						 WOLFSSL_FILETYPE_ASN1);
#endif
	lws_free_set_NULL(p);
	if (ret != 1) {
		lwsl_err("%s: Problem loading cert\n", __func__);

		return 1;
	}

	if (lws_tls_alloc_pem_to_der_file(vhost->context, private_key,
					  mem_privkey, mem_privkey_len,
					  &p, &flen)) {
		lwsl_notice("unable to convert memory privkey\n");

		return 1;
	}

#if !defined(USE_WOLFSSL)
	ret = SSL_CTX_use_PrivateKey_ASN1(EVP_PKEY_RSA, vhost->tls.ssl_ctx, p,
					  (long)(long long)flen);
	if (ret != 1) {
		ret = SSL_CTX_use_PrivateKey_ASN1(EVP_PKEY_EC,
						  vhost->tls.ssl_ctx, p,
						  (long)(long long)flen);
	}
#else
	ret = wolfSSL_CTX_use_PrivateKey_buffer(vhost->tls.ssl_ctx, p, flen,
						WOLFSSL_FILETYPE_ASN1);
#endif
	lws_free_set_NULL(p);
	if (ret != 1)  {
		lwsl_notice("unable to use memory privkey\n");

		return 1;
	}

#else
		/*
		 * Although we have prepared update certs, we no longer have
		 * the rights to read our own cert + key we saved.
		 *
		 * If we were passed copies in memory buffers, use those
		 * instead.
		 *
		 * The passed memory-buffer cert image is in DER, and the
		 * memory-buffer private key image is PEM.
		 */
#ifndef USE_WOLFSSL
		if (SSL_CTX_use_certificate_ASN1(vhost->tls.ssl_ctx,
						 (int)mem_cert_len,
						 (uint8_t *)mem_cert) != 1) {
#else
		if (wolfSSL_CTX_use_certificate_buffer(vhost->tls.ssl_ctx,
						 (uint8_t *)mem_cert,
						 (int)mem_cert_len,
						 WOLFSSL_FILETYPE_ASN1) != 1) {

#endif
			lwsl_err("Problem loading update cert\n");

			return 1;
		}

		if (lws_tls_alloc_pem_to_der_file(vhost->context, NULL,
						  mem_privkey, mem_privkey_len,
						  &p, &flen)) {
			lwsl_notice("unable to convert memory privkey\n");

			return 1;
		}
#ifndef USE_WOLFSSL
		if (SSL_CTX_use_PrivateKey_ASN1(EVP_PKEY_RSA,
						vhost->tls.ssl_ctx, p,
						(long)(long long)flen) != 1) {
#else
		if (wolfSSL_CTX_use_PrivateKey_buffer(vhost->tls.ssl_ctx, p,
					    flen, WOLFSSL_FILETYPE_ASN1) != 1) {
#endif
			lwsl_notice("unable to use memory privkey\n");

			return 1;
		}

		goto check_key;
	}

	/* set the local certificate from CertFile */
	m = SSL_CTX_use_certificate_chain_file(vhost->tls.ssl_ctx, cert);
	if (m != 1) {
		error = ERR_get_error();
		lwsl_err("problem getting cert '%s' %lu: %s\n",
			 cert, error, ERR_error_string(error,
			       (char *)vhost->context->pt[0].serv_buf));

		return 1;
	}

	if (n != LWS_TLS_EXTANT_ALTERNATIVE && private_key) {
		/* set the private key from KeyFile */
		if (SSL_CTX_use_PrivateKey_file(vhost->tls.ssl_ctx, private_key,
					        SSL_FILETYPE_PEM) != 1) {
			error = ERR_get_error();
			lwsl_err("ssl problem getting key '%s' %lu: %s\n",
				 private_key, error,
				 ERR_error_string(error,
				      (char *)vhost->context->pt[0].serv_buf));
			return 1;
		}
	} else {
		if (vhost->protocols[0].callback(wsi,
			      LWS_CALLBACK_OPENSSL_CONTEXT_REQUIRES_PRIVATE_KEY,
						 vhost->tls.ssl_ctx, NULL, 0)) {
			lwsl_err("ssl private key not set\n");

			return 1;
		}
	}

check_key:
#endif

	/* verify private key */
	if (!SSL_CTX_check_private_key(vhost->tls.ssl_ctx)) {
		lwsl_err("Private SSL key doesn't match cert\n");

		return 1;
	}


#if !defined(OPENSSL_NO_EC)
	if (vhost->tls.ecdh_curve[0])
		ecdh_curve = vhost->tls.ecdh_curve;

	ecdh_nid = OBJ_sn2nid(ecdh_curve);
	if (NID_undef == ecdh_nid) {
		lwsl_err("SSL: Unknown curve name '%s'", ecdh_curve);
		return 1;
	}

	ecdh = EC_KEY_new_by_curve_name(ecdh_nid);
	if (NULL == ecdh) {
		lwsl_err("SSL: Unable to create curve '%s'", ecdh_curve);
		return 1;
	}
	SSL_CTX_set_tmp_ecdh(vhost->tls.ssl_ctx, ecdh);
	EC_KEY_free(ecdh);

	SSL_CTX_set_options(vhost->tls.ssl_ctx, SSL_OP_SINGLE_ECDH_USE);

	lwsl_notice(" SSL ECDH curve '%s'\n", ecdh_curve);

	if (lws_check_opt(vhost->context->options, LWS_SERVER_OPTION_SSL_ECDH))
		lwsl_notice(" Using ECDH certificate support\n");

	/* Get X509 certificate from ssl context */
#if !defined(LWS_WITH_BORINGSSL)
#if !defined(LWS_HAVE_SSL_EXTRA_CHAIN_CERTS)
	x = sk_X509_value(vhost->tls.ssl_ctx->extra_certs, 0);
#else
	SSL_CTX_get_extra_chain_certs_only(vhost->tls.ssl_ctx, &extra_certs);
	if (extra_certs)
		x = sk_X509_value(extra_certs, 0);
	else
		lwsl_info("%s: no extra certs\n", __func__);
#endif
	if (!x) {
		//lwsl_err("%s: x is NULL\n", __func__);
		goto post_ecdh;
	}
#else
	return 0;
#endif
	/* Get the public key from certificate */
	pkey = X509_get_pubkey(x);
	if (!pkey) {
		lwsl_err("%s: pkey is NULL\n", __func__);

		return 1;
	}
	/* Get the key type */
	KeyType = EVP_PKEY_type(EVP_PKEY_id(pkey));

	if (EVP_PKEY_EC != KeyType) {
		lwsl_notice("Key type is not EC\n");
		return 0;
	}
	/* Get the key */
	EC_key = EVP_PKEY_get1_EC_KEY(pkey);
	/* Set ECDH parameter */
	if (!EC_key) {
		lwsl_err("%s: ECDH key is NULL \n", __func__);
		return 1;
	}
	SSL_CTX_set_tmp_ecdh(vhost->tls.ssl_ctx, EC_key);

	EC_KEY_free(EC_key);
#else
	lwsl_notice(" OpenSSL doesn't support ECDH\n");
#endif
#if !defined(OPENSSL_NO_EC) && !defined(LWS_WITH_BORINGSSL)
post_ecdh:
#endif
	vhost->tls.skipped_certs = 0;

	return 0;
}

int
lws_tls_server_vhost_backend_init(const struct lws_context_creation_info *info,
				  struct lws_vhost *vhost, struct lws *wsi)
{
	unsigned long error;
	SSL_METHOD *method = (SSL_METHOD *)SSLv23_server_method();

	if (!method) {
		error = ERR_get_error();
		lwsl_err("problem creating ssl method %lu: %s\n",
				error, ERR_error_string(error,
				      (char *)vhost->context->pt[0].serv_buf));
		return 1;
	}
	vhost->tls.ssl_ctx = SSL_CTX_new(method);	/* create context */
	if (!vhost->tls.ssl_ctx) {
		error = ERR_get_error();
		lwsl_err("problem creating ssl context %lu: %s\n",
				error, ERR_error_string(error,
				      (char *)vhost->context->pt[0].serv_buf));
		return 1;
	}

	SSL_CTX_set_ex_data(vhost->tls.ssl_ctx,
			    openssl_SSL_CTX_private_data_index,
			    (char *)vhost->context);
	/* Disable SSLv2 and SSLv3 */
	SSL_CTX_set_options(vhost->tls.ssl_ctx, SSL_OP_NO_SSLv2 |
						SSL_OP_NO_SSLv3);
#ifdef SSL_OP_NO_COMPRESSION
	SSL_CTX_set_options(vhost->tls.ssl_ctx, SSL_OP_NO_COMPRESSION);
#endif
	SSL_CTX_set_options(vhost->tls.ssl_ctx, SSL_OP_SINGLE_DH_USE);
	SSL_CTX_set_options(vhost->tls.ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);

	if (info->ssl_cipher_list)
		SSL_CTX_set_cipher_list(vhost->tls.ssl_ctx, info->ssl_cipher_list);

#if defined(LWS_HAVE_SSL_CTX_set_ciphersuites)
	if (info->tls1_3_plus_cipher_list)
		SSL_CTX_set_ciphersuites(vhost->tls.ssl_ctx,
					 info->tls1_3_plus_cipher_list);
#endif

#if !defined(OPENSSL_NO_TLSEXT)
	SSL_CTX_set_tlsext_servername_callback(vhost->tls.ssl_ctx,
					       lws_ssl_server_name_cb);
	SSL_CTX_set_tlsext_servername_arg(vhost->tls.ssl_ctx, vhost->context);
#endif

	if (info->ssl_ca_filepath &&
	    !SSL_CTX_load_verify_locations(vhost->tls.ssl_ctx,
					   info->ssl_ca_filepath, NULL)) {
		lwsl_err("%s: SSL_CTX_load_verify_locations unhappy\n",
			 __func__);
	}

	if (info->ssl_options_set)
		SSL_CTX_set_options(vhost->tls.ssl_ctx, info->ssl_options_set);

/* SSL_clear_options introduced in 0.9.8m */
#if (OPENSSL_VERSION_NUMBER >= 0x009080df) && !defined(USE_WOLFSSL)
	if (info->ssl_options_clear)
		SSL_CTX_clear_options(vhost->tls.ssl_ctx,
				      info->ssl_options_clear);
#endif

	lwsl_info(" SSL options 0x%lX\n",
			(unsigned long)SSL_CTX_get_options(vhost->tls.ssl_ctx));
	if (!vhost->tls.use_ssl ||
	    (!info->ssl_cert_filepath && !info->server_ssl_cert_mem))
		return 0;

	lws_ssl_bind_passphrase(vhost->tls.ssl_ctx, info);

	return lws_tls_server_certs_load(vhost, wsi, info->ssl_cert_filepath,
					 info->ssl_private_key_filepath,
					 info->server_ssl_cert_mem,
					 info->server_ssl_cert_mem_len,
					 info->server_ssl_private_key_mem,
					 info->server_ssl_private_key_mem_len);
}