anope

- supernets anope source code & configuration
git clone git://git.acid.vegas/anope.git
Log | Files | Refs | Archive | README

m_ssl_openssl.cpp (11095B)

      1 /*
      2  *
      3  * (C) 2010-2022 Anope Team
      4  * Contact us at team@anope.org
      5  *
      6  * Please read COPYING and README for further details.
      7  */
      8 
      9 /* RequiredLibraries: ssl,crypto */
     10 /* RequiredWindowsLibraries: ssleay32,libeay32 */
     11 
     12 #include "module.h"
     13 #include "modules/ssl.h"
     14 
     15 #define OPENSSL_NO_SHA512
     16 #include <openssl/bio.h>
     17 #include <openssl/ssl.h>
     18 #include <openssl/err.h>
     19 #include <openssl/crypto.h>
     20 #include <openssl/evp.h>
     21 
     22 static SSL_CTX *server_ctx, *client_ctx;
     23 
     24 class MySSLService : public SSLService
     25 {
     26  public:
     27 	MySSLService(Module *o, const Anope::string &n);
     28 
     29 	/** Initialize a socket to use SSL
     30 	 * @param s The socket
     31 	 */
     32 	void Init(Socket *s) anope_override;
     33 };
     34 
     35 class SSLSocketIO : public SocketIO
     36 {
     37  public:
     38 	/* The SSL socket for this socket */
     39 	SSL *sslsock;
     40 
     41 	/** Constructor
     42 	 */
     43 	SSLSocketIO();
     44 
     45 	/** Really receive something from the buffer
     46 	 * @param s The socket
     47 	 * @param buf The buf to read to
     48 	 * @param sz How much to read
     49 	 * @return Number of bytes received
     50 	 */
     51 	int Recv(Socket *s, char *buf, size_t sz) anope_override;
     52 
     53 	/** Write something to the socket
     54 	 * @param s The socket
     55 	 * @param buf The data to write
     56 	 * @param size The length of the data
     57 	 */
     58 	int Send(Socket *s, const char *buf, size_t sz) anope_override;
     59 
     60 	/** Accept a connection from a socket
     61 	 * @param s The socket
     62 	 * @return The new socket
     63 	 */
     64 	ClientSocket *Accept(ListenSocket *s) anope_override;
     65 
     66 	/** Finished accepting a connection from a socket
     67 	 * @param s The socket
     68 	 * @return SF_ACCEPTED if accepted, SF_ACCEPTING if still in process, SF_DEAD on error
     69 	 */
     70 	SocketFlag FinishAccept(ClientSocket *cs) anope_override;
     71 
     72 	/** Connect the socket
     73 	 * @param s THe socket
     74 	 * @param target IP to connect to
     75 	 * @param port to connect to
     76 	 */
     77 	void Connect(ConnectionSocket *s, const Anope::string &target, int port) anope_override;
     78 
     79 	/** Called to potentially finish a pending connection
     80 	 * @param s The socket
     81 	 * @return SF_CONNECTED on success, SF_CONNECTING if still pending, and SF_DEAD on error.
     82 	 */
     83 	SocketFlag FinishConnect(ConnectionSocket *s) anope_override;
     84 
     85 	/** Called when the socket is destructing
     86 	 */
     87 	void Destroy() anope_override;
     88 };
     89 
     90 class SSLModule;
     91 static SSLModule *me;
     92 class SSLModule : public Module
     93 {
     94 	Anope::string certfile, keyfile;
     95 
     96  public:
     97 	MySSLService service;
     98 
     99 	SSLModule(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR), service(this, "ssl")
    100 	{
    101 		me = this;
    102 
    103 		this->SetPermanent(true);
    104 
    105 		SSL_library_init();
    106 		SSL_load_error_strings();
    107 
    108 		client_ctx = SSL_CTX_new(SSLv23_client_method());
    109 		server_ctx = SSL_CTX_new(SSLv23_server_method());
    110 
    111 		if (!client_ctx || !server_ctx)
    112 			throw ModuleException("Error initializing SSL CTX");
    113 
    114 		long opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_CIPHER_SERVER_PREFERENCE;
    115 		SSL_CTX_set_options(client_ctx, opts);
    116 		SSL_CTX_set_options(server_ctx, opts);
    117 
    118 		SSL_CTX_set_mode(client_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
    119 		SSL_CTX_set_mode(server_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
    120 
    121 		Anope::string context_name = "Anope";
    122 		SSL_CTX_set_session_id_context(client_ctx, reinterpret_cast<const unsigned char *>(context_name.c_str()), context_name.length());
    123 		SSL_CTX_set_session_id_context(server_ctx, reinterpret_cast<const unsigned char *>(context_name.c_str()), context_name.length());
    124 	}
    125 
    126 	~SSLModule()
    127 	{
    128 		for (std::map<int, Socket *>::const_iterator it = SocketEngine::Sockets.begin(), it_end = SocketEngine::Sockets.end(); it != it_end;)
    129 		{
    130 			Socket *s = it->second;
    131 			++it;
    132 
    133 			if (dynamic_cast<SSLSocketIO *>(s->io))
    134 				delete s;
    135 		}
    136 
    137 		SSL_CTX_free(client_ctx);
    138 		SSL_CTX_free(server_ctx);
    139 	}
    140 
    141 	void OnReload(Configuration::Conf *conf) anope_override
    142 	{
    143 		Configuration::Block *config = conf->GetModule(this);
    144 
    145 		this->certfile = config->Get<const Anope::string>("cert", "data/anope.crt");
    146 		this->keyfile = config->Get<const Anope::string>("key", "data/anope.key");
    147 
    148 		if (Anope::IsFile(this->certfile.c_str()))
    149 		{
    150 			if (!SSL_CTX_use_certificate_chain_file(client_ctx, this->certfile.c_str()) || !SSL_CTX_use_certificate_chain_file(server_ctx, this->certfile.c_str()))
    151 				throw ConfigException("Error loading certificate");
    152 			else
    153 				Log(LOG_DEBUG) << "m_ssl_openssl: Successfully loaded certificate " << this->certfile;
    154 		}
    155 		else
    156 			Log() << "Unable to open certificate " << this->certfile;
    157 
    158 		if (Anope::IsFile(this->keyfile.c_str()))
    159 		{
    160 			if (!SSL_CTX_use_PrivateKey_file(client_ctx, this->keyfile.c_str(), SSL_FILETYPE_PEM) || !SSL_CTX_use_PrivateKey_file(server_ctx, this->keyfile.c_str(), SSL_FILETYPE_PEM))
    161 				throw ConfigException("Error loading private key");
    162 			else
    163 				Log(LOG_DEBUG) << "m_ssl_openssl: Successfully loaded private key " << this->keyfile;
    164 		}
    165 		else
    166 		{
    167 			if (Anope::IsFile(this->certfile.c_str()))
    168 				throw ConfigException("Error loading private key " + this->keyfile + " - file not found");
    169 			else
    170 				Log() << "Unable to open private key " << this->keyfile;
    171 		}
    172 
    173 		// Allow disabling SSLv3
    174 		if (!config->Get<Anope::string>("sslv3").empty())
    175 		{
    176 			if (config->Get<bool>("sslv3"))
    177 			{
    178 				SSL_CTX_clear_options(client_ctx, SSL_OP_NO_SSLv3);
    179 				SSL_CTX_clear_options(server_ctx, SSL_OP_NO_SSLv3);
    180 			}
    181 			else
    182 			{
    183 				SSL_CTX_set_options(client_ctx, SSL_OP_NO_SSLv3);
    184 				SSL_CTX_set_options(server_ctx, SSL_OP_NO_SSLv3);
    185 			}
    186 		}
    187 	}
    188 
    189 	void OnPreServerConnect() anope_override
    190 	{
    191 		Configuration::Block *config = Config->GetBlock("uplink", Anope::CurrentUplink);
    192 
    193 		if (config->Get<bool>("ssl"))
    194 		{
    195 			this->service.Init(UplinkSock);
    196 		}
    197 	}
    198 };
    199 
    200 MySSLService::MySSLService(Module *o, const Anope::string &n) : SSLService(o, n)
    201 {
    202 }
    203 
    204 void MySSLService::Init(Socket *s)
    205 {
    206 	if (s->io != &NormalSocketIO)
    207 		throw CoreException("Socket initializing SSL twice");
    208 
    209 	s->io = new SSLSocketIO();
    210 }
    211 
    212 SSLSocketIO::SSLSocketIO()
    213 {
    214 	this->sslsock = NULL;
    215 }
    216 
    217 int SSLSocketIO::Recv(Socket *s, char *buf, size_t sz)
    218 {
    219 	int i = SSL_read(this->sslsock, buf, sz);
    220 	if (i > 0)
    221 		TotalRead += i;
    222 	else if (i < 0)
    223 	{
    224 		int err = SSL_get_error(this->sslsock, i);
    225 		switch (err)
    226 		{
    227 			case SSL_ERROR_WANT_READ:
    228 			case SSL_ERROR_WANT_WRITE:
    229 				SocketEngine::SetLastError(EAGAIN);
    230 		}
    231 	}
    232 
    233 	return i;
    234 }
    235 
    236 int SSLSocketIO::Send(Socket *s, const char *buf, size_t sz)
    237 {
    238 	int i = SSL_write(this->sslsock, buf, sz);
    239 	if (i > 0)
    240 		TotalWritten += i;
    241 	else if (i < 0)
    242 	{
    243 		int err = SSL_get_error(this->sslsock, i);
    244 		switch (err)
    245 		{
    246 			case SSL_ERROR_WANT_READ:
    247 			case SSL_ERROR_WANT_WRITE:
    248 				SocketEngine::SetLastError(EAGAIN);
    249 		}
    250 	}
    251 	return i;
    252 }
    253 
    254 ClientSocket *SSLSocketIO::Accept(ListenSocket *s)
    255 {
    256 	if (s->io == &NormalSocketIO)
    257 		throw SocketException("Attempting to accept on uninitialized socket with SSL");
    258 
    259 	sockaddrs conaddr;
    260 
    261 	socklen_t size = sizeof(conaddr);
    262 	int newsock = accept(s->GetFD(), &conaddr.sa, &size);
    263 
    264 #ifndef INVALID_SOCKET
    265 	const int INVALID_SOCKET = -1;
    266 #endif
    267 
    268 	if (newsock < 0 || newsock == INVALID_SOCKET)
    269 		throw SocketException("Unable to accept connection: " + Anope::LastError());
    270 
    271 	ClientSocket *newsocket = s->OnAccept(newsock, conaddr);
    272 	me->service.Init(newsocket);
    273 	SSLSocketIO *io = anope_dynamic_static_cast<SSLSocketIO *>(newsocket->io);
    274 
    275 	io->sslsock = SSL_new(server_ctx);
    276 	if (!io->sslsock)
    277 		throw SocketException("Unable to initialize SSL socket");
    278 
    279 	SSL_set_accept_state(io->sslsock);
    280 
    281 	if (!SSL_set_fd(io->sslsock, newsocket->GetFD()))
    282 		throw SocketException("Unable to set SSL fd");
    283 
    284 	newsocket->flags[SF_ACCEPTING] = true;
    285 	this->FinishAccept(newsocket);
    286 
    287 	return newsocket;
    288 }
    289 
    290 SocketFlag SSLSocketIO::FinishAccept(ClientSocket *cs)
    291 {
    292 	if (cs->io == &NormalSocketIO)
    293 		throw SocketException("Attempting to finish connect uninitialized socket with SSL");
    294 	else if (cs->flags[SF_ACCEPTED])
    295 		return SF_ACCEPTED;
    296 	else if (!cs->flags[SF_ACCEPTING])
    297 		throw SocketException("SSLSocketIO::FinishAccept called for a socket not accepted nor accepting?");
    298 
    299 	SSLSocketIO *io = anope_dynamic_static_cast<SSLSocketIO *>(cs->io);
    300 
    301 	int ret = SSL_accept(io->sslsock);
    302 	if (ret <= 0)
    303 	{
    304 		int error = SSL_get_error(io->sslsock, ret);
    305 		if (ret == -1 && (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE))
    306 		{
    307 			SocketEngine::Change(cs, error == SSL_ERROR_WANT_WRITE, SF_WRITABLE);
    308 			SocketEngine::Change(cs, error == SSL_ERROR_WANT_READ, SF_READABLE);
    309 			return SF_ACCEPTING;
    310 		}
    311 		else
    312 		{
    313 			cs->OnError(ERR_error_string(ERR_get_error(), NULL));
    314 			cs->flags[SF_DEAD] = true;
    315 			cs->flags[SF_ACCEPTING] = false;
    316 			return SF_DEAD;
    317 		}
    318 	}
    319 	else
    320 	{
    321 		cs->flags[SF_ACCEPTED] = true;
    322 		cs->flags[SF_ACCEPTING] = false;
    323 		SocketEngine::Change(cs, false, SF_WRITABLE);
    324 		SocketEngine::Change(cs, true, SF_READABLE);
    325 		cs->OnAccept();
    326 		return SF_ACCEPTED;
    327 	}
    328 }
    329 
    330 void SSLSocketIO::Connect(ConnectionSocket *s, const Anope::string &target, int port)
    331 {
    332 	if (s->io == &NormalSocketIO)
    333 		throw SocketException("Attempting to connect uninitialized socket with SSL");
    334 
    335 	s->flags[SF_CONNECTING] = s->flags[SF_CONNECTED] = false;
    336 
    337 	s->conaddr.pton(s->IsIPv6() ? AF_INET6 : AF_INET, target, port);
    338 	int c = connect(s->GetFD(), &s->conaddr.sa, s->conaddr.size());
    339 	if (c == -1)
    340 	{
    341 		if (Anope::LastErrorCode() != EINPROGRESS)
    342 		{
    343 			s->OnError(Anope::LastError());
    344 			s->flags[SF_DEAD] = true;
    345 			return;
    346 		}
    347 		else
    348 		{
    349 			SocketEngine::Change(s, true, SF_WRITABLE);
    350 			s->flags[SF_CONNECTING] = true;
    351 			return;
    352 		}
    353 	}
    354 	else
    355 	{
    356 		s->flags[SF_CONNECTING] = true;
    357 		this->FinishConnect(s);
    358 	}
    359 }
    360 
    361 SocketFlag SSLSocketIO::FinishConnect(ConnectionSocket *s)
    362 {
    363 	if (s->io == &NormalSocketIO)
    364 		throw SocketException("Attempting to finish connect uninitialized socket with SSL");
    365 	else if (s->flags[SF_CONNECTED])
    366 		return SF_CONNECTED;
    367 	else if (!s->flags[SF_CONNECTING])
    368 		throw SocketException("SSLSocketIO::FinishConnect called for a socket not connected nor connecting?");
    369 
    370 	SSLSocketIO *io = anope_dynamic_static_cast<SSLSocketIO *>(s->io);
    371 
    372 	if (io->sslsock == NULL)
    373 	{
    374 		io->sslsock = SSL_new(client_ctx);
    375 		if (!io->sslsock)
    376 			throw SocketException("Unable to initialize SSL socket");
    377 
    378 		if (!SSL_set_fd(io->sslsock, s->GetFD()))
    379 			throw SocketException("Unable to set SSL fd");
    380 	}
    381 
    382 	int ret = SSL_connect(io->sslsock);
    383 	if (ret <= 0)
    384 	{
    385 		int error = SSL_get_error(io->sslsock, ret);
    386 		if (ret == -1 && (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE))
    387 		{
    388 			SocketEngine::Change(s, error == SSL_ERROR_WANT_WRITE, SF_WRITABLE);
    389 			SocketEngine::Change(s, error == SSL_ERROR_WANT_READ, SF_READABLE);
    390 			return SF_CONNECTING;
    391 		}
    392 		else
    393 		{
    394 			s->OnError(ERR_error_string(ERR_get_error(), NULL));
    395 			s->flags[SF_CONNECTING] = false;
    396 			s->flags[SF_DEAD] = true;
    397 			return SF_DEAD;
    398 		}
    399 	}
    400 	else
    401 	{
    402 		s->flags[SF_CONNECTING] = false;
    403 		s->flags[SF_CONNECTED] = true;
    404 		SocketEngine::Change(s, false, SF_WRITABLE);
    405 		SocketEngine::Change(s, true, SF_READABLE);
    406 		s->OnConnect();
    407 		return SF_CONNECTED;
    408 	}
    409 }
    410 
    411 void SSLSocketIO::Destroy()
    412 {
    413 	if (this->sslsock)
    414 	{
    415 		SSL_shutdown(this->sslsock);
    416 		SSL_free(this->sslsock);
    417 	}
    418 
    419 	delete this;
    420 }
    421 
    422 MODULE_INIT(SSLModule)