diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-03-26 11:14:57 +0200 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-03-26 11:14:57 +0200 |
commit | 1e5dfdc840824723dfa142707aca1f0fca4c0056 (patch) | |
tree | 1b2c10b7529381754383e7f0140971f26557263a /src/gmcerts.c | |
parent | 2740b24b1ff0c6c5363303fcc35028d471c1ce0e (diff) |
GmCerts: Relaxed domain verification
Allow a certificate for a higher-level domain to be verified against any subdomains, i.e., implicitly assume every certificate uses wildcards.
CA verification is still done separately, and OpenSSL does that strictly as before.
Diffstat (limited to 'src/gmcerts.c')
-rw-r--r-- | src/gmcerts.c | 31 |
1 files changed, 30 insertions, 1 deletions
diff --git a/src/gmcerts.c b/src/gmcerts.c index 6a1ba98c..2cc10a3d 100644 --- a/src/gmcerts.c +++ b/src/gmcerts.c | |||
@@ -374,6 +374,35 @@ void deinit_GmCerts(iGmCerts *d) { | |||
374 | delete_Mutex(d->mtx); | 374 | delete_Mutex(d->mtx); |
375 | } | 375 | } |
376 | 376 | ||
377 | static iRangecc stripFirstDomainLabel_(iRangecc domain) { | ||
378 | iRangecc label = iNullRange; | ||
379 | if (nextSplit_Rangecc(domain, ".", &label) && nextSplit_Rangecc(domain, ".", &label)) { | ||
380 | return (iRangecc){ label.start, domain.end }; | ||
381 | } | ||
382 | return iNullRange; | ||
383 | } | ||
384 | |||
385 | iBool verifyDomain_GmCerts(const iTlsCertificate *cert, iRangecc domain) { | ||
386 | if (verifyDomain_TlsCertificate(cert, domain)) { | ||
387 | return iTrue; | ||
388 | } | ||
389 | /* Allow for an implicit wildcard in the domain name. Self-signed TOFU is really only | ||
390 | about the public/private key pair; any other details should be considered | ||
391 | complementary. */ | ||
392 | for (iRangecc higherDomain = stripFirstDomainLabel_(domain); | ||
393 | !isEmpty_Range(&higherDomain); | ||
394 | higherDomain = stripFirstDomainLabel_(higherDomain)) { | ||
395 | if (!iStrStrN(higherDomain.start, ".", size_Range(&higherDomain))) { | ||
396 | /* Must have two labels at least. */ | ||
397 | break; | ||
398 | } | ||
399 | if (verifyDomain_TlsCertificate(cert, higherDomain)) { | ||
400 | return iTrue; | ||
401 | } | ||
402 | } | ||
403 | return iFalse; | ||
404 | } | ||
405 | |||
377 | iBool checkTrust_GmCerts(iGmCerts *d, iRangecc domain, const iTlsCertificate *cert) { | 406 | iBool checkTrust_GmCerts(iGmCerts *d, iRangecc domain, const iTlsCertificate *cert) { |
378 | if (!cert) { | 407 | if (!cert) { |
379 | return iFalse; | 408 | return iFalse; |
@@ -383,7 +412,7 @@ iBool checkTrust_GmCerts(iGmCerts *d, iRangecc domain, const iTlsCertificate *ce | |||
383 | } | 412 | } |
384 | /* We trust CA verification implicitly. */ | 413 | /* We trust CA verification implicitly. */ |
385 | const iBool isAuth = verify_TlsCertificate(cert) == authority_TlsCertificateVerifyStatus; | 414 | const iBool isAuth = verify_TlsCertificate(cert) == authority_TlsCertificateVerifyStatus; |
386 | if (!isAuth && !verifyDomain_TlsCertificate(cert, domain)) { | 415 | if (!isAuth && !verifyDomain_GmCerts(cert, domain)) { |
387 | return iFalse; | 416 | return iFalse; |
388 | } | 417 | } |
389 | /* TODO: Could call setTrusted_GmCerts() instead of duplicating the trust-setting. */ | 418 | /* TODO: Could call setTrusted_GmCerts() instead of duplicating the trust-setting. */ |