00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "inspircd.h"
00015
00016 #include <gnutls/gnutls.h>
00017 #include <gnutls/x509.h>
00018
00019 #include "inspircd_config.h"
00020 #include "configreader.h"
00021 #include "users.h"
00022 #include "channels.h"
00023 #include "modules.h"
00024 #include "socket.h"
00025 #include "hashcomp.h"
00026 #include "transport.h"
00027
00028 #ifdef WINDOWS
00029 #pragma comment(lib, "libgnutls-13.lib")
00030 #undef MAX_DESCRIPTORS
00031 #define MAX_DESCRIPTORS 10000
00032 #endif
00033
00034
00035
00036
00037
00038
00039 enum issl_status { ISSL_NONE, ISSL_HANDSHAKING_READ, ISSL_HANDSHAKING_WRITE, ISSL_HANDSHAKEN, ISSL_CLOSING, ISSL_CLOSED };
00040
00041 bool isin(int port, const std::vector<int> &portlist)
00042 {
00043 for(unsigned int i = 0; i < portlist.size(); i++)
00044 if(portlist[i] == port)
00045 return true;
00046
00047 return false;
00048 }
00049
00052 class issl_session : public classbase
00053 {
00054 public:
00055 issl_session()
00056 {
00057 sess = NULL;
00058 }
00059 gnutls_session_t sess;
00060 issl_status status;
00061 std::string outbuf;
00062 int inbufoffset;
00063 char* inbuf;
00064 int fd;
00065 };
00066
00067 class ModuleSSLGnuTLS : public Module
00068 {
00069
00070 ConfigReader* Conf;
00071
00072 char* dummy;
00073
00074 std::vector<int> listenports;
00075
00076 int inbufsize;
00077 issl_session sessions[MAX_DESCRIPTORS];
00078
00079 gnutls_certificate_credentials x509_cred;
00080 gnutls_dh_params dh_params;
00081
00082 std::string keyfile;
00083 std::string certfile;
00084 std::string cafile;
00085 std::string crlfile;
00086 std::string sslports;
00087 int dh_bits;
00088
00089 int clientactive;
00090 bool cred_alloc;
00091
00092 public:
00093
00094 ModuleSSLGnuTLS(InspIRCd* Me)
00095 : Module(Me)
00096 {
00097 ServerInstance->PublishInterface("InspSocketHook", this);
00098
00099
00100 inbufsize = ServerInstance->Config->NetBufferSize;
00101
00102 gnutls_global_init();
00103
00104 cred_alloc = false;
00105
00106 OnRehash(NULL,"ssl");
00107
00108
00109 gnutls_certificate_set_dh_params(x509_cred, dh_params);
00110 }
00111
00112 virtual void OnRehash(userrec* user, const std::string ¶m)
00113 {
00114 Conf = new ConfigReader(ServerInstance);
00115
00116 for(unsigned int i = 0; i < listenports.size(); i++)
00117 {
00118 ServerInstance->Config->DelIOHook(listenports[i]);
00119 }
00120
00121 listenports.clear();
00122 clientactive = 0;
00123 sslports.clear();
00124
00125 for(int i = 0; i < Conf->Enumerate("bind"); i++)
00126 {
00127
00128 std::string x = Conf->ReadValue("bind", "type", i);
00129 if(((x.empty()) || (x == "clients")) && (Conf->ReadValue("bind", "ssl", i) == "gnutls"))
00130 {
00131
00132 std::string port = Conf->ReadValue("bind", "port", i);
00133 irc::portparser portrange(port, false);
00134 long portno = -1;
00135 while ((portno = portrange.GetToken()))
00136 {
00137 clientactive++;
00138 try
00139 {
00140 if (ServerInstance->Config->AddIOHook(portno, this))
00141 {
00142 listenports.push_back(portno);
00143 for (size_t i = 0; i < ServerInstance->Config->ports.size(); i++)
00144 if (ServerInstance->Config->ports[i]->GetPort() == portno)
00145 ServerInstance->Config->ports[i]->SetDescription("ssl");
00146 ServerInstance->Log(DEFAULT, "m_ssl_gnutls.so: Enabling SSL for port %d", portno);
00147 sslports.append("*:").append(ConvToStr(portno)).append(";");
00148 }
00149 else
00150 {
00151 ServerInstance->Log(DEFAULT, "m_ssl_gnutls.so: FAILED to enable SSL on port %d, maybe you have another ssl or similar module loaded?", portno);
00152 }
00153 }
00154 catch (ModuleException &e)
00155 {
00156 ServerInstance->Log(DEFAULT, "m_ssl_gnutls.so: FAILED to enable SSL on port %d: %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());
00157 }
00158 }
00159 }
00160 }
00161
00162 if(param != "ssl")
00163 {
00164 delete Conf;
00165 return;
00166 }
00167
00168 std::string confdir(ServerInstance->ConfigFileName);
00169
00170 confdir = confdir.substr(0, confdir.find_last_of('/') + 1);
00171
00172 cafile = Conf->ReadValue("gnutls", "cafile", 0);
00173 crlfile = Conf->ReadValue("gnutls", "crlfile", 0);
00174 certfile = Conf->ReadValue("gnutls", "certfile", 0);
00175 keyfile = Conf->ReadValue("gnutls", "keyfile", 0);
00176 dh_bits = Conf->ReadInteger("gnutls", "dhbits", 0, false);
00177
00178
00179 if (cafile.empty())
00180 cafile = "ca.pem";
00181
00182 if (crlfile.empty())
00183 crlfile = "crl.pem";
00184
00185 if (certfile.empty())
00186 certfile = "cert.pem";
00187
00188 if (keyfile.empty())
00189 keyfile = "key.pem";
00190
00191 if((dh_bits != 768) && (dh_bits != 1024) && (dh_bits != 2048) && (dh_bits != 3072) && (dh_bits != 4096))
00192 dh_bits = 1024;
00193
00194
00195 if(cafile[0] != '/')
00196 cafile = confdir + cafile;
00197
00198 if(crlfile[0] != '/')
00199 crlfile = confdir + crlfile;
00200
00201 if(certfile[0] != '/')
00202 certfile = confdir + certfile;
00203
00204 if(keyfile[0] != '/')
00205 keyfile = confdir + keyfile;
00206
00207 int ret;
00208
00209 if (cred_alloc)
00210 {
00211
00212 gnutls_dh_params_deinit(dh_params);
00213 gnutls_certificate_free_credentials(x509_cred);
00214 }
00215 else
00216 cred_alloc = true;
00217
00218 if((ret = gnutls_certificate_allocate_credentials(&x509_cred)) < 0)
00219 ServerInstance->Log(DEFAULT, "m_ssl_gnutls.so: Failed to allocate certificate credentials: %s", gnutls_strerror(ret));
00220
00221 if((ret = gnutls_dh_params_init(&dh_params)) < 0)
00222 ServerInstance->Log(DEFAULT, "m_ssl_gnutls.so: Failed to initialise DH parameters: %s", gnutls_strerror(ret));
00223
00224 if((ret =gnutls_certificate_set_x509_trust_file(x509_cred, cafile.c_str(), GNUTLS_X509_FMT_PEM)) < 0)
00225 ServerInstance->Log(DEFAULT, "m_ssl_gnutls.so: Failed to set X.509 trust file '%s': %s", cafile.c_str(), gnutls_strerror(ret));
00226
00227 if((ret = gnutls_certificate_set_x509_crl_file (x509_cred, crlfile.c_str(), GNUTLS_X509_FMT_PEM)) < 0)
00228 ServerInstance->Log(DEFAULT, "m_ssl_gnutls.so: Failed to set X.509 CRL file '%s': %s", crlfile.c_str(), gnutls_strerror(ret));
00229
00230 if((ret = gnutls_certificate_set_x509_key_file (x509_cred, certfile.c_str(), keyfile.c_str(), GNUTLS_X509_FMT_PEM)) < 0)
00231 {
00232
00233 throw ModuleException("Unable to load GnuTLS server certificate (" + certfile + ", key: " + keyfile + "): " + std::string(gnutls_strerror(ret)));
00234 }
00235
00236
00237 GenerateDHParams();
00238
00239 DELETE(Conf);
00240 }
00241
00242 void GenerateDHParams()
00243 {
00244
00245
00246
00247
00248
00249 int ret;
00250
00251 if((ret = gnutls_dh_params_generate2(dh_params, dh_bits)) < 0)
00252 ServerInstance->Log(DEFAULT, "m_ssl_gnutls.so: Failed to generate DH parameters (%d bits): %s", dh_bits, gnutls_strerror(ret));
00253 }
00254
00255 virtual ~ModuleSSLGnuTLS()
00256 {
00257 gnutls_dh_params_deinit(dh_params);
00258 gnutls_certificate_free_credentials(x509_cred);
00259 gnutls_global_deinit();
00260 ServerInstance->UnpublishInterface("InspSocketHook", this);
00261 }
00262
00263 virtual void OnCleanup(int target_type, void* item)
00264 {
00265 if(target_type == TYPE_USER)
00266 {
00267 userrec* user = (userrec*)item;
00268
00269 if(user->GetExt("ssl", dummy) && isin(user->GetPort(), listenports))
00270 {
00271
00272
00273 userrec::QuitUser(ServerInstance, user, "SSL module unloading");
00274 }
00275 if (user->GetExt("ssl_cert", dummy) && isin(user->GetPort(), listenports))
00276 {
00277 ssl_cert* tofree;
00278 user->GetExt("ssl_cert", tofree);
00279 delete tofree;
00280 user->Shrink("ssl_cert");
00281 }
00282 }
00283 }
00284
00285 virtual void OnUnloadModule(Module* mod, const std::string &name)
00286 {
00287 if(mod == this)
00288 {
00289 for(unsigned int i = 0; i < listenports.size(); i++)
00290 {
00291 ServerInstance->Config->DelIOHook(listenports[i]);
00292 for (size_t j = 0; j < ServerInstance->Config->ports.size(); j++)
00293 if (ServerInstance->Config->ports[j]->GetPort() == listenports[i])
00294 ServerInstance->Config->ports[j]->SetDescription("plaintext");
00295 }
00296 }
00297 }
00298
00299 virtual Version GetVersion()
00300 {
00301 return Version(1, 1, 0, 0, VF_VENDOR, API_VERSION);
00302 }
00303
00304 void Implements(char* List)
00305 {
00306 List[I_On005Numeric] = List[I_OnRawSocketConnect] = List[I_OnRawSocketAccept] = List[I_OnRawSocketClose] = List[I_OnRawSocketRead] = List[I_OnRawSocketWrite] = List[I_OnCleanup] = 1;
00307 List[I_OnBufferFlushed] = List[I_OnRequest] = List[I_OnSyncUserMetaData] = List[I_OnDecodeMetaData] = List[I_OnUnloadModule] = List[I_OnRehash] = List[I_OnWhois] = List[I_OnPostConnect] = 1;
00308 }
00309
00310 virtual void On005Numeric(std::string &output)
00311 {
00312 output.append(" SSL=" + sslports);
00313 }
00314
00315 virtual char* OnRequest(Request* request)
00316 {
00317 ISHRequest* ISR = (ISHRequest*)request;
00318 if (strcmp("IS_NAME", request->GetId()) == 0)
00319 {
00320 return "gnutls";
00321 }
00322 else if (strcmp("IS_HOOK", request->GetId()) == 0)
00323 {
00324 char* ret = "OK";
00325 try
00326 {
00327 ret = ServerInstance->Config->AddIOHook((Module*)this, (InspSocket*)ISR->Sock) ? (char*)"OK" : NULL;
00328 }
00329 catch (ModuleException &e)
00330 {
00331 return NULL;
00332 }
00333 return ret;
00334 }
00335 else if (strcmp("IS_UNHOOK", request->GetId()) == 0)
00336 {
00337 return ServerInstance->Config->DelIOHook((InspSocket*)ISR->Sock) ? (char*)"OK" : NULL;
00338 }
00339 else if (strcmp("IS_HSDONE", request->GetId()) == 0)
00340 {
00341 if (ISR->Sock->GetFd() < 0)
00342 return (char*)"OK";
00343
00344 issl_session* session = &sessions[ISR->Sock->GetFd()];
00345 return (session->status == ISSL_HANDSHAKING_READ || session->status == ISSL_HANDSHAKING_WRITE) ? NULL : (char*)"OK";
00346 }
00347 else if (strcmp("IS_ATTACH", request->GetId()) == 0)
00348 {
00349 if (ISR->Sock->GetFd() > -1)
00350 {
00351 issl_session* session = &sessions[ISR->Sock->GetFd()];
00352 if (session->sess)
00353 {
00354 if ((Extensible*)ServerInstance->FindDescriptor(ISR->Sock->GetFd()) == (Extensible*)(ISR->Sock))
00355 {
00356 VerifyCertificate(session, (InspSocket*)ISR->Sock);
00357 return "OK";
00358 }
00359 }
00360 }
00361 }
00362 return NULL;
00363 }
00364
00365
00366 virtual void OnRawSocketAccept(int fd, const std::string &ip, int localport)
00367 {
00368
00369 if ((fd < 0) || (fd > MAX_DESCRIPTORS))
00370 return;
00371
00372 issl_session* session = &sessions[fd];
00373
00374 session->fd = fd;
00375 session->inbuf = new char[inbufsize];
00376 session->inbufoffset = 0;
00377
00378 gnutls_init(&session->sess, GNUTLS_SERVER);
00379
00380 gnutls_set_default_priority(session->sess);
00381 gnutls_credentials_set(session->sess, GNUTLS_CRD_CERTIFICATE, x509_cred);
00382 gnutls_dh_set_prime_bits(session->sess, dh_bits);
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392 gnutls_transport_set_ptr(session->sess, (gnutls_transport_ptr_t) fd);
00393
00394 gnutls_certificate_server_set_request(session->sess, GNUTLS_CERT_REQUEST);
00395
00396 Handshake(session);
00397 }
00398
00399 virtual void OnRawSocketConnect(int fd)
00400 {
00401
00402 if ((fd < 0) || (fd > MAX_DESCRIPTORS))
00403 return;
00404
00405 issl_session* session = &sessions[fd];
00406
00407 session->fd = fd;
00408 session->inbuf = new char[inbufsize];
00409 session->inbufoffset = 0;
00410
00411 gnutls_init(&session->sess, GNUTLS_CLIENT);
00412
00413 gnutls_set_default_priority(session->sess);
00414 gnutls_credentials_set(session->sess, GNUTLS_CRD_CERTIFICATE, x509_cred);
00415 gnutls_dh_set_prime_bits(session->sess, dh_bits);
00416 gnutls_transport_set_ptr(session->sess, (gnutls_transport_ptr_t) fd);
00417
00418 Handshake(session);
00419 }
00420
00421 virtual void OnRawSocketClose(int fd)
00422 {
00423
00424 if ((fd < 0) || (fd > MAX_DESCRIPTORS))
00425 return;
00426
00427 CloseSession(&sessions[fd]);
00428
00429 EventHandler* user = ServerInstance->SE->GetRef(fd);
00430
00431 if ((user) && (user->GetExt("ssl_cert", dummy)))
00432 {
00433 ssl_cert* tofree;
00434 user->GetExt("ssl_cert", tofree);
00435 delete tofree;
00436 user->Shrink("ssl_cert");
00437 }
00438 }
00439
00440 virtual int OnRawSocketRead(int fd, char* buffer, unsigned int count, int &readresult)
00441 {
00442
00443 if ((fd < 0) || (fd > MAX_DESCRIPTORS))
00444 return 0;
00445
00446 issl_session* session = &sessions[fd];
00447
00448 if (!session->sess)
00449 {
00450 readresult = 0;
00451 CloseSession(session);
00452 return 1;
00453 }
00454
00455 if (session->status == ISSL_HANDSHAKING_READ)
00456 {
00457
00458
00459 if(!Handshake(session))
00460 {
00461
00462 return -1;
00463 }
00464 }
00465 else if (session->status == ISSL_HANDSHAKING_WRITE)
00466 {
00467 errno = EAGAIN;
00468 MakePollWrite(session);
00469 return -1;
00470 }
00471
00472
00473
00474 if (session->status == ISSL_HANDSHAKEN)
00475 {
00476
00477
00478 int ret = gnutls_record_recv(session->sess, session->inbuf + session->inbufoffset, inbufsize - session->inbufoffset);
00479
00480 if (ret == 0)
00481 {
00482
00483 readresult = 0;
00484 CloseSession(session);
00485 return 1;
00486 }
00487 else if (ret < 0)
00488 {
00489 if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED)
00490 {
00491 errno = EAGAIN;
00492 return -1;
00493 }
00494 else
00495 {
00496 readresult = 0;
00497 CloseSession(session);
00498 }
00499 }
00500 else
00501 {
00502
00503
00504
00505
00506 unsigned int length = ret + session->inbufoffset;
00507
00508 if(count <= length)
00509 {
00510 memcpy(buffer, session->inbuf, count);
00511
00512 memmove(session->inbuf, session->inbuf + count, (length - count));
00513
00514 session->inbufoffset = length - count;
00515
00516 readresult = count;
00517 }
00518 else
00519 {
00520
00521 memcpy(buffer, session->inbuf, length);
00522
00523 session->inbufoffset = 0;
00524
00525 readresult = length;
00526 }
00527 }
00528 }
00529 else if(session->status == ISSL_CLOSING)
00530 readresult = 0;
00531
00532 return 1;
00533 }
00534
00535 virtual int OnRawSocketWrite(int fd, const char* buffer, int count)
00536 {
00537
00538 if ((fd < 0) || (fd > MAX_DESCRIPTORS))
00539 return 0;
00540
00541 issl_session* session = &sessions[fd];
00542 const char* sendbuffer = buffer;
00543
00544 if (!session->sess)
00545 {
00546 CloseSession(session);
00547 return 1;
00548 }
00549
00550 session->outbuf.append(sendbuffer, count);
00551 sendbuffer = session->outbuf.c_str();
00552 count = session->outbuf.size();
00553
00554 if (session->status == ISSL_HANDSHAKING_WRITE || session->status == ISSL_HANDSHAKING_READ)
00555 {
00556
00557 Handshake(session);
00558 errno = EAGAIN;
00559 return -1;
00560 }
00561
00562 int ret = 0;
00563
00564 if (session->status == ISSL_HANDSHAKEN)
00565 {
00566 ret = gnutls_record_send(session->sess, sendbuffer, count);
00567
00568 if (ret == 0)
00569 {
00570 CloseSession(session);
00571 }
00572 else if (ret < 0)
00573 {
00574 if(ret != GNUTLS_E_AGAIN && ret != GNUTLS_E_INTERRUPTED)
00575 {
00576 CloseSession(session);
00577 }
00578 else
00579 {
00580 errno = EAGAIN;
00581 }
00582 }
00583 else
00584 {
00585 session->outbuf = session->outbuf.substr(ret);
00586 }
00587 }
00588
00589 MakePollWrite(session);
00590
00591
00592
00593
00594 return ret < 1 ? 0 : ret;
00595 }
00596
00597
00598 virtual void OnWhois(userrec* source, userrec* dest)
00599 {
00600 if (!clientactive)
00601 return;
00602
00603
00604 if(dest->GetExt("ssl", dummy) || (IS_LOCAL(dest) && isin(dest->GetPort(), listenports)))
00605 {
00606 ServerInstance->SendWhoisLine(source, dest, 320, "%s %s :is using a secure connection", source->nick, dest->nick);
00607 }
00608 }
00609
00610 virtual void OnSyncUserMetaData(userrec* user, Module* proto, void* opaque, const std::string &extname, bool displayable)
00611 {
00612
00613 if(extname == "ssl")
00614 {
00615
00616 if(user->GetExt(extname, dummy))
00617 {
00618
00619
00620 proto->ProtoSendMetaData(opaque, TYPE_USER, user, extname, displayable ? "Enabled" : "ON");
00621 }
00622 }
00623 }
00624
00625 virtual void OnDecodeMetaData(int target_type, void* target, const std::string &extname, const std::string &extdata)
00626 {
00627
00628 if ((target_type == TYPE_USER) && (extname == "ssl"))
00629 {
00630 userrec* dest = (userrec*)target;
00631
00632 if (!dest->GetExt(extname, dummy))
00633 {
00634 dest->Extend(extname, "ON");
00635 }
00636 }
00637 }
00638
00639 bool Handshake(issl_session* session)
00640 {
00641 int ret = gnutls_handshake(session->sess);
00642
00643 if (ret < 0)
00644 {
00645 if(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED)
00646 {
00647
00648
00649 if(gnutls_record_get_direction(session->sess) == 0)
00650 {
00651
00652 session->status = ISSL_HANDSHAKING_READ;
00653 }
00654 else
00655 {
00656
00657 session->status = ISSL_HANDSHAKING_WRITE;
00658 MakePollWrite(session);
00659 }
00660 }
00661 else
00662 {
00663
00664 CloseSession(session);
00665 session->status = ISSL_CLOSING;
00666 }
00667
00668 return false;
00669 }
00670 else
00671 {
00672
00673
00674 userrec* extendme = ServerInstance->FindDescriptor(session->fd);
00675 if (extendme)
00676 {
00677 if (!extendme->GetExt("ssl", dummy))
00678 extendme->Extend("ssl", "ON");
00679 }
00680
00681
00682 session->status = ISSL_HANDSHAKEN;
00683
00684
00685 MakePollWrite(session);
00686
00687 return true;
00688 }
00689 }
00690
00691 virtual void OnPostConnect(userrec* user)
00692 {
00693
00694
00695 if ((user->GetExt("ssl", dummy)) && (IS_LOCAL(user)))
00696 {
00697
00698 std::deque<std::string>* metadata = new std::deque<std::string>;
00699 metadata->push_back(user->nick);
00700 metadata->push_back("ssl");
00701 metadata->push_back("ON");
00702 Event* event = new Event((char*)metadata,(Module*)this,"send_metadata");
00703 event->Send(ServerInstance);
00704 DELETE(event);
00705 DELETE(metadata);
00706
00707 VerifyCertificate(&sessions[user->GetFd()],user);
00708 if (sessions[user->GetFd()].sess)
00709 {
00710 std::string cipher = gnutls_kx_get_name(gnutls_kx_get(sessions[user->GetFd()].sess));
00711 cipher.append("-").append(gnutls_cipher_get_name(gnutls_cipher_get(sessions[user->GetFd()].sess))).append("-");
00712 cipher.append(gnutls_mac_get_name(gnutls_mac_get(sessions[user->GetFd()].sess)));
00713 user->WriteServ("NOTICE %s :*** You are connected using SSL cipher \"%s\"", user->nick, cipher.c_str());
00714 }
00715 }
00716 }
00717
00718 void MakePollWrite(issl_session* session)
00719 {
00720
00721 EventHandler* eh = ServerInstance->FindDescriptor(session->fd);
00722 if (eh)
00723 ServerInstance->SE->WantWrite(eh);
00724 }
00725
00726 virtual void OnBufferFlushed(userrec* user)
00727 {
00728 if (user->GetExt("ssl"))
00729 {
00730 issl_session* session = &sessions[user->GetFd()];
00731 if (session && session->outbuf.size())
00732 OnRawSocketWrite(user->GetFd(), NULL, 0);
00733 }
00734 }
00735
00736 void CloseSession(issl_session* session)
00737 {
00738 if(session->sess)
00739 {
00740 gnutls_bye(session->sess, GNUTLS_SHUT_WR);
00741 gnutls_deinit(session->sess);
00742 }
00743
00744 if(session->inbuf)
00745 {
00746 delete[] session->inbuf;
00747 }
00748
00749 session->outbuf.clear();
00750 session->inbuf = NULL;
00751 session->sess = NULL;
00752 session->status = ISSL_NONE;
00753 }
00754
00755 void VerifyCertificate(issl_session* session, Extensible* user)
00756 {
00757 if (!session->sess || !user)
00758 return;
00759
00760 unsigned int status;
00761 const gnutls_datum_t* cert_list;
00762 int ret;
00763 unsigned int cert_list_size;
00764 gnutls_x509_crt_t cert;
00765 char name[MAXBUF];
00766 unsigned char digest[MAXBUF];
00767 size_t digest_size = sizeof(digest);
00768 size_t name_size = sizeof(name);
00769 ssl_cert* certinfo = new ssl_cert;
00770
00771 user->Extend("ssl_cert",certinfo);
00772
00773
00774
00775
00776 ret = gnutls_certificate_verify_peers2(session->sess, &status);
00777
00778 if (ret < 0)
00779 {
00780 certinfo->data.insert(std::make_pair("error",std::string(gnutls_strerror(ret))));
00781 return;
00782 }
00783
00784 if (status & GNUTLS_CERT_INVALID)
00785 {
00786 certinfo->data.insert(std::make_pair("invalid",ConvToStr(1)));
00787 }
00788 else
00789 {
00790 certinfo->data.insert(std::make_pair("invalid",ConvToStr(0)));
00791 }
00792 if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
00793 {
00794 certinfo->data.insert(std::make_pair("unknownsigner",ConvToStr(1)));
00795 }
00796 else
00797 {
00798 certinfo->data.insert(std::make_pair("unknownsigner",ConvToStr(0)));
00799 }
00800 if (status & GNUTLS_CERT_REVOKED)
00801 {
00802 certinfo->data.insert(std::make_pair("revoked",ConvToStr(1)));
00803 }
00804 else
00805 {
00806 certinfo->data.insert(std::make_pair("revoked",ConvToStr(0)));
00807 }
00808 if (status & GNUTLS_CERT_SIGNER_NOT_CA)
00809 {
00810 certinfo->data.insert(std::make_pair("trusted",ConvToStr(0)));
00811 }
00812 else
00813 {
00814 certinfo->data.insert(std::make_pair("trusted",ConvToStr(1)));
00815 }
00816
00817
00818
00819
00820
00821 if (gnutls_certificate_type_get(session->sess) != GNUTLS_CRT_X509)
00822 {
00823 certinfo->data.insert(std::make_pair("error","No X509 keys sent"));
00824 return;
00825 }
00826
00827 ret = gnutls_x509_crt_init(&cert);
00828 if (ret < 0)
00829 {
00830 certinfo->data.insert(std::make_pair("error",gnutls_strerror(ret)));
00831 return;
00832 }
00833
00834 cert_list_size = 0;
00835 cert_list = gnutls_certificate_get_peers(session->sess, &cert_list_size);
00836 if (cert_list == NULL)
00837 {
00838 certinfo->data.insert(std::make_pair("error","No certificate was found"));
00839 return;
00840 }
00841
00842
00843
00844
00845
00846 ret = gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER);
00847 if (ret < 0)
00848 {
00849 certinfo->data.insert(std::make_pair("error",gnutls_strerror(ret)));
00850 return;
00851 }
00852
00853 gnutls_x509_crt_get_dn(cert, name, &name_size);
00854
00855 certinfo->data.insert(std::make_pair("dn",name));
00856
00857 gnutls_x509_crt_get_issuer_dn(cert, name, &name_size);
00858
00859 certinfo->data.insert(std::make_pair("issuer",name));
00860
00861 if ((ret = gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_MD5, digest, &digest_size)) < 0)
00862 {
00863 certinfo->data.insert(std::make_pair("error",gnutls_strerror(ret)));
00864 }
00865 else
00866 {
00867 certinfo->data.insert(std::make_pair("fingerprint",irc::hex(digest, digest_size)));
00868 }
00869
00870
00871
00872 if ((gnutls_x509_crt_get_expiration_time(cert) < time(0)) || (gnutls_x509_crt_get_activation_time(cert) > time(0)))
00873 {
00874 certinfo->data.insert(std::make_pair("error","Not activated, or expired certificate"));
00875 }
00876
00877 gnutls_x509_crt_deinit(cert);
00878
00879 return;
00880 }
00881
00882 };
00883
00884 MODULE_INIT(ModuleSSLGnuTLS);
00885