Merge branch 'development'
[NeonServV5.git] / src / IOHandler_SSL.c
1 /* IOHandler_SSL.c - IOMultiplexer
2  * Copyright (C) 2012  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 #include "IOEngine.h"
18 #include "IOHandler_SSL.h"
19 #ifdef HAVE_SSL
20
21 void iohandler_ssl_init() {
22     SSL_library_init();
23     OpenSSL_add_all_algorithms(); /* load & register all cryptos, etc. */
24     SSL_load_error_strings();
25 }
26
27 static void iohandler_ssl_error() {
28     unsigned long e;
29     while((e = ERR_get_error())) {
30         iohandler_log(IOLOG_ERROR, "SSLv23 ERROR %lu: %s", e, ERR_error_string(e, NULL));
31     }
32 }
33
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");
42         goto ssl_connect_err;
43     }
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");
48         goto ssl_connect_err;
49     }
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");
53         goto ssl_connect_err;
54     }
55     SSL_set_connect_state(sslnode->sslHandle);
56     iofd->sslnode = sslnode;
57     iohandler_ssl_client_handshake(iofd);
58     return;
59 ssl_connect_err:
60     free(sslnode);
61     iohandler_events(iofd, 0, 0);
62 }
63
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");
70         goto ssl_listen_err;
71     }
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);
76         goto ssl_listen_err;
77     }
78     /* load keyfile */
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);
82         goto ssl_listen_err;
83     }
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);
88         goto ssl_listen_err;
89     }
90     iofd->sslnode = sslnode;
91     return;
92 ssl_listen_err:
93     free(sslnode);
94     iofd->sslnode = NULL;
95     iohandler_events(iofd, 0, 0);
96 }
97
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)) {
104         case SSL_ERROR_NONE:
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
109             break;
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);
113             break;
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);
117             break;
118         default:
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);
121             break;
122     }
123 }
124
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");
131         goto ssl_accept_err;
132     }
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");
136         goto ssl_accept_err;
137     }
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;
144     return;
145 ssl_accept_err:
146     iohandler_close(client_iofd);
147     free(sslnode);
148 }
149
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)) {
156         case SSL_ERROR_NONE:
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
161             break;
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);
165             break;
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);
169             break;
170         default:
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);
173             break;
174     }
175 }
176
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);
182     free(iofd->sslnode);
183     iofd->sslnode = NULL;
184     iofd->ssl_active = 0;
185 }
186
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)) {
194         case SSL_ERROR_NONE:
195         case SSL_ERROR_ZERO_RETURN:
196             if(update)
197                 iohandler_update(iofd);
198             return ret;
199             break;
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);
204             errno = EAGAIN;
205             return -1;
206             break;
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);
211             errno = EAGAIN;
212             return -1;
213             break;
214         default:
215             iohandler_log(IOLOG_ERROR, "SSL_read for %s (fd: %d) failed with ", iohandler_iotype_name(iofd->type), iofd->fd);
216             return -1;
217             break;
218     }
219 }
220
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)) {
228         case SSL_ERROR_NONE:
229         case SSL_ERROR_ZERO_RETURN:
230             if(update)
231                 iohandler_update(iofd);
232             return ret;
233             break;
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);
238             errno = EAGAIN;
239             return -1;
240             break;
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);
245             errno = EAGAIN;
246             return -1;
247             break;
248         default:
249             iohandler_log(IOLOG_ERROR, "SSL_write for %s (fd: %d) failed with ", iohandler_iotype_name(iofd->type), iofd->fd);
250             return -1;
251             break;
252     }
253 }
254
255 #else
256 // NULL-backend
257
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; };
267 #endif