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"
21 void iohandler_ssl_init() {
23 OpenSSL_add_all_algorithms(); /* load & register all cryptos, etc. */
24 SSL_load_error_strings();
27 static void iohandler_ssl_error() {
29 while((e = ERR_get_error())) {
30 iohandler_log(IOLOG_ERROR, "SSLv23 ERROR %lu: %s", e, ERR_error_string(e, NULL));
34 void iohandler_ssl_connect(struct IODescriptor *iofd) {
35 iofd->state = IO_SSLWAIT;
36 iofd->ssl_server_hs = 0;
37 struct IOSSLNode *sslnode = malloc(sizeof(*sslnode));
38 sslnode->sslContext = SSL_CTX_new(SSLv23_client_method());
39 if(!sslnode->sslContext) {
40 iohandler_ssl_error();
41 iohandler_log(IOLOG_ERROR, "SSL: could not create client SSL CTX");
44 sslnode->sslHandle = SSL_new(sslnode->sslContext);
45 if(!sslnode->sslHandle) {
46 iohandler_ssl_error();
47 iohandler_log(IOLOG_ERROR, "SSL: could not create client SSL Handle");
50 if(!SSL_set_fd(sslnode->sslHandle, iofd->fd)) {
51 iohandler_ssl_error();
52 iohandler_log(IOLOG_ERROR, "SSL: could not set client fd in SSL Handle");
55 SSL_set_connect_state(sslnode->sslHandle);
56 iofd->sslnode = sslnode;
57 iohandler_ssl_client_handshake(iofd);
61 iohandler_events(iofd, 0, 0);
64 void iohandler_ssl_listen(struct IODescriptor *iofd, const char *certfile, const char *keyfile) {
65 struct IOSSLNode *sslnode = malloc(sizeof(*sslnode));
66 sslnode->sslContext = SSL_CTX_new(SSLv23_server_method());
67 if(!sslnode->sslContext) {
68 iohandler_ssl_error();
69 iohandler_log(IOLOG_ERROR, "SSL: could not create server SSL CTX");
72 /* load certificate */
73 if(SSL_CTX_use_certificate_file(sslnode->sslContext, certfile, SSL_FILETYPE_PEM) <= 0) {
74 iohandler_ssl_error();
75 iohandler_log(IOLOG_ERROR, "SSL: could not load server certificate (%s)", certfile);
79 if(SSL_CTX_use_PrivateKey_file(sslnode->sslContext, keyfile, SSL_FILETYPE_PEM) <= 0) {
80 iohandler_ssl_error();
81 iohandler_log(IOLOG_ERROR, "SSL: could not load server keyfile (%s)", keyfile);
84 /* check certificate and keyfile */
85 if(!SSL_CTX_check_private_key(sslnode->sslContext)) {
86 iohandler_ssl_error();
87 iohandler_log(IOLOG_ERROR, "SSL: server certificate (%s) and keyfile (%s) doesn't match!", certfile, keyfile);
90 iofd->sslnode = sslnode;
95 iohandler_events(iofd, 0, 0);
98 void iohandler_ssl_client_handshake(struct IODescriptor *iofd) {
99 // Perform an SSL handshake.
100 int ret = SSL_do_handshake(iofd->sslnode->sslHandle);
101 iofd->ssl_hs_read = 0;
102 iofd->ssl_hs_write = 0;
103 switch(SSL_get_error(iofd->sslnode->sslHandle, ret)) {
105 iofd->state = IO_CONNECTING;
106 iofd->ssl_active = 1;
107 iohandler_log(IOLOG_DEBUG, "SSL handshake for %s (fd: %d) successful", iohandler_iotype_name(iofd->type), iofd->fd);
108 iohandler_events(iofd, 0, 1); //perform IOEVENT_CONNECTED event
110 case SSL_ERROR_WANT_READ:
111 iofd->ssl_hs_read = 1;
112 iohandler_log(IOLOG_DEBUG, "SSL_do_handshake for %s (fd: %d) returned SSL_ERROR_WANT_READ", iohandler_iotype_name(iofd->type), iofd->fd);
114 case SSL_ERROR_WANT_WRITE:
115 iofd->ssl_hs_write = 1;
116 iohandler_log(IOLOG_DEBUG, "SSL_do_handshake for %s (fd: %d) returned SSL_ERROR_WANT_WRITE", iohandler_iotype_name(iofd->type), iofd->fd);
119 iohandler_log(IOLOG_ERROR, "SSL_do_handshake for %s (fd: %d) failed with ", iohandler_iotype_name(iofd->type), iofd->fd);
120 iohandler_events(iofd, 0, 0);
125 void iohandler_ssl_client_accepted(struct IODescriptor *iofd, struct IODescriptor *client_iofd) {
126 struct IOSSLNode *sslnode = malloc(sizeof(*sslnode));
127 sslnode->sslHandle = SSL_new(sslnode->sslContext);
128 if(!sslnode->sslHandle) {
129 iohandler_ssl_error();
130 iohandler_log(IOLOG_ERROR, "SSL: could not create client SSL Handle");
133 if(!SSL_set_fd(sslnode->sslHandle, client_iofd->fd)) {
134 iohandler_ssl_error();
135 iohandler_log(IOLOG_ERROR, "SSL: could not set client fd in SSL Handle");
138 client_iofd->state = IO_SSLWAIT;
139 client_iofd->ssl_server_hs = 1;
140 client_iofd->ssl = 1;
141 client_iofd->sslnode = sslnode;
142 client_iofd->callback = iofd->callback;
143 client_iofd->data = iofd;
146 iohandler_close(client_iofd);
150 void iohandler_ssl_server_handshake(struct IODescriptor *iofd) {
151 // Perform an SSL handshake.
152 int ret = SSL_accept(iofd->sslnode->sslHandle);
153 iofd->ssl_hs_read = 0;
154 iofd->ssl_hs_write = 0;
155 switch(SSL_get_error(iofd->sslnode->sslHandle, ret)) {
157 iofd->state = IO_CONNECTING;
158 iofd->ssl_active = 1;
159 iohandler_log(IOLOG_DEBUG, "SSL handshake for %s (fd: %d) successful", iohandler_iotype_name(iofd->type), iofd->fd);
160 iohandler_events(iofd, 0, 1); //perform IOEVENT_CONNECTED event
162 case SSL_ERROR_WANT_READ:
163 iofd->ssl_hs_read = 1;
164 iohandler_log(IOLOG_DEBUG, "SSL_do_handshake for %s (fd: %d) returned SSL_ERROR_WANT_READ", iohandler_iotype_name(iofd->type), iofd->fd);
166 case SSL_ERROR_WANT_WRITE:
167 iofd->ssl_hs_write = 1;
168 iohandler_log(IOLOG_DEBUG, "SSL_do_handshake for %s (fd: %d) returned SSL_ERROR_WANT_WRITE", iohandler_iotype_name(iofd->type), iofd->fd);
171 iohandler_log(IOLOG_ERROR, "SSL_do_handshake for %s (fd: %d) failed with ", iohandler_iotype_name(iofd->type), iofd->fd);
172 iohandler_events(iofd, 0, 0);
177 void iohandler_ssl_disconnect(struct IODescriptor *iofd) {
178 if(!iofd->sslnode) return;
179 SSL_shutdown(iofd->sslnode->sslHandle);
180 SSL_free(iofd->sslnode->sslHandle);
181 SSL_CTX_free(iofd->sslnode->sslContext);
183 iofd->sslnode = NULL;
184 iofd->ssl_active = 0;
187 int iohandler_ssl_read(struct IODescriptor *iofd, char *buffer, int len) {
188 if(!iofd->sslnode) return 0;
189 int ret = SSL_read(iofd->sslnode->sslHandle, buffer, len);
190 int update = (iofd->ssl_hs_read || iofd->ssl_hs_write);
191 iofd->ssl_hs_read = 0;
192 iofd->ssl_hs_write = 0;
193 switch(SSL_get_error(iofd->sslnode->sslHandle, ret)) {
195 case SSL_ERROR_ZERO_RETURN:
197 iohandler_update(iofd);
200 case SSL_ERROR_WANT_READ:
201 iofd->ssl_hs_read = 1;
202 iohandler_update(iofd);
203 iohandler_log(IOLOG_DEBUG, "SSL_read for %s (fd: %d) returned SSL_ERROR_WANT_READ", iohandler_iotype_name(iofd->type), iofd->fd);
207 case SSL_ERROR_WANT_WRITE:
208 iofd->ssl_hs_write = 1;
209 iohandler_update(iofd);
210 iohandler_log(IOLOG_DEBUG, "SSL_read for %s (fd: %d) returned SSL_ERROR_WANT_WRITE", iohandler_iotype_name(iofd->type), iofd->fd);
215 iohandler_log(IOLOG_ERROR, "SSL_read for %s (fd: %d) failed with ", iohandler_iotype_name(iofd->type), iofd->fd);
221 int iohandler_ssl_write(struct IODescriptor *iofd, char *buffer, int len) {
222 if(!iofd->sslnode) return 0;
223 int ret = SSL_write(iofd->sslnode->sslHandle, buffer, len);
224 int update = (iofd->ssl_hs_read || iofd->ssl_hs_write);
225 iofd->ssl_hs_read = 0;
226 iofd->ssl_hs_write = 0;
227 switch(SSL_get_error(iofd->sslnode->sslHandle, ret)) {
229 case SSL_ERROR_ZERO_RETURN:
231 iohandler_update(iofd);
234 case SSL_ERROR_WANT_READ:
235 iofd->ssl_hs_read = 1;
236 iohandler_update(iofd);
237 iohandler_log(IOLOG_DEBUG, "SSL_write for %s (fd: %d) returned SSL_ERROR_WANT_READ", iohandler_iotype_name(iofd->type), iofd->fd);
241 case SSL_ERROR_WANT_WRITE:
242 iofd->ssl_hs_write = 1;
243 iohandler_update(iofd);
244 iohandler_log(IOLOG_DEBUG, "SSL_write for %s (fd: %d) returned SSL_ERROR_WANT_WRITE", iohandler_iotype_name(iofd->type), iofd->fd);
249 iohandler_log(IOLOG_ERROR, "SSL_write for %s (fd: %d) failed with ", iohandler_iotype_name(iofd->type), iofd->fd);
258 void iohandler_ssl_init() {};
259 void iohandler_ssl_connect(struct IODescriptor *iofd) {};
260 void iohandler_ssl_listen(struct IODescriptor *iofd, const char *certfile, const char *keyfile) {};
261 void iohandler_ssl_client_handshake(struct IODescriptor *iofd) {};
262 void iohandler_ssl_client_accepted(struct IODescriptor *iofd, struct IODescriptor *client_iofd) {};
263 void iohandler_ssl_server_handshake(struct IODescriptor *iofd) {};
264 void iohandler_ssl_disconnect(struct IODescriptor *iofd) {};
265 int iohandler_ssl_read(struct IODescriptor *iofd, char *buffer, int len) { return 0; };
266 int iohandler_ssl_write(struct IODescriptor *iofd, char *buffer, int len) { return 0; };