From 05ef7ebad9af2c03b9ce7dd63331df246cf9ce5f Mon Sep 17 00:00:00 2001 From: "Sergio R. Caprile" Date: Tue, 3 Mar 2026 13:03:56 -0300 Subject: [PATCH] allow no certs for client with (not enforced) two-way auth --- mongoose.c | 43 +++++++++++++++++++++++-------------------- src/tls_builtin.c | 43 +++++++++++++++++++++++-------------------- 2 files changed, 46 insertions(+), 40 deletions(-) diff --git a/mongoose.c b/mongoose.c index c8b91d25bf..1ac905241b 100644 --- a/mongoose.c +++ b/mongoose.c @@ -16125,33 +16125,36 @@ static bool mg_tls_send_cert(struct mg_connection *c, bool is_client) { cert = (uint8_t *) mg_calloc(1, 13 + total_size); if (cert == NULL) return res; cert[0] = MG_TLS_CERTIFICATE; // handshake header + if (is_client && tls->cert_der.len == 0) total_size = 0; // empty list MG_STORE_BE24(cert + 1, total_size + 4); cert[4] = 0; // request context MG_STORE_BE24(cert + 5, total_size); // 3 bytes: cert (s) length offset = 8; - MG_STORE_BE24(cert + offset, tls->cert_der.len); // 3 bytes: first cert len - offset += 3; - // bytes 11+ are certificate in DER format - memmove(cert + offset, tls->cert_der.buf, tls->cert_der.len); - offset += tls->cert_der.len; - MG_STORE_BE16(cert + offset, 0); // certificate extensions (none) - offset += 2; - for (i = 1; i < tls->chain_len; i++) { - MG_STORE_BE24(cert + offset, tls->chain_der[i].len); + if (total_size > 0) { // handle empty list, RFC-8446 4.4.2 + MG_STORE_BE24(cert + offset, tls->cert_der.len); // 3 bytes: 1st cert len offset += 3; - memmove(cert + offset, tls->chain_der[i].buf, tls->chain_der[i].len); - offset += tls->chain_der[i].len; - MG_STORE_BE16(cert + offset, 0); // certificate extensions (none) - offset += 2; - } - if (send_ca) { - MG_STORE_BE24(cert + offset, tls->ca_der.len); // 3 bytes: CA cert length - offset += 3; - memmove(cert + offset, tls->ca_der.buf, - tls->ca_der.len); // CA cert data - offset += tls->ca_der.len; + // bytes 11+ are certificate in DER format + memmove(cert + offset, tls->cert_der.buf, tls->cert_der.len); + offset += tls->cert_der.len; MG_STORE_BE16(cert + offset, 0); // certificate extensions (none) offset += 2; + for (i = 1; i < tls->chain_len; i++) { + MG_STORE_BE24(cert + offset, tls->chain_der[i].len); + offset += 3; + memmove(cert + offset, tls->chain_der[i].buf, tls->chain_der[i].len); + offset += tls->chain_der[i].len; + MG_STORE_BE16(cert + offset, 0); // certificate extensions (none) + offset += 2; + } + if (send_ca) { + MG_STORE_BE24(cert + offset, tls->ca_der.len); // 3 bytes: CA cert length + offset += 3; + memmove(cert + offset, tls->ca_der.buf, + tls->ca_der.len); // CA cert data + offset += tls->ca_der.len; + MG_STORE_BE16(cert + offset, 0); // certificate extensions (none) + offset += 2; + } } mg_sha256_update(&tls->sha256, cert, offset); res = mg_tls_encrypt(c, cert, offset, MG_TLS_HANDSHAKE); diff --git a/src/tls_builtin.c b/src/tls_builtin.c index 6d10728616..91ced4b403 100644 --- a/src/tls_builtin.c +++ b/src/tls_builtin.c @@ -813,33 +813,36 @@ static bool mg_tls_send_cert(struct mg_connection *c, bool is_client) { cert = (uint8_t *) mg_calloc(1, 13 + total_size); if (cert == NULL) return res; cert[0] = MG_TLS_CERTIFICATE; // handshake header + if (is_client && tls->cert_der.len == 0) total_size = 0; // empty list MG_STORE_BE24(cert + 1, total_size + 4); cert[4] = 0; // request context MG_STORE_BE24(cert + 5, total_size); // 3 bytes: cert (s) length offset = 8; - MG_STORE_BE24(cert + offset, tls->cert_der.len); // 3 bytes: first cert len - offset += 3; - // bytes 11+ are certificate in DER format - memmove(cert + offset, tls->cert_der.buf, tls->cert_der.len); - offset += tls->cert_der.len; - MG_STORE_BE16(cert + offset, 0); // certificate extensions (none) - offset += 2; - for (i = 1; i < tls->chain_len; i++) { - MG_STORE_BE24(cert + offset, tls->chain_der[i].len); - offset += 3; - memmove(cert + offset, tls->chain_der[i].buf, tls->chain_der[i].len); - offset += tls->chain_der[i].len; - MG_STORE_BE16(cert + offset, 0); // certificate extensions (none) - offset += 2; - } - if (send_ca) { - MG_STORE_BE24(cert + offset, tls->ca_der.len); // 3 bytes: CA cert length + if (total_size > 0) { // handle empty list, RFC-8446 4.4.2 + MG_STORE_BE24(cert + offset, tls->cert_der.len); // 3 bytes: 1st cert len offset += 3; - memmove(cert + offset, tls->ca_der.buf, - tls->ca_der.len); // CA cert data - offset += tls->ca_der.len; + // bytes 11+ are certificate in DER format + memmove(cert + offset, tls->cert_der.buf, tls->cert_der.len); + offset += tls->cert_der.len; MG_STORE_BE16(cert + offset, 0); // certificate extensions (none) offset += 2; + for (i = 1; i < tls->chain_len; i++) { + MG_STORE_BE24(cert + offset, tls->chain_der[i].len); + offset += 3; + memmove(cert + offset, tls->chain_der[i].buf, tls->chain_der[i].len); + offset += tls->chain_der[i].len; + MG_STORE_BE16(cert + offset, 0); // certificate extensions (none) + offset += 2; + } + if (send_ca) { + MG_STORE_BE24(cert + offset, tls->ca_der.len); // 3 bytes: CA cert length + offset += 3; + memmove(cert + offset, tls->ca_der.buf, + tls->ca_der.len); // CA cert data + offset += tls->ca_der.len; + MG_STORE_BE16(cert + offset, 0); // certificate extensions (none) + offset += 2; + } } mg_sha256_update(&tls->sha256, cert, offset); res = mg_tls_encrypt(c, cert, offset, MG_TLS_HANDSHAKE);