m_ssl.cpp

Go to the documentation of this file.
00001 /* RequiredLibraries: ssl,crypto */
00002 
00003 #include "module.h"
00004 #include "ssl.h"
00005 
00006 #define OPENSSL_NO_SHA512
00007 #include <openssl/bio.h>
00008 #include <openssl/ssl.h>
00009 #include <openssl/err.h>
00010 #include <openssl/crypto.h>
00011 #include <openssl/evp.h>
00012 
00013 static SSL_CTX *server_ctx, *client_ctx;
00014 
00015 class MySSLService : public SSLService
00016 {
00017  public:
00018         MySSLService(Module *o, const Anope::string &n);
00019 
00023         void Init(Socket *s) anope_override;
00024 };
00025 
00026 class SSLSocketIO : public SocketIO
00027 {
00028  public:
00029         /* The SSL socket for this socket */
00030         SSL *sslsock;
00031 
00034         SSLSocketIO();
00035 
00042         int Recv(Socket *s, char *buf, size_t sz) anope_override;
00043 
00049         int Send(Socket *s, const char *buf, size_t sz) anope_override;
00050 
00055         ClientSocket *Accept(ListenSocket *s) anope_override;
00056 
00061         SocketFlag FinishAccept(ClientSocket *cs) anope_override;
00062 
00068         void Connect(ConnectionSocket *s, const Anope::string &target, int port) anope_override;
00069 
00074         SocketFlag FinishConnect(ConnectionSocket *s) anope_override;
00075 
00078         void Destroy() anope_override;
00079 };
00080 
00081 class SSLModule;
00082 static SSLModule *me;
00083 class SSLModule : public Module
00084 {
00085         static int AlwaysAccept(int, X509_STORE_CTX *)
00086         {
00087                 return 1;
00088         }
00089 
00090         Anope::string certfile, keyfile;
00091 
00092  public:
00093         MySSLService service;
00094 
00095         SSLModule(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, SUPPORTED), service(this, "ssl")
00096         {
00097                 me = this;
00098 
00099                 this->SetAuthor("Anope");
00100                 this->SetPermanent(true);
00101 
00102                 SSL_library_init();
00103                 SSL_load_error_strings();
00104 
00105                 client_ctx = SSL_CTX_new(SSLv23_client_method());
00106                 server_ctx = SSL_CTX_new(SSLv23_server_method());
00107 
00108                 if (!client_ctx || !server_ctx)
00109                         throw ModuleException("Error initializing SSL CTX");
00110 
00111                 this->OnReload();
00112 
00113                 if (Anope::IsFile(this->certfile.c_str()))
00114                 {
00115                         if (!SSL_CTX_use_certificate_file(client_ctx, this->certfile.c_str(), SSL_FILETYPE_PEM) || !SSL_CTX_use_certificate_file(server_ctx, this->certfile.c_str(), SSL_FILETYPE_PEM))
00116                         {
00117                                 SSL_CTX_free(client_ctx);
00118                                 SSL_CTX_free(server_ctx);
00119                                 throw ModuleException("Error loading certificate");
00120                         }
00121                         else
00122                                 Log(LOG_DEBUG) << "m_ssl: Successfully loaded certificate " << this->certfile;
00123                 }
00124                 else
00125                         Log() << "Unable to open certificate " << this->certfile;
00126 
00127                 if (Anope::IsFile(this->keyfile.c_str()))
00128                 {
00129                         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))
00130                         {
00131                                 SSL_CTX_free(client_ctx);
00132                                 SSL_CTX_free(server_ctx);
00133                                 throw ModuleException("Error loading private key");
00134                         }
00135                         else
00136                                 Log(LOG_DEBUG) << "m_ssl: Successfully loaded private key " << this->keyfile;
00137                 }
00138                 else
00139                 {
00140                         if (Anope::IsFile(this->certfile.c_str()))
00141                         {
00142                                 SSL_CTX_free(client_ctx);
00143                                 SSL_CTX_free(server_ctx);
00144                                 throw ModuleException("Error loading private key " + this->keyfile + " - file not found");
00145                         }
00146                         else
00147                                 Log() << "Unable to open private key " << this->keyfile;
00148                 }
00149 
00150                 SSL_CTX_set_mode(client_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
00151                 SSL_CTX_set_mode(server_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
00152 
00153                 SSL_CTX_set_verify(client_ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, SSLModule::AlwaysAccept);
00154                 SSL_CTX_set_verify(server_ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, SSLModule::AlwaysAccept);
00155 
00156                 Anope::string context_name = "Anope";
00157                 SSL_CTX_set_session_id_context(client_ctx, reinterpret_cast<const unsigned char *>(context_name.c_str()), context_name.length());
00158                 SSL_CTX_set_session_id_context(server_ctx, reinterpret_cast<const unsigned char *>(context_name.c_str()), context_name.length());
00159 
00160                 ModuleManager::Attach(I_OnReload, this);
00161                 ModuleManager::Attach(I_OnPreServerConnect, this);
00162         }
00163 
00164         ~SSLModule()
00165         {
00166                 for (std::map<int, Socket *>::const_iterator it = SocketEngine::Sockets.begin(), it_end = SocketEngine::Sockets.end(); it != it_end;)
00167                 {
00168                         Socket *s = it->second;
00169                         ++it;
00170 
00171                         if (dynamic_cast<SSLSocketIO *>(s->io))
00172                                 delete s;
00173                 }
00174 
00175                 SSL_CTX_free(client_ctx);
00176                 SSL_CTX_free(server_ctx);
00177         }
00178 
00179         void OnReload() anope_override
00180         {
00181                 ConfigReader config;
00182 
00183                 this->certfile = config.ReadValue("ssl", "cert", "data/anope.crt", 0);
00184                 this->keyfile = config.ReadValue("ssl", "key", "data/anope.key", 0);
00185         }
00186 
00187         void OnPreServerConnect() anope_override
00188         {
00189                 ConfigReader config;
00190 
00191                 if (config.ReadFlag("uplink", "ssl", "no", Anope::CurrentUplink))
00192                 {
00193                         this->service.Init(UplinkSock);
00194                 }
00195         }
00196 };
00197 
00198 MySSLService::MySSLService(Module *o, const Anope::string &n) : SSLService(o, n)
00199 {
00200 }
00201 
00202 void MySSLService::Init(Socket *s)
00203 {
00204         if (s->io != &NormalSocketIO)
00205                 throw CoreException("Socket initializing SSL twice");
00206         
00207         s->io = new SSLSocketIO();
00208 }
00209 
00210 SSLSocketIO::SSLSocketIO()
00211 {
00212         this->sslsock = NULL;
00213 }
00214 
00215 int SSLSocketIO::Recv(Socket *s, char *buf, size_t sz)
00216 {
00217         int i = SSL_read(this->sslsock, buf, sz);
00218         TotalRead += i;
00219         return i;
00220 }
00221 
00222 int SSLSocketIO::Send(Socket *s, const char *buf, size_t sz)
00223 {
00224         int i = SSL_write(this->sslsock, buf, sz);
00225         TotalWritten += i;
00226         return i;
00227 }
00228 
00229 ClientSocket *SSLSocketIO::Accept(ListenSocket *s)
00230 {
00231         if (s->io == &NormalSocketIO)
00232                 throw SocketException("Attempting to accept on uninitialized socket with SSL");
00233 
00234         sockaddrs conaddr;
00235 
00236         socklen_t size = sizeof(conaddr);
00237         int newsock = accept(s->GetFD(), &conaddr.sa, &size);
00238 
00239 #ifndef INVALID_SOCKET
00240         const int INVALID_SOCKET = -1;
00241 #endif
00242 
00243         if (newsock < 0 || newsock == INVALID_SOCKET)
00244                 throw SocketException("Unable to accept connection: " + Anope::LastError());
00245 
00246         ClientSocket *newsocket = s->OnAccept(newsock, conaddr);
00247         me->service.Init(newsocket);
00248         SSLSocketIO *io = anope_dynamic_static_cast<SSLSocketIO *>(newsocket->io);
00249 
00250         io->sslsock = SSL_new(server_ctx);
00251         if (!io->sslsock)
00252                 throw SocketException("Unable to initialize SSL socket");
00253 
00254         SSL_set_accept_state(io->sslsock);
00255 
00256         if (!SSL_set_fd(io->sslsock, newsocket->GetFD()))
00257                 throw SocketException("Unable to set SSL fd");
00258 
00259         newsocket->flags[SF_ACCEPTING] = true;
00260         this->FinishAccept(newsocket);
00261         
00262         return newsocket;
00263 }
00264 
00265 SocketFlag SSLSocketIO::FinishAccept(ClientSocket *cs)
00266 {
00267         if (cs->io == &NormalSocketIO)
00268                 throw SocketException("Attempting to finish connect uninitialized socket with SSL");
00269         else if (cs->flags[SF_ACCEPTED])
00270                 return SF_ACCEPTED;
00271         else if (!cs->flags[SF_ACCEPTING])
00272                 throw SocketException("SSLSocketIO::FinishAccept called for a socket not accepted nor accepting?");
00273 
00274         SSLSocketIO *io = anope_dynamic_static_cast<SSLSocketIO *>(cs->io);
00275         
00276         int ret = SSL_accept(io->sslsock);
00277         if (ret <= 0)
00278         {
00279                 int error = SSL_get_error(io->sslsock, ret);
00280                 if (ret == -1 && (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE))
00281                 {
00282                         SocketEngine::Change(cs, error == SSL_ERROR_WANT_WRITE, SF_WRITABLE);
00283                         SocketEngine::Change(cs, error == SSL_ERROR_WANT_READ, SF_READABLE);
00284                         return SF_ACCEPTING;
00285                 }
00286                 else
00287                 {
00288                         cs->OnError(ERR_error_string(ERR_get_error(), NULL));
00289                         cs->flags[SF_DEAD] = true;
00290                         cs->flags[SF_ACCEPTING] = false;
00291                         return SF_DEAD;
00292                 }
00293         }
00294         else
00295         {
00296                 cs->flags[SF_ACCEPTED] = true;
00297                 cs->flags[SF_ACCEPTING] = false;
00298                 SocketEngine::Change(cs, false, SF_WRITABLE);
00299                 SocketEngine::Change(cs, true, SF_READABLE);
00300                 cs->OnAccept();
00301                 return SF_ACCEPTED;
00302         }
00303 }
00304 
00305 void SSLSocketIO::Connect(ConnectionSocket *s, const Anope::string &target, int port)
00306 {
00307         if (s->io == &NormalSocketIO)
00308                 throw SocketException("Attempting to connect uninitialized socket with SSL");
00309 
00310         s->flags[SF_CONNECTING] = s->flags[SF_CONNECTED] = false;
00311 
00312         s->conaddr.pton(s->IsIPv6() ? AF_INET6 : AF_INET, target, port);
00313         int c = connect(s->GetFD(), &s->conaddr.sa, s->conaddr.size());
00314         if (c == -1)
00315         {
00316                 if (Anope::LastErrorCode() != EINPROGRESS)
00317                 {
00318                         s->OnError(Anope::LastError());
00319                         s->flags[SF_DEAD] = true;
00320                         return;
00321                 }
00322                 else
00323                 {
00324                         SocketEngine::Change(s, true, SF_WRITABLE);
00325                         s->flags[SF_CONNECTING] = true;
00326                         return;
00327                 }
00328         }
00329         else
00330         {
00331                 s->flags[SF_CONNECTING] = true;
00332                 this->FinishConnect(s);
00333         }
00334 }
00335 
00336 SocketFlag SSLSocketIO::FinishConnect(ConnectionSocket *s)
00337 {
00338         if (s->io == &NormalSocketIO)
00339                 throw SocketException("Attempting to finish connect uninitialized socket with SSL");
00340         else if (s->flags[SF_CONNECTED])
00341                 return SF_CONNECTED;
00342         else if (!s->flags[SF_CONNECTING])
00343                 throw SocketException("SSLSocketIO::FinishConnect called for a socket not connected nor connecting?");
00344 
00345         SSLSocketIO *io = anope_dynamic_static_cast<SSLSocketIO *>(s->io);
00346 
00347         if (io->sslsock == NULL)
00348         {
00349                 io->sslsock = SSL_new(client_ctx);
00350                 if (!io->sslsock)
00351                         throw SocketException("Unable to initialize SSL socket");
00352 
00353                 if (!SSL_set_fd(io->sslsock, s->GetFD()))
00354                         throw SocketException("Unable to set SSL fd");
00355         }
00356         
00357         int ret = SSL_connect(io->sslsock);
00358         if (ret <= 0)
00359         {
00360                 int error = SSL_get_error(io->sslsock, ret);
00361                 if (ret == -1 && (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE))
00362                 {
00363                         SocketEngine::Change(s, error == SSL_ERROR_WANT_WRITE, SF_WRITABLE);
00364                         SocketEngine::Change(s, error == SSL_ERROR_WANT_READ, SF_READABLE);
00365                         return SF_CONNECTING;
00366                 }
00367                 else
00368                 {
00369                         s->OnError(ERR_error_string(ERR_get_error(), NULL));
00370                         s->flags[SF_CONNECTING] = false;
00371                         s->flags[SF_DEAD] = true;
00372                         return SF_DEAD;
00373                 }
00374         }
00375         else
00376         {
00377                 s->flags[SF_CONNECTING] = false;
00378                 s->flags[SF_CONNECTED] = true;
00379                 SocketEngine::Change(s, false, SF_WRITABLE);
00380                 SocketEngine::Change(s, true, SF_READABLE);
00381                 s->OnConnect();
00382                 return SF_CONNECTED;
00383         }
00384 }
00385 
00386 void SSLSocketIO::Destroy()
00387 {
00388         if (this->sslsock)
00389         {
00390                 SSL_shutdown(this->sslsock);
00391                 SSL_free(this->sslsock);
00392         }
00393 
00394         delete this;
00395 }
00396 
00397 MODULE_INIT(SSLModule)