From 0613cc62f4dbec6beb76e9ddece60d52171585c0 Mon Sep 17 00:00:00 2001 From: cpq Date: Tue, 25 Jul 2023 13:07:28 +0100 Subject: [PATCH] TLS API refactor --- Makefile | 6 +- examples/device-dashboard/Makefile | 2 +- examples/device-dashboard/mbedtls_config.h | 5 +- examples/device-dashboard/net.c | 45 +- examples/device-dashboard/net.h | 2 +- examples/embedded-filesystem/packed_fs.c | 743 ++---------------- examples/http-streaming-client/main.c | 27 +- examples/mqtt-client/main.c | 11 +- examples/smtp-client/main.c | 13 +- .../Makefile | 4 +- .../mbedtls_config.h | 7 +- examples/tcp/main.c | 62 +- mongoose.c | 399 +++++++--- mongoose.h | 228 +++++- src/certs.h | 159 ++++ src/config.h | 12 - src/net.c | 6 + src/sock.c | 1 + src/tcpip/tcpip.c | 1 + src/tls.h | 27 +- src/tls_dummy.c | 12 +- src/tls_mbed.c | 178 +++-- src/tls_mbed.h | 19 +- src/tls_openssl.c | 201 +++-- src/tls_openssl.h | 11 +- test/unit_test.c | 87 +- 26 files changed, 1180 insertions(+), 1088 deletions(-) create mode 100644 src/certs.h diff --git a/Makefile b/Makefile index c89dfaf4..ae84eb07 100644 --- a/Makefile +++ b/Makefile @@ -36,13 +36,13 @@ endif ifeq "$(SSL)" "MBEDTLS" MBEDTLS ?= /usr/local -CFLAGS += -DMG_ENABLE_MBEDTLS=1 -I$(MBEDTLS)/include -I/usr/include +CFLAGS += -DMG_TLS=MG_TLS_MBED -I$(MBEDTLS)/include -I/usr/include LDFLAGS += -L$(MBEDTLS)/lib -lmbedtls -lmbedcrypto -lmbedx509 endif ifeq "$(SSL)" "OPENSSL" OPENSSL ?= /usr/local -CFLAGS += -DMG_ENABLE_OPENSSL=1 -I$(OPENSSL)/include +CFLAGS += -DMG_TLS=MG_TLS_OPENSSL -I$(OPENSSL)/include LDFLAGS += -L$(OPENSSL)/lib -lssl -lcrypto endif @@ -175,7 +175,7 @@ mongoose.c: Makefile $(wildcard src/*.c) $(wildcard src/tcpip/*.c) (cat src/license.h; echo; echo '#include "mongoose.h"' ; (for F in src/*.c src/tcpip/*.c ; do echo; echo '#ifdef MG_ENABLE_LINES'; echo "#line 1 \"$$F\""; echo '#endif'; cat $$F | sed -e 's,#include ".*,,'; done))> $@ mongoose.h: $(HDRS) Makefile - (cat src/license.h; echo; echo '#ifndef MONGOOSE_H'; echo '#define MONGOOSE_H'; echo; cat src/version.h ; echo; echo '#ifdef __cplusplus'; echo 'extern "C" {'; echo '#endif'; cat src/arch.h src/arch_*.h src/net_*.h src/config.h src/str.h src/queue.h src/fmt.h src/printf.h src/log.h src/timer.h src/fs.h src/util.h src/url.h src/iobuf.h src/base64.h src/md5.h src/sha1.h src/event.h src/net.h src/http.h src/ssi.h src/tls.h src/tls_mbed.h src/tls_openssl.h src/ws.h src/sntp.h src/mqtt.h src/dns.h src/json.h src/rpc.h src/tcpip/tcpip.h src/tcpip/driver_*.h | sed -e '/keep/! s,#include ".*,,' -e 's,^#pragma once,,'; echo; echo '#ifdef __cplusplus'; echo '}'; echo '#endif'; echo '#endif // MONGOOSE_H')> $@ + (cat src/license.h; echo; echo '#ifndef MONGOOSE_H'; echo '#define MONGOOSE_H'; echo; cat src/version.h ; echo; echo '#ifdef __cplusplus'; echo 'extern "C" {'; echo '#endif'; cat src/arch.h src/arch_*.h src/net_*.h src/config.h src/str.h src/queue.h src/fmt.h src/printf.h src/log.h src/timer.h src/fs.h src/util.h src/url.h src/iobuf.h src/base64.h src/md5.h src/sha1.h src/event.h src/net.h src/http.h src/ssi.h src/tls.h src/tls_mbed.h src/tls_openssl.h src/ws.h src/sntp.h src/mqtt.h src/dns.h src/json.h src/rpc.h src/tcpip/tcpip.h src/tcpip/driver_*.h src/certs.h | sed -e '/keep/! s,#include ".*,,' -e 's,^#pragma once,,'; echo; echo '#ifdef __cplusplus'; echo '}'; echo '#endif'; echo '#endif // MONGOOSE_H')> $@ clean: clean_examples clean_embedded diff --git a/examples/device-dashboard/Makefile b/examples/device-dashboard/Makefile index fc4e261b..c6ddfecc 100644 --- a/examples/device-dashboard/Makefile +++ b/examples/device-dashboard/Makefile @@ -41,7 +41,7 @@ mbedtls: git clone --depth 1 -b v2.28.2 https://github.com/mbed-tls/mbedtls $@ ifeq ($(TLS), mbedtls) -CFLAGS += -DMG_ENABLE_MBEDTLS=1 -Wno-conversion -Imbedtls/include +CFLAGS += -DMG_TLS=MG_TLS_MBED -Wno-conversion -Imbedtls/include CFLAGS += -DMBEDTLS_CONFIG_FILE=\"mbedtls_config.h\" mbedtls/library/*.c $(PROG): mbedtls endif diff --git a/examples/device-dashboard/mbedtls_config.h b/examples/device-dashboard/mbedtls_config.h index 0103ace3..9d41fa75 100644 --- a/examples/device-dashboard/mbedtls_config.h +++ b/examples/device-dashboard/mbedtls_config.h @@ -6,6 +6,7 @@ #define MBEDTLS_SSL_OUT_CONTENT_LEN 2048 #define MBEDTLS_ALLOW_PRIVATE_ACCESS #define MBEDTLS_HAVE_TIME +#define MBEDTLS_SSL_SESSION_TICKETS #define MBEDTLS_CIPHER_MODE_CBC #define MBEDTLS_ECP_DP_SECP192R1_ENABLED @@ -51,8 +52,9 @@ #define MBEDTLS_AES_FEWER_TABLES #define MBEDTLS_PEM_PARSE_C #define MBEDTLS_BASE64_C +#define MBEDTLS_SSL_TICKET_C -// TLS 1.2 +#define MBEDTLS_SSL_PROTO_TLS1_3 #define MBEDTLS_SSL_PROTO_TLS1_2 #define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED #define MBEDTLS_GCM_C @@ -60,4 +62,3 @@ #define MBEDTLS_ECP_C #define MBEDTLS_ECDSA_C #define MBEDTLS_ASN1_WRITE_C - diff --git a/examples/device-dashboard/net.c b/examples/device-dashboard/net.c index f93c3ceb..10816c5b 100644 --- a/examples/device-dashboard/net.c +++ b/examples/device-dashboard/net.c @@ -31,7 +31,7 @@ static uint64_t s_boot_timestamp = 0; // Updated by SNTP // Certificate generation procedure: // openssl ecparam -name prime256v1 -genkey -noout -out key.pem // openssl req -new -key key.pem -x509 -nodes -days 3650 -out cert.pem -static const char *s_ssl_cert = +static const char *s_tls_cert = "-----BEGIN CERTIFICATE-----\n" "MIIBCTCBsAIJAK9wbIDkHnAoMAoGCCqGSM49BAMCMA0xCzAJBgNVBAYTAklFMB4X\n" "DTIzMDEyOTIxMjEzOFoXDTMzMDEyNjIxMjEzOFowDTELMAkGA1UEBhMCSUUwWTAT\n" @@ -41,7 +41,7 @@ static const char *s_ssl_cert = "aEWiBp1xshs4iz6WbpxrS1IHucrqkZuJLfNZGZI=\n" "-----END CERTIFICATE-----\n"; -static const char *s_ssl_key = +static const char *s_tls_key = "-----BEGIN EC PRIVATE KEY-----\n" "MHcCAQEEICBz3HOkQLPBDtdknqC7k1PNsWj6HfhyNB5MenfjmqiooAoGCCqGSM49\n" "AwEHoUQDQgAEc0kEuTh3de5VHjSPupKfVmLtHMbhCIvyU46YWwpnSQ9XFL4ZszPf\n" @@ -54,19 +54,18 @@ uint64_t mg_now(void) { } int ui_event_next(int no, struct ui_event *e) { - if (no < 0 || no >= MAX_EVENTS_NO) - return 0; + if (no < 0 || no >= MAX_EVENTS_NO) return 0; srand(no); e->type = (uint8_t) rand() % 4; e->prio = (uint8_t) rand() % 3; - e->timestamp = (unsigned long) (mg_now() - 86400 * 1000 /* one day back */ + - no * 300 * 1000 /* 5 mins between alerts */ + - 1000 * (rand() % 300) /* randomize event time */) / - 1000; - - mg_snprintf(e->text, MAX_EVENT_TEXT_SIZE, - "event#%d", no); + e->timestamp = + (unsigned long) (mg_now() - 86400 * 1000 /* one day back */ + + no * 300 * 1000 /* 5 mins between alerts */ + + 1000 * (rand() % 300) /* randomize event time */) / + 1000; + + mg_snprintf(e->text, MAX_EVENT_TEXT_SIZE, "event#%d", no); return no + 1; } @@ -171,16 +170,17 @@ static size_t print_events(void (*out)(char, void *), void *ptr, va_list *ap) { while ((no = ui_event_next(no, &ev)) != 0 && no <= end) { len += mg_xprintf(out, ptr, "%s{%m:%lu,%m:%d,%m:%d,%m:%m}", // len == 0 ? "" : ",", // - MG_ESC("time"), ev.timestamp, // - MG_ESC("type"), ev.type, // - MG_ESC("prio"), ev.prio, // + MG_ESC("time"), ev.timestamp, // + MG_ESC("type"), ev.type, // + MG_ESC("prio"), ev.prio, // MG_ESC("text"), MG_ESC(ev.text)); } return len; } -static void handle_events_get(struct mg_connection *c, struct mg_http_message *hm) { +static void handle_events_get(struct mg_connection *c, + struct mg_http_message *hm) { int pageno = mg_json_get_long(hm->body, "$.page", 1); mg_http_reply(c, 200, s_json_header, "{%m:[%M], %m:%d}", MG_ESC("arr"), print_events, pageno, MG_ESC("totalCount"), MAX_EVENTS_NO); @@ -220,10 +220,7 @@ static void handle_settings_get(struct mg_connection *c) { // HTTP request handler function static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { - if (ev == MG_EV_ACCEPT && fn_data != NULL) { - struct mg_tls_opts opts = {.cert = s_ssl_cert, .certkey = s_ssl_key}; - mg_tls_init(c, &opts); - } else if (ev == MG_EV_HTTP_MSG) { + if (ev == MG_EV_HTTP_MSG) { struct mg_http_message *hm = (struct mg_http_message *) ev_data; struct user *u = authenticate(hm); @@ -258,15 +255,19 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { hm->method.ptr, (int) hm->uri.len, hm->uri.ptr, (int) 3, &c->send.buf[9])); } + (void) fn_data; } void web_init(struct mg_mgr *mgr) { + struct mg_tls_opts opts = {0}; + opts.server_cert = mg_str(s_tls_cert); + opts.server_key = mg_str(s_tls_key); + mg_tls_ctx_init(mgr, &opts); + s_settings.device_name = strdup("My Device"); mg_http_listen(mgr, HTTP_URL, fn, NULL); -#if MG_ENABLE_MBEDTLS || MG_ENABLE_OPENSSL - mg_http_listen(mgr, HTTPS_URL, fn, ""); -#endif + mg_http_listen(mgr, HTTPS_URL, fn, NULL); // mg_timer_add(c->mgr, 1000, MG_TIMER_REPEAT, timer_mqtt_fn, c->mgr); mg_timer_add(mgr, 3600 * 1000, MG_TIMER_RUN_NOW | MG_TIMER_REPEAT, diff --git a/examples/device-dashboard/net.h b/examples/device-dashboard/net.h index 2fb00658..94d340a8 100644 --- a/examples/device-dashboard/net.h +++ b/examples/device-dashboard/net.h @@ -9,7 +9,7 @@ #endif #if !defined(HTTPS_URL) -#define HTTPS_URL "http://0.0.0.0:8443" +#define HTTPS_URL "https://0.0.0.0:8443" #endif #define MAX_DEVICE_NAME 40 diff --git a/examples/embedded-filesystem/packed_fs.c b/examples/embedded-filesystem/packed_fs.c index 138100d1..eafd9064 100644 --- a/examples/embedded-filesystem/packed_fs.c +++ b/examples/embedded-filesystem/packed_fs.c @@ -3,552 +3,51 @@ #include static const unsigned char v1[] = { - 31, 139, 8, 8, 219, 27, 244, 98, 0, 3, 112, 114, // .......b..pr - 101, 97, 99, 116, 46, 109, 105, 110, 46, 106, 115, 0, // eact.min.js. - 157, 91, 123, 119, 219, 182, 146, 255, 127, 63, 69, 164, // .[{w.....?E. - 211, 163, 18, 43, 68, 177, 147, 182, 187, 75, 5, 213, // ...+D....K.. - 105, 29, 183, 238, 109, 234, 230, 38, 105, 123, 123, 85, // i...m..&i{{U - 93, 30, 138, 132, 44, 214, 20, 169, 242, 97, 91, 53, // ]...,....a[5 - 245, 221, 247, 55, 3, 128, 164, 108, 185, 247, 236, 158, // ...7...l.... - 36, 34, 30, 131, 1, 48, 47, 204, 12, 144, 155, 176, // $"...0/..... - 120, 166, 101, 38, 3, 89, 201, 92, 22, 178, 150, 169, // x.e&.Y...... - 186, 223, 203, 68, 205, 23, 50, 82, 47, 194, 40, 169, // ...D..2R/.(. - 26, 125, 231, 205, 252, 178, 185, 106, 178, 102, 219, 124, // .}.....j.f.| - 34, 154, 98, 187, 110, 174, 138, 36, 110, 242, 219, 178, // ".b.n..$n... - 217, 100, 81, 147, 85, 183, 77, 146, 233, 121, 180, 94, // .dQ.U.M..y.^ - 52, 127, 230, 121, 243, 175, 188, 136, 155, 164, 210, 69, // 4..y.......E - 248, 34, 153, 174, 234, 44, 170, 146, 60, 123, 86, 122, // ."...,..<{Vz - 152, 72, 220, 175, 242, 194, 187, 193, 172, 193, 179, 36, // .H.........$ - 123, 150, 9, 61, 15, 22, 42, 195, 207, 180, 208, 85, // {..=..*....U - 93, 100, 207, 244, 190, 29, 177, 242, 180, 184, 39, 216, // ]d........'. - 76, 233, 201, 54, 44, 116, 86, 93, 230, 177, 158, 102, // L..6,tV]...f - 163, 81, 54, 41, 244, 38, 191, 209, 103, 235, 36, 141, // .Q6).&..g.$. - 1, 214, 13, 10, 61, 222, 141, 25, 216, 109, 105, 74, // ....=....miJ - 243, 214, 52, 103, 32, 134, 215, 122, 55, 84, 170, 158, // ..4g ..z7T.. - 229, 42, 152, 215, 11, 127, 88, 232, 21, 215, 11, 83, // .*....X....S - 79, 241, 195, 165, 105, 178, 242, 194, 226, 170, 222, 96, // O...i......` - 230, 114, 146, 234, 236, 170, 90, 127, 249, 114, 52, 242, // .r....Z..r4. - 210, 73, 68, 19, 99, 69, 234, 81, 255, 171, 153, 158, // .ID.cE.Q.... - 68, 97, 154, 118, 35, 229, 75, 225, 87, 66, 14, 221, // Da.v#.K.WB.. - 26, 49, 87, 181, 219, 234, 124, 245, 140, 118, 82, 167, // .1W...|..vR. - 233, 64, 101, 147, 88, 175, 194, 58, 173, 222, 21, 249, // .@e.X..:.... - 182, 20, 237, 98, 31, 180, 223, 228, 73, 252, 236, 68, // ...b....I..D - 41, 69, 75, 164, 117, 208, 74, 15, 97, 208, 34, 28, // )EK.u.J.a.". - 45, 183, 160, 69, 202, 124, 165, 89, 122, 68, 218, 130, // -..E.|.YzD.. - 23, 150, 225, 134, 80, 32, 17, 45, 201, 215, 114, 75, // ....P .-..rK - 72, 252, 74, 130, 70, 62, 0, 244, 202, 47, 100, 16, // H.J.F>.../d. - 92, 251, 132, 1, 5, 247, 93, 250, 39, 248, 213, 174, // ......].'... - 26, 251, 102, 105, 40, 70, 174, 109, 109, 10, 81, 158, // ..fi(F.mm.Q. - 149, 85, 81, 71, 85, 94, 116, 64, 55, 220, 71, 52, // .UQGU^t@7.G4 - 31, 143, 3, 191, 222, 187, 21, 59, 106, 220, 100, 96, // .......;j.d` - 52, 177, 153, 11, 94, 42, 100, 218, 173, 126, 77, 114, // 4...^*d..~Mr - 225, 196, 165, 229, 68, 215, 31, 27, 73, 171, 214, 73, // ....D...I..I - 57, 225, 237, 40, 236, 150, 42, 88, 74, 165, 239, 42, // 9..(..*XJ..* - 213, 131, 189, 49, 176, 96, 180, 89, 80, 38, 90, 196, // ...1.`.YP&Z. - 65, 48, 67, 47, 62, 146, 126, 240, 247, 122, 146, 100, // A0C/>.~..z.d - 177, 190, 251, 145, 228, 114, 124, 42, 120, 11, 211, 86, // .....r|*x..V - 158, 167, 217, 107, 205, 64, 70, 14, 166, 217, 120, 44, // ...k.@F...x, - 44, 218, 129, 242, 2, 197, 157, 243, 108, 33, 28, 207, // ,.......l!.. - 9, 165, 118, 211, 113, 197, 82, 225, 136, 160, 232, 9, // ..v.q.R..... - 21, 104, 61, 102, 218, 110, 3, 187, 86, 73, 100, 48, // .h=f.n..VId0 - 237, 230, 211, 60, 95, 59, 23, 85, 34, 163, 124, 84, // ...<_;.U".|T - 52, 189, 209, 100, 25, 150, 90, 49, 151, 50, 117, 242, // 4..d..Z1.2u. - 255, 220, 192, 253, 35, 132, 102, 47, 203, 66, 135, 215, // ....#.f/.B.. - 123, 187, 61, 90, 229, 190, 91, 244, 134, 22, 237, 13, // {.=Z..[..... - 104, 76, 12, 49, 230, 175, 26, 156, 0, 115, 53, 217, // hL.1.....s5. - 214, 37, 49, 120, 52, 26, 92, 161, 185, 24, 143, 155, // .%1x4....... - 166, 24, 40, 150, 242, 101, 14, 4, 250, 189, 6, 23, // ..(..e...... - 138, 36, 187, 2, 140, 231, 21, 71, 123, 154, 38, 23, // .$.....G{.&. - 222, 85, 79, 226, 175, 188, 206, 244, 232, 41, 99, 86, // .UO......)cV - 149, 219, 169, 208, 40, 151, 121, 81, 121, 14, 222, 72, // ....(.yQy..H - 69, 79, 20, 110, 240, 111, 249, 60, 115, 165, 189, 144, // EO.n.o...D....J. - 208, 20, 246, 246, 155, 230, 206, 193, 99, 113, 128, 35, // ........cq.# - 225, 8, 58, 208, 64, 0, 99, 64, 59, 199, 20, 248, // ..:.@.c@;... - 28, 194, 83, 135, 216, 59, 57, 25, 230, 142, 124, 163, // ..S..;9...|. - 209, 48, 51, 229, 211, 133, 128, 11, 2, 250, 227, 104, // .03........h - 167, 168, 100, 155, 134, 145, 246, 94, 156, 133, 91, 176, // ..d....^..[. - 71, 127, 242, 130, 166, 132, 61, 67, 95, 149, 191, 205, // G.....=C_... - 111, 117, 113, 6, 23, 201, 19, 152, 89, 207, 30, 180, // ouq.....Y... - 77, 202, 52, 193, 88, 68, 11, 89, 91, 132, 22, 164, // M.4.XD.Y[... - 176, 163, 248, 69, 16, 195, 181, 121, 54, 46, 16, 158, // ...E...y6... - 200, 96, 86, 53, 13, 4, 47, 142, 207, 111, 32, 139, // .`V5../..o . - 111, 147, 178, 210, 240, 5, 192, 202, 98, 246, 193, 63, // o.......b..? - 135, 152, 192, 54, 153, 40, 233, 41, 128, 86, 1, 134, // ...6.(.).V.. - 113, 152, 93, 233, 34, 175, 203, 116, 247, 65, 87, 223, // q.]."..t.AW. - 101, 128, 187, 248, 248, 195, 91, 50, 134, 198, 59, 206, // e.....[2..;. - 197, 193, 246, 238, 32, 96, 215, 243, 11, 127, 189, 192, // .... `...... - 6, 215, 67, 209, 245, 148, 151, 225, 134, 183, 93, 14, // ..C.......]. - 123, 248, 215, 20, 98, 17, 50, 16, 46, 197, 66, 92, // {...b.2...B. - 25, 108, 216, 184, 114, 21, 46, 191, 35, 255, 218, 213, // .l..r...#... - 99, 248, 54, 105, 30, 198, 182, 206, 220, 210, 162, 42, // c.6i.......* - 118, 247, 15, 5, 53, 152, 90, 101, 217, 71, 97, 21, // v...5.Ze.Ga. - 113, 120, 176, 63, 102, 66, 65, 72, 235, 185, 66, 136, // qx.?fBAH..B. - 6, 167, 3, 214, 249, 97, 216, 99, 106, 209, 50, 213, // .....a.cj.2. - 40, 200, 87, 21, 196, 111, 89, 87, 218, 106, 136, 37, // (.W..oYW.j.% - 104, 175, 89, 244, 253, 218, 115, 154, 154, 67, 141, 116, // h.Y...s..C.t - 110, 92, 246, 241, 224, 116, 225, 101, 19, 77, 28, 152, // n....t.e.M.. - 217, 47, 57, 241, 253, 144, 245, 195, 145, 81, 39, 255, // ./9......Q'. - 118, 20, 29, 203, 189, 176, 93, 38, 50, 50, 90, 183, // v.....]&22Z. - 146, 161, 220, 202, 27, 235, 155, 45, 229, 25, 121, 103, // .......-..yg - 240, 200, 204, 9, 114, 96, 27, 131, 73, 47, 58, 19, // ....r`..I/:. - 189, 24, 108, 106, 232, 68, 254, 220, 26, 180, 138, 76, // ..lj.D.....L - 9, 38, 204, 156, 91, 21, 27, 101, 42, 175, 77, 248, // .&..[..e*.M. - 80, 171, 121, 130, 131, 222, 91, 177, 153, 93, 194, 172, // P.y...[..].. - 145, 146, 77, 153, 89, 108, 2, 30, 115, 227, 156, 229, // ..M.Yl..s... - 138, 252, 31, 227, 45, 157, 41, 140, 62, 119, 49, 218, // ....-.).>w1. - 71, 242, 73, 70, 163, 124, 190, 34, 183, 0, 135, 145, // G.IF.|.".... - 90, 205, 206, 102, 103, 6, 214, 28, 185, 62, 117, 33, // Z..fg....>u! - 70, 165, 197, 68, 179, 43, 133, 19, 141, 86, 100, 214, // F..D.+...Vd. - 26, 145, 255, 172, 66, 252, 156, 251, 222, 16, 163, 170, // ....B....... - 156, 230, 29, 66, 134, 206, 71, 163, 243, 73, 219, 2, // ...B..G..I.. - 142, 82, 208, 48, 51, 67, 67, 149, 233, 91, 176, 113, // .R.03CC..[.q - 41, 239, 132, 239, 245, 219, 98, 110, 147, 97, 159, 98, // ).....bn.a.b - 234, 28, 117, 51, 94, 125, 37, 228, 217, 104, 116, 54, // ..u3^}%..ht6 - 41, 235, 165, 23, 18, 156, 137, 60, 151, 40, 149, 85, // )......<.(.U - 88, 105, 200, 158, 45, 177, 34, 135, 109, 48, 122, 39, // Xi..-.".m0z' - 105, 149, 153, 202, 229, 150, 215, 75, 129, 16, 55, 173, // i......K..7. - 217, 119, 50, 98, 78, 117, 248, 20, 30, 127, 149, 69, // .w2bNu.....E - 228, 220, 164, 243, 201, 149, 174, 222, 32, 240, 185, 209, // ........ ... - 241, 7, 234, 248, 166, 200, 55, 156, 12, 104, 71, 184, // ......7..hG. - 33, 109, 3, 71, 25, 92, 132, 117, 42, 77, 163, 124, // !m.G...u*M.| - 26, 145, 183, 116, 192, 66, 222, 40, 187, 57, 248, 132, // ...t.B.(.9.. - 22, 173, 220, 10, 179, 206, 191, 90, 138, 89, 44, 109, // .......Z.Y,m - 124, 179, 205, 51, 72, 244, 47, 73, 154, 254, 128, 192, // |..3H./I.... - 13, 6, 248, 88, 171, 231, 246, 215, 235, 124, 147, 196, // ...X.....|.. - 237, 8, 80, 200, 248, 142, 71, 250, 69, 123, 128, 252, // ..P...G.E{.. - 251, 117, 45, 161, 8, 55, 79, 44, 239, 189, 142, 52, // .u-..7O,...4 - 198, 88, 200, 191, 232, 52, 210, 49, 8, 141, 83, 230, // .X...4.1..S. - 112, 149, 235, 188, 78, 227, 51, 55, 232, 167, 109, 204, // p...N.37..m. - 60, 24, 156, 42, 245, 84, 175, 163, 52, 208, 53, 77, // <..*.T..4.5M - 192, 65, 160, 98, 137, 190, 17, 247, 143, 132, 202, 200, // .A.b........ - 5, 43, 226, 205, 192, 130, 89, 22, 67, 140, 78, 5, // .+....Y.C.N. - 163, 186, 161, 195, 226, 129, 218, 94, 115, 249, 218, 148, // .......^s... - 39, 176, 194, 231, 33, 236, 102, 63, 140, 213, 54, 46, // '...!.f?..6. - 87, 129, 216, 27, 60, 107, 235, 166, 140, 70, 169, 165, // W...i........ - 117, 155, 249, 75, 196, 194, 174, 156, 164, 71, 155, 51, // u..K.....G.3 - 184, 239, 2, 188, 161, 38, 113, 79, 189, 17, 37, 48, // .....&qO..%0 - 241, 65, 60, 163, 197, 163, 84, 17, 128, 248, 120, 100, // .A<...T...xd - 2, 174, 237, 116, 199, 83, 74, 54, 161, 76, 154, 216, // ...t.SJ6.L.. - 237, 160, 157, 159, 109, 195, 190, 159, 180, 185, 245, 250, // ....m....... - 41, 155, 214, 49, 40, 217, 49, 88, 131, 118, 70, 140, // )..1(.1X.vF. - 227, 246, 236, 221, 89, 231, 64, 110, 16, 163, 176, 215, // ....Y.@n.... - 125, 67, 46, 183, 218, 113, 222, 106, 112, 226, 84, 180, // }C...q.jp.T. - 102, 191, 121, 186, 121, 93, 187, 144, 101, 99, 50, 56, // f.y.y]..ec28 - 136, 109, 235, 249, 134, 67, 189, 146, 60, 40, 136, 232, // .m...C..<(.. - 110, 6, 127, 38, 199, 194, 201, 33, 4, 42, 255, 21, // n..&...!.*.. - 194, 226, 9, 165, 115, 249, 108, 23, 216, 129, 42, 37, // ....s.l...*% - 141, 50, 177, 146, 201, 57, 244, 18, 177, 157, 245, 86, // .2...9.....V - 59, 231, 155, 196, 121, 196, 57, 245, 73, 4, 232, 74, // ;...y.9.I..J - 147, 247, 79, 65, 152, 23, 139, 105, 166, 138, 217, 131, // ..OA...i.... - 110, 155, 20, 187, 252, 0, 7, 180, 170, 182, 254, 139, // n........... - 23, 183, 183, 183, 147, 219, 87, 147, 188, 184, 122, 241, // ......W...z. - 242, 228, 228, 228, 5, 237, 19, 234, 226, 31, 31, 232, // ............ - 237, 100, 12, 69, 24, 141, 98, 23, 209, 201, 136, 100, // .d.E..b....d - 181, 191, 176, 53, 126, 99, 196, 69, 196, 107, 168, 95, // ...5~c.E.k._ - 104, 170, 158, 173, 196, 221, 65, 84, 147, 92, 91, 78, // h.....AT..[N - 102, 70, 231, 104, 233, 37, 116, 64, 121, 45, 83, 154, // fF.h.%t@y-S. - 38, 21, 147, 39, 188, 113, 56, 8, 241, 147, 125, 131, // &..'.q8...}. - 168, 37, 152, 227, 211, 154, 174, 114, 136, 163, 155, 215, // .%.....r.... - 217, 36, 116, 46, 107, 217, 103, 221, 122, 222, 239, 1, // .$t.k.g.z... - 47, 38, 25, 184, 69, 119, 10, 135, 173, 236, 112, 77, // /&..Ew....pM - 61, 216, 166, 144, 120, 188, 37, 85, 30, 141, 182, 36, // =...x.%U...$ - 179, 213, 198, 250, 39, 84, 106, 154, 174, 13, 72, 18, // ....'Tj...H. - 183, 60, 193, 36, 105, 171, 106, 219, 13, 134, 7, 142, // .<.$i.j..... - 8, 137, 104, 218, 79, 190, 30, 134, 145, 180, 155, 194, // ..h.O....... - 94, 222, 56, 107, 69, 242, 137, 88, 220, 94, 230, 112, // ^.8kE..X.^.p - 88, 206, 55, 38, 77, 67, 113, 168, 185, 242, 64, 252, // X.7&MCq...@. - 86, 44, 160, 159, 29, 130, 76, 228, 20, 118, 56, 111, // V,....L..v8o - 180, 13, 109, 51, 0, 2, 217, 211, 200, 135, 76, 2, // ..m3......L. - 87, 137, 214, 58, 186, 214, 177, 173, 210, 44, 28, 55, // W..:.....,.7 - 16, 14, 59, 59, 77, 108, 103, 223, 67, 29, 99, 185, // ..;;Mlg.C.c. - 70, 43, 172, 230, 86, 184, 100, 104, 27, 29, 109, 156, // F+..V.dh..m. - 30, 182, 150, 24, 118, 56, 147, 143, 50, 145, 27, 31, // ....v8..2... - 172, 112, 138, 109, 130, 39, 157, 92, 101, 63, 46, 127, // .p.m.'..e?.. - 215, 17, 71, 84, 59, 214, 246, 122, 86, 35, 152, 241, // ..GT;..zV#.. - 43, 147, 9, 163, 60, 16, 244, 55, 58, 84, 225, 141, // +...<..7:T.. - 234, 52, 184, 203, 62, 145, 50, 146, 161, 100, 85, 158, // .4..>.2..dU. - 194, 44, 122, 118, 215, 32, 92, 12, 84, 46, 108, 192, // .,zv. ..T.l. - 240, 216, 136, 4, 9, 195, 134, 147, 44, 92, 5, 101, // ........,..e - 176, 145, 171, 66, 151, 165, 53, 31, 131, 13, 64, 46, // ...B..5...@. - 176, 27, 139, 9, 49, 201, 218, 192, 74, 242, 79, 90, // ....1...J.OZ - 66, 30, 155, 193, 246, 81, 234, 146, 167, 176, 117, 139, // B....Q....u. - 207, 141, 100, 140, 182, 66, 56, 197, 254, 113, 162, 232, // ..d..B8..q.. - 163, 181, 211, 108, 113, 143, 93, 175, 204, 180, 199, 225, // ...lq.]..... - 93, 84, 23, 148, 216, 81, 193, 99, 59, 123, 96, 229, // ]T...Q.c;{`. - 127, 114, 8, 237, 45, 35, 223, 188, 76, 234, 108, 99, // .r..-#..L.lc - 156, 211, 182, 8, 4, 146, 83, 97, 38, 59, 234, 229, // ......Sa&;.. - 110, 6, 132, 54, 174, 72, 25, 36, 154, 163, 105, 62, // n..6.H.$..i> - 82, 10, 140, 197, 182, 77, 129, 218, 60, 90, 100, 18, // R....M.......| - 163, 48, 87, 7, 57, 241, 128, 239, 43, 140, 99, 193, // .0W.9...+.c. - 151, 222, 239, 160, 46, 129, 242, 6, 208, 175, 28, 29, // ............ - 130, 117, 53, 244, 214, 134, 47, 243, 0, 17, 89, 77, // .u5.../...YM - 121, 240, 180, 187, 132, 169, 30, 93, 194, 240, 232, 217, // y......].... - 60, 95, 248, 181, 153, 170, 154, 172, 146, 162, 52, 190, // <_........4. - 158, 187, 30, 174, 250, 103, 128, 185, 167, 73, 236, 200, // .....g...I.. - 28, 227, 106, 162, 213, 193, 64, 74, 252, 189, 241, 146, // ..j...@J.... - 3, 50, 124, 99, 46, 170, 248, 2, 82, 221, 243, 229, // .2|c....R... - 171, 26, 226, 115, 54, 28, 215, 227, 49, 221, 215, 106, // ...s6...1..j - 9, 231, 178, 196, 225, 86, 248, 79, 92, 110, 57, 163, // .....V.O.n9. - 227, 101, 98, 47, 17, 204, 220, 36, 241, 1, 176, 69, // .eb/...$...E - 47, 171, 105, 159, 53, 15, 92, 87, 216, 10, 119, 129, // /.i.5..W..w. - 133, 240, 150, 242, 51, 4, 37, 143, 129, 170, 158, 31, // ....3.%..... - 239, 48, 238, 13, 228, 209, 136, 72, 245, 151, 210, 93, // .0.....H...] - 234, 26, 43, 194, 202, 195, 37, 114, 26, 217, 115, 66, // ..+...%r..sB - 8, 96, 177, 213, 203, 131, 177, 129, 187, 91, 156, 186, // .`.......[.. - 71, 5, 199, 84, 102, 122, 188, 185, 191, 106, 76, 180, // G..Tfz...jL. - 229, 252, 92, 208, 187, 17, 150, 48, 103, 252, 50, 129, // .......0g.2. - 185, 75, 215, 157, 36, 240, 237, 237, 116, 123, 197, 29, // .K..$...t{.. - 76, 28, 141, 57, 186, 154, 56, 246, 244, 51, 31, 176, // L..9..8..3.. - 63, 112, 65, 77, 18, 80, 102, 196, 88, 253, 128, 123, // ?pAM.Pf.X..{ - 237, 181, 51, 105, 193, 52, 227, 88, 102, 202, 158, 88, // ..3i.4.Xf..X - 192, 229, 136, 46, 80, 233, 164, 97, 227, 64, 237, 213, // ....P..a.@.. - 131, 108, 143, 139, 82, 171, 99, 161, 241, 121, 81, 228, // .l..R.c..yQ. - 5, 59, 195, 37, 162, 12, 106, 245, 158, 134, 195, 102, // .;.%..j....f - 133, 204, 205, 253, 131, 179, 91, 193, 65, 128, 118, 70, // ......[.A.vF - 54, 136, 209, 61, 106, 37, 202, 181, 99, 243, 254, 117, // 6..=j%..c..u - 248, 121, 107, 133, 177, 95, 173, 178, 125, 181, 46, 242, // .yk.._..}... - 91, 4, 155, 123, 104, 232, 9, 60, 179, 46, 135, 227, // [..{h..<.... - 22, 169, 14, 137, 100, 238, 229, 3, 27, 9, 177, 76, // ....d......L - 112, 26, 197, 149, 72, 121, 89, 80, 104, 236, 204, 181, // p...HyYPh... - 250, 174, 96, 146, 36, 29, 196, 209, 235, 39, 142, 147, // ..`.$....'.. - 149, 54, 65, 29, 226, 200, 78, 64, 65, 20, 116, 150, // .6A...N@A.t. - 198, 251, 183, 215, 240, 237, 220, 20, 166, 103, 109, 205, // .........gm. - 6, 184, 153, 144, 27, 143, 154, 112, 136, 29, 236, 15, // .......p.... - 220, 142, 244, 83, 218, 96, 144, 217, 162, 166, 236, 145, // ...S.`...... - 126, 136, 88, 63, 133, 216, 38, 175, 214, 230, 54, 59, // ~.X?..&...6; - 63, 102, 46, 33, 173, 155, 164, 212, 51, 251, 237, 13, // ?f.!....3... - 174, 214, 58, 155, 44, 161, 1, 158, 235, 195, 193, 159, // ..:.,....... - 167, 55, 26, 113, 172, 15, 150, 124, 76, 54, 58, 175, // .7.q...|L6:. - 43, 105, 110, 219, 79, 96, 144, 79, 88, 243, 222, 202, // +in.O`.OX... - 75, 249, 139, 124, 143, 150, 239, 104, 214, 31, 77, 206, // K..|...h..M. - 80, 254, 108, 2, 114, 249, 71, 27, 181, 201, 175, 141, // P.l.r.G..... - 44, 203, 79, 84, 123, 162, 118, 15, 138, 126, 239, 34, // ,.OT{.v..~." - 173, 181, 177, 251, 107, 239, 82, 106, 249, 30, 14, 153, // ....k.Rj.... - 32, 244, 60, 89, 165, 46, 209, 115, 1, 251, 196, 95, // ..!.....m. - 15, 231, 22, 225, 143, 241, 161, 219, 51, 136, 146, 154, // ........3... - 237, 176, 146, 195, 16, 134, 160, 231, 74, 18, 93, 88, // ........J.]X - 167, 169, 242, 88, 109, 146, 160, 4, 68, 65, 93, 127, // ...Xm...DA]. - 14, 199, 25, 230, 26, 220, 73, 56, 226, 67, 89, 208, // ......I8.CY. - 79, 173, 232, 72, 74, 15, 160, 233, 246, 144, 159, 193, // O..HJ....... - 0, 95, 174, 242, 238, 237, 197, 191, 126, 43, 255, 243, // ._......~+.. - 183, 12, 63, 141, 43, 124, 242, 226, 138, 31, 160, 136, // ..?.+|...... - 89, 109, 54, 141, 224, 0, 81, 22, 229, 226, 29, 138, // Ym6...Q..... - 92, 204, 60, 219, 249, 138, 59, 177, 130, 151, 194, 127, // ..<...;..... - 105, 32, 134, 147, 201, 132, 82, 121, 57, 84, 196, 225, // i ....Ry9T.. - 248, 12, 96, 39, 45, 4, 122, 6, 109, 215, 231, 242, // ..`'-.z.m... - 68, 194, 71, 192, 12, 213, 151, 234, 115, 122, 159, 155, // D.G.....sz.. - 55, 205, 0, 166, 145, 88, 95, 145, 163, 99, 1, 43, // 7....X_..c.+ - 0, 230, 28, 47, 169, 47, 56, 78, 234, 58, 128, 220, // ..././8N.:.. - 117, 8, 166, 196, 158, 159, 78, 37, 175, 117, 247, 78, // u.....N%.u.N - 138, 222, 54, 210, 97, 97, 150, 144, 66, 33, 83, 47, // ..6.aa..B!S/ - 17, 162, 21, 241, 8, 3, 162, 215, 122, 158, 44, 220, // ........z.,. - 152, 8, 99, 16, 242, 163, 101, 14, 167, 135, 7, 206, // ..c...e..... - 134, 175, 249, 185, 199, 204, 35, 4, 160, 116, 13, 215, // ......#..t.. - 88, 189, 18, 126, 62, 86, 25, 75, 52, 64, 158, 63, // X..~>V.K4@.? - 183, 219, 31, 126, 105, 129, 29, 131, 0, 167, 178, 113, // ...~i......q - 78, 185, 214, 98, 150, 81, 38, 120, 70, 44, 51, 163, // N..b.Q&xF,3. - 63, 29, 126, 106, 238, 65, 134, 159, 154, 97, 5, 26, // ?.~j.A...a.. - 91, 20, 52, 31, 208, 128, 74, 244, 216, 79, 181, 136, // [.4...J..O.. - 63, 135, 205, 205, 45, 242, 225, 11, 110, 38, 167, 248, // ?...-...n&.. - 245, 231, 192, 195, 99, 205, 250, 199, 244, 62, 133, 145, // ....c....>.. - 56, 62, 214, 138, 114, 190, 132, 180, 150, 174, 98, 232, // 8>..r.....b. - 249, 18, 212, 172, 168, 3, 28, 27, 62, 27, 218, 69, // ........>..E - 253, 86, 181, 165, 172, 45, 21, 7, 171, 123, 105, 232, // .V...-...{i. - 208, 206, 49, 28, 180, 164, 192, 74, 63, 147, 118, 22, // ..1....J?.v. - 167, 67, 76, 194, 61, 167, 2, 48, 166, 251, 191, 15, // .CL.=..0.... - 56, 74, 132, 251, 175, 17, 167, 179, 204, 39, 189, 220, // 8J.......'.. - 155, 168, 49, 20, 83, 125, 183, 205, 139, 234, 62, 124, // ..1.S}....>| - 22, 150, 207, 214, 208, 60, 254, 86, 155, 84, 254, 64, // .....<.V.T.@ - 37, 19, 157, 202, 152, 202, 109, 82, 72, 126, 67, 85, // %.....mRH~CU - 115, 79, 99, 51, 74, 242, 91, 106, 130, 91, 201, 81, // sOc3J.[j.[.Q - 142, 252, 211, 214, 222, 235, 184, 142, 48, 254, 111, 182, // ........0.o. - 126, 14, 239, 36, 170, 228, 247, 182, 250, 54, 220, 225, // ~..$.....6.. - 252, 182, 141, 127, 111, 199, 172, 228, 63, 108, 249, 187, // ....o...?l.. - 205, 86, 23, 56, 84, 110, 244, 69, 152, 197, 169, 150, // .V.8Tn.E.... - 191, 218, 142, 31, 244, 38, 151, 255, 180, 149, 179, 48, // .....&.....0 - 77, 151, 97, 116, 45, 181, 118, 45, 118, 85, 153, 107, // M.at-.v-vU.k - 232, 188, 93, 25, 184, 54, 206, 156, 124, 141, 179, 51, // ..]..6..|..3 - 14, 139, 221, 126, 250, 31, 255, 11, 22, 19, 178, 116, // ...~.......t - 138, 51, 0, 0, 0 // .3.. + 60, 33, 68, 79, 67, 84, 89, 80, 69, 32, 104, 116, // .. < + 104, 101, 97, 100, 62, 10, 32, 32, 32, 32, 60, 109, // head>. . + 32, 32, 32, 32, 60, 109, 101, 116, 97, 32, 104, 116, // . + 32, 32, 32, 32, 60, 109, 101, 116, 97, 32, 104, 116, // . + 32, 32, 60, 109, 101, 116, 97, 32, 110, 97, 109, 101, // . + 32, 32, 32, 32, 32, 32, 32, 60, 116, 105, 116, 108, // Mongoose E + 109, 98, 101, 100, 100, 101, 100, 32, 70, 105, 108, 101, // mbedded File + 115, 121, 116, 101, 109, 32, 101, 120, 97, 109, 112, 108, // sytem exampl + 101, 60, 47, 116, 105, 116, 108, 101, 62, 10, 32, 32, // e. + 32, 32, 60, 108, 105, 110, 107, 32, 114, 101, 108, 61, // . < + 47, 104, 101, 97, 100, 62, 10, 32, 32, 60, 98, 111, // /head>. . + 32, 60, 115, 99, 114, 105, 112, 116, 32, 116, 121, 112, // .< + 47, 104, 116, 109, 108, 62, 10, 0 // /html>. }; static const unsigned char v2[] = { - 31, 139, 8, 8, 219, 27, 244, 98, 0, 3, 109, 97, // .......b..ma - 105, 110, 46, 106, 115, 0, 165, 86, 237, 110, 219, 54, // in.js..V.n.6 - 20, 253, 239, 167, 184, 8, 6, 52, 65, 109, 41, 77, // .......4Am)M - 246, 1, 52, 138, 1, 55, 93, 129, 20, 93, 61, 204, // ..4..7]..]=. - 233, 218, 254, 43, 37, 210, 22, 91, 138, 84, 249, 97, // ...+%..[.T.a - 205, 11, 242, 46, 125, 150, 62, 217, 14, 37, 217, 177, // ....}.>..%.. - 19, 103, 195, 218, 95, 166, 36, 222, 123, 15, 207, 185, // .g.._.$.{... - 247, 208, 143, 130, 19, 228, 188, 149, 133, 127, 116, 54, // ..........t6 - 144, 85, 109, 172, 167, 107, 42, 135, 84, 250, 74, 13, // .Um..k*.T.J. - 201, 10, 205, 133, 165, 27, 154, 91, 83, 209, 163, 36, // .......[S..$ - 173, 173, 96, 133, 79, 42, 169, 147, 143, 14, 33, 131, // ..`.O*....!. - 65, 97, 180, 243, 244, 142, 206, 105, 30, 116, 225, 165, // Aa.....i.t.. - 209, 116, 120, 68, 215, 131, 1, 33, 218, 7, 171, 219, // .txD...!.... - 84, 31, 240, 152, 113, 185, 164, 66, 49, 231, 206, 15, // T...q..B1... - 16, 229, 153, 212, 194, 30, 140, 241, 5, 223, 202, 147, // ............ - 245, 39, 39, 218, 44, 7, 227, 201, 179, 233, 155, 43, // .''.,......+ - 122, 51, 203, 210, 242, 164, 223, 181, 149, 193, 154, 166, // z3.......... - 143, 189, 155, 89, 141, 126, 217, 124, 193, 183, 122, 220, // ...Y.~.|..z. - 45, 54, 111, 136, 46, 132, 99, 168, 79, 51, 51, 247, // -6o...c.O33. - 13, 179, 130, 94, 121, 158, 144, 116, 84, 10, 198, 63, // ...^y..tT..? - 7, 102, 189, 176, 130, 127, 253, 34, 53, 61, 15, 185, // .f....."5=.. - 146, 122, 72, 127, 136, 58, 174, 10, 50, 115, 186, 180, // .zH..:..2s.. - 66, 49, 205, 147, 219, 26, 105, 189, 83, 112, 231, 121, // B1....i.Sp.y - 26, 44, 40, 54, 118, 69, 214, 24, 239, 40, 103, 197, // .,(6vE...(g. - 39, 242, 134, 78, 142, 143, 127, 28, 82, 83, 10, 77, // '..N....RS.M - 191, 25, 189, 48, 6, 82, 188, 21, 57, 205, 132, 93, // ...0.R..9..] - 130, 243, 87, 50, 183, 204, 174, 190, 126, 225, 98, 41, // ..W2....~.b) - 148, 169, 43, 161, 61, 242, 68, 108, 192, 154, 229, 118, // ..+.=.Dl...v - 60, 216, 148, 152, 184, 189, 41, 22, 86, 52, 132, 51, // <.....).V4.3 - 212, 166, 14, 138, 89, 233, 87, 4, 216, 84, 49, 200, // ....Y.W..T1. - 34, 56, 153, 184, 199, 151, 130, 230, 70, 41, 211, 72, // "8......F).H - 189, 160, 149, 96, 214, 13, 99, 204, 201, 241, 147, 211, // ...`..c..... - 13, 79, 13, 115, 36, 80, 27, 4, 184, 18, 145, 64, // .O.s$P.....@ - 31, 5, 148, 58, 8, 146, 56, 210, 54, 196, 88, 97, // ...:..8.6.Xa - 3, 172, 182, 102, 41, 57, 90, 44, 212, 109, 107, 33, // ...f)9Z,.mk! - 208, 128, 142, 37, 83, 1, 105, 138, 0, 94, 42, 97, // ...%S.i..^*a - 221, 195, 76, 190, 21, 20, 245, 65, 158, 208, 150, 45, // ..L....A...- - 217, 18, 111, 42, 28, 182, 77, 180, 201, 128, 67, 233, // ..o*..M...C. - 21, 101, 114, 252, 2, 101, 130, 22, 244, 211, 241, 113, // .er..e.....q - 150, 202, 49, 112, 86, 53, 211, 82, 56, 194, 25, 26, // ..1pV5.R8... - 161, 84, 252, 173, 4, 151, 161, 106, 161, 186, 138, 225, // .T.....j.... - 157, 147, 127, 11, 202, 131, 67, 71, 58, 39, 182, 240, // ......CG:'.. - 16, 184, 44, 194, 134, 58, 244, 134, 138, 107, 52, 65, // ..,..:...k4A - 44, 239, 140, 10, 177, 87, 93, 236, 29, 70, 53, 179, // ,....W]..F5. - 128, 22, 64, 194, 220, 88, 10, 174, 13, 105, 9, 198, // ..@..X...i.. - 204, 96, 193, 252, 94, 153, 16, 139, 49, 228, 148, 175, // .`..^...1... - 232, 245, 100, 54, 33, 150, 27, 102, 187, 192, 75, 141, // ..d6!..f..K. - 78, 212, 44, 214, 96, 138, 102, 53, 43, 4, 205, 124, // N.,.`.f5+..| - 251, 28, 195, 182, 96, 198, 221, 57, 52, 138, 194, 204, // ....`..94... - 165, 173, 186, 61, 96, 76, 250, 100, 135, 212, 150, 214, // ...=`L.d.... - 153, 212, 200, 20, 53, 30, 110, 68, 46, 163, 200, 127, // ....5.nD.... - 129, 44, 14, 44, 81, 85, 144, 206, 3, 128, 71, 229, // .,.,QU....G. - 208, 34, 210, 36, 64, 189, 214, 186, 61, 27, 151, 209, // .".$@...=... - 59, 242, 224, 5, 137, 42, 23, 60, 70, 186, 245, 76, // ;....*.4..`.z - 17, 96, 1, 163, 198, 148, 99, 119, 95, 227, 150, 170, // .`....cw_... - 238, 196, 194, 71, 138, 175, 74, 244, 164, 235, 224, 175, // ...G..J..... - 39, 61, 197, 168, 247, 102, 176, 94, 246, 139, 15, 103, // '=...f.^...g - 131, 155, 179, 181, 31, 189, 255, 110, 63, 58, 189, 239, // .......n?:.. - 71, 155, 182, 187, 69, 109, 197, 83, 216, 211, 233, 55, // G...Em.S...7 - 219, 83, 22, 212, 150, 52, 153, 146, 219, 66, 81, 6, // .S...4...BQ. - 85, 172, 152, 159, 31, 148, 222, 215, 238, 105, 154, 86, // U........i.V - 125, 251, 36, 141, 75, 15, 198, 123, 154, 41, 75, 217, // }.$.K..{.)K. - 78, 134, 17, 136, 189, 213, 166, 193, 62, 215, 53, 93, // N.......>.5] - 228, 27, 52, 55, 198, 126, 138, 131, 175, 58, 183, 217, // ..47.~...:.. - 130, 146, 238, 96, 249, 79, 100, 75, 48, 152, 72, 3, // ...`.OdK0.H. - 84, 127, 94, 76, 95, 99, 117, 31, 201, 196, 242, 32, // T.^L_cu.... - 181, 25, 181, 35, 233, 101, 174, 208, 177, 177, 211, 93, // ...#.e.....] - 215, 29, 121, 144, 202, 143, 96, 61, 177, 125, 219, 166, // ..y...`=.}.. - 153, 94, 77, 40, 212, 156, 121, 225, 182, 51, 117, 30, // .^M(..y..3u. - 166, 217, 66, 180, 134, 195, 153, 43, 219, 60, 223, 14, // ..B....+.<.. - 190, 138, 57, 18, 208, 1, 248, 213, 243, 126, 189, 151, // ..9......~.. - 74, 152, 5, 32, 142, 12, 28, 230, 210, 92, 209, 239, // J.. ........ - 138, 97, 52, 108, 245, 29, 165, 123, 13, 71, 198, 37, // .a4l...{.G.% - 32, 102, 75, 212, 233, 108, 47, 2, 83, 11, 11, 246, // fK..l/.S... - 160, 153, 91, 57, 47, 170, 214, 107, 96, 223, 163, 218, // ..[9/..k`... - 52, 208, 181, 146, 133, 53, 177, 155, 45, 76, 29, 198, // 4....5..-L.. - 120, 23, 217, 255, 128, 182, 128, 42, 33, 143, 168, 210, // x......*!... - 162, 243, 136, 180, 250, 232, 192, 208, 203, 253, 200, 54, // ...........6 - 109, 246, 146, 45, 217, 172, 176, 178, 246, 36, 244, 2, // m..-.....$.. - 83, 213, 98, 188, 72, 47, 30, 63, 126, 128, 168, 44, // S.b.H/.?~.., - 189, 157, 131, 173, 17, 191, 63, 58, 63, 239, 222, 236, // ......?:?... - 89, 62, 158, 238, 248, 112, 55, 144, 249, 238, 13, 188, // Y>...p7..... - 59, 100, 237, 193, 37, 108, 102, 1, 30, 163, 213, 105, // ;d..%lf....i - 184, 164, 47, 77, 192, 17, 209, 139, 240, 29, 156, 24, // ../M........ - 119, 74, 33, 97, 185, 235, 73, 191, 35, 107, 155, 131, // wJ!a..I.#k.. - 139, 90, 153, 85, 119, 29, 150, 65, 115, 220, 169, 109, // .Z.Uw..As..m - 120, 37, 149, 106, 193, 192, 42, 37, 152, 107, 175, 224, // x%.j..*%.k.. - 46, 79, 116, 35, 161, 151, 210, 26, 29, 123, 247, 78, // .Ot#.....{.N - 218, 7, 88, 248, 87, 163, 155, 212, 245, 142, 213, 161, // ..X.W....... - 80, 237, 246, 249, 93, 86, 62, 25, 63, 99, 14, 255, // P...]V>.?c.. - 96, 126, 93, 235, 244, 66, 42, 209, 55, 17, 23, 21, // `~]..B*.7... - 38, 22, 91, 6, 89, 95, 236, 135, 235, 242, 240, 221, // &.[.Y_...... - 209, 205, 160, 47, 186, 253, 250, 253, 230, 117, 15, 5, // .../.....u.. - 255, 29, 184, 105, 18, 163, 149, 97, 28, 112, 96, 184, // ...i...a.p`. - 231, 227, 254, 207, 227, 97, 121, 8, 140, 71, 67, 226, // .....ay..GC. - 112, 255, 120, 232, 36, 55, 124, 117, 116, 54, 248, 7, // p.x.$7|ut6.. - 71, 33, 75, 134, 124, 10, 0, 0, 0 // G!K.|... -}; -static const unsigned char v3[] = { 39, 117, 115, 101, 32, 115, 116, 114, 105, 99, 116, 39, // 'use strict' 59, 10, 105, 109, 112, 111, 114, 116, 32, 123, 32, 104, // ;.import { h 44, 32, 104, 116, 109, 108, 44, 32, 114, 101, 110, 100, // , html, rend @@ -774,7 +273,7 @@ static const unsigned char v3[] = { 112, 41, 44, 32, 100, 111, 99, 117, 109, 101, 110, 116, // p), document 46, 98, 111, 100, 121, 41, 59, 10, 0 // .body);. }; -static const unsigned char v4[] = { +static const unsigned char v3[] = { 118, 97, 114, 32, 101, 44, 110, 44, 95, 44, 116, 44, // var e,n,_,t, 111, 44, 114, 44, 117, 44, 108, 61, 123, 125, 44, 105, // o,r,u,l={},i 61, 91, 93, 44, 99, 61, 47, 97, 99, 105, 116, 124, // =[],c=/acit| @@ -1876,147 +1375,7 @@ static const unsigned char v4[] = { 115, 101, 69, 114, 114, 111, 114, 66, 111, 117, 110, 100, // seErrorBound 97, 114, 121, 125, 59, 10, 0 // ary};. }; -static const unsigned char v5[] = { - 60, 33, 68, 79, 67, 84, 89, 80, 69, 32, 104, 116, // .. < - 104, 101, 97, 100, 62, 10, 32, 32, 32, 32, 60, 109, // head>. . - 32, 32, 32, 32, 60, 109, 101, 116, 97, 32, 104, 116, // . - 32, 32, 32, 32, 60, 109, 101, 116, 97, 32, 104, 116, // . - 32, 32, 60, 109, 101, 116, 97, 32, 110, 97, 109, 101, // . - 32, 32, 32, 32, 32, 32, 32, 60, 116, 105, 116, 108, // Mongoose E - 109, 98, 101, 100, 100, 101, 100, 32, 70, 105, 108, 101, // mbedded File - 115, 121, 116, 101, 109, 32, 101, 120, 97, 109, 112, 108, // sytem exampl - 101, 60, 47, 116, 105, 116, 108, 101, 62, 10, 32, 32, // e. - 32, 32, 60, 108, 105, 110, 107, 32, 114, 101, 108, 61, // . < - 47, 104, 101, 97, 100, 62, 10, 32, 32, 60, 98, 111, // /head>. . - 32, 60, 115, 99, 114, 105, 112, 116, 32, 116, 121, 112, // .< - 47, 104, 116, 109, 108, 62, 10, 0 // /html>. -}; -static const unsigned char v6[] = { - 31, 139, 8, 8, 219, 27, 244, 98, 0, 3, 105, 110, // .......b..in - 100, 101, 120, 46, 104, 116, 109, 108, 0, 141, 145, 77, // dex.html...M - 75, 3, 49, 16, 134, 239, 253, 21, 99, 206, 166, 139, // K.1.....c... - 55, 193, 205, 130, 212, 22, 60, 136, 30, 90, 208, 99, // 7.....<..Z.c - 154, 140, 205, 104, 62, 214, 205, 244, 99, 255, 189, 217, // ...h>...c... - 110, 133, 5, 17, 60, 205, 7, 47, 15, 51, 239, 91, // n...<../.3.[ - 95, 61, 60, 47, 214, 111, 47, 75, 112, 28, 124, 51, // _= - 82, 102, 53, 76, 247, 11, 203, 208, 90, 0, 251, 237, // Rf5L....Z... - 44, 132, 66, 114, 251, 230, 89, 9, 61, 233, 201, 42, // ,.Br..Y.=..* - 183, 139, 233, 148, 178, 71, 132, 89, 141, 14, 229, 150, // .....G.Y.... - 43, 52, 53, 74, 74, 210, 220, 120, 102, 26, 108, 67, // +45JJ..xf.lC - 113, 20, 29, 155, 158, 228, 107, 39, 196, 72, 139, 175, // q.....k'.H.. - 229, 176, 44, 105, 5, 92, 16, 56, 175, 225, 222, 199, // ..,i...8.... - 148, 55, 108, 148, 26, 28, 237, 6, 246, 244, 248, 163, // .7l......... - 119, 163, 171, 55, 18, 98, 60, 203, 192, 102, 80, 68, // w..7.b<..fPD - 241, 40, 117, 42, 213, 89, 211, 30, 17, 231, 35, 202, // .(u*.Y....#. - 157, 120, 255, 186, 46, 46, 234, 1, 157, 57, 188, 87, // .x.......9.W - 152, 65, 59, 139, 38, 160, 69, 34, 203, 208, 187, 220, // .A;.&.E".... - 177, 91, 79, 69, 102, 220, 185, 35, 62, 81, 226, 29, // .[OEf..#>Q.. - 238, 219, 24, 60, 217, 220, 155, 41, 208, 149, 141, 51, // ...<...)...3 - 90, 213, 243, 6, 173, 205, 168, 69, 107, 166, 127, 148, // Z......Ek... - 65, 88, 220, 35, 247, 7, 165, 252, 240, 160, 60, 185, // AX.#......<. - 232, 80, 51, 209, 131, 236, 35, 212, 149, 30, 106, 45, // .P3...#...j- - 253, 219, 210, 208, 245, 125, 178, 133, 33, 233, 70, 121, // .....}..!.Fy - 159, 163, 224, 79, 197, 234, 241, 158, 252, 212, 72, 197, // ...O......H. - 253, 163, 83, 224, 124, 43, 172, 251, 77, 28, 193, 21, // ..S.|+..M... - 153, 105, 70, 139, 127, 126, 63, 170, 87, 208, 173, 192, // .iF..~?.W... - 235, 43, 152, 6, 241, 73, 150, 59, 221, 6, 55, 13, // .+...I.;..7. - 87, 231, 148, 200, 66, 98, 151, 165, 155, 77, 148, 90, // W...Bb...M.Z - 135, 212, 115, 145, 22, 69, 72, 237, 66, 102, 91, 134, // ..s..EH.Bf[. - 240, 115, 8, 111, 54, 139, 90, 219, 144, 41, 159, 23, // .s.o6.Z..).. - 165, 54, 81, 38, 154, 171, 12, 225, 167, 229, 88, 79, // .6Q&......XO - 33, 83, 44, 167, 42, 66, 38, 143, 166, 138, 87, 95, // !S,.*B&...W_ - 78, 21, 237, 62, 15, 245, 163, 3, 198, 41, 249, 22, // N..>.....).. - 221, 74, 89, 145, 225, 105, 252, 142, 224, 15, 15, 235, // .JY..i...... - 64, 244, 132, 205, 183, 254, 228, 94, 227, 82, 244, 50, // @......^.R.2 - 95, 112, 249, 84, 201, 201, 61, 74, 185, 212, 5, 63, // _p.T..=J...? - 252, 15, 225, 232, 67, 124, 39, 7, 0, 0, 0 // ....C|'... -}; -static const unsigned char v8[] = { +static const unsigned char v4[] = { 42, 32, 123, 32, 98, 111, 120, 45, 115, 105, 122, 105, // * { box-sizi 110, 103, 58, 32, 98, 111, 114, 100, 101, 114, 45, 98, // ng: border-b 111, 120, 59, 32, 125, 10, 104, 116, 109, 108, 44, 32, // ox; }.html, @@ -2178,14 +1537,10 @@ static const struct packed_file { size_t size; time_t mtime; } packed_files[] = { - {"/web_root/preact.min.js.gz", v1, sizeof(v1), 1660165083}, - {"/web_root/main.js.gz", v2, sizeof(v2), 1660165083}, - {"/web_root/main.js", v3, sizeof(v3), 1660586478}, - {"/web_root/preact.min.js", v4, sizeof(v4), 1660586478}, - {"/web_root/index.html", v5, sizeof(v5), 1660586478}, - {"/web_root/index.html.gz", v6, sizeof(v6), 1660165083}, - {"/web_root/style.css.gz", v7, sizeof(v7), 1660165083}, - {"/web_root/style.css", v8, sizeof(v8), 1660586478}, + {"/web_root/index.html", v1, sizeof(v1), 1660216320}, + {"/web_root/main.js", v2, sizeof(v2), 1660216320}, + {"/web_root/preact.min.js", v3, sizeof(v3), 1660216320}, + {"/web_root/style.css", v4, sizeof(v4), 1660216320}, {NULL, NULL, 0, 0} }; diff --git a/examples/http-streaming-client/main.c b/examples/http-streaming-client/main.c index 51b4efb4..40f78cfd 100644 --- a/examples/http-streaming-client/main.c +++ b/examples/http-streaming-client/main.c @@ -21,13 +21,6 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { if (ev == MG_EV_CONNECT) { // Connected to server. Extract host name from URL struct mg_str host = mg_url_host(s_url); - - // If s_url is https://, tell client connection to use TLS - if (mg_url_is_ssl(s_url)) { - struct mg_tls_opts opts = {.ca = "ca.pem", .srvname = host}; - mg_tls_init(c, &opts); - } - // Send request mg_printf(c, "GET %s HTTP/1.1\r\n" @@ -54,15 +47,21 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { } int main(int argc, char *argv[]) { - struct mg_mgr mgr; // Event manager - bool done = false; // Event handler flips it to true - const char *log_level = getenv("V"); // Log level - if (log_level == NULL) log_level = "3"; // If not set, set to DEBUG - mg_log_set(atoi(log_level)); // Set to 0 to disable debug log - if (argc > 1) s_url = argv[1]; // Use URL from command line - mg_mgr_init(&mgr); // Initialise event manager + struct mg_mgr mgr; // Event manager + bool done = false; // Event handler flips it to true + const char *log_level = getenv("V"); // Log level + + mg_mgr_init(&mgr); // Initialise event manager + if (log_level == NULL) log_level = "3"; // If not set, set to DEBUG + mg_log_set(atoi(log_level)); // Set to 0 to disable debug log + if (argc > 1) s_url = argv[1]; // Use URL from command line + + struct mg_tls_opts opts = {.client_ca = mg_str(CA_ALL)}; + mg_tls_ctx_init(&mgr, &opts); + mg_http_connect(&mgr, s_url, fn, &done); // Create client connection while (!done) mg_mgr_poll(&mgr, 1000); // Infinite event loop mg_mgr_free(&mgr); // Free resources + return 0; } diff --git a/examples/mqtt-client/main.c b/examples/mqtt-client/main.c index 796c6328..177bea3f 100644 --- a/examples/mqtt-client/main.c +++ b/examples/mqtt-client/main.c @@ -20,7 +20,9 @@ static struct mg_connection *s_conn; // Client connection // Handle interrupts, like Ctrl-C static int s_signo; -static void signal_handler(int signo) { s_signo = signo; } +static void signal_handler(int signo) { + s_signo = signo; +} static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { if (ev == MG_EV_OPEN) { @@ -29,12 +31,6 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { } else if (ev == MG_EV_ERROR) { // On error, log error message MG_ERROR(("%lu ERROR %s", c->id, (char *) ev_data)); - } else if (ev == MG_EV_CONNECT) { - // If target URL is SSL/TLS, command client connection to use TLS - if (mg_url_is_ssl(s_url)) { - struct mg_tls_opts opts = {.ca = "ca.pem"}; - mg_tls_init(c, &opts); - } } else if (ev == MG_EV_MQTT_OPEN) { // MQTT connect is successful struct mg_str subt = mg_str(s_sub_topic); @@ -105,6 +101,7 @@ int main(int argc, char *argv[]) { signal(SIGTERM, signal_handler); // manager loop on SIGINT and SIGTERM mg_mgr_init(&mgr); + mg_tls_init_client(&mgr, "ca.pem"); mg_timer_add(&mgr, 3000, MG_TIMER_REPEAT | MG_TIMER_RUN_NOW, timer_fn, &mgr); while (s_signo == 0) mg_mgr_poll(&mgr, 1000); // Event loop, 1s timeout mg_mgr_free(&mgr); // Finished, cleanup diff --git a/examples/smtp-client/main.c b/examples/smtp-client/main.c index e52e3bbb..2ec367ed 100644 --- a/examples/smtp-client/main.c +++ b/examples/smtp-client/main.c @@ -1,7 +1,6 @@ #include "mongoose.h" -static const char *server = - "tcp://mail.domain.com:587"; // Change this! Your mail server and port +static const char *server = "tcp://smtp.gmail.com:587"; static const char *user = "aaa@domain.com"; // Change this! Your mail account static const char *pass = "xxxxxxxxxxxxxx"; // Change this! Your mail password static const char *to = "bbb@domain.com"; // Change this! Destination email @@ -29,8 +28,8 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { mg_printf(c, "STARTTLS\r\n"); *state = STARTTLS_WAIT; } else if (*state == STARTTLS_WAIT) { - struct mg_tls_opts opts = {.ca = "ca.pem"}; - mg_tls_init(c, &opts); + struct mg_str host = mg_url_host(server); + mg_tls_init(c, host); *state = AUTH; } else if (*state == AUTH) { char a[100], b[300] = ""; @@ -75,7 +74,11 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { int main(void) { struct mg_mgr mgr; mg_mgr_init(&mgr); - // mg_log_set(MG_LL_VERBOSE); + + struct mg_tls_opts opts = {.client_ca = mg_str(CA_GLOBALSIGN_RSA)}; + mg_tls_ctx_init(&mgr, &opts); + + mg_log_set(MG_LL_DEBUG); mg_connect(&mgr, server, fn, NULL); while (s_quit == false) mg_mgr_poll(&mgr, 1000); return 0; diff --git a/examples/stm32/nucleo-f746zg-make-baremetal-builtin/Makefile b/examples/stm32/nucleo-f746zg-make-baremetal-builtin/Makefile index 04360584..1ac58e7c 100644 --- a/examples/stm32/nucleo-f746zg-make-baremetal-builtin/Makefile +++ b/examples/stm32/nucleo-f746zg-make-baremetal-builtin/Makefile @@ -41,7 +41,7 @@ mbedtls: # mbedTLS library git clone --depth 1 -b v2.28.2 https://github.com/mbed-tls/mbedtls $@ ifeq ($(TLS), mbedtls) -CFLAGS += -DMG_ENABLE_MBEDTLS=1 -Wno-conversion -Imbedtls/include +CFLAGS += -DMG_TLS=MG_TLS_MBED -Wno-conversion -Imbedtls/include CFLAGS += -DMBEDTLS_CONFIG_FILE=\"mbedtls_config.h\" mbedtls/library/*.c firmware.elf: mbedtls endif @@ -58,4 +58,4 @@ test: update # grep 'MQTT connected' /tmp/output.txt # Check for MQTT connection success clean: - $(RM) firmware.* *.su cmsis_core cmsis_f7 + $(RM) firmware.* *.su cmsis_core cmsis_f7 mbedtls diff --git a/examples/stm32/nucleo-f746zg-make-baremetal-builtin/mbedtls_config.h b/examples/stm32/nucleo-f746zg-make-baremetal-builtin/mbedtls_config.h index 14d8f994..6e93f56d 100644 --- a/examples/stm32/nucleo-f746zg-make-baremetal-builtin/mbedtls_config.h +++ b/examples/stm32/nucleo-f746zg-make-baremetal-builtin/mbedtls_config.h @@ -2,10 +2,12 @@ #include #define MBEDTLS_NO_PLATFORM_ENTROPY -//#define MBEDTLS_ENTROPY_HARDWARE_ALT +#define MBEDTLS_ENTROPY_HARDWARE_ALT #define MBEDTLS_SSL_OUT_CONTENT_LEN 2048 #define MBEDTLS_ALLOW_PRIVATE_ACCESS #define MBEDTLS_HAVE_TIME +#define MBEDTLS_SSL_SESSION_TICKETS +#define MBEDTLS_SSL_KEEP_PEER_CERTIFICATE #define MBEDTLS_CIPHER_MODE_CBC #define MBEDTLS_ECP_DP_SECP256R1_ENABLED @@ -40,9 +42,10 @@ #define MBEDTLS_AES_FEWER_TABLES #define MBEDTLS_PEM_PARSE_C #define MBEDTLS_BASE64_C +#define MBEDTLS_SSL_TICKET_C -// TLS 1.2 #define MBEDTLS_SSL_PROTO_TLS1_2 +#define MBEDTLS_SSL_PROTO_TLS1_3 #define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED #define MBEDTLS_GCM_C #define MBEDTLS_ECDH_C diff --git a/examples/tcp/main.c b/examples/tcp/main.c index 8e76d473..3889ac62 100644 --- a/examples/tcp/main.c +++ b/examples/tcp/main.c @@ -12,6 +12,41 @@ static struct c_res_s { struct mg_connection *c; } c_res; +// Self signed certificates +// https://mongoose.ws/documentation/tutorials/tls/#self-signed-certificates +static const char *s_tls_ca = + "-----BEGIN CERTIFICATE-----\n" + "MIIBqjCCAU+gAwIBAgIUESoOPGqMhf9uarzblVFwzrQweMcwCgYIKoZIzj0EAwIw\n" + "RDELMAkGA1UEBhMCSUUxDzANBgNVBAcMBkR1YmxpbjEQMA4GA1UECgwHQ2VzYW50\n" + "YTESMBAGA1UEAwwJVGVzdCBSb290MCAXDTIwMDUwOTIxNTE0NFoYDzIwNTAwNTA5\n" + "MjE1MTQ0WjBEMQswCQYDVQQGEwJJRTEPMA0GA1UEBwwGRHVibGluMRAwDgYDVQQK\n" + "DAdDZXNhbnRhMRIwEAYDVQQDDAlUZXN0IFJvb3QwWTATBgcqhkjOPQIBBggqhkjO\n" + "PQMBBwNCAAQsq9ECZiSW1xI+CVBP8VDuUehVA166sR2YsnJ5J6gbMQ1dUCH/QvLa\n" + "dBdeU7JlQcH8hN5KEbmM9BnZxMor6ussox0wGzAMBgNVHRMEBTADAQH/MAsGA1Ud\n" + "DwQEAwIBrjAKBggqhkjOPQQDAgNJADBGAiEAnHFsAIwGQQyRL81B04dH6d86Iq0l\n" + "fL8OKzndegxOaB0CIQCPwSIwEGFdURDqCC0CY2dnMrUGY5ZXu3hHCojZGS7zvg==\n" + "-----END CERTIFICATE-----\n"; + +static const char *s_tls_cert = + "-----BEGIN CERTIFICATE-----\n" + "MIIBhzCCASygAwIBAgIUbnMoVd8TtWH1T09dANkK2LU6IUswCgYIKoZIzj0EAwIw\n" + "RDELMAkGA1UEBhMCSUUxDzANBgNVBAcMBkR1YmxpbjEQMA4GA1UECgwHQ2VzYW50\n" + "YTESMBAGA1UEAwwJVGVzdCBSb290MB4XDTIwMDUwOTIxNTE0OVoXDTMwMDUwOTIx\n" + "NTE0OVowETEPMA0GA1UEAwwGc2VydmVyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD\n" + "QgAEkuBGnInDN6l06zVVQ1VcrOvH5FDu9MC6FwJc2e201P8hEpq0Q/SJS2nkbSuW\n" + "H/wBTTBaeXN2uhlBzMUWK790KKMvMC0wCQYDVR0TBAIwADALBgNVHQ8EBAMCA6gw\n" + "EwYDVR0lBAwwCgYIKwYBBQUHAwEwCgYIKoZIzj0EAwIDSQAwRgIhAPo6xx7LjCdZ\n" + "QY133XvLjAgVFrlucOZHONFVQuDXZsjwAiEAzHBNligA08c5U3SySYcnkhurGg50\n" + "BllCI0eYQ9ggp/o=\n" + "-----END CERTIFICATE-----\n"; + +static const char *s_tls_key = + "-----BEGIN PRIVATE KEY-----\n" + "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQglNni0t9Dg9icgG8w\n" + "kbfxWSS+TuNgbtNybIQXcm3NHpmhRANCAASS4EacicM3qXTrNVVDVVys68fkUO70\n" + "wLoXAlzZ7bTU/yESmrRD9IlLaeRtK5Yf/AFNMFp5c3a6GUHMxRYrv3Qo\n" + "-----END PRIVATE KEY-----\n"; + // CLIENT event handler static void cfn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { int *i = &((struct c_res_s *) fn_data)->i; @@ -19,16 +54,11 @@ static void cfn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { MG_INFO(("CLIENT has been initialized")); } else if (ev == MG_EV_CONNECT) { MG_INFO(("CLIENT connected")); -#if MG_ENABLE_MBEDTLS || MG_ENABLE_OPENSSL - struct mg_tls_opts opts = {.ca = "ss_ca.pem"}; - mg_tls_init(c, &opts); - MG_INFO(("CLIENT initialized TLS")); -#endif *i = 1; // do something } else if (ev == MG_EV_READ) { struct mg_iobuf *r = &c->recv; MG_INFO(("CLIENT got data: %.*s", r->len, r->buf)); - r->len = 0; // Tell Mongoose we've consumed data + r->len = 0; // Tell Mongoose we've consumed data } else if (ev == MG_EV_CLOSE) { MG_INFO(("CLIENT disconnected")); // signal we are done @@ -55,15 +85,6 @@ static void sfn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { MG_INFO(("SERVER is listening")); } else if (ev == MG_EV_ACCEPT) { MG_INFO(("SERVER accepted a connection")); -#if MG_ENABLE_MBEDTLS || MG_ENABLE_OPENSSL - struct mg_tls_opts opts = { - //.ca = "ss_ca.pem", // Uncomment to enable two-way SSL - .cert = "ss_server.pem", // Certificate PEM file - .certkey = "ss_server.pem", // This pem contains both cert and key - }; - mg_tls_init(c, &opts); - MG_INFO(("SERVER initialized TLS")); -#endif } else if (ev == MG_EV_READ) { struct mg_iobuf *r = &c->recv; MG_INFO(("SERVER got data: %.*s", r->len, r->buf)); @@ -96,9 +117,14 @@ int main(void) { struct mg_connection *c; mg_log_set(MG_LL_INFO); // Set log level - mg_mgr_init(&mgr); // Initialize event manager - mg_timer_add(&mgr, 15000, MG_TIMER_REPEAT | MG_TIMER_RUN_NOW, timer_fn, - &mgr); // Init timer for demo purposes, 15s + mg_mgr_init(&mgr); // Initialize event manager + + struct mg_tls_opts opts = {.client_ca = mg_str(s_tls_ca), + .server_cert = mg_str(s_tls_cert), + .server_key = mg_str(s_tls_key)}; + mg_tls_ctx_init(&mgr, &opts); + + mg_timer_add(&mgr, 15000, MG_TIMER_REPEAT | MG_TIMER_RUN_NOW, timer_fn, &mgr); c = mg_listen(&mgr, s_lsn, sfn, NULL); // Create server connection if (c == NULL) { MG_INFO(("SERVER cant' open a connection")); diff --git a/mongoose.c b/mongoose.c index 0148f269..f29373cc 100644 --- a/mongoose.c +++ b/mongoose.c @@ -3715,6 +3715,10 @@ struct mg_connection *mg_connect(struct mg_mgr *mgr, const char *url, MG_DEBUG(("%lu %p %s", c->id, c->fd, url)); mg_call(c, MG_EV_OPEN, NULL); mg_resolve(c, url); + if (mg_url_is_ssl(url)) { + struct mg_str host = mg_url_host(url); + mg_tls_init(c, host); + } } return c; } @@ -3735,6 +3739,7 @@ struct mg_connection *mg_listen(struct mg_mgr *mgr, const char *url, c->fn = fn; c->fn_data = fn_data; mg_call(c, MG_EV_OPEN, NULL); + if (mg_url_is_ssl(url)) c->is_tls = 1; // Accepted connection must MG_DEBUG(("%lu %p %s", c->id, c->fd, url)); } return c; @@ -3778,6 +3783,7 @@ void mg_mgr_free(struct mg_mgr *mgr) { #if MG_ENABLE_EPOLL if (mgr->epoll_fd >= 0) close(mgr->epoll_fd), mgr->epoll_fd = -1; #endif + mg_tls_ctx_free(mgr); } void mg_mgr_init(struct mg_mgr *mgr) { @@ -4897,6 +4903,7 @@ static void accept_conn(struct mg_mgr *mgr, struct mg_connection *lsn) { &c->rem, mg_print_ip_port, &c->loc)); mg_call(c, MG_EV_OPEN, NULL); mg_call(c, MG_EV_ACCEPT, NULL); + if (lsn->is_tls) mg_tls_init(c, mg_str("")); } } @@ -5492,9 +5499,9 @@ void mg_timer_poll(struct mg_timer **head, uint64_t now_ms) { #endif -#if !MG_ENABLE_MBEDTLS && !MG_ENABLE_OPENSSL && !MG_ENABLE_CUSTOM_TLS -void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) { - (void) opts; +#if MG_TLS == MG_TLS_NONE +void mg_tls_init(struct mg_connection *c, struct mg_str hostname) { + (void) hostname; mg_error(c, "TLS is not enabled"); } void mg_tls_handshake(struct mg_connection *c) { @@ -5513,6 +5520,12 @@ size_t mg_tls_pending(struct mg_connection *c) { (void) c; return 0; } +void mg_tls_ctx_free(struct mg_mgr *mgr) { + mgr->tls_ctx = NULL; +} +void mg_tls_ctx_init(struct mg_mgr *mgr, const struct mg_tls_opts *opts) { + (void) opts, (void) mgr; +} #endif #ifdef MG_ENABLE_LINES @@ -5522,7 +5535,7 @@ size_t mg_tls_pending(struct mg_connection *c) { -#if MG_ENABLE_MBEDTLS +#if MG_TLS == MG_TLS_MBED #if defined(MBEDTLS_VERSION_NUMBER) && MBEDTLS_VERSION_NUMBER >= 0x03000000 #define MGRNG , rng_get, NULL @@ -5533,11 +5546,7 @@ size_t mg_tls_pending(struct mg_connection *c) { void mg_tls_free(struct mg_connection *c) { struct mg_tls *tls = (struct mg_tls *) c->tls; if (tls != NULL) { - free(tls->cafile); mbedtls_ssl_free(&tls->ssl); - mbedtls_pk_free(&tls->pk); - mbedtls_x509_crt_free(&tls->ca); - mbedtls_x509_crt_free(&tls->cert); mbedtls_ssl_config_free(&tls->conf); free(tls); c->tls = NULL; @@ -5590,7 +5599,7 @@ static void debug_cb(void *c, int lev, const char *s, int n, const char *s2) { (void) s; } -#if defined(MBEDTLS_VERSION_NUMBER) && MBEDTLS_VERSION_NUMBER >= 0x03000000 +#ifdef MBEDTLS_SSL_SESSION_TICKETS static int rng_get(void *p_rng, unsigned char *buf, size_t len) { (void) p_rng; mg_random(buf, len); @@ -5598,28 +5607,20 @@ static int rng_get(void *p_rng, unsigned char *buf, size_t len) { } #endif -static struct mg_str mg_loadfile(struct mg_fs *fs, const char *path) { - size_t n = 0; - if (path[0] == '-') return mg_str(path); - char *p = mg_file_read(fs, path, &n); - return mg_str_n(p, n); -} - -void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) { - struct mg_fs *fs = opts->fs == NULL ? &mg_fs_posix : opts->fs; +void mg_tls_init(struct mg_connection *c, struct mg_str hostname) { + struct mg_tls_ctx *ctx = (struct mg_tls_ctx *) c->mgr->tls_ctx; struct mg_tls *tls = (struct mg_tls *) calloc(1, sizeof(*tls)); int rc = 0; + c->tls = tls; if (c->tls == NULL) { mg_error(c, "TLS OOM"); goto fail; } + MG_DEBUG(("%lu Setting TLS", c->id)); mbedtls_ssl_init(&tls->ssl); mbedtls_ssl_config_init(&tls->conf); - mbedtls_x509_crt_init(&tls->ca); - mbedtls_x509_crt_init(&tls->cert); - mbedtls_pk_init(&tls->pk); mbedtls_ssl_conf_dbg(&tls->conf, debug_cb, c); #if defined(MG_MBEDTLS_DEBUG_LEVEL) mbedtls_debug_set_threshold(MG_MBEDTLS_DEBUG_LEVEL); @@ -5632,60 +5633,47 @@ void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) { goto fail; } mbedtls_ssl_conf_rng(&tls->conf, mbed_rng, c); - if (opts->ca == NULL || strcmp(opts->ca, "*") == 0) { - mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_NONE); - } else if (opts->ca != NULL && opts->ca[0] != '\0') { -#if defined(MBEDTLS_X509_CA_CHAIN_ON_DISK) - tls->cafile = strdup(opts->ca); - rc = mbedtls_ssl_conf_ca_chain_file(&tls->conf, tls->cafile, NULL); - if (rc != 0) { - mg_error(c, "parse on-disk chain(%s) err %#x", tls->cafile, -rc); - goto fail; - } -#else - struct mg_str s = mg_loadfile(fs, opts->ca); - rc = mbedtls_x509_crt_parse(&tls->ca, (uint8_t *) s.ptr, s.len + 1); - if (opts->ca[0] != '-') free((char *) s.ptr); - if (rc != 0) { - mg_error(c, "parse(%s) err %#x", opts->ca, -rc); - goto fail; - } - mbedtls_ssl_conf_ca_chain(&tls->conf, &tls->ca, NULL); -#endif - if (opts->srvname.len > 0) { - char *x = mg_mprintf("%.*s", (int) opts->srvname.len, opts->srvname.ptr); - mbedtls_ssl_set_hostname(&tls->ssl, x); - free(x); - } + + if (c->is_client && ctx->client_ca.version) { + mbedtls_ssl_conf_ca_chain(&tls->conf, &ctx->client_ca, NULL); mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED); + if (hostname.ptr != NULL && hostname.ptr[0] != '\0') { + struct mg_addr addr; + if (!mg_aton(hostname, &addr)) { // if srvname is not an IP address + char *host = mg_mprintf("%.*s", (int) hostname.len, hostname.ptr); + mbedtls_ssl_set_hostname(&tls->ssl, host); + free(host); + } + } + } else if (!c->is_client && ctx->server_ca.version) { + mbedtls_ssl_conf_ca_chain(&tls->conf, &ctx->server_ca, NULL); + mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED); + } else { + mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_NONE); } - if (opts->cert != NULL && opts->cert[0] != '\0') { - struct mg_str s = mg_loadfile(fs, opts->cert); - const char *key = opts->certkey == NULL ? opts->cert : opts->certkey; - rc = mbedtls_x509_crt_parse(&tls->cert, (uint8_t *) s.ptr, s.len + 1); - if (opts->cert[0] != '-') free((char *) s.ptr); - if (rc != 0) { - mg_error(c, "parse(%s) err %#x", opts->cert, -rc); - goto fail; - } - s = mg_loadfile(fs, key); - rc = mbedtls_pk_parse_key(&tls->pk, (uint8_t *) s.ptr, s.len + 1, NULL, - 0 MGRNG); - if (key[0] != '-') free((char *) s.ptr); - if (rc != 0) { - mg_error(c, "tls key(%s) %#x", key, -rc); - goto fail; - } - rc = mbedtls_ssl_conf_own_cert(&tls->conf, &tls->cert, &tls->pk); - if (rc != 0) { - mg_error(c, "own cert %#x", -rc); - goto fail; - } + if (c->is_client && ctx->client_cert.version && + (rc = mbedtls_ssl_conf_own_cert(&tls->conf, &ctx->client_cert, + &ctx->client_key)) != 0) { + mg_error(c, "own cert %#x", -rc); + goto fail; } + if (!c->is_client && ctx->server_cert.version && + (rc = mbedtls_ssl_conf_own_cert(&tls->conf, &ctx->server_cert, + &ctx->server_key)) != 0) { + mg_error(c, "own cert %#x", -rc); + goto fail; + } +#ifdef MBEDTLS_SSL_SESSION_TICKETS + mbedtls_ssl_conf_session_tickets_cb(&tls->conf, mbedtls_ssl_ticket_write, + mbedtls_ssl_ticket_parse, + &ctx->ticket_ctx); +#endif + if ((rc = mbedtls_ssl_setup(&tls->ssl, &tls->conf)) != 0) { mg_error(c, "setup err %#x", -rc); goto fail; } + c->tls = tls; c->is_tls = 1; c->is_tls_hs = 1; @@ -5720,6 +5708,79 @@ long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) { if (n <= 0) return MG_IO_ERR; return n; } + +static bool load_cert(struct mg_str str, mbedtls_x509_crt *p) { + int rc; + if (str.ptr == NULL || str.ptr[0] == '\0' || str.ptr[0] == '*') return true; + if (str.ptr[0] == '-') str.len++; // PEM, include trailing NUL + if ((rc = mbedtls_x509_crt_parse(p, (uint8_t *) str.ptr, str.len)) != 0) { + MG_ERROR(("cert err %#x", -rc)); + return false; + } + return true; +} + +static bool load_key(struct mg_str str, mbedtls_pk_context *p) { + int rc; + if (str.ptr == NULL || str.ptr[0] == '\0' || str.ptr[0] == '*') return true; + if (str.ptr[0] == '-') str.len++; // PEM, include trailing NUL + if ((rc = mbedtls_pk_parse_key(p, (uint8_t *) str.ptr, str.len, NULL, + 0 MGRNG)) != 0) { + MG_ERROR(("key err %#x", -rc)); + return false; + } + return true; +} + +void mg_tls_ctx_init(struct mg_mgr *mgr, const struct mg_tls_opts *opts) { + struct mg_tls_ctx *ctx = (struct mg_tls_ctx *) calloc(1, sizeof(*ctx)); + if (ctx == NULL) goto fail; + MG_DEBUG(("Setting up TLS context")); + +#if defined(MG_MBEDTLS_DEBUG_LEVEL) + mbedtls_debug_set_threshold(MG_MBEDTLS_DEBUG_LEVEL); +#endif + + if (!load_cert(opts->client_ca, &ctx->client_ca)) goto fail; + if (!load_cert(opts->server_ca, &ctx->server_ca)) goto fail; + if (!load_cert(opts->client_cert, &ctx->client_cert)) goto fail; + if (!load_cert(opts->server_cert, &ctx->server_cert)) goto fail; + if (!load_key(opts->server_key, &ctx->server_key)) goto fail; + if (!load_key(opts->client_key, &ctx->client_key)) goto fail; + +#ifdef MBEDTLS_SSL_SESSION_TICKETS + { + int rc; + mbedtls_ssl_ticket_init(&ctx->ticket_ctx); + if ((rc = mbedtls_ssl_ticket_setup(&ctx->ticket_ctx, rng_get, NULL, + MBEDTLS_CIPHER_AES_128_GCM, 86400)) != + 0) { + MG_ERROR(("setup session tickets err %#x", -rc)); + goto fail; + } + } +#endif + mgr->tls_ctx = ctx; + return; +fail: + mg_tls_ctx_free(mgr); +} + +void mg_tls_ctx_free(struct mg_mgr *mgr) { + struct mg_tls_ctx *ctx = (struct mg_tls_ctx *) mgr->tls_ctx; + if (ctx != NULL) { + mbedtls_x509_crt_free(&ctx->server_cert); + mbedtls_pk_free(&ctx->server_key); + mbedtls_x509_crt_free(&ctx->client_cert); + mbedtls_pk_free(&ctx->client_key); + mbedtls_x509_crt_free(&ctx->client_ca); +#ifdef MBEDTLS_SSL_SESSION_TICKETS + mbedtls_ssl_ticket_free(&ctx->ticket_ctx); +#endif + free(ctx); + mgr->tls_ctx = NULL; + } +} #endif #ifdef MG_ENABLE_LINES @@ -5728,7 +5789,7 @@ long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) { -#if MG_ENABLE_OPENSSL +#if MG_TLS == MG_TLS_OPENSSL static int mg_tls_err(struct mg_tls *tls, int res) { int err = SSL_get_error(tls->ssl, res); // We've just fetched the last error from the queue. @@ -5747,38 +5808,63 @@ static int mg_tls_err(struct mg_tls *tls, int res) { return err; } -void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) { +static STACK_OF(X509_INFO) * load_ca_certs(const char *ca, int ca_len) { + BIO *ca_bio = BIO_new_mem_buf(ca, ca_len); + if (!ca_bio) return NULL; + STACK_OF(X509_INFO) *certs = PEM_X509_INFO_read_bio(ca_bio, NULL, NULL, NULL); + BIO_free(ca_bio); + return certs; +} + +static bool add_ca_certs(SSL_CTX *ctx, STACK_OF(X509_INFO) * certs) { + X509_STORE *cert_store = SSL_CTX_get_cert_store(ctx); + for (int i = 0; i < sk_X509_INFO_num(certs); i++) { + X509_INFO *cert_info = sk_X509_INFO_value(certs, i); + if (cert_info->x509 && !X509_STORE_add_cert(cert_store, cert_info->x509)) + return false; + } + return true; +} + +static EVP_PKEY *load_key(const char *key, int key_len) { + BIO *key_bio = BIO_new_mem_buf(key, key_len); + if (!key_bio) return NULL; + EVP_PKEY *priv_key = PEM_read_bio_PrivateKey(key_bio, NULL, 0, NULL); + BIO_free(key_bio); + return priv_key; +} + +static X509 *load_cert(const char *cert, int cert_len) { + BIO *cert_bio = BIO_new_mem_buf(cert, cert_len); + if (!cert_bio) return NULL; + X509 *x509 = PEM_read_bio_X509(cert_bio, NULL, 0, NULL); + BIO_free(cert_bio); + return x509; +} + +void mg_tls_init(struct mg_connection *c, struct mg_str hostname) { + struct mg_tls_ctx *ctx = (struct mg_tls_ctx *) c->mgr->tls_ctx; struct mg_tls *tls = (struct mg_tls *) calloc(1, sizeof(*tls)); - const char *id = "mongoose"; - static unsigned char s_initialised = 0; - int rc; + + if (ctx == NULL) { + mg_error(c, "TLS context not initialized"); + goto fail; + } if (tls == NULL) { mg_error(c, "TLS OOM"); goto fail; } - if (!s_initialised) { - SSL_library_init(); - s_initialised++; - } - MG_DEBUG(("%lu Setting TLS, CA: %s, cert: %s, key: %s", c->id, - opts->ca == NULL ? "null" : opts->ca, - opts->cert == NULL ? "null" : opts->cert, - opts->certkey == NULL ? "null" : opts->certkey)); - tls->ctx = c->is_client ? SSL_CTX_new(SSLv23_client_method()) - : SSL_CTX_new(SSLv23_server_method()); + tls->ctx = c->is_client ? SSL_CTX_new(TLS_client_method()) + : SSL_CTX_new(TLS_server_method()); if ((tls->ssl = SSL_new(tls->ctx)) == NULL) { mg_error(c, "SSL_new"); goto fail; } - SSL_set_session_id_context(tls->ssl, (const uint8_t *) id, - (unsigned) strlen(id)); - // Disable deprecated protocols - SSL_set_options(tls->ssl, SSL_OP_NO_SSLv2); - SSL_set_options(tls->ssl, SSL_OP_NO_SSLv3); - SSL_set_options(tls->ssl, SSL_OP_NO_TLSv1); - SSL_set_options(tls->ssl, SSL_OP_NO_TLSv1_1); + + SSL_set_min_proto_version(tls->ssl, TLS1_2_VERSION); + #ifdef MG_ENABLE_OPENSSL_NO_COMPRESSION SSL_set_options(tls->ssl, SSL_OP_NO_COMPRESSION); #endif @@ -5786,45 +5872,54 @@ void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) { SSL_set_options(tls->ssl, SSL_OP_CIPHER_SERVER_PREFERENCE); #endif - if (opts->ca != NULL && opts->ca[0] != '\0') { - SSL_set_verify(tls->ssl, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, - NULL); - if ((rc = SSL_CTX_load_verify_locations(tls->ctx, opts->ca, NULL)) != 1) { - mg_error(c, "load('%s') %d err %d", opts->ca, rc, mg_tls_err(tls, rc)); - goto fail; + if (c->is_client) { + if (ctx->client_ca) { + SSL_set_verify(tls->ssl, + SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); + if (!add_ca_certs(tls->ctx, ctx->client_ca)) goto fail; + } + if (ctx->client_cert && ctx->client_key) { + if (SSL_use_certificate(tls->ssl, ctx->client_cert) != 1) { + mg_error(c, "SSL_CTX_use_certificate"); + goto fail; + } + if (SSL_use_PrivateKey(tls->ssl, ctx->client_key) != 1) { + mg_error(c, "SSL_CTX_use_PrivateKey"); + goto fail; + } + } + } else { + if (ctx->server_ca) { + SSL_set_verify(tls->ssl, + SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); + if (!add_ca_certs(tls->ctx, ctx->server_ca)) goto fail; + } + if (ctx->server_cert && ctx->server_key) { + if (SSL_use_certificate(tls->ssl, ctx->server_cert) != 1) { + mg_error(c, "SSL_CTX_use_certificate"); + goto fail; + } + if (SSL_use_PrivateKey(tls->ssl, ctx->server_key) != 1) { + mg_error(c, "SSL_CTX_use_PrivateKey"); + goto fail; + } } } - if (opts->cert != NULL && opts->cert[0] != '\0') { - const char *key = opts->certkey; - if (key == NULL) key = opts->cert; - if ((rc = SSL_use_certificate_file(tls->ssl, opts->cert, 1)) != 1) { - mg_error(c, "Invalid SSL cert, err %d", mg_tls_err(tls, rc)); - goto fail; - } else if ((rc = SSL_use_PrivateKey_file(tls->ssl, key, 1)) != 1) { - mg_error(c, "Invalid SSL key, err %d", mg_tls_err(tls, rc)); - goto fail; -#if OPENSSL_VERSION_NUMBER > 0x10100000L - } else if ((rc = SSL_use_certificate_chain_file(tls->ssl, opts->cert)) != - 1) { - mg_error(c, "Invalid chain, err %d", mg_tls_err(tls, rc)); - goto fail; -#endif - } else { - SSL_set_mode(tls->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); + + SSL_set_mode(tls->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); #if OPENSSL_VERSION_NUMBER > 0x10002000L - SSL_set_ecdh_auto(tls->ssl, 1); + SSL_set_ecdh_auto(tls->ssl, 1); #endif - } - } - if (opts->ciphers != NULL) SSL_set_cipher_list(tls->ssl, opts->ciphers); + #if OPENSSL_VERSION_NUMBER >= 0x10100000L - if (opts->srvname.len > 0) { - char *s = mg_mprintf("%.*s", (int) opts->srvname.len, opts->srvname.ptr); + if (c->is_client && hostname.ptr && hostname.ptr[0] != '\0') { + char *s = mg_mprintf("%.*s", (int) hostname.len, hostname.ptr); SSL_set1_host(tls->ssl, s); SSL_set_tlsext_host_name(tls->ssl, s); free(s); } #endif + c->tls = tls; c->is_tls = 1; c->is_tls_hs = 1; @@ -5833,6 +5928,7 @@ void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) { } MG_DEBUG(("%lu SSL %s OK", c->id, c->is_accepted ? "accept" : "client")); return; + fail: c->is_closing = 1; free(tls); @@ -5882,6 +5978,70 @@ long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) { if (n <= 0) return MG_IO_ERR; return n; } + +void mg_tls_ctx_free(struct mg_mgr *mgr) { + struct mg_tls_ctx *ctx = (struct mg_tls_ctx *) mgr->tls_ctx; + if (ctx) { + if (ctx->server_cert) X509_free(ctx->server_cert); + if (ctx->server_key) EVP_PKEY_free(ctx->server_key); + if (ctx->server_ca) + sk_X509_INFO_pop_free(ctx->server_ca, X509_INFO_free); + if (ctx->client_cert) X509_free(ctx->client_cert); + if (ctx->client_key) EVP_PKEY_free(ctx->client_key); + if (ctx->client_ca) + sk_X509_INFO_pop_free(ctx->client_ca, X509_INFO_free); + free(ctx); + mgr->tls_ctx = NULL; + } +} + +void mg_tls_ctx_init(struct mg_mgr *mgr, const struct mg_tls_opts *opts) { + static unsigned char s_initialised = 0; + if (!s_initialised) { + SSL_library_init(); + s_initialised++; + } + + struct mg_tls_ctx *ctx = (struct mg_tls_ctx *) calloc(1, sizeof(*ctx)); + if (ctx == NULL) return; + + if (opts->server_cert.ptr && opts->server_cert.ptr[0] != '\0') { + struct mg_str key = opts->server_key; + if (!key.ptr) key = opts->server_cert; + if (!(ctx->server_cert = + load_cert(opts->server_cert.ptr, (int) opts->server_cert.len))) + goto fail; + if (!(ctx->server_key = load_key(key.ptr, (int) key.len))) goto fail; + } + + if (opts->server_ca.ptr && opts->server_ca.ptr[0] != '\0') { + if (!(ctx->server_ca = + load_ca_certs(opts->server_ca.ptr, (int) opts->server_ca.len))) + goto fail; + } + + if (opts->client_cert.ptr && opts->client_cert.ptr[0] != '\0') { + struct mg_str key = opts->client_key; + if (!key.ptr) key = opts->client_cert; + if (!(ctx->client_cert = + load_cert(opts->client_cert.ptr, (int) opts->client_cert.len))) + goto fail; + if (!(ctx->client_key = load_key(key.ptr, (int) key.len))) goto fail; + } + + if (opts->client_ca.ptr && opts->client_ca.ptr[0] != '\0') { + if (!(ctx->client_ca = + load_ca_certs(opts->client_ca.ptr, (int) opts->client_ca.len))) + goto fail; + } + + mgr->tls_ctx = ctx; + return; +fail: + MG_ERROR(("TLS ctx init error")); + mg_tls_ctx_free(mgr); +} + #endif #ifdef MG_ENABLE_LINES @@ -8087,6 +8247,7 @@ static struct mg_connection *accept_conn(struct mg_connection *lsn, c->fn_data = lsn->fn_data; mg_call(c, MG_EV_OPEN, NULL); mg_call(c, MG_EV_ACCEPT, NULL); + if (lsn->is_tls) mg_tls_init(c, mg_str("")); return c; } diff --git a/mongoose.h b/mongoose.h index 92ea0fba..29e6f077 100644 --- a/mongoose.h +++ b/mongoose.h @@ -701,18 +701,6 @@ struct timeval { #define MG_ENABLE_FATFS 0 #endif -#ifndef MG_ENABLE_MBEDTLS -#define MG_ENABLE_MBEDTLS 0 -#endif - -#ifndef MG_ENABLE_OPENSSL -#define MG_ENABLE_OPENSSL 0 -#endif - -#ifndef MG_ENABLE_CUSTOM_TLS -#define MG_ENABLE_CUSTOM_TLS 0 -#endif - #ifndef MG_ENABLE_SSI #define MG_ENABLE_SSI 0 #endif @@ -1331,21 +1319,32 @@ void mg_http_serve_ssi(struct mg_connection *c, const char *root, const char *fullpath); +#define MG_TLS_NONE 0 // No TLS support +#define MG_TLS_MBED 1 // mbedTLS +#define MG_TLS_OPENSSL 2 // OpenSSL +#define MG_TLS_BUILTIN 3 // Built-in +#define MG_TLS_CUSTOM 4 // Custom implementation + +#ifndef MG_TLS +#define MG_TLS MG_TLS_NONE +#endif + struct mg_tls_opts { - const char *ca; // CA certificate file. For both listeners and clients - const char *crl; // Certificate Revocation List. For clients - const char *cert; // Certificate - const char *certkey; // Certificate key - const char *ciphers; // Cipher list - struct mg_str srvname; // If not empty, enables server name verification - struct mg_fs *fs; // FS API for reading certificate files + struct mg_str client_ca; + struct mg_str server_ca; + struct mg_str server_cert; + struct mg_str server_key; + struct mg_str client_cert; + struct mg_str client_key; }; -void mg_tls_init(struct mg_connection *, const struct mg_tls_opts *); +void mg_tls_ctx_init(struct mg_mgr *, const struct mg_tls_opts *); +void mg_tls_ctx_free(struct mg_mgr *); +void mg_tls_init(struct mg_connection *, struct mg_str hostname); void mg_tls_free(struct mg_connection *); long mg_tls_send(struct mg_connection *, const void *buf, size_t len); long mg_tls_recv(struct mg_connection *, void *buf, size_t len); @@ -1358,27 +1357,45 @@ void mg_tls_handshake(struct mg_connection *); -#if MG_ENABLE_MBEDTLS +#if MG_TLS == MG_TLS_MBED #include #include #include +#include + +struct mg_tls_ctx { + mbedtls_x509_crt server_ca; // Parsed CA certificate + mbedtls_x509_crt client_ca; // Parsed CA certificate + mbedtls_x509_crt server_cert; // Parsed server certificate + mbedtls_pk_context server_key; // Parsed server private key context + mbedtls_x509_crt client_cert; // Parsed client certificate + mbedtls_pk_context client_key; // Parsed client private key context +#ifdef MBEDTLS_SSL_SESSION_TICKETS + mbedtls_ssl_ticket_context ticket_ctx; // Session tickets context +#endif +}; struct mg_tls { - char *cafile; // CA certificate path - mbedtls_x509_crt ca; // Parsed CA certificate - mbedtls_x509_crt cert; // Parsed certificate mbedtls_ssl_context ssl; // SSL/TLS context mbedtls_ssl_config conf; // SSL-TLS config - mbedtls_pk_context pk; // Private key context }; #endif -#if MG_ENABLE_OPENSSL +#if MG_TLS == MG_TLS_OPENSSL #include #include +struct mg_tls_ctx { + X509 *server_cert; + EVP_PKEY *server_key; + STACK_OF(X509_INFO) *server_ca; + X509 *client_cert; + EVP_PKEY *client_key; + STACK_OF(X509_INFO) *client_ca; +}; + struct mg_tls { SSL_CTX *ctx; SSL *ssl; @@ -1750,6 +1767,165 @@ struct mg_tcpip_driver_tm4c_data { int mdc_cr; // Valid values: -1, 0, 1, 2, 3 }; + +#define CA_ISRG_ROOT_X2 \ + "-----BEGIN CERTIFICATE-----\n" \ + "MIICGzCCAaGgAwIBAgIQQdKd0XLq7qeAwSxs6S+HUjAKBggqhkjOPQQDAzBPMQsw\n" \ + "CQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2gg\n" \ + "R3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMjAeFw0yMDA5MDQwMDAwMDBaFw00\n" \ + "MDA5MTcxNjAwMDBaME8xCzAJBgNVBAYTAlVTMSkwJwYDVQQKEyBJbnRlcm5ldCBT\n" \ + "ZWN1cml0eSBSZXNlYXJjaCBHcm91cDEVMBMGA1UEAxMMSVNSRyBSb290IFgyMHYw\n" \ + "EAYHKoZIzj0CAQYFK4EEACIDYgAEzZvVn4CDCuwJSvMWSj5cz3es3mcFDR0HttwW\n" \ + "+1qLFNvicWDEukWVEYmO6gbf9yoWHKS5xcUy4APgHoIYOIvXRdgKam7mAHf7AlF9\n" \ + "ItgKbppbd9/w+kHsOdx1ymgHDB/qo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0T\n" \ + "AQH/BAUwAwEB/zAdBgNVHQ4EFgQUfEKWrt5LSDv6kviejM9ti6lyN5UwCgYIKoZI\n" \ + "zj0EAwMDaAAwZQIwe3lORlCEwkSHRhtFcP9Ymd70/aTSVaYgLXTWNLxBo1BfASdW\n" \ + "tL4ndQavEi51mI38AjEAi/V3bNTIZargCyzuFJ0nN6T5U6VR5CmD1/iQMVtCnwr1\n" \ + "/q4AaOeMSQ+2b1tbFfLn\n" \ + "-----END CERTIFICATE-----\n" + +#define CA_ISRG_ROOT_X1 \ + "-----BEGIN CERTIFICATE-----\n" \ + "MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw\n" \ + "TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh\n" \ + "cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4\n" \ + "WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu\n" \ + "ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY\n" \ + "MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc\n" \ + "h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+\n" \ + "0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U\n" \ + "A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW\n" \ + "T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH\n" \ + "B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC\n" \ + "B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv\n" \ + "KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn\n" \ + "OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn\n" \ + "jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw\n" \ + "qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI\n" \ + "rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV\n" \ + "HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq\n" \ + "hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL\n" \ + "ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ\n" \ + "3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK\n" \ + "NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5\n" \ + "ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur\n" \ + "TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC\n" \ + "jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc\n" \ + "oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq\n" \ + "4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA\n" \ + "mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d\n" \ + "emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=\n" \ + "-----END CERTIFICATE-----\n" + +#define CA_GOOGLE_TRUST \ + "-----BEGIN CERTIFICATE-----\n" \ + "MIIBxTCCAWugAwIBAgINAfD3nVndblD3QnNxUDAKBggqhkjOPQQDAjBEMQswCQYD\n" \ + "VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzERMA8G\n" \ + "A1UEAxMIR1RTIExUU1IwHhcNMTgxMTAxMDAwMDQyWhcNNDIxMTAxMDAwMDQyWjBE\n" \ + "MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM\n" \ + "QzERMA8GA1UEAxMIR1RTIExUU1IwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATN\n" \ + "8YyO2u+yCQoZdwAkUNv5c3dokfULfrA6QJgFV2XMuENtQZIG5HUOS6jFn8f0ySlV\n" \ + "eORCxqFyjDJyRn86d+Iko0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUw\n" \ + "AwEB/zAdBgNVHQ4EFgQUPv7/zFLrvzQ+PfNA0OQlsV+4u1IwCgYIKoZIzj0EAwID\n" \ + "SAAwRQIhAPKuf/VtBHqGw3TUwUIq7TfaExp3bH7bjCBmVXJupT9FAiBr0SmCtsuk\n" \ + "miGgpajjf/gFigGM34F9021bCWs1MbL0SA==\n" \ + "-----END CERTIFICATE-----\n" + +#define CA_GLOBALSIGN_EC \ + "-----BEGIN CERTIFICATE-----\n" \ + "MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEk\n" \ + "MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpH\n" \ + "bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX\n" \ + "DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD\n" \ + "QSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu\n" \ + "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprlOQcJ\n" \ + "FspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAw\n" \ + "DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61F\n" \ + "uOJAf/sKbvu+M8k8o4TVMAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGX\n" \ + "kPoUVy0D7O48027KqGx2vKLeuwIgJ6iFJzWbVsaj8kfSt24bAgAXqmemFZHe+pTs\n" \ + "ewv4n4Q=\n" \ + "-----END CERTIFICATE-----\n" + +#define CA_GLOBALSIGN_RSA \ + "-----BEGIN CERTIFICATE-----\n" \ + "MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG\n" \ + "A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv\n" \ + "b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw\n" \ + "MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i\n" \ + "YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT\n" \ + "aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ\n" \ + "jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp\n" \ + "xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp\n" \ + "1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG\n" \ + "snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ\n" \ + "U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8\n" \ + "9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E\n" \ + "BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B\n" \ + "AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz\n" \ + "yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE\n" \ + "38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP\n" \ + "AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad\n" \ + "DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME\n" \ + "HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==\n" \ + "-----END CERTIFICATE-----\n" + +#define CA_DIGICERT \ + "-----BEGIN CERTIFICATE-----\n" \ + "MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh\n" \ + "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n" \ + "d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD\n" \ + "QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT\n" \ + "MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n" \ + "b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG\n" \ + "9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB\n" \ + "CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97\n" \ + "nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt\n" \ + "43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P\n" \ + "T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4\n" \ + "gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO\n" \ + "BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR\n" \ + "TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw\n" \ + "DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr\n" \ + "hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg\n" \ + "06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF\n" \ + "PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls\n" \ + "YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk\n" \ + "CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=\n" \ + "-----END CERTIFICATE-----\n" + +#define CA_AMAZON_4 \ + "-----BEGIN CERTIFICATE-----\n" \ + "MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5\n" \ + "MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g\n" \ + "Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG\n" \ + "A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg\n" \ + "Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi\n" \ + "9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk\n" \ + "M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB\n" \ + "/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB\n" \ + "MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw\n" \ + "CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW\n" \ + "1KyLa2tJElMzrdfkviT8tQp21KW8EA==\n" \ + "-----END CERTIFICATE-----\n" + +#define CA_AMAZON_3 \ + "-----BEGIN CERTIFICATE-----\n" \ + "MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5\n" \ + "MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g\n" \ + "Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG\n" \ + "A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg\n" \ + "Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl\n" \ + "ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j\n" \ + "QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr\n" \ + "ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr\n" \ + "BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM\n" \ + "YyRIHN8wfdVoOw==\n" \ + "-----END CERTIFICATE-----\n" + +#define CA_ALL \ + CA_ISRG_ROOT_X1 CA_ISRG_ROOT_X2 CA_GOOGLE_TRUST CA_GLOBALSIGN_EC \ + CA_GLOBALSIGN_RSA CA_DIGICERT CA_AMAZON_4 CA_AMAZON_3 + #ifdef __cplusplus } #endif diff --git a/src/certs.h b/src/certs.h new file mode 100644 index 00000000..c6658d51 --- /dev/null +++ b/src/certs.h @@ -0,0 +1,159 @@ +#pragma once + +#define CA_ISRG_ROOT_X2 \ + "-----BEGIN CERTIFICATE-----\n" \ + "MIICGzCCAaGgAwIBAgIQQdKd0XLq7qeAwSxs6S+HUjAKBggqhkjOPQQDAzBPMQsw\n" \ + "CQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2gg\n" \ + "R3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMjAeFw0yMDA5MDQwMDAwMDBaFw00\n" \ + "MDA5MTcxNjAwMDBaME8xCzAJBgNVBAYTAlVTMSkwJwYDVQQKEyBJbnRlcm5ldCBT\n" \ + "ZWN1cml0eSBSZXNlYXJjaCBHcm91cDEVMBMGA1UEAxMMSVNSRyBSb290IFgyMHYw\n" \ + "EAYHKoZIzj0CAQYFK4EEACIDYgAEzZvVn4CDCuwJSvMWSj5cz3es3mcFDR0HttwW\n" \ + "+1qLFNvicWDEukWVEYmO6gbf9yoWHKS5xcUy4APgHoIYOIvXRdgKam7mAHf7AlF9\n" \ + "ItgKbppbd9/w+kHsOdx1ymgHDB/qo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0T\n" \ + "AQH/BAUwAwEB/zAdBgNVHQ4EFgQUfEKWrt5LSDv6kviejM9ti6lyN5UwCgYIKoZI\n" \ + "zj0EAwMDaAAwZQIwe3lORlCEwkSHRhtFcP9Ymd70/aTSVaYgLXTWNLxBo1BfASdW\n" \ + "tL4ndQavEi51mI38AjEAi/V3bNTIZargCyzuFJ0nN6T5U6VR5CmD1/iQMVtCnwr1\n" \ + "/q4AaOeMSQ+2b1tbFfLn\n" \ + "-----END CERTIFICATE-----\n" + +#define CA_ISRG_ROOT_X1 \ + "-----BEGIN CERTIFICATE-----\n" \ + "MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw\n" \ + "TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh\n" \ + "cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4\n" \ + "WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu\n" \ + "ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY\n" \ + "MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc\n" \ + "h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+\n" \ + "0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U\n" \ + "A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW\n" \ + "T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH\n" \ + "B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC\n" \ + "B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv\n" \ + "KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn\n" \ + "OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn\n" \ + "jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw\n" \ + "qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI\n" \ + "rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV\n" \ + "HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq\n" \ + "hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL\n" \ + "ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ\n" \ + "3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK\n" \ + "NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5\n" \ + "ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur\n" \ + "TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC\n" \ + "jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc\n" \ + "oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq\n" \ + "4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA\n" \ + "mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d\n" \ + "emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=\n" \ + "-----END CERTIFICATE-----\n" + +#define CA_GOOGLE_TRUST \ + "-----BEGIN CERTIFICATE-----\n" \ + "MIIBxTCCAWugAwIBAgINAfD3nVndblD3QnNxUDAKBggqhkjOPQQDAjBEMQswCQYD\n" \ + "VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzERMA8G\n" \ + "A1UEAxMIR1RTIExUU1IwHhcNMTgxMTAxMDAwMDQyWhcNNDIxMTAxMDAwMDQyWjBE\n" \ + "MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM\n" \ + "QzERMA8GA1UEAxMIR1RTIExUU1IwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATN\n" \ + "8YyO2u+yCQoZdwAkUNv5c3dokfULfrA6QJgFV2XMuENtQZIG5HUOS6jFn8f0ySlV\n" \ + "eORCxqFyjDJyRn86d+Iko0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUw\n" \ + "AwEB/zAdBgNVHQ4EFgQUPv7/zFLrvzQ+PfNA0OQlsV+4u1IwCgYIKoZIzj0EAwID\n" \ + "SAAwRQIhAPKuf/VtBHqGw3TUwUIq7TfaExp3bH7bjCBmVXJupT9FAiBr0SmCtsuk\n" \ + "miGgpajjf/gFigGM34F9021bCWs1MbL0SA==\n" \ + "-----END CERTIFICATE-----\n" + +#define CA_GLOBALSIGN_EC \ + "-----BEGIN CERTIFICATE-----\n" \ + "MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEk\n" \ + "MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpH\n" \ + "bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX\n" \ + "DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD\n" \ + "QSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu\n" \ + "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprlOQcJ\n" \ + "FspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAw\n" \ + "DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61F\n" \ + "uOJAf/sKbvu+M8k8o4TVMAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGX\n" \ + "kPoUVy0D7O48027KqGx2vKLeuwIgJ6iFJzWbVsaj8kfSt24bAgAXqmemFZHe+pTs\n" \ + "ewv4n4Q=\n" \ + "-----END CERTIFICATE-----\n" + +#define CA_GLOBALSIGN_RSA \ + "-----BEGIN CERTIFICATE-----\n" \ + "MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG\n" \ + "A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv\n" \ + "b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw\n" \ + "MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i\n" \ + "YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT\n" \ + "aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ\n" \ + "jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp\n" \ + "xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp\n" \ + "1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG\n" \ + "snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ\n" \ + "U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8\n" \ + "9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E\n" \ + "BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B\n" \ + "AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz\n" \ + "yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE\n" \ + "38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP\n" \ + "AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad\n" \ + "DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME\n" \ + "HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==\n" \ + "-----END CERTIFICATE-----\n" + +#define CA_DIGICERT \ + "-----BEGIN CERTIFICATE-----\n" \ + "MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh\n" \ + "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n" \ + "d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD\n" \ + "QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT\n" \ + "MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n" \ + "b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG\n" \ + "9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB\n" \ + "CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97\n" \ + "nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt\n" \ + "43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P\n" \ + "T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4\n" \ + "gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO\n" \ + "BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR\n" \ + "TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw\n" \ + "DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr\n" \ + "hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg\n" \ + "06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF\n" \ + "PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls\n" \ + "YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk\n" \ + "CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=\n" \ + "-----END CERTIFICATE-----\n" + +#define CA_AMAZON_4 \ + "-----BEGIN CERTIFICATE-----\n" \ + "MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5\n" \ + "MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g\n" \ + "Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG\n" \ + "A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg\n" \ + "Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi\n" \ + "9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk\n" \ + "M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB\n" \ + "/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB\n" \ + "MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw\n" \ + "CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW\n" \ + "1KyLa2tJElMzrdfkviT8tQp21KW8EA==\n" \ + "-----END CERTIFICATE-----\n" + +#define CA_AMAZON_3 \ + "-----BEGIN CERTIFICATE-----\n" \ + "MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5\n" \ + "MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g\n" \ + "Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG\n" \ + "A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg\n" \ + "Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl\n" \ + "ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j\n" \ + "QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr\n" \ + "ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr\n" \ + "BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM\n" \ + "YyRIHN8wfdVoOw==\n" \ + "-----END CERTIFICATE-----\n" + +#define CA_ALL \ + CA_ISRG_ROOT_X1 CA_ISRG_ROOT_X2 CA_GOOGLE_TRUST CA_GLOBALSIGN_EC \ + CA_GLOBALSIGN_RSA CA_DIGICERT CA_AMAZON_4 CA_AMAZON_3 diff --git a/src/config.h b/src/config.h index 7a99eb9c..a1eff241 100644 --- a/src/config.h +++ b/src/config.h @@ -36,18 +36,6 @@ #define MG_ENABLE_FATFS 0 #endif -#ifndef MG_ENABLE_MBEDTLS -#define MG_ENABLE_MBEDTLS 0 -#endif - -#ifndef MG_ENABLE_OPENSSL -#define MG_ENABLE_OPENSSL 0 -#endif - -#ifndef MG_ENABLE_CUSTOM_TLS -#define MG_ENABLE_CUSTOM_TLS 0 -#endif - #ifndef MG_ENABLE_SSI #define MG_ENABLE_SSI 0 #endif diff --git a/src/net.c b/src/net.c index f43dbe87..6c7d4b5f 100644 --- a/src/net.c +++ b/src/net.c @@ -164,6 +164,10 @@ struct mg_connection *mg_connect(struct mg_mgr *mgr, const char *url, MG_DEBUG(("%lu %p %s", c->id, c->fd, url)); mg_call(c, MG_EV_OPEN, NULL); mg_resolve(c, url); + if (mg_url_is_ssl(url)) { + struct mg_str host = mg_url_host(url); + mg_tls_init(c, host); + } } return c; } @@ -184,6 +188,7 @@ struct mg_connection *mg_listen(struct mg_mgr *mgr, const char *url, c->fn = fn; c->fn_data = fn_data; mg_call(c, MG_EV_OPEN, NULL); + if (mg_url_is_ssl(url)) c->is_tls = 1; // Accepted connection must MG_DEBUG(("%lu %p %s", c->id, c->fd, url)); } return c; @@ -227,6 +232,7 @@ void mg_mgr_free(struct mg_mgr *mgr) { #if MG_ENABLE_EPOLL if (mgr->epoll_fd >= 0) close(mgr->epoll_fd), mgr->epoll_fd = -1; #endif + mg_tls_ctx_free(mgr); } void mg_mgr_init(struct mg_mgr *mgr) { diff --git a/src/sock.c b/src/sock.c index 5a7ecf10..9982102a 100644 --- a/src/sock.c +++ b/src/sock.c @@ -414,6 +414,7 @@ static void accept_conn(struct mg_mgr *mgr, struct mg_connection *lsn) { &c->rem, mg_print_ip_port, &c->loc)); mg_call(c, MG_EV_OPEN, NULL); mg_call(c, MG_EV_ACCEPT, NULL); + if (lsn->is_tls) mg_tls_init(c, mg_str("")); } } diff --git a/src/tcpip/tcpip.c b/src/tcpip/tcpip.c index c500709d..beb5e572 100644 --- a/src/tcpip/tcpip.c +++ b/src/tcpip/tcpip.c @@ -525,6 +525,7 @@ static struct mg_connection *accept_conn(struct mg_connection *lsn, c->fn_data = lsn->fn_data; mg_call(c, MG_EV_OPEN, NULL); mg_call(c, MG_EV_ACCEPT, NULL); + if (lsn->is_tls) mg_tls_init(c, mg_str("")); return c; } diff --git a/src/tls.h b/src/tls.h index 5f8d299c..97128d94 100644 --- a/src/tls.h +++ b/src/tls.h @@ -1,20 +1,31 @@ #pragma once +#define MG_TLS_NONE 0 // No TLS support +#define MG_TLS_MBED 1 // mbedTLS +#define MG_TLS_OPENSSL 2 // OpenSSL +#define MG_TLS_BUILTIN 3 // Built-in +#define MG_TLS_CUSTOM 4 // Custom implementation + +#ifndef MG_TLS +#define MG_TLS MG_TLS_NONE +#endif + #include "net.h" #include "tls_mbed.h" #include "tls_openssl.h" struct mg_tls_opts { - const char *ca; // CA certificate file. For both listeners and clients - const char *crl; // Certificate Revocation List. For clients - const char *cert; // Certificate - const char *certkey; // Certificate key - const char *ciphers; // Cipher list - struct mg_str srvname; // If not empty, enables server name verification - struct mg_fs *fs; // FS API for reading certificate files + struct mg_str client_ca; + struct mg_str server_ca; + struct mg_str server_cert; + struct mg_str server_key; + struct mg_str client_cert; + struct mg_str client_key; }; -void mg_tls_init(struct mg_connection *, const struct mg_tls_opts *); +void mg_tls_ctx_init(struct mg_mgr *, const struct mg_tls_opts *); +void mg_tls_ctx_free(struct mg_mgr *); +void mg_tls_init(struct mg_connection *, struct mg_str hostname); void mg_tls_free(struct mg_connection *); long mg_tls_send(struct mg_connection *, const void *buf, size_t len); long mg_tls_recv(struct mg_connection *, void *buf, size_t len); diff --git a/src/tls_dummy.c b/src/tls_dummy.c index c0067283..3c00cb6d 100644 --- a/src/tls_dummy.c +++ b/src/tls_dummy.c @@ -1,8 +1,8 @@ #include "tls.h" -#if !MG_ENABLE_MBEDTLS && !MG_ENABLE_OPENSSL && !MG_ENABLE_CUSTOM_TLS -void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) { - (void) opts; +#if MG_TLS == MG_TLS_NONE +void mg_tls_init(struct mg_connection *c, struct mg_str hostname) { + (void) hostname; mg_error(c, "TLS is not enabled"); } void mg_tls_handshake(struct mg_connection *c) { @@ -21,4 +21,10 @@ size_t mg_tls_pending(struct mg_connection *c) { (void) c; return 0; } +void mg_tls_ctx_free(struct mg_mgr *mgr) { + mgr->tls_ctx = NULL; +} +void mg_tls_ctx_init(struct mg_mgr *mgr, const struct mg_tls_opts *opts) { + (void) opts, (void) mgr; +} #endif diff --git a/src/tls_mbed.c b/src/tls_mbed.c index 5f3241cb..2d6d7232 100644 --- a/src/tls_mbed.c +++ b/src/tls_mbed.c @@ -2,7 +2,7 @@ #include "printf.h" #include "tls.h" -#if MG_ENABLE_MBEDTLS +#if MG_TLS == MG_TLS_MBED #if defined(MBEDTLS_VERSION_NUMBER) && MBEDTLS_VERSION_NUMBER >= 0x03000000 #define MGRNG , rng_get, NULL @@ -13,11 +13,7 @@ void mg_tls_free(struct mg_connection *c) { struct mg_tls *tls = (struct mg_tls *) c->tls; if (tls != NULL) { - free(tls->cafile); mbedtls_ssl_free(&tls->ssl); - mbedtls_pk_free(&tls->pk); - mbedtls_x509_crt_free(&tls->ca); - mbedtls_x509_crt_free(&tls->cert); mbedtls_ssl_config_free(&tls->conf); free(tls); c->tls = NULL; @@ -70,7 +66,7 @@ static void debug_cb(void *c, int lev, const char *s, int n, const char *s2) { (void) s; } -#if defined(MBEDTLS_VERSION_NUMBER) && MBEDTLS_VERSION_NUMBER >= 0x03000000 +#ifdef MBEDTLS_SSL_SESSION_TICKETS static int rng_get(void *p_rng, unsigned char *buf, size_t len) { (void) p_rng; mg_random(buf, len); @@ -78,28 +74,20 @@ static int rng_get(void *p_rng, unsigned char *buf, size_t len) { } #endif -static struct mg_str mg_loadfile(struct mg_fs *fs, const char *path) { - size_t n = 0; - if (path[0] == '-') return mg_str(path); - char *p = mg_file_read(fs, path, &n); - return mg_str_n(p, n); -} - -void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) { - struct mg_fs *fs = opts->fs == NULL ? &mg_fs_posix : opts->fs; +void mg_tls_init(struct mg_connection *c, struct mg_str hostname) { + struct mg_tls_ctx *ctx = (struct mg_tls_ctx *) c->mgr->tls_ctx; struct mg_tls *tls = (struct mg_tls *) calloc(1, sizeof(*tls)); int rc = 0; + c->tls = tls; if (c->tls == NULL) { mg_error(c, "TLS OOM"); goto fail; } + MG_DEBUG(("%lu Setting TLS", c->id)); mbedtls_ssl_init(&tls->ssl); mbedtls_ssl_config_init(&tls->conf); - mbedtls_x509_crt_init(&tls->ca); - mbedtls_x509_crt_init(&tls->cert); - mbedtls_pk_init(&tls->pk); mbedtls_ssl_conf_dbg(&tls->conf, debug_cb, c); #if defined(MG_MBEDTLS_DEBUG_LEVEL) mbedtls_debug_set_threshold(MG_MBEDTLS_DEBUG_LEVEL); @@ -112,60 +100,47 @@ void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) { goto fail; } mbedtls_ssl_conf_rng(&tls->conf, mbed_rng, c); - if (opts->ca == NULL || strcmp(opts->ca, "*") == 0) { - mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_NONE); - } else if (opts->ca != NULL && opts->ca[0] != '\0') { -#if defined(MBEDTLS_X509_CA_CHAIN_ON_DISK) - tls->cafile = strdup(opts->ca); - rc = mbedtls_ssl_conf_ca_chain_file(&tls->conf, tls->cafile, NULL); - if (rc != 0) { - mg_error(c, "parse on-disk chain(%s) err %#x", tls->cafile, -rc); - goto fail; - } -#else - struct mg_str s = mg_loadfile(fs, opts->ca); - rc = mbedtls_x509_crt_parse(&tls->ca, (uint8_t *) s.ptr, s.len + 1); - if (opts->ca[0] != '-') free((char *) s.ptr); - if (rc != 0) { - mg_error(c, "parse(%s) err %#x", opts->ca, -rc); - goto fail; - } - mbedtls_ssl_conf_ca_chain(&tls->conf, &tls->ca, NULL); -#endif - if (opts->srvname.len > 0) { - char *x = mg_mprintf("%.*s", (int) opts->srvname.len, opts->srvname.ptr); - mbedtls_ssl_set_hostname(&tls->ssl, x); - free(x); - } + + if (c->is_client && ctx->client_ca.version) { + mbedtls_ssl_conf_ca_chain(&tls->conf, &ctx->client_ca, NULL); mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED); + if (hostname.ptr != NULL && hostname.ptr[0] != '\0') { + struct mg_addr addr; + if (!mg_aton(hostname, &addr)) { // if srvname is not an IP address + char *host = mg_mprintf("%.*s", (int) hostname.len, hostname.ptr); + mbedtls_ssl_set_hostname(&tls->ssl, host); + free(host); + } + } + } else if (!c->is_client && ctx->server_ca.version) { + mbedtls_ssl_conf_ca_chain(&tls->conf, &ctx->server_ca, NULL); + mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED); + } else { + mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_NONE); } - if (opts->cert != NULL && opts->cert[0] != '\0') { - struct mg_str s = mg_loadfile(fs, opts->cert); - const char *key = opts->certkey == NULL ? opts->cert : opts->certkey; - rc = mbedtls_x509_crt_parse(&tls->cert, (uint8_t *) s.ptr, s.len + 1); - if (opts->cert[0] != '-') free((char *) s.ptr); - if (rc != 0) { - mg_error(c, "parse(%s) err %#x", opts->cert, -rc); - goto fail; - } - s = mg_loadfile(fs, key); - rc = mbedtls_pk_parse_key(&tls->pk, (uint8_t *) s.ptr, s.len + 1, NULL, - 0 MGRNG); - if (key[0] != '-') free((char *) s.ptr); - if (rc != 0) { - mg_error(c, "tls key(%s) %#x", key, -rc); - goto fail; - } - rc = mbedtls_ssl_conf_own_cert(&tls->conf, &tls->cert, &tls->pk); - if (rc != 0) { - mg_error(c, "own cert %#x", -rc); - goto fail; - } + if (c->is_client && ctx->client_cert.version && + (rc = mbedtls_ssl_conf_own_cert(&tls->conf, &ctx->client_cert, + &ctx->client_key)) != 0) { + mg_error(c, "own cert %#x", -rc); + goto fail; } + if (!c->is_client && ctx->server_cert.version && + (rc = mbedtls_ssl_conf_own_cert(&tls->conf, &ctx->server_cert, + &ctx->server_key)) != 0) { + mg_error(c, "own cert %#x", -rc); + goto fail; + } +#ifdef MBEDTLS_SSL_SESSION_TICKETS + mbedtls_ssl_conf_session_tickets_cb(&tls->conf, mbedtls_ssl_ticket_write, + mbedtls_ssl_ticket_parse, + &ctx->ticket_ctx); +#endif + if ((rc = mbedtls_ssl_setup(&tls->ssl, &tls->conf)) != 0) { mg_error(c, "setup err %#x", -rc); goto fail; } + c->tls = tls; c->is_tls = 1; c->is_tls_hs = 1; @@ -200,4 +175,77 @@ long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) { if (n <= 0) return MG_IO_ERR; return n; } + +static bool load_cert(struct mg_str str, mbedtls_x509_crt *p) { + int rc; + if (str.ptr == NULL || str.ptr[0] == '\0' || str.ptr[0] == '*') return true; + if (str.ptr[0] == '-') str.len++; // PEM, include trailing NUL + if ((rc = mbedtls_x509_crt_parse(p, (uint8_t *) str.ptr, str.len)) != 0) { + MG_ERROR(("cert err %#x", -rc)); + return false; + } + return true; +} + +static bool load_key(struct mg_str str, mbedtls_pk_context *p) { + int rc; + if (str.ptr == NULL || str.ptr[0] == '\0' || str.ptr[0] == '*') return true; + if (str.ptr[0] == '-') str.len++; // PEM, include trailing NUL + if ((rc = mbedtls_pk_parse_key(p, (uint8_t *) str.ptr, str.len, NULL, + 0 MGRNG)) != 0) { + MG_ERROR(("key err %#x", -rc)); + return false; + } + return true; +} + +void mg_tls_ctx_init(struct mg_mgr *mgr, const struct mg_tls_opts *opts) { + struct mg_tls_ctx *ctx = (struct mg_tls_ctx *) calloc(1, sizeof(*ctx)); + if (ctx == NULL) goto fail; + MG_DEBUG(("Setting up TLS context")); + +#if defined(MG_MBEDTLS_DEBUG_LEVEL) + mbedtls_debug_set_threshold(MG_MBEDTLS_DEBUG_LEVEL); +#endif + + if (!load_cert(opts->client_ca, &ctx->client_ca)) goto fail; + if (!load_cert(opts->server_ca, &ctx->server_ca)) goto fail; + if (!load_cert(opts->client_cert, &ctx->client_cert)) goto fail; + if (!load_cert(opts->server_cert, &ctx->server_cert)) goto fail; + if (!load_key(opts->server_key, &ctx->server_key)) goto fail; + if (!load_key(opts->client_key, &ctx->client_key)) goto fail; + +#ifdef MBEDTLS_SSL_SESSION_TICKETS + { + int rc; + mbedtls_ssl_ticket_init(&ctx->ticket_ctx); + if ((rc = mbedtls_ssl_ticket_setup(&ctx->ticket_ctx, rng_get, NULL, + MBEDTLS_CIPHER_AES_128_GCM, 86400)) != + 0) { + MG_ERROR(("setup session tickets err %#x", -rc)); + goto fail; + } + } +#endif + mgr->tls_ctx = ctx; + return; +fail: + mg_tls_ctx_free(mgr); +} + +void mg_tls_ctx_free(struct mg_mgr *mgr) { + struct mg_tls_ctx *ctx = (struct mg_tls_ctx *) mgr->tls_ctx; + if (ctx != NULL) { + mbedtls_x509_crt_free(&ctx->server_cert); + mbedtls_pk_free(&ctx->server_key); + mbedtls_x509_crt_free(&ctx->client_cert); + mbedtls_pk_free(&ctx->client_key); + mbedtls_x509_crt_free(&ctx->client_ca); +#ifdef MBEDTLS_SSL_SESSION_TICKETS + mbedtls_ssl_ticket_free(&ctx->ticket_ctx); +#endif + free(ctx); + mgr->tls_ctx = NULL; + } +} #endif diff --git a/src/tls_mbed.h b/src/tls_mbed.h index 7628f299..80dce601 100644 --- a/src/tls_mbed.h +++ b/src/tls_mbed.h @@ -5,17 +5,26 @@ #include "url.h" #include "util.h" -#if MG_ENABLE_MBEDTLS +#if MG_TLS == MG_TLS_MBED #include #include #include +#include + +struct mg_tls_ctx { + mbedtls_x509_crt server_ca; // Parsed CA certificate + mbedtls_x509_crt client_ca; // Parsed CA certificate + mbedtls_x509_crt server_cert; // Parsed server certificate + mbedtls_pk_context server_key; // Parsed server private key context + mbedtls_x509_crt client_cert; // Parsed client certificate + mbedtls_pk_context client_key; // Parsed client private key context +#ifdef MBEDTLS_SSL_SESSION_TICKETS + mbedtls_ssl_ticket_context ticket_ctx; // Session tickets context +#endif +}; struct mg_tls { - char *cafile; // CA certificate path - mbedtls_x509_crt ca; // Parsed CA certificate - mbedtls_x509_crt cert; // Parsed certificate mbedtls_ssl_context ssl; // SSL/TLS context mbedtls_ssl_config conf; // SSL-TLS config - mbedtls_pk_context pk; // Private key context }; #endif diff --git a/src/tls_openssl.c b/src/tls_openssl.c index cbc3cbc7..34d8788d 100644 --- a/src/tls_openssl.c +++ b/src/tls_openssl.c @@ -1,7 +1,7 @@ #include "printf.h" #include "tls.h" -#if MG_ENABLE_OPENSSL +#if MG_TLS == MG_TLS_OPENSSL static int mg_tls_err(struct mg_tls *tls, int res) { int err = SSL_get_error(tls->ssl, res); // We've just fetched the last error from the queue. @@ -20,38 +20,63 @@ static int mg_tls_err(struct mg_tls *tls, int res) { return err; } -void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) { +static STACK_OF(X509_INFO) * load_ca_certs(const char *ca, int ca_len) { + BIO *ca_bio = BIO_new_mem_buf(ca, ca_len); + if (!ca_bio) return NULL; + STACK_OF(X509_INFO) *certs = PEM_X509_INFO_read_bio(ca_bio, NULL, NULL, NULL); + BIO_free(ca_bio); + return certs; +} + +static bool add_ca_certs(SSL_CTX *ctx, STACK_OF(X509_INFO) * certs) { + X509_STORE *cert_store = SSL_CTX_get_cert_store(ctx); + for (int i = 0; i < sk_X509_INFO_num(certs); i++) { + X509_INFO *cert_info = sk_X509_INFO_value(certs, i); + if (cert_info->x509 && !X509_STORE_add_cert(cert_store, cert_info->x509)) + return false; + } + return true; +} + +static EVP_PKEY *load_key(const char *key, int key_len) { + BIO *key_bio = BIO_new_mem_buf(key, key_len); + if (!key_bio) return NULL; + EVP_PKEY *priv_key = PEM_read_bio_PrivateKey(key_bio, NULL, 0, NULL); + BIO_free(key_bio); + return priv_key; +} + +static X509 *load_cert(const char *cert, int cert_len) { + BIO *cert_bio = BIO_new_mem_buf(cert, cert_len); + if (!cert_bio) return NULL; + X509 *x509 = PEM_read_bio_X509(cert_bio, NULL, 0, NULL); + BIO_free(cert_bio); + return x509; +} + +void mg_tls_init(struct mg_connection *c, struct mg_str hostname) { + struct mg_tls_ctx *ctx = (struct mg_tls_ctx *) c->mgr->tls_ctx; struct mg_tls *tls = (struct mg_tls *) calloc(1, sizeof(*tls)); - const char *id = "mongoose"; - static unsigned char s_initialised = 0; - int rc; + + if (ctx == NULL) { + mg_error(c, "TLS context not initialized"); + goto fail; + } if (tls == NULL) { mg_error(c, "TLS OOM"); goto fail; } - if (!s_initialised) { - SSL_library_init(); - s_initialised++; - } - MG_DEBUG(("%lu Setting TLS, CA: %s, cert: %s, key: %s", c->id, - opts->ca == NULL ? "null" : opts->ca, - opts->cert == NULL ? "null" : opts->cert, - opts->certkey == NULL ? "null" : opts->certkey)); - tls->ctx = c->is_client ? SSL_CTX_new(SSLv23_client_method()) - : SSL_CTX_new(SSLv23_server_method()); + tls->ctx = c->is_client ? SSL_CTX_new(TLS_client_method()) + : SSL_CTX_new(TLS_server_method()); if ((tls->ssl = SSL_new(tls->ctx)) == NULL) { mg_error(c, "SSL_new"); goto fail; } - SSL_set_session_id_context(tls->ssl, (const uint8_t *) id, - (unsigned) strlen(id)); - // Disable deprecated protocols - SSL_set_options(tls->ssl, SSL_OP_NO_SSLv2); - SSL_set_options(tls->ssl, SSL_OP_NO_SSLv3); - SSL_set_options(tls->ssl, SSL_OP_NO_TLSv1); - SSL_set_options(tls->ssl, SSL_OP_NO_TLSv1_1); + + SSL_set_min_proto_version(tls->ssl, TLS1_2_VERSION); + #ifdef MG_ENABLE_OPENSSL_NO_COMPRESSION SSL_set_options(tls->ssl, SSL_OP_NO_COMPRESSION); #endif @@ -59,45 +84,54 @@ void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) { SSL_set_options(tls->ssl, SSL_OP_CIPHER_SERVER_PREFERENCE); #endif - if (opts->ca != NULL && opts->ca[0] != '\0') { - SSL_set_verify(tls->ssl, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, - NULL); - if ((rc = SSL_CTX_load_verify_locations(tls->ctx, opts->ca, NULL)) != 1) { - mg_error(c, "load('%s') %d err %d", opts->ca, rc, mg_tls_err(tls, rc)); - goto fail; + if (c->is_client) { + if (ctx->client_ca) { + SSL_set_verify(tls->ssl, + SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); + if (!add_ca_certs(tls->ctx, ctx->client_ca)) goto fail; + } + if (ctx->client_cert && ctx->client_key) { + if (SSL_use_certificate(tls->ssl, ctx->client_cert) != 1) { + mg_error(c, "SSL_CTX_use_certificate"); + goto fail; + } + if (SSL_use_PrivateKey(tls->ssl, ctx->client_key) != 1) { + mg_error(c, "SSL_CTX_use_PrivateKey"); + goto fail; + } + } + } else { + if (ctx->server_ca) { + SSL_set_verify(tls->ssl, + SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); + if (!add_ca_certs(tls->ctx, ctx->server_ca)) goto fail; + } + if (ctx->server_cert && ctx->server_key) { + if (SSL_use_certificate(tls->ssl, ctx->server_cert) != 1) { + mg_error(c, "SSL_CTX_use_certificate"); + goto fail; + } + if (SSL_use_PrivateKey(tls->ssl, ctx->server_key) != 1) { + mg_error(c, "SSL_CTX_use_PrivateKey"); + goto fail; + } } } - if (opts->cert != NULL && opts->cert[0] != '\0') { - const char *key = opts->certkey; - if (key == NULL) key = opts->cert; - if ((rc = SSL_use_certificate_file(tls->ssl, opts->cert, 1)) != 1) { - mg_error(c, "Invalid SSL cert, err %d", mg_tls_err(tls, rc)); - goto fail; - } else if ((rc = SSL_use_PrivateKey_file(tls->ssl, key, 1)) != 1) { - mg_error(c, "Invalid SSL key, err %d", mg_tls_err(tls, rc)); - goto fail; -#if OPENSSL_VERSION_NUMBER > 0x10100000L - } else if ((rc = SSL_use_certificate_chain_file(tls->ssl, opts->cert)) != - 1) { - mg_error(c, "Invalid chain, err %d", mg_tls_err(tls, rc)); - goto fail; -#endif - } else { - SSL_set_mode(tls->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); + + SSL_set_mode(tls->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); #if OPENSSL_VERSION_NUMBER > 0x10002000L - SSL_set_ecdh_auto(tls->ssl, 1); + SSL_set_ecdh_auto(tls->ssl, 1); #endif - } - } - if (opts->ciphers != NULL) SSL_set_cipher_list(tls->ssl, opts->ciphers); + #if OPENSSL_VERSION_NUMBER >= 0x10100000L - if (opts->srvname.len > 0) { - char *s = mg_mprintf("%.*s", (int) opts->srvname.len, opts->srvname.ptr); + if (c->is_client && hostname.ptr && hostname.ptr[0] != '\0') { + char *s = mg_mprintf("%.*s", (int) hostname.len, hostname.ptr); SSL_set1_host(tls->ssl, s); SSL_set_tlsext_host_name(tls->ssl, s); free(s); } #endif + c->tls = tls; c->is_tls = 1; c->is_tls_hs = 1; @@ -106,6 +140,7 @@ void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) { } MG_DEBUG(("%lu SSL %s OK", c->id, c->is_accepted ? "accept" : "client")); return; + fail: c->is_closing = 1; free(tls); @@ -155,4 +190,68 @@ long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) { if (n <= 0) return MG_IO_ERR; return n; } + +void mg_tls_ctx_free(struct mg_mgr *mgr) { + struct mg_tls_ctx *ctx = (struct mg_tls_ctx *) mgr->tls_ctx; + if (ctx) { + if (ctx->server_cert) X509_free(ctx->server_cert); + if (ctx->server_key) EVP_PKEY_free(ctx->server_key); + if (ctx->server_ca) + sk_X509_INFO_pop_free(ctx->server_ca, X509_INFO_free); + if (ctx->client_cert) X509_free(ctx->client_cert); + if (ctx->client_key) EVP_PKEY_free(ctx->client_key); + if (ctx->client_ca) + sk_X509_INFO_pop_free(ctx->client_ca, X509_INFO_free); + free(ctx); + mgr->tls_ctx = NULL; + } +} + +void mg_tls_ctx_init(struct mg_mgr *mgr, const struct mg_tls_opts *opts) { + static unsigned char s_initialised = 0; + if (!s_initialised) { + SSL_library_init(); + s_initialised++; + } + + struct mg_tls_ctx *ctx = (struct mg_tls_ctx *) calloc(1, sizeof(*ctx)); + if (ctx == NULL) return; + + if (opts->server_cert.ptr && opts->server_cert.ptr[0] != '\0') { + struct mg_str key = opts->server_key; + if (!key.ptr) key = opts->server_cert; + if (!(ctx->server_cert = + load_cert(opts->server_cert.ptr, (int) opts->server_cert.len))) + goto fail; + if (!(ctx->server_key = load_key(key.ptr, (int) key.len))) goto fail; + } + + if (opts->server_ca.ptr && opts->server_ca.ptr[0] != '\0') { + if (!(ctx->server_ca = + load_ca_certs(opts->server_ca.ptr, (int) opts->server_ca.len))) + goto fail; + } + + if (opts->client_cert.ptr && opts->client_cert.ptr[0] != '\0') { + struct mg_str key = opts->client_key; + if (!key.ptr) key = opts->client_cert; + if (!(ctx->client_cert = + load_cert(opts->client_cert.ptr, (int) opts->client_cert.len))) + goto fail; + if (!(ctx->client_key = load_key(key.ptr, (int) key.len))) goto fail; + } + + if (opts->client_ca.ptr && opts->client_ca.ptr[0] != '\0') { + if (!(ctx->client_ca = + load_ca_certs(opts->client_ca.ptr, (int) opts->client_ca.len))) + goto fail; + } + + mgr->tls_ctx = ctx; + return; +fail: + MG_ERROR(("TLS ctx init error")); + mg_tls_ctx_free(mgr); +} + #endif diff --git a/src/tls_openssl.h b/src/tls_openssl.h index ed5bf3d5..d794bcc2 100644 --- a/src/tls_openssl.h +++ b/src/tls_openssl.h @@ -1,10 +1,19 @@ #pragma once -#if MG_ENABLE_OPENSSL +#if MG_TLS == MG_TLS_OPENSSL #include #include +struct mg_tls_ctx { + X509 *server_cert; + EVP_PKEY *server_key; + STACK_OF(X509_INFO) *server_ca; + X509 *client_cert; + EVP_PKEY *client_key; + STACK_OF(X509_INFO) *client_ca; +}; + struct mg_tls { SSL_CTX *ctx; SSL *ssl; diff --git a/test/unit_test.c b/test/unit_test.c index 17ca7238..17dd956b 100644 --- a/test/unit_test.c +++ b/test/unit_test.c @@ -16,6 +16,41 @@ static int s_num_tests = 0; #define FETCH_BUF_SIZE (256 * 1024) +// Self-signed CA, CERT, KEY +static const char *s_tls_ca = + "-----BEGIN CERTIFICATE-----\n" + "MIIBqjCCAU+gAwIBAgIUESoOPGqMhf9uarzblVFwzrQweMcwCgYIKoZIzj0EAwIw\n" + "RDELMAkGA1UEBhMCSUUxDzANBgNVBAcMBkR1YmxpbjEQMA4GA1UECgwHQ2VzYW50\n" + "YTESMBAGA1UEAwwJVGVzdCBSb290MCAXDTIwMDUwOTIxNTE0NFoYDzIwNTAwNTA5\n" + "MjE1MTQ0WjBEMQswCQYDVQQGEwJJRTEPMA0GA1UEBwwGRHVibGluMRAwDgYDVQQK\n" + "DAdDZXNhbnRhMRIwEAYDVQQDDAlUZXN0IFJvb3QwWTATBgcqhkjOPQIBBggqhkjO\n" + "PQMBBwNCAAQsq9ECZiSW1xI+CVBP8VDuUehVA166sR2YsnJ5J6gbMQ1dUCH/QvLa\n" + "dBdeU7JlQcH8hN5KEbmM9BnZxMor6ussox0wGzAMBgNVHRMEBTADAQH/MAsGA1Ud\n" + "DwQEAwIBrjAKBggqhkjOPQQDAgNJADBGAiEAnHFsAIwGQQyRL81B04dH6d86Iq0l\n" + "fL8OKzndegxOaB0CIQCPwSIwEGFdURDqCC0CY2dnMrUGY5ZXu3hHCojZGS7zvg==\n" + "-----END CERTIFICATE-----\n"; + +static const char *s_tls_cert = + "-----BEGIN CERTIFICATE-----\n" + "MIIBhzCCASygAwIBAgIUbnMoVd8TtWH1T09dANkK2LU6IUswCgYIKoZIzj0EAwIw\n" + "RDELMAkGA1UEBhMCSUUxDzANBgNVBAcMBkR1YmxpbjEQMA4GA1UECgwHQ2VzYW50\n" + "YTESMBAGA1UEAwwJVGVzdCBSb290MB4XDTIwMDUwOTIxNTE0OVoXDTMwMDUwOTIx\n" + "NTE0OVowETEPMA0GA1UEAwwGc2VydmVyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD\n" + "QgAEkuBGnInDN6l06zVVQ1VcrOvH5FDu9MC6FwJc2e201P8hEpq0Q/SJS2nkbSuW\n" + "H/wBTTBaeXN2uhlBzMUWK790KKMvMC0wCQYDVR0TBAIwADALBgNVHQ8EBAMCA6gw\n" + "EwYDVR0lBAwwCgYIKwYBBQUHAwEwCgYIKoZIzj0EAwIDSQAwRgIhAPo6xx7LjCdZ\n" + "QY133XvLjAgVFrlucOZHONFVQuDXZsjwAiEAzHBNligA08c5U3SySYcnkhurGg50\n" + "BllCI0eYQ9ggp/o=\n" + "-----END CERTIFICATE-----\n"; + +static const char *s_tls_key = + "-----BEGIN PRIVATE KEY-----\n" + "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQglNni0t9Dg9icgG8w\n" + "kbfxWSS+TuNgbtNybIQXcm3NHpmhRANCAASS4EacicM3qXTrNVVDVVys68fkUO70\n" + "wLoXAlzZ7bTU/yESmrRD9IlLaeRtK5Yf/AFNMFp5c3a6GUHMxRYrv3Qo\n" + "-----END PRIVATE KEY-----\n"; + + // Important: we use different port numbers for the Windows bug workaround. See // https://support.microsoft.com/en-ae/help/3039044/error-10013-wsaeacces-is-returned-when-a-second-bind-to-a-excluded-por @@ -615,8 +650,6 @@ static void test_mqtt(void) { } static void eh1(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { - struct mg_tls_opts *topts = (struct mg_tls_opts *) fn_data; - if (ev == MG_EV_ACCEPT && topts != NULL) mg_tls_init(c, topts); if (ev == MG_EV_HTTP_MSG) { struct mg_http_message *hm = (struct mg_http_message *) ev_data; MG_INFO(("[%.*s %.*s] message len %d", (int) hm->method.len, hm->method.ptr, @@ -679,6 +712,7 @@ static void eh1(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { struct mg_ws_message *wm = (struct mg_ws_message *) ev_data; mg_ws_send(c, wm->data.ptr, wm->data.len, WEBSOCKET_OP_BINARY); } + (void) fn_data; } struct fetch_data { @@ -705,24 +739,23 @@ static int fetch(struct mg_mgr *mgr, char *buf, const char *url, const char *fmt, ...) { struct fetch_data fd = {buf, 0, 0}; int i; - struct mg_connection *c = mg_http_connect(mgr, url, fcb, &fd); + struct mg_connection *c = NULL; va_list ap; - ASSERT(c != NULL); - if (mg_url_is_ssl(url)) { + if (mgr->tls_ctx == NULL) { struct mg_tls_opts opts; - struct mg_str host = mg_url_host(url); memset(&opts, 0, sizeof(opts)); - opts.ca = "./test/data/ca.pem"; + opts.client_ca = mg_str(CA_ISRG_ROOT_X1); if (strstr(url, "127.0.0.1") != NULL) { // Local connection, use self-signed certificates - opts.ca = "./test/data/ss_ca.pem"; - opts.cert = "./test/data/ss_client.pem"; - } else { - opts.srvname = host; + opts.client_ca = mg_str(s_tls_ca); + opts.server_cert = mg_str(s_tls_cert); + opts.server_key = mg_str(s_tls_key); } - mg_tls_init(c, &opts); - if (c->tls == NULL) fd.closed = 1; + mg_tls_ctx_init(mgr, &opts); + if (mgr->tls_ctx == NULL) fd.closed = 1; } + c = mg_http_connect(mgr, url, fcb, &fd); + ASSERT(c != NULL); // c->is_hexdumping = 1; va_start(ap, fmt); mg_vprintf(c, fmt, &ap); @@ -1149,20 +1182,18 @@ static void test_http_404(void) { } static void test_tls(void) { -#if MG_ENABLE_MBEDTLS || MG_ENABLE_OPENSSL - struct mg_tls_opts opts = {"./test/data/ss_ca.pem", - NULL, - "./test/data/ss_server.pem", - "./test/data/ss_server.pem", - NULL, - {0, 0}, - NULL}; +#if MG_TLS + struct mg_tls_opts opts = {}; + opts.client_ca = s_tls_ca; + opts.server_cert = s_tls_cert; + opts.server_key = s_tls_key; struct mg_mgr mgr; struct mg_connection *c; const char *url = "https://127.0.0.1:12347"; char buf[FETCH_BUF_SIZE]; mg_mgr_init(&mgr); - c = mg_http_listen(&mgr, url, eh1, (void *) &opts); + mg_tls_ctx_init(&mgr, &opts); + c = mg_http_listen(&mgr, url, eh1, NULL); ASSERT(c != NULL); ASSERT(fetch(&mgr, buf, url, "GET /a.txt HTTP/1.0\n\n") == 200); // MG_INFO(("%s", buf)); @@ -1194,10 +1225,13 @@ static void f3(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { } static void test_http_client(void) { + struct mg_tls_opts opts = {0}; struct mg_mgr mgr; - struct mg_connection *c; + struct mg_connection *c = NULL; int i, ok = 0; mg_mgr_init(&mgr); + opts.client_ca = mg_str(CA_ISRG_ROOT_X2 CA_ISRG_ROOT_X1); + mg_tls_ctx_init(&mgr, &opts); c = mg_http_connect(&mgr, "http://cesanta.com", f3, &ok); ASSERT(c != NULL); for (i = 0; i < 500 && ok <= 0; i++) mg_mgr_poll(&mgr, 10); @@ -1205,20 +1239,18 @@ static void test_http_client(void) { c->is_closing = 1; mg_mgr_poll(&mgr, 0); ok = 0; -#if MG_ENABLE_MBEDTLS || MG_ENABLE_OPENSSL +#if MG_TLS { const char *url = "https://cesanta.com"; struct mg_str host = mg_url_host(url); - struct mg_tls_opts opts = { - "./test/data/ca.pem", NULL, NULL, NULL, NULL, host, NULL}; c = mg_http_connect(&mgr, url, f3, &ok); ASSERT(c != NULL); - mg_tls_init(c, &opts); for (i = 0; i < 1500 && ok <= 0; i++) mg_mgr_poll(&mgr, 1000); ASSERT(ok == 200); c->is_closing = 1; mg_mgr_poll(&mgr, 1); +#if 0 // Test failed host validation ok = 0; opts.srvname = mg_str("dummy"); @@ -1240,6 +1272,7 @@ static void test_http_client(void) { ASSERT(ok == 200); c->is_closing = 1; mg_mgr_poll(&mgr, 1); +#endif } #endif