Dillo v3.1.1-119-g140d9ebd
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
358const char *a_Tls_mbedtls_version(char *buf, int n)
359{
360 char ver[128]; /* Only 9 characters needed */
361 mbedtls_version_get_string(ver);
362
363 int k = snprintf(buf, n, "mbedTLS/%s", ver);
364 if (k >= n)
365 return "mbedTLS/?";
366 return buf;
367}
368
369/*
370 * Initialize the mbed TLS library.
371 */
373{
374 int ret;
375 char version[128];
376 mbedtls_version_get_string_full(version);
377 MSG("TLS library: %s\n", version);
378
379 /* As of 2.3.0 in 2016, the 'default' profile allows SHA1, RIPEMD160,
380 * and SHA224 (in addition to the stronger ones), and the 'next' profile
381 * doesn't allow anything below SHA256. Since we're never going to hear
382 * when/if RIPEMD160 and SHA224 are deprecated, and they're obscure enough
383 * not to encounter, let's not allow those.
384 * These profiles are for certificates, and mbed tls points out that these
385 * have nothing to do with hashes during handshakes.
386 * Their 'next' profile only allows "Curves at or above 128-bit security
387 * level". For now, we follow 'default' and allow all curves.
388 */
389 static const mbedtls_x509_crt_profile prof = {
390 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) |
391 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
392 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) |
393 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ),
394 0xFFFFFFF, /* Any PK alg */
395 0xFFFFFFF, /* Any curve */
396 2048,
397 };
398
399 mbedtls_ssl_config_init(&ssl_conf);
400
401 mbedtls_ssl_config_defaults(&ssl_conf, MBEDTLS_SSL_IS_CLIENT,
402 MBEDTLS_SSL_TRANSPORT_STREAM,
403 MBEDTLS_SSL_PRESET_DEFAULT);
404 mbedtls_ssl_conf_cert_profile(&ssl_conf, &prof);
405
406 /*
407 * TLSv1.3 brings some changes, among them, having to call
408 * psa_crypto_init(), and a new way of resuming sessions,
409 * which is not currently supported by the code here.
410 */
411#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
412 mbedtls_ssl_conf_max_tls_version(&ssl_conf, MBEDTLS_SSL_VERSION_TLS1_2);
413#endif
414
415 /*
416 * There are security concerns surrounding session tickets --
417 * wrecking forward security, for instance.
418 */
419 mbedtls_ssl_conf_session_tickets(&ssl_conf,
420 MBEDTLS_SSL_SESSION_TICKETS_DISABLED);
421
423
424 mbedtls_x509_crt_init(&cacerts); /* trusted root certificates */
425 mbedtls_ctr_drbg_init(&ctr_drbg); /* Counter mode Deterministic Random Byte
426 * Generator */
427 mbedtls_entropy_init(&entropy);
428
429 if((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
430 (unsigned char*)"dillo tls", 9))) {
432 MSG_ERR("tls: mbedtls_ctr_drbg_seed() failed. TLS disabled.\n");
433 return;
434 }
435
436 mbedtls_ssl_conf_authmode(&ssl_conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
437 mbedtls_ssl_conf_ca_chain(&ssl_conf, &cacerts, NULL);
438 mbedtls_ssl_conf_rng(&ssl_conf, mbedtls_ctr_drbg_random, &ctr_drbg);
439
440 fd_map = dList_new(20);
441 servers = dList_new(8);
443
445}
446
447/*
448 * Ordered comparison of servers.
449 */
450static int Tls_servers_cmp(const void *v1, const void *v2)
451{
452 const Server_t *s1 = (const Server_t *)v1, *s2 = (const Server_t *)v2;
453 int cmp = dStrAsciiCasecmp(s1->hostname, s2->hostname);
454
455 if (!cmp)
456 cmp = s1->port - s2->port;
457 return cmp;
458}
459/*
460 * Ordered comparison of server with URL.
461 */
462static int Tls_servers_by_url_cmp(const void *v1, const void *v2)
463{
464 const Server_t *s = (const Server_t *)v1;
465 const DilloUrl *url = (const DilloUrl *)v2;
466
467 int cmp = dStrAsciiCasecmp(s->hostname, URL_HOST(url));
468
469 if (!cmp)
470 cmp = s->port - URL_PORT(url);
471 return cmp;
472}
473
474/*
475 * The purpose here is to permit a single initial connection to a server.
476 * Once we have the certificate, know whether we like it -- and whether the
477 * user accepts it -- HTTP can run through queued sockets as normal.
478 *
479 * Return: TLS_CONNECT_READY or TLS_CONNECT_NOT_YET or TLS_CONNECT_NEVER.
480 */
482{
483 Server_t *s;
484 int ret = TLS_CONNECT_READY;
485
487
489 if (s->cert_status == CERT_STATUS_RECEIVING)
491 else if (s->cert_status == CERT_STATUS_BAD)
492 ret = TLS_CONNECT_NEVER;
493
494 if (s->cert_status == CERT_STATUS_NONE)
495 s->cert_status = CERT_STATUS_RECEIVING;
496 } else {
497 s = dNew(Server_t, 1);
498
499 s->hostname = dStrdup(URL_HOST(url));
500 s->port = URL_PORT(url);
501 s->cert_status = CERT_STATUS_RECEIVING;
503 }
504 return ret;
505}
506
507static int Tls_cert_status(const DilloUrl *url)
508{
510
511 return s ? s->cert_status : CERT_STATUS_NONE;
512}
513
514/*
515 * Did we find problems with the certificate, and did the user proceed to
516 * reject the connection?
517 */
518static int Tls_user_said_no(const DilloUrl *url)
519{
520 return Tls_cert_status(url) == CERT_STATUS_BAD;
521}
522
523/*
524 * Did everything seem proper with the certificate -- no warnings to
525 * click through?
526 */
531
532#if 0
533/*
534 * Print certificate and its chain of issuer certificates.
535 */
536static void Tls_print_cert_chain(const mbedtls_x509_crt *cert)
537{
538 /* print for first connection to server */
539 const mbedtls_x509_crt *last_cert;
540 const uint_t buflen = 2048;
541 char buf[buflen];
542 int key_bits;
543 const char *sigalg;
544
545 while (cert) {
546 if (cert->sig_md == MBEDTLS_MD_SHA1) {
547 MSG_WARN("In 2015, browsers have begun to deprecate SHA1 "
548 "certificates.\n");
549 }
550
551 if (mbedtls_oid_get_sig_alg_desc(&cert->sig_oid, &sigalg))
552 sigalg = "(??" ")";
553
554 key_bits = mbedtls_pk_get_bitlen(&cert->pk);
555 mbedtls_x509_dn_gets(buf, buflen, &cert->subject);
556 MSG("%d-bit %s: %s\n", key_bits, sigalg, buf);
557
558 last_cert = cert;
559 cert = cert->next;
560 }
561 if (last_cert) {
562 mbedtls_x509_dn_gets(buf, buflen, &last_cert->issuer);
563 MSG("root: %s\n", buf);
564 }
565}
566#endif
567
568/*
569 * Generate dialog msg for expired cert.
570 */
571static void Tls_cert_expired(const mbedtls_x509_crt *cert, Dstr *ds)
572{
573 const mbedtls_x509_time *date = &cert->valid_to;
574
575 dStr_sprintfa(ds,"Certificate expired at: %04d/%02d/%02d %02d:%02d:%02d.\n",
576 date->year, date->mon, date->day, date->hour, date->min,
577 date->sec);
578}
579
580/*
581 * Generate dialog msg when certificate is not for this host.
582 */
583static void Tls_cert_cn_mismatch(const mbedtls_x509_crt *cert, Dstr *ds)
584{
585 const uint_t buflen = 2048;
586 char cert_info_buf[buflen];
587 char *san, *s;
588
589 dStr_append(ds, "This host is not one of the hostnames listed on the TLS "
590 "certificate that it sent");
591 /*
592 *
593 * Taking the human-readable certificate info and scraping it is brittle
594 * and horrible, but the alternative is to mimic
595 * x509_info_subject_alt_name(), an option that seems equally brittle and
596 * horrible.
597 *
598 * Once I find a case where SAN isn't used, I can add code to work with
599 * the subject field as well.
600 *
601 */
602 mbedtls_x509_crt_info(cert_info_buf, buflen, "", cert);
603
604 if ((san = strstr(cert_info_buf, "subject alt name : "))) {
605 san += 20;
606 s = strchr(san, '\n');
607 if (s) {
608 *s = '\0';
609 dStr_sprintfa(ds, " (%s)", san);
610 }
611 }
612 dStr_append(ds, ".\n");
613}
614
615/*
616 * Generate dialog msg when certificate is not trusted.
617 */
618static void Tls_cert_trust_chain_failed(const mbedtls_x509_crt *cert, Dstr *ds)
619{
620 const uint_t buflen = 2048;
621 char buf[buflen];
622
623 while (cert->next)
624 cert = cert->next;
625 mbedtls_x509_dn_gets(buf, buflen, &cert->issuer);
626
627 dStr_sprintfa(ds, "Couldn't reach any trusted root certificate from "
628 "supplied certificate. The issuer at the end of the "
629 "chain was: \"%s\"\n", buf);
630}
631
632/*
633 * Generate dialog msg when certificate start date is in the future.
634 */
635static void Tls_cert_not_valid_yet(const mbedtls_x509_crt *cert, Dstr *ds)
636{
637 const mbedtls_x509_time *date = &cert->valid_to;
638
639 dStr_sprintfa(ds, "Certificate validity begins in the future at: "
640 "%04d/%02d/%02d %02d:%02d:%02d.\n",
641 date->year, date->mon, date->day, date->hour, date->min,
642 date->sec);
643}
644
645/*
646 * Generate dialog msg when certificate hash algorithm is not accepted.
647 */
648static void Tls_cert_bad_hash(const mbedtls_x509_crt *cert, Dstr *ds)
649{
650#if MBEDTLS_VERSION_NUMBER < 0x03000000
651 mbedtls_md_type_t md = cert->sig_md;
652#else
653 mbedtls_md_type_t md = cert->MBEDTLS_PRIVATE(sig_md);
654#endif
655 const char *hash = (md == MBEDTLS_MD_MD5) ? "MD5" :
656 (md == MBEDTLS_MD_SHA1) ? "SHA1" :
657 (md == MBEDTLS_MD_SHA224) ? "SHA224" :
658 (md == MBEDTLS_MD_RIPEMD160) ? "RIPEMD160" :
659 (md == MBEDTLS_MD_SHA256) ? "SHA256" :
660 (md == MBEDTLS_MD_SHA384) ? "SHA384" :
661 (md == MBEDTLS_MD_SHA512) ? "SHA512" :
662#if MBEDTLS_VERSION_NUMBER < 0x03000000
663/* In version 3, these are removed: */
664 (md == MBEDTLS_MD_MD4) ? "MD4" :
665 (md == MBEDTLS_MD_MD2) ? "MD2" :
666#endif
667 "Unrecognized";
668
669 dStr_sprintfa(ds, "This certificate's hash algorithm is not accepted "
670 "(%s).\n", hash);
671}
672
673/*
674 * Generate dialog msg when public key algorithm (RSA, ECDSA) is not accepted.
675 */
676static void Tls_cert_bad_pk_alg(const mbedtls_x509_crt *cert, Dstr *ds)
677{
678 const char *type_str = mbedtls_pk_get_name(&cert->pk);
679
680 dStr_sprintfa(ds, "This certificate's public key algorithm is not accepted "
681 "(%s).\n", type_str);
682}
683
684/*
685 * Generate dialog msg when the public key is not acceptable. As of 2016,
686 * this was triggered by RSA keys below 2048 bits, if I recall correctly.
687 */
688static void Tls_cert_bad_key(const mbedtls_x509_crt *cert, Dstr *ds) {
689 int key_bits = mbedtls_pk_get_bitlen(&cert->pk);
690 const char *type_str = mbedtls_pk_get_name(&cert->pk);
691
692 dStr_sprintfa(ds, "This certificate's key is not accepted, which generally "
693 "means it's too weak (%d-bit %s).\n", key_bits, type_str);
694}
695
696/*
697 * Make a dialog msg containing warnings about problems with the certificate.
698 */
699static char *Tls_make_bad_cert_msg(const mbedtls_x509_crt *cert,uint32_t flags)
700{
701 static const struct certerr {
702 int val;
703 void (*cert_err_fn)(const mbedtls_x509_crt *cert, Dstr *ds);
704 } cert_error [] = {
705 { MBEDTLS_X509_BADCERT_EXPIRED, Tls_cert_expired},
706 { MBEDTLS_X509_BADCERT_CN_MISMATCH, Tls_cert_cn_mismatch},
707 { MBEDTLS_X509_BADCERT_NOT_TRUSTED, Tls_cert_trust_chain_failed},
708 { MBEDTLS_X509_BADCERT_FUTURE, Tls_cert_not_valid_yet},
709 { MBEDTLS_X509_BADCERT_BAD_MD, Tls_cert_bad_hash},
710 { MBEDTLS_X509_BADCERT_BAD_PK, Tls_cert_bad_pk_alg},
711 { MBEDTLS_X509_BADCERT_BAD_KEY, Tls_cert_bad_key}
712 };
713 const uint_t ncert_errors = sizeof(cert_error) /sizeof(cert_error[0]);
714 char *ret;
715 Dstr *ds = dStr_new(NULL);
716 uint_t u;
717
718 for (u = 0; u < ncert_errors; u++) {
719 if (flags & cert_error[u].val) {
720 flags &= ~cert_error[u].val;
721 cert_error[u].cert_err_fn(cert, ds);
722 }
723 }
724 if (flags)
725 dStr_sprintfa(ds, "Unknown certificate error(s): flag value 0x%04x",
726 flags);
727 ret = ds->str;
728 dStr_free(ds, 0);
729 return ret;
730}
731
732static int Tls_cert_auth_cmp(const void *v1, const void *v2)
733{
734 const CertAuth_t *c1 = (CertAuth_t *)v1, *c2 = (CertAuth_t *)v2;
735
736 return strcmp(c1->name, c2->name);
737}
738
739static int Tls_cert_auth_cmp_by_name(const void *v1, const void *v2)
740{
741 const CertAuth_t *c = (CertAuth_t *)v1;
742 const char *name = (char *)v2;
743
744 return strcmp(c->name, name);
745}
746
747/*
748 * Keep account of on whose authority we are trusting servers.
749 */
750static void Tls_update_cert_authorities_data(const mbedtls_x509_crt *cert,
751 Server_t *srv)
752{
753 const uint_t buflen = 512;
754 char buf[buflen];
755 const mbedtls_x509_crt *last = cert;
756
757 while (last->next)
758 last = last->next;
759
760 mbedtls_x509_dn_gets(buf, buflen, &last->issuer);
761
762 CertAuth_t *ca = dList_find_custom(cert_authorities, buf,
764 if (!ca) {
765 ca = dNew(CertAuth_t, 1);
766 ca->name = dStrdup(buf);
767 ca->servers = dList_new(8);
769 }
770 dList_append(ca->servers, srv);
771}
772
773/*
774 * Examine the certificate, and, if problems are detected, ask the user what
775 * to do.
776 * Return: -1 if connection should be canceled, or 0 if it should continue.
777 */
778static int Tls_examine_certificate(mbedtls_ssl_context *ssl, Server_t *srv)
779{
780 const mbedtls_x509_crt *cert;
781 uint32_t st;
782 int choice = -1, ret = -1;
783 char *title = dStrconcat("Dillo TLS security warning: ",srv->hostname,NULL);
784
785 cert = mbedtls_ssl_get_peer_cert(ssl);
786 if (cert == NULL){
787 /* Inform user that remote system cannot be trusted */
788 choice = a_Dialog_choice(title,
789 "No certificate received from this site. Can't verify who it is.",
790 "Continue", "Cancel", NULL);
791
792 /* Abort on anything but "Continue" */
793 if (choice == 1){
794 ret = 0;
795 }
796 } else {
797 /* check the certificate */
798 st = mbedtls_ssl_get_verify_result(ssl);
799 if (st == 0) {
800 if (srv->cert_status == CERT_STATUS_RECEIVING) {
801 /* first connection to server */
802#if 0
803 Tls_print_cert_chain(cert);
804#endif
806 }
807 ret = 0;
808 } else if (st == 0xFFFFFFFF) {
809 /* "result is not available (eg because the handshake was aborted too
810 * early)" is what the documentation says. Maybe it's only what
811 * happens if you call get_verify_result() too early or when the
812 * handshake failed. But just in case...
813 */
814 MSG_ERR("mbedtls_ssl_get_verify_result: result is not available");
815 } else {
816 char *dialog_warning_msg = Tls_make_bad_cert_msg(cert, st);
817
818 choice = a_Dialog_choice(title, dialog_warning_msg, "Continue",
819 "Cancel", NULL);
820 if (choice == 1) {
821 ret = 0;
822 }
823 dFree(dialog_warning_msg);
824 }
825 }
826 dFree(title);
827
828 if (choice == -1) {
829 srv->cert_status = CERT_STATUS_CLEAN; /* no warning popups */
830 } else if (choice == 1) {
831 srv->cert_status = CERT_STATUS_USER_ACCEPTED; /* clicked Continue */
832 } else {
833 /* 2 for Cancel, or 0 when window closed. */
834 srv->cert_status = CERT_STATUS_BAD;
835 }
836 return ret;
837}
838
839/*
840 * If the connection was closed before we got the certificate, we need to
841 * reset state so that we'll try again.
842 */
844{
845 if (servers) {
847
848 if (s && s->cert_status == CERT_STATUS_RECEIVING)
849 s->cert_status = CERT_STATUS_NONE;
850 }
851}
852
853/*
854 * Close an open TLS connection.
855 */
856static void Tls_close_by_key(int connkey)
857{
858 Conn_t *c;
859
860 if ((c = a_Klist_get_data(conn_list, connkey))) {
862 if (c->connecting) {
863 a_IOwatch_remove_fd(c->fd, -1);
864 dClose(c->fd);
865 }
866 mbedtls_ssl_close_notify(c->ssl);
867 mbedtls_ssl_free(c->ssl);
868 dFree(c->ssl);
869
870 a_Url_free(c->url);
872 a_Klist_remove(conn_list, connkey);
873 dFree(c);
874 }
875}
876
877/*
878 * Print a message about the fatal alert.
879 *
880 * The values have gaps, and a few are never fatal error values, and some may
881 * never be sent to clients, but let's go ahead and translate every value that
882 * we recognize.
883 */
884static void Tls_fatal_error_msg(int error_type)
885{
886 const char *errmsg;
887
888 if (error_type == MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY)
889 errmsg = "close notify";
890 else if (error_type == MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE)
891 errmsg = "unexpected message received";
892 else if (error_type == MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC)
893 errmsg = "record received with incorrect MAC";
894 else if (error_type == MBEDTLS_SSL_ALERT_MSG_DECRYPTION_FAILED) {
895 /* last used in TLS 1.1 */
896 errmsg = "decryption failed";
897 } else if (error_type == MBEDTLS_SSL_ALERT_MSG_RECORD_OVERFLOW)
898 errmsg = "\"A TLSCiphertext record was received that had a length more "
899 "than 2^14+2048 bytes, or a record decrypted to a TLSCompressed"
900 " record with more than 2^14+1024 bytes.\"";
901 else if (error_type == MBEDTLS_SSL_ALERT_MSG_DECOMPRESSION_FAILURE)
902 errmsg = "\"decompression function received improper input\"";
903 else if (error_type == MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE)
904 errmsg = "\"sender was unable to negotiate an acceptable set of security"
905 " parameters given the options available\"";
906 else if (error_type == MBEDTLS_SSL_ALERT_MSG_NO_CERT)
907 errmsg = "no cert (an obsolete alert last used in SSL3)";
908 else if (error_type == MBEDTLS_SSL_ALERT_MSG_BAD_CERT)
909 errmsg = "bad certificate";
910 else if (error_type == MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT)
911 errmsg = "certificate of unsupported type";
912 else if (error_type == MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED)
913 errmsg = "certificate revoked by its signer";
914 else if (error_type == MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED)
915 errmsg = "certificate expired or not currently valid";
916 else if (error_type == MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN)
917 errmsg = "certificate error of an unknown sort";
918 else if (error_type == MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER)
919 errmsg = "illegal parameter in handshake";
920 else if (error_type == MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA)
921 errmsg = "unknown CA";
922 else if (error_type == MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED)
923 errmsg = "access denied";
924 else if (error_type == MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR)
925 errmsg = "decode error";
926 else if (error_type == MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR)
927 errmsg = "decrypt error";
928 else if (error_type == MBEDTLS_SSL_ALERT_MSG_EXPORT_RESTRICTION) {
929 /* last used in TLS 1.0 */
930 errmsg = "export restriction";
931 } else if (error_type == MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION)
932 errmsg = "protocol version is recognized but not supported";
933 else if (error_type == MBEDTLS_SSL_ALERT_MSG_INSUFFICIENT_SECURITY)
934 errmsg = "server requires ciphers more secure than those supported by "
935 "the client";
936 else if (error_type == MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR)
937 errmsg = "internal error (not the client's fault)";
938 else if (error_type == MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK)
939 errmsg = "inappropriate fallback";
940 else if (error_type == MBEDTLS_SSL_ALERT_MSG_USER_CANCELED)
941 errmsg = "\"handshake is being canceled for some reason unrelated to a "
942 "protocol failure\"";
943 else if (error_type == MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION)
944 errmsg = "no renegotiation";
945 else if (error_type == MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT)
946 errmsg = "unsupported ext";
947 else if (error_type == MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME)
948 errmsg = "unrecognized name";
949 else if (error_type == MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY)
950 errmsg = "unknown psk identity";
951 else if (error_type == MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL)
952 errmsg = "no application protocol";
953 else errmsg = "unknown alert value";
954
955 MSG_WARN("mbedtls_ssl_handshake() received TLS fatal alert %d (%s)\n",
956 error_type, errmsg);
957}
958
959/*
960 * Connect, set a callback if it's still not completed. If completed, check
961 * the certificate and report back to http.
962 */
963static void Tls_handshake(int fd, int connkey)
964{
965 int ret;
966 bool_t ongoing = FALSE, failed = TRUE;
967 Conn_t *conn;
968
969 if (!(conn = a_Klist_get_data(conn_list, connkey))) {
970 MSG("Tls_connect: conn for fd %d not valid\n", fd);
971 return;
972 }
973
974#if MBEDTLS_VERSION_NUMBER < 0x03000000
975 int ssl_state = conn->ssl->state;
976#else
977 int ssl_state = conn->ssl->MBEDTLS_PRIVATE(state);
978#endif
979 if (ssl_state != MBEDTLS_SSL_HANDSHAKE_OVER) {
980 ret = mbedtls_ssl_handshake(conn->ssl);
981
982 if (ret == MBEDTLS_ERR_SSL_WANT_READ ||
983 ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
984 int want = ret == MBEDTLS_ERR_SSL_WANT_READ ? DIO_READ : DIO_WRITE;
985
986 _MSG("iowatching fd %d for tls -- want %s\n", fd,
987 ret == MBEDTLS_ERR_SSL_WANT_READ ? "read" : "write");
988 a_IOwatch_remove_fd(fd, -1);
989 a_IOwatch_add_fd(fd, want, Tls_handshake_cb, INT2VOIDP(connkey));
990 ongoing = TRUE;
991 failed = FALSE;
992 } else if (ret == 0) {
993 Server_t *srv = dList_find_sorted(servers, conn->url,
995
996 if (srv->cert_status == CERT_STATUS_RECEIVING) {
997 /* Making first connection with the server. Show cipher used. */
998 mbedtls_ssl_context *ssl = conn->ssl;
999 const char *version = mbedtls_ssl_get_version(ssl),
1000 *cipher = mbedtls_ssl_get_ciphersuite(ssl);
1001
1002 MSG("%s", URL_AUTHORITY(conn->url));
1003 if (URL_PORT(conn->url) != URL_HTTPS_PORT)
1004 MSG(":%d", URL_PORT(conn->url));
1005 MSG(" %s, cipher %s\n", version, cipher);
1006 }
1007 if (srv->cert_status == CERT_STATUS_USER_ACCEPTED ||
1008 (Tls_examine_certificate(conn->ssl, srv) != -1)) {
1009 failed = FALSE;
1010 }
1011 } else if (ret == MBEDTLS_ERR_NET_SEND_FAILED) {
1012 MSG("mbedtls_ssl_handshake() send failed. Server may not be accepting"
1013 " connections.\n");
1014 } else if (ret == MBEDTLS_ERR_NET_CONNECT_FAILED) {
1015 MSG("mbedtls_ssl_handshake() connect failed.\n");
1016 } else if (ret == MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE) {
1017 /* Paul Bakker, the mbed tls guy, says "beware, this might change in
1018 * future versions" and "ssl->in_msg[1] is not going to change anytime
1019 * soon, unless there are radical changes". It seems to be the best of
1020 * the alternatives.
1021 */
1022#if MBEDTLS_VERSION_NUMBER < 0x03000000
1023 Tls_fatal_error_msg(conn->ssl->in_msg[1]);
1024#else
1025 Tls_fatal_error_msg(conn->ssl->MBEDTLS_PRIVATE(in_msg[1]));
1026#endif
1027 } else if (ret == MBEDTLS_ERR_SSL_INVALID_RECORD) {
1028 MSG("mbedtls_ssl_handshake() failed upon receiving 'an invalid "
1029 "record'.\n");
1030 } else if (ret == MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE) {
1031 MSG("mbedtls_ssl_handshake() failed: 'The requested feature is not "
1032 "available.'\n");
1033#if MBEDTLS_VERSION_NUMBER < 0x03000000
1034 } else if (ret == MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE) {
1035 MSG("mbedtls_ssl_handshake() failed: 'Processing of the "
1036 "ServerKeyExchange handshake message failed.'\n");
1037#endif
1038 } else if (ret == MBEDTLS_ERR_SSL_CONN_EOF) {
1039 MSG("mbedtls_ssl_handshake() failed: Read EOF. Connection closed by "
1040 "server.\n");
1041 } else {
1042 MSG("mbedtls_ssl_handshake() failed with error -0x%04x\n", -ret);
1043 }
1044 }
1045
1046 /*
1047 * If there were problems with the certificate, the connection may have
1048 * been closed by the server if the user responded too slowly to a popup.
1049 */
1050
1051 if (!ongoing) {
1052 if (a_Klist_get_data(conn_list, connkey)) {
1053 conn->connecting = FALSE;
1054 if (failed) {
1055 Tls_close_by_key(connkey);
1056 }
1057 a_IOwatch_remove_fd(fd, -1);
1059 } else {
1060 MSG("Connection disappeared. Too long with a popup popped up?\n");
1061 }
1062 }
1063}
1064
1065static void Tls_handshake_cb(int fd, void *vconnkey)
1066{
1067 Tls_handshake(fd, VOIDP2INT(vconnkey));
1068}
1069
1070/*
1071 * Make TLS connection over a connect()ed socket.
1072 */
1073void a_Tls_mbedtls_connect(int fd, const DilloUrl *url)
1074{
1075 mbedtls_ssl_context *ssl = dNew0(mbedtls_ssl_context, 1);
1076 bool_t success = TRUE;
1077 int connkey = -1;
1078 int ret;
1079
1080 if (!ssl_enabled)
1081 success = FALSE;
1082
1083 if (success && Tls_user_said_no(url)) {
1084 success = FALSE;
1085 }
1086
1087 if (success && (ret = mbedtls_ssl_setup(ssl, &ssl_conf))) {
1088 MSG("mbedtls_ssl_setup failed %d\n", ret);
1089 success = FALSE;
1090 }
1091
1092 /* assign TLS connection to this file descriptor */
1093 if (success) {
1094 Conn_t *conn = Tls_conn_new(fd, url, ssl);
1095 connkey = Tls_make_conn_key(conn);
1096 mbedtls_ssl_set_bio(ssl, &conn->fd, mbedtls_net_send, mbedtls_net_recv,
1097 NULL);
1098 }
1099
1100 if (success && (ret = mbedtls_ssl_set_hostname(ssl, URL_HOST(url)))) {
1101 MSG("mbedtls_ssl_set_hostname failed %d\n", ret);
1102 success = FALSE;
1103 }
1104
1105 if (!success) {
1107 a_Http_connect_done(fd, success);
1108 } else {
1109 Tls_handshake(fd, connkey);
1110 }
1111}
1112
1113/*
1114 * Read data from an open TLS connection.
1115 */
1116int a_Tls_mbedtls_read(void *conn, void *buf, size_t len)
1117{
1118 Conn_t *c = (Conn_t*)conn;
1119 int ret = mbedtls_ssl_read(c->ssl, buf, len);
1120
1121 if (ret < 0) {
1122 if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) {
1123 /* treat it as EOF */
1124 ret = 0;
1125 } else if (ret == MBEDTLS_ERR_SSL_WANT_READ) {
1126 ret = -1;
1127 errno = EAGAIN; /* already happens to be set, but let's make sure */
1128 } else if (ret == MBEDTLS_ERR_NET_CONN_RESET) {
1129 MSG("READ failed: TLS connection reset by server.\n");
1130 } else {
1131 MSG("READ failed with -0x%04x: an mbed tls error.\n", -ret);
1132 }
1133 }
1134 return ret;
1135}
1136
1137/*
1138 * Write data to an open TLS connection.
1139 */
1140int a_Tls_mbedtls_write(void *conn, void *buf, size_t len)
1141{
1142 Conn_t *c = (Conn_t*)conn;
1143 int ret = mbedtls_ssl_write(c->ssl, buf, len);
1144
1145 if (ret < 0) {
1146 MSG("WRITE failed with -0x%04x: an mbed tls error\n", -ret);
1147 }
1148 return ret;
1149}
1150
1152{
1153 FdMapEntry_t *fme = dList_find_custom(fd_map, INT2VOIDP(fd),
1155
1156 if (fme) {
1157 Tls_close_by_key(fme->connkey);
1158 }
1159}
1160
1162{
1163 const int ca_len = dList_length(cert_authorities);
1164 Dstr *ds = dStr_new("");
1165 int i, j;
1166
1167 if (ca_len)
1168 dStr_append(ds, "TLS: Certificate chain roots during this session:\n");
1169
1170 for (i = 0; i < ca_len; i++) {
1171 CertAuth_t *ca = (CertAuth_t *)dList_nth_data(cert_authorities, i);
1172 const int servers_len = ca->servers ? dList_length(ca->servers) : 0;
1173 char *ca_name = strstr(ca->name, "CN=");
1174
1175 if (!ca_name)
1176 ca_name = strstr(ca->name, "OU=");
1177
1178 if (ca_name)
1179 ca_name += 3;
1180 else
1181 ca_name = ca->name;
1182 dStr_sprintfa(ds, "- %s for: ", ca_name);
1183
1184 for (j = 0; j < servers_len; j++) {
1185 Server_t *s = dList_nth_data(ca->servers, j);
1186 bool_t ipv6 = a_Url_host_type(s->hostname) == URL_HOST_IPV6;
1187
1188 dStr_sprintfa(ds, "%s%s%s", ipv6?"[":"", s->hostname, ipv6?"]":"");
1189 if (s->port != URL_HTTPS_PORT)
1190 dStr_sprintfa(ds, ":%d", s->port);
1191 dStr_append_c(ds, ' ');
1192 }
1193 dStr_append_c(ds, '\n');
1194 }
1195 MSG("%s", ds->str);
1196 dStr_free(ds, 1);
1197}
1198
1199/*
1200 * Free mbed tls's chain of certificates and free our data on which root
1201 * certificates caused us to trust which servers.
1202 */
1204{
1205 if (cacerts.next)
1206 mbedtls_x509_crt_free(cacerts.next);
1207
1208 if (cert_authorities) {
1209 CertAuth_t *ca;
1210 int i, n = dList_length(cert_authorities);
1211
1212 for (i = 0; i < n; i++) {
1213 ca = (CertAuth_t *) dList_nth_data(cert_authorities, i);
1214 dFree(ca->name);
1215 if (ca->servers)
1216 dList_free(ca->servers);
1217 dFree(ca);
1218 }
1220 }
1221}
1222
1224{
1225 if (servers) {
1226 Server_t *s;
1227 int i, n = dList_length(servers);
1228
1229 for (i = 0; i < n; i++) {
1230 s = (Server_t *) dList_nth_data(servers, i);
1231 dFree(s->hostname);
1232 dFree(s);
1233 }
1235 }
1236}
1237
1239{
1240 if (fd_map) {
1241 FdMapEntry_t *fme;
1242 int i, n = dList_length(fd_map);
1243
1244 for (i = 0; i < n; i++) {
1245 fme = (FdMapEntry_t *) dList_nth_data(fd_map, i);
1246 dFree(fme);
1247 }
1249 }
1250}
1251
1252/*
1253 * Clean up
1254 */
#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:342
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:121
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
const char * a_Tls_mbedtls_version(char *buf, int n)
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