Added SILC Thread Queue API
[crypto.git] / apps / irssi / src / core / network-openssl.c
1 /*
2  network-ssl.c : SSL support
3
4     Copyright (C) 2002 vjt
5
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21 #include "module.h"
22 #include "network.h"
23 #include "misc.h"
24
25 #ifdef HAVE_OPENSSL
26
27 #include <openssl/crypto.h>
28 #include <openssl/x509.h>
29 #include <openssl/pem.h>
30 #include <openssl/ssl.h>
31 #include <openssl/err.h>
32
33 /* ssl i/o channel object */
34 typedef struct
35 {
36         GIOChannel pad;
37         gint fd;
38         GIOChannel *giochan;
39         SSL *ssl;
40         SSL_CTX *ctx;
41         unsigned int got_cert:1;
42         unsigned int verify:1;
43 } GIOSSLChannel;
44         
45 static SSL_CTX *ssl_ctx = NULL;
46
47 static void irssi_ssl_free(GIOChannel *handle)
48 {
49         GIOSSLChannel *chan = (GIOSSLChannel *)handle;
50         g_io_channel_unref(chan->giochan);
51         SSL_free(chan->ssl);
52         if (chan->ctx != ssl_ctx)
53                 SSL_CTX_free(chan->ctx);
54         g_free(chan);
55 }
56
57 static gboolean irssi_ssl_verify(SSL *ssl, SSL_CTX *ctx, X509 *cert)
58 {
59         if (SSL_get_verify_result(ssl) != X509_V_OK) {
60                 unsigned char md[EVP_MAX_MD_SIZE];
61                 unsigned int n;
62                 char *str;
63
64                 g_warning("Could not verify SSL servers certificate:");
65                 if ((str = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0)) == NULL)
66                         g_warning("  Could not get subject-name from peer certificate");
67                 else {
68                         g_warning("  Subject : %s", str);
69                         free(str);
70                 }
71                 if ((str = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0)) == NULL)
72                         g_warning("  Could not get issuer-name from peer certificate");
73                 else {
74                         g_warning("  Issuer  : %s", str);
75                         free(str);
76                 }
77                 if (! X509_digest(cert, EVP_md5(), md, &n))
78                         g_warning("  Could not get fingerprint from peer certificate");
79                 else {
80                         char hex[] = "0123456789ABCDEF";
81                         char fp[EVP_MAX_MD_SIZE*3];
82                         if (n < sizeof(fp)) {
83                                 unsigned int i;
84                                 for (i = 0; i < n; i++) {
85                                         fp[i*3+0] = hex[(md[i] >> 4) & 0xF];
86                                         fp[i*3+1] = hex[(md[i] >> 0) & 0xF];
87                                         fp[i*3+2] = i == n - 1 ? '\0' : ':';
88                                 }
89                                 g_warning("  MD5 Fingerprint : %s", fp);
90                         }
91                 }
92                 return FALSE;
93         }
94         return TRUE;
95 }
96
97
98 #if GLIB_MAJOR_VERSION < 2
99
100 static GIOError ssl_errno(gint e)
101 {
102         switch(e)
103         {
104                 case EINVAL:
105                         return G_IO_ERROR_INVAL;
106                 case EINTR:
107                 case EAGAIN:
108                         return G_IO_ERROR_AGAIN;
109                 default:
110                         return G_IO_ERROR_INVAL;
111         }
112         /*UNREACH*/
113         return G_IO_ERROR_INVAL;
114 }
115
116 static GIOError irssi_ssl_cert_step(GIOSSLChannel *chan)
117 {
118         X509 *cert;
119         gint err;
120         switch(err = SSL_do_handshake(chan->ssl))
121         {
122                 case 1:
123                         if(!(cert = SSL_get_peer_certificate(chan->ssl)))
124                         {
125                                 g_warning("SSL server supplied no certificate");
126                                 return G_IO_ERROR_INVAL;
127                         }
128                         if (chan->verify && ! irssi_ssl_verify(chan->ssl, chan->ctx, cert)) {
129                                 X509_free(cert);
130                                 return G_IO_ERROR_INVAL;
131                         }
132                         X509_free(cert);
133                         return G_IO_ERROR_NONE;
134                 default:
135                         if(SSL_get_error(chan->ssl, err) == SSL_ERROR_WANT_READ)
136                                 return G_IO_ERROR_AGAIN;
137                         return ssl_errno(errno);
138         }
139         /*UNREACH*/
140         return G_IO_ERROR_INVAL;
141 }
142
143 static GIOError irssi_ssl_read(GIOChannel *handle, gchar *buf, guint len, guint *ret)
144 {
145         GIOSSLChannel *chan = (GIOSSLChannel *)handle;
146         gint err;
147         
148         if(! chan->got_cert)
149         {
150                 gint cert_err = irssi_ssl_cert_step(chan);
151                 if(cert_err != G_IO_ERROR_NONE)
152                         return cert_err;
153         }
154         
155         err = SSL_read(chan->ssl, buf, len);
156         if(err < 0)
157         {
158                 *ret = 0;
159                 if(SSL_get_error(chan->ssl, err) == SSL_ERROR_WANT_READ)
160                         return G_IO_ERROR_AGAIN;
161                 return ssl_errno(errno);
162         }
163         else
164         {
165                 *ret = err;
166                 return G_IO_ERROR_NONE;
167         }
168         /*UNREACH*/
169         return -1;
170 }
171
172 static GIOError irssi_ssl_write(GIOChannel *handle, gchar *buf, guint len, guint *ret)
173 {
174         GIOSSLChannel *chan = (GIOSSLChannel *)handle;
175         gint err;
176
177         if(chan->got_cert)
178         {
179                 gint cert_err = irssi_ssl_cert_step(chan);
180                 if(cert_err != G_IO_ERROR_NONE)
181                         return cert_err;
182         }
183         
184
185         err = SSL_write(chan->ssl, (const char *)buf, len);
186         if(err < 0)
187         {
188                 *ret = 0;
189                 if(SSL_get_error(chan->ssl, err) == SSL_ERROR_WANT_READ)
190                         return G_IO_ERROR_AGAIN;
191                 return ssl_errno(errno);
192         }
193         else
194         {
195                 *ret = err;
196                 return G_IO_ERROR_NONE;
197         }
198         /*UNREACH*/
199         return G_IO_ERROR_INVAL;
200 }
201
202 static GIOError irssi_ssl_seek(GIOChannel *handle, gint offset, GSeekType type)
203 {
204         GIOSSLChannel *chan = (GIOSSLChannel *)handle;
205         GIOError e;
206         e = g_io_channel_seek(chan->giochan, offset, type);
207         return (e == G_IO_ERROR_NONE) ? G_IO_ERROR_NONE : G_IO_ERROR_INVAL;
208 }
209
210 static void irssi_ssl_close(GIOChannel *handle)
211 {
212         GIOSSLChannel *chan = (GIOSSLChannel *)handle;
213         g_io_channel_close(chan->giochan);
214 }
215
216 static guint irssi_ssl_create_watch(GIOChannel *handle, gint priority, GIOCondition cond,
217                              GIOFunc func, gpointer data, GDestroyNotify notify)
218 {
219         GIOSSLChannel *chan = (GIOSSLChannel *)handle;
220
221         return chan->giochan->funcs->io_add_watch(handle, priority, cond, func, data, notify);
222 }
223
224 /* ssl function pointers */
225 static GIOFuncs irssi_ssl_channel_funcs =
226 {
227         irssi_ssl_read,
228         irssi_ssl_write,
229         irssi_ssl_seek,
230         irssi_ssl_close,
231         irssi_ssl_create_watch,
232         irssi_ssl_free
233 };
234
235 #else /* GLIB_MAJOR_VERSION < 2 */
236
237 static GIOStatus ssl_errno(gint e)
238 {
239         switch(e)
240         {
241                 case EINVAL:
242                         return G_IO_STATUS_ERROR;
243                 case EINTR:
244                 case EAGAIN:
245                         return G_IO_STATUS_AGAIN;
246                 default:
247                         return G_IO_STATUS_ERROR;
248         }
249         /*UNREACH*/
250         return G_IO_STATUS_ERROR;
251 }
252
253 static GIOStatus irssi_ssl_cert_step(GIOSSLChannel *chan)
254 {
255         X509 *cert;
256         gint err;
257         switch(err = SSL_do_handshake(chan->ssl))
258         {
259                 case 1:
260                         if(!(cert = SSL_get_peer_certificate(chan->ssl)))
261                         {
262                                 g_warning("SSL server supplied no certificate");
263                                 return G_IO_STATUS_ERROR;
264                         }
265                         if (chan->verify && ! irssi_ssl_verify(chan->ssl, chan->ctx, cert)) {
266                                 X509_free(cert);
267                                 return G_IO_STATUS_ERROR;
268                         }
269                         X509_free(cert);
270                         return G_IO_STATUS_NORMAL;
271                 default:
272                         if(SSL_get_error(chan->ssl, err) == SSL_ERROR_WANT_READ)
273                                 return G_IO_STATUS_AGAIN;
274                         return ssl_errno(errno);
275         }
276         /*UNREACH*/
277         return G_IO_STATUS_ERROR;
278 }
279
280 static GIOStatus irssi_ssl_read(GIOChannel *handle, gchar *buf, gsize len, gsize *ret, GError **gerr)
281 {
282         GIOSSLChannel *chan = (GIOSSLChannel *)handle;
283         gint err;
284         
285         if(! chan->got_cert)
286         {
287                 gint cert_err = irssi_ssl_cert_step(chan);
288                 if(cert_err != G_IO_STATUS_NORMAL)
289                         return cert_err;
290         }
291         
292         err = SSL_read(chan->ssl, buf, len);
293         if(err < 0)
294         {
295                 *ret = 0;
296                 if(SSL_get_error(chan->ssl, err) == SSL_ERROR_WANT_READ)
297                         return G_IO_STATUS_AGAIN;
298                 return ssl_errno(errno);
299         }
300         else
301         {
302                 *ret = err;
303                 return G_IO_STATUS_NORMAL;
304         }
305         /*UNREACH*/
306         return G_IO_STATUS_ERROR;
307 }
308
309 static GIOStatus irssi_ssl_write(GIOChannel *handle, const gchar *buf, gsize len, gsize *ret, GError **gerr)
310 {
311         GIOSSLChannel *chan = (GIOSSLChannel *)handle;
312         gint err;
313
314         if(! chan->got_cert)
315         {
316                 gint cert_err = irssi_ssl_cert_step(chan);
317                 if(cert_err != G_IO_STATUS_NORMAL)
318                         return cert_err;
319         }
320
321         err = SSL_write(chan->ssl, (const char *)buf, len);
322         if(err < 0)
323         {
324                 *ret = 0;
325                 if(SSL_get_error(chan->ssl, err) == SSL_ERROR_WANT_READ)
326                         return G_IO_STATUS_AGAIN;
327                 return ssl_errno(errno);
328         }
329         else
330         {
331                 *ret = err;
332                 return G_IO_STATUS_NORMAL;
333         }
334         /*UNREACH*/
335         return G_IO_STATUS_ERROR;
336 }
337
338 static GIOStatus irssi_ssl_seek(GIOChannel *handle, gint64 offset, GSeekType type, GError **gerr)
339 {
340         GIOSSLChannel *chan = (GIOSSLChannel *)handle;
341         GIOError e;
342         e = g_io_channel_seek(chan->giochan, offset, type);
343         return (e == G_IO_ERROR_NONE) ? G_IO_STATUS_NORMAL : G_IO_STATUS_ERROR;
344 }
345
346 static GIOStatus irssi_ssl_close(GIOChannel *handle, GError **gerr)
347 {
348         GIOSSLChannel *chan = (GIOSSLChannel *)handle;
349         g_io_channel_close(chan->giochan);
350
351         return G_IO_STATUS_NORMAL;
352 }
353
354 static GSource *irssi_ssl_create_watch(GIOChannel *handle, GIOCondition cond)
355 {
356         GIOSSLChannel *chan = (GIOSSLChannel *)handle;
357
358         return chan->giochan->funcs->io_create_watch(handle, cond);
359 }
360
361 static GIOStatus irssi_ssl_set_flags(GIOChannel *handle, GIOFlags flags, GError **gerr)
362 {
363     GIOSSLChannel *chan = (GIOSSLChannel *)handle;
364
365     return chan->giochan->funcs->io_set_flags(handle, flags, gerr);
366 }
367
368 static GIOFlags irssi_ssl_get_flags(GIOChannel *handle)
369 {
370     GIOSSLChannel *chan = (GIOSSLChannel *)handle;
371
372     return chan->giochan->funcs->io_get_flags(handle);
373 }
374
375 static GIOFuncs irssi_ssl_channel_funcs = {
376     irssi_ssl_read,
377     irssi_ssl_write,
378     irssi_ssl_seek,
379     irssi_ssl_close,
380     irssi_ssl_create_watch,
381     irssi_ssl_free,
382     irssi_ssl_set_flags,
383     irssi_ssl_get_flags
384 };
385
386 #endif
387
388 static gboolean irssi_ssl_init(void)
389 {
390         SSL_library_init();
391         SSL_load_error_strings();
392         
393         ssl_ctx = SSL_CTX_new(SSLv23_client_method());
394         if(!ssl_ctx)
395         {
396                 g_error("Initialization of the SSL library failed");
397                 return FALSE;
398         }
399
400         return TRUE;
401
402 }
403
404 static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle, const char *mycert, const char *mypkey, const char *cafile, const char *capath, gboolean verify)
405 {
406         GIOSSLChannel *chan;
407         GIOChannel *gchan;
408         int err, fd;
409         SSL *ssl;
410         X509 *cert = NULL;
411         SSL_CTX *ctx = NULL;
412
413         g_return_val_if_fail(handle != NULL, NULL);
414         
415         if(!ssl_ctx && !irssi_ssl_init())
416                 return NULL;
417
418         if(!(fd = g_io_channel_unix_get_fd(handle)))
419                 return NULL;
420
421         if (mycert && *mycert) {        
422                 char *scert = NULL, *spkey = NULL;
423                 if ((ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) {
424                         g_error("Could not allocate memory for SSL context");
425                         return NULL;
426                 }
427                 scert = convert_home(mycert);
428                 if (mypkey && *mypkey)
429                         spkey = convert_home(mypkey);
430                 if (! SSL_CTX_use_certificate_file(ctx, scert, SSL_FILETYPE_PEM))
431                         g_warning("Loading of client certificate '%s' failed", mycert);
432                 else if (! SSL_CTX_use_PrivateKey_file(ctx, spkey ? spkey : scert, SSL_FILETYPE_PEM))
433                         g_warning("Loading of private key '%s' failed", mypkey ? mypkey : mycert);
434                 else if (! SSL_CTX_check_private_key(ctx))
435                         g_warning("Private key does not match the certificate");
436                 g_free(scert);
437                 g_free(spkey);
438         }
439
440         if ((cafile && *cafile) || (capath && *capath)) {
441                 char *scafile = NULL;
442                 char *scapath = NULL;
443                 if (! ctx && (ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) {
444                         g_error("Could not allocate memory for SSL context");
445                         return NULL;
446                 }
447                 if (cafile && *cafile)
448                         scafile = convert_home(cafile);
449                 if (capath && *capath)
450                         scapath = convert_home(capath);
451                 if (! SSL_CTX_load_verify_locations(ctx, scafile, scapath)) {
452                         g_warning("Could not load CA list for verifying SSL server certificate");
453                         g_free(scafile);
454                         g_free(scapath);
455                         SSL_CTX_free(ctx);
456                         return NULL;
457                 }
458                 g_free(scafile);
459                 g_free(scapath);
460                 verify = TRUE;
461         }
462
463         if (ctx == NULL)
464                 ctx = ssl_ctx;
465         
466         if(!(ssl = SSL_new(ctx)))
467         {
468                 g_warning("Failed to allocate SSL structure");
469                 return NULL;
470         }
471
472         if(!(err = SSL_set_fd(ssl, fd)))
473         {
474                 g_warning("Failed to associate socket to SSL stream");
475                 SSL_free(ssl);
476                 if (ctx != ssl_ctx)
477                         SSL_CTX_free(ctx);
478                 return NULL;
479         }
480
481         if((err = SSL_connect(ssl)) <= 0)
482         {
483                 switch(err = SSL_get_error(ssl, err))
484                 {
485                         case SSL_ERROR_SYSCALL:
486                                 if(errno == EINTR || errno == EAGAIN)
487                         case SSL_ERROR_WANT_READ:
488                         case SSL_ERROR_WANT_WRITE:
489                                         break;
490                         default:
491                                         SSL_free(ssl);
492                                         if (ctx != ssl_ctx)
493                                                 SSL_CTX_free(ctx);
494                                         return NULL;
495                 }
496         }
497         else if(!(cert = SSL_get_peer_certificate(ssl)))
498         {
499                 g_warning("SSL server supplied no certificate");
500                 if (ctx != ssl_ctx)
501                         SSL_CTX_free(ctx);
502                 SSL_free(ssl);
503                 return NULL;
504         }
505         else
506         {
507                 if (verify && ! irssi_ssl_verify(ssl, ctx, cert)) {
508                         SSL_free(ssl);
509                         if (ctx != ssl_ctx)
510                                 SSL_CTX_free(ctx);
511                         return NULL;
512                 }
513                 X509_free(cert);
514         }
515
516         chan = g_new0(GIOSSLChannel, 1);
517         chan->fd = fd;
518         chan->giochan = handle;
519         chan->ssl = ssl;
520         chan->ctx = ctx;
521         chan->got_cert = cert != NULL;
522         chan->verify = verify;
523
524         gchan = (GIOChannel *)chan;
525         gchan->funcs = &irssi_ssl_channel_funcs;
526         g_io_channel_init(gchan);
527         
528         return gchan;
529 }
530
531 GIOChannel *net_connect_ip_ssl(IPADDR *ip, int port, IPADDR *my_ip, const char *cert, const char *pkey, const char *cafile, const char *capath, gboolean verify)
532 {
533         GIOChannel *handle, *ssl_handle;
534
535         handle = net_connect_ip(ip, port, my_ip);
536         ssl_handle  = irssi_ssl_get_iochannel(handle, cert, pkey, cafile, capath, verify);
537         if (ssl_handle == NULL)
538                 g_io_channel_unref(handle);
539         return ssl_handle;
540 }
541
542 #else /* HAVE_OPENSSL */
543
544 GIOChannel *net_connect_ip_ssl(IPADDR *ip, int port, IPADDR *my_ip, const char *cert, const char *pkey, const char *cafile, const char *capath, gboolean verify)
545 {
546         g_warning("Connection failed: SSL support not enabled in this build.");
547         errno = ENOSYS;
548         return NULL;
549 }
550
551 #endif /* ! HAVE_OPENSSL */