summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-03-26 11:14:57 +0200
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-03-26 11:14:57 +0200
commit1e5dfdc840824723dfa142707aca1f0fca4c0056 (patch)
tree1b2c10b7529381754383e7f0140971f26557263a /src
parent2740b24b1ff0c6c5363303fcc35028d471c1ce0e (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')
-rw-r--r--src/gmcerts.c31
-rw-r--r--src/gmcerts.h2
-rw-r--r--src/gmrequest.c2
3 files changed, 33 insertions, 2 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
377static 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
385iBool 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
377iBool checkTrust_GmCerts(iGmCerts *d, iRangecc domain, const iTlsCertificate *cert) { 406iBool 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. */
diff --git a/src/gmcerts.h b/src/gmcerts.h
index a28c050e..a9859845 100644
--- a/src/gmcerts.h
+++ b/src/gmcerts.h
@@ -95,3 +95,5 @@ const iPtrArray * listIdentities_GmCerts (const iGmCerts *, iGmCertsIdentityF
95 95
96void signIn_GmCerts (iGmCerts *, iGmIdentity *identity, const iString *url); 96void signIn_GmCerts (iGmCerts *, iGmIdentity *identity, const iString *url);
97void signOut_GmCerts (iGmCerts *, const iString *url); 97void signOut_GmCerts (iGmCerts *, const iString *url);
98
99iBool verifyDomain_GmCerts (const iTlsCertificate *cert, iRangecc domain);
diff --git a/src/gmrequest.c b/src/gmrequest.c
index f065f935..c968990c 100644
--- a/src/gmrequest.c
+++ b/src/gmrequest.c
@@ -157,7 +157,7 @@ static void checkServerCertificate_GmRequest_(iGmRequest *d) {
157 if (!isExpired_TlsCertificate(cert)) { 157 if (!isExpired_TlsCertificate(cert)) {
158 resp->certFlags |= timeVerified_GmCertFlag; 158 resp->certFlags |= timeVerified_GmCertFlag;
159 } 159 }
160 if (verifyDomain_TlsCertificate(cert, domain)) { 160 if (verifyDomain_GmCerts(cert, domain)) {
161 resp->certFlags |= domainVerified_GmCertFlag; 161 resp->certFlags |= domainVerified_GmCertFlag;
162 } 162 }
163 if (checkTrust_GmCerts(d->certs, domain, cert)) { 163 if (checkTrust_GmCerts(d->certs, domain, cert)) {