1 /*
2 * mtls-openssl.c
3 *
4 * This file is part of msmtp, an SMTP client, and of mpop, a POP3 client.
5 *
6 * Copyright (C) 2000, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
7 * 2012, 2014, 2016, 2018, 2019, 2020
8 * Martin Lambers <marlam@marlam.de>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
27
28 #include <stdio.h>
29 #include <string.h>
30 #include <strings.h>
31 #include <ctype.h>
32 #include <stdlib.h>
33 #include <limits.h>
34 #include <time.h>
35 #include <errno.h>
36
37 #include <openssl/ssl.h>
38 #include <openssl/x509.h>
39 #include <openssl/x509v3.h>
40 #include <openssl/err.h>
41 #include <openssl/rand.h>
42 #include <openssl/evp.h>
43 #if OPENSSL_VERSION_NUMBER < 0x10100000L
44 #define X509_get0_notBefore X509_get_notBefore
45 #define X509_get0_notAfter X509_get_notAfter
46 #endif
47
48 #ifdef HAVE_LIBIDN
49 # include <idn2.h>
50 #endif
51
52 #include "gettext.h"
53 #define _(string) gettext(string)
54 #define N_(string) gettext_noop(string)
55
56 #include "xalloc.h"
57 #include "readbuf.h"
58 #include "tools.h"
59 #include "mtls.h"
60
61
62 struct mtls_internals_t
63 {
64 SSL_CTX *ssl_ctx;
65 SSL *ssl;
66 };
67
68
69
70 /*
71 * seed_prng()
72 *
73 * Seeds the OpenSSL random number generator.
74 * Used error codes: TLS_ESEED
75 */
76
seed_prng(char ** errstr)77 static int seed_prng(char **errstr)
78 {
79 char randfile[512];
80 time_t t;
81 int prn;
82 int system_prn_max = 1024;
83
84 /* Most systems have /dev/random or other sources of random numbers that
85 * OpenSSL can use to seed itself.
86 * The only system I know of where we must seed the PRNG is DOS.
87 */
88 if (!RAND_status())
89 {
90 if (!RAND_file_name(randfile, 512))
91 {
92 *errstr = xasprintf(_("no environment variables RANDFILE or HOME, "
93 "or filename of rand file too long"));
94 return TLS_ESEED;
95 }
96 if (RAND_load_file(randfile, -1) < 1)
97 {
98 *errstr = xasprintf(_("%s: input error"), randfile);
99 return TLS_ESEED;
100 }
101 /* Seed in time. I can't think of other "random" things on DOS
102 * systems. */
103 t = time(NULL);
104 RAND_seed((unsigned char *)&t, sizeof(time_t));
105 /* If the RANDFILE + time is not enough, we fall back to the insecure
106 * and stupid method of seeding OpenSSLs PRNG with the systems PRNG. */
107 if (!RAND_status())
108 {
109 srand((unsigned int)(t % UINT_MAX));
110 while (!RAND_status() && system_prn_max > 0)
111 {
112 prn = rand();
113 RAND_seed(&prn, sizeof(int));
114 system_prn_max--;
115 }
116 }
117 /* Are we happy now? */
118 if (!RAND_status())
119 {
120 *errstr = xasprintf(_("random file + time + pseudo randomness is "
121 "not enough, giving up"));
122 return TLS_ESEED;
123 }
124 /* Save a rand file for later usage. We ignore errors here as we can't
125 * do anything about them. */
126 (void)RAND_write_file(randfile);
127 }
128 return TLS_EOK;
129 }
130
131
132 /*
133 * mtls_lib_init()
134 *
135 * see mtls.h
136 */
137
mtls_lib_init(char ** errstr)138 int mtls_lib_init(char **errstr)
139 {
140 int e;
141
142 #if OPENSSL_VERSION_NUMBER < 0x10100000L
143 SSL_load_error_strings();
144 SSL_library_init();
145 #endif
146 if ((e = seed_prng(errstr)) != TLS_EOK)
147 {
148 return e;
149 }
150
151 return TLS_EOK;
152 }
153
154
155 /*
156 * asn1time_to_time_t() [OpenSSL only]
157 *
158 * Convert a ASN1 time string ([YY]YYMMDDhhmm[ss](Z)) into a time_t.
159 * The flag 'is_utc' indicates whether the string is in UTC or GENERALIZED
160 * format. GENERALIZED means a 4 digit year.
161 * In case of invalid strings or over-/underflows, 1 is returned, and the value
162 * of 't' is undefined. On success, 0 is returned.
163 *
164 * This code uses many ideas from GnuTLS code (lib/x509/common.c).
165 * The transformation of struct tm to time_t is based on code from Russ Allbery
166 * (rra@stanford.edu), who wrote a mktime_utc function and placed it under
167 * public domain.
168 */
169
is_leap(int year)170 static int is_leap(int year)
171 {
172 return (((year) % 4) == 0 && (((year) % 100) != 0 || ((year) % 400) == 0));
173 }
174
asn1time_to_time_t(const char * asn1time,int is_utc,time_t * t)175 static int asn1time_to_time_t(const char *asn1time, int is_utc, time_t *t)
176 {
177 size_t len;
178 int i;
179 size_t j;
180 const char *p;
181 char xx[3];
182 char xxxx[5];
183 const int monthdays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
184 struct tm tm;
185
186 len = strlen(asn1time);
187 if ((is_utc && len < 10) || (!is_utc && len < 12))
188 {
189 goto error_exit;
190 }
191 for (j = 0; j < len - 1; j++)
192 {
193 if (!isdigit((unsigned char)asn1time[j]))
194 {
195 goto error_exit;
196 }
197 }
198
199 xx[2] = '\0';
200 xxxx[4] = '\0';
201 p = asn1time;
202 if (is_utc)
203 {
204 strncpy(xx, p, 2);
205 tm.tm_year = atoi(xx);
206 tm.tm_year += (tm.tm_year > 49) ? 1900 : 2000;
207 p += 2;
208 }
209 else
210 {
211 strncpy(xxxx, p, 4);
212 tm.tm_year = atoi(xxxx);
213 p += 4;
214 }
215 strncpy(xx, p, 2);
216 tm.tm_mon = atoi(xx) - 1;
217 p += 2;
218 strncpy(xx, p, 2);
219 tm.tm_mday = atoi(xx);
220 p += 2;
221 strncpy(xx, p, 2);
222 tm.tm_hour = atoi(xx);
223 p += 2;
224 strncpy(xx, p, 2);
225 tm.tm_min = atoi(xx);
226 p += 2;
227 if (isdigit((unsigned char)(*p)))
228 {
229 strncpy(xx, p, 2);
230 tm.tm_sec = atoi(xx);
231 }
232 else
233 {
234 tm.tm_sec = 0;
235 }
236
237 /* basic check for 32 bit time_t overflows. */
238 if (sizeof(time_t) <= 4 && tm.tm_year >= 2038)
239 {
240 goto error_exit;
241 }
242 if (tm.tm_year < 1970 || tm.tm_mon < 0 || tm.tm_mon > 11)
243 {
244 goto error_exit;
245 }
246 *t = 0;
247 for (i = 1970; i < tm.tm_year; i++)
248 {
249 *t += 365 + (is_leap(i) ? 1 : 0);
250 }
251 for (i = 0; i < tm.tm_mon; i++)
252 {
253 *t += monthdays[i];
254 }
255 if (tm.tm_mon > 1 && is_leap(tm.tm_year))
256 {
257 *t += 1;
258 }
259 *t = 24 * (*t + tm.tm_mday - 1) + tm.tm_hour;
260 *t = 60 * (*t) + tm.tm_min;
261 *t = 60 * (*t) + tm.tm_sec;
262
263 return 0;
264
265 error_exit:
266 return 1;
267 }
268
269
270 /*
271 * mtls_cert_info_get()
272 *
273 * see mtls.h
274 */
275
mtls_cert_info_get(mtls_t * mtls,mtls_cert_info_t * mtci,char ** errstr)276 int mtls_cert_info_get(mtls_t *mtls, mtls_cert_info_t *mtci, char **errstr)
277 {
278 X509 *x509cert;
279 X509_NAME *x509_subject;
280 X509_NAME *x509_issuer;
281 const ASN1_TIME *asn1time;
282 unsigned int usize;
283 const char *errmsg;
284
285 errmsg = _("cannot get TLS certificate info");
286 if (!(x509cert = SSL_get_peer_certificate(mtls->internals->ssl)))
287 {
288 *errstr = xasprintf(_("%s: no certificate was found"), errmsg);
289 return TLS_ECERT;
290 }
291 if (!(x509_subject = X509_get_subject_name(x509cert)))
292 {
293 *errstr = xasprintf(_("%s: cannot get certificate subject"), errmsg);
294 X509_free(x509cert);
295 return TLS_ECERT;
296 }
297 if (!(x509_issuer = X509_get_issuer_name(x509cert)))
298 {
299 *errstr = xasprintf(_("%s: cannot get certificate issuer"), errmsg);
300 X509_free(x509cert);
301 return TLS_ECERT;
302 }
303
304 /* certificate information */
305 usize = 32;
306 if (!X509_digest(x509cert, EVP_sha256(), mtci->sha256_fingerprint, &usize))
307 {
308 *errstr = xasprintf(_("%s: error getting SHA256 fingerprint"), errmsg);
309 return TLS_ECERT;
310 }
311 usize = 20;
312 if (!X509_digest(x509cert, EVP_sha1(), mtci->sha1_fingerprint, &usize))
313 {
314 *errstr = xasprintf(_("%s: error getting SHA1 fingerprint"), errmsg);
315 return TLS_ECERT;
316 }
317 asn1time = X509_get0_notBefore(x509cert);
318 if (asn1time_to_time_t((const char *)asn1time->data,
319 (asn1time->type != V_ASN1_GENERALIZEDTIME),
320 &(mtci->activation_time)) != 0)
321 {
322 *errstr = xasprintf(_("%s: cannot get activation time"), errmsg);
323 X509_free(x509cert);
324 mtls_cert_info_free(mtci);
325 return TLS_ECERT;
326 }
327 asn1time = X509_get0_notAfter(x509cert);
328 if (asn1time_to_time_t((const char *)asn1time->data,
329 (asn1time->type != V_ASN1_GENERALIZEDTIME),
330 &(mtci->expiration_time)) != 0)
331 {
332 *errstr = xasprintf(_("%s: cannot get expiration time"), errmsg);
333 X509_free(x509cert);
334 mtls_cert_info_free(mtci);
335 return TLS_ECERT;
336 }
337
338 /* subject information */
339 mtci->subject_info = X509_NAME_oneline(x509_subject, NULL, 0);
340
341 /* issuer information */
342 mtci->issuer_info = X509_NAME_oneline(x509_issuer, NULL, 0);
343
344 X509_free(x509cert);
345 return TLS_EOK;
346 }
347
348
349 /*
350 * [OpenSSL only] hostname_match()
351 *
352 * Compares the hostname with the name in the certificate. The certificate name
353 * may include a wildcard as the leftmost domain component (its first two
354 * characters are "*." in this case).
355 *
356 * Returns 1 if the names match, 0 otherwise.
357 *
358 * This is the same form of matching that gnutls_x509_crt_check_hostname() from
359 * GnuTLS 1.2.0 uses.
360 * It conforms to RFC2595 (Using TLS with IMAP, POP3 and ACAP), section 2.4.
361 * RFC2818 (HTTP over TLS), section 3.1 says that `f*.com matches foo.com'. This
362 * function does not allow that.
363 * RFC3207 (SMTP Service Extension for Secure SMTP over Transport Layer
364 * Security), section 4.1 says nothing more than `A SMTP client would probably
365 * only want to authenticate an SMTP server whose server certificate has a
366 * domain name that is the domain name that the client thought it was connecting
367 * to'.
368 */
369
hostname_match(const char * hostname,const char * certname)370 static int hostname_match(const char *hostname, const char *certname)
371 {
372 const char *cmp1, *cmp2;
373
374 if (strncmp(certname, "*.", 2) == 0)
375 {
376 cmp1 = certname + 2;
377 cmp2 = strchr(hostname, '.');
378 if (!cmp2)
379 {
380 return 0;
381 }
382 else
383 {
384 cmp2++;
385 }
386 }
387 else
388 {
389 cmp1 = certname;
390 cmp2 = hostname;
391 }
392
393 if (*cmp1 == '\0' || *cmp2 == '\0')
394 {
395 return 0;
396 }
397
398 if (strcasecmp(cmp1, cmp2) != 0)
399 {
400 return 0;
401 }
402
403 return 1;
404 }
405
406
407 /*
408 * mtls_check_cert()
409 *
410 * If the 'mtls->have_trust_file' flag is set, perform a real verification of
411 * the peer's certificate. If this succeeds, the connection can be considered
412 * secure.
413 * If one of the 'mtls->have_*_fingerprint' flags is
414 * set, compare the 'mtls->fingerprint' data with the peer certificate's
415 * fingerprint. If this succeeds, the connection can be considered secure.
416 * If none of these flags is set, perform only a few sanity checks of the
417 * peer's certificate. You cannot trust the connection when this succeeds.
418 * Used error codes: TLS_ECERT
419 */
420
mtls_check_cert(mtls_t * mtls,char ** errstr)421 static int mtls_check_cert(mtls_t *mtls, char **errstr)
422 {
423 X509 *x509cert;
424 long status;
425 const char *error_msg;
426 int i;
427 /* hostname in ASCII format: */
428 char *idn_hostname = NULL;
429 /* needed to get the common name: */
430 X509_NAME *x509_subject;
431 char *buf;
432 int length;
433 /* needed to get the DNS subjectAltNames: */
434 void *subj_alt_names;
435 int subj_alt_names_count;
436 GENERAL_NAME *subj_alt_name;
437 /* did we find a name matching hostname? */
438 int match_found;
439 /* needed for fingerprint checking */
440 unsigned int usize;
441 unsigned char fingerprint[32];
442
443
444 if (mtls->have_trust_file)
445 {
446 error_msg = _("TLS certificate verification failed");
447 }
448 else
449 {
450 error_msg = _("TLS certificate check failed");
451 }
452
453 /* Get certificate */
454 if (!(x509cert = SSL_get_peer_certificate(mtls->internals->ssl)))
455 {
456 *errstr = xasprintf(_("%s: no certificate was sent"), error_msg);
457 return TLS_ECERT;
458 }
459
460 if (mtls->have_sha256_fingerprint
461 || mtls->have_sha1_fingerprint || mtls->have_md5_fingerprint)
462 {
463 /* If one of these matches, we trust the peer and do not perform any
464 * other checks. */
465 if (mtls->have_sha256_fingerprint)
466 {
467 usize = 32;
468 if (!X509_digest(x509cert, EVP_sha256(), fingerprint, &usize))
469 {
470 *errstr = xasprintf(_("%s: error getting SHA256 fingerprint"),
471 error_msg);
472 X509_free(x509cert);
473 return TLS_ECERT;
474 }
475 if (memcmp(fingerprint, mtls->fingerprint, 32) != 0)
476 {
477 *errstr = xasprintf(_("%s: the certificate fingerprint "
478 "does not match"), error_msg);
479 X509_free(x509cert);
480 return TLS_ECERT;
481 }
482 }
483 else if (mtls->have_sha1_fingerprint)
484 {
485 usize = 20;
486 if (!X509_digest(x509cert, EVP_sha1(), fingerprint, &usize))
487 {
488 *errstr = xasprintf(_("%s: error getting SHA1 fingerprint"),
489 error_msg);
490 X509_free(x509cert);
491 return TLS_ECERT;
492 }
493 if (memcmp(fingerprint, mtls->fingerprint, 20) != 0)
494 {
495 *errstr = xasprintf(_("%s: the certificate fingerprint "
496 "does not match"), error_msg);
497 X509_free(x509cert);
498 return TLS_ECERT;
499 }
500 }
501 else
502 {
503 usize = 16;
504 if (!X509_digest(x509cert, EVP_md5(), fingerprint, &usize))
505 {
506 *errstr = xasprintf(_("%s: error getting MD5 fingerprint"),
507 error_msg);
508 X509_free(x509cert);
509 return TLS_ECERT;
510 }
511 if (memcmp(fingerprint, mtls->fingerprint, 16) != 0)
512 {
513 *errstr = xasprintf(_("%s: the certificate fingerprint "
514 "does not match"), error_msg);
515 X509_free(x509cert);
516 return TLS_ECERT;
517 }
518 }
519 X509_free(x509cert);
520 return TLS_EOK;
521 }
522
523 /* Get result of OpenSSL's default verify function */
524 if ((status = SSL_get_verify_result(mtls->internals->ssl)) != X509_V_OK)
525 {
526 if (mtls->have_trust_file
527 || (status != X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
528 && status != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
529 && status != X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN))
530 {
531 *errstr = xasprintf("%s: %s", error_msg,
532 X509_verify_cert_error_string(status));
533 X509_free(x509cert);
534 return TLS_ECERT;
535 }
536 }
537
538 /* Check if 'hostname' matches the one of the subjectAltName extensions of
539 * type DNS or the Common Name (CN). */
540
541 #ifdef HAVE_LIBIDN
542 idn2_to_ascii_lz(mtls->hostname, &idn_hostname, IDN2_NFC_INPUT | IDN2_NONTRANSITIONAL);
543 #endif
544
545 /* Try the DNS subjectAltNames. */
546 match_found = 0;
547 if ((subj_alt_names =
548 X509_get_ext_d2i(x509cert, NID_subject_alt_name, NULL, NULL)))
549 {
550 subj_alt_names_count = sk_GENERAL_NAME_num(subj_alt_names);
551 for (i = 0; i < subj_alt_names_count; i++)
552 {
553 subj_alt_name = sk_GENERAL_NAME_value(subj_alt_names, i);
554 if (subj_alt_name->type == GEN_DNS)
555 {
556 if ((size_t)(subj_alt_name->d.ia5->length)
557 != strlen((char *)(subj_alt_name->d.ia5->data)))
558 {
559 *errstr = xasprintf(_("%s: certificate subject "
560 "alternative name contains NUL"), error_msg);
561 X509_free(x509cert);
562 free(idn_hostname);
563 return TLS_ECERT;
564 }
565 if ((match_found = hostname_match(
566 idn_hostname ? idn_hostname : mtls->hostname,
567 (char *)(subj_alt_name->d.ia5->data))))
568 {
569 break;
570 }
571 }
572 }
573 }
574 if (!match_found)
575 {
576 /* Try the common name */
577 if (!(x509_subject = X509_get_subject_name(x509cert)))
578 {
579 *errstr = xasprintf(_("%s: cannot get certificate subject"),
580 error_msg);
581 X509_free(x509cert);
582 free(idn_hostname);
583 return TLS_ECERT;
584 }
585 length = X509_NAME_get_text_by_NID(x509_subject, NID_commonName,
586 NULL, 0);
587 buf = xmalloc((size_t)length + 1);
588 if (X509_NAME_get_text_by_NID(x509_subject, NID_commonName,
589 buf, length + 1) == -1)
590 {
591 *errstr = xasprintf(_("%s: cannot get certificate common name"),
592 error_msg);
593 X509_free(x509cert);
594 free(idn_hostname);
595 free(buf);
596 return TLS_ECERT;
597 }
598 if ((size_t)length != strlen(buf))
599 {
600 *errstr = xasprintf(_("%s: certificate common name contains NUL"),
601 error_msg);
602 X509_free(x509cert);
603 free(idn_hostname);
604 free(buf);
605 return TLS_ECERT;
606 }
607 match_found = hostname_match(idn_hostname ? idn_hostname : mtls->hostname,
608 buf);
609 free(buf);
610 }
611 X509_free(x509cert);
612 free(idn_hostname);
613
614 if (!match_found)
615 {
616 *errstr = xasprintf(
617 _("%s: the certificate owner does not match hostname %s"),
618 error_msg, mtls->hostname);
619 return TLS_ECERT;
620 }
621
622 return TLS_EOK;
623 }
624
625
626 /*
627 * mtls_init()
628 *
629 * see mtls.h
630 */
631
mtls_init(mtls_t * mtls,const char * key_file,const char * cert_file,const char * pin,const char * trust_file,const char * crl_file,const unsigned char * sha256_fingerprint,const unsigned char * sha1_fingerprint,const unsigned char * md5_fingerprint,int min_dh_prime_bits,const char * priorities,const char * hostname,int no_certcheck,char ** errstr)632 int mtls_init(mtls_t *mtls,
633 const char *key_file, const char *cert_file, const char *pin,
634 const char *trust_file, const char *crl_file,
635 const unsigned char *sha256_fingerprint,
636 const unsigned char *sha1_fingerprint,
637 const unsigned char *md5_fingerprint,
638 int min_dh_prime_bits, const char *priorities,
639 const char *hostname,
640 int no_certcheck,
641 char **errstr)
642 {
643 const SSL_METHOD *ssl_method = SSLv23_client_method();
644
645 /* FIXME: Implement support for 'min_dh_prime_bits' */
646 if (min_dh_prime_bits >= 0)
647 {
648 *errstr = xasprintf(
649 _("cannot set minimum number of DH prime bits for TLS: %s"),
650 _("feature not yet implemented for OpenSSL"));
651 return TLS_ELIBFAILED;
652 }
653 /* FIXME: Implement support for 'priorities' */
654 if (priorities)
655 {
656 *errstr = xasprintf(
657 _("cannot set priorities for TLS session: %s"),
658 _("feature not yet implemented for OpenSSL"));
659 return TLS_ELIBFAILED;
660 }
661 /* FIXME: Implement support for 'crl_file' */
662 if (trust_file && crl_file)
663 {
664 *errstr = xasprintf(
665 _("cannot load CRL file: %s"),
666 _("feature not yet implemented for OpenSSL"));
667 return TLS_ELIBFAILED;
668 }
669
670 if (!ssl_method)
671 {
672 *errstr = xasprintf(_("cannot set TLS method"));
673 return TLS_ELIBFAILED;
674 }
675
676 mtls->internals = xmalloc(sizeof(struct mtls_internals_t));
677
678 if (!(mtls->internals->ssl_ctx = SSL_CTX_new(ssl_method)))
679 {
680 *errstr = xasprintf(_("cannot create TLS context: %s"),
681 ERR_error_string(ERR_get_error(), NULL));
682 free(mtls->internals);
683 mtls->internals = NULL;
684 return TLS_ELIBFAILED;
685 }
686 /* SSLv2 and SSLv3 have known flaws. Disable them. */
687 (void)SSL_CTX_set_options(mtls->internals->ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
688 if (key_file && cert_file)
689 {
690 if (SSL_CTX_use_PrivateKey_file(
691 mtls->internals->ssl_ctx, key_file, SSL_FILETYPE_PEM) != 1)
692 {
693 *errstr = xasprintf(_("cannot load key file %s: %s"),
694 key_file, ERR_error_string(ERR_get_error(), NULL));
695 SSL_CTX_free(mtls->internals->ssl_ctx);
696 free(mtls->internals);
697 mtls->internals = NULL;
698 return TLS_EFILE;
699 }
700 if (SSL_CTX_use_certificate_chain_file(mtls->internals->ssl_ctx, cert_file) != 1)
701 {
702 *errstr = xasprintf(_("cannot load certificate file %s: %s"),
703 cert_file, ERR_error_string(ERR_get_error(), NULL));
704 SSL_CTX_free(mtls->internals->ssl_ctx);
705 free(mtls->internals);
706 mtls->internals = NULL;
707 return TLS_EFILE;
708 }
709 }
710 if (trust_file
711 && !no_certcheck
712 && !sha256_fingerprint
713 && !sha1_fingerprint
714 && !md5_fingerprint)
715 {
716 if (strcmp(trust_file, "system") == 0)
717 {
718 if (SSL_CTX_set_default_verify_paths(mtls->internals->ssl_ctx) != 1)
719 {
720 *errstr = xasprintf(_("cannot set X509 system trust for TLS session: %s"),
721 ERR_error_string(ERR_get_error(), NULL));
722 SSL_CTX_free(mtls->internals->ssl_ctx);
723 free(mtls->internals);
724 mtls->internals = NULL;
725 return TLS_EFILE;
726 }
727 }
728 else
729 {
730 if (SSL_CTX_load_verify_locations(mtls->internals->ssl_ctx, trust_file, NULL) != 1)
731 {
732 *errstr = xasprintf(_("cannot load trust file %s: %s"),
733 trust_file, ERR_error_string(ERR_get_error(), NULL));
734 SSL_CTX_free(mtls->internals->ssl_ctx);
735 free(mtls->internals);
736 mtls->internals = NULL;
737 return TLS_EFILE;
738 }
739 }
740 mtls->have_trust_file = 1;
741 }
742 if (sha256_fingerprint && !no_certcheck)
743 {
744 memcpy(mtls->fingerprint, sha256_fingerprint, 32);
745 mtls->have_sha256_fingerprint = 1;
746 }
747 else if (sha1_fingerprint && !no_certcheck)
748 {
749 memcpy(mtls->fingerprint, sha1_fingerprint, 20);
750 mtls->have_sha1_fingerprint = 1;
751 }
752 else if (md5_fingerprint && !no_certcheck)
753 {
754 memcpy(mtls->fingerprint, md5_fingerprint, 16);
755 mtls->have_md5_fingerprint = 1;
756 }
757 if (!(mtls->internals->ssl = SSL_new(mtls->internals->ssl_ctx)))
758 {
759 *errstr = xasprintf(_("cannot create a TLS structure: %s"),
760 ERR_error_string(ERR_get_error(), NULL));
761 SSL_CTX_free(mtls->internals->ssl_ctx);
762 free(mtls->internals);
763 mtls->internals = NULL;
764 return TLS_ELIBFAILED;
765 }
766 mtls->no_certcheck = no_certcheck;
767 mtls->hostname = xstrdup(hostname);
768 return TLS_EOK;
769 }
770
771
772 /*
773 * openssl_io_error()
774 *
775 * Used only internally by the OpenSSL code.
776 *
777 * Construct an error line according to 'error_code' (which originates from an
778 * SSL_read(), SSL_write() or SSL_connect() operation) and 'error_code2' (which
779 * originates from an SSL_get_error() call with 'error_code' as its argument).
780 * The line will read: "error_string: error_reason". 'error_string' is given by
781 * the calling function, this function finds out 'error_reason'.
782 * The resulting string will be returned in an allocated string.
783 * OpenSSL error strings are max 120 characters long according to
784 * ERR_error_string(3).
785 */
786
openssl_io_error(int error_code,int error_code2,const char * error_string)787 static char *openssl_io_error(int error_code, int error_code2,
788 const char *error_string)
789 {
790 unsigned long error_code3;
791 const char *error_reason;
792
793 switch (error_code2)
794 {
795 case SSL_ERROR_SYSCALL:
796 error_code3 = ERR_get_error();
797 if (error_code3 == 0)
798 {
799 if (error_code == 0)
800 {
801 error_reason = _("a protocol violating EOF occurred");
802 }
803 else if (error_code == -1)
804 {
805 error_reason = strerror(errno);
806 }
807 else
808 {
809 error_reason = _("unknown error");
810 }
811 }
812 else
813 {
814 error_reason = ERR_error_string(error_code3, NULL);
815 }
816 break;
817
818 case SSL_ERROR_ZERO_RETURN:
819 error_reason = _("the connection was closed unexpectedly");
820 break;
821
822 case SSL_ERROR_SSL:
823 error_reason = ERR_error_string(ERR_get_error(), NULL);
824 break;
825
826 case SSL_ERROR_WANT_READ:
827 case SSL_ERROR_WANT_WRITE:
828 error_reason = _("the operation timed out");
829 break;
830
831 default:
832 /* probably SSL_ERROR_NONE */
833 error_reason = _("unknown error");
834 break;
835 }
836 return xasprintf("%s: %s", error_string, error_reason);
837 }
838
839
840 /*
841 * mtls_start()
842 *
843 * see mtls.h
844 */
845
mtls_start(mtls_t * mtls,int fd,mtls_cert_info_t * tci,char ** mtls_parameter_description,char ** errstr)846 int mtls_start(mtls_t *mtls, int fd,
847 mtls_cert_info_t *tci, char **mtls_parameter_description, char **errstr)
848 {
849 int error_code;
850
851 if (!SSL_set_fd(mtls->internals->ssl, fd))
852 {
853 *errstr = xasprintf(_("cannot set the file descriptor for TLS: %s"),
854 ERR_error_string(ERR_get_error(), NULL));
855 SSL_free(mtls->internals->ssl);
856 SSL_CTX_free(mtls->internals->ssl_ctx);
857 return TLS_ELIBFAILED;
858 }
859 if ((error_code = SSL_connect(mtls->internals->ssl)) < 1)
860 {
861 if (errno == EINTR
862 && (SSL_get_error(mtls->internals->ssl, error_code) == SSL_ERROR_WANT_READ
863 || SSL_get_error(mtls->internals->ssl, error_code)
864 == SSL_ERROR_WANT_WRITE))
865 {
866 *errstr = xasprintf(_("operation aborted"));
867 }
868 else
869 {
870 *errstr = openssl_io_error(error_code,
871 SSL_get_error(mtls->internals->ssl, error_code),
872 _("TLS handshake failed"));
873 }
874 SSL_free(mtls->internals->ssl);
875 SSL_CTX_free(mtls->internals->ssl_ctx);
876 return TLS_EIO;
877 }
878 if (tci)
879 {
880 if ((error_code = mtls_cert_info_get(mtls, tci, errstr)) != TLS_EOK)
881 {
882 SSL_free(mtls->internals->ssl);
883 SSL_CTX_free(mtls->internals->ssl_ctx);
884 return error_code;
885 }
886 }
887 if (mtls_parameter_description)
888 {
889 *mtls_parameter_description = NULL; /* TODO */
890 }
891 if (!mtls->no_certcheck)
892 {
893 if ((error_code = mtls_check_cert(mtls, errstr)) != TLS_EOK)
894 {
895 SSL_free(mtls->internals->ssl);
896 SSL_CTX_free(mtls->internals->ssl_ctx);
897 return error_code;
898 }
899 }
900 mtls->is_active = 1;
901 return TLS_EOK;
902 }
903
904
905 /*
906 * mtls_readbuf_read()
907 *
908 * Wraps TLS read function to provide buffering for mtls_gets().
909 */
910
mtls_readbuf_read(mtls_t * mtls,readbuf_t * readbuf,char * ptr,char ** errstr)911 int mtls_readbuf_read(mtls_t *mtls, readbuf_t *readbuf, char *ptr,
912 char **errstr)
913 {
914 int ret;
915 int error_code;
916
917 if (readbuf->count <= 0)
918 {
919 ret = SSL_read(mtls->internals->ssl, readbuf->buf, sizeof(readbuf->buf));
920 if (ret < 1)
921 {
922 if ((error_code = SSL_get_error(mtls->internals->ssl, ret)) == SSL_ERROR_NONE)
923 {
924 return 0;
925 }
926 else
927 {
928 if (errno == EINTR
929 && (SSL_get_error(mtls->internals->ssl, ret) == SSL_ERROR_WANT_READ
930 || SSL_get_error(mtls->internals->ssl, ret)
931 == SSL_ERROR_WANT_WRITE))
932 {
933 *errstr = xasprintf(_("operation aborted"));
934 }
935 else
936 {
937 *errstr = openssl_io_error(ret, error_code,
938 _("cannot read from TLS connection"));
939 }
940 return TLS_EIO;
941 }
942 }
943 readbuf->count = ret;
944 readbuf->ptr = readbuf->buf;
945 }
946 readbuf->count--;
947 *ptr = *((readbuf->ptr)++);
948 return 1;
949 }
950
951
952 /*
953 * mtls_puts()
954 *
955 * see mtls.h
956 */
957
mtls_puts(mtls_t * mtls,const char * s,size_t len,char ** errstr)958 int mtls_puts(mtls_t *mtls, const char *s, size_t len, char **errstr)
959 {
960 int error_code;
961
962 if (len < 1)
963 {
964 /* nothing to be done */
965 return TLS_EOK;
966 }
967
968 if ((error_code = SSL_write(mtls->internals->ssl, s, (int)len)) != (int)len)
969 {
970 if (errno == EINTR
971 && ((SSL_get_error(mtls->internals->ssl, error_code) == SSL_ERROR_WANT_READ
972 || SSL_get_error(mtls->internals->ssl, error_code)
973 == SSL_ERROR_WANT_WRITE)))
974 {
975 *errstr = xasprintf(_("operation aborted"));
976 }
977 else
978 {
979 *errstr = openssl_io_error(error_code,
980 SSL_get_error(mtls->internals->ssl, error_code),
981 _("cannot write to TLS connection"));
982 }
983 return TLS_EIO;
984 }
985
986 return TLS_EOK;
987 }
988
989
990 /*
991 * mtls_close()
992 *
993 * see mtls.h
994 */
995
mtls_close(mtls_t * mtls)996 void mtls_close(mtls_t *mtls)
997 {
998 if (mtls->is_active)
999 {
1000 SSL_shutdown(mtls->internals->ssl);
1001 SSL_free(mtls->internals->ssl);
1002 SSL_CTX_free(mtls->internals->ssl_ctx);
1003 }
1004 free(mtls->internals);
1005 mtls->internals = NULL;
1006 if (mtls->hostname)
1007 {
1008 free(mtls->hostname);
1009 }
1010 mtls_clear(mtls);
1011 }
1012
1013
1014 /*
1015 * mtls_lib_deinit()
1016 *
1017 * see mtls.h
1018 */
1019
mtls_lib_deinit(void)1020 void mtls_lib_deinit(void)
1021 {
1022 }
1023