1 /* IOHandler_SSL.c - IOMultiplexer
2 * Copyright (C) 2012 Philipp Kreil (pk910)
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #include "IOHandler_SSL.h"
20 void iohandler_ssl_init() {
23 SSL_load_error_strings();
27 void iohandler_ssl_connect(struct IODescriptor *iofd) {
29 iofd->state = IO_SSLWAIT;
30 struct IOSSLNode *sslnode = malloc(sizeof(*sslnode));
31 sslnode->sslContext = SSL_CTX_new(SSLv23_client_method());
32 if(!sslnode->sslContext)
34 sslnode->sslHandle = SSL_new(sslnode->sslContext);
35 if(!sslnode->sslHandle)
37 if(!SSL_set_fd(sslnode->sslHandle, iofd->fd))
39 SSL_set_connect_state(sslnode->sslHandle);
40 iofd->sslnode = sslnode;
41 iohandler_ssl_client_handshake(iofd);
45 iohandler_events(iofd, 0, 0);
49 void iohandler_ssl_client_handshake(struct IODescriptor *iofd) {
51 // Perform an SSL handshake.
52 int ret = SSL_do_handshake(iofd->sslnode->sslHandle);
53 iofd->ssl_hs_read = 0;
54 iofd->ssl_hs_write = 0;
55 switch(SSL_get_error(iofd->sslnode->sslHandle, ret)) {
57 iofd->state = IO_CONNECTING;
59 iohandler_log(IOLOG_DEBUG, "SSL handshake for %s (fd: %d) successful", iohandler_iotype_name(iofd->type), iofd->fd);
60 iohandler_events(iofd, 0, 1); //perform IOEVENT_CONNECTED event
62 case SSL_ERROR_WANT_READ:
63 iofd->ssl_hs_read = 1;
64 iohandler_log(IOLOG_DEBUG, "SSL_do_handshake for %s (fd: %d) returned SSL_ERROR_WANT_READ", iohandler_iotype_name(iofd->type), iofd->fd);
66 case SSL_ERROR_WANT_WRITE:
67 iofd->ssl_hs_write = 1;
68 iohandler_log(IOLOG_DEBUG, "SSL_do_handshake for %s (fd: %d) returned SSL_ERROR_WANT_WRITE", iohandler_iotype_name(iofd->type), iofd->fd);
71 iohandler_log(IOLOG_ERROR, "SSL_do_handshake for %s (fd: %d) failed with ", iohandler_iotype_name(iofd->type), iofd->fd);
72 iohandler_events(iofd, 0, 0);
78 void iohandler_ssl_disconnect(struct IODescriptor *iofd) {
80 if(!iofd->sslnode) return;
81 SSL_shutdown(iofd->sslnode->sslHandle);
82 SSL_free(iofd->sslnode->sslHandle);
83 SSL_CTX_free(iofd->sslnode->sslContext);
90 int iohandler_ssl_read(struct IODescriptor *iofd, char *buffer, int len) {
92 if(!iofd->sslnode) return 0;
93 int ret = SSL_read(iofd->sslnode->sslHandle, buffer, len);
94 int update = (iofd->ssl_hs_read || iofd->ssl_hs_write);
95 iofd->ssl_hs_read = 0;
96 iofd->ssl_hs_write = 0;
97 switch(SSL_get_error(iofd->sslnode->sslHandle, ret)) {
99 case SSL_ERROR_ZERO_RETURN:
101 iohandler_update(iofd);
104 case SSL_ERROR_WANT_READ:
105 iofd->ssl_hs_read = 1;
106 iohandler_update(iofd);
107 iohandler_log(IOLOG_DEBUG, "SSL_read for %s (fd: %d) returned SSL_ERROR_WANT_READ", iohandler_iotype_name(iofd->type), iofd->fd);
111 case SSL_ERROR_WANT_WRITE:
112 iofd->ssl_hs_write = 1;
113 iohandler_update(iofd);
114 iohandler_log(IOLOG_DEBUG, "SSL_read for %s (fd: %d) returned SSL_ERROR_WANT_WRITE", iohandler_iotype_name(iofd->type), iofd->fd);
119 iohandler_log(IOLOG_ERROR, "SSL_read for %s (fd: %d) failed with ", iohandler_iotype_name(iofd->type), iofd->fd);
127 int iohandler_ssl_write(struct IODescriptor *iofd, char *buffer, int len) {
129 if(!iofd->sslnode) return 0;
130 int ret = SSL_write(iofd->sslnode->sslHandle, buffer, len);
131 int update = (iofd->ssl_hs_read || iofd->ssl_hs_write);
132 iofd->ssl_hs_read = 0;
133 iofd->ssl_hs_write = 0;
134 switch(SSL_get_error(iofd->sslnode->sslHandle, ret)) {
136 case SSL_ERROR_ZERO_RETURN:
138 iohandler_update(iofd);
141 case SSL_ERROR_WANT_READ:
142 iofd->ssl_hs_read = 1;
143 iohandler_update(iofd);
144 iohandler_log(IOLOG_DEBUG, "SSL_write for %s (fd: %d) returned SSL_ERROR_WANT_READ", iohandler_iotype_name(iofd->type), iofd->fd);
148 case SSL_ERROR_WANT_WRITE:
149 iofd->ssl_hs_write = 1;
150 iohandler_update(iofd);
151 iohandler_log(IOLOG_DEBUG, "SSL_write for %s (fd: %d) returned SSL_ERROR_WANT_WRITE", iohandler_iotype_name(iofd->type), iofd->fd);
156 iohandler_log(IOLOG_ERROR, "SSL_write for %s (fd: %d) failed with ", iohandler_iotype_name(iofd->type), iofd->fd);