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

iossl.c

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.19 2007/10/17 22:58:35 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 
00032 int io_ssl_get_SSL(io_t *io, SSL **pssl)
00033 {
00034     io_ssl_t *io_ssl = (io_ssl_t*)io;
00035 
00036     dbg_err_if(io_ssl == NULL);
00037     dbg_err_if(pssl == NULL);
00038     dbg_err_if(io_ssl->io.type != IO_TYPE_SSL);
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     if(c < 0 && errno == EINTR)
00060         goto again; 
00061 
00062     dbg_err_if(c < 0); 
00063 
00064     return c;
00065 err:
00066     return -1;
00067 }
00068 
00069 static ssize_t io_ssl_write(io_ssl_t *io_ssl, const char *buf, size_t size)
00070 {
00071     ssize_t c;
00072 
00073     dbg_err_if (io_ssl == NULL);
00074     dbg_err_if (buf == NULL);
00075 
00076 again:
00077     c = SSL_write(io_ssl->ssl, buf, size);
00078     /* if(c < 0 && (errno == EINTR || errno == EAGAIN)) */
00079     if(c < 0 && errno == EINTR)
00080         goto again; 
00081 
00082     dbg_err_if(c < 0); 
00083 
00084     return c;
00085 err:
00086     return -1;
00087 }
00088 
00089 /* close the underlaying fd (may be called more then once) */
00090 static int io_ssl_close(io_ssl_t *io_ssl)
00091 {
00092     dbg_err_if(io_ssl == NULL);
00093 
00094     if(io_ssl->flags & IO_FD_CLOSE && io_ssl->fd != -1)
00095     {
00096         close(io_ssl->fd);
00097         io_ssl->fd = -1;
00098     }
00099 
00100     return 0;
00101 err:
00102     return ~0;
00103 }
00104 
00105 /* free data alloc'ed by this io type */
00106 static int io_ssl_free(io_ssl_t *io_ssl)
00107 {
00108     dbg_err_if(io_ssl == NULL);
00109 
00110     dbg_if(io_ssl_close(io_ssl));
00111 
00112     if(io_ssl->ssl)
00113     {
00114         SSL_free(io_ssl->ssl);
00115         io_ssl->ssl = NULL;
00116     }
00117 
00118     return 0;
00119 err:
00120     return -1;
00121 }
00122 
00123 int io_ssl_create(int fd, int flags, SSL_CTX *ssl_ctx, io_t **pio)
00124 {
00125     io_ssl_t *io_ssl = NULL;
00126     int rc = 0;
00127     long vfy;
00128 
00129     dbg_return_if (pio == NULL, ~0);
00130     dbg_return_if (ssl_ctx == NULL, ~0);
00131 
00132     dbg_err_if(io_create(io_ssl_t, (io_t**)&io_ssl));
00133 
00134     io_ssl->io.type = IO_TYPE_SSL;
00135 
00136     io_ssl->fd = fd;
00137     io_ssl->flags = flags;
00138 
00139     io_ssl->ssl = SSL_new(ssl_ctx);
00140     dbg_err_if(io_ssl->ssl == NULL);
00141 
00142     /* assign a working descriptor to the SSL stream */
00143     dbg_err_if(SSL_set_fd(io_ssl->ssl, fd) == 0);
00144 
00145     io_ssl->io.read = (io_read_op) io_ssl_read;
00146     io_ssl->io.write = (io_write_op) io_ssl_write;
00147     io_ssl->io.close = (io_close_op) io_ssl_close; 
00148     io_ssl->io.free = (io_free_op) io_ssl_free; 
00149     io_ssl->io.size = 0;
00150 
00151     /* set the secure flag (encrypted connection) */
00152     io_ssl->io.is_secure = 1;
00153     
00154     /* accept a SSL connection */
00155     while((rc = SSL_accept(io_ssl->ssl)) <= 0)
00156     {
00157         /* will return 1 if accept has been blocked by a signal or async IO */
00158         if(BIO_sock_should_retry(rc))
00159             continue;
00160 
00161         if(SSL_get_error(io_ssl->ssl, rc) == SSL_ERROR_WANT_READ)
00162             break; 
00163 
00164         warn_err("SSL accept error: %d", SSL_get_error(io_ssl->ssl, rc));
00165     }
00166 
00167     *pio = (io_t*)io_ssl;
00168 
00169     return 0;
00170 err:
00171     if(io_ssl && io_ssl->ssl)
00172     {
00173         /* print a warning message for bad client certificates */
00174         if((vfy = SSL_get_verify_result(io_ssl->ssl)) != X509_V_OK)
00175             warn("SSL client cert verify error: %s", 
00176                 X509_verify_cert_error_string(vfy));
00177         SSL_set_shutdown(io_ssl->ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
00178     }
00179     if(io_ssl)
00180         io_free((io_t *)io_ssl);
00181     return ~0;
00182 }