fixed game_uno +2/+4 timeout handling
[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
20 void iohandler_ssl_init() {
21 #ifdef HAVE_SSL
22     SSL_library_init();
23     OpenSSL_add_all_algorithms(); /* load & register all cryptos, etc. */
24     SSL_load_error_strings();
25 #endif
26 }
27
28 static void iohandler_ssl_error() {
29     unsigned long e;
30     while((e = ERR_get_error())) {
31         iohandler_log(IOLOG_ERROR, "SSLv23 ERROR %lu: %s", e, ERR_error_string(e, NULL));
32     }
33 }
34
35 void iohandler_ssl_connect(struct IODescriptor *iofd) {
36 #ifdef HAVE_SSL
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");
44         goto ssl_connect_err;
45     }
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");
50         goto ssl_connect_err;
51     }
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");
55         goto ssl_connect_err;
56     }
57     SSL_set_connect_state(sslnode->sslHandle);
58     iofd->sslnode = sslnode;
59     iohandler_ssl_client_handshake(iofd);
60     return;
61 ssl_connect_err:
62     free(sslnode);
63     iohandler_events(iofd, 0, 0);
64 #endif    
65 }
66
67 void iohandler_ssl_listen(struct IODescriptor *iofd, const char *certfile, const char *keyfile) {
68 #ifdef HAVE_SSL
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");
74         goto ssl_listen_err;
75     }
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);
80         goto ssl_listen_err;
81     }
82     /* load keyfile */
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);
86         goto ssl_listen_err;
87     }
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);
92         goto ssl_listen_err;
93     }
94     iofd->sslnode = sslnode;
95     return;
96 ssl_listen_err:
97     free(sslnode);
98     iofd->sslnode = NULL;
99     iohandler_events(iofd, 0, 0);
100 #endif    
101 }
102
103 void iohandler_ssl_client_handshake(struct IODescriptor *iofd) {
104 #ifdef HAVE_SSL
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)) {
110         case SSL_ERROR_NONE:
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
115             break;
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);
119             break;
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);
123             break;
124         default:
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);
127             break;
128     }
129 #endif
130 }
131
132 void iohandler_ssl_client_accepted(struct IODescriptor *iofd, struct IODescriptor *client_iofd) {
133 #ifdef HAVE_SSL
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");
139         goto ssl_accept_err;
140     }
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");
144         goto ssl_accept_err;
145     }
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;
152     return;
153 ssl_accept_err:
154     iohandler_close(client_iofd);
155     free(sslnode);
156 #endif
157 }
158
159 void iohandler_ssl_server_handshake(struct IODescriptor *iofd) {
160 #ifdef HAVE_SSL
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)) {
166         case SSL_ERROR_NONE:
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
171             break;
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);
175             break;
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);
179             break;
180         default:
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);
183             break;
184     }
185 #endif
186 }
187
188 void iohandler_ssl_disconnect(struct IODescriptor *iofd) {
189 #ifdef HAVE_SSL
190     if(!iofd->sslnode) return;
191     SSL_shutdown(iofd->sslnode->sslHandle);
192     SSL_free(iofd->sslnode->sslHandle);
193     SSL_CTX_free(iofd->sslnode->sslContext);
194     free(iofd->sslnode);
195     iofd->sslnode = NULL;
196     iofd->ssl_active = 0;
197 #endif
198 }
199
200 int iohandler_ssl_read(struct IODescriptor *iofd, char *buffer, int len) {
201 #ifdef HAVE_SSL
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)) {
208         case SSL_ERROR_NONE:
209         case SSL_ERROR_ZERO_RETURN:
210             if(update)
211                 iohandler_update(iofd);
212             return ret;
213             break;
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);
218             errno = EAGAIN;
219             return -1;
220             break;
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);
225             errno = EAGAIN;
226             return -1;
227             break;
228         default:
229             iohandler_log(IOLOG_ERROR, "SSL_read for %s (fd: %d) failed with ", iohandler_iotype_name(iofd->type), iofd->fd);
230             return -1;
231             break;
232     }
233 #endif
234     return 0;
235 }
236
237 int iohandler_ssl_write(struct IODescriptor *iofd, char *buffer, int len) {
238 #ifdef HAVE_SSL
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)) {
245         case SSL_ERROR_NONE:
246         case SSL_ERROR_ZERO_RETURN:
247             if(update)
248                 iohandler_update(iofd);
249             return ret;
250             break;
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);
255             errno = EAGAIN;
256             return -1;
257             break;
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);
262             errno = EAGAIN;
263             return -1;
264             break;
265         default:
266             iohandler_log(IOLOG_ERROR, "SSL_write for %s (fd: %d) failed with ", iohandler_iotype_name(iofd->type), iofd->fd);
267             return -1;
268             break;
269     }
270 #endif
271     return 0;
272 }