00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "inspircd.h"
00015
00016 #include <openssl/ssl.h>
00017 #include <openssl/err.h>
00018
00019 #include "configreader.h"
00020 #include "users.h"
00021 #include "channels.h"
00022 #include "modules.h"
00023
00024 #include "socket.h"
00025 #include "hashcomp.h"
00026
00027 #include "transport.h"
00028
00029 #ifdef WINDOWS
00030 #pragma comment(lib, "libeay32MTd")
00031 #pragma comment(lib, "ssleay32MTd")
00032 #undef MAX_DESCRIPTORS
00033 #define MAX_DESCRIPTORS 10000
00034 #endif
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 enum issl_status { ISSL_NONE, ISSL_HANDSHAKING, ISSL_OPEN };
00049 enum issl_io_status { ISSL_WRITE, ISSL_READ };
00050
00051 static bool SelfSigned = false;
00052
00053 bool isin(const std::string &host, int port, const std::vector<std::string> &portlist)
00054 {
00055 if (std::find(portlist.begin(), portlist.end(), "*:" + ConvToStr(port)) != portlist.end())
00056 return true;
00057
00058 if (std::find(portlist.begin(), portlist.end(), ":" + ConvToStr(port)) != portlist.end())
00059 return true;
00060
00061 return std::find(portlist.begin(), portlist.end(), host + ":" + ConvToStr(port)) != portlist.end();
00062 }
00063
00064 char* get_error()
00065 {
00066 return ERR_error_string(ERR_get_error(), NULL);
00067 }
00068
00069 static int error_callback(const char *str, size_t len, void *u);
00070
00073 class issl_session : public classbase
00074 {
00075 public:
00076 SSL* sess;
00077 issl_status status;
00078 issl_io_status rstat;
00079 issl_io_status wstat;
00080
00081 unsigned int inbufoffset;
00082 char* inbuf;
00083 std::string outbuf;
00084 int fd;
00085 bool outbound;
00086
00087 issl_session()
00088 {
00089 outbound = false;
00090 rstat = ISSL_READ;
00091 wstat = ISSL_WRITE;
00092 }
00093 };
00094
00095 static int OnVerify(int preverify_ok, X509_STORE_CTX *ctx)
00096 {
00097
00098
00099
00100
00101
00102 int ve = X509_STORE_CTX_get_error(ctx);
00103
00104 SelfSigned = (ve == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT);
00105
00106 return 1;
00107 }
00108
00109 class ModuleSSLOpenSSL : public Module
00110 {
00111 std::vector<std::string> listenports;
00112
00113 int inbufsize;
00114 issl_session* sessions;
00115
00116 SSL_CTX* ctx;
00117 SSL_CTX* clictx;
00118
00119 char* dummy;
00120 char cipher[MAXBUF];
00121
00122 std::string keyfile;
00123 std::string certfile;
00124 std::string cafile;
00125
00126 std::string dhfile;
00127 std::string sslports;
00128
00129 int clientactive;
00130
00131 public:
00132
00133 InspIRCd* PublicInstance;
00134
00135 ModuleSSLOpenSSL(InspIRCd* Me)
00136 : Module(Me), PublicInstance(Me)
00137 {
00138 ServerInstance->Modules->PublishInterface("BufferedSocketHook", this);
00139
00140 sessions = new issl_session[ServerInstance->SE->GetMaxFds()];
00141
00142
00143 inbufsize = ServerInstance->Config->NetBufferSize;
00144
00145
00146 SSL_library_init();
00147 SSL_load_error_strings();
00148
00149
00150
00151
00152 ctx = SSL_CTX_new( SSLv23_server_method() );
00153 clictx = SSL_CTX_new( SSLv23_client_method() );
00154
00155 SSL_CTX_set_mode(ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
00156 SSL_CTX_set_mode(clictx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
00157
00158 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, OnVerify);
00159 SSL_CTX_set_verify(clictx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, OnVerify);
00160
00161
00162 OnRehash(NULL,"ssl");
00163 Implementation eventlist[] = { I_OnRawSocketConnect, I_OnRawSocketAccept, I_OnRawSocketClose, I_OnRawSocketRead, I_OnRawSocketWrite, I_OnCleanup, I_On005Numeric,
00164 I_OnBufferFlushed, I_OnRequest, I_OnSyncUserMetaData, I_OnDecodeMetaData, I_OnUnloadModule, I_OnRehash, I_OnWhois, I_OnPostConnect, I_OnHookUserIO };
00165 ServerInstance->Modules->Attach(eventlist, this, 16);
00166 }
00167
00168 virtual void OnHookUserIO(User* user, const std::string &targetip)
00169 {
00170 if (!user->io && isin(targetip,user->GetPort(), listenports))
00171 {
00172
00173 user->io = this;
00174 }
00175 }
00176
00177 virtual void OnRehash(User* user, const std::string ¶m)
00178 {
00179 ConfigReader Conf(ServerInstance);
00180
00181 listenports.clear();
00182 clientactive = 0;
00183 sslports.clear();
00184
00185 for(int index = 0; index < Conf.Enumerate("bind"); index++)
00186 {
00187
00188 std::string x = Conf.ReadValue("bind", "type", index);
00189 if(((x.empty()) || (x == "clients")) && (Conf.ReadValue("bind", "ssl", index) == "openssl"))
00190 {
00191
00192 std::string port = Conf.ReadValue("bind", "port", index);
00193 std::string addr = Conf.ReadValue("bind", "address", index);
00194
00195 irc::portparser portrange(port, false);
00196 long portno = -1;
00197 while ((portno = portrange.GetToken()))
00198 {
00199 clientactive++;
00200 try
00201 {
00202 listenports.push_back(addr + ":" + ConvToStr(portno));
00203
00204 for (size_t i = 0; i < ServerInstance->Config->ports.size(); i++)
00205 if ((ServerInstance->Config->ports[i]->GetPort() == portno) && (ServerInstance->Config->ports[i]->GetIP() == addr))
00206 ServerInstance->Config->ports[i]->SetDescription("ssl");
00207 ServerInstance->Logs->Log("m_ssl_openssl",DEFAULT, "m_ssl_gnutls.so: Enabling SSL for port %ld", portno);
00208
00209 sslports.append((addr.empty() ? "*" : addr)).append(":").append(ConvToStr(portno)).append(";");
00210 }
00211 catch (ModuleException &e)
00212 {
00213 ServerInstance->Logs->Log("m_ssl_openssl",DEFAULT, "m_ssl_gnutls.so: FAILED to enable SSL on port %ld: %s. Maybe it's already hooked by the same port on a different IP, or you have an other SSL or similar module loaded?", portno, e.GetReason());
00214 }
00215 }
00216 }
00217 }
00218
00219 if (!sslports.empty())
00220 sslports.erase(sslports.end() - 1);
00221
00222 if (param != "ssl")
00223 {
00224 return;
00225 }
00226
00227 std::string confdir(ServerInstance->ConfigFileName);
00228
00229 confdir = confdir.substr(0, confdir.find_last_of('/') + 1);
00230
00231 cafile = Conf.ReadValue("openssl", "cafile", 0);
00232 certfile = Conf.ReadValue("openssl", "certfile", 0);
00233 keyfile = Conf.ReadValue("openssl", "keyfile", 0);
00234 dhfile = Conf.ReadValue("openssl", "dhfile", 0);
00235
00236
00237 if (cafile.empty())
00238 cafile = "ca.pem";
00239
00240 if (certfile.empty())
00241 certfile = "cert.pem";
00242
00243 if (keyfile.empty())
00244 keyfile = "key.pem";
00245
00246 if (dhfile.empty())
00247 dhfile = "dhparams.pem";
00248
00249
00250 if ((cafile[0] != '/') && (!ServerInstance->Config->StartsWithWindowsDriveLetter(cafile)))
00251 cafile = confdir + cafile;
00252
00253 if ((certfile[0] != '/') && (!ServerInstance->Config->StartsWithWindowsDriveLetter(certfile)))
00254 certfile = confdir + certfile;
00255
00256 if ((keyfile[0] != '/') && (!ServerInstance->Config->StartsWithWindowsDriveLetter(keyfile)))
00257 keyfile = confdir + keyfile;
00258
00259 if ((dhfile[0] != '/') && (!ServerInstance->Config->StartsWithWindowsDriveLetter(dhfile)))
00260 dhfile = confdir + dhfile;
00261
00262
00263
00264
00265 if ((!SSL_CTX_use_certificate_chain_file(ctx, certfile.c_str())) || (!SSL_CTX_use_certificate_chain_file(clictx, certfile.c_str())))
00266 {
00267 ServerInstance->Logs->Log("m_ssl_openssl",DEFAULT, "m_ssl_openssl.so: Can't read certificate file %s. %s", certfile.c_str(), strerror(errno));
00268 ERR_print_errors_cb(error_callback, this);
00269 }
00270
00271 if (((!SSL_CTX_use_PrivateKey_file(ctx, keyfile.c_str(), SSL_FILETYPE_PEM))) || (!SSL_CTX_use_PrivateKey_file(clictx, keyfile.c_str(), SSL_FILETYPE_PEM)))
00272 {
00273 ServerInstance->Logs->Log("m_ssl_openssl",DEFAULT, "m_ssl_openssl.so: Can't read key file %s. %s", keyfile.c_str(), strerror(errno));
00274 ERR_print_errors_cb(error_callback, this);
00275 }
00276
00277
00278 if (((!SSL_CTX_load_verify_locations(ctx, cafile.c_str(), 0))) || (!SSL_CTX_load_verify_locations(clictx, cafile.c_str(), 0)))
00279 {
00280 ServerInstance->Logs->Log("m_ssl_openssl",DEFAULT, "m_ssl_openssl.so: Can't read CA list from %s. %s", cafile.c_str(), strerror(errno));
00281 ERR_print_errors_cb(error_callback, this);
00282 }
00283
00284 FILE* dhpfile = fopen(dhfile.c_str(), "r");
00285 DH* ret;
00286
00287 if (dhpfile == NULL)
00288 {
00289 ServerInstance->Logs->Log("m_ssl_openssl",DEFAULT, "m_ssl_openssl.so Couldn't open DH file %s: %s", dhfile.c_str(), strerror(errno));
00290 throw ModuleException("Couldn't open DH file " + dhfile + ": " + strerror(errno));
00291 }
00292 else
00293 {
00294 ret = PEM_read_DHparams(dhpfile, NULL, NULL, NULL);
00295 if ((SSL_CTX_set_tmp_dh(ctx, ret) < 0) || (SSL_CTX_set_tmp_dh(clictx, ret) < 0))
00296 {
00297 ServerInstance->Logs->Log("m_ssl_openssl",DEFAULT, "m_ssl_openssl.so: Couldn't set DH parameters %s. SSL errors follow:", dhfile.c_str());
00298 ERR_print_errors_cb(error_callback, this);
00299 }
00300 }
00301
00302 fclose(dhpfile);
00303 }
00304
00305 virtual void On005Numeric(std::string &output)
00306 {
00307 output.append(" SSL=" + sslports);
00308 }
00309
00310 virtual ~ModuleSSLOpenSSL()
00311 {
00312 SSL_CTX_free(ctx);
00313 SSL_CTX_free(clictx);
00314 ServerInstance->Modules->UnpublishInterface("BufferedSocketHook", this);
00315 delete[] sessions;
00316 }
00317
00318 virtual void OnCleanup(int target_type, void* item)
00319 {
00320 if (target_type == TYPE_USER)
00321 {
00322 User* user = (User*)item;
00323
00324 if (user->io == this)
00325 {
00326
00327
00328 ServerInstance->Users->QuitUser(user, "SSL module unloading");
00329 user->io = NULL;
00330 }
00331 if (user->GetExt("ssl_cert", dummy))
00332 {
00333 ssl_cert* tofree;
00334 user->GetExt("ssl_cert", tofree);
00335 delete tofree;
00336 user->Shrink("ssl_cert");
00337 }
00338 }
00339 }
00340
00341 virtual void OnUnloadModule(Module* mod, const std::string &name)
00342 {
00343 if (mod == this)
00344 {
00345 for(unsigned int i = 0; i < listenports.size(); i++)
00346 {
00347 for (size_t j = 0; j < ServerInstance->Config->ports.size(); j++)
00348 if (listenports[i] == (ServerInstance->Config->ports[j]->GetIP()+":"+ConvToStr(ServerInstance->Config->ports[j]->GetPort())))
00349 ServerInstance->Config->ports[j]->SetDescription("plaintext");
00350 }
00351 }
00352 }
00353
00354 virtual Version GetVersion()
00355 {
00356 return Version("$Id: m_ssl_openssl.cpp 10290 2008-08-25 20:35:36Z w00t $", VF_VENDOR, API_VERSION);
00357 }
00358
00359
00360 virtual const char* OnRequest(Request* request)
00361 {
00362 ISHRequest* ISR = (ISHRequest*)request;
00363 if (strcmp("IS_NAME", request->GetId()) == 0)
00364 {
00365 return "openssl";
00366 }
00367 else if (strcmp("IS_HOOK", request->GetId()) == 0)
00368 {
00369 const char* ret = "OK";
00370 try
00371 {
00372 ret = ServerInstance->Config->AddIOHook((Module*)this, (BufferedSocket*)ISR->Sock) ? "OK" : NULL;
00373 }
00374 catch (ModuleException &e)
00375 {
00376 return NULL;
00377 }
00378
00379 return ret;
00380 }
00381 else if (strcmp("IS_UNHOOK", request->GetId()) == 0)
00382 {
00383 return ServerInstance->Config->DelIOHook((BufferedSocket*)ISR->Sock) ? "OK" : NULL;
00384 }
00385 else if (strcmp("IS_HSDONE", request->GetId()) == 0)
00386 {
00387 if (ISR->Sock->GetFd() < 0)
00388 return "OK";
00389
00390 issl_session* session = &sessions[ISR->Sock->GetFd()];
00391 return (session->status == ISSL_HANDSHAKING) ? NULL : "OK";
00392 }
00393 else if (strcmp("IS_ATTACH", request->GetId()) == 0)
00394 {
00395 issl_session* session = &sessions[ISR->Sock->GetFd()];
00396 if (session->sess)
00397 {
00398 VerifyCertificate(session, (BufferedSocket*)ISR->Sock);
00399 return "OK";
00400 }
00401 }
00402 return NULL;
00403 }
00404
00405
00406 virtual void OnRawSocketAccept(int fd, const std::string &ip, int localport)
00407 {
00408
00409 if ((fd < 0) || (fd > ServerInstance->SE->GetMaxFds() - 1))
00410 return;
00411
00412 issl_session* session = &sessions[fd];
00413
00414 session->fd = fd;
00415 session->inbuf = new char[inbufsize];
00416 session->inbufoffset = 0;
00417 session->sess = SSL_new(ctx);
00418 session->status = ISSL_NONE;
00419 session->outbound = false;
00420
00421 if (session->sess == NULL)
00422 return;
00423
00424 if (SSL_set_fd(session->sess, fd) == 0)
00425 {
00426 ServerInstance->Logs->Log("m_ssl_openssl",DEBUG,"BUG: Can't set fd with SSL_set_fd: %d", fd);
00427 return;
00428 }
00429
00430 Handshake(session);
00431 }
00432
00433 virtual void OnRawSocketConnect(int fd)
00434 {
00435
00436 if ((fd < 0) || (fd > ServerInstance->SE->GetMaxFds() -1))
00437 return;
00438
00439 issl_session* session = &sessions[fd];
00440
00441 session->fd = fd;
00442 session->inbuf = new char[inbufsize];
00443 session->inbufoffset = 0;
00444 session->sess = SSL_new(clictx);
00445 session->status = ISSL_NONE;
00446 session->outbound = true;
00447
00448 if (session->sess == NULL)
00449 return;
00450
00451 if (SSL_set_fd(session->sess, fd) == 0)
00452 {
00453 ServerInstance->Logs->Log("m_ssl_openssl",DEBUG,"BUG: Can't set fd with SSL_set_fd: %d", fd);
00454 return;
00455 }
00456
00457 Handshake(session);
00458 }
00459
00460 virtual void OnRawSocketClose(int fd)
00461 {
00462
00463 if ((fd < 0) || (fd > ServerInstance->SE->GetMaxFds() - 1))
00464 return;
00465
00466 CloseSession(&sessions[fd]);
00467
00468 EventHandler* user = ServerInstance->SE->GetRef(fd);
00469
00470 if ((user) && (user->GetExt("ssl_cert", dummy)))
00471 {
00472 ssl_cert* tofree;
00473 user->GetExt("ssl_cert", tofree);
00474 delete tofree;
00475 user->Shrink("ssl_cert");
00476 }
00477 }
00478
00479 virtual int OnRawSocketRead(int fd, char* buffer, unsigned int count, int &readresult)
00480 {
00481
00482 if ((fd < 0) || (fd > ServerInstance->SE->GetMaxFds() - 1))
00483 return 0;
00484
00485 issl_session* session = &sessions[fd];
00486
00487 if (!session->sess)
00488 {
00489 readresult = 0;
00490 CloseSession(session);
00491 return 1;
00492 }
00493
00494 if (session->status == ISSL_HANDSHAKING)
00495 {
00496 if (session->rstat == ISSL_READ || session->wstat == ISSL_READ)
00497 {
00498
00499 if (!Handshake(session))
00500 {
00501
00502 return -1;
00503 }
00504 }
00505 else
00506 {
00507 errno = EAGAIN;
00508 return -1;
00509 }
00510 }
00511
00512
00513
00514 if (session->status == ISSL_OPEN)
00515 {
00516 if (session->wstat == ISSL_READ)
00517 {
00518 if(DoWrite(session) == 0)
00519 return 0;
00520 }
00521
00522 if (session->rstat == ISSL_READ)
00523 {
00524 int ret = DoRead(session);
00525
00526 if (ret > 0)
00527 {
00528 if (count <= session->inbufoffset)
00529 {
00530 memcpy(buffer, session->inbuf, count);
00531
00532 memmove(session->inbuf, session->inbuf + count, (session->inbufoffset - count));
00533
00534 session->inbufoffset -= count;
00535
00536 readresult = count;
00537 }
00538 else
00539 {
00540
00541 memcpy(buffer, session->inbuf, session->inbufoffset);
00542
00543 readresult = session->inbufoffset;
00544
00545 session->inbufoffset = 0;
00546 }
00547 return 1;
00548 }
00549 return ret;
00550 }
00551 }
00552
00553 return -1;
00554 }
00555
00556 virtual int OnRawSocketWrite(int fd, const char* buffer, int count)
00557 {
00558
00559 if ((fd < 0) || (fd > ServerInstance->SE->GetMaxFds() - 1))
00560 return 0;
00561
00562 issl_session* session = &sessions[fd];
00563
00564 if (!session->sess)
00565 {
00566 CloseSession(session);
00567 return -1;
00568 }
00569
00570 session->outbuf.append(buffer, count);
00571 MakePollWrite(session);
00572
00573 if (session->status == ISSL_HANDSHAKING)
00574 {
00575
00576 if (session->rstat == ISSL_WRITE || session->wstat == ISSL_WRITE)
00577 {
00578 Handshake(session);
00579 }
00580 }
00581
00582 if (session->status == ISSL_OPEN)
00583 {
00584 if (session->rstat == ISSL_WRITE)
00585 {
00586 DoRead(session);
00587 }
00588
00589 if (session->wstat == ISSL_WRITE)
00590 {
00591 return DoWrite(session);
00592 }
00593 }
00594
00595 return 1;
00596 }
00597
00598 int DoWrite(issl_session* session)
00599 {
00600 if (!session->outbuf.size())
00601 return -1;
00602
00603 int ret = SSL_write(session->sess, session->outbuf.data(), session->outbuf.size());
00604
00605 if (ret == 0)
00606 {
00607 CloseSession(session);
00608 return 0;
00609 }
00610 else if (ret < 0)
00611 {
00612 int err = SSL_get_error(session->sess, ret);
00613
00614 if (err == SSL_ERROR_WANT_WRITE)
00615 {
00616 session->wstat = ISSL_WRITE;
00617 return -1;
00618 }
00619 else if (err == SSL_ERROR_WANT_READ)
00620 {
00621 session->wstat = ISSL_READ;
00622 return -1;
00623 }
00624 else
00625 {
00626 CloseSession(session);
00627 return 0;
00628 }
00629 }
00630 else
00631 {
00632 session->outbuf = session->outbuf.substr(ret);
00633 return ret;
00634 }
00635 }
00636
00637 int DoRead(issl_session* session)
00638 {
00639
00640
00641
00642 int ret = SSL_read(session->sess, session->inbuf + session->inbufoffset, inbufsize - session->inbufoffset);
00643
00644 if (ret == 0)
00645 {
00646
00647 CloseSession(session);
00648 return 0;
00649 }
00650 else if (ret < 0)
00651 {
00652 int err = SSL_get_error(session->sess, ret);
00653
00654 if (err == SSL_ERROR_WANT_READ)
00655 {
00656 session->rstat = ISSL_READ;
00657 return -1;
00658 }
00659 else if (err == SSL_ERROR_WANT_WRITE)
00660 {
00661 session->rstat = ISSL_WRITE;
00662 MakePollWrite(session);
00663 return -1;
00664 }
00665 else
00666 {
00667 CloseSession(session);
00668 return 0;
00669 }
00670 }
00671 else
00672 {
00673
00674
00675
00676
00677 session->inbufoffset += ret;
00678
00679 return ret;
00680 }
00681 }
00682
00683
00684 virtual void OnWhois(User* source, User* dest)
00685 {
00686 if (!clientactive)
00687 return;
00688
00689
00690 if (dest->GetExt("ssl", dummy) || ((IS_LOCAL(dest) && dest->io == this)))
00691 {
00692 ServerInstance->SendWhoisLine(source, dest, 320, "%s %s :is using a secure connection", source->nick.c_str(), dest->nick.c_str());
00693 }
00694 }
00695
00696 virtual void OnSyncUserMetaData(User* user, Module* proto, void* opaque, const std::string &extname, bool displayable)
00697 {
00698
00699 if (extname == "ssl")
00700 {
00701
00702 if(user->GetExt(extname, dummy))
00703 {
00704
00705
00706 proto->ProtoSendMetaData(opaque, TYPE_USER, user, extname, displayable ? "Enabled" : "ON");
00707 }
00708 }
00709 }
00710
00711 virtual void OnDecodeMetaData(int target_type, void* target, const std::string &extname, const std::string &extdata)
00712 {
00713
00714 if ((target_type == TYPE_USER) && (extname == "ssl"))
00715 {
00716 User* dest = (User*)target;
00717
00718 if (!dest->GetExt(extname, dummy))
00719 {
00720 dest->Extend(extname, "ON");
00721 }
00722 }
00723 }
00724
00725 bool Handshake(issl_session* session)
00726 {
00727 int ret;
00728
00729 if (session->outbound)
00730 ret = SSL_connect(session->sess);
00731 else
00732 ret = SSL_accept(session->sess);
00733
00734 if (ret < 0)
00735 {
00736 int err = SSL_get_error(session->sess, ret);
00737
00738 if (err == SSL_ERROR_WANT_READ)
00739 {
00740 session->rstat = ISSL_READ;
00741 session->status = ISSL_HANDSHAKING;
00742 return true;
00743 }
00744 else if (err == SSL_ERROR_WANT_WRITE)
00745 {
00746 session->wstat = ISSL_WRITE;
00747 session->status = ISSL_HANDSHAKING;
00748 MakePollWrite(session);
00749 return true;
00750 }
00751 else
00752 {
00753 CloseSession(session);
00754 }
00755
00756 return false;
00757 }
00758 else if (ret > 0)
00759 {
00760
00761
00762 User* u = ServerInstance->FindDescriptor(session->fd);
00763 if (u)
00764 {
00765 if (!u->GetExt("ssl", dummy))
00766 u->Extend("ssl", "ON");
00767 }
00768
00769 session->status = ISSL_OPEN;
00770
00771 MakePollWrite(session);
00772
00773 return true;
00774 }
00775 else if (ret == 0)
00776 {
00777 CloseSession(session);
00778 return true;
00779 }
00780
00781 return true;
00782 }
00783
00784 virtual void OnPostConnect(User* user)
00785 {
00786
00787
00788 if ((user->GetExt("ssl", dummy)) && (IS_LOCAL(user)))
00789 {
00790
00791 ServerInstance->PI->SendMetaData(user, TYPE_USER, "SSL", "on");
00792
00793 VerifyCertificate(&sessions[user->GetFd()], user);
00794 if (sessions[user->GetFd()].sess)
00795 user->WriteServ("NOTICE %s :*** You are connected using SSL cipher \"%s\"", user->nick.c_str(), SSL_get_cipher(sessions[user->GetFd()].sess));
00796 }
00797 }
00798
00799 void MakePollWrite(issl_session* session)
00800 {
00801
00802 EventHandler* eh = ServerInstance->FindDescriptor(session->fd);
00803 if (eh)
00804 {
00805 ServerInstance->SE->WantWrite(eh);
00806 }
00807 }
00808
00809 virtual void OnBufferFlushed(User* user)
00810 {
00811 if (user->GetExt("ssl"))
00812 {
00813 issl_session* session = &sessions[user->GetFd()];
00814 if (session && session->outbuf.size())
00815 OnRawSocketWrite(user->GetFd(), NULL, 0);
00816 }
00817 }
00818
00819 void CloseSession(issl_session* session)
00820 {
00821 if (session->sess)
00822 {
00823 SSL_shutdown(session->sess);
00824 SSL_free(session->sess);
00825 }
00826
00827 if (session->inbuf)
00828 {
00829 delete[] session->inbuf;
00830 }
00831
00832 session->outbuf.clear();
00833 session->inbuf = NULL;
00834 session->sess = NULL;
00835 session->status = ISSL_NONE;
00836 }
00837
00838 void VerifyCertificate(issl_session* session, Extensible* user)
00839 {
00840 if (!session->sess || !user)
00841 return;
00842
00843 X509* cert;
00844 ssl_cert* certinfo = new ssl_cert;
00845 unsigned int n;
00846 unsigned char md[EVP_MAX_MD_SIZE];
00847 const EVP_MD *digest = EVP_md5();
00848
00849 user->Extend("ssl_cert",certinfo);
00850
00851 cert = SSL_get_peer_certificate((SSL*)session->sess);
00852
00853 if (!cert)
00854 {
00855 certinfo->data.insert(std::make_pair("error","Could not get peer certificate: "+std::string(get_error())));
00856 return;
00857 }
00858
00859 certinfo->data.insert(std::make_pair("invalid", SSL_get_verify_result(session->sess) != X509_V_OK ? ConvToStr(1) : ConvToStr(0)));
00860
00861 if (SelfSigned)
00862 {
00863 certinfo->data.insert(std::make_pair("unknownsigner",ConvToStr(0)));
00864 certinfo->data.insert(std::make_pair("trusted",ConvToStr(1)));
00865 }
00866 else
00867 {
00868 certinfo->data.insert(std::make_pair("unknownsigner",ConvToStr(1)));
00869 certinfo->data.insert(std::make_pair("trusted",ConvToStr(0)));
00870 }
00871
00872 certinfo->data.insert(std::make_pair("dn",std::string(X509_NAME_oneline(X509_get_subject_name(cert),0,0))));
00873 certinfo->data.insert(std::make_pair("issuer",std::string(X509_NAME_oneline(X509_get_issuer_name(cert),0,0))));
00874
00875 if (!X509_digest(cert, digest, md, &n))
00876 {
00877 certinfo->data.insert(std::make_pair("error","Out of memory generating fingerprint"));
00878 }
00879 else
00880 {
00881 certinfo->data.insert(std::make_pair("fingerprint",irc::hex(md, n)));
00882 }
00883
00884 if ((ASN1_UTCTIME_cmp_time_t(X509_get_notAfter(cert), time(NULL)) == -1) || (ASN1_UTCTIME_cmp_time_t(X509_get_notBefore(cert), time(NULL)) == 0))
00885 {
00886 certinfo->data.insert(std::make_pair("error","Not activated, or expired certificate"));
00887 }
00888
00889 X509_free(cert);
00890 }
00891
00892 void Prioritize()
00893 {
00894 Module* server = ServerInstance->Modules->Find("m_spanningtree.so");
00895 ServerInstance->Modules->SetPriority(this,