mirror of
https://github.com/cesanta/mongoose.git
synced 2026-10-20 11:19:56 +00:00
Add CA bundle parsing for TLS clients
This commit is contained in:
1 parent
83c046e4f4
commit
a84ac510b1
4 files changed
+3266
-3178
No files matched your search
+81
-25
@@ -14583,7 +14583,9 @@ struct tls_data {
|
||||
bool cert_requested; // client received a CertificateRequest
|
||||
bool is_twoway; // server is configured to authenticate clients
|
||||
struct mg_str cert_der; // certificate in DER format
|
||||
struct mg_str ca_der; // CA certificate
|
||||
struct mg_str ca_der; // current CA certificate
|
||||
struct mg_str *ca_bundle_der; // bundle of CA certificates
|
||||
size_t ca_bundle_len; // number of certificates in bundle
|
||||
struct mg_str *chain_der; // certificate chain (intermediate certs)
|
||||
size_t chain_len; // number of certificates in chain
|
||||
uint8_t ec_key[32]; // EC private key
|
||||
@@ -14591,7 +14593,7 @@ struct tls_data {
|
||||
struct mg_str rsa_key_der; // RSA private key in DER format
|
||||
char hostname[254]; // matching hostname
|
||||
|
||||
bool is_ec_pubkey; // EC or RSA
|
||||
bool is_ec_pubkey; // EC or RSA. TODO(): currently unused
|
||||
uint8_t pubkey[512 + 16]; // server EC (64) or RSA (512+exp) public key to
|
||||
// verify cert
|
||||
size_t pubkeysz; // size of the server public key
|
||||
@@ -15835,18 +15837,20 @@ static int mg_tls_client_recv_ext(struct mg_connection *c) {
|
||||
}
|
||||
|
||||
struct mg_tls_cert {
|
||||
int is_ec_pubkey;
|
||||
bool is_ec_pubkey;
|
||||
struct mg_str sn;
|
||||
struct mg_str pubkey;
|
||||
struct mg_der_tlv issuer;
|
||||
struct mg_der_tlv subj;
|
||||
struct mg_str sig; // signature
|
||||
uint8_t tbshash[48]; // 32b for sha256/secp256, 48b for sha384/secp384
|
||||
uint8_t tbshash[48]; // 32B for sha256/secp256, 48B for sha384/secp384
|
||||
size_t tbshashsz; // actual TBS hash size
|
||||
};
|
||||
|
||||
static void mg_der_debug_cert_name(const char *name, struct mg_der_tlv *tlv) {
|
||||
struct mg_der_tlv v;
|
||||
struct mg_str cn, c, o, ou;
|
||||
if (mg_log_level < MG_LL_VERBOSE) return; // skip recursive computations
|
||||
cn = c = o = ou = mg_str("");
|
||||
if (mg_der_find_oid(tlv, (uint8_t *) "\x55\x04\x03", 3, &v))
|
||||
cn = mg_str_n((const char *) v.value, v.len);
|
||||
@@ -15926,6 +15930,7 @@ static int mg_tls_parse_cert_der(void *buf, size_t dersz,
|
||||
|
||||
// issuer
|
||||
if (mg_der_next(&tbs_cert, &field) <= 0 || field.type != 0x30) return -1;
|
||||
cert->issuer = field;
|
||||
mg_der_debug_cert_name("issuer", &field);
|
||||
|
||||
// validity dates (before/after)
|
||||
@@ -15957,21 +15962,21 @@ static int mg_tls_parse_cert_der(void *buf, size_t dersz,
|
||||
MG_VERBOSE(("pk algo (oid): %M", mg_print_hex, pki_algo.len, pki_algo.value));
|
||||
if (pki_algo.len == 8 &&
|
||||
memcmp(pki_algo.value, "\x2A\x86\x48\xCE\x3D\x03\x01\x07", 8) == 0) {
|
||||
cert->is_ec_pubkey = 1;
|
||||
cert->is_ec_pubkey = true;
|
||||
MG_VERBOSE(("pk algo: ECDSA secp256r1"));
|
||||
} else if (pki_algo.len == 8 &&
|
||||
memcmp(pki_algo.value, "\x2A\x86\x48\xCE\x3D\x03\x01\x08", 8) ==
|
||||
0) {
|
||||
cert->is_ec_pubkey = 1;
|
||||
cert->is_ec_pubkey = true;
|
||||
MG_VERBOSE(("pk algo: ECDSA secp384r1"));
|
||||
} else if (pki_algo.len == 7 &&
|
||||
memcmp(pki_algo.value, "\x2A\x86\x48\xCE\x3D\x02\x01", 7) == 0) {
|
||||
cert->is_ec_pubkey = 1;
|
||||
cert->is_ec_pubkey = true;
|
||||
MG_VERBOSE(("pk algo: EC public key"));
|
||||
} else if (pki_algo.len == 9 &&
|
||||
memcmp(pki_algo.value, "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01",
|
||||
9) == 0) {
|
||||
cert->is_ec_pubkey = 0;
|
||||
cert->is_ec_pubkey = false;
|
||||
MG_VERBOSE(("pk algo: RSA"));
|
||||
} else {
|
||||
MG_ERROR(("unsupported pk algo: %M", mg_print_hex, pki_algo.len,
|
||||
@@ -16062,7 +16067,7 @@ static int mg_tls_verify_cert_signature(const struct mg_tls_cert *cert,
|
||||
(unsigned) cert->tbshashsz, sig,
|
||||
mg_uecc_secp256r1());
|
||||
} else if (issuer->pubkey.len == 96) {
|
||||
MG_ERROR(("reject secp386 for now"));
|
||||
MG_ERROR(("reject secp384 for now"));
|
||||
return 0;
|
||||
} else {
|
||||
MG_ERROR(("unsupported public key length: %d", issuer->pubkey.len));
|
||||
@@ -16103,6 +16108,27 @@ static int mg_tls_verify_cert_cn(struct mg_der_tlv *subj, const char *host) {
|
||||
return matched;
|
||||
}
|
||||
|
||||
static int tls_bundle_find(struct tls_data *tls, struct mg_der_tlv *name,
|
||||
struct mg_tls_cert *cert) {
|
||||
size_t i;
|
||||
struct mg_der_tlv v;
|
||||
struct mg_str *p = tls->ca_bundle_der, tgt;
|
||||
if (!mg_der_find_oid(name, (uint8_t *) "\x55\x04\x03", 3, &v)) return false;
|
||||
tgt = mg_str_n((const char *) v.value, v.len);
|
||||
for (i = 0; i < tls->ca_bundle_len; i++, p++) {
|
||||
struct mg_str subj;
|
||||
if (mg_tls_parse_cert_der(p->buf, p->len, cert) < 0 ||
|
||||
!mg_der_find_oid(&cert->subj, (uint8_t *) "\x55\x04\x03", 3, &v)) {
|
||||
MG_ERROR(("failed to parse certificate #%u in bundle", i + 1));
|
||||
return -1;
|
||||
}
|
||||
subj = mg_str_n((const char *) v.value, v.len);
|
||||
MG_VERBOSE(("#%u: %.*s (%.*s)", i + 1, subj.len, subj.buf, tgt.len, tgt.buf));
|
||||
if (mg_strcasecmp(subj, tgt) == 0) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mg_tls_recv_cert(struct mg_connection *c, bool is_client) {
|
||||
struct tls_data *tls = (struct tls_data *) c->tls;
|
||||
unsigned char *recv_buf;
|
||||
@@ -16152,7 +16178,7 @@ static int mg_tls_recv_cert(struct mg_connection *c, bool is_client) {
|
||||
memset(certs, 0, sizeof(certs));
|
||||
memset(&ca, 0, sizeof(ca));
|
||||
|
||||
if (tls->ca_der.len > 0) {
|
||||
if (tls->ca_der.len > 0) { // single cert or server
|
||||
if (mg_tls_parse_cert_der(tls->ca_der.buf, tls->ca_der.len, &ca) < 0) {
|
||||
mg_error(c, "failed to parse CA certificate");
|
||||
return -1;
|
||||
@@ -16202,10 +16228,18 @@ static int mg_tls_recv_cert(struct mg_connection *c, bool is_client) {
|
||||
}
|
||||
}
|
||||
|
||||
if (ca.pubkey.len == ci->pubkey.len &&
|
||||
memcmp(ca.pubkey.buf, ci->pubkey.buf, ca.pubkey.len) == 0) {
|
||||
found_ca = true;
|
||||
break;
|
||||
if (tls->ca_bundle_len > 0) { // bundle, find subject and compare keys
|
||||
MG_VERBOSE(("Search current cert in bundle"));
|
||||
int r = tls_bundle_find(tls, &ci->subj, &ca); // find current cert ci
|
||||
if (r < 0) {
|
||||
mg_error(c, "failed to parse CA bundle");
|
||||
return -1;
|
||||
} else if (r > 0 && ca.pubkey.len == ci->pubkey.len &&
|
||||
memcmp(ca.pubkey.buf, ci->pubkey.buf, ca.pubkey.len) == 0) {
|
||||
found_ca = true;
|
||||
MG_VERBOSE(("CA serial: %M", mg_print_hex, ca.sn.len, ca.sn.buf));
|
||||
break;
|
||||
} // else either r = 0 => subj not found or pubkey not matching
|
||||
}
|
||||
|
||||
if (certnum == sizeof(certs) / sizeof(certs[0]) - 1) {
|
||||
@@ -16214,15 +16248,23 @@ static int mg_tls_recv_cert(struct mg_connection *c, bool is_client) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!found_ca && tls->ca_der.len > 0) {
|
||||
if (!found_ca && certnum > 0 && tls->ca_bundle_len > 0) { // bundle
|
||||
MG_VERBOSE(("Search bundle for issuer of last cert in chain"));
|
||||
int r = tls_bundle_find(tls, &certs[certnum - 1].issuer, &ca);
|
||||
if (r <= 0) {
|
||||
mg_error(c, r < 0 ? "failed to parse CA bundle"
|
||||
: "failed to find issuing CA in bundle");
|
||||
return -1;
|
||||
} // else r > 0 => issuer found
|
||||
MG_VERBOSE(("CA serial: %M", mg_print_hex, ca.sn.len, ca.sn.buf));
|
||||
}
|
||||
if (!found_ca && tls->ca_der.len > 0) { // single cert or server
|
||||
if (certnum < 1 ||
|
||||
!mg_tls_verify_cert_signature(&certs[certnum - 1], &ca)) {
|
||||
mg_error(c, "failed to verify CA");
|
||||
return -1;
|
||||
} else if (is_client) {
|
||||
MG_VERBOSE(
|
||||
("CA was not in the chain, but verification with builtin CA "
|
||||
"passed"));
|
||||
MG_VERBOSE(("no CA in chain; verification with builtin CA passed"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16920,12 +16962,26 @@ void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) {
|
||||
strncpy((char *) tls->hostname, opts->name.buf, sizeof(tls->hostname) - 1);
|
||||
tls->hostname[opts->name.len] = 0;
|
||||
}
|
||||
// server CA certificate, store serial number
|
||||
if (opts->ca.len > 0) {
|
||||
if (mg_parse_pem(opts->ca, mg_str_s("CERTIFICATE"), &tls->ca_der) < 0) {
|
||||
MG_ERROR(("Failed to load certificate"));
|
||||
return;
|
||||
}
|
||||
|
||||
// server CA certificate; parse PEM [bundle] or DER
|
||||
if (opts->ca.len > 0) {
|
||||
struct mg_str *all_certs = NULL;
|
||||
int cert_count = mg_parse_pem_certs(opts->ca, &all_certs);
|
||||
|
||||
if (cert_count > 1 && c->is_client) { // use bundle for clients only
|
||||
tls->ca_bundle_len = (size_t) cert_count;
|
||||
tls->ca_bundle_der = all_certs;
|
||||
MG_VERBOSE(("%d-cert bundle", cert_count));
|
||||
} else if (cert_count > 0) {
|
||||
tls->ca_der.buf = all_certs[0].buf;
|
||||
tls->ca_der.len = all_certs[0].len;
|
||||
mg_free(all_certs);
|
||||
} else { // parse again for a possible DER (or a truncated begin string)
|
||||
if (mg_parse_pem(opts->ca, mg_str_s("CERTIFICATE"), &tls->ca_der) < 0) {
|
||||
MG_ERROR(("Failed to load CA certificate"));
|
||||
return;
|
||||
}
|
||||
} // ca_bundle_len != 0 && ca_der.len = 0 => bundle
|
||||
if (!c->is_client) tls->is_twoway = true; // server + CA: two-way auth
|
||||
}
|
||||
|
||||
@@ -16948,7 +17004,7 @@ void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) {
|
||||
} else {
|
||||
mg_free(all_certs);
|
||||
}
|
||||
} else {
|
||||
} else { // parse again for a possible DER (or a truncated begin string)
|
||||
if (mg_parse_pem(opts->cert, mg_str_s("CERTIFICATE"), &tls->cert_der) <
|
||||
0) {
|
||||
MG_ERROR(("Failed to load certificate"));
|
||||
|
||||
+81
-25
@@ -109,7 +109,9 @@ struct tls_data {
|
||||
bool cert_requested; // client received a CertificateRequest
|
||||
bool is_twoway; // server is configured to authenticate clients
|
||||
struct mg_str cert_der; // certificate in DER format
|
||||
struct mg_str ca_der; // CA certificate
|
||||
struct mg_str ca_der; // current CA certificate
|
||||
struct mg_str *ca_bundle_der; // bundle of CA certificates
|
||||
size_t ca_bundle_len; // number of certificates in bundle
|
||||
struct mg_str *chain_der; // certificate chain (intermediate certs)
|
||||
size_t chain_len; // number of certificates in chain
|
||||
uint8_t ec_key[32]; // EC private key
|
||||
@@ -117,7 +119,7 @@ struct tls_data {
|
||||
struct mg_str rsa_key_der; // RSA private key in DER format
|
||||
char hostname[254]; // matching hostname
|
||||
|
||||
bool is_ec_pubkey; // EC or RSA
|
||||
bool is_ec_pubkey; // EC or RSA. TODO(): currently unused
|
||||
uint8_t pubkey[512 + 16]; // server EC (64) or RSA (512+exp) public key to
|
||||
// verify cert
|
||||
size_t pubkeysz; // size of the server public key
|
||||
@@ -1361,18 +1363,20 @@ static int mg_tls_client_recv_ext(struct mg_connection *c) {
|
||||
}
|
||||
|
||||
struct mg_tls_cert {
|
||||
int is_ec_pubkey;
|
||||
bool is_ec_pubkey;
|
||||
struct mg_str sn;
|
||||
struct mg_str pubkey;
|
||||
struct mg_der_tlv issuer;
|
||||
struct mg_der_tlv subj;
|
||||
struct mg_str sig; // signature
|
||||
uint8_t tbshash[48]; // 32b for sha256/secp256, 48b for sha384/secp384
|
||||
uint8_t tbshash[48]; // 32B for sha256/secp256, 48B for sha384/secp384
|
||||
size_t tbshashsz; // actual TBS hash size
|
||||
};
|
||||
|
||||
static void mg_der_debug_cert_name(const char *name, struct mg_der_tlv *tlv) {
|
||||
struct mg_der_tlv v;
|
||||
struct mg_str cn, c, o, ou;
|
||||
if (mg_log_level < MG_LL_VERBOSE) return; // skip recursive computations
|
||||
cn = c = o = ou = mg_str("");
|
||||
if (mg_der_find_oid(tlv, (uint8_t *) "\x55\x04\x03", 3, &v))
|
||||
cn = mg_str_n((const char *) v.value, v.len);
|
||||
@@ -1452,6 +1456,7 @@ static int mg_tls_parse_cert_der(void *buf, size_t dersz,
|
||||
|
||||
// issuer
|
||||
if (mg_der_next(&tbs_cert, &field) <= 0 || field.type != 0x30) return -1;
|
||||
cert->issuer = field;
|
||||
mg_der_debug_cert_name("issuer", &field);
|
||||
|
||||
// validity dates (before/after)
|
||||
@@ -1483,21 +1488,21 @@ static int mg_tls_parse_cert_der(void *buf, size_t dersz,
|
||||
MG_VERBOSE(("pk algo (oid): %M", mg_print_hex, pki_algo.len, pki_algo.value));
|
||||
if (pki_algo.len == 8 &&
|
||||
memcmp(pki_algo.value, "\x2A\x86\x48\xCE\x3D\x03\x01\x07", 8) == 0) {
|
||||
cert->is_ec_pubkey = 1;
|
||||
cert->is_ec_pubkey = true;
|
||||
MG_VERBOSE(("pk algo: ECDSA secp256r1"));
|
||||
} else if (pki_algo.len == 8 &&
|
||||
memcmp(pki_algo.value, "\x2A\x86\x48\xCE\x3D\x03\x01\x08", 8) ==
|
||||
0) {
|
||||
cert->is_ec_pubkey = 1;
|
||||
cert->is_ec_pubkey = true;
|
||||
MG_VERBOSE(("pk algo: ECDSA secp384r1"));
|
||||
} else if (pki_algo.len == 7 &&
|
||||
memcmp(pki_algo.value, "\x2A\x86\x48\xCE\x3D\x02\x01", 7) == 0) {
|
||||
cert->is_ec_pubkey = 1;
|
||||
cert->is_ec_pubkey = true;
|
||||
MG_VERBOSE(("pk algo: EC public key"));
|
||||
} else if (pki_algo.len == 9 &&
|
||||
memcmp(pki_algo.value, "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01",
|
||||
9) == 0) {
|
||||
cert->is_ec_pubkey = 0;
|
||||
cert->is_ec_pubkey = false;
|
||||
MG_VERBOSE(("pk algo: RSA"));
|
||||
} else {
|
||||
MG_ERROR(("unsupported pk algo: %M", mg_print_hex, pki_algo.len,
|
||||
@@ -1588,7 +1593,7 @@ static int mg_tls_verify_cert_signature(const struct mg_tls_cert *cert,
|
||||
(unsigned) cert->tbshashsz, sig,
|
||||
mg_uecc_secp256r1());
|
||||
} else if (issuer->pubkey.len == 96) {
|
||||
MG_ERROR(("reject secp386 for now"));
|
||||
MG_ERROR(("reject secp384 for now"));
|
||||
return 0;
|
||||
} else {
|
||||
MG_ERROR(("unsupported public key length: %d", issuer->pubkey.len));
|
||||
@@ -1629,6 +1634,27 @@ static int mg_tls_verify_cert_cn(struct mg_der_tlv *subj, const char *host) {
|
||||
return matched;
|
||||
}
|
||||
|
||||
static int tls_bundle_find(struct tls_data *tls, struct mg_der_tlv *name,
|
||||
struct mg_tls_cert *cert) {
|
||||
size_t i;
|
||||
struct mg_der_tlv v;
|
||||
struct mg_str *p = tls->ca_bundle_der, tgt;
|
||||
if (!mg_der_find_oid(name, (uint8_t *) "\x55\x04\x03", 3, &v)) return false;
|
||||
tgt = mg_str_n((const char *) v.value, v.len);
|
||||
for (i = 0; i < tls->ca_bundle_len; i++, p++) {
|
||||
struct mg_str subj;
|
||||
if (mg_tls_parse_cert_der(p->buf, p->len, cert) < 0 ||
|
||||
!mg_der_find_oid(&cert->subj, (uint8_t *) "\x55\x04\x03", 3, &v)) {
|
||||
MG_ERROR(("failed to parse certificate #%u in bundle", i + 1));
|
||||
return -1;
|
||||
}
|
||||
subj = mg_str_n((const char *) v.value, v.len);
|
||||
MG_VERBOSE(("#%u: %.*s (%.*s)", i + 1, subj.len, subj.buf, tgt.len, tgt.buf));
|
||||
if (mg_strcasecmp(subj, tgt) == 0) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mg_tls_recv_cert(struct mg_connection *c, bool is_client) {
|
||||
struct tls_data *tls = (struct tls_data *) c->tls;
|
||||
unsigned char *recv_buf;
|
||||
@@ -1678,7 +1704,7 @@ static int mg_tls_recv_cert(struct mg_connection *c, bool is_client) {
|
||||
memset(certs, 0, sizeof(certs));
|
||||
memset(&ca, 0, sizeof(ca));
|
||||
|
||||
if (tls->ca_der.len > 0) {
|
||||
if (tls->ca_der.len > 0) { // single cert or server
|
||||
if (mg_tls_parse_cert_der(tls->ca_der.buf, tls->ca_der.len, &ca) < 0) {
|
||||
mg_error(c, "failed to parse CA certificate");
|
||||
return -1;
|
||||
@@ -1728,10 +1754,18 @@ static int mg_tls_recv_cert(struct mg_connection *c, bool is_client) {
|
||||
}
|
||||
}
|
||||
|
||||
if (ca.pubkey.len == ci->pubkey.len &&
|
||||
memcmp(ca.pubkey.buf, ci->pubkey.buf, ca.pubkey.len) == 0) {
|
||||
found_ca = true;
|
||||
break;
|
||||
if (tls->ca_bundle_len > 0) { // bundle, find subject and compare keys
|
||||
MG_VERBOSE(("Search current cert in bundle"));
|
||||
int r = tls_bundle_find(tls, &ci->subj, &ca); // find current cert ci
|
||||
if (r < 0) {
|
||||
mg_error(c, "failed to parse CA bundle");
|
||||
return -1;
|
||||
} else if (r > 0 && ca.pubkey.len == ci->pubkey.len &&
|
||||
memcmp(ca.pubkey.buf, ci->pubkey.buf, ca.pubkey.len) == 0) {
|
||||
found_ca = true;
|
||||
MG_VERBOSE(("CA serial: %M", mg_print_hex, ca.sn.len, ca.sn.buf));
|
||||
break;
|
||||
} // else either r = 0 => subj not found or pubkey not matching
|
||||
}
|
||||
|
||||
if (certnum == sizeof(certs) / sizeof(certs[0]) - 1) {
|
||||
@@ -1740,15 +1774,23 @@ static int mg_tls_recv_cert(struct mg_connection *c, bool is_client) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!found_ca && tls->ca_der.len > 0) {
|
||||
if (!found_ca && certnum > 0 && tls->ca_bundle_len > 0) { // bundle
|
||||
MG_VERBOSE(("Search bundle for issuer of last cert in chain"));
|
||||
int r = tls_bundle_find(tls, &certs[certnum - 1].issuer, &ca);
|
||||
if (r <= 0) {
|
||||
mg_error(c, r < 0 ? "failed to parse CA bundle"
|
||||
: "failed to find issuing CA in bundle");
|
||||
return -1;
|
||||
} // else r > 0 => issuer found
|
||||
MG_VERBOSE(("CA serial: %M", mg_print_hex, ca.sn.len, ca.sn.buf));
|
||||
}
|
||||
if (!found_ca && tls->ca_der.len > 0) { // single cert or server
|
||||
if (certnum < 1 ||
|
||||
!mg_tls_verify_cert_signature(&certs[certnum - 1], &ca)) {
|
||||
mg_error(c, "failed to verify CA");
|
||||
return -1;
|
||||
} else if (is_client) {
|
||||
MG_VERBOSE(
|
||||
("CA was not in the chain, but verification with builtin CA "
|
||||
"passed"));
|
||||
MG_VERBOSE(("no CA in chain; verification with builtin CA passed"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2446,12 +2488,26 @@ void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) {
|
||||
strncpy((char *) tls->hostname, opts->name.buf, sizeof(tls->hostname) - 1);
|
||||
tls->hostname[opts->name.len] = 0;
|
||||
}
|
||||
// server CA certificate, store serial number
|
||||
if (opts->ca.len > 0) {
|
||||
if (mg_parse_pem(opts->ca, mg_str_s("CERTIFICATE"), &tls->ca_der) < 0) {
|
||||
MG_ERROR(("Failed to load certificate"));
|
||||
return;
|
||||
}
|
||||
|
||||
// server CA certificate; parse PEM [bundle] or DER
|
||||
if (opts->ca.len > 0) {
|
||||
struct mg_str *all_certs = NULL;
|
||||
int cert_count = mg_parse_pem_certs(opts->ca, &all_certs);
|
||||
|
||||
if (cert_count > 1 && c->is_client) { // use bundle for clients only
|
||||
tls->ca_bundle_len = (size_t) cert_count;
|
||||
tls->ca_bundle_der = all_certs;
|
||||
MG_VERBOSE(("%d-cert bundle", cert_count));
|
||||
} else if (cert_count > 0) {
|
||||
tls->ca_der.buf = all_certs[0].buf;
|
||||
tls->ca_der.len = all_certs[0].len;
|
||||
mg_free(all_certs);
|
||||
} else { // parse again for a possible DER (or a truncated begin string)
|
||||
if (mg_parse_pem(opts->ca, mg_str_s("CERTIFICATE"), &tls->ca_der) < 0) {
|
||||
MG_ERROR(("Failed to load CA certificate"));
|
||||
return;
|
||||
}
|
||||
} // ca_bundle_len != 0 && ca_der.len = 0 => bundle
|
||||
if (!c->is_client) tls->is_twoway = true; // server + CA: two-way auth
|
||||
}
|
||||
|
||||
@@ -2474,7 +2530,7 @@ void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) {
|
||||
} else {
|
||||
mg_free(all_certs);
|
||||
}
|
||||
} else {
|
||||
} else { // parse again for a possible DER (or a truncated begin string)
|
||||
if (mg_parse_pem(opts->cert, mg_str_s("CERTIFICATE"), &tls->cert_der) <
|
||||
0) {
|
||||
MG_ERROR(("Failed to load certificate"));
|
||||
|
||||
+3103
-3128
File diff suppressed because it is too large.
Load diff
@@ -99,6 +99,7 @@ static void mqtt_ev_handler(struct mg_connection *c, int ev, void *ev_data) {
|
||||
void mg_mqtt_init(struct mg_mgr *mgr) {
|
||||
(void) mgr;
|
||||
if (!s_rpc) mg_rpc_add(&s_rpc, mg_str("ota.update"), rpc_ota_update, NULL);
|
||||
mg_mem_files = mg_packed_files; // Use generated packed filesystem
|
||||
}
|
||||
|
||||
void mg_mqtt_poll(struct mg_mgr *mgr) {
|
||||
|
||||
Reference in new issue
Block a user