]> arthur.barton.de Git - ngircd-alex.git/blob - src/ngircd/conn-ssl.c
Optionally validate certificates on TLS server links
[ngircd-alex.git] / src / ngircd / conn-ssl.c
1 /*
2  * ngIRCd -- The Next Generation IRC Daemon
3  * Copyright (c)2005-2008 Florian Westphal (fw@strlen.de).
4  * Copyright (c)2008-2014 Alexander Barton (alex@barton.de) and Contributors.
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  * Please read the file COPYING, README and AUTHORS for more information.
11  */
12
13 #include "portab.h"
14
15 /**
16  * @file
17  * SSL wrapper functions
18  */
19
20 #include "conf-ssl.h"
21
22 #ifdef SSL_SUPPORT
23
24 #include "io.h"
25 #include <assert.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <stdlib.h>
29 #include <errno.h>
30
31 #define CONN_MODULE
32 #include "conn.h"
33 #include "conf.h"
34 #include "conn-func.h"
35 #include "conn-ssl.h"
36 #include "log.h"
37
38 #include "defines.h"
39
40 extern struct SSLOptions Conf_SSLOptions;
41
42 #ifdef HAVE_LIBSSL
43 #include <openssl/err.h>
44 #include <openssl/rand.h>
45
46 static SSL_CTX * ssl_ctx;
47 static DH *dh_params;
48
49 static bool ConnSSL_LoadServerKey_openssl PARAMS(( SSL_CTX *c ));
50 static bool ConnSSL_SetVerifyProperties_openssl PARAMS(( SSL_CTX *c ));
51 #endif
52
53 #define MAX_CERT_CHAIN_LENGTH   10 /* XXX: do not hardcode */
54
55 #ifdef HAVE_LIBGNUTLS
56 #include <sys/types.h>
57 #include <sys/stat.h>
58 #include <fcntl.h>
59 #include <unistd.h>
60 #include <gnutls/x509.h>
61
62 #define DH_BITS 2048
63 #define DH_BITS_MIN 1024
64
65 #define MAX_HASH_SIZE   64      /* from gnutls-int.h */
66
67 gnutls_x509_crl_t *crl_list;
68 gnutls_x509_crt_t *ca_list;
69 size_t crl_list_size;
70 size_t ca_list_size;
71
72 static gnutls_certificate_credentials_t x509_cred;
73 static gnutls_dh_params_t dh_params;
74 static gnutls_priority_t priorities_cache;
75 static bool ConnSSL_LoadServerKey_gnutls PARAMS(( void ));
76 static bool ConnSSL_SetVerifyProperties_gnutls PARAMS(( void ));
77 #endif
78
79 #define SHA256_STRING_LEN       (32 * 2 + 1)
80
81 static bool ConnSSL_Init_SSL PARAMS(( CONNECTION *c ));
82 static int ConnectAccept PARAMS(( CONNECTION *c, bool connect ));
83 static int ConnSSL_HandleError PARAMS(( CONNECTION *c, const int code, const char *fname ));
84
85 #ifdef HAVE_LIBGNUTLS
86 static char * openreadclose(const char *name, size_t *len)
87 {
88         char *buf = NULL;
89         struct stat s;
90         ssize_t br;
91         int fd = open(name, O_RDONLY);
92         if (fd < 0) {
93                 Log(LOG_ERR, "Could not open %s: %s", name, strerror(errno));
94                 return NULL;
95         }
96         if (fstat(fd, &s)) {
97                 Log(LOG_ERR, "Could not fstat %s: %s", name, strerror(errno));
98                 goto out;
99         }
100         if (!S_ISREG(s.st_mode)) {
101                 Log(LOG_ERR, "%s: Not a regular file", name);
102                 goto out;
103         }
104         if (s.st_size <= 0) {
105                 Log(LOG_ERR, "%s: invalid file length (size %ld <= 0)", name, (long) s.st_size);
106                 goto out;
107         }
108         buf = malloc(s.st_size);
109         if (!buf) {
110                 Log(LOG_ERR, "Could not malloc %lu bytes for file %s: %s", s.st_size, name, strerror(errno));
111                 goto out;
112         }
113         br = read(fd, buf, s.st_size);
114         if (br != (ssize_t)s.st_size) {
115                 Log(LOG_ERR, "Could not read file %s: read returned %ld, expected %ld: %s",
116                         name, (long) br, (long) s.st_size, br == -1 ? strerror(errno):"short read?!");
117                 memset(buf, 0, s.st_size);
118                 free(buf);
119                 buf = NULL;
120         } else {
121                 *len = br;
122         }
123 out:
124         close(fd);
125         return buf;
126 }
127 #endif
128
129
130 #ifdef HAVE_LIBSSL
131 /**
132  * Log OpenSSL error message.
133  *
134  * @param msg The error message.
135  * @param info Additional information text or NULL.
136  */
137 static void
138 LogOpenSSL_CertInfo(X509 *cert, const char *msg)
139 {
140         BIO *mem;
141         char *memptr;
142         long len;
143
144         assert(cert);
145         assert(msg);
146
147         if (!cert) return;
148
149         mem = BIO_new(BIO_s_mem());
150         if (!mem) return;
151
152         X509_NAME_print_ex(mem, X509_get_subject_name (cert), 4, XN_FLAG_ONELINE);
153         X509_NAME_print_ex(mem, X509_get_issuer_name (cert), 4, XN_FLAG_ONELINE);
154         if (BIO_write(mem, "", 1) == 1) {
155                 len = BIO_get_mem_data(mem, &memptr);
156                 assert(memptr);
157                 assert(len>0);
158                 Log(LOG_INFO, "%s: \"%s\"", msg, memptr);
159         }
160
161         (void)BIO_set_close(mem, BIO_CLOSE);
162         BIO_free(mem);
163 }
164
165 static void
166 LogOpenSSLError(const char *error, const char *info)
167 {
168         unsigned long err = ERR_get_error();
169         char * errmsg = err
170                 ? ERR_error_string(err, NULL)
171                 : "Unable to determine error";
172
173         assert(error != NULL);
174
175         if (info)
176                 Log(LOG_ERR, "%s: %s (%s)", error, info, errmsg);
177         else
178                 Log(LOG_ERR, "%s: %s", error, errmsg);
179 }
180
181
182 static int
183 pem_passwd_cb(char *buf, int size, int rwflag, void *password)
184 {
185         array *pass = password;
186         int passlen;
187
188         (void)rwflag;           /* rwflag is unused if DEBUG is not set. */
189         assert(rwflag == 0);    /* 0 -> callback used for decryption.
190                                  * See SSL_CTX_set_default_passwd_cb(3) */
191
192         passlen = (int) array_bytes(pass);
193
194         LogDebug("pem_passwd_cb buf size %d, array size %d", size, passlen);
195         assert(passlen >= 0);
196         if (passlen <= 0) {
197                 Log(LOG_ERR, "PEM password required but not set [in pem_passwd_cb()]!");
198                 return 0;
199         }
200         size = passlen > size ? size : passlen;
201         memcpy(buf, (char *)(array_start(pass)), size);
202         return size;
203 }
204
205
206 static int
207 Verify_openssl(int preverify_ok, X509_STORE_CTX *ctx)
208 {
209         X509 *err_cert;
210         int err, depth;
211
212         err_cert = X509_STORE_CTX_get_current_cert(ctx);
213         err = X509_STORE_CTX_get_error(ctx);
214         depth = X509_STORE_CTX_get_error_depth(ctx);
215
216         LogDebug("preverify_ok %d error:num=%d:%s:depth=%d",
217                         preverify_ok, err, X509_verify_cert_error_string(err), depth);
218
219         if (preverify_ok != 1) {
220                 /*
221                  * if certificates are not being enforced, ignore any errors.
222                  * its possible to check if a connection has a valid certificate
223                  * by testing the CONN_SSL_PEERCERT_OK flag.
224                  * This can be used to enforce certificates for incoming servers,
225                  * but not irc clients.
226                  */
227                 if (!Conf_SSLOptions.RequireClientCert)
228                         preverify_ok = 1;
229                 else
230                         Log(LOG_ERR, "verify error:num=%d:%s:depth=%d", err,
231                                 X509_verify_cert_error_string(err), depth);
232         }
233         return preverify_ok;
234 }
235 #endif
236
237
238 static bool
239 Load_DH_params(void)
240 {
241 #ifdef HAVE_LIBSSL
242         FILE *fp;
243         bool ret = true;
244
245         if (!Conf_SSLOptions.DHFile) {
246                 Log(LOG_NOTICE, "Configuration option \"DHFile\" not set!");
247                 return false;
248         }
249         fp = fopen(Conf_SSLOptions.DHFile, "r");
250         if (!fp) {
251                 Log(LOG_ERR, "%s: %s", Conf_SSLOptions.DHFile, strerror(errno));
252                 return false;
253         }
254         dh_params = PEM_read_DHparams(fp, NULL, NULL, NULL);
255         if (!dh_params) {
256                 Log(LOG_ERR, "%s: Failed to read SSL DH parameters!",
257                     Conf_SSLOptions.DHFile);
258                 ret = false;
259         }
260         fclose(fp);
261         return ret;
262 #endif
263 #ifdef HAVE_LIBGNUTLS
264         bool need_dhgenerate = true;
265         int err;
266         gnutls_dh_params_t tmp_dh_params;
267
268         err = gnutls_dh_params_init(&tmp_dh_params);
269         if (err < 0) {
270                 Log(LOG_ERR, "Failed to initialize SSL DH parameters: %s",
271                     gnutls_strerror(err));
272                 return false;
273         }
274         if (Conf_SSLOptions.DHFile) {
275                 gnutls_datum_t dhparms;
276                 size_t size;
277                 dhparms.data = (unsigned char *) openreadclose(Conf_SSLOptions.DHFile, &size);
278                 if (dhparms.data) {
279                         dhparms.size = size;
280                         err = gnutls_dh_params_import_pkcs3(tmp_dh_params, &dhparms, GNUTLS_X509_FMT_PEM);
281                         if (err == 0)
282                                 need_dhgenerate = false;
283                         else
284                                 Log(LOG_ERR,
285                                     "Failed to initialize SSL DH parameters: %s",
286                                     gnutls_strerror(err));
287
288                         memset(dhparms.data, 0, size);
289                         free(dhparms.data);
290                 }
291         }
292         if (need_dhgenerate) {
293                 Log(LOG_WARNING,
294                     "DHFile not set, generating %u bit DH parameters. This may take a while ...",
295                     DH_BITS);
296                 err = gnutls_dh_params_generate2(tmp_dh_params, DH_BITS);
297                 if (err < 0) {
298                         Log(LOG_ERR, "Failed to generate SSL DH parameters: %s",
299                             gnutls_strerror(err));
300                         return false;
301                 }
302         }
303         dh_params = tmp_dh_params;
304         return true;
305 #endif
306 }
307
308
309 void ConnSSL_Free(CONNECTION *c)
310 {
311 #ifdef HAVE_LIBSSL
312         SSL *ssl = c->ssl_state.ssl;
313         if (ssl) {
314                 SSL_shutdown(ssl);
315                 SSL_free(ssl);
316                 c->ssl_state.ssl = NULL;
317                 if (c->ssl_state.fingerprint) {
318                         free(c->ssl_state.fingerprint);
319                         c->ssl_state.fingerprint = NULL;
320                 }
321         }
322 #endif
323 #ifdef HAVE_LIBGNUTLS
324         gnutls_session_t sess = c->ssl_state.gnutls_session;
325         if (Conn_OPTION_ISSET(c, CONN_SSL)) {
326                 gnutls_bye(sess, GNUTLS_SHUT_RDWR);
327                 gnutls_deinit(sess);
328         }
329 #endif
330         assert(Conn_OPTION_ISSET(c, CONN_SSL));
331         /* can't just set bitmask to 0 -- there are other, non-ssl related flags, e.g. CONN_ZIP. */
332         Conn_OPTION_DEL(c, CONN_SSL_FLAGS_ALL);
333 }
334
335
336 bool
337 ConnSSL_InitLibrary( void )
338 {
339         if (!Conf_SSLInUse()) {
340                 LogDebug("SSL not in use, skipping initialization.");
341                 return true;
342         }
343
344 #ifdef HAVE_LIBSSL
345         SSL_CTX *newctx;
346
347         if (!ssl_ctx) {
348                 SSL_library_init();
349                 SSL_load_error_strings();
350         }
351
352         if (!RAND_status()) {
353                 Log(LOG_ERR, "OpenSSL PRNG not seeded: /dev/urandom missing?");
354                 /*
355                  * it is probably best to fail and let the user install EGD or
356                  * a similar program if no kernel random device is available.
357                  * According to OpenSSL RAND_egd(3): "The automatic query of
358                  * /var/run/egd-pool et al was added in OpenSSL 0.9.7";
359                  * so it makes little sense to deal with PRNGD seeding ourselves.
360                  */
361                 array_free(&Conf_SSLOptions.ListenPorts);
362                 return false;
363         }
364
365         newctx = SSL_CTX_new(SSLv23_method());
366         if (!newctx) {
367                 LogOpenSSLError("Failed to create SSL context", NULL);
368                 array_free(&Conf_SSLOptions.ListenPorts);
369                 return false;
370         }
371
372         if (!ConnSSL_LoadServerKey_openssl(newctx))
373                 goto out;
374
375         if (SSL_CTX_set_cipher_list(newctx, Conf_SSLOptions.CipherList) == 0) {
376                 Log(LOG_ERR, "Failed to apply OpenSSL cipher list \"%s\"!",
377                     Conf_SSLOptions.CipherList);
378                 goto out;
379         }
380
381         if (!ConnSSL_SetVerifyProperties_openssl(newctx))
382                 goto out;
383
384         SSL_CTX_set_options(newctx, SSL_OP_SINGLE_DH_USE|SSL_OP_NO_SSLv2);
385         SSL_CTX_set_mode(newctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
386         SSL_CTX_set_verify(newctx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,
387                            Verify_openssl);
388         SSL_CTX_free(ssl_ctx);
389         ssl_ctx = newctx;
390         Log(LOG_INFO, "%s initialized.", SSLeay_version(SSLEAY_VERSION));
391         return true;
392 out:
393         SSL_CTX_free(newctx);
394         array_free(&Conf_SSLOptions.ListenPorts);
395         return false;
396 #endif
397 #ifdef HAVE_LIBGNUTLS
398         int err;
399         static bool initialized;
400
401         if (initialized) {
402                 /* TODO: cannot reload gnutls keys: can't simply free x509
403                  * context -- it may still be in use */
404                 return false;
405         }
406
407         err = gnutls_global_init();
408         if (err) {
409                 Log(LOG_ERR, "Failed to initialize GnuTLS: %s",
410                     gnutls_strerror(err));
411                 goto out;
412         }
413
414         if (!ConnSSL_LoadServerKey_gnutls())
415                 goto out;
416
417         if (gnutls_priority_init(&priorities_cache, Conf_SSLOptions.CipherList,
418                                  NULL) != GNUTLS_E_SUCCESS) {
419                 Log(LOG_ERR,
420                     "Failed to apply GnuTLS cipher list \"%s\"!",
421                     Conf_SSLOptions.CipherList);
422                 goto out;
423         }
424
425         if (!ConnSSL_SetVerifyProperties_gnutls())
426                 goto out;
427
428         Log(LOG_INFO, "GnuTLS %s initialized.", gnutls_check_version(NULL));
429         initialized = true;
430         return true;
431 out:
432         array_free(&Conf_SSLOptions.ListenPorts);
433         return false;
434 #endif
435 }
436
437
438 #ifdef HAVE_LIBGNUTLS
439 static bool
440 ConnSSL_SetVerifyProperties_gnutls(void)
441 {
442         int err;
443
444         if (Conf_SSLOptions.CAFile) {
445                 err = gnutls_certificate_set_x509_trust_file(x509_cred, Conf_SSLOptions.CAFile, GNUTLS_X509_FMT_PEM);
446                 if (err < 0) {
447                         Log(LOG_ERR, "Failed to load x509 trust file %s: %s", Conf_SSLOptions.CAFile, gnutls_strerror(err));
448                         return false;
449                 }
450         }
451         if (Conf_SSLOptions.CRLFile) {
452                 err = gnutls_certificate_set_x509_crl_file(x509_cred, Conf_SSLOptions.CRLFile, GNUTLS_X509_FMT_PEM);
453                 if (err < 0) {
454                         Log(LOG_ERR, "Failed to load x509 crl file %s: %s", Conf_SSLOptions.CRLFile, gnutls_strerror(err));
455                         return false;
456                 }
457         }
458
459         return true;
460 }
461
462
463 static bool
464 ConnSSL_LoadServerKey_gnutls(void)
465 {
466         int err;
467         const char *cert_file;
468
469         err = gnutls_certificate_allocate_credentials(&x509_cred);
470         if (err < 0) {
471                 Log(LOG_ERR, "Failed to allocate certificate credentials: %s",
472                     gnutls_strerror(err));
473                 return false;
474         }
475
476         cert_file = Conf_SSLOptions.CertFile ? Conf_SSLOptions.CertFile:Conf_SSLOptions.KeyFile;
477         if (!cert_file) {
478                 Log(LOG_ERR, "No SSL server key configured!");
479                 return false;
480         }
481
482         if (array_bytes(&Conf_SSLOptions.KeyFilePassword))
483                 Log(LOG_WARNING,
484                     "Ignoring SSL \"KeyFilePassword\": Not supported by GnuTLS.");
485
486         if (!Load_DH_params())
487                 return false;
488
489         gnutls_certificate_set_dh_params(x509_cred, dh_params);
490         err = gnutls_certificate_set_x509_key_file(x509_cred, cert_file, Conf_SSLOptions.KeyFile, GNUTLS_X509_FMT_PEM);
491         if (err < 0) {
492                 Log(LOG_ERR,
493                     "Failed to set certificate key file (cert %s, key %s): %s",
494                     cert_file,
495                     Conf_SSLOptions.KeyFile ? Conf_SSLOptions.KeyFile : "(NULL)",
496                     gnutls_strerror(err));
497                 return false;
498         }
499         return true;
500 }
501 #endif
502
503
504 #ifdef HAVE_LIBSSL
505 static bool
506 ConnSSL_LoadServerKey_openssl(SSL_CTX *ctx)
507 {
508         char *cert_key;
509
510         assert(ctx);
511         if (!Conf_SSLOptions.KeyFile) {
512                 Log(LOG_ERR, "No SSL server key configured!");
513                 return false;
514         }
515
516         SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_cb);
517         SSL_CTX_set_default_passwd_cb_userdata(ctx, &Conf_SSLOptions.KeyFilePassword);
518
519         if (SSL_CTX_use_PrivateKey_file(ctx, Conf_SSLOptions.KeyFile, SSL_FILETYPE_PEM) != 1) {
520                 array_free_wipe(&Conf_SSLOptions.KeyFilePassword);
521                 LogOpenSSLError("Failed to add private key", Conf_SSLOptions.KeyFile);
522                 return false;
523         }
524
525         cert_key = Conf_SSLOptions.CertFile ? Conf_SSLOptions.CertFile:Conf_SSLOptions.KeyFile;
526         if (SSL_CTX_use_certificate_chain_file(ctx, cert_key) != 1) {
527                 array_free_wipe(&Conf_SSLOptions.KeyFilePassword);
528                 LogOpenSSLError("Failed to load certificate chain", cert_key);
529                 return false;
530         }
531
532         array_free_wipe(&Conf_SSLOptions.KeyFilePassword);
533
534         if (!SSL_CTX_check_private_key(ctx)) {
535                 LogOpenSSLError("Server private key does not match certificate", NULL);
536                 return false;
537         }
538         if (Load_DH_params()) {
539                 if (SSL_CTX_set_tmp_dh(ctx, dh_params) != 1)
540                         LogOpenSSLError("Error setting DH parameters", Conf_SSLOptions.DHFile);
541                 /* don't return false here: the non-DH modes will still work */
542                 DH_free(dh_params);
543                 dh_params = NULL;
544         }
545         return true;
546 }
547
548
549 static bool
550 ConnSSL_SetVerifyProperties_openssl(SSL_CTX * ctx)
551 {
552         X509_STORE *store = NULL;
553         X509_LOOKUP *lookup;
554         int verify_flags = SSL_VERIFY_PEER;
555         bool ret = false;
556
557         if (!Conf_SSLOptions.CAFile)
558                 return true;
559
560         if (SSL_CTX_load_verify_locations(ctx, Conf_SSLOptions.CAFile, NULL) != 1) {
561                 LogOpenSSLError("SSL_CTX_load_verify_locations", NULL);
562                 goto out;
563         }
564
565         store = SSL_CTX_get_cert_store(ctx);
566         assert(store);
567         lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
568         if (!lookup) {
569                 LogOpenSSLError("X509_STORE_add_lookup", Conf_SSLOptions.CRLFile);
570                 goto out;
571         }
572
573         if (1 != X509_load_crl_file(lookup, Conf_SSLOptions.CRLFile, X509_FILETYPE_PEM)) {
574                 LogOpenSSLError("X509_load_crl_file", Conf_SSLOptions.CRLFile);
575                 goto out;
576         }
577
578         if (Conf_SSLOptions.RequireClientCert)
579                 verify_flags |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
580
581         SSL_CTX_set_verify(ctx, verify_flags, Verify_openssl);
582         SSL_CTX_set_verify_depth(ctx, MAX_CERT_CHAIN_LENGTH);
583         ret = true;
584  out:
585         free(Conf_SSLOptions.CRLFile);
586         Conf_SSLOptions.CRLFile = NULL;
587         return ret;
588 }
589
590
591 #endif
592 static bool
593 ConnSSL_Init_SSL(CONNECTION *c)
594 {
595         int ret;
596
597         LogDebug("Initializing SSL ...");
598         assert(c != NULL);
599
600 #ifdef HAVE_LIBSSL
601         if (!ssl_ctx) {
602                 Log(LOG_ERR,
603                     "Can't initialize SSL context, OpenSSL initialization failed at startup!");
604                 return false;
605         }
606         assert(c->ssl_state.ssl == NULL);
607         assert(c->ssl_state.fingerprint == NULL);
608
609         c->ssl_state.ssl = SSL_new(ssl_ctx);
610         if (!c->ssl_state.ssl) {
611                 LogOpenSSLError("Failed to create SSL structure", NULL);
612                 return false;
613         }
614         Conn_OPTION_ADD(c, CONN_SSL);
615
616         ret = SSL_set_fd(c->ssl_state.ssl, c->sock);
617         if (ret != 1) {
618                 LogOpenSSLError("Failed to set SSL file descriptor", NULL);
619                 ConnSSL_Free(c);
620                 return false;
621         }
622 #endif
623 #ifdef HAVE_LIBGNUTLS
624         Conn_OPTION_ADD(c, CONN_SSL);
625         ret = gnutls_priority_set(c->ssl_state.gnutls_session, priorities_cache);
626         if (ret != GNUTLS_E_SUCCESS) {
627                 Log(LOG_ERR, "Failed to set GnuTLS session priorities: %s",
628                     gnutls_strerror(ret));
629                 ConnSSL_Free(c);
630                 return false;
631         }
632         /*
633          * The intermediate (long) cast is here to avoid a warning like:
634          * "cast to pointer from integer of different size" on 64-bit platforms.
635          * There doesn't seem to be an alternate GNUTLS API we could use instead, see e.g.
636          * http://www.mail-archive.com/help-gnutls@gnu.org/msg00286.html
637          */
638         gnutls_transport_set_ptr(c->ssl_state.gnutls_session,
639                                  (gnutls_transport_ptr_t) (long) c->sock);
640         gnutls_certificate_server_set_request(c->ssl_state.gnutls_session,
641                                               GNUTLS_CERT_REQUEST);
642         ret = gnutls_credentials_set(c->ssl_state.gnutls_session,
643                                      GNUTLS_CRD_CERTIFICATE, x509_cred);
644         if (ret != 0) {
645                 Log(LOG_ERR, "Failed to set SSL credentials: %s",
646                     gnutls_strerror(ret));
647                 ConnSSL_Free(c);
648                 return false;
649         }
650         gnutls_dh_set_prime_bits(c->ssl_state.gnutls_session, DH_BITS_MIN);
651 #endif
652         return true;
653 }
654
655
656 bool
657 ConnSSL_PrepareConnect(CONNECTION *c, UNUSED CONF_SERVER *s)
658 {
659         bool ret;
660 #ifdef HAVE_LIBGNUTLS
661         int err;
662
663         err = gnutls_init(&c->ssl_state.gnutls_session, GNUTLS_CLIENT);
664         if (err) {
665                 Log(LOG_ERR, "Failed to initialize new SSL session: %s",
666                     gnutls_strerror(err));
667                 return false;
668         }
669 #endif
670         ret = ConnSSL_Init_SSL(c);
671         if (!ret)
672                 return false;
673         Conn_OPTION_ADD(c, CONN_SSL_CONNECT);
674 #ifdef HAVE_LIBSSL
675         assert(c->ssl_state.ssl);
676
677         if (s->SSLVerify)
678                 SSL_set_verify(c->ssl_state.ssl, SSL_VERIFY_PEER, Verify_openssl);
679         else
680                 SSL_set_verify(c->ssl_state.ssl, SSL_VERIFY_NONE, NULL);
681 #endif
682         return true;
683 }
684
685
686 /**
687  * Check and handle error return codes after failed calls to SSL functions.
688  *
689  * OpenSSL:
690  * SSL_connect(), SSL_accept(), SSL_do_handshake(), SSL_read(), SSL_peek(), or
691  * SSL_write() on ssl.
692  *
693  * GnuTLS:
694  * gnutlsssl_read(), gnutls_write() or gnutls_handshake().
695  *
696  * @param c The connection handle.
697  * @prarm code The return code.
698  * @param fname The name of the function in which the error occurred.
699  * @return -1 on fatal errors, 0 if we can try again later.
700  */
701 static int
702 ConnSSL_HandleError(CONNECTION * c, const int code, const char *fname)
703 {
704 #ifdef HAVE_LIBSSL
705         int ret = SSL_ERROR_SYSCALL;
706         unsigned long sslerr;
707         int real_errno = errno;
708
709         ret = SSL_get_error(c->ssl_state.ssl, code);
710
711         switch (ret) {
712         case SSL_ERROR_WANT_READ:
713                 io_event_del(c->sock, IO_WANTWRITE);
714                 Conn_OPTION_ADD(c, CONN_SSL_WANT_READ);
715                 return 0;       /* try again later */
716         case SSL_ERROR_WANT_WRITE:
717                 io_event_del(c->sock, IO_WANTREAD);
718                 Conn_OPTION_ADD(c, CONN_SSL_WANT_WRITE); /* fall through */
719         case SSL_ERROR_NONE:
720                 return 0;       /* try again later */
721         case SSL_ERROR_ZERO_RETURN:
722                 LogDebug("SSL connection shut down normally.");
723                 break;
724         case SSL_ERROR_SYSCALL:
725                 /* SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_ACCEPT,
726                  * and SSL_ERROR_WANT_X509_LOOKUP */
727                 sslerr = ERR_get_error();
728                 if (sslerr) {
729                         Log(LOG_ERR, "SSL error: %s [in %s()]!",
730                             ERR_error_string(sslerr, NULL), fname);
731                 } else {
732                         switch (code) { /* EOF that violated protocol */
733                         case 0:
734                                 Log(LOG_ERR,
735                                     "SSL error, client disconnected [in %s()]!",
736                                     fname);
737                                 break;
738                         case -1:        /* low level socket I/O error, check errno */
739                                 Log(LOG_ERR, "SSL error: %s [in %s()]!",
740                                     strerror(real_errno), fname);
741                         }
742                 }
743                 break;
744         case SSL_ERROR_SSL:
745                 LogOpenSSLError("SSL protocol error", fname);
746                 break;
747         default:
748                 Log(LOG_ERR, "Unknown SSL error %d [in %s()]!", ret, fname);
749         }
750         ConnSSL_Free(c);
751         return -1;
752 #endif
753 #ifdef HAVE_LIBGNUTLS
754         switch (code) {
755         case GNUTLS_E_AGAIN:
756         case GNUTLS_E_INTERRUPTED:
757                 if (gnutls_record_get_direction(c->ssl_state.gnutls_session)) {
758                         Conn_OPTION_ADD(c, CONN_SSL_WANT_WRITE);
759                         io_event_del(c->sock, IO_WANTREAD);
760                 } else {
761                         Conn_OPTION_ADD(c, CONN_SSL_WANT_READ);
762                         io_event_del(c->sock, IO_WANTWRITE);
763                 }
764                 break;
765         default:
766                 assert(code < 0);
767                 if (gnutls_error_is_fatal(code)) {
768                         Log(LOG_ERR, "SSL error: %s [%s].",
769                             gnutls_strerror(code), fname);
770                         ConnSSL_Free(c);
771                         return -1;
772                 }
773         }
774         return 0;
775 #endif
776 }
777
778
779 #ifdef HAVE_LIBGNUTLS
780 static bool check_verification(unsigned output)
781 {
782         char errmsg[256] = "";
783
784         if (output & GNUTLS_CERT_SIGNER_NOT_FOUND)
785                 strlcpy(errmsg, "No Issuer found", sizeof errmsg);
786         if (output & GNUTLS_CERT_SIGNER_NOT_CA) {
787                 if (errmsg[0])
788                         strlcat(errmsg, " ,", sizeof errmsg);
789                 strlcat(errmsg, "Issuer is not a CA", sizeof errmsg);
790         }
791         if (output & GNUTLS_CERT_INSECURE_ALGORITHM) {
792                 if (errmsg[0])
793                         strlcat(errmsg, " ,", sizeof errmsg);
794                 strlcat(errmsg, "Insecure Algorithm", sizeof errmsg);
795         }
796         if (output & GNUTLS_CERT_REVOKED) {
797                 if (errmsg[0])
798                         strlcat(errmsg, " ,", sizeof errmsg);
799                 strlcat(errmsg, "Certificate Revoked", sizeof errmsg);
800         }
801 #ifdef DEBUG
802         if (output & GNUTLS_CERT_INVALID)
803                 assert(errmsg[0]); /* check for unhandled error */
804 #endif
805         if (!(output & GNUTLS_CERT_INVALID) && !errmsg[0]) {
806                 LogDebug("Certificate verified.");
807                 return true;
808         }
809         Log(LOG_ERR, "Certificate Validation failed: %s", errmsg);
810         return false;
811 }
812
813 static void *LogMalloc(size_t s)
814 {
815         void *mem = malloc(s);
816         if (!mem)
817                 Log(LOG_ERR, "Out of memory: Could not allocate %lu byte", (unsigned long) s);
818         return mem;
819 }
820
821 static void
822 LogGnuTLS_CertInfo(gnutls_x509_crt_t cert, const char *msg)
823 {
824         char *dn, *issuer_dn;
825         size_t size = 0;
826         int err = gnutls_x509_crt_get_dn(cert, NULL, &size);
827         if (size == 0 || (err && err != GNUTLS_E_SHORT_MEMORY_BUFFER))
828                 goto err_crt_get;
829         dn = LogMalloc(size);
830         if (!dn)
831                 return;
832         err = gnutls_x509_crt_get_dn(cert, dn, &size);
833         if (err) {
834  err_crt_get:
835                 Log(LOG_ERR, "gnutls_x509_crt_get_dn: %s", err ? gnutls_strerror(err) : "size == 0");
836                 return;
837         }
838         gnutls_x509_crt_get_issuer_dn(cert, NULL, &size);
839         assert(size);
840         issuer_dn = LogMalloc(size);
841         if (!issuer_dn) {
842                 Log(LOG_INFO, "%s: Distinguished Name: %s", msg, dn);
843                 free(dn);
844                 return;
845         }
846         gnutls_x509_crt_get_issuer_dn(cert, issuer_dn, &size);
847         Log(LOG_INFO, "%s: Distinguished Name: \"%s\", Issuer \"%s\"", msg, dn, issuer_dn);
848         free(dn);
849         free(issuer_dn);
850 }
851 #endif
852
853 static void
854 ConnSSL_LogCertInfo( CONNECTION *c )
855 {
856         const char *comp_alg = "no compression";
857         bool cert_seen = false, cert_ok = false, cn_match = false;
858         char msg[128];
859 #ifdef HAVE_LIBSSL
860         const void *comp;
861         X509 *client_cert = NULL;
862         SSL *ssl = c->ssl_state.ssl;
863
864         assert(ssl);
865         comp=SSL_get_current_compression(ssl);
866         if (comp) {
867                 Conn_OPTION_ADD(c, CONN_SSL_COMPRESSION);
868                 comp_alg = SSL_COMP_get_name(comp);
869         }
870         Log(LOG_INFO, "Connection %d: initialized %s using cipher %s, %s.",
871                 c->sock, SSL_get_version(ssl), SSL_get_cipher(ssl), comp_alg);
872         client_cert = SSL_get_peer_certificate(ssl);
873         if (client_cert) {
874                 int err = SSL_get_verify_result(ssl);
875                 if (err == X509_V_OK)
876                         cert_ok = true;
877                 else
878                         Log(LOG_ERR, "Certificate Validation failed: %s", X509_verify_cert_error_string(err));
879                 X509_NAME *subjectName;
880                 char cn[256];
881                 subjectName = X509_get_subject_name(client_cert);
882                 X509_NAME_get_text_by_NID(
883                             subjectName, NID_commonName, cn, sizeof(cn));
884                 if (strcmp (cn, c->host) == 0)
885                         cn_match = true;
886                 else
887                         Log(LOG_ERR, "CN mismatch! Got \"%s\", expected \"%s\"", cn, c->host);
888
889                 snprintf(msg, sizeof(msg), "%svalid peer certificate", cert_ok ? "":"in");
890                 LogOpenSSL_CertInfo(client_cert, msg);
891                 X509_free(client_cert);
892                 cert_seen = true;
893         }
894 #endif
895 #ifdef HAVE_LIBGNUTLS
896         unsigned int status;
897         int ret;
898         gnutls_credentials_type_t cred;
899         gnutls_session_t sess = c->ssl_state.gnutls_session;
900         gnutls_cipher_algorithm_t cipher = gnutls_cipher_get(sess);
901         gnutls_compression_method_t comp = gnutls_compression_get(sess);
902
903         if (comp != GNUTLS_COMP_NULL)
904                 comp_alg = gnutls_compression_get_name(comp);
905         Log(LOG_INFO, "Connection %d: initialized %s using cipher %s-%s, %s.",
906             c->sock,
907             gnutls_protocol_get_name(gnutls_protocol_get_version(sess)),
908             gnutls_cipher_get_name(cipher),
909             gnutls_mac_get_name(gnutls_mac_get(sess)),
910             comp_alg);
911         ret = gnutls_certificate_verify_peers2(c->ssl_state.gnutls_session, &status);
912         if (ret < 0)
913                 Log(LOG_ERR, "gnutls_certificate_verify_peers2 failed: %s", gnutls_strerror(ret));
914         if (ret == 0 && check_verification(status))
915                 cert_ok = true;
916
917         cred = gnutls_auth_get_type (c->ssl_state.gnutls_session);
918         if (cred == GNUTLS_CRD_CERTIFICATE) {
919                 gnutls_x509_crt_t cert;
920                 unsigned cert_list_size;
921                 const gnutls_datum_t *cert_list = gnutls_certificate_get_peers(sess, &cert_list_size);
922                 if (!cert_list) {
923                         Log(LOG_ERR, "gnutls_certificate_get_peers() failed");
924                         return;
925                 }
926                 assert(cert_list_size > 0);
927                 gnutls_x509_crt_init(&cert);
928                 gnutls_x509_crt_import(cert, cert_list, GNUTLS_X509_FMT_DER);
929
930                 char *cn;
931                 size_t size = 0;
932                 int err = gnutls_x509_crt_get_dn_by_oid(cert,
933                         GNUTLS_OID_X520_COMMON_NAME,
934                         0, 0, NULL, &size);
935                 if (size == 0 || (err && err != GNUTLS_E_SHORT_MEMORY_BUFFER))
936                         goto done_cn_validation;
937                 cn = LogMalloc(size);
938                 if (!cn)
939                         goto done_cn_validation;
940                 gnutls_x509_crt_get_dn_by_oid (cert,
941                         GNUTLS_OID_X520_COMMON_NAME,
942                         0, 0, cn, &size);
943                 if (strcmp (cn, c->host) == 0)
944                         cn_match = true;
945                 else
946                         Log(LOG_ERR, "CN mismatch! Got \"%s\", expected \"%s\"", cn, c->host);
947                 free (cn);
948 done_cn_validation:
949
950                 snprintf(msg, sizeof(msg), "%svalid peer certificate", cert_ok ? "":"in");
951                 LogGnuTLS_CertInfo(cert, msg);
952                 gnutls_x509_crt_deinit(cert);
953                 cert_seen = true;
954         }
955 #endif
956         /*
957          * can be used later to check if connection was authenticated, e.g. if inbound connection
958          * tries to register itself as server. could also restrict /OPER to authenticated connections, etc.
959          */
960         if (cert_ok && cn_match)
961                 Conn_OPTION_ADD(c, CONN_SSL_PEERCERT_OK);
962         if (!cert_seen)
963                 Log(LOG_INFO, "Peer did not present a certificate");
964 }
965
966
967 /*
968  Accept incoming SSL connection.
969  Return Values:
970          1: SSL Connection established
971          0: try again
972         -1: SSL Connection not established due to fatal error.
973 */
974 int
975 ConnSSL_Accept( CONNECTION *c )
976 {
977         assert(c != NULL);
978         if (!Conn_OPTION_ISSET(c, CONN_SSL)) {
979 #ifdef HAVE_LIBGNUTLS
980                 gnutls_certificate_request_t req;
981                 int err = gnutls_init(&c->ssl_state.gnutls_session, GNUTLS_SERVER);
982                 if (err) {
983                         Log(LOG_ERR, "Failed to initialize new SSL session: %s",
984                             gnutls_strerror(err));
985                         return false;
986                 }
987                 req = Conf_SSLOptions.RequireClientCert ? GNUTLS_CERT_REQUIRE : GNUTLS_CERT_REQUEST;
988                 gnutls_certificate_server_set_request(c->ssl_state.gnutls_session, req);
989 #endif
990                 if (!ConnSSL_Init_SSL(c))
991                         return -1;
992         }
993         return ConnectAccept(c, false );
994 }
995
996
997 int
998 ConnSSL_Connect( CONNECTION *c )
999 {
1000         assert(c != NULL);
1001 #ifdef HAVE_LIBSSL
1002         assert(c->ssl_state.ssl);
1003 #endif
1004         assert(Conn_OPTION_ISSET(c, CONN_SSL));
1005         return ConnectAccept(c, true);
1006 }
1007
1008 static int
1009 ConnSSL_InitCertFp( CONNECTION *c )
1010 {
1011         const char hex[] = "0123456789abcdef";
1012         int i;
1013
1014 #ifdef HAVE_LIBSSL
1015         unsigned char digest[EVP_MAX_MD_SIZE];
1016         unsigned int digest_size;
1017         X509 *cert;
1018
1019         cert = SSL_get_peer_certificate(c->ssl_state.ssl);
1020         if (!cert)
1021                 return 0;
1022
1023         if (!X509_digest(cert, EVP_sha256(), digest, &digest_size)) {
1024                 X509_free(cert);
1025                 return 0;
1026         }
1027
1028         X509_free(cert);
1029 #endif /* HAVE_LIBSSL */
1030 #ifdef HAVE_LIBGNUTLS
1031         gnutls_x509_crt_t cert;
1032         unsigned int cert_list_size;
1033         const gnutls_datum_t *cert_list;
1034         unsigned char digest[MAX_HASH_SIZE];
1035         size_t digest_size;
1036
1037         if (gnutls_certificate_type_get(c->ssl_state.gnutls_session) !=
1038                                         GNUTLS_CRT_X509)
1039                 return 0;
1040
1041         if (gnutls_x509_crt_init(&cert) != GNUTLS_E_SUCCESS)
1042                 return 0;
1043
1044         cert_list_size = 0;
1045         cert_list = gnutls_certificate_get_peers(c->ssl_state.gnutls_session,
1046                                                  &cert_list_size);
1047         if (!cert_list) {
1048                 gnutls_x509_crt_deinit(cert);
1049                 return 0;
1050         }
1051
1052         if (gnutls_x509_crt_import(cert, &cert_list[0],
1053                                    GNUTLS_X509_FMT_DER) != GNUTLS_E_SUCCESS) {
1054                 gnutls_x509_crt_deinit(cert);
1055                 return 0;
1056         }
1057
1058         digest_size = sizeof(digest);
1059         if (gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA256, digest,
1060                                             &digest_size)) {
1061                 gnutls_x509_crt_deinit(cert);
1062                 return 0;
1063         }
1064
1065         gnutls_x509_crt_deinit(cert);
1066 #endif /* HAVE_LIBGNUTLS */
1067
1068         assert(c->ssl_state.fingerprint == NULL);
1069
1070         c->ssl_state.fingerprint = malloc(SHA256_STRING_LEN);
1071         if (!c->ssl_state.fingerprint)
1072                 return 0;
1073
1074         for (i = 0; i < (int)digest_size; i++) {
1075                 c->ssl_state.fingerprint[i * 2] = hex[digest[i] / 16];
1076                 c->ssl_state.fingerprint[i * 2 + 1] = hex[digest[i] % 16];
1077         }
1078         c->ssl_state.fingerprint[i * 2] = '\0';
1079
1080         return 1;
1081 }
1082
1083 /* accept/connect wrapper. if connect is true, connect to peer, otherwise wait for incoming connection */
1084 static int
1085 ConnectAccept( CONNECTION *c, bool connect)
1086 {
1087         int ret;
1088 #ifdef HAVE_LIBSSL
1089         SSL *ssl = c->ssl_state.ssl;
1090         assert(ssl != NULL);
1091
1092         ret = connect ? SSL_connect(ssl) : SSL_accept(ssl);
1093         if (1 != ret)
1094                 return ConnSSL_HandleError(c, ret, connect ? "SSL_connect": "SSL_accept");
1095 #endif
1096 #ifdef HAVE_LIBGNUTLS
1097         (void) connect;
1098         ret = gnutls_handshake(c->ssl_state.gnutls_session);
1099         if (ret)
1100                 return ConnSSL_HandleError(c, ret, "gnutls_handshake");
1101 #endif /* _GNUTLS */
1102         (void)ConnSSL_InitCertFp(c);
1103
1104         Conn_OPTION_DEL(c, (CONN_SSL_WANT_WRITE|CONN_SSL_WANT_READ|CONN_SSL_CONNECT));
1105         ConnSSL_LogCertInfo(c);
1106
1107         Conn_StartLogin(CONNECTION2ID(c));
1108         return 1;
1109 }
1110
1111
1112 ssize_t
1113 ConnSSL_Write(CONNECTION *c, const void *buf, size_t count)
1114 {
1115         ssize_t bw;
1116
1117         Conn_OPTION_DEL(c, CONN_SSL_WANT_WRITE|CONN_SSL_WANT_READ);
1118
1119         assert(count > 0);
1120 #ifdef HAVE_LIBSSL
1121         bw = (ssize_t) SSL_write(c->ssl_state.ssl, buf, count);
1122 #endif
1123 #ifdef HAVE_LIBGNUTLS
1124         bw = gnutls_write(c->ssl_state.gnutls_session, buf, count);
1125 #endif
1126         if (bw > 0)
1127                 return bw;
1128         if (ConnSSL_HandleError( c, bw, "ConnSSL_Write") == 0)
1129                 errno = EAGAIN; /* try again */
1130         return -1;
1131 }
1132
1133
1134 ssize_t
1135 ConnSSL_Read(CONNECTION *c, void * buf, size_t count)
1136 {
1137         ssize_t br;
1138
1139         Conn_OPTION_DEL(c, CONN_SSL_WANT_WRITE|CONN_SSL_WANT_READ);
1140 #ifdef HAVE_LIBSSL
1141         br = (ssize_t) SSL_read(c->ssl_state.ssl, buf, count);
1142         if (br > 0)     /* on EOF we have to call ConnSSL_HandleError(), see SSL_read(3) */
1143                 return br;
1144 #endif
1145 #ifdef HAVE_LIBGNUTLS
1146         br = gnutls_read(c->ssl_state.gnutls_session, buf, count);
1147         if (br >= 0)    /* on EOF we must _not_ call ConnSSL_HandleError, see gnutls_record_recv(3) */
1148                 return br;
1149 #endif
1150         /* error on read: switch ConnSSL_HandleError() return values -> 0 is "try again", so return -1 and set EAGAIN */
1151         if (ConnSSL_HandleError(c, br, "ConnSSL_Read") == 0) {
1152                 errno = EAGAIN;
1153                 return -1;
1154         }
1155         return 0;
1156 }
1157
1158
1159 bool
1160 ConnSSL_GetCipherInfo(CONNECTION *c, char *buf, size_t len)
1161 {
1162 #ifdef HAVE_LIBSSL
1163         char *nl;
1164         SSL *ssl = c->ssl_state.ssl;
1165
1166         if (!ssl)
1167                 return false;
1168         *buf = 0;
1169         SSL_CIPHER_description(SSL_get_current_cipher(ssl), buf, len);
1170         nl = strchr(buf, '\n');
1171         if (nl)
1172                 *nl = 0;
1173         return true;
1174 #endif
1175 #ifdef HAVE_LIBGNUTLS
1176         if (Conn_OPTION_ISSET(c, CONN_SSL)) {
1177                 const char *name_cipher, *name_mac, *name_proto, *name_keyexchange;
1178                 unsigned keysize;
1179
1180                 gnutls_session_t sess = c->ssl_state.gnutls_session;
1181                 gnutls_cipher_algorithm_t cipher = gnutls_cipher_get(sess);
1182                 name_cipher = gnutls_cipher_get_name(cipher);
1183                 name_mac = gnutls_mac_get_name(gnutls_mac_get(sess));
1184                 keysize = gnutls_cipher_get_key_size(cipher) * 8;
1185                 name_proto = gnutls_protocol_get_name(gnutls_protocol_get_version(sess));
1186                 name_keyexchange = gnutls_kx_get_name(gnutls_kx_get(sess));
1187
1188                 return snprintf(buf, len, "%s-%s%15s Kx=%s      Enc=%s(%u) Mac=%s",
1189                         name_cipher, name_mac, name_proto, name_keyexchange, name_cipher, keysize, name_mac) > 0;
1190         }
1191         return false;
1192 #endif
1193 }
1194
1195 char *
1196 ConnSSL_GetCertFp(CONNECTION *c)
1197 {
1198         return c->ssl_state.fingerprint;
1199 }
1200
1201 bool
1202 ConnSSL_SetCertFp(CONNECTION *c, const char *fingerprint)
1203 {
1204         assert (c != NULL);
1205         c->ssl_state.fingerprint = strndup(fingerprint, SHA256_STRING_LEN - 1);
1206         return c->ssl_state.fingerprint != NULL;
1207 }
1208 #else
1209
1210 bool
1211 ConnSSL_InitLibrary(void)
1212 {
1213         return true;
1214 }
1215
1216 #endif /* SSL_SUPPORT */
1217 /* -eof- */
1218
1219