1 /* IOHandler_SSL.c - TransparentIRC 0.1
2 * Copyright (C) 2011-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/>.
17 #include "IOHandler.h"
19 #include "IOHandler_SSL.h"
21 void iohandler_ssl_init() {
24 SSL_load_error_strings();
28 void iohandler_ssl_connect(struct IODescriptor *iofd) {
30 iofd->state = IO_SSLWAIT;
31 struct IOSSLNode *sslnode = malloc(sizeof(*sslnode));
32 sslnode->sslContext = SSL_CTX_new(SSLv23_client_method());
33 if(!sslnode->sslContext)
35 sslnode->sslHandle = SSL_new(sslnode->sslContext);
36 if(!sslnode->sslHandle)
38 if(!SSL_set_fd(sslnode->sslHandle, iofd->fd))
40 SSL_set_connect_state(sslnode->sslHandle);
41 iofd->sslnode = sslnode;
42 iohandler_ssl_client_handshake(iofd);
46 iohandler_events(iofd, 0, 0);
50 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);
77 void iohandler_ssl_disconnect(struct IODescriptor *iofd) {
79 if(!iofd->sslnode) return;
80 SSL_shutdown(iofd->sslnode->sslHandle);
81 SSL_free(iofd->sslnode->sslHandle);
82 SSL_CTX_free(iofd->sslnode->sslContext);
89 int iohandler_ssl_read(struct IODescriptor *iofd, char *buffer, int len) {
91 if(!iofd->sslnode) return 0;
92 int ret = SSL_read(iofd->sslnode->sslHandle, buffer, len);
93 int update = (iofd->ssl_hs_read || iofd->ssl_hs_write);
94 iofd->ssl_hs_read = 0;
95 iofd->ssl_hs_write = 0;
96 switch(SSL_get_error(iofd->sslnode->sslHandle, ret)) {
98 case SSL_ERROR_ZERO_RETURN:
100 iohandler_update(iofd);
103 case SSL_ERROR_WANT_READ:
104 iofd->ssl_hs_read = 1;
105 iohandler_update(iofd);
106 iohandler_log(IOLOG_DEBUG, "SSL_read for %s (fd: %d) returned SSL_ERROR_WANT_READ", iohandler_iotype_name(iofd->type), iofd->fd);
110 case SSL_ERROR_WANT_WRITE:
111 iofd->ssl_hs_write = 1;
112 iohandler_update(iofd);
113 iohandler_log(IOLOG_DEBUG, "SSL_read for %s (fd: %d) returned SSL_ERROR_WANT_WRITE", iohandler_iotype_name(iofd->type), iofd->fd);
118 iohandler_log(IOLOG_ERROR, "SSL_read for %s (fd: %d) failed with ", iohandler_iotype_name(iofd->type), iofd->fd);
126 int iohandler_ssl_write(struct IODescriptor *iofd, char *buffer, int len) {
128 if(!iofd->sslnode) return 0;
129 int ret = SSL_write(iofd->sslnode->sslHandle, buffer, len);
130 int update = (iofd->ssl_hs_read || iofd->ssl_hs_write);
131 iofd->ssl_hs_read = 0;
132 iofd->ssl_hs_write = 0;
133 switch(SSL_get_error(iofd->sslnode->sslHandle, ret)) {
135 case SSL_ERROR_ZERO_RETURN:
137 iohandler_update(iofd);
140 case SSL_ERROR_WANT_READ:
141 iofd->ssl_hs_read = 1;
142 iohandler_update(iofd);
143 iohandler_log(IOLOG_DEBUG, "SSL_write for %s (fd: %d) returned SSL_ERROR_WANT_READ", iohandler_iotype_name(iofd->type), iofd->fd);
147 case SSL_ERROR_WANT_WRITE:
148 iofd->ssl_hs_write = 1;
149 iohandler_update(iofd);
150 iohandler_log(IOLOG_DEBUG, "SSL_write for %s (fd: %d) returned SSL_ERROR_WANT_WRITE", iohandler_iotype_name(iofd->type), iofd->fd);
155 iohandler_log(IOLOG_ERROR, "SSL_write for %s (fd: %d) failed with ", iohandler_iotype_name(iofd->type), iofd->fd);