[IOMultiplexerV2] Fixed listening SSL sockets
[NextIRCd.git] / src / IOHandler / IOSSLBackend.c
1 /* IOSSLBackend.c - IOMultiplexer
2  * Copyright (C) 2014  Philipp Kreil (pk910)
3  * 
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.
8  * 
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.
13  * 
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/>. 
16  */
17 #define _IOHandler_internals
18 #include "IOInternal.h"
19 #include "IOHandler.h"
20 #include "IOLog.h"
21 #include "IOSockets.h"
22 #include "IOSSLBackend.h"
23
24 #if defined(HAVE_GNUTLS_GNUTLS_H)
25 #include <string.h>
26 #include <stdlib.h>
27 #include <errno.h>
28 /* GnuTLS Backend */
29 static gnutls_dh_params_t dh_params;
30 static unsigned int dh_params_bits;
31
32 static int generate_dh_params() {
33         dh_params_bits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, GNUTLS_SEC_PARAM_LEGACY);
34         gnutls_dh_params_init(&dh_params);
35         gnutls_dh_params_generate2(dh_params, dh_params_bits);
36         return 0;
37 }
38
39 void iossl_init() {
40         int ret;
41         if((ret = gnutls_global_init()) != GNUTLS_E_SUCCESS) {
42                 iolog_trigger(IOLOG_ERROR, "SSL: gnutls_global_init(): failed (%d)", ret);
43                 //TODO: Error handling?
44                 return;
45         }
46         generate_dh_params();
47 }
48
49 // Client
50 void iossl_connect(struct _IOSocket *iosock) {
51         struct IOSSLDescriptor *sslnode = malloc(sizeof(*sslnode));
52         int err;
53         
54         err = gnutls_certificate_allocate_credentials(&sslnode->ssl.client.credentials);
55         if(err < 0) {
56                 goto ssl_connect_err;
57         }
58         
59         gnutls_init(&sslnode->ssl.client.session, GNUTLS_CLIENT);
60         
61         gnutls_priority_set_direct(sslnode->ssl.client.session, "SECURE128:+SECURE192:-VERS-TLS-ALL:+VERS-TLS1.2", NULL);
62         gnutls_credentials_set(sslnode->ssl.client.session, GNUTLS_CRD_CERTIFICATE, sslnode->ssl.client.credentials);
63         
64         gnutls_transport_set_int(sslnode->ssl.client.session, iosock->fd);
65         gnutls_handshake_set_timeout(sslnode->ssl.client.session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
66         
67         iosock->sslnode = sslnode;
68         iosock->socket_flags |= IOSOCKETFLAG_SSL_HANDSHAKE;
69         iossl_client_handshake(iosock);
70         return;
71 ssl_connect_err:
72         free(sslnode);
73         iosocket_events_callback(iosock, 0, 0);
74 }
75
76 void iossl_client_handshake(struct _IOSocket *iosock) {
77         // Perform an SSL handshake.
78         int ret = gnutls_handshake(iosock->sslnode->ssl.client.session);
79         iosock->socket_flags &= ~IOSOCKETFLAG_SSL_WANTWRITE;
80         
81         if(ret < 0) {
82                 if(gnutls_error_is_fatal(ret) == 0) {
83                         if(gnutls_record_get_direction(iosock->sslnode->ssl.client.session)) {
84                                 iosock->socket_flags |= IOSOCKETFLAG_SSL_WANTWRITE;
85                                 iolog_trigger(IOLOG_DEBUG, "gnutls_handshake for fd %d wants to write...", iosock->fd);
86                         } else {
87                                 iolog_trigger(IOLOG_DEBUG, "gnutls_handshake for fd %d wants to read...", iosock->fd);
88                         }
89                 } else {
90                         iolog_trigger(IOLOG_ERROR, "gnutls_handshake for fd %d failed with %s", iosock->fd, gnutls_strerror(ret));
91                         iosocket_events_callback(iosock, 0, 0);
92                 }
93         } else {
94                 char *desc;
95                 desc = gnutls_session_get_desc(iosock->sslnode->ssl.client.session);
96                 iolog_trigger(IOLOG_DEBUG, "SSL handshake for fd %d successful: %s", iosock->fd, desc);
97                 gnutls_free(desc);
98                 iosock->socket_flags |= IOSOCKETFLAG_SSL_ESTABLISHED;
99                 iosocket_events_callback(iosock, 0, 0); //perform IOEVENT_CONNECTED event
100         }
101 }
102
103
104 // Server
105 void iossl_listen(struct _IOSocket *iosock, const char *certfile, const char *keyfile) {
106         struct IOSSLDescriptor *sslnode = malloc(sizeof(*sslnode));
107         
108         gnutls_priority_init(&sslnode->ssl.server.priority, "SECURE128:+SECURE192:-VERS-TLS-ALL:+VERS-TLS1.2", NULL);
109         
110         gnutls_certificate_allocate_credentials(&sslnode->ssl.server.credentials);
111         int ret = gnutls_certificate_set_x509_key_file(sslnode->ssl.server.credentials, certfile, keyfile, GNUTLS_X509_FMT_PEM);
112         if (ret < 0) {
113                 iolog_trigger(IOLOG_ERROR, "SSL: could not load server certificate/key (%s %s): %d - %s", certfile, keyfile, ret, gnutls_strerror(ret));
114                 goto ssl_listen_err;
115         }
116         
117         gnutls_certificate_set_dh_params(sslnode->ssl.server.credentials, dh_params);
118         
119         iosock->sslnode = sslnode;
120         iosock->socket_flags |= IOSOCKETFLAG_SSL_ESTABLISHED;
121         return;
122 ssl_listen_err:
123         free(sslnode);
124         iosock->sslnode = NULL;
125         iosocket_events_callback(iosock, 0, 0);
126 }
127
128 void iossl_client_accepted(struct _IOSocket *iosock, struct _IOSocket *new_iosock) {
129         struct IOSSLDescriptor *sslnode = malloc(sizeof(*sslnode));
130         
131         gnutls_init(&sslnode->ssl.client.session, GNUTLS_SERVER);
132         gnutls_priority_set(sslnode->ssl.client.session, iosock->sslnode->ssl.server.priority);
133         gnutls_credentials_set(sslnode->ssl.client.session, GNUTLS_CRD_CERTIFICATE, iosock->sslnode->ssl.server.credentials);
134         gnutls_dh_set_prime_bits(sslnode->ssl.client.session, dh_params_bits);
135         
136         /* We don't request any certificate from the client.
137          * If we did we would need to verify it.
138          */
139         gnutls_certificate_server_set_request(sslnode->ssl.client.session, GNUTLS_CERT_IGNORE);
140         
141         gnutls_transport_set_int(sslnode->ssl.client.session, new_iosock->fd);
142         
143         new_iosock->sslnode = sslnode;
144         new_iosock->socket_flags |= IOSOCKETFLAG_SSL_HANDSHAKE;
145         return;
146         /*
147 ssl_accept_err:
148         free(sslnode);
149         iosock->sslnode = NULL;
150         iosocket_events_callback(new_iosock, 0, 0);
151         */
152 }
153
154 void iossl_server_handshake(struct _IOSocket *iosock) {
155         return iossl_client_handshake(iosock);
156 }
157
158 void iossl_disconnect(struct _IOSocket *iosock) {
159         if(!iosock->sslnode) return;
160         
161         if((iosock->socket_flags & IOSOCKETFLAG_LISTENING)) {
162                 gnutls_certificate_free_credentials(iosock->sslnode->ssl.server.credentials);
163                 gnutls_priority_deinit(iosock->sslnode->ssl.server.priority);
164         } else {
165                 gnutls_bye(iosock->sslnode->ssl.client.session, GNUTLS_SHUT_RDWR);
166                 if(!(iosock->socket_flags & IOSOCKETFLAG_INCOMING))
167                         gnutls_certificate_free_credentials(iosock->sslnode->ssl.client.credentials);
168                 gnutls_deinit(iosock->sslnode->ssl.client.session);
169         }
170         
171         free(iosock->sslnode);
172         iosock->sslnode = NULL;
173         iosock->socket_flags &= ~IOSOCKETFLAG_SSLSOCKET;
174 }
175
176 static void iossl_rehandshake(struct _IOSocket *iosock, int hsflag) {
177         int ret = gnutls_handshake(iosock->sslnode->ssl.client.session);
178         iosock->socket_flags &= ~IOSOCKETFLAG_SSL_WANTWRITE;
179         
180         if(ret < 0) {
181                 if(gnutls_error_is_fatal(ret) == 0) {
182                         if(gnutls_record_get_direction(iosock->sslnode->ssl.client.session)) {
183                                 iosock->socket_flags |= IOSOCKETFLAG_SSL_WANTWRITE | hsflag;
184                                 iolog_trigger(IOLOG_DEBUG, "gnutls_handshake for fd %d wants to write...", iosock->fd);
185                         } else {
186                                 iosock->socket_flags |= hsflag;
187                                 iolog_trigger(IOLOG_DEBUG, "gnutls_handshake for fd %d wants to read...", iosock->fd);
188                         }
189                 } else {
190                         iolog_trigger(IOLOG_ERROR, "gnutls_handshake for fd %d failed: %s", iosock->fd, gnutls_strerror(ret));
191                         //TODO: Error Action?
192                 }
193         } else {
194                 char *desc;
195                 desc = gnutls_session_get_desc(iosock->sslnode->ssl.client.session);
196                 iolog_trigger(IOLOG_DEBUG, "SSL handshake for fd %d successful: %s", iosock->fd, desc);
197                 gnutls_free(desc);
198                 iosock->socket_flags &= ~hsflag;
199         }
200 }
201
202 int iossl_read(struct _IOSocket *iosock, char *buffer, int len) {
203         if((iosock->socket_flags & (IOSOCKETFLAG_SSLSOCKET | IOSOCKETFLAG_SSL_ESTABLISHED)) != (IOSOCKETFLAG_SSLSOCKET | IOSOCKETFLAG_SSL_ESTABLISHED))
204                 return 0;
205         if((iosock->socket_flags & IOSOCKETFLAG_SSL_READHS)) {
206                 iossl_rehandshake(iosock, IOSOCKETFLAG_SSL_READHS);
207                 errno = EAGAIN;
208                 return -1;
209         }
210         int ret = gnutls_record_recv(iosock->sslnode->ssl.client.session, buffer, len);
211         if(ret == 0) {
212                 //TLS session closed
213                 //TODO: Action?
214         } else if(ret < 0 && gnutls_error_is_fatal(ret) == 0) {
215                 iolog_trigger(IOLOG_WARNING, "gnutls_record_recv for fd %d returned %s", iosock->fd, gnutls_strerror(ret));
216                 if(ret == GNUTLS_E_REHANDSHAKE) {
217                         iossl_rehandshake(iosock, IOSOCKETFLAG_SSL_READHS);
218                         errno = EAGAIN;
219                         return -1;
220                 }
221         } else if(ret < 0) {
222                 iolog_trigger(IOLOG_ERROR, "gnutls_record_recv for fd %d failed: %s", iosock->fd, gnutls_strerror(ret));
223                 errno = ret;
224                 return ret;
225         }
226         return ret;
227 }
228
229 int iossl_write(struct _IOSocket *iosock, char *buffer, int len) {
230         if((iosock->socket_flags & (IOSOCKETFLAG_SSLSOCKET | IOSOCKETFLAG_SSL_ESTABLISHED)) != (IOSOCKETFLAG_SSLSOCKET | IOSOCKETFLAG_SSL_ESTABLISHED))
231                 return 0;
232         if((iosock->socket_flags & IOSOCKETFLAG_SSL_WRITEHS)) {
233                 iossl_rehandshake(iosock, IOSOCKETFLAG_SSL_WRITEHS);
234                 errno = EAGAIN;
235                 return -1;
236         }
237         int ret = gnutls_record_send(iosock->sslnode->ssl.client.session, buffer, len);
238         if(ret < 0 && gnutls_error_is_fatal(ret) == 0) {
239                 iolog_trigger(IOLOG_WARNING, "gnutls_record_send for fd %d returned %s", iosock->fd, gnutls_strerror(ret));
240                 if(ret == GNUTLS_E_REHANDSHAKE) {
241                         iossl_rehandshake(iosock, IOSOCKETFLAG_SSL_WRITEHS);
242                         errno = EAGAIN;
243                         return -1;
244                 }
245         } else if(ret < 0) {
246                 iolog_trigger(IOLOG_ERROR, "gnutls_record_send for fd %d failed: %s", iosock->fd, gnutls_strerror(ret));
247                 errno = ret;
248                 return ret;
249         }
250         return ret;
251 }
252
253 #elif defined(HAVE_OPENSSL_SSL_H)
254 /* OpenSSL Backend */
255
256
257 void iossl_init() {
258         SSL_library_init();
259         OpenSSL_add_all_algorithms(); /* load & register all cryptos, etc. */
260         SSL_load_error_strings();
261 }
262
263 static void iossl_error() {
264         unsigned long e;
265         while((e = ERR_get_error())) {
266                 iolog_trigger(IOLOG_ERROR, "SSLv23 ERROR %lu: %s", e, ERR_error_string(e, NULL));
267         }
268 }
269
270 // Client
271 void iossl_connect(struct _IOSocket *iosock) {
272         struct IOSSLDescriptor *sslnode = malloc(sizeof(*sslnode));
273         sslnode->sslContext = SSL_CTX_new(SSLv23_client_method());
274         if(!sslnode->sslContext) {
275                 iossl_error();
276                 iolog_trigger(IOLOG_ERROR, "SSL: could not create client SSL CTX");
277                 goto ssl_connect_err;
278         }
279         sslnode->sslHandle = SSL_new(sslnode->sslContext);
280         if(!sslnode->sslHandle) {
281                 iossl_error();
282                 iolog_trigger(IOLOG_ERROR, "SSL: could not create client SSL Handle");
283                 goto ssl_connect_err;
284         }
285         if(!SSL_set_fd(sslnode->sslHandle, iosock->fd)) {
286                 iossl_error();
287                 iolog_trigger(IOLOG_ERROR, "SSL: could not set client fd in SSL Handle");
288                 goto ssl_connect_err;
289         }
290         SSL_set_connect_state(sslnode->sslHandle);
291         iosock->sslnode = sslnode;
292         iosock->socket_flags |= IOSOCKETFLAG_SSL_HANDSHAKE;
293         iossl_client_handshake(iosock);
294         return;
295 ssl_connect_err:
296         free(sslnode);
297         iosocket_events_callback(iosock, 0, 0);
298 }
299
300 void iossl_client_handshake(struct _IOSocket *iosock) {
301         // Perform an SSL handshake.
302         int ret = SSL_do_handshake(iosock->sslnode->sslHandle);
303         iosock->socket_flags &= ~IOSOCKETFLAG_SSL_WANTWRITE;
304         switch(SSL_get_error(iosock->sslnode->sslHandle, ret)) {
305                 case SSL_ERROR_NONE:
306                         iolog_trigger(IOLOG_DEBUG, "SSL handshake for fd %d successful", iosock->fd);
307                         iosock->socket_flags |= IOSOCKETFLAG_SSL_ESTABLISHED;
308                         iosocket_events_callback(iosock, 0, 0); //perform IOEVENT_CONNECTED event
309                         break;
310                 case SSL_ERROR_WANT_READ:
311                         iolog_trigger(IOLOG_DEBUG, "SSL_do_handshake for fd %d returned SSL_ERROR_WANT_READ", iosock->fd);
312                         break;
313                 case SSL_ERROR_WANT_WRITE:
314                         iosock->socket_flags |= IOSOCKETFLAG_SSL_WANTWRITE;
315                         iolog_trigger(IOLOG_DEBUG, "SSL_do_handshake for fd %d returned SSL_ERROR_WANT_WRITE", iosock->fd);
316                         break;
317                 default:
318                         iolog_trigger(IOLOG_ERROR, "SSL_do_handshake for fd %d failed with ", iosock->fd);
319                         iosocket_events_callback(iosock, 0, 0);
320                         break;
321         }
322 }
323
324
325 // Server
326 void iossl_listen(struct _IOSocket *iosock, const char *certfile, const char *keyfile) {
327         struct IOSSLDescriptor *sslnode = malloc(sizeof(*sslnode));
328         sslnode->sslContext = SSL_CTX_new(SSLv23_server_method());
329         if(!sslnode->sslContext) {
330                 iossl_error();
331                 iolog_trigger(IOLOG_ERROR, "SSL: could not create server SSL CTX");
332                 goto ssl_listen_err;
333         }
334         /* load certificate */
335         if(SSL_CTX_use_certificate_file(sslnode->sslContext, certfile, SSL_FILETYPE_PEM) <= 0) {
336                 iossl_error();
337                 iolog_trigger(IOLOG_ERROR, "SSL: could not load server certificate (%s)", certfile);
338                 goto ssl_listen_err;
339         }
340         /* load keyfile */
341         if(SSL_CTX_use_PrivateKey_file(sslnode->sslContext, keyfile, SSL_FILETYPE_PEM) <= 0) {
342                 iossl_error();
343                 iolog_trigger(IOLOG_ERROR, "SSL: could not load server keyfile (%s)", keyfile);
344                 goto ssl_listen_err;
345         }
346         /* check certificate and keyfile */
347         if(!SSL_CTX_check_private_key(sslnode->sslContext)) {
348                 iossl_error();
349                 iolog_trigger(IOLOG_ERROR, "SSL: server certificate (%s) and keyfile (%s) doesn't match!", certfile, keyfile);
350                 goto ssl_listen_err;
351         }
352         iosock->sslnode = sslnode;
353         iosock->socket_flags |= IOSOCKETFLAG_SSL_ESTABLISHED;
354         return;
355 ssl_listen_err:
356         free(sslnode);
357         iosock->sslnode = NULL;
358         iosocket_events_callback(iosock, 0, 0);
359 }
360
361 void iossl_client_accepted(struct _IOSocket *iosock, struct _IOSocket *new_iosock) {
362         struct IOSSLDescriptor *sslnode = malloc(sizeof(*sslnode));
363         sslnode->sslHandle = SSL_new(iosock->sslnode->sslContext);
364         if(!sslnode->sslHandle) {
365                 iossl_error();
366                 iolog_trigger(IOLOG_ERROR, "SSL: could not create client SSL Handle");
367                 goto ssl_accept_err;
368         }
369         if(!SSL_set_fd(sslnode->sslHandle, new_iosock->fd)) {
370                 iossl_error();
371                 iolog_trigger(IOLOG_ERROR, "SSL: could not set client fd in SSL Handle");
372                 goto ssl_accept_err;
373         }
374         new_iosock->sslnode = sslnode;
375         new_iosock->socket_flags |= IOSOCKETFLAG_SSL_HANDSHAKE;
376         return;
377 ssl_accept_err:
378         free(sslnode);
379         iosock->sslnode = NULL;
380         iosocket_events_callback(new_iosock, 0, 0);
381 }
382
383 void iossl_server_handshake(struct _IOSocket *iosock) {
384         // Perform an SSL handshake.
385         int ret = SSL_accept(iosock->sslnode->sslHandle);
386         iosock->socket_flags &= ~IOSOCKETFLAG_SSL_WANTWRITE;
387         switch(SSL_get_error(iosock->sslnode->sslHandle, ret)) {
388                 case SSL_ERROR_NONE:
389                         iolog_trigger(IOLOG_DEBUG, "SSL handshake for fd %d successful", iosock->fd);
390                         iosock->socket_flags |= IOSOCKETFLAG_SSL_ESTABLISHED;
391                         iosocket_events_callback(iosock, 0, 0); //perform IOEVENT_CONNECTED event
392                         break;
393                 case SSL_ERROR_WANT_READ:
394                         iolog_trigger(IOLOG_DEBUG, "SSL_do_handshake for fd %d returned SSL_ERROR_WANT_READ", iosock->fd);
395                         break;
396                 case SSL_ERROR_WANT_WRITE:
397                         iosock->socket_flags |= IOSOCKETFLAG_SSL_WANTWRITE;
398                         iolog_trigger(IOLOG_DEBUG, "SSL_do_handshake for fd %d returned SSL_ERROR_WANT_WRITE", iosock->fd);
399                         break;
400                 default:
401                         iolog_trigger(IOLOG_ERROR, "SSL_do_handshake for fd %d failed with ", iosock->fd);
402                         iosocket_events_callback(iosock, 0, 0);
403                         break;
404         }
405 }
406
407 void iossl_disconnect(struct _IOSocket *iosock) {
408         if(!iosock->sslnode) return;
409         SSL_shutdown(iosock->sslnode->sslHandle);
410         SSL_free(iosock->sslnode->sslHandle);
411         if(!(iosock->socket_flags & IOSOCKETFLAG_INCOMING))
412                 SSL_CTX_free(iosock->sslnode->sslContext);
413         free(iosock->sslnode);
414         iosock->sslnode = NULL;
415         iosock->socket_flags &= ~IOSOCKETFLAG_SSLSOCKET;
416 }
417
418 int iossl_read(struct _IOSocket *iosock, char *buffer, int len) {
419         if((iosock->socket_flags & (IOSOCKETFLAG_SSLSOCKET | IOSOCKETFLAG_SSL_ESTABLISHED)) != (IOSOCKETFLAG_SSLSOCKET | IOSOCKETFLAG_SSL_ESTABLISHED))
420                 return 0;
421         int ret = SSL_read(iosock->sslnode->sslHandle, buffer, len);
422         iosock->socket_flags &= ~(IOSOCKETFLAG_SSL_WANTWRITE | IOSOCKETFLAG_SSL_READHS);
423         int err = SSL_get_error(iosock->sslnode->sslHandle, ret);
424         switch(err) {
425                 case SSL_ERROR_NONE:
426                 case SSL_ERROR_ZERO_RETURN:
427                         break;
428                 case SSL_ERROR_WANT_READ:
429                         iosock->socket_flags |= IOSOCKETFLAG_SSL_READHS;
430                         iolog_trigger(IOLOG_DEBUG, "SSL_read for fd %d returned SSL_ERROR_WANT_READ", iosock->fd);
431                         errno = EAGAIN;
432                         ret = -1;
433                         break;
434                 case SSL_ERROR_WANT_WRITE:
435                         iosock->socket_flags |= IOSOCKETFLAG_SSL_WANTWRITE | IOSOCKETFLAG_SSL_READHS;
436                         iolog_trigger(IOLOG_DEBUG, "SSL_read for fd %d returned SSL_ERROR_WANT_WRITE", iosock->fd);
437                         errno = EAGAIN;
438                         ret = -1;
439                         break;
440                 case SSL_ERROR_SYSCALL:
441                         iolog_trigger(IOLOG_ERROR, "SSL_read for fd %d failed with SSL_ERROR_SYSCALL: %d", iosock->fd, errno);
442                         ret = -1;
443                         break;
444                 default:
445                         iolog_trigger(IOLOG_ERROR, "SSL_read for fd %d failed with %d", iosock->fd, err);
446                         ret = -1;
447                         break;
448         }
449         return ret;
450 }
451
452 int iossl_write(struct _IOSocket *iosock, char *buffer, int len) {
453         if((iosock->socket_flags & (IOSOCKETFLAG_SSLSOCKET | IOSOCKETFLAG_SSL_ESTABLISHED)) != (IOSOCKETFLAG_SSLSOCKET | IOSOCKETFLAG_SSL_ESTABLISHED))
454                 return 0;
455         int ret = SSL_write(iosock->sslnode->sslHandle, buffer, len);
456         iosock->socket_flags &= ~(IOSOCKETFLAG_SSL_WANTWRITE | IOSOCKETFLAG_SSL_WRITEHS);
457         switch(SSL_get_error(iosock->sslnode->sslHandle, ret)) {
458                 case SSL_ERROR_NONE:
459                 case SSL_ERROR_ZERO_RETURN:
460                         break;
461                 case SSL_ERROR_WANT_READ:
462                         iosock->socket_flags |= IOSOCKETFLAG_SSL_WRITEHS;
463                         iolog_trigger(IOLOG_DEBUG, "SSL_write for fd %d returned SSL_ERROR_WANT_READ", iosock->fd);
464                         errno = EAGAIN;
465                         ret = -1;
466                         break;
467                 case SSL_ERROR_WANT_WRITE:
468                         iosock->socket_flags |= IOSOCKETFLAG_SSL_WANTWRITE | IOSOCKETFLAG_SSL_WRITEHS;
469                         iolog_trigger(IOLOG_DEBUG, "SSL_write for fd %d returned SSL_ERROR_WANT_WRITE", iosock->fd);
470                         errno = EAGAIN;
471                         ret = -1;
472                         break;
473                 default:
474                         iolog_trigger(IOLOG_ERROR, "SSL_write for fd %d failed with ", iosock->fd);
475                         ret = -1;
476                         break;
477         }
478         return ret;
479 }
480
481 #else
482 // NULL-backend
483
484 void iossl_init() {};
485 void iossl_connect(struct _IOSocket *iosock) {};
486 void iossl_listen(struct _IOSocket *iosock, const char *certfile, const char *keyfile) {};
487 void iossl_client_handshake(struct _IOSocket *iosock) {};
488 void iossl_client_accepted(struct _IOSocket *iosock, struct _IOSocket *client_iofd) {};
489 void iossl_server_handshake(struct _IOSocket *iosock) {};
490 void iossl_disconnect(struct _IOSocket *iosock) {};
491 int iossl_read(struct _IOSocket *iosock, char *buffer, int len) { return 0; };
492 int iossl_write(struct _IOSocket *iosock, char *buffer, int len) { return 0; };
493 #endif