Dillo v3.1.1-46-g8a360e32
Loading...
Searching...
No Matches
tls_mbedtls.c
Go to the documentation of this file.
1/*
2 * File: tls_mbedtls.c
3 *
4 * Copyright (C) 2011 Benjamin Johnson <obeythepenguin@users.sourceforge.net>
5 * (for the https code offered from dplus browser that formed the basis...)
6 * Copyright 2016 corvid
7 * Copyright (C) 2023-2024 Rodrigo Arias Mallo <rodarima@gmail.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
13 */
14
15/*
16 * https://www.ssllabs.com/ssltest/viewMyClient.html
17 * https://badssl.com
18 *
19 * Using TLS in Applications: https://datatracker.ietf.org/wg/uta/documents/
20 * TLS: https://datatracker.ietf.org/wg/tls/documents/
21 */
22
23#include "config.h"
24#include "../msg.h"
25
26#ifndef ENABLE_TLS
27# error "ENABLE_TLS not defined"
28#endif
29
30#include <assert.h>
31#include <errno.h>
32
33#include "../../dlib/dlib.h"
34#include "../dialog.hh"
35#include "../klist.h"
36#include "iowatch.hh"
37#include "tls.h"
38#include "Url.h"
39
40#include <mbedtls/platform.h> /* WORKAROUND: mbed TLS 2.3.0 ssl.h needs it */
41#include <mbedtls/ssl.h>
42#include <mbedtls/ctr_drbg.h> /* random number generator */
43#include <mbedtls/entropy.h>
44#include <mbedtls/error.h>
45#include <mbedtls/oid.h>
46#include <mbedtls/x509.h>
47#include <mbedtls/version.h>
48#if MBEDTLS_VERSION_NUMBER < 0x03000000
49#include <mbedtls/net.h> /* net_send, net_recv */
50#else
51#include <mbedtls/net_sockets.h> /* net_send, net_recv */
52#endif
53
54#define CERT_STATUS_NONE 0
55#define CERT_STATUS_RECEIVING 1
56#define CERT_STATUS_CLEAN 2
57#define CERT_STATUS_BAD 3
58#define CERT_STATUS_USER_ACCEPTED 4
59
60typedef struct {
61 char *hostname;
62 int port;
63 int cert_status;
64} Server_t;
65
66typedef struct {
67 char *name;
69} CertAuth_t;
70
71typedef struct {
72 int fd;
73 int connkey;
74} FdMapEntry_t;
75
76/*
77 * Data type for TLS connection information
78 */
79typedef struct {
80 int fd;
81 DilloUrl *url;
82 mbedtls_ssl_context *ssl;
83 bool_t connecting;
84} Conn_t;
85
86/* List of active TLS connections */
87static Klist_t *conn_list = NULL;
88
90static mbedtls_ssl_config ssl_conf;
91static mbedtls_x509_crt cacerts;
92static mbedtls_ctr_drbg_context ctr_drbg;
93static mbedtls_entropy_context entropy;
94
95static Dlist *servers;
97static Dlist *fd_map;
98
99static void Tls_handshake_cb(int fd, void *vconnkey);
100
101
102#if MBEDTLS_VERSION_NUMBER >= 0x03060000
103/* Moved to ssl_ciphersuites_internal.h in mbedtls 3.6.0 */
104int mbedtls_ssl_ciphersuite_uses_psk(const mbedtls_ssl_ciphersuite_t *info);
105#endif
106
107/*
108 * Compare by FD.
109 */
110static int Tls_fd_map_cmp(const void *v1, const void *v2)
111{
112 int fd = VOIDP2INT(v2);
113 const FdMapEntry_t *e = v1;
114
115 return (fd != e->fd);
116}
117
118static void Tls_fd_map_add_entry(int fd, int connkey)
119{
120 FdMapEntry_t *e = dNew0(FdMapEntry_t, 1);
121 e->fd = fd;
122 e->connkey = connkey;
123
125 MSG_ERR("TLS FD ENTRY ALREADY FOUND FOR %d\n", e->fd);
126 assert(0);
127 }
128
130//MSG("ADD ENTRY %d %s\n", e->fd, URL_STR(sd->url));
131}
132
133/*
134 * Remove and free entry from fd_map.
135 */
136static void Tls_fd_map_remove_entry(int fd)
137{
139
140//MSG("REMOVE ENTRY %d\n", fd);
141 if (data) {
143 dFree(data);
144 } else {
145 MSG("TLS FD ENTRY NOT FOUND FOR %d\n", fd);
146 }
147}
148
149/*
150 * Return TLS connection information for a given file
151 * descriptor, or NULL if no TLS connection was found.
152 */
154{
155 Conn_t *conn;
156
157 if (fd_map) {
158 FdMapEntry_t *fme = dList_find_custom(fd_map, INT2VOIDP(fd),
160
161 if (fme && (conn = a_Klist_get_data(conn_list, fme->connkey)))
162 return conn;
163 }
164 return NULL;
165}
166
167/*
168 * Add a new TLS connection information node.
169 */
170static Conn_t *Tls_conn_new(int fd, const DilloUrl *url,
171 mbedtls_ssl_context *ssl)
172{
173 Conn_t *conn = dNew0(Conn_t, 1);
174 conn->fd = fd;
175 conn->url = a_Url_dup(url);
176 conn->ssl = ssl;
177 conn->connecting = TRUE;
178 return conn;
179}
180
181static int Tls_make_conn_key(Conn_t *conn)
182{
183 int key = a_Klist_insert(&conn_list, conn);
184
185 Tls_fd_map_add_entry(conn->fd, key);
186
187 return key;
188}
189
190/*
191 * Load certificates from a given filename.
192 */
193static void Tls_load_certificates_from_file(const char *const filename)
194{
195 int ret = mbedtls_x509_crt_parse_file(&cacerts, filename);
196
197 if (ret < 0) {
198 if (ret == MBEDTLS_ERR_PK_FILE_IO_ERROR) {
199 /* can't read from file */
200 } else {
201 MSG("Failed to parse certificates from %s (returned -0x%04x)\n",
202 filename, -ret);
203 }
204 }
205}
206
207/*
208 * Load certificates from a given pathname.
209 */
210static void Tls_load_certificates_from_path(const char *const pathname)
211{
212 int ret = mbedtls_x509_crt_parse_path(&cacerts, pathname);
213
214 if (ret < 0) {
215 if (ret == MBEDTLS_ERR_X509_FILE_IO_ERROR) {
216 /* can't read from path */
217 } else {
218 MSG("Failed to parse certificates from %s (returned -0x%04x)\n",
219 pathname, -ret);
220 }
221 }
222}
223
224/*
225 * Remove duplicate certificates.
226 */
228{
229 mbedtls_x509_crt *cp, *curr = &cacerts;
230
231 while (curr) {
232 cp = curr;
233 while (cp->next) {
234 if (curr->serial.len == cp->next->serial.len &&
235 !memcmp(curr->serial.p, cp->next->serial.p, curr->serial.len) &&
236 curr->subject_raw.len == cp->next->subject_raw.len &&
237 !memcmp(curr->subject_raw.p, cp->next->subject_raw.p,
238 curr->subject_raw.len)) {
239 mbedtls_x509_crt *duplicate = cp->next;
240
241 cp->next = duplicate->next;
242
243 /* clearing the next field prevents it from freeing the whole
244 * chain of certificates
245 */
246 duplicate->next = NULL;
247 mbedtls_x509_crt_free(duplicate);
248 dFree(duplicate);
249 } else {
250 cp = cp->next;
251 }
252 }
253 curr = curr->next;
254 }
255}
256
257/*
258 * Load trusted certificates.
259 */
261{
262 /* curl-7.37.1 says that the following bundle locations are used on "Debian
263 * systems", "Redhat and Mandriva", "old(er) Redhat", "FreeBSD", and
264 * "OpenBSD", respectively -- and that the /etc/ssl/certs/ path is needed on
265 * "SUSE". No doubt it's all changed some over time, but this gives us
266 * something to work with.
267 */
268 uint_t u;
269 char *userpath;
270 mbedtls_x509_crt *curr;
271
272 static const char *const ca_files[] = {
273 "/etc/ssl/certs/ca-certificates.crt",
274 "/etc/pki/tls/certs/ca-bundle.crt",
275 "/usr/share/ssl/certs/ca-bundle.crt",
276 "/usr/local/share/certs/ca-root.crt",
277 "/etc/ssl/cert.pem",
278 CA_CERTS_FILE
279 };
280
281 static const char *const ca_paths[] = {
282 "/etc/ssl/certs/",
283 CA_CERTS_DIR
284 };
285
286 for (u = 0; u < sizeof(ca_files)/sizeof(ca_files[0]); u++) {
287 if (*ca_files[u])
289 }
290
291 for (u = 0; u < sizeof(ca_paths)/sizeof(ca_paths[0]); u++) {
292 if (*ca_paths[u]) {
294 }
295 }
296
297 userpath = dStrconcat(dGethomedir(), "/.dillo/certs/", NULL);
299 dFree(userpath);
300
302
303 /* Count our trusted certificates */
304 u = 0;
305 if (cacerts.next) {
306 u++;
307 for (curr = cacerts.next; curr; curr = curr->next)
308 u++;
309 } else {
310 mbedtls_x509_crt empty;
311 mbedtls_x509_crt_init(&empty);
312
313 if (memcmp(&cacerts, &empty, sizeof(mbedtls_x509_crt)))
314 u++;
315 }
316
317 MSG("Trusting %u TLS certificate%s.\n", u, u==1 ? "" : "s");
318}
319
320/*
321 * Remove the pre-shared key ciphersuites. There are lots of them,
322 * and we aren't making any use of them.
323 */
325{
326 const mbedtls_ssl_ciphersuite_t *cs_info;
327 int *our_ciphers, *q;
328 int n = 0;
329
330 const int *default_ciphers = mbedtls_ssl_list_ciphersuites(),
331 *p = default_ciphers;
332
333 /* count how many we will want */
334 while (*p) {
335 cs_info = mbedtls_ssl_ciphersuite_from_id(*p);
336 if (!mbedtls_ssl_ciphersuite_uses_psk(cs_info))
337 n++;
338 p++;
339 }
340 n++;
341 our_ciphers = dNew(int, n);
342
343 /* iterate through again and copy them over */
344 p = default_ciphers;
345 q = our_ciphers;
346 while (*p) {
347 cs_info = mbedtls_ssl_ciphersuite_from_id(*p);
348
349 if (!mbedtls_ssl_ciphersuite_uses_psk(cs_info))
350 *q++ = *p;
351 p++;
352 }
353 *q = 0;
354
355 mbedtls_ssl_conf_ciphersuites(&ssl_conf, our_ciphers);
356}
357
358/*
359 * Initialize the mbed TLS library.
360 */
362{
363 int ret;
364 char version[128];
365 mbedtls_version_get_string_full(version);
366 MSG("TLS library: %s\n", version);
367
368 /* As of 2.3.0 in 2016, the 'default' profile allows SHA1, RIPEMD160,
369 * and SHA224 (in addition to the stronger ones), and the 'next' profile
370 * doesn't allow anything below SHA256. Since we're never going to hear
371 * when/if RIPEMD160 and SHA224 are deprecated, and they're obscure enough
372 * not to encounter, let's not allow those.
373 * These profiles are for certificates, and mbed tls points out that these
374 * have nothing to do with hashes during handshakes.
375 * Their 'next' profile only allows "Curves at or above 128-bit security
376 * level". For now, we follow 'default' and allow all curves.
377 */
378 static const mbedtls_x509_crt_profile prof = {
379 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) |
380 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
381 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) |
382 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ),
383 0xFFFFFFF, /* Any PK alg */
384 0xFFFFFFF, /* Any curve */
385 2048,
386 };
387
388 mbedtls_ssl_config_init(&ssl_conf);
389
390 mbedtls_ssl_config_defaults(&ssl_conf, MBEDTLS_SSL_IS_CLIENT,
391 MBEDTLS_SSL_TRANSPORT_STREAM,
392 MBEDTLS_SSL_PRESET_DEFAULT);
393 mbedtls_ssl_conf_cert_profile(&ssl_conf, &prof);
394
395 /*
396 * TLSv1.3 brings some changes, among them, having to call
397 * psa_crypto_init(), and a new way of resuming sessions,
398 * which is not currently supported by the code here.
399 */
400#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
401 mbedtls_ssl_conf_max_tls_version(&ssl_conf, MBEDTLS_SSL_VERSION_TLS1_2);
402#endif
403
404 /*
405 * There are security concerns surrounding session tickets --
406 * wrecking forward security, for instance.
407 */
408 mbedtls_ssl_conf_session_tickets(&ssl_conf,
409 MBEDTLS_SSL_SESSION_TICKETS_DISABLED);
410
412
413 mbedtls_x509_crt_init(&cacerts); /* trusted root certificates */
414 mbedtls_ctr_drbg_init(&ctr_drbg); /* Counter mode Deterministic Random Byte
415 * Generator */
416 mbedtls_entropy_init(&entropy);
417
418 if((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
419 (unsigned char*)"dillo tls", 9))) {
421 MSG_ERR("tls: mbedtls_ctr_drbg_seed() failed. TLS disabled.\n");
422 return;
423 }
424
425 mbedtls_ssl_conf_authmode(&ssl_conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
426 mbedtls_ssl_conf_ca_chain(&ssl_conf, &cacerts, NULL);
427 mbedtls_ssl_conf_rng(&ssl_conf, mbedtls_ctr_drbg_random, &ctr_drbg);
428
429 fd_map = dList_new(20);
430 servers = dList_new(8);
432
434}
435
436/*
437 * Ordered comparison of servers.
438 */
439static int Tls_servers_cmp(const void *v1, const void *v2)
440{
441 const Server_t *s1 = (const Server_t *)v1, *s2 = (const Server_t *)v2;
442 int cmp = dStrAsciiCasecmp(s1->hostname, s2->hostname);
443
444 if (!cmp)
445 cmp = s1->port - s2->port;
446 return cmp;
447}
448/*
449 * Ordered comparison of server with URL.
450 */
451static int Tls_servers_by_url_cmp(const void *v1, const void *v2)
452{
453 const Server_t *s = (const Server_t *)v1;
454 const DilloUrl *url = (const DilloUrl *)v2;
455
456 int cmp = dStrAsciiCasecmp(s->hostname, URL_HOST(url));
457
458 if (!cmp)
459 cmp = s->port - URL_PORT(url);
460 return cmp;
461}
462
463/*
464 * The purpose here is to permit a single initial connection to a server.
465 * Once we have the certificate, know whether we like it -- and whether the
466 * user accepts it -- HTTP can run through queued sockets as normal.
467 *
468 * Return: TLS_CONNECT_READY or TLS_CONNECT_NOT_YET or TLS_CONNECT_NEVER.
469 */
471{
472 Server_t *s;
473 int ret = TLS_CONNECT_READY;
474
476
478 if (s->cert_status == CERT_STATUS_RECEIVING)
480 else if (s->cert_status == CERT_STATUS_BAD)
481 ret = TLS_CONNECT_NEVER;
482
483 if (s->cert_status == CERT_STATUS_NONE)
484 s->cert_status = CERT_STATUS_RECEIVING;
485 } else {
486 s = dNew(Server_t, 1);
487
488 s->hostname = dStrdup(URL_HOST(url));
489 s->port = URL_PORT(url);
490 s->cert_status = CERT_STATUS_RECEIVING;
492 }
493 return ret;
494}
495
496static int Tls_cert_status(const DilloUrl *url)
497{
499
500 return s ? s->cert_status : CERT_STATUS_NONE;
501}
502
503/*
504 * Did we find problems with the certificate, and did the user proceed to
505 * reject the connection?
506 */
507static int Tls_user_said_no(const DilloUrl *url)
508{
509 return Tls_cert_status(url) == CERT_STATUS_BAD;
510}
511
512/*
513 * Did everything seem proper with the certificate -- no warnings to
514 * click through?
515 */
520
521#if 0
522/*
523 * Print certificate and its chain of issuer certificates.
524 */
525static void Tls_print_cert_chain(const mbedtls_x509_crt *cert)
526{
527 /* print for first connection to server */
528 const mbedtls_x509_crt *last_cert;
529 const uint_t buflen = 2048;
530 char buf[buflen];
531 int key_bits;
532 const char *sigalg;
533
534 while (cert) {
535 if (cert->sig_md == MBEDTLS_MD_SHA1) {
536 MSG_WARN("In 2015, browsers have begun to deprecate SHA1 "
537 "certificates.\n");
538 }
539
540 if (mbedtls_oid_get_sig_alg_desc(&cert->sig_oid, &sigalg))
541 sigalg = "(??" ")";
542
543 key_bits = mbedtls_pk_get_bitlen(&cert->pk);
544 mbedtls_x509_dn_gets(buf, buflen, &cert->subject);
545 MSG("%d-bit %s: %s\n", key_bits, sigalg, buf);
546
547 last_cert = cert;
548 cert = cert->next;
549 }
550 if (last_cert) {
551 mbedtls_x509_dn_gets(buf, buflen, &last_cert->issuer);
552 MSG("root: %s\n", buf);
553 }
554}
555#endif
556
557/*
558 * Generate dialog msg for expired cert.
559 */
560static void Tls_cert_expired(const mbedtls_x509_crt *cert, Dstr *ds)
561{
562 const mbedtls_x509_time *date = &cert->valid_to;
563
564 dStr_sprintfa(ds,"Certificate expired at: %04d/%02d/%02d %02d:%02d:%02d.\n",
565 date->year, date->mon, date->day, date->hour, date->min,
566 date->sec);
567}
568
569/*
570 * Generate dialog msg when certificate is not for this host.
571 */
572static void Tls_cert_cn_mismatch(const mbedtls_x509_crt *cert, Dstr *ds)
573{
574 const uint_t buflen = 2048;
575 char cert_info_buf[buflen];
576 char *san, *s;
577
578 dStr_append(ds, "This host is not one of the hostnames listed on the TLS "
579 "certificate that it sent");
580 /*
581 *
582 * Taking the human-readable certificate info and scraping it is brittle
583 * and horrible, but the alternative is to mimic
584 * x509_info_subject_alt_name(), an option that seems equally brittle and
585 * horrible.
586 *
587 * Once I find a case where SAN isn't used, I can add code to work with
588 * the subject field as well.
589 *
590 */
591 mbedtls_x509_crt_info(cert_info_buf, buflen, "", cert);
592
593 if ((san = strstr(cert_info_buf, "subject alt name : "))) {
594 san += 20;
595 s = strchr(san, '\n');
596 if (s) {
597 *s = '\0';
598 dStr_sprintfa(ds, " (%s)", san);
599 }
600 }
601 dStr_append(ds, ".\n");
602}
603
604/*
605 * Generate dialog msg when certificate is not trusted.
606 */
607static void Tls_cert_trust_chain_failed(const mbedtls_x509_crt *cert, Dstr *ds)
608{
609 const uint_t buflen = 2048;
610 char buf[buflen];
611
612 while (cert->next)
613 cert = cert->next;
614 mbedtls_x509_dn_gets(buf, buflen, &cert->issuer);
615
616 dStr_sprintfa(ds, "Couldn't reach any trusted root certificate from "
617 "supplied certificate. The issuer at the end of the "
618 "chain was: \"%s\"\n", buf);
619}
620
621/*
622 * Generate dialog msg when certificate start date is in the future.
623 */
624static void Tls_cert_not_valid_yet(const mbedtls_x509_crt *cert, Dstr *ds)
625{
626 const mbedtls_x509_time *date = &cert->valid_to;
627
628 dStr_sprintfa(ds, "Certificate validity begins in the future at: "
629 "%04d/%02d/%02d %02d:%02d:%02d.\n",
630 date->year, date->mon, date->day, date->hour, date->min,
631 date->sec);
632}
633
634/*
635 * Generate dialog msg when certificate hash algorithm is not accepted.
636 */
637static void Tls_cert_bad_hash(const mbedtls_x509_crt *cert, Dstr *ds)
638{
639#if MBEDTLS_VERSION_NUMBER < 0x03000000
640 mbedtls_md_type_t md = cert->sig_md;
641#else
642 mbedtls_md_type_t md = cert->MBEDTLS_PRIVATE(sig_md);
643#endif
644 const char *hash = (md == MBEDTLS_MD_MD5) ? "MD5" :
645 (md == MBEDTLS_MD_SHA1) ? "SHA1" :
646 (md == MBEDTLS_MD_SHA224) ? "SHA224" :
647 (md == MBEDTLS_MD_RIPEMD160) ? "RIPEMD160" :
648 (md == MBEDTLS_MD_SHA256) ? "SHA256" :
649 (md == MBEDTLS_MD_SHA384) ? "SHA384" :
650 (md == MBEDTLS_MD_SHA512) ? "SHA512" :
651#if MBEDTLS_VERSION_NUMBER < 0x03000000
652/* In version 3, these are removed: */
653 (md == MBEDTLS_MD_MD4) ? "MD4" :
654 (md == MBEDTLS_MD_MD2) ? "MD2" :
655#endif
656 "Unrecognized";
657
658 dStr_sprintfa(ds, "This certificate's hash algorithm is not accepted "
659 "(%s).\n", hash);
660}
661
662/*
663 * Generate dialog msg when public key algorithm (RSA, ECDSA) is not accepted.
664 */
665static void Tls_cert_bad_pk_alg(const mbedtls_x509_crt *cert, Dstr *ds)
666{
667 const char *type_str = mbedtls_pk_get_name(&cert->pk);
668
669 dStr_sprintfa(ds, "This certificate's public key algorithm is not accepted "
670 "(%s).\n", type_str);
671}
672
673/*
674 * Generate dialog msg when the public key is not acceptable. As of 2016,
675 * this was triggered by RSA keys below 2048 bits, if I recall correctly.
676 */
677static void Tls_cert_bad_key(const mbedtls_x509_crt *cert, Dstr *ds) {
678 int key_bits = mbedtls_pk_get_bitlen(&cert->pk);
679 const char *type_str = mbedtls_pk_get_name(&cert->pk);
680
681 dStr_sprintfa(ds, "This certificate's key is not accepted, which generally "
682 "means it's too weak (%d-bit %s).\n", key_bits, type_str);
683}
684
685/*
686 * Make a dialog msg containing warnings about problems with the certificate.
687 */
688static char *Tls_make_bad_cert_msg(const mbedtls_x509_crt *cert,uint32_t flags)
689{
690 static const struct certerr {
691 int val;
692 void (*cert_err_fn)(const mbedtls_x509_crt *cert, Dstr *ds);
693 } cert_error [] = {
694 { MBEDTLS_X509_BADCERT_EXPIRED, Tls_cert_expired},
695 { MBEDTLS_X509_BADCERT_CN_MISMATCH, Tls_cert_cn_mismatch},
696 { MBEDTLS_X509_BADCERT_NOT_TRUSTED, Tls_cert_trust_chain_failed},
697 { MBEDTLS_X509_BADCERT_FUTURE, Tls_cert_not_valid_yet},
698 { MBEDTLS_X509_BADCERT_BAD_MD, Tls_cert_bad_hash},
699 { MBEDTLS_X509_BADCERT_BAD_PK, Tls_cert_bad_pk_alg},
700 { MBEDTLS_X509_BADCERT_BAD_KEY, Tls_cert_bad_key}
701 };
702 const uint_t ncert_errors = sizeof(cert_error) /sizeof(cert_error[0]);
703 char *ret;
704 Dstr *ds = dStr_new(NULL);
705 uint_t u;
706
707 for (u = 0; u < ncert_errors; u++) {
708 if (flags & cert_error[u].val) {
709 flags &= ~cert_error[u].val;
710 cert_error[u].cert_err_fn(cert, ds);
711 }
712 }
713 if (flags)
714 dStr_sprintfa(ds, "Unknown certificate error(s): flag value 0x%04x",
715 flags);
716 ret = ds->str;
717 dStr_free(ds, 0);
718 return ret;
719}
720
721static int Tls_cert_auth_cmp(const void *v1, const void *v2)
722{
723 const CertAuth_t *c1 = (CertAuth_t *)v1, *c2 = (CertAuth_t *)v2;
724
725 return strcmp(c1->name, c2->name);
726}
727
728static int Tls_cert_auth_cmp_by_name(const void *v1, const void *v2)
729{
730 const CertAuth_t *c = (CertAuth_t *)v1;
731 const char *name = (char *)v2;
732
733 return strcmp(c->name, name);
734}
735
736/*
737 * Keep account of on whose authority we are trusting servers.
738 */
739static void Tls_update_cert_authorities_data(const mbedtls_x509_crt *cert,
740 Server_t *srv)
741{
742 const uint_t buflen = 512;
743 char buf[buflen];
744 const mbedtls_x509_crt *last = cert;
745
746 while (last->next)
747 last = last->next;
748
749 mbedtls_x509_dn_gets(buf, buflen, &last->issuer);
750
751 CertAuth_t *ca = dList_find_custom(cert_authorities, buf,
753 if (!ca) {
754 ca = dNew(CertAuth_t, 1);
755 ca->name = dStrdup(buf);
756 ca->servers = dList_new(8);
758 }
759 dList_append(ca->servers, srv);
760}
761
762/*
763 * Examine the certificate, and, if problems are detected, ask the user what
764 * to do.
765 * Return: -1 if connection should be canceled, or 0 if it should continue.
766 */
767static int Tls_examine_certificate(mbedtls_ssl_context *ssl, Server_t *srv)
768{
769 const mbedtls_x509_crt *cert;
770 uint32_t st;
771 int choice = -1, ret = -1;
772 char *title = dStrconcat("Dillo TLS security warning: ",srv->hostname,NULL);
773
774 cert = mbedtls_ssl_get_peer_cert(ssl);
775 if (cert == NULL){
776 /* Inform user that remote system cannot be trusted */
777 choice = a_Dialog_choice(title,
778 "No certificate received from this site. Can't verify who it is.",
779 "Continue", "Cancel", NULL);
780
781 /* Abort on anything but "Continue" */
782 if (choice == 1){
783 ret = 0;
784 }
785 } else {
786 /* check the certificate */
787 st = mbedtls_ssl_get_verify_result(ssl);
788 if (st == 0) {
789 if (srv->cert_status == CERT_STATUS_RECEIVING) {
790 /* first connection to server */
791#if 0
792 Tls_print_cert_chain(cert);
793#endif
795 }
796 ret = 0;
797 } else if (st == 0xFFFFFFFF) {
798 /* "result is not available (eg because the handshake was aborted too
799 * early)" is what the documentation says. Maybe it's only what
800 * happens if you call get_verify_result() too early or when the
801 * handshake failed. But just in case...
802 */
803 MSG_ERR("mbedtls_ssl_get_verify_result: result is not available");
804 } else {
805 char *dialog_warning_msg = Tls_make_bad_cert_msg(cert, st);
806
807 choice = a_Dialog_choice(title, dialog_warning_msg, "Continue",
808 "Cancel", NULL);
809 if (choice == 1) {
810 ret = 0;
811 }
812 dFree(dialog_warning_msg);
813 }
814 }
815 dFree(title);
816
817 if (choice == -1) {
818 srv->cert_status = CERT_STATUS_CLEAN; /* no warning popups */
819 } else if (choice == 1) {
820 srv->cert_status = CERT_STATUS_USER_ACCEPTED; /* clicked Continue */
821 } else {
822 /* 2 for Cancel, or 0 when window closed. */
823 srv->cert_status = CERT_STATUS_BAD;
824 }
825 return ret;
826}
827
828/*
829 * If the connection was closed before we got the certificate, we need to
830 * reset state so that we'll try again.
831 */
833{
834 if (servers) {
836
837 if (s && s->cert_status == CERT_STATUS_RECEIVING)
838 s->cert_status = CERT_STATUS_NONE;
839 }
840}
841
842/*
843 * Close an open TLS connection.
844 */
845static void Tls_close_by_key(int connkey)
846{
847 Conn_t *c;
848
849 if ((c = a_Klist_get_data(conn_list, connkey))) {
851 if (c->connecting) {
852 a_IOwatch_remove_fd(c->fd, -1);
853 dClose(c->fd);
854 }
855 mbedtls_ssl_close_notify(c->ssl);
856 mbedtls_ssl_free(c->ssl);
857 dFree(c->ssl);
858
859 a_Url_free(c->url);
861 a_Klist_remove(conn_list, connkey);
862 dFree(c);
863 }
864}
865
866/*
867 * Print a message about the fatal alert.
868 *
869 * The values have gaps, and a few are never fatal error values, and some may
870 * never be sent to clients, but let's go ahead and translate every value that
871 * we recognize.
872 */
873static void Tls_fatal_error_msg(int error_type)
874{
875 const char *errmsg;
876
877 if (error_type == MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY)
878 errmsg = "close notify";
879 else if (error_type == MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE)
880 errmsg = "unexpected message received";
881 else if (error_type == MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC)
882 errmsg = "record received with incorrect MAC";
883 else if (error_type == MBEDTLS_SSL_ALERT_MSG_DECRYPTION_FAILED) {
884 /* last used in TLS 1.1 */
885 errmsg = "decryption failed";
886 } else if (error_type == MBEDTLS_SSL_ALERT_MSG_RECORD_OVERFLOW)
887 errmsg = "\"A TLSCiphertext record was received that had a length more "
888 "than 2^14+2048 bytes, or a record decrypted to a TLSCompressed"
889 " record with more than 2^14+1024 bytes.\"";
890 else if (error_type == MBEDTLS_SSL_ALERT_MSG_DECOMPRESSION_FAILURE)
891 errmsg = "\"decompression function received improper input\"";
892 else if (error_type == MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE)
893 errmsg = "\"sender was unable to negotiate an acceptable set of security"
894 " parameters given the options available\"";
895 else if (error_type == MBEDTLS_SSL_ALERT_MSG_NO_CERT)
896 errmsg = "no cert (an obsolete alert last used in SSL3)";
897 else if (error_type == MBEDTLS_SSL_ALERT_MSG_BAD_CERT)
898 errmsg = "bad certificate";
899 else if (error_type == MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT)
900 errmsg = "certificate of unsupported type";
901 else if (error_type == MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED)
902 errmsg = "certificate revoked by its signer";
903 else if (error_type == MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED)
904 errmsg = "certificate expired or not currently valid";
905 else if (error_type == MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN)
906 errmsg = "certificate error of an unknown sort";
907 else if (error_type == MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER)
908 errmsg = "illegal parameter in handshake";
909 else if (error_type == MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA)
910 errmsg = "unknown CA";
911 else if (error_type == MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED)
912 errmsg = "access denied";
913 else if (error_type == MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR)
914 errmsg = "decode error";
915 else if (error_type == MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR)
916 errmsg = "decrypt error";
917 else if (error_type == MBEDTLS_SSL_ALERT_MSG_EXPORT_RESTRICTION) {
918 /* last used in TLS 1.0 */
919 errmsg = "export restriction";
920 } else if (error_type == MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION)
921 errmsg = "protocol version is recognized but not supported";
922 else if (error_type == MBEDTLS_SSL_ALERT_MSG_INSUFFICIENT_SECURITY)
923 errmsg = "server requires ciphers more secure than those supported by "
924 "the client";
925 else if (error_type == MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR)
926 errmsg = "internal error (not the client's fault)";
927 else if (error_type == MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK)
928 errmsg = "inappropriate fallback";
929 else if (error_type == MBEDTLS_SSL_ALERT_MSG_USER_CANCELED)
930 errmsg = "\"handshake is being canceled for some reason unrelated to a "
931 "protocol failure\"";
932 else if (error_type == MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION)
933 errmsg = "no renegotiation";
934 else if (error_type == MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT)
935 errmsg = "unsupported ext";
936 else if (error_type == MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME)
937 errmsg = "unrecognized name";
938 else if (error_type == MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY)
939 errmsg = "unknown psk identity";
940 else if (error_type == MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL)
941 errmsg = "no application protocol";
942 else errmsg = "unknown alert value";
943
944 MSG_WARN("mbedtls_ssl_handshake() received TLS fatal alert %d (%s)\n",
945 error_type, errmsg);
946}
947
948/*
949 * Connect, set a callback if it's still not completed. If completed, check
950 * the certificate and report back to http.
951 */
952static void Tls_handshake(int fd, int connkey)
953{
954 int ret;
955 bool_t ongoing = FALSE, failed = TRUE;
956 Conn_t *conn;
957
958 if (!(conn = a_Klist_get_data(conn_list, connkey))) {
959 MSG("Tls_connect: conn for fd %d not valid\n", fd);
960 return;
961 }
962
963#if MBEDTLS_VERSION_NUMBER < 0x03000000
964 int ssl_state = conn->ssl->state;
965#else
966 int ssl_state = conn->ssl->MBEDTLS_PRIVATE(state);
967#endif
968 if (ssl_state != MBEDTLS_SSL_HANDSHAKE_OVER) {
969 ret = mbedtls_ssl_handshake(conn->ssl);
970
971 if (ret == MBEDTLS_ERR_SSL_WANT_READ ||
972 ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
973 int want = ret == MBEDTLS_ERR_SSL_WANT_READ ? DIO_READ : DIO_WRITE;
974
975 _MSG("iowatching fd %d for tls -- want %s\n", fd,
976 ret == MBEDTLS_ERR_SSL_WANT_READ ? "read" : "write");
977 a_IOwatch_remove_fd(fd, -1);
978 a_IOwatch_add_fd(fd, want, Tls_handshake_cb, INT2VOIDP(connkey));
979 ongoing = TRUE;
980 failed = FALSE;
981 } else if (ret == 0) {
982 Server_t *srv = dList_find_sorted(servers, conn->url,
984
985 if (srv->cert_status == CERT_STATUS_RECEIVING) {
986 /* Making first connection with the server. Show cipher used. */
987 mbedtls_ssl_context *ssl = conn->ssl;
988 const char *version = mbedtls_ssl_get_version(ssl),
989 *cipher = mbedtls_ssl_get_ciphersuite(ssl);
990
991 MSG("%s", URL_AUTHORITY(conn->url));
992 if (URL_PORT(conn->url) != URL_HTTPS_PORT)
993 MSG(":%d", URL_PORT(conn->url));
994 MSG(" %s, cipher %s\n", version, cipher);
995 }
996 if (srv->cert_status == CERT_STATUS_USER_ACCEPTED ||
997 (Tls_examine_certificate(conn->ssl, srv) != -1)) {
998 failed = FALSE;
999 }
1000 } else if (ret == MBEDTLS_ERR_NET_SEND_FAILED) {
1001 MSG("mbedtls_ssl_handshake() send failed. Server may not be accepting"
1002 " connections.\n");
1003 } else if (ret == MBEDTLS_ERR_NET_CONNECT_FAILED) {
1004 MSG("mbedtls_ssl_handshake() connect failed.\n");
1005 } else if (ret == MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE) {
1006 /* Paul Bakker, the mbed tls guy, says "beware, this might change in
1007 * future versions" and "ssl->in_msg[1] is not going to change anytime
1008 * soon, unless there are radical changes". It seems to be the best of
1009 * the alternatives.
1010 */
1011#if MBEDTLS_VERSION_NUMBER < 0x03000000
1012 Tls_fatal_error_msg(conn->ssl->in_msg[1]);
1013#else
1014 Tls_fatal_error_msg(conn->ssl->MBEDTLS_PRIVATE(in_msg[1]));
1015#endif
1016 } else if (ret == MBEDTLS_ERR_SSL_INVALID_RECORD) {
1017 MSG("mbedtls_ssl_handshake() failed upon receiving 'an invalid "
1018 "record'.\n");
1019 } else if (ret == MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE) {
1020 MSG("mbedtls_ssl_handshake() failed: 'The requested feature is not "
1021 "available.'\n");
1022#if MBEDTLS_VERSION_NUMBER < 0x03000000
1023 } else if (ret == MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE) {
1024 MSG("mbedtls_ssl_handshake() failed: 'Processing of the "
1025 "ServerKeyExchange handshake message failed.'\n");
1026#endif
1027 } else if (ret == MBEDTLS_ERR_SSL_CONN_EOF) {
1028 MSG("mbedtls_ssl_handshake() failed: Read EOF. Connection closed by "
1029 "server.\n");
1030 } else {
1031 MSG("mbedtls_ssl_handshake() failed with error -0x%04x\n", -ret);
1032 }
1033 }
1034
1035 /*
1036 * If there were problems with the certificate, the connection may have
1037 * been closed by the server if the user responded too slowly to a popup.
1038 */
1039
1040 if (!ongoing) {
1041 if (a_Klist_get_data(conn_list, connkey)) {
1042 conn->connecting = FALSE;
1043 if (failed) {
1044 Tls_close_by_key(connkey);
1045 }
1046 a_IOwatch_remove_fd(fd, -1);
1048 } else {
1049 MSG("Connection disappeared. Too long with a popup popped up?\n");
1050 }
1051 }
1052}
1053
1054static void Tls_handshake_cb(int fd, void *vconnkey)
1055{
1056 Tls_handshake(fd, VOIDP2INT(vconnkey));
1057}
1058
1059/*
1060 * Make TLS connection over a connect()ed socket.
1061 */
1062void a_Tls_mbedtls_connect(int fd, const DilloUrl *url)
1063{
1064 mbedtls_ssl_context *ssl = dNew0(mbedtls_ssl_context, 1);
1065 bool_t success = TRUE;
1066 int connkey = -1;
1067 int ret;
1068
1069 if (!ssl_enabled)
1070 success = FALSE;
1071
1072 if (success && Tls_user_said_no(url)) {
1073 success = FALSE;
1074 }
1075
1076 if (success && (ret = mbedtls_ssl_setup(ssl, &ssl_conf))) {
1077 MSG("mbedtls_ssl_setup failed %d\n", ret);
1078 success = FALSE;
1079 }
1080
1081 /* assign TLS connection to this file descriptor */
1082 if (success) {
1083 Conn_t *conn = Tls_conn_new(fd, url, ssl);
1084 connkey = Tls_make_conn_key(conn);
1085 mbedtls_ssl_set_bio(ssl, &conn->fd, mbedtls_net_send, mbedtls_net_recv,
1086 NULL);
1087 }
1088
1089 if (success && (ret = mbedtls_ssl_set_hostname(ssl, URL_HOST(url)))) {
1090 MSG("mbedtls_ssl_set_hostname failed %d\n", ret);
1091 success = FALSE;
1092 }
1093
1094 if (!success) {
1096 a_Http_connect_done(fd, success);
1097 } else {
1098 Tls_handshake(fd, connkey);
1099 }
1100}
1101
1102/*
1103 * Read data from an open TLS connection.
1104 */
1105int a_Tls_mbedtls_read(void *conn, void *buf, size_t len)
1106{
1107 Conn_t *c = (Conn_t*)conn;
1108 int ret = mbedtls_ssl_read(c->ssl, buf, len);
1109
1110 if (ret < 0) {
1111 if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) {
1112 /* treat it as EOF */
1113 ret = 0;
1114 } else if (ret == MBEDTLS_ERR_SSL_WANT_READ) {
1115 ret = -1;
1116 errno = EAGAIN; /* already happens to be set, but let's make sure */
1117 } else if (ret == MBEDTLS_ERR_NET_CONN_RESET) {
1118 MSG("READ failed: TLS connection reset by server.\n");
1119 } else {
1120 MSG("READ failed with -0x%04x: an mbed tls error.\n", -ret);
1121 }
1122 }
1123 return ret;
1124}
1125
1126/*
1127 * Write data to an open TLS connection.
1128 */
1129int a_Tls_mbedtls_write(void *conn, void *buf, size_t len)
1130{
1131 Conn_t *c = (Conn_t*)conn;
1132 int ret = mbedtls_ssl_write(c->ssl, buf, len);
1133
1134 if (ret < 0) {
1135 MSG("WRITE failed with -0x%04x: an mbed tls error\n", -ret);
1136 }
1137 return ret;
1138}
1139
1141{
1142 FdMapEntry_t *fme = dList_find_custom(fd_map, INT2VOIDP(fd),
1144
1145 if (fme) {
1146 Tls_close_by_key(fme->connkey);
1147 }
1148}
1149
1151{
1152 const int ca_len = dList_length(cert_authorities);
1153 Dstr *ds = dStr_new("");
1154 int i, j;
1155
1156 if (ca_len)
1157 dStr_append(ds, "TLS: Certificate chain roots during this session:\n");
1158
1159 for (i = 0; i < ca_len; i++) {
1160 CertAuth_t *ca = (CertAuth_t *)dList_nth_data(cert_authorities, i);
1161 const int servers_len = ca->servers ? dList_length(ca->servers) : 0;
1162 char *ca_name = strstr(ca->name, "CN=");
1163
1164 if (!ca_name)
1165 ca_name = strstr(ca->name, "OU=");
1166
1167 if (ca_name)
1168 ca_name += 3;
1169 else
1170 ca_name = ca->name;
1171 dStr_sprintfa(ds, "- %s for: ", ca_name);
1172
1173 for (j = 0; j < servers_len; j++) {
1174 Server_t *s = dList_nth_data(ca->servers, j);
1175 bool_t ipv6 = a_Url_host_type(s->hostname) == URL_HOST_IPV6;
1176
1177 dStr_sprintfa(ds, "%s%s%s", ipv6?"[":"", s->hostname, ipv6?"]":"");
1178 if (s->port != URL_HTTPS_PORT)
1179 dStr_sprintfa(ds, ":%d", s->port);
1180 dStr_append_c(ds, ' ');
1181 }
1182 dStr_append_c(ds, '\n');
1183 }
1184 MSG("%s", ds->str);
1185 dStr_free(ds, 1);
1186}
1187
1188/*
1189 * Free mbed tls's chain of certificates and free our data on which root
1190 * certificates caused us to trust which servers.
1191 */
1193{
1194 if (cacerts.next)
1195 mbedtls_x509_crt_free(cacerts.next);
1196
1197 if (cert_authorities) {
1198 CertAuth_t *ca;
1199 int i, n = dList_length(cert_authorities);
1200
1201 for (i = 0; i < n; i++) {
1202 ca = (CertAuth_t *) dList_nth_data(cert_authorities, i);
1203 dFree(ca->name);
1204 if (ca->servers)
1205 dList_free(ca->servers);
1206 dFree(ca);
1207 }
1209 }
1210}
1211
1213{
1214 if (servers) {
1215 Server_t *s;
1216 int i, n = dList_length(servers);
1217
1218 for (i = 0; i < n; i++) {
1219 s = (Server_t *) dList_nth_data(servers, i);
1220 dFree(s->hostname);
1221 dFree(s);
1222 }
1224 }
1225}
1226
1228{
1229 if (fd_map) {
1230 FdMapEntry_t *fme;
1231 int i, n = dList_length(fd_map);
1232
1233 for (i = 0; i < n; i++) {
1234 fme = (FdMapEntry_t *) dList_nth_data(fd_map, i);
1235 dFree(fme);
1236 }
1238 }
1239}
1240
1241/*
1242 * Clean up
1243 */
#define _MSG(...)
Definition bookmarks.c:45
#define MSG(...)
Definition bookmarks.c:46
unsigned int uint_t
Definition d_size.h:20
unsigned char bool_t
Definition d_size.h:21
int a_Dialog_choice(const char *title, const char *msg,...)
Make a question-dialog with a question and alternatives.
Definition dialog.cc:341
char * dStrconcat(const char *s1,...)
Concatenate a NULL-terminated list of strings.
Definition dlib.c:102
void dList_insert_sorted(Dlist *lp, void *data, dCompareFunc func)
Insert an element into a sorted list.
Definition dlib.c:769
void dFree(void *mem)
Definition dlib.c:68
int dStrAsciiCasecmp(const char *s1, const char *s2)
Definition dlib.c:203
void dStr_sprintfa(Dstr *ds, const char *format,...)
Printf-like function that appends.
Definition dlib.c:464
void dStr_append(Dstr *ds, const char *s)
Append a C string to a Dstr.
Definition dlib.c:316
char * dStrdup(const char *s)
Definition dlib.c:77
Dlist * dList_new(int size)
Create a new empty list.
Definition dlib.c:548
int dList_length(Dlist *lp)
For completing the ADT.
Definition dlib.c:613
void * dList_nth_data(Dlist *lp, int n0)
Return the nth data item, NULL when not found or 'n0' is out of range.
Definition dlib.c:662
void dList_remove_fast(Dlist *lp, const void *data)
Remove a data item without preserving order.
Definition dlib.c:623
void dStr_free(Dstr *ds, int all)
Free a dillo string.
Definition dlib.c:337
int dClose(int fd)
Close a FD handling EINTR.
Definition dlib.c:951
void dStr_append_c(Dstr *ds, int c)
Append one character.
Definition dlib.c:349
Dstr * dStr_new(const char *s)
Create a new string.
Definition dlib.c:325
void dList_append(Dlist *lp, void *data)
Append a data item to the list.
Definition dlib.c:597
void * dList_find_sorted(Dlist *lp, const void *data, dCompareFunc func)
Search a sorted list.
Definition dlib.c:796
void dList_free(Dlist *lp)
Free a list (not its elements)
Definition dlib.c:564
void * dList_find_custom(Dlist *lp, const void *data, dCompareFunc func)
Search a data item using a custom function.
Definition dlib.c:704
char * dGethomedir(void)
Return the home directory in a static string (don't free)
Definition dlib.c:906
#define dNew0(type, count)
Definition dlib.h:51
#define dReturn_val_if_fail(expr, val)
Definition dlib.h:76
#define VOIDP2INT(p)
Definition dlib.h:43
#define TRUE
Definition dlib.h:23
#define FALSE
Definition dlib.h:19
#define INT2VOIDP(i)
Definition dlib.h:44
#define dNew(type, count)
Definition dlib.h:49
void errmsg(char *caller, char *called, int errornum, char *file, int line)
Definition dpid_common.c:20
#define MSG_ERR(...)
Definition dpid_common.h:23
void a_Http_connect_done(int fd, bool_t success)
Definition http.c:214
void a_IOwatch_add_fd(int fd, int when, Fl_FD_Handler Callback, void *usr_data=0)
Hook a Callback for a certain activities in a FD.
Definition iowatch.cc:22
void a_IOwatch_remove_fd(int fd, int when)
Remove a Callback for a given FD (or just remove some events)
Definition iowatch.cc:32
#define DIO_READ
Definition iowatch.hh:7
#define DIO_WRITE
Definition iowatch.hh:8
void a_Klist_remove(Klist_t *Klist, int Key)
Remove data by Key.
Definition klist.c:86
void * a_Klist_get_data(Klist_t *Klist, int Key)
Return the data pointer for a given Key (or NULL if not found)
Definition klist.c:43
int a_Klist_insert(Klist_t **Klist, void *Data)
Insert a data pointer and return a key for it.
Definition klist.c:56
#define MSG_WARN(...)
Definition msg.h:26
DilloPrefs prefs
Global Data.
Definition prefs.c:33
bool_t show_msg
Definition prefs.h:117
Definition url.h:88
Definition dlib.h:131
Definition dlib.h:102
Dstr_char_t * str
Definition dlib.h:105
static uint_t failed
Definition cookies.c:54
#define TLS_CONNECT_NEVER
Definition tls.h:30
#define TLS_CONNECT_READY
Definition tls.h:32
#define TLS_CONNECT_NOT_YET
Definition tls.h:31
static void Tls_cert_authorities_print_summary()
int a_Tls_mbedtls_certificate_is_clean(const DilloUrl *url)
static Dlist * fd_map
Definition tls_mbedtls.c:97
static mbedtls_x509_crt cacerts
Definition tls_mbedtls.c:91
static void Tls_load_certificates_from_file(const char *const filename)
static void Tls_fd_map_remove_entry(int fd)
void * a_Tls_mbedtls_connection(int fd)
static void Tls_servers_freeall()
void a_Tls_mbedtls_init(void)
static void Tls_cert_bad_hash(const mbedtls_x509_crt *cert, Dstr *ds)
static int Tls_servers_cmp(const void *v1, const void *v2)
static Conn_t * Tls_conn_new(int fd, const DilloUrl *url, mbedtls_ssl_context *ssl)
static int Tls_cert_auth_cmp(const void *v1, const void *v2)
static void Tls_load_certificates_from_path(const char *const pathname)
static void Tls_handshake(int fd, int connkey)
void a_Tls_mbedtls_reset_server_state(const DilloUrl *url)
void a_Tls_mbedtls_freeall(void)
#define CERT_STATUS_USER_ACCEPTED
Definition tls_mbedtls.c:58
static void Tls_fd_map_add_entry(int fd, int connkey)
static void Tls_remove_psk_ciphersuites()
#define CERT_STATUS_BAD
Definition tls_mbedtls.c:57
static int Tls_fd_map_cmp(const void *v1, const void *v2)
static void Tls_load_certificates()
static int Tls_user_said_no(const DilloUrl *url)
static void Tls_cert_expired(const mbedtls_x509_crt *cert, Dstr *ds)
void a_Tls_mbedtls_close_by_fd(int fd)
static void Tls_handshake_cb(int fd, void *vconnkey)
static void Tls_close_by_key(int connkey)
int a_Tls_mbedtls_write(void *conn, void *buf, size_t len)
static void Tls_fatal_error_msg(int error_type)
#define CERT_STATUS_RECEIVING
Definition tls_mbedtls.c:55
static void Tls_cert_cn_mismatch(const mbedtls_x509_crt *cert, Dstr *ds)
#define CERT_STATUS_CLEAN
Definition tls_mbedtls.c:56
static mbedtls_ctr_drbg_context ctr_drbg
Definition tls_mbedtls.c:92
static Dlist * servers
Definition tls_mbedtls.c:95
static void Tls_cert_not_valid_yet(const mbedtls_x509_crt *cert, Dstr *ds)
static int Tls_servers_by_url_cmp(const void *v1, const void *v2)
static int Tls_cert_auth_cmp_by_name(const void *v1, const void *v2)
static mbedtls_ssl_config ssl_conf
Definition tls_mbedtls.c:90
int a_Tls_mbedtls_read(void *conn, void *buf, size_t len)
static void Tls_cert_bad_key(const mbedtls_x509_crt *cert, Dstr *ds)
#define CERT_STATUS_NONE
Definition tls_mbedtls.c:54
static mbedtls_entropy_context entropy
Definition tls_mbedtls.c:93
static bool_t ssl_enabled
Definition tls_mbedtls.c:89
static void Tls_fd_map_remove_all()
int a_Tls_mbedtls_connect_ready(const DilloUrl *url)
static int Tls_cert_status(const DilloUrl *url)
static char * Tls_make_bad_cert_msg(const mbedtls_x509_crt *cert, uint32_t flags)
static Klist_t * conn_list
Definition tls_mbedtls.c:87
static void Tls_cert_trust_chain_failed(const mbedtls_x509_crt *cert, Dstr *ds)
static Dlist * cert_authorities
Definition tls_mbedtls.c:96
static int Tls_make_conn_key(Conn_t *conn)
void a_Tls_mbedtls_connect(int fd, const DilloUrl *url)
static void Tls_update_cert_authorities_data(const mbedtls_x509_crt *cert, Server_t *srv)
static void Tls_cert_authorities_freeall()
static void Tls_cert_bad_pk_alg(const mbedtls_x509_crt *cert, Dstr *ds)
static void Tls_remove_duplicate_certificates()
static int Tls_examine_certificate(mbedtls_ssl_context *ssl, Server_t *srv)
void a_Url_free(DilloUrl *url)
Free a DilloUrl.
Definition url.c:208
int a_Url_host_type(const char *host)
What type of host is this?
Definition url.c:683
DilloUrl * a_Url_dup(const DilloUrl *ori)
Duplicate a Url structure.
Definition url.c:477
#define URL_AUTHORITY(u)
Definition url.h:71
#define URL_HOST_IPV6
Definition url.h:26
#define URL_HTTPS_PORT
Definition url.h:20
#define URL_PORT(u)
Definition url.h:78
#define URL_HOST(u)
Definition url.h:75