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 OpenSSL_add_all_algorithms(); /* load & register all cryptos, etc. */
24 SSL_load_error_strings();
28 static void iohandler_ssl_error() {
30 while((e = ERR_get_error())) {
31 iohandler_log(IOLOG_ERROR, "SSLv23 ERROR %lu: %s", e, ERR_error_string(e, NULL));
35 void iohandler_ssl_connect(struct IODescriptor *iofd) {
37 iofd->state = IO_SSLWAIT;
38 iofd->ssl_server_hs = 0;
39 struct IOSSLNode *sslnode = malloc(sizeof(*sslnode));
40 sslnode->sslContext = SSL_CTX_new(SSLv23_client_method());
41 if(!sslnode->sslContext) {
42 iohandler_ssl_error();
43 iohandler_log(IOLOG_ERROR, "SSL: could not create client SSL CTX");
46 sslnode->sslHandle = SSL_new(sslnode->sslContext);
47 if(!sslnode->sslHandle) {
48 iohandler_ssl_error();
49 iohandler_log(IOLOG_ERROR, "SSL: could not create client SSL Handle");
52 if(!SSL_set_fd(sslnode->sslHandle, iofd->fd)) {
53 iohandler_ssl_error();
54 iohandler_log(IOLOG_ERROR, "SSL: could not set client fd in SSL Handle");
57 SSL_set_connect_state(sslnode->sslHandle);
58 iofd->sslnode = sslnode;
59 iohandler_ssl_client_handshake(iofd);
63 iohandler_events(iofd, 0, 0);
67 void iohandler_ssl_listen(struct IODescriptor *iofd, const char *certfile, const char *keyfile) {
69 struct IOSSLNode *sslnode = malloc(sizeof(*sslnode));
70 sslnode->sslContext = SSL_CTX_new(SSLv23_server_method());
71 if(!sslnode->sslContext) {
72 iohandler_ssl_error();
73 iohandler_log(IOLOG_ERROR, "SSL: could not create server SSL CTX");
76 /* load certificate */
77 if(SSL_CTX_use_certificate_file(sslnode->sslContext, certfile, SSL_FILETYPE_PEM) <= 0) {
78 iohandler_ssl_error();
79 iohandler_log(IOLOG_ERROR, "SSL: could not load server certificate (%s)", certfile);
83 if(SSL_CTX_use_PrivateKey_file(sslnode->sslContext, keyfile, SSL_FILETYPE_PEM) <= 0) {
84 iohandler_ssl_error();
85 iohandler_log(IOLOG_ERROR, "SSL: could not load server keyfile (%s)", keyfile);
88 /* check certificate and keyfile */
89 if(!SSL_CTX_check_private_key(sslnode->sslContext)) {
90 iohandler_ssl_error();
91 iohandler_log(IOLOG_ERROR, "SSL: server certificate (%s) and keyfile (%s) doesn't match!", certfile, keyfile);
94 iofd->sslnode = sslnode;
99 iohandler_events(iofd, 0, 0);
103 void iohandler_ssl_client_handshake(struct IODescriptor *iofd) {
105 // Perform an SSL handshake.
106 int ret = SSL_do_handshake(iofd->sslnode->sslHandle);
107 iofd->ssl_hs_read = 0;
108 iofd->ssl_hs_write = 0;
109 switch(SSL_get_error(iofd->sslnode->sslHandle, ret)) {
111 iofd->state = IO_CONNECTING;
112 iofd->ssl_active = 1;
113 iohandler_log(IOLOG_DEBUG, "SSL handshake for %s (fd: %d) successful", iohandler_iotype_name(iofd->type), iofd->fd);
114 iohandler_events(iofd, 0, 1); //perform IOEVENT_CONNECTED event
116 case SSL_ERROR_WANT_READ:
117 iofd->ssl_hs_read = 1;
118 iohandler_log(IOLOG_DEBUG, "SSL_do_handshake for %s (fd: %d) returned SSL_ERROR_WANT_READ", iohandler_iotype_name(iofd->type), iofd->fd);
120 case SSL_ERROR_WANT_WRITE:
121 iofd->ssl_hs_write = 1;
122 iohandler_log(IOLOG_DEBUG, "SSL_do_handshake for %s (fd: %d) returned SSL_ERROR_WANT_WRITE", iohandler_iotype_name(iofd->type), iofd->fd);
125 iohandler_log(IOLOG_ERROR, "SSL_do_handshake for %s (fd: %d) failed with ", iohandler_iotype_name(iofd->type), iofd->fd);
126 iohandler_events(iofd, 0, 0);
132 void iohandler_ssl_client_accepted(struct IODescriptor *iofd, struct IODescriptor *client_iofd) {
134 struct IOSSLNode *sslnode = malloc(sizeof(*sslnode));
135 sslnode->sslHandle = SSL_new(sslnode->sslContext);
136 if(!sslnode->sslHandle) {
137 iohandler_ssl_error();
138 iohandler_log(IOLOG_ERROR, "SSL: could not create client SSL Handle");
141 if(!SSL_set_fd(sslnode->sslHandle, client_iofd->fd)) {
142 iohandler_ssl_error();
143 iohandler_log(IOLOG_ERROR, "SSL: could not set client fd in SSL Handle");
146 client_iofd->state = IO_SSLWAIT;
147 client_iofd->ssl_server_hs = 1;
148 client_iofd->ssl = 1;
149 client_iofd->sslnode = sslnode;
150 client_iofd->callback = iofd->callback;
151 client_iofd->data = iofd;
154 iohandler_close(client_iofd);
159 void iohandler_ssl_server_handshake(struct IODescriptor *iofd) {
161 // Perform an SSL handshake.
162 int ret = SSL_accept(iofd->sslnode->sslHandle);
163 iofd->ssl_hs_read = 0;
164 iofd->ssl_hs_write = 0;
165 switch(SSL_get_error(iofd->sslnode->sslHandle, ret)) {
167 iofd->state = IO_CONNECTING;
168 iofd->ssl_active = 1;
169 iohandler_log(IOLOG_DEBUG, "SSL handshake for %s (fd: %d) successful", iohandler_iotype_name(iofd->type), iofd->fd);
170 iohandler_events(iofd, 0, 1); //perform IOEVENT_CONNECTED event
172 case SSL_ERROR_WANT_READ:
173 iofd->ssl_hs_read = 1;
174 iohandler_log(IOLOG_DEBUG, "SSL_do_handshake for %s (fd: %d) returned SSL_ERROR_WANT_READ", iohandler_iotype_name(iofd->type), iofd->fd);
176 case SSL_ERROR_WANT_WRITE:
177 iofd->ssl_hs_write = 1;
178 iohandler_log(IOLOG_DEBUG, "SSL_do_handshake for %s (fd: %d) returned SSL_ERROR_WANT_WRITE", iohandler_iotype_name(iofd->type), iofd->fd);
181 iohandler_log(IOLOG_ERROR, "SSL_do_handshake for %s (fd: %d) failed with ", iohandler_iotype_name(iofd->type), iofd->fd);
182 iohandler_events(iofd, 0, 0);
188 void iohandler_ssl_disconnect(struct IODescriptor *iofd) {
190 if(!iofd->sslnode) return;
191 SSL_shutdown(iofd->sslnode->sslHandle);
192 SSL_free(iofd->sslnode->sslHandle);
193 SSL_CTX_free(iofd->sslnode->sslContext);
195 iofd->sslnode = NULL;
196 iofd->ssl_active = 0;
200 int iohandler_ssl_read(struct IODescriptor *iofd, char *buffer, int len) {
202 if(!iofd->sslnode) return 0;
203 int ret = SSL_read(iofd->sslnode->sslHandle, buffer, len);
204 int update = (iofd->ssl_hs_read || iofd->ssl_hs_write);
205 iofd->ssl_hs_read = 0;
206 iofd->ssl_hs_write = 0;
207 switch(SSL_get_error(iofd->sslnode->sslHandle, ret)) {
209 case SSL_ERROR_ZERO_RETURN:
211 iohandler_update(iofd);
214 case SSL_ERROR_WANT_READ:
215 iofd->ssl_hs_read = 1;
216 iohandler_update(iofd);
217 iohandler_log(IOLOG_DEBUG, "SSL_read for %s (fd: %d) returned SSL_ERROR_WANT_READ", iohandler_iotype_name(iofd->type), iofd->fd);
221 case SSL_ERROR_WANT_WRITE:
222 iofd->ssl_hs_write = 1;
223 iohandler_update(iofd);
224 iohandler_log(IOLOG_DEBUG, "SSL_read for %s (fd: %d) returned SSL_ERROR_WANT_WRITE", iohandler_iotype_name(iofd->type), iofd->fd);
229 iohandler_log(IOLOG_ERROR, "SSL_read for %s (fd: %d) failed with ", iohandler_iotype_name(iofd->type), iofd->fd);
237 int iohandler_ssl_write(struct IODescriptor *iofd, char *buffer, int len) {
239 if(!iofd->sslnode) return 0;
240 int ret = SSL_write(iofd->sslnode->sslHandle, buffer, len);
241 int update = (iofd->ssl_hs_read || iofd->ssl_hs_write);
242 iofd->ssl_hs_read = 0;
243 iofd->ssl_hs_write = 0;
244 switch(SSL_get_error(iofd->sslnode->sslHandle, ret)) {
246 case SSL_ERROR_ZERO_RETURN:
248 iohandler_update(iofd);
251 case SSL_ERROR_WANT_READ:
252 iofd->ssl_hs_read = 1;
253 iohandler_update(iofd);
254 iohandler_log(IOLOG_DEBUG, "SSL_write for %s (fd: %d) returned SSL_ERROR_WANT_READ", iohandler_iotype_name(iofd->type), iofd->fd);
258 case SSL_ERROR_WANT_WRITE:
259 iofd->ssl_hs_write = 1;
260 iohandler_update(iofd);
261 iohandler_log(IOLOG_DEBUG, "SSL_write for %s (fd: %d) returned SSL_ERROR_WANT_WRITE", iohandler_iotype_name(iofd->type), iofd->fd);
266 iohandler_log(IOLOG_ERROR, "SSL_write for %s (fd: %d) failed with ", iohandler_iotype_name(iofd->type), iofd->fd);