Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals

iossl.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2005, 2006 by KoanLogic s.r.l. <http://www.koanlogic.com>
00003  * All rights reserved.
00004  *
00005  * This file is part of KLone, and as such it is subject to the license stated
00006  * in the LICENSE file which you have received as part of this distribution.
00007  *
00008  * $Id: iossl.c,v 1.14 2006/05/27 16:34:01 tat Exp $
00009  */
00010 
00011 #include "klone_conf.h"
00012 #include <unistd.h>
00013 #include <klone/io.h>
00014 #include <klone/ioprv.h>
00015 #include <u/libu.h>
00016 #include <openssl/ssl.h>
00017 #include <openssl/err.h>
00018 
00019 struct io_ssl_s
00020 {
00021     struct io_s io; /* must be the first item */
00022     SSL *ssl;
00023     int fd;
00024     int flags;
00025 };
00026 
00027 typedef struct io_ssl_s io_ssl_t;
00028 
00029 static ssize_t io_ssl_read(io_ssl_t *io, char *buf, size_t size);
00030 static ssize_t io_ssl_write(io_ssl_t *io, const char *buf, size_t size);
00031 static int io_ssl_term(io_ssl_t *io);
00032 
00033 int io_ssl_get_SSL(io_t *io, SSL **pssl)
00034 {
00035     io_ssl_t *io_ssl = (io_ssl_t*)io;
00036 
00037     dbg_err_if(io_ssl == NULL);
00038     dbg_err_if(pssl == NULL);
00039 
00040     dbg_err_if(io_ssl->ssl == NULL);
00041 
00042     *pssl = io_ssl->ssl;
00043 
00044     return 0;
00045 err:
00046     return ~0;
00047 }
00048 
00049 static ssize_t io_ssl_read(io_ssl_t *io_ssl, char *buf, size_t size)
00050 {
00051     ssize_t c;
00052 
00053     dbg_err_if (io_ssl == NULL);
00054     dbg_err_if (buf == NULL);
00055 
00056 again:
00057     c = SSL_read(io_ssl->ssl, buf, size);
00058     if(c < 0 && (errno == EINTR || errno == EAGAIN))
00059         goto again; 
00060 
00061     dbg_err_if(c < 0); 
00062 
00063     return c;
00064 err:
00065     return -1;
00066 }
00067 
00068 static ssize_t io_ssl_write(io_ssl_t *io_ssl, const char *buf, size_t size)
00069 {
00070     ssize_t c;
00071 
00072     dbg_err_if (io_ssl == NULL);
00073     dbg_err_if (buf == NULL);
00074 
00075 again:
00076     c = SSL_write(io_ssl->ssl, buf, size);
00077     if(c < 0 && (errno == EINTR || errno == EAGAIN))
00078         goto again; 
00079 
00080     dbg_err_if(c < 0); 
00081 
00082     return c;
00083 err:
00084     return -1;
00085 }
00086 
00087 static int io_ssl_term(io_ssl_t *io_ssl)
00088 {
00089     dbg_err_if(io_ssl == NULL);
00090 
00091     /* we cannot free io_ssl->ssl because on connection timeout the process 
00092      * is blocked in a SSL_read so freeing the SSL object will segfault 
00093      * (i.e. we're leaking here) */
00094     /* SSL_free(io_ssl->ssl); */
00095 
00096     if(io_ssl->flags & IO_FD_CLOSE)
00097     {
00098         close(io_ssl->fd);
00099         io_ssl->fd = -1;
00100     }
00101 
00102     return 0;
00103 err:
00104     return -1;
00105 }
00106 
00107 int io_ssl_create(int fd, int flags, SSL_CTX *ssl_ctx, io_t **pio)
00108 {
00109     io_ssl_t *io_ssl = NULL;
00110     int rc = 0;
00111     long vfy;
00112 
00113     dbg_return_if (pio == NULL, ~0);
00114     dbg_return_if (ssl_ctx == NULL, ~0);
00115 
00116     dbg_err_if(io_create(io_ssl_t, (io_t**)&io_ssl));
00117 
00118     io_ssl->fd = fd;
00119     io_ssl->flags = flags;
00120 
00121     io_ssl->ssl = SSL_new(ssl_ctx);
00122     dbg_err_if(io_ssl->ssl == NULL);
00123 
00124     /* assign a working descriptor to the SSL stream */
00125     dbg_err_if(SSL_set_fd(io_ssl->ssl, fd) == 0);
00126 
00127     io_ssl->io.read = (io_read_op) io_ssl_read;
00128     io_ssl->io.write = (io_write_op) io_ssl_write;
00129     io_ssl->io.term = (io_term_op) io_ssl_term; 
00130     io_ssl->io.size = 0;
00131 
00132     /* set the secure flag (encrypted connection) */
00133     io_ssl->io.is_secure = 1;
00134     
00135     /* accept a SSL connection */
00136     while((rc = SSL_accept(io_ssl->ssl)) <= 0)
00137     {
00138         /* will return 1 if accept has been blocked by a signal or async IO */
00139         if(BIO_sock_should_retry(rc))
00140             continue;
00141 
00142         if(SSL_get_error(io_ssl->ssl, rc) == SSL_ERROR_WANT_READ)
00143             break; 
00144 
00145         warn_err("SSL accept error: %d", SSL_get_error(io_ssl->ssl, rc));
00146     }
00147 
00148     *pio = (io_t*)io_ssl;
00149 
00150     return 0;
00151 err:
00152     if(io_ssl && io_ssl->ssl)
00153     {
00154         /* print a warning message for bad client certificates */
00155         if((vfy = SSL_get_verify_result(io_ssl->ssl)) != X509_V_OK)
00156             warn("SSL client cert verify error: %s", 
00157                 X509_verify_cert_error_string(vfy));
00158         SSL_set_shutdown(io_ssl->ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
00159     }
00160     if(io_ssl)
00161         io_free((io_t *)io_ssl);
00162     return ~0;
00163 }

←Products
© 2005-2006 - KoanLogic S.r.l. - All rights reserved