From 52767927889b305fe18b28ddfc5351f08b703d2d Mon Sep 17 00:00:00 2001 From: m0gg Date: Mon, 6 Mar 2006 13:37:38 +0000 Subject: Various changes see ChangeLog --- nanohttp/nanohttp-ssl.c | 521 ++++++++++++++++++++++++++++-------------------- 1 file changed, 307 insertions(+), 214 deletions(-) (limited to 'nanohttp/nanohttp-ssl.c') diff --git a/nanohttp/nanohttp-ssl.c b/nanohttp/nanohttp-ssl.c index 63bf0f7..a365e64 100644 --- a/nanohttp/nanohttp-ssl.c +++ b/nanohttp/nanohttp-ssl.c @@ -1,4 +1,7 @@ -/* +/************************************************************************* + * $Id: nanohttp-ssl.c,v 1.18 2006/03/06 13:37:38 m0gg Exp $ + * + * CSOAP Project: A http client/server library in C * Copyright (C) 2001-2005 Rochester Institute of Technology * * This program is free software; you can redistribute it and/or modify @@ -21,9 +24,6 @@ * Descrip: SSL connection routines */ -/* Enter only if --with-ssl was specified to the configure script */ -#ifdef HAVE_SSL - #ifdef HAVE_CONFIG_H #include #endif @@ -36,16 +36,6 @@ #include #endif -#if HAVE_INTTYPES_H -#include -#else -# if HAVE_STDINT_H -# include -# else -typedef unsigned int uint32_t; -# endif -#endif - #ifdef HAVE_STRING_H #include #endif @@ -54,6 +44,10 @@ typedef unsigned int uint32_t; #include #endif +#ifdef HAVE_ERRNO_H +#include +#endif + #ifdef HAVE_TIME_H #include #endif @@ -66,12 +60,11 @@ typedef unsigned int uint32_t; #include #endif -#ifdef WIN32 +#ifdef HAVE_IO_H #include -typedef unsigned int uint32_t; -#else #endif +#ifdef HAVE_SSL #ifdef HAVE_OPENSSL_RAND_H #include #endif @@ -79,24 +72,25 @@ typedef unsigned int uint32_t; #ifdef HAVE_OPENSSL_ERR_H #include #endif +#endif #include "nanohttp-common.h" #include "nanohttp-socket.h" #include "nanohttp-ssl.h" -#define MAXCHUNK 1024 -#define HEADER_LEN 5 -char HEADER[HEADER_LEN] = { 186, 84, 202, 86, 224 }; -static char *pass; +#ifdef HAVE_SSL -/* - * superseed - * Creates a 1k random seed and uses it to seed - * the SSL random number generator - */ +static char *certificate = NULL; +static char *certpass = NULL; +static char *ca_list = NULL; +static SSL_CTX *context = NULL; -void -superseed () +static int enabled = 0; +static int initialized = 0; + + +static void +_hssl_superseed (void) { int buf[256], i; @@ -107,18 +101,47 @@ superseed () buf[i] = rand (); } RAND_seed ((unsigned char *) buf, sizeof (buf)); + + return; } + +static char * +_hssl_get_error(SSL *ssl, int ret) +{ + switch(SSL_get_error(ssl, ret)) + { + case SSL_ERROR_NONE: + return "None"; + case SSL_ERROR_ZERO_RETURN: + return "Zero return"; + case SSL_ERROR_WANT_READ: + return "Want read"; + case SSL_ERROR_WANT_WRITE: + return "Want write"; + case SSL_ERROR_WANT_X509_LOOKUP: + return "Want x509 lookup"; + case SSL_ERROR_SYSCALL: + return "Syscall failed"; + case SSL_ERROR_SSL: + return "SSL error"; + default: + return "Unkown"; + } +} + + static int pw_cb (char *buf, int num, int rwflag, void *userdata) { - if (num < (int) strlen (pass) + 1) + if (num < (int) strlen (certpass) + 1) return (0); - strcpy (buf, pass); - return strlen (pass); + strcpy(buf, certpass); + return strlen(certpass); } + int verify_sn (X509 * cert, int who, int nid, char *str) { @@ -152,6 +175,7 @@ verify_sn (X509 * cert, int who, int nid, char *str) } } + #ifdef NOUSER_VERIFY static int user_verify (X509 * cert) @@ -190,262 +214,331 @@ verify_cb (int prev_ok, X509_STORE_CTX * ctx) #endif } -void -start_ssl( void ) + +static void +_hssl_parse_arguments(int argc, char **argv) +{ + + int i; + + for (i=1; isock); + + if ((ret = SSL_connect(ssl)) <= 0) { - log_error1 ("SSL handshake was not successful, fatal error at protocol"); - } + herror_t err; - errqueue = SSL_get_error (ssl, ret); + log_error2 ("SSL connect error (%s)", _hssl_get_error(ssl, -1)); + err = herror_new("hssl_client_ssl", HSSL_ERROR_CONNECT, "SSL_connect failed (%s)", _hssl_get_error(ssl, ret)); + SSL_free (ssl); + return err; + } - switch (errqueue) + /* SSL_connect should take care of this for us. + if (SSL_get_peer_certificate(ssl) == NULL) { - case SSL_ERROR_NONE: - strcat (errorbuf, "None"); - break; - case SSL_ERROR_ZERO_RETURN: - strcat (errorbuf, "Zero return"); - break; - case SSL_ERROR_WANT_READ: - strcat (errorbuf, "Want read"); - break; - case SSL_ERROR_WANT_WRITE: - strcat (errorbuf, "Want write"); - break; - case SSL_ERROR_WANT_X509_LOOKUP: - strcat (errorbuf, "Want x509 lookup"); - break; - case SSL_ERROR_SYSCALL: - strcat (errorbuf, "Syscall:"); - if (ret == 0) - { - strcat (errorbuf, "Protocol violation"); - } - else if (ret == -1) - { - strcat (errorbuf, "BIO reported an I/O error"); - } - else - { - strcat (errorbuf, "Unknown syscall error"); - } /* if */ + log_error1("No certificate provided"); + SSL_free(ssl); + return herror_new("hssl_client_ssl", HSSL_ERROR_CERTIFICATE, "No certificate provided"); + } - break; - case SSL_ERROR_SSL: - strcat (errorbuf, "SSL library"); - while ((errqueue = ERR_get_error())) - { - log_error2 ("SSL %s", ERR_error_string (errqueue, NULL)); - } - break; - } /* switch code */ + if (SSL_get_verify_result(ssl) != X509_V_OK) + { + log_error1("Certificate did not verify"); + SSL_free(ssl); + return herror_new("hssl_client_ssl", HSSL_ERROR_CERTIFICATE, "Verfiy certificate failed"); + } */ - log_error1 (errorbuf); + log_verbose1 ("SSL client initialization completed"); + + /* XXX: why??? + if ((status = hsocket_block(sock, sock->block)) != H_OK) + { + log_error2("Cannot make socket non-blocking (%s)", herror_message(status)); + SSL_free(ssl); + return status; + } */ + + sock->ssl = ssl; + + return H_OK; } -SSL * -init_ssl (SSL_CTX * ctx, int sock, int type) + +herror_t +hssl_server_ssl(hsocket_t *sock) { - int ret; SSL *ssl; -#if 0 -#ifdef WIN32 - BIO *rbio; - BIO *wbio; -#else - BIO *sbio; -#endif -#endif + int ret; - log_verbose1 ("Starting SSL Initialization"); + if (!enabled) + return H_OK; - ssl = SSL_new (ctx); + log_verbose2("Starting SSL initialization for socket %d", sock->sock); - if (ssl == NULL) + if (!(ssl = SSL_new(context))) { - log_error1 ("Cannot create new ssl object"); - return NULL; + log_warn1("SSL_new failed"); + return herror_new("hssl_server_ssl", HSSL_ERROR_SERVER, "Cannot create SSL object"); } + SSL_set_fd(ssl, sock->sock); -#if 0 -#ifdef WIN32 - log_error1 ("Setting up BIO with socket"); - rbio = BIO_new_socket (sock, BIO_NOCLOSE); - if (rbio == NULL) + if ((ret = SSL_accept(ssl)) <= 0) { - log_error1 ("BIO_new_socket failed"); - return NULL; + herror_t err; + + log_error2 ("SSL_accept failed (%s)", _hssl_get_error(ssl, ret)); + + err = herror_new("hssl_server_ssl", HSSL_ERROR_SERVER, "SSL_accept failed (%s)", _hssl_get_error(ssl, ret)); + SSL_free (ssl); + + return err; } - SSL_set_bio (ssl, rbio, rbio); -#else - sbio = BIO_new_socket (sock, BIO_NOCLOSE); + sock->ssl = ssl; - if (sbio == NULL) + return H_OK; +} + + +void +hssl_cleanup(hsocket_t *sock) +{ + + if (sock->ssl) { - log_error1 ("BIO_new_socket failed"); - return NULL; + SSL_shutdown (sock->ssl); + SSL_free (sock->ssl); + sock->ssl = NULL; } - SSL_set_bio (ssl, sbio, sbio); -#endif -#endif - SSL_set_fd (ssl, sock); - if (type == SSL_SERVER) + return; +} + + +herror_t hssl_read(hsocket_t *sock, char *buf, size_t len, size_t *received) +{ + int count; + + log_verbose4("sock->sock=%d sock->ssl=%p, len=%li", sock->sock, sock->ssl, len); + + if (sock->ssl) { - hsocket_t sock_t; - sock_t.sock = sock; - hsocket_block (sock_t, 1); - ret = SSL_accept (ssl); - hsocket_block (sock_t, 0); - if (ret <= 0) - { - log_error1 ("SSL accept error"); - log_ssl_error (ssl, ret); - SSL_free (ssl); - return NULL; - } /* if error */ + if ((count = SSL_read(sock->ssl, buf, len)) == -1) + return herror_new("SSL_read", HSOCKET_ERROR_RECEIVE, "SSL_read failed (%s)", _hssl_get_error(sock->ssl, count)); } else - { /* client */ - ret = SSL_connect (ssl); - if (ret <= 0) - { - log_error1 ("SSL connect error"); - log_ssl_error (ssl, ret); - SSL_free (ssl); - return NULL; - } /* if error */ - /* SSL_connect should take care of this for us. - if(SSL_get_peer_certificate(ssl) == NULL) { log_error1( "No - certificate provided"); SSL_free(ssl); return ssl = NULL; } - if(SSL_get_verify_result(ssl) != X509_V_OK) { log_error1( "Certificate - did not verify"); SSL_free(ssl); return ssl = NULL; } */ + { + if ((count = recv(sock->sock, buf, len, 0)) == -1) + return herror_new("hssl_read", HSOCKET_ERROR_RECEIVE, "recv failed (%s)", strerror(errno)); } + *received = count; - log_verbose1 ("Completed SSL Initialization"); - return ssl; + return H_OK; } -void -ssl_cleanup (SSL * ssl) + +herror_t hssl_write(hsocket_t *sock, const char *buf, size_t len, size_t *sent) { - /* does nothing to context */ + int count; - if (ssl != NULL) - { + log_verbose4("sock->sock=%d, sock->ssl=%p, len=%li", sock->sock, sock->ssl, len); - SSL_shutdown (ssl); -// SSL_clear(ssl); - SSL_free (ssl); - ssl = NULL; + if (sock->ssl) + { + if ((count = SSL_write(sock->ssl, buf, len)) == -1) + return herror_new("SSL_write", HSOCKET_ERROR_SEND, "SSL_write failed (%s)", _hssl_get_error(sock->ssl, count)); + } + else + { + if ((count = send(sock->sock, buf, len, 0)) == -1) + return herror_new("hssl_write", HSOCKET_ERROR_SEND, "send failed (%s)", strerror(errno)); } + *sent = count; + + return H_OK; } -int -ssl_checkFatal( SSL *ssl, int status ){ - switch (SSL_get_error(ssl, status)) { - case SSL_ERROR_ZERO_RETURN: - case SSL_ERROR_SSL: - case SSL_ERROR_SYSCALL: - return 1; - break; - default: - return 0; - } +#else + +herror_t hssl_read(hsocket_t *sock, char *buf, size_t len, size_t *received) +{ + int count; + + if ((count = recv(sock->sock, buf, len, 0)) == -1) + return herror_new("hssl_read", HSOCKET_ERROR_RECEIVE, "recv failed (%s)", strerror(errno)); + *received = count; + return H_OK; +} + + +herror_t hssl_write(hsocket_t *sock, const char *buf, size_t len, size_t *sent) +{ + int count; + + if ((count = send(sock->sock, buf, len, 0)) == -1) + return herror_new("hssl_write", HSOCKET_ERROR_SEND, "send failed (%s)", strerror(errno)); + *sent = count; + return H_OK; } -#endif /* end of ifdef HAVE_SSL */ +#endif -- cgit v1.1-32-gdbae