"Fossies" - the Fresh Open Source Software Archive

Member "bahamut-2.1.5/src/ssl.c" (28 May 2020, 8758 Bytes) of package /linux/privat/bahamut-2.1.5.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ssl.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.1.4_vs_2.1.5.

    1 /************************************************************************
    2  *   IRC - Internet Relay Chat, src/ssl.c
    3  *   Copyright (C) 2002 Barnaba Marcello <vjt@azzurra.org>
    4  *
    5  *   This program is free software; you can redistribute it and/or modify
    6  *   it under the terms of the GNU General Public License as published by
    7  *   the Free Software Foundation; either version 1, or (at your option)
    8  *   any later version.
    9  *
   10  *   This program is distributed in the hope that it will be useful,
   11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
   12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13  *   GNU General Public License for more details.
   14  *
   15  *   You should have received a copy of the GNU General Public License
   16  *   along with this program; if not, write to the Free Software
   17  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   18  *   
   19  *   SSL functions . . .
   20  */
   21 
   22 #include "struct.h"
   23 #include "common.h"
   24 #include "sys.h"
   25 #include <sys/types.h>
   26 #include "h.h"
   27 
   28 #ifdef USE_SSL
   29 
   30 
   31 #define SAFE_SSL_READ   1
   32 #define SAFE_SSL_WRITE  2
   33 #define SAFE_SSL_ACCEPT 3
   34 
   35 extern int errno;
   36 
   37 SSL_CTX *ircdssl_ctx;
   38 int ssl_capable = 0;
   39 
   40 int ssl_init()
   41 {
   42     FILE *file;
   43 
   44     if(!(file = fopen(IRCDSSL_CPATH,"r")))
   45     {
   46         fprintf(stderr, "Can't open %s!\n", IRCDSSL_CPATH);
   47         return 0;
   48     }
   49     fclose(file);
   50 
   51     if(!(file = fopen(IRCDSSL_KPATH,"r")))
   52     {
   53         fprintf(stderr, "Can't open %s!\n", IRCDSSL_KPATH);
   54         return 0;
   55     }
   56     fclose(file);
   57 
   58     SSL_load_error_strings();
   59     SSLeay_add_ssl_algorithms();
   60 #if OPENSSL_VERSION_NUMBER < 0x10100000L
   61     ircdssl_ctx = SSL_CTX_new(SSLv23_server_method());
   62 #else
   63     ircdssl_ctx = SSL_CTX_new(TLS_server_method());
   64 #endif
   65 
   66     if(!ircdssl_ctx)
   67     {
   68     ERR_print_errors_fp(stderr);
   69     return 0;
   70     }
   71 
   72     if(SSL_CTX_use_certificate_chain_file(ircdssl_ctx, IRCDSSL_CPATH) <= 0)
   73     {
   74     ERR_print_errors_fp(stderr);
   75     SSL_CTX_free(ircdssl_ctx);
   76     return 0;
   77     }
   78 
   79     if(SSL_CTX_use_PrivateKey_file(ircdssl_ctx,
   80         IRCDSSL_KPATH, SSL_FILETYPE_PEM) <= 0)
   81     {
   82     ERR_print_errors_fp(stderr);
   83     SSL_CTX_free(ircdssl_ctx);
   84     return 0;
   85     }
   86 
   87     if(!SSL_CTX_check_private_key(ircdssl_ctx))
   88     {
   89     fprintf(stderr, "Server certificate does not match Server key");
   90     SSL_CTX_free(ircdssl_ctx);
   91     return 0;
   92     }
   93 
   94     return 1;
   95 }
   96 
   97 static void abort_ssl_rehash(int do_errors)
   98 {
   99     if(do_errors)
  100     {
  101         char buf[256];
  102         unsigned long e;
  103 
  104         while((e = ERR_get_error()))
  105         {
  106             ERR_error_string_n(e, buf, sizeof(buf) - 1);
  107             sendto_realops("SSL ERROR: %s", buf);
  108         }
  109     }
  110 
  111     sendto_realops("Aborting SSL rehash due to error(s) detected during rehash. Using current SSL configuration.");
  112 
  113     return;
  114 }
  115 
  116 int ssl_rehash()
  117 {
  118     FILE *file;
  119     SSL_CTX *temp_ircdssl_ctx;
  120 
  121     if(!(file = fopen(IRCDSSL_CPATH,"r")))
  122     {
  123         sendto_realops("SSL ERROR: Cannot open server certificate file.");
  124         abort_ssl_rehash(0);
  125 
  126         return 0;
  127     }
  128     fclose(file);
  129 
  130     if(!(file = fopen(IRCDSSL_KPATH,"r")))
  131     {
  132         sendto_realops("SSL ERROR: Cannot open server key file.");
  133         abort_ssl_rehash(0);
  134 
  135         return 0;
  136     }
  137     fclose(file);
  138 
  139 #if OPENSSL_VERSION_NUMBER < 0x10100000L
  140     if(!(temp_ircdssl_ctx = SSL_CTX_new(SSLv23_server_method())))
  141 #else
  142     if(!(temp_ircdssl_ctx = SSL_CTX_new(TLS_server_method())))
  143 #endif
  144     {
  145         abort_ssl_rehash(1);
  146 
  147         return 0;
  148     }
  149 
  150     if(SSL_CTX_use_certificate_chain_file(temp_ircdssl_ctx, IRCDSSL_CPATH) <= 0)
  151     {
  152         abort_ssl_rehash(1);
  153         if(temp_ircdssl_ctx) {
  154             SSL_CTX_free(temp_ircdssl_ctx);
  155         }
  156 
  157         return 0;
  158     }
  159 
  160     if(SSL_CTX_use_PrivateKey_file(temp_ircdssl_ctx,
  161         IRCDSSL_KPATH, SSL_FILETYPE_PEM) <= 0)
  162     {
  163         abort_ssl_rehash(1);
  164         if(temp_ircdssl_ctx) {
  165             SSL_CTX_free(temp_ircdssl_ctx);
  166         }
  167 
  168         return 0;
  169     }
  170 
  171     if(!SSL_CTX_check_private_key(temp_ircdssl_ctx))
  172     {
  173         sendto_realops("SSL ERROR: Server certificate does not match server key");
  174         abort_ssl_rehash(0);
  175         if(temp_ircdssl_ctx) {
  176             SSL_CTX_free(temp_ircdssl_ctx);
  177         }
  178 
  179         return 0;
  180     }
  181 
  182     if(ircdssl_ctx) {
  183         SSL_CTX_free(ircdssl_ctx);
  184     }
  185 
  186     ircdssl_ctx = temp_ircdssl_ctx;
  187 
  188     return 1;
  189 }
  190 
  191 static int fatal_ssl_error(int, int, aClient *);
  192 
  193 int safe_ssl_read(aClient *acptr, void *buf, int sz)
  194 {
  195     int len, ssl_err;
  196 
  197     len = SSL_read(acptr->ssl, buf, sz);
  198     if (len <= 0)
  199     {
  200     switch(ssl_err = SSL_get_error(acptr->ssl, len))
  201         {
  202         case SSL_ERROR_SYSCALL:
  203         if(errno == EWOULDBLOCK || errno == EAGAIN ||
  204             errno == EINTR)
  205                 {
  206         case SSL_ERROR_WANT_READ:
  207             errno = EWOULDBLOCK;
  208             return -1;
  209         }
  210         case SSL_ERROR_SSL:
  211         if(errno == EAGAIN)
  212             return -1;
  213         default:
  214         return fatal_ssl_error(ssl_err, SAFE_SSL_READ, acptr);
  215     }
  216     }
  217     return len;
  218 }
  219 
  220 int safe_ssl_write(aClient *acptr, const void *buf, int sz)
  221 {
  222     int len, ssl_err;
  223 
  224     len = SSL_write(acptr->ssl, buf, sz);
  225     if (len <= 0)
  226     {
  227     switch(ssl_err = SSL_get_error(acptr->ssl, len))
  228         {
  229         case SSL_ERROR_SYSCALL:
  230         if(errno == EWOULDBLOCK || errno == EAGAIN ||
  231             errno == EINTR)
  232                 {
  233         case SSL_ERROR_WANT_WRITE:
  234         case SSL_ERROR_WANT_READ:
  235             errno = EWOULDBLOCK;
  236             return -1;
  237         }
  238         case SSL_ERROR_SSL:
  239         if(errno == EAGAIN)
  240             return -1;
  241         default:
  242         return fatal_ssl_error(ssl_err, SAFE_SSL_WRITE, acptr);
  243         }
  244     }
  245     return len;
  246 }
  247 
  248 int safe_ssl_accept(aClient *acptr, int fd)
  249 {
  250 
  251     int ssl_err;
  252 
  253     if((ssl_err = SSL_accept(acptr->ssl)) <= 0)
  254     {
  255     switch(ssl_err = SSL_get_error(acptr->ssl, ssl_err))
  256         {
  257         case SSL_ERROR_SYSCALL:
  258         if(errno == EINTR || errno == EWOULDBLOCK
  259             || errno == EAGAIN)
  260         case SSL_ERROR_WANT_READ:
  261         case SSL_ERROR_WANT_WRITE:
  262             /* handshake will be completed later . . */
  263             return 1;
  264         default:
  265         return fatal_ssl_error(ssl_err, SAFE_SSL_ACCEPT, acptr);
  266         
  267     }
  268     /* NOTREACHED */
  269     return -1;
  270     }
  271     return 1;
  272 }
  273 
  274 int ssl_smart_shutdown(SSL *ssl) {
  275     char i;
  276     int rc;
  277 
  278     rc = 0;
  279     for(i = 0; i < 4; i++)
  280     {
  281     if((rc = SSL_shutdown(ssl)))
  282         break;
  283     }
  284 
  285     return rc;
  286 }
  287 
  288 static int fatal_ssl_error(int ssl_error, int where, aClient *sptr)
  289 {
  290     /* don`t alter errno */
  291     int errtmp = errno;
  292     char *errstr = strerror(errtmp);
  293     char *ssl_errstr, *ssl_func;
  294 
  295     switch(where)
  296     {
  297     case SAFE_SSL_READ:
  298         ssl_func = "SSL_read()";
  299         break;
  300     case SAFE_SSL_WRITE:
  301         ssl_func = "SSL_write()";
  302         break;
  303     case SAFE_SSL_ACCEPT:
  304         ssl_func = "SSL_accept()";
  305         break;
  306     default:
  307         ssl_func = "undefined SSL func [this is a bug] report to coders@dal.net";
  308     }
  309 
  310     switch(ssl_error)
  311     {
  312         case SSL_ERROR_NONE:
  313         ssl_errstr = "No error";
  314         break;
  315     case SSL_ERROR_SSL:
  316         ssl_errstr = "Internal OpenSSL error or protocol error";
  317         break;
  318     case SSL_ERROR_WANT_READ:
  319         ssl_errstr = "OpenSSL functions requested a read()";
  320         break;
  321     case SSL_ERROR_WANT_WRITE:
  322         ssl_errstr = "OpenSSL functions requested a write()";
  323         break;
  324     case SSL_ERROR_WANT_X509_LOOKUP:
  325         ssl_errstr = "OpenSSL requested a X509 lookup which didn`t arrive";
  326         break;
  327     case SSL_ERROR_SYSCALL:
  328         ssl_errstr = "Underlying syscall error";
  329         break;
  330     case SSL_ERROR_ZERO_RETURN:
  331         ssl_errstr = "Underlying socket operation returned zero";
  332         break;
  333     case SSL_ERROR_WANT_CONNECT:
  334         ssl_errstr = "OpenSSL functions wanted a connect()";
  335         break;
  336     default:
  337         ssl_errstr = "Unknown OpenSSL error (huh?)";
  338     }
  339 
  340     if((ssl_error==SSL_ERROR_SYSCALL || ssl_error==SSL_ERROR_ZERO_RETURN) && errtmp==0)
  341     {
  342         /* Client most likely just closed the connection... -Kobi_S. */
  343         errno = 0; /* Not really an error */
  344         sptr->sockerr = IRCERR_SSL;
  345         sptr->flags |= FLAGS_DEADSOCKET;
  346         return -1;
  347     }
  348 
  349     sendto_realops_lev(DEBUG_LEV, "%s to "
  350         "%s!%s@%s aborted with%serror (%s). [%s]", 
  351         ssl_func, *sptr->name ? sptr->name : "<unknown>",
  352         (sptr->user && sptr->user->username) ? sptr->user->
  353         username : "<unregistered>", sptr->sockhost,
  354         (errno > 0) ? " " : " no ", errstr, ssl_errstr);
  355 #ifdef USE_SYSLOG
  356     syslog(LOG_ERR, "SSL error in %s for %s!%s@%s: %s [%s]", ssl_func,
  357             *sptr->name ? sptr->name : "<unknown>",
  358             (sptr->user && sptr->user->username) ? sptr->user->
  359             username : "<unregistered>", sptr->sockhost,
  360             errstr, ssl_errstr);
  361 #endif
  362 
  363     /* if we reply() something here, we might just trigger another
  364      * fatal_ssl_error() call and loop until a stack overflow... 
  365      * the client won`t get the ERROR : ... string, but this is
  366      * the only way to do it.
  367      * IRC protocol wasn`t SSL enabled .. --vjt
  368      */
  369 
  370     errno = errtmp ? errtmp : EIO; /* Stick a generic I/O error */
  371     sptr->sockerr = IRCERR_SSL;
  372     sptr->flags |= FLAGS_DEADSOCKET;
  373     return -1;
  374 }
  375 #endif