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)