1 /* IOSSLBackend.c - IOMultiplexer
2 * Copyright (C) 2014 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 #define _IOHandler_internals
18 #include "IOInternal.h"
19 #include "IOHandler.h"
21 #include "IOSockets.h"
22 #include "IOSSLBackend.h"
24 #ifdef HAVE_OPENSSL_SSL_H
30 OpenSSL_add_all_algorithms(); /* load & register all cryptos, etc. */
31 SSL_load_error_strings();
34 static void iossl_error() {
36 while((e = ERR_get_error())) {
37 iolog_trigger(IOLOG_ERROR, "SSLv23 ERROR %lu: %s", e, ERR_error_string(e, NULL));
42 void iossl_connect(struct _IOSocket *iosock) {
43 struct IOSSLDescriptor *sslnode = malloc(sizeof(*sslnode));
44 sslnode->sslContext = SSL_CTX_new(SSLv23_client_method());
45 if(!sslnode->sslContext) {
47 iolog_trigger(IOLOG_ERROR, "SSL: could not create client SSL CTX");
50 sslnode->sslHandle = SSL_new(sslnode->sslContext);
51 if(!sslnode->sslHandle) {
53 iolog_trigger(IOLOG_ERROR, "SSL: could not create client SSL Handle");
56 if(!SSL_set_fd(sslnode->sslHandle, iosock->fd)) {
58 iolog_trigger(IOLOG_ERROR, "SSL: could not set client fd in SSL Handle");
61 SSL_set_connect_state(sslnode->sslHandle);
62 iosock->sslnode = sslnode;
63 iosock->socket_flags |= IOSOCKETFLAG_SSL_HANDSHAKE;
64 iossl_client_handshake(iosock);
68 iosocket_events_callback(iosock, 0, 0);
71 void iossl_client_handshake(struct _IOSocket *iosock) {
72 // Perform an SSL handshake.
73 int ret = SSL_do_handshake(iosock->sslnode->sslHandle);
74 iosock->socket_flags &= ~IOSOCKETFLAG_SSL_WANTWRITE;
75 switch(SSL_get_error(iosock->sslnode->sslHandle, ret)) {
77 iolog_trigger(IOLOG_DEBUG, "SSL handshake for fd %d successful", iosock->fd);
78 iosock->socket_flags |= IOSOCKETFLAG_SSL_ESTABLISHED;
79 iosocket_events_callback(iosock, 0, 0); //perform IOEVENT_CONNECTED event
81 case SSL_ERROR_WANT_READ:
82 iolog_trigger(IOLOG_DEBUG, "SSL_do_handshake for fd %d returned SSL_ERROR_WANT_READ", iosock->fd);
84 case SSL_ERROR_WANT_WRITE:
85 iosock->socket_flags |= IOSOCKETFLAG_SSL_WANTWRITE;
86 iolog_trigger(IOLOG_DEBUG, "SSL_do_handshake for fd %d returned SSL_ERROR_WANT_WRITE", iosock->fd);
89 iolog_trigger(IOLOG_ERROR, "SSL_do_handshake for fd %d failed with ", iosock->fd);
90 iosocket_events_callback(iosock, 0, 0);
97 void iossl_listen(struct _IOSocket *iosock, const char *certfile, const char *keyfile) {
98 struct IOSSLDescriptor *sslnode = malloc(sizeof(*sslnode));
99 sslnode->sslContext = SSL_CTX_new(SSLv23_server_method());
100 if(!sslnode->sslContext) {
102 iolog_trigger(IOLOG_ERROR, "SSL: could not create server SSL CTX");
105 /* load certificate */
106 if(SSL_CTX_use_certificate_file(sslnode->sslContext, certfile, SSL_FILETYPE_PEM) <= 0) {
108 iolog_trigger(IOLOG_ERROR, "SSL: could not load server certificate (%s)", certfile);
112 if(SSL_CTX_use_PrivateKey_file(sslnode->sslContext, keyfile, SSL_FILETYPE_PEM) <= 0) {
114 iolog_trigger(IOLOG_ERROR, "SSL: could not load server keyfile (%s)", keyfile);
117 /* check certificate and keyfile */
118 if(!SSL_CTX_check_private_key(sslnode->sslContext)) {
120 iolog_trigger(IOLOG_ERROR, "SSL: server certificate (%s) and keyfile (%s) doesn't match!", certfile, keyfile);
123 iosock->sslnode = sslnode;
\r
124 iosock->socket_flags |= IOSOCKETFLAG_SSL_ESTABLISHED;
128 iosock->sslnode = NULL;
129 iosocket_events_callback(iosock, 0, 0);
132 void iossl_client_accepted(struct _IOSocket *iosock, struct _IOSocket *new_iosock) {
133 struct IOSSLDescriptor *sslnode = malloc(sizeof(*sslnode));
134 sslnode->sslHandle = SSL_new(sslnode->sslContext);
135 if(!sslnode->sslHandle) {
137 iolog_trigger(IOLOG_ERROR, "SSL: could not create client SSL Handle");
140 if(!SSL_set_fd(sslnode->sslHandle, new_iosock->fd)) {
142 iolog_trigger(IOLOG_ERROR, "SSL: could not set client fd in SSL Handle");
145 new_iosock->sslnode = sslnode;
\r
146 new_iosock->socket_flags |= IOSOCKETFLAG_SSL_HANDSHAKE;
150 iosock->sslnode = NULL;
\r
151 iosocket_events_callback(new_iosock, 0, 0);
154 void iossl_server_handshake(struct _IOSocket *iosock) {
155 // Perform an SSL handshake.
156 int ret = SSL_accept(iosock->sslnode->sslHandle);
157 iosock->socket_flags &= ~IOSOCKETFLAG_SSL_WANTWRITE;
158 switch(SSL_get_error(iosock->sslnode->sslHandle, ret)) {
160 iolog_trigger(IOLOG_DEBUG, "SSL handshake for fd %d successful", iosock->fd);
161 iosock->socket_flags |= IOSOCKETFLAG_SSL_ESTABLISHED;
162 iosocket_events_callback(iosock, 0, 0); //perform IOEVENT_CONNECTED event
164 case SSL_ERROR_WANT_READ:
165 iolog_trigger(IOLOG_DEBUG, "SSL_do_handshake for fd %d returned SSL_ERROR_WANT_READ", iosock->fd);
167 case SSL_ERROR_WANT_WRITE:
168 iosock->socket_flags |= IOSOCKETFLAG_SSL_WANTWRITE;
169 iolog_trigger(IOLOG_DEBUG, "SSL_do_handshake for fd %d returned SSL_ERROR_WANT_WRITE", iosock->fd);
172 iolog_trigger(IOLOG_ERROR, "SSL_do_handshake for fd %d failed with ", iosock->fd);
173 iosocket_events_callback(iosock, 0, 0);
178 void iossl_disconnect(struct _IOSocket *iosock) {
179 if(!iosock->sslnode) return;
180 SSL_shutdown(iosock->sslnode->sslHandle);
181 SSL_free(iosock->sslnode->sslHandle);
182 SSL_CTX_free(iosock->sslnode->sslContext);
183 free(iosock->sslnode);
184 iosock->sslnode = NULL;
185 iosock->socket_flags &= ~IOSOCKETFLAG_SSLSOCKET;
188 int iossl_read(struct _IOSocket *iosock, char *buffer, int len) {
189 if((iosock->socket_flags & (IOSOCKETFLAG_SSLSOCKET | IOSOCKETFLAG_SSL_ESTABLISHED)) != (IOSOCKETFLAG_SSLSOCKET | IOSOCKETFLAG_SSL_ESTABLISHED))
\r
191 int ret = SSL_read(iosock->sslnode->sslHandle, buffer, len);
192 iosock->socket_flags &= ~(IOSOCKETFLAG_SSL_WANTWRITE | IOSOCKETFLAG_SSL_READHS);
193 switch(SSL_get_error(iosock->sslnode->sslHandle, ret)) {
195 case SSL_ERROR_ZERO_RETURN:
197 case SSL_ERROR_WANT_READ:
\r
198 iosock->socket_flags |= IOSOCKETFLAG_SSL_READHS;
199 iolog_trigger(IOLOG_DEBUG, "SSL_read for fd %d returned SSL_ERROR_WANT_READ", iosock->fd);
203 case SSL_ERROR_WANT_WRITE:
204 iosock->socket_flags |= IOSOCKETFLAG_SSL_WANTWRITE | IOSOCKETFLAG_SSL_READHS;
205 iolog_trigger(IOLOG_DEBUG, "SSL_read for fd %d returned SSL_ERROR_WANT_WRITE", iosock->fd);
210 iolog_trigger(IOLOG_ERROR, "SSL_read for fd %d failed with ", iosock->fd);
217 int iossl_write(struct _IOSocket *iosock, char *buffer, int len) {
218 if((iosock->socket_flags & (IOSOCKETFLAG_SSLSOCKET | IOSOCKETFLAG_SSL_ESTABLISHED)) != (IOSOCKETFLAG_SSLSOCKET | IOSOCKETFLAG_SSL_ESTABLISHED))
\r
220 int ret = SSL_write(iosock->sslnode->sslHandle, buffer, len);
221 iosock->socket_flags &= ~(IOSOCKETFLAG_SSL_WANTWRITE | IOSOCKETFLAG_SSL_WRITEHS);
222 switch(SSL_get_error(iosock->sslnode->sslHandle, ret)) {
224 case SSL_ERROR_ZERO_RETURN:
226 case SSL_ERROR_WANT_READ:
227 iosock->socket_flags |= IOSOCKETFLAG_SSL_WRITEHS;
228 iolog_trigger(IOLOG_DEBUG, "SSL_write for fd %d returned SSL_ERROR_WANT_READ", iosock->fd);
232 case SSL_ERROR_WANT_WRITE:
233 iosock->socket_flags |= IOSOCKETFLAG_SSL_WANTWRITE | IOSOCKETFLAG_SSL_WRITEHS;
234 iolog_trigger(IOLOG_DEBUG, "SSL_write for fd %d returned SSL_ERROR_WANT_WRITE", iosock->fd);
239 iolog_trigger(IOLOG_ERROR, "SSL_write for fd %d failed with ", iosock->fd);
249 void iossl_init() {};
250 void iossl_connect(struct _IOSocket *iosock) {};
251 void iossl_listen(struct _IOSocket *iosock, const char *certfile, const char *keyfile) {};
252 void iossl_client_handshake(struct _IOSocket *iosock) {};
253 void iossl_client_accepted(struct _IOSocket *iosock, struct _IOSocket *client_iofd) {};
254 void iossl_server_handshake(struct _IOSocket *iosock) {};
255 void iossl_disconnect(struct _IOSocket *iosock) {};
256 int iossl_read(struct _IOSocket *iosock, char *buffer, int len) { return 0; };
257 int iossl_write(struct _IOSocket *iosock, char *buffer, int len) { return 0; };