<commit_before>/* <x0/plugins/ssl/ssl.cpp>
 *
 * This file is part of the x0 web server project and is released under LGPL-3.
 * http://www.xzero.ws/
 *
 * (c) 2009-2010 <NAME> <<EMAIL>>
 */

#include "SslContext.h"
#include "SslDriver.h"
#include "SslSocket.h"
#include <x0/http/HttpPlugin.h>
#include <x0/http/HttpServer.h>
#include <x0/http/HttpListener.h>
#include <x0/http/HttpRequest.h>
#include <x0/http/HttpHeader.h>
#include <x0/io/BufferSource.h>
#include <x0/strutils.h>
#include <x0/Types.h>

#include <boost/lexical_cast.hpp>

#include <cstring>
#include <cerrno>
#include <cstddef>

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>

#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
#include <gnutls/extra.h>
#include <pthread.h>
#include <gcrypt.h>
GCRY_THREAD_OPTION_PTHREAD_IMPL;

#if 0
#	define TRACE(msg...) DEBUG("ssl: " msg)
#else
#	define TRACE(msg...) /*!*/
#endif


/*
 * possible flow API:
 *
 *     void ssl.listen('IP:PORT');
 *     void ssl.listen('IP:PORT', backlog);
 *     void ssl.listen('IP:PORT', backlog, defaultKey, defaultCrt);
 *
 *     void ssl.add(hostname, certfile, keyfile);
 *
 *
 * EXAMPLE:
 *     ssl.listen '0.0.0.0:8443';
 *
 *     ssl.add 'hostname' => 'www.trapni.de',
 *             'certfile' => '/path/to/my.crt',
 *             'keyfile' => '/path/to/my.key',
 *             'crlfile' => '/path/to/my.crl';
 *
 */

/**
 * \ingroup plugins
 * \brief SSL plugin
 */
class ssl_plugin :
	public x0::HttpPlugin,
	public SslContextSelector
{
public:
	ssl_plugin(x0::HttpServer& srv, const std::string& name) :
		x0::HttpPlugin(srv, name)
	{
		gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);

		int rv = gnutls_global_init();
		if (rv != GNUTLS_E_SUCCESS)
		{
			TRACE("gnutls_global_init: %s", gnutls_strerror(rv));
			return; //Error::CouldNotInitializeSslLibrary;
		}

		gnutls_global_init_extra();

		server().addComponent(std::string("GnuTLS/") + gnutls_check_version(nullptr));

		registerSetupFunction<ssl_plugin, &ssl_plugin::add_listener>("ssl.listen", x0::FlowValue::VOID);
		registerSetupFunction<ssl_plugin, &ssl_plugin::add_context>("ssl.context", x0::FlowValue::VOID);
		registerSetupProperty<ssl_plugin, &ssl_plugin::set_loglevel>("ssl.loglevel", x0::FlowValue::VOID);
	}

	~ssl_plugin()
	{
		gnutls_global_deinit();
	}

	std::vector<SslContext *> contexts_;

	/** select the SSL context based on host name or nullptr if nothing found. */
	virtual SslContext *select(const std::string& dnsName) const
	{
		if (dnsName.empty())
			return contexts_.front();

		for (auto i = contexts_.begin(), e = contexts_.end(); i != e; ++i)
		{
			SslContext *cx = *i;

			if (cx->isValidDnsName(dnsName))
			{
				TRACE("select SslContext: CN:%s, dnsName:%s", cx->commonName().c_str(), dnsName.c_str());<commit_msg>[plugins] ssl: close a minor context destruction leak<commit_after>/* <x0/plugins/ssl/ssl.cpp>
 *
 * This file is part of the x0 web server project and is released under LGPL-3.
 * http://www.xzero.ws/
 *
 * (c) 2009-2010 <NAME> <<EMAIL>>
 */

#include "SslContext.h"
#include "SslDriver.h"
#include "SslSocket.h"
#include <x0/http/HttpPlugin.h>
#include <x0/http/HttpServer.h>
#include <x0/http/HttpListener.h>
#include <x0/http/HttpRequest.h>
#include <x0/http/HttpHeader.h>
#include <x0/io/BufferSource.h>
#include <x0/strutils.h>
#include <x0/Types.h>

#include <boost/lexical_cast.hpp>

#include <cstring>
#include <cerrno>
#include <cstddef>

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>

#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
#include <gnutls/extra.h>
#include <pthread.h>
#include <gcrypt.h>
GCRY_THREAD_OPTION_PTHREAD_IMPL;

#if 0
#	define TRACE(msg...) DEBUG("ssl: " msg)
#else
#	define TRACE(msg...) /*!*/
#endif


/*
 * possible flow API:
 *
 *     void ssl.listen('IP:PORT');
 *     void ssl.listen('IP:PORT', backlog);
 *     void ssl.listen('IP:PORT', backlog, defaultKey, defaultCrt);
 *
 *     void ssl.add(hostname, certfile, keyfile);
 *
 *
 * EXAMPLE:
 *     ssl.listen '0.0.0.0:8443';
 *
 *     ssl.add 'hostname' => 'www.trapni.de',
 *             'certfile' => '/path/to/my.crt',
 *             'keyfile' => '/path/to/my.key',
 *             'crlfile' => '/path/to/my.crl';
 *
 */

/**
 * \ingroup plugins
 * \brief SSL plugin
 */
class ssl_plugin :
	public x0::HttpPlugin,
	public SslContextSelector
{
public:
	ssl_plugin(x0::HttpServer& srv, const std::string& name) :
		x0::HttpPlugin(srv, name)
	{
		gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);

		int rv = gnutls_global_init();
		if (rv != GNUTLS_E_SUCCESS)
		{
			TRACE("gnutls_global_init: %s", gnutls_strerror(rv));
			return; //Error::CouldNotInitializeSslLibrary;
		}

		gnutls_global_init_extra();

		server().addComponent(std::string("GnuTLS/") + gnutls_check_version(nullptr));

		registerSetupFunction<ssl_plugin, &ssl_plugin::add_listener>("ssl.listen", x0::FlowValue::VOID);
		registerSetupFunction<ssl_plugin, &ssl_plugin::add_context>("ssl.context", x0::FlowValue::VOID);
		registerSetupProperty<ssl_plugin, &ssl_plugin::set_loglevel>("ssl.loglevel", x0::FlowValue::VOID);
	}

	~ssl_plugin()
	{
		for (auto i: contexts_)
			delete i;

		gnutls_global_deinit();
	}

	std::vector<SslContext *> contexts_;

	/** select the SSL context based on host name or nullptr if nothing found. */
	virtual SslContext *select(const std::string& dnsName) const
	{
		if (dnsName.empty())
			return contexts_.front();

		for (auto i = contexts_.begin(), e = contexts_.end(); i != e; ++i)
		{
			SslContext *cx = *i;

			if (cx->isValidDnsName(dnsName))
			{
				TRACE("select SslContext: CN:%s, dnsName:%s", cx->commonName().c_str(), dnsName.c_str());
{'fraction_non_alphanumeric': 0.17641906096706378, 'fraction_numerical': 0.01296426068675543, 'mean_word_length': 4.208941605839416, 'pattern_counts': {'":': 0, '<': 61, '<?xml version=': 0, '>': 73, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5068583', 'n_tokens_mistral': 2349, 'n_tokens_neox': 2236, 'n_words': 414}