summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gmcerts.c26
-rw-r--r--src/gmrequest.c10
-rw-r--r--src/gmutil.c6
-rw-r--r--src/gmutil.h1
-rw-r--r--src/ui/documentwidget.c38
5 files changed, 60 insertions, 21 deletions
diff --git a/src/gmcerts.c b/src/gmcerts.c
index 32e47b40..d8e77b12 100644
--- a/src/gmcerts.c
+++ b/src/gmcerts.c
@@ -456,13 +456,8 @@ iBool checkTrust_GmCerts(iGmCerts *d, iRangecc domain, uint16_t port, const iTls
456 if (!cert) { 456 if (!cert) {
457 return iFalse; 457 return iFalse;
458 } 458 }
459 if (isExpired_TlsCertificate(cert)) {
460 return iFalse;
461 }
462 /* We trust CA verification implicitly. */ 459 /* We trust CA verification implicitly. */
463 //const iBool isAuth = verify_TlsCertificate(cert) == authority_TlsCertificateVerifyStatus; 460 if (!verifyDomain_GmCerts(cert, domain)) {
464// const iBool isAuth = iFalse; /* CA verification done during handshake */
465 if (/*!isAuth &&*/ !verifyDomain_GmCerts(cert, domain)) {
466 return iFalse; 461 return iFalse;
467 } 462 }
468 /* TODO: Could call setTrusted_GmCerts() instead of duplicating the trust-setting. */ 463 /* TODO: Could call setTrusted_GmCerts() instead of duplicating the trust-setting. */
@@ -474,11 +469,12 @@ iBool checkTrust_GmCerts(iGmCerts *d, iRangecc domain, uint16_t port, const iTls
474 init_String(&key); 469 init_String(&key);
475 makeTrustKey_(domain, port, &key); 470 makeTrustKey_(domain, port, &key);
476 lock_Mutex(d->mtx); 471 lock_Mutex(d->mtx);
472 iBool ok = !isExpired_TlsCertificate(cert);
477 iTrustEntry *trust = value_StringHash(d->trusted, &key); 473 iTrustEntry *trust = value_StringHash(d->trusted, &key);
478 if (trust) { 474 if (trust) {
479 /* We already have it, check if it matches the one we trust for this domain (if it's 475 /* We already have it, check if it matches the one we trust for this domain (if it's
480 still valid. */ 476 still valid. */
481 if (/*!isAuth && */elapsedSeconds_Time(&trust->validUntil) < 0) { 477 if (elapsedSeconds_Time(&trust->validUntil) < 0) {
482 /* Trusted cert is still valid. */ 478 /* Trusted cert is still valid. */
483 const iBool isTrusted = cmp_Block(fingerprint, &trust->fingerprint) == 0; 479 const iBool isTrusted = cmp_Block(fingerprint, &trust->fingerprint) == 0;
484 unlock_Mutex(d->mtx); 480 unlock_Mutex(d->mtx);
@@ -487,17 +483,23 @@ iBool checkTrust_GmCerts(iGmCerts *d, iRangecc domain, uint16_t port, const iTls
487 return isTrusted; 483 return isTrusted;
488 } 484 }
489 /* Update the trusted cert. */ 485 /* Update the trusted cert. */
490 init_Time(&trust->validUntil, &until); 486 if (ok) {
491 set_Block(&trust->fingerprint, fingerprint); 487 init_Time(&trust->validUntil, &until);
488 set_Block(&trust->fingerprint, fingerprint);
489 }
492 } 490 }
493 else { 491 else {
494 insert_StringHash(d->trusted, &key, iClob(new_TrustEntry(fingerprint, &until))); 492 if (ok) {
493 insert_StringHash(d->trusted, &key, iClob(new_TrustEntry(fingerprint, &until)));
494 }
495 }
496 if (ok) {
497 save_GmCerts_(d);
495 } 498 }
496 save_GmCerts_(d);
497 unlock_Mutex(d->mtx); 499 unlock_Mutex(d->mtx);
498 delete_Block(fingerprint); 500 delete_Block(fingerprint);
499 deinit_String(&key); 501 deinit_String(&key);
500 return iTrue; 502 return ok;
501} 503}
502 504
503void setTrusted_GmCerts(iGmCerts *d, iRangecc domain, uint16_t port, const iBlock *fingerprint, 505void setTrusted_GmCerts(iGmCerts *d, iRangecc domain, uint16_t port, const iBlock *fingerprint,
diff --git a/src/gmrequest.c b/src/gmrequest.c
index 9b640cee..44ef063f 100644
--- a/src/gmrequest.c
+++ b/src/gmrequest.c
@@ -290,8 +290,14 @@ static void requestFinished_GmRequest_(iGmRequest *d, iTlsRequest *req) {
290 : finished_GmRequestState); 290 : finished_GmRequestState);
291 if (d->state == failure_GmRequestState) { 291 if (d->state == failure_GmRequestState) {
292 if (!isVerified_TlsRequest(req)) { 292 if (!isVerified_TlsRequest(req)) {
293 d->resp->statusCode = tlsServerCertificateNotVerified_GmStatusCode; 293 if (isExpired_TlsCertificate(serverCertificate_TlsRequest(req))) {
294 setCStr_String(&d->resp->meta, "Server certificate could not be verified"); 294 d->resp->statusCode = tlsServerCertificateExpired_GmStatusCode;
295 setCStr_String(&d->resp->meta, "Server certificate has expired");
296 }
297 else {
298 d->resp->statusCode = tlsServerCertificateNotVerified_GmStatusCode;
299 setCStr_String(&d->resp->meta, "Server certificate could not be verified");
300 }
295 } 301 }
296 else { 302 else {
297 d->resp->statusCode = tlsFailure_GmStatusCode; 303 d->resp->statusCode = tlsFailure_GmStatusCode;
diff --git a/src/gmutil.c b/src/gmutil.c
index 0ae0861c..fda8489b 100644
--- a/src/gmutil.c
+++ b/src/gmutil.c
@@ -682,8 +682,12 @@ static const struct {
682 { 0x1f5a7, /* networked computers */ 682 { 0x1f5a7, /* networked computers */
683 "${error.tls}", 683 "${error.tls}",
684 "${error.tls.msg}" } }, 684 "${error.tls.msg}" } },
685 { tlsServerCertificateExpired_GmStatusCode,
686 { 0x1f4C6, /* calendar */
687 "${error.certexpired}",
688 "${error.certexpired.msg}" } },
685 { tlsServerCertificateNotVerified_GmStatusCode, 689 { tlsServerCertificateNotVerified_GmStatusCode,
686 { 0x1f645, 690 { 0x1f645, /* no good */
687 "${error.certverify}", 691 "${error.certverify}",
688 "${error.certverify.msg}" } }, 692 "${error.certverify.msg}" } },
689 { temporaryFailure_GmStatusCode, 693 { temporaryFailure_GmStatusCode,
diff --git a/src/gmutil.h b/src/gmutil.h
index 1bf41775..f8491781 100644
--- a/src/gmutil.h
+++ b/src/gmutil.h
@@ -43,6 +43,7 @@ enum iGmStatusCode {
43 unknownStatusCode_GmStatusCode, 43 unknownStatusCode_GmStatusCode,
44 invalidLocalResource_GmStatusCode, 44 invalidLocalResource_GmStatusCode,
45 tlsFailure_GmStatusCode, 45 tlsFailure_GmStatusCode,
46 tlsServerCertificateExpired_GmStatusCode,
46 tlsServerCertificateNotVerified_GmStatusCode, 47 tlsServerCertificateNotVerified_GmStatusCode,
47 48
48 none_GmStatusCode = 0, 49 none_GmStatusCode = 0,
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index 4a4101b1..f0ee9823 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -1135,7 +1135,18 @@ static void showErrorPage_DocumentWidget_(iDocumentWidget *d, enum iGmStatusCode
1135 useBanner = iFalse; /* valid data wasn't received from host */ 1135 useBanner = iFalse; /* valid data wasn't received from host */
1136 appendFormat_String(src, "\n\n>%s\n", cstr_String(meta)); 1136 appendFormat_String(src, "\n\n>%s\n", cstr_String(meta));
1137 break; 1137 break;
1138 /* fall through */ 1138 case tlsServerCertificateExpired_GmStatusCode:
1139 makeFooterButtons_DocumentWidget_(
1140 d,
1141 (iMenuItem[]){ { rightArrowhead_Icon " Ignore Expiry and Continue Loading",
1142 0, 0, "server.unexpire"
1143 },
1144 { info_Icon " ${menu.pageinfo}",
1145 SDLK_i,
1146 KMOD_PRIMARY,
1147 "document.info" } },
1148 2);
1149 break;
1139 case tlsServerCertificateNotVerified_GmStatusCode: 1150 case tlsServerCertificateNotVerified_GmStatusCode:
1140 makeFooterButtons_DocumentWidget_( 1151 makeFooterButtons_DocumentWidget_(
1141 d, 1152 d,
@@ -1575,12 +1586,12 @@ static void updateTrust_DocumentWidget_(iDocumentWidget *d, const iGmResponse *r
1575 ~d->certFlags & trusted_GmCertFlag) { 1586 ~d->certFlags & trusted_GmCertFlag) {
1576 updateTextCStr_LabelWidget(lock, red_ColorEscape warning_Icon); 1587 updateTextCStr_LabelWidget(lock, red_ColorEscape warning_Icon);
1577 } 1588 }
1578 else if (d->certFlags & trusted_GmCertFlag) { 1589 else if (~d->certFlags & timeVerified_GmCertFlag) {
1579 updateTextCStr_LabelWidget(lock, green_ColorEscape closedLock_Icon); 1590 updateTextCStr_LabelWidget(lock, isDarkMode ? orange_ColorEscape warning_Icon
1591 : black_ColorEscape warning_Icon);
1580 } 1592 }
1581 else { 1593 else {
1582 updateTextCStr_LabelWidget(lock, isDarkMode ? orange_ColorEscape warning_Icon 1594 updateTextCStr_LabelWidget(lock, green_ColorEscape closedLock_Icon);
1583 : black_ColorEscape warning_Icon);
1584 } 1595 }
1585 setBanner_GmDocument(d->doc, bannerType_DocumentWidget_(d)); 1596 setBanner_GmDocument(d->doc, bannerType_DocumentWidget_(d));
1586} 1597}
@@ -2631,12 +2642,27 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)
2631 addAction_Widget(dlg, SDLK_SPACE, 0, "message.ok"); 2642 addAction_Widget(dlg, SDLK_SPACE, 0, "message.ok");
2632 return iTrue; 2643 return iTrue;
2633 } 2644 }
2645 else if (equal_Command(cmd, "server.unexpire") && document_App() == d) {
2646 const iRangecc host = urlHost_String(d->mod.url);
2647 const uint16_t port = urlPort_String(d->mod.url);
2648 if (!isEmpty_Block(d->certFingerprint) && !isEmpty_Range(&host)) {
2649 iTime expiry;
2650 initCurrent_Time(&expiry);
2651 iTime oneHour; /* One hour is long enough for a single visit (?). */
2652 initSeconds_Time(&oneHour, 3600);
2653 add_Time(&expiry, &oneHour);
2654 iDate expDate;
2655 init_Date(&expDate, &expiry);
2656 setTrusted_GmCerts(certs_App(), host, port, d->certFingerprint, &expDate);
2657 postCommand_Widget(w, "navigate.reload");
2658 }
2659 return iTrue;
2660 }
2634 else if (equal_Command(cmd, "server.trustcert") && document_App() == d) { 2661 else if (equal_Command(cmd, "server.trustcert") && document_App() == d) {
2635 const iRangecc host = urlHost_String(d->mod.url); 2662 const iRangecc host = urlHost_String(d->mod.url);
2636 const uint16_t port = urlPort_String(d->mod.url); 2663 const uint16_t port = urlPort_String(d->mod.url);
2637 if (!isEmpty_Block(d->certFingerprint) && !isEmpty_Range(&host)) { 2664 if (!isEmpty_Block(d->certFingerprint) && !isEmpty_Range(&host)) {
2638 setTrusted_GmCerts(certs_App(), host, port, d->certFingerprint, &d->certExpiry); 2665 setTrusted_GmCerts(certs_App(), host, port, d->certFingerprint, &d->certExpiry);
2639 d->certFlags |= trusted_GmCertFlag;
2640 postCommand_Widget(w, "navigate.reload"); 2666 postCommand_Widget(w, "navigate.reload");
2641 } 2667 }
2642 return iTrue; 2668 return iTrue;