iossl.c
00001
00002
00003
00004
00005
00006
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;
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
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
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
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
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
00126 while((rc = SSL_connect(io_ssl->ssl)) <= 0)
00127 {
00128 #ifdef SSL_OPENSSL
00129
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
00150 while((rc = SSL_accept(io_ssl->ssl)) <= 0)
00151 {
00152 #ifdef SSL_OPENSSL
00153
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
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
00199 io_ssl->io.is_secure = 1;
00200
00201
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
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