iossl.c

00001 /*
00002  * Copyright (c) 2005-2012 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 
00009 #include "klone_conf.h"
00010 #include <unistd.h>
00011 #include <klone/io.h>
00012 #include <klone/ioprv.h>
00013 #include <u/libu.h>
00014 #include <openssl/ssl.h>
00015 #include <openssl/err.h>
00016 
00017 struct io_ssl_s
00018 {
00019     struct io_s io; /* must be the first item */
00020     SSL *ssl;
00021     int fd;
00022     int flags;
00023 };
00024 
00025 typedef struct io_ssl_s io_ssl_t;
00026 
00027 static ssize_t io_ssl_read(io_ssl_t *io, char *buf, size_t size);
00028 static ssize_t io_ssl_write(io_ssl_t *io, const char *buf, size_t size);
00029 
00030 int io_ssl_get_SSL(io_t *io, SSL **pssl)
00031 {
00032     io_ssl_t *io_ssl = (io_ssl_t*)io;
00033 
00034     dbg_err_if(io_ssl == NULL);
00035     dbg_err_if(pssl == NULL);
00036     dbg_err_if(io_ssl->io.type != IO_TYPE_SSL);
00037 
00038     dbg_err_if(io_ssl->ssl == NULL);
00039 
00040     *pssl = io_ssl->ssl;
00041 
00042     return 0;
00043 err:
00044     return ~0;
00045 }
00046 
00047 static ssize_t io_ssl_read(io_ssl_t *io_ssl, char *buf, size_t size)
00048 {
00049     ssize_t c;
00050 
00051     dbg_err_if (io_ssl == NULL);
00052     dbg_err_if (buf == NULL);
00053 
00054 again:
00055     c = SSL_read(io_ssl->ssl, buf, size);
00056     /* if(c < 0 && (errno == EINTR || errno == EAGAIN)) */
00057     if(c < 0 && errno == EINTR)
00058         goto again; 
00059 
00060     dbg_err_if(c < 0); 
00061 
00062     return c;
00063 err:
00064     return -1;
00065 }
00066 
00067 static ssize_t io_ssl_write(io_ssl_t *io_ssl, const char *buf, size_t size)
00068 {
00069     ssize_t c;
00070 
00071     dbg_err_if (io_ssl == NULL);
00072     dbg_err_if (buf == NULL);
00073 
00074 again:
00075     c = SSL_write(io_ssl->ssl, buf, size);
00076     /* if(c < 0 && (errno == EINTR || errno == EAGAIN)) */
00077     if(c < 0 && errno == EINTR)
00078         goto again; 
00079 
00080     dbg_err_if(c < 0); 
00081 
00082     return c;
00083 err:
00084     return -1;
00085 }
00086 
00087 /* close the underlaying fd (may be called more then once) */
00088 static int io_ssl_close(io_ssl_t *io_ssl)
00089 {
00090     dbg_err_if(io_ssl == NULL);
00091 
00092     if(io_ssl->flags & IO_FD_CLOSE && io_ssl->fd != -1)
00093     {
00094         close(io_ssl->fd);
00095         io_ssl->fd = -1;
00096     }
00097 
00098     return 0;
00099 err:
00100     return ~0;
00101 }
00102 
00103 /* free data alloc'ed by this io type */
00104 static int io_ssl_free(io_ssl_t *io_ssl)
00105 {
00106     dbg_err_if(io_ssl == NULL);
00107 
00108     dbg_if(io_ssl_close(io_ssl));
00109 
00110     if(io_ssl->ssl)
00111     {
00112         SSL_free(io_ssl->ssl);
00113         io_ssl->ssl = NULL;
00114     }
00115 
00116     return 0;
00117 err:
00118     return -1;
00119 }
00120 
00121 static int io_ssl_connect(io_ssl_t *io_ssl)
00122 {
00123     int rc;
00124 
00125     /* accept a SSL connection */
00126     while((rc = SSL_connect(io_ssl->ssl)) <= 0)
00127     {
00128         #ifdef SSL_OPENSSL
00129         /* will return 1 if accept has been blocked by a signal or async IO */
00130         if(BIO_sock_should_retry(rc))
00131             continue;
00132         #endif
00133 
00134         if(SSL_get_error(io_ssl->ssl, rc) == SSL_ERROR_WANT_READ)
00135             break; 
00136 
00137         warn_err("SSL accept error: %d", SSL_get_error(io_ssl->ssl, rc));
00138     }
00139 
00140     return 0;
00141 err:
00142     return ~0;
00143 }
00144 
00145 static int io_ssl_accept(io_ssl_t *io_ssl)
00146 {
00147     int rc;
00148 
00149     /* accept a SSL connection */
00150     while((rc = SSL_accept(io_ssl->ssl)) <= 0)
00151     {
00152         #ifdef SSL_OPENSSL
00153         /* will return 1 if accept has been blocked by a signal or async IO */
00154         if(BIO_sock_should_retry(rc))
00155             continue;
00156         #endif
00157 
00158         if(SSL_get_error(io_ssl->ssl, rc) == SSL_ERROR_WANT_READ)
00159             break; 
00160 
00161         warn_err("SSL accept error: %d", SSL_get_error(io_ssl->ssl, rc));
00162     }
00163 
00164     return 0;
00165 err:
00166     return ~0;
00167 }
00168 
00169 int io_ssl_create(int fd, int flags, int client_mode, 
00170         SSL_CTX *ssl_ctx, io_t **pio)
00171 {
00172     io_ssl_t *io_ssl = NULL;
00173     int rc = 0;
00174     long vfy;
00175 
00176     dbg_return_if (pio == NULL, ~0);
00177     dbg_return_if (ssl_ctx == NULL, ~0);
00178 
00179     dbg_err_if(io_create(io_ssl_t, (io_t**)&io_ssl));
00180 
00181     io_ssl->io.type = IO_TYPE_SSL;
00182 
00183     io_ssl->fd = fd;
00184     io_ssl->flags = flags;
00185 
00186     io_ssl->ssl = SSL_new(ssl_ctx);
00187     dbg_err_if(io_ssl->ssl == NULL);
00188 
00189     /* assign a working descriptor to the SSL stream */
00190     dbg_err_if(SSL_set_fd(io_ssl->ssl, fd) == 0);
00191 
00192     io_ssl->io.read = (io_read_op) io_ssl_read;
00193     io_ssl->io.write = (io_write_op) io_ssl_write;
00194     io_ssl->io.close = (io_close_op) io_ssl_close; 
00195     io_ssl->io.free = (io_free_op) io_ssl_free; 
00196     io_ssl->io.size = 0;
00197 
00198     /* set the secure flag (encrypted connection) */
00199     io_ssl->io.is_secure = 1;
00200     
00201     /* wait for the peer to start the TLS handshake */
00202     if(client_mode)
00203         dbg_err_if(io_ssl_connect(io_ssl));
00204     else
00205         dbg_err_if(io_ssl_accept(io_ssl));
00206 
00207     *pio = (io_t*)io_ssl;
00208 
00209     return 0;
00210 err:
00211     if(io_ssl && io_ssl->ssl)
00212     {
00213         #ifdef SSL_OPENSSL
00214         /* print a warning message for bad client certificates */
00215         if((vfy = SSL_get_verify_result(io_ssl->ssl)) != X509_V_OK)
00216             warn("SSL client cert verify error: %s", 
00217                 X509_verify_cert_error_string(vfy));
00218         SSL_set_shutdown(io_ssl->ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
00219         #endif
00220         #ifdef SSL_CYASSL
00221         warn("SSL %s error", client_mode ? "connect" : "accept");
00222         #endif
00223     }
00224     if(io_ssl)
00225         io_free((io_t *)io_ssl);
00226     return ~0;
00227 }
00228 

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