nanohttp-ssl.c

Go to the documentation of this file.
00001 /******************************************************************
00002 *  $Id: nanohttp-ssl.c,v 1.37 2006/12/11 08:13:19 m0gg Exp $
00003 *
00004 * CSOAP Project:  A http client/server library in C
00005 * Copyright (C) 2001-2005  Rochester Institute of Technology
00006 *
00007 * This library is free software; you can redistribute it and/or
00008 * modify it under the terms of the GNU Library General Public
00009 * License as published by the Free Software Foundation; either
00010 * version 2 of the License, or (at your option) any later version.
00011 *
00012 * This library is distributed in the hope that it will be useful,
00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015 * Library General Public License for more details.
00016 *
00017 * You should have received a copy of the GNU Library General Public
00018 * License along with this library; if not, write to the
00019 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00020 * Boston, MA  02111-1307, USA.
00021 *
00022 * Author: Matt Campbell
00023 ******************************************************************/
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027 
00028 #ifdef HAVE_SYS_TYPES_H
00029 #include <sys/types.h>
00030 #endif
00031 
00032 #ifdef HAVE_SYS_TYPES_H
00033 #include <sys/socket.h>
00034 #endif
00035 
00036 #ifdef HAVE_NETINET_IN_H
00037 #include <netinet/in.h>
00038 #endif
00039 
00040 #ifdef HAVE_STRING_H
00041 #include <string.h>
00042 #endif
00043 
00044 #ifdef HAVE_STDLIB_H
00045 #include <stdlib.h>
00046 #endif
00047 
00048 #ifdef HAVE_ERRNO_H
00049 #include <errno.h>
00050 #endif
00051 
00052 #ifdef HAVE_TIME_H
00053 #include <time.h>
00054 #endif
00055 
00056 #ifdef HAVE_FCNTL_H
00057 #include <fcntl.h>
00058 #endif
00059 
00060 #ifdef HAVE_UNISTD_H
00061 #include <unistd.h>
00062 #endif
00063 
00064 #ifdef HAVE_IO_H
00065 #include <io.h>
00066 #endif
00067 
00068 #ifdef HAVE_OPENSSL_SSL_H
00069 #include <openssl/ssl.h>
00070 #endif
00071 
00072 #ifdef HAVE_OPENSSL_RAND_H
00073 #include <openssl/rand.h>
00074 #endif
00075 
00076 #ifdef HAVE_OPENSSL_ERR_H
00077 #include <openssl/err.h>
00078 #endif
00079 
00080 #include "nanohttp-error.h"
00081 #include "nanohttp-common.h"
00082 #include "nanohttp-socket.h"
00083 #include "nanohttp-logging.h"
00084 
00085 #include "nanohttp-ssl.h"
00086 
00087 #define CERT_SUBJECT    1
00088 
00089 static char *_hssl_certificate = NULL;
00090 static char *_hssl_certpass = NULL;
00091 static char *_hssl_ca_list = NULL;
00092 static SSL_CTX *_hssl_context = NULL;
00093 static int _hssl_enabled = 0;
00094 
00095 static int
00096 _hssl_dummy_verify_cert(X509 * cert)
00097 {
00098   /* TODO: Make sure that the client is providing a client cert, or that the
00099      Module is providing the Module cert */
00100 
00101   /* connect to anyone */
00102 
00103   log_verbose1("_Not_ validating certificate.");
00104   return 1;
00105 }
00106 
00107 int (*_hssl_verify_cert) (X509 * cert) = _hssl_dummy_verify_cert;
00108 
00109 static int
00110 _hssl_cert_verify_callback(int prev_ok, X509_STORE_CTX * ctx)
00111 {
00112 /*
00113     if ((X509_STORE_CTX_get_error(ctx) = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN))
00114     {
00115         log_verbose1("Self signed cert in chain");
00116         return 1;
00117     }
00118 */
00119   log_verbose2("Cert depth = %d", X509_STORE_CTX_get_error_depth(ctx));
00120   if (X509_STORE_CTX_get_error_depth(ctx) == 0)
00121   {
00122     return _hssl_verify_cert(X509_STORE_CTX_get_current_cert(ctx));
00123   }
00124   else
00125   {
00126     log_verbose1("Cert ok (prev)");
00127     return prev_ok;
00128   }
00129 }
00130 
00131 static void
00132 _hssl_superseed(void)
00133 {
00134   int buf[256], i;
00135 
00136   srand(time(NULL));
00137 
00138   for (i = 0; i < 256; i++)
00139   {
00140     buf[i] = rand();
00141   }
00142   RAND_seed((unsigned char *) buf, sizeof(buf));
00143 
00144   return;
00145 }
00146 
00147 static char *
00148 _hssl_get_error(SSL * ssl, int ret)
00149 {
00150   switch (SSL_get_error(ssl, ret))
00151   {
00152   case SSL_ERROR_NONE:
00153     return "None";
00154   case SSL_ERROR_ZERO_RETURN:
00155     return "Zero return";
00156   case SSL_ERROR_WANT_READ:
00157     return "Want read";
00158   case SSL_ERROR_WANT_WRITE:
00159     return "Want write";
00160   case SSL_ERROR_WANT_X509_LOOKUP:
00161     return "Want x509 lookup";
00162   case SSL_ERROR_SYSCALL:
00163     if (ERR_get_error() == 0 && ret == -1)
00164     {
00165       return strerror(errno);
00166     }
00167     return "Syscall failed";
00168   case SSL_ERROR_SSL:
00169     return "SSL error";
00170   default:
00171     return "Unkown error";
00172   }
00173 }
00174 
00175 static int
00176 _hssl_password_callback(char *buf, int num, int rwflag, void *userdata)
00177 {
00178   int ret;
00179 
00180   if (!_hssl_certpass)
00181     return 0;
00182 
00183   ret = strlen(_hssl_certpass);
00184 
00185   if (num < ret + 1)
00186     return 0;
00187 
00188   strcpy(buf, _hssl_certpass);
00189 
00190   return ret;
00191 }
00192 
00193 int
00194 verify_sn(X509 * cert, int who, int nid, char *str)
00195 {
00196   char name[256];
00197   char buf[256];
00198 
00199   memset(name, '\0', 256);
00200   memset(buf, '\0', 256);
00201 
00202   if (who == CERT_SUBJECT)
00203   {
00204     X509_NAME_oneline(X509_get_subject_name(cert), name, 256);
00205   }
00206   else
00207   {
00208     X509_NAME_oneline(X509_get_issuer_name(cert), name, 256);
00209   }
00210 
00211   buf[0] = '/';
00212   strcat(buf, OBJ_nid2sn(nid));
00213   strcat(buf, "=");
00214   strcat(buf, str);
00215 
00216   return strstr(name, buf) ? 1 : 0;
00217 }
00218 
00219 void
00220 hssl_set_hssl_verify_cert(int func(X509 * cert))
00221 {
00222   _hssl_verify_cert = func;
00223 
00224   return;
00225 }
00226 
00227 void
00228 hssl_set_certificate(const char *filename)
00229 {
00230   if (_hssl_certificate)
00231     free(_hssl_certificate);
00232 
00233   _hssl_certificate = strdup(filename);
00234 
00235   return;
00236 }
00237 
00238 void
00239 hssl_set_certpass(const char *password)
00240 {
00241   if (_hssl_certpass)
00242     free(_hssl_certpass);
00243 
00244   _hssl_certpass = strdup(password);
00245 
00246   return;
00247 }
00248 
00249 void
00250 hssl_set_ca_list(const char *filename)
00251 {
00252   if (_hssl_ca_list)
00253     free(_hssl_ca_list);
00254 
00255   _hssl_ca_list = strdup(filename);
00256 
00257   return;
00258 }
00259 
00260 void
00261 hssl_enable(void)
00262 {
00263   _hssl_enabled = 1;
00264 
00265   return;
00266 }
00267 
00268 static void
00269 _hssl_parse_arguments(int argc, char **argv)
00270 {
00271   int i;
00272 
00273   for (i=1; i<argc; i++)
00274   {
00275     if (!strcmp(argv[i - 1], NHTTP_ARG_CERT))
00276     {
00277       hssl_set_certificate(argv[i]);
00278     }
00279     else if (!strcmp(argv[i - 1], NHTTP_ARG_CERTPASS))
00280     {
00281       hssl_set_certpass(argv[i]);
00282     }
00283     else if (!strcmp(argv[i - 1], NHTTP_ARG_CA))
00284     {
00285       hssl_set_ca_list(argv[i]);
00286     }
00287     else if (!strcmp(argv[i - 1], NHTTPD_ARG_HTTPS))
00288     {
00289       hssl_enable();
00290     }
00291   }
00292 
00293   return;
00294 }
00295 
00296 static void
00297 _hssl_library_init(void)
00298 {
00299   static int initialized = 0;
00300 
00301   if (!initialized)
00302   {
00303     log_verbose1("Initializing library");
00304 
00305     SSL_library_init();
00306 
00307     SSL_load_error_strings();
00308     ERR_load_crypto_strings();
00309 
00310     OpenSSL_add_ssl_algorithms();
00311 
00312     initialized = 1;
00313   }
00314 
00315   return;
00316 }
00317 
00318 static herror_t
00319 _hssl_server_context_init(void)
00320 {
00321   log_verbose3("enabled=%i, certificate=%p", _hssl_enabled, _hssl_certificate);
00322 
00323   if (!_hssl_enabled || !_hssl_certificate)
00324     return H_OK;
00325 
00326   if (!(_hssl_context = SSL_CTX_new(SSLv23_method())))
00327   {
00328     log_error1("Cannot create SSL context");
00329     return herror_new("_hssl_server_context_init", HSSL_ERROR_CONTEXT,
00330                       "Unable to create SSL context");
00331   }
00332 
00333   if (!(SSL_CTX_use_certificate_file(_hssl_context, _hssl_certificate, SSL_FILETYPE_PEM)))
00334   {
00335     log_error2("Cannot read certificate file: \"%s\"", _hssl_certificate);
00336     SSL_CTX_free(_hssl_context);
00337     return herror_new("_hssl_server_context_init", HSSL_ERROR_CERTIFICATE,
00338                       "Unable to use SSL certificate \"%s\"", _hssl_certificate);
00339   }
00340 
00341   SSL_CTX_set_default_passwd_cb(_hssl_context, _hssl_password_callback);
00342 
00343   if (!(SSL_CTX_use_PrivateKey_file(_hssl_context, _hssl_certificate, SSL_FILETYPE_PEM)))
00344   {
00345     log_error2("Cannot read key file: \"%s\"", _hssl_certificate);
00346     SSL_CTX_free(_hssl_context);
00347     return herror_new("_hssl_server_context_init", HSSL_ERROR_PEM,
00348                       "Unable to use private key");
00349   }
00350 
00351   if (_hssl_ca_list != NULL && *_hssl_ca_list != '\0')
00352   {
00353     if (!(SSL_CTX_load_verify_locations(_hssl_context, _hssl_ca_list, NULL)))
00354     {
00355       SSL_CTX_free(_hssl_context);
00356       log_error2("Cannot read CA list: \"%s\"", _hssl_ca_list);
00357       return herror_new("_hssl_server_context_init", HSSL_ERROR_CA_LIST,
00358                         "Unable to read certification authorities \"%s\"");
00359     }
00360 
00361     SSL_CTX_set_client_CA_list(_hssl_context, SSL_load_client_CA_file(_hssl_ca_list));
00362     log_verbose1("Certification authority contacted");
00363   }
00364 
00365   SSL_CTX_set_verify(_hssl_context, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE,
00366                      _hssl_cert_verify_callback);
00367   log_verbose1("Certificate verification callback registered");
00368 
00369   SSL_CTX_set_mode(_hssl_context, SSL_MODE_AUTO_RETRY);
00370 
00371   SSL_CTX_set_session_cache_mode(_hssl_context, SSL_SESS_CACHE_OFF);
00372 
00373   _hssl_superseed();
00374 
00375   return H_OK;
00376 }
00377 
00378 static void
00379 _hssl_server_context_destroy(void)
00380 {
00381   if (_hssl_context)
00382   {
00383     SSL_CTX_free(_hssl_context);
00384     _hssl_context = NULL;
00385   }
00386   return;
00387 }
00388 
00389 herror_t
00390 hssl_module_init(int argc, char **argv)
00391 {
00392   _hssl_parse_arguments(argc, argv);
00393 
00394   if (_hssl_enabled)
00395   {
00396     _hssl_library_init();
00397     log_verbose1("SSL enabled");
00398   }
00399   else
00400   {
00401     log_verbose1("SSL _not_ enabled");
00402   }
00403 
00404   return _hssl_server_context_init();
00405 }
00406 
00407 void
00408 hssl_module_destroy(void)
00409 {
00410   _hssl_server_context_destroy();
00411 
00412   if (_hssl_certpass)
00413   {
00414     free(_hssl_certpass);
00415     _hssl_certpass = NULL;
00416   }
00417 
00418   if (_hssl_ca_list)
00419   {
00420     free(_hssl_ca_list);
00421     _hssl_ca_list = NULL;
00422   }
00423 
00424   if (_hssl_certificate)
00425   {
00426     free(_hssl_certificate);
00427     _hssl_certificate = NULL;
00428   }
00429 
00430   return;
00431 }
00432 
00433 int
00434 hssl_enabled(void)
00435 {
00436   return _hssl_enabled;
00437 }
00438 
00439 herror_t
00440 hssl_client_ssl(struct hsocket_t * sock)
00441 {
00442   SSL_CTX *ctx;
00443   SSL *ssl;
00444   int ret;
00445 
00446   log_verbose1("Starting SSL client initialization");
00447 
00448   _hssl_library_init();
00449 
00450   if (!(ctx = SSL_CTX_new(SSLv23_method())))
00451   {
00452     log_error2("SSL_CTX_new failed (ctx == %p)", ctx);
00453     return herror_new("hssl_client_ssl", HSSL_ERROR_CONTEXT, "Cannot create SSL client context");
00454   }
00455 
00456   if (!(ssl = SSL_new(ctx)))
00457   {
00458     log_error1("Cannot create new SSL object");
00459     return herror_new("hssl_client_ssl", HSSL_ERROR_CLIENT, "SSL_new failed");
00460   }
00461 
00462   SSL_set_fd(ssl, sock->sock);
00463 
00464   if ((ret = SSL_connect(ssl)) <= 0)
00465   {
00466     herror_t err;
00467 
00468     log_error2("SSL connect error (%s)", _hssl_get_error(ssl, -1));
00469     err =
00470       herror_new("hssl_client_ssl", HSSL_ERROR_CONNECT,
00471                  "SSL_connect failed (%s)", _hssl_get_error(ssl, ret));
00472     SSL_free(ssl);
00473     return err;
00474   }
00475 
00476   /* SSL_connect should take care of this for us. if
00477      (SSL_get_peer_certificate(ssl) == NULL) { log_error1("No certificate
00478      provided"); SSL_free(ssl); return herror_new("hssl_client_ssl",
00479      HSSL_ERROR_CERTIFICATE, "No certificate provided"); }
00480 
00481      if (SSL_get_verify_result(ssl) != X509_V_OK) { log_error1("Certificate
00482      did not verify"); SSL_free(ssl); return herror_new("hssl_client_ssl",
00483      HSSL_ERROR_CERTIFICATE, "Verfiy certificate failed"); } */
00484 
00485   log_verbose1("SSL client initialization completed");
00486 
00487   sock->ssl = ssl;
00488 
00489   return H_OK;
00490 }
00491 
00492 static int
00493 _hssl_bio_read(BIO * b, char *out, int outl)
00494 {
00495   return hsocket_select_recv(b->num, out, outl);;
00496 }
00497 
00498 herror_t
00499 hssl_server_ssl(struct hsocket_t *sock)
00500 {
00501   SSL *ssl;
00502   int ret;
00503   BIO *sbio;
00504 
00505   if (!_hssl_enabled)
00506     return H_OK;
00507 
00508   log_verbose2("Starting SSL initialization for socket %d", sock->sock);
00509 
00510   if (!(ssl = SSL_new(_hssl_context)))
00511   {
00512     log_warn1("SSL_new failed");
00513     return herror_new("hssl_server_ssl", HSSL_ERROR_SERVER,
00514                       "Cannot create SSL object");
00515   }
00516   /* SSL_set_fd(ssl, sock->sock); */
00517 
00518   sbio = BIO_new_socket(sock->sock, BIO_NOCLOSE);
00519 
00520   if (sbio == NULL)
00521   {
00522     log_error1("BIO_new_socket failed");
00523     return NULL;
00524   }
00525   /* BIO_set_callback(sbio, hssl_bio_cb); */
00526   sbio->method->bread = _hssl_bio_read;
00527   SSL_set_bio(ssl, sbio, sbio);
00528 
00529   if ((ret = SSL_accept(ssl)) <= 0)
00530   {
00531     herror_t err;
00532 
00533     log_error2("SSL_accept failed (%s)", _hssl_get_error(ssl, ret));
00534 
00535     err = herror_new("hssl_server_ssl", HSSL_ERROR_SERVER, "SSL_accept failed (%s)", _hssl_get_error(ssl, ret));
00536     SSL_free(ssl);
00537 
00538     return err;
00539   }
00540 
00541   sock->ssl = ssl;
00542 
00543   return H_OK;
00544 }
00545 
00546 void
00547 hssl_cleanup(struct hsocket_t * sock)
00548 {
00549   if (sock->ssl)
00550   {
00551     SSL_shutdown(sock->ssl);
00552     SSL_free(sock->ssl);
00553     sock->ssl = NULL;
00554   }
00555 
00556   return;
00557 }
00558 
00559 herror_t
00560 hssl_read(struct hsocket_t * sock, char *buf, size_t len, size_t * received)
00561 {
00562   int count;
00563 
00564 /* log_verbose4("sock->sock=%d sock->ssl=%p, len=%li", sock->sock, sock->ssl, len); */
00565 
00566   if (sock->ssl)
00567   {
00568     if ((count = SSL_read(sock->ssl, buf, len)) < 1)
00569       return herror_new("hssl_read", HSOCKET_ERROR_RECEIVE,
00570                         "SSL_read failed (%s)", _hssl_get_error(sock->ssl,
00571                                                                 count));
00572   }
00573   else
00574   {
00575     if ((count = hsocket_select_recv(sock->sock, buf, len)) == -1)
00576       return herror_new("hssl_read", HSOCKET_ERROR_RECEIVE,
00577                         "recv failed (%s)", strerror(errno));
00578   }
00579   *received = count;
00580 
00581   return H_OK;
00582 }
00583 
00584 
00585 herror_t
00586 hssl_write(struct hsocket_t * sock, const char *buf, size_t len, size_t * sent)
00587 {
00588   int count;
00589 
00590 /*  log_verbose4("sock->sock=%d, sock->ssl=%p, len=%li", sock->sock, sock->ssl, len); */
00591 
00592   if (sock->ssl)
00593   {
00594     if ((count = SSL_write(sock->ssl, buf, len)) == -1)
00595       return herror_new("hssl_write", HSOCKET_ERROR_SEND,
00596                         "SSL_write failed (%s)", _hssl_get_error(sock->ssl,
00597                                                                  count));
00598   }
00599   else
00600   {
00601     if ((count = send(sock->sock, buf, len, 0)) == -1)
00602       return herror_new("hssl_write", HSOCKET_ERROR_SEND, "send failed (%s)",
00603                         strerror(errno));
00604   }
00605   *sent = count;
00606 
00607   return H_OK;
00608 }

Generated on Thu Jan 25 23:36:03 2007 for csoap by  doxygen 1.4.6