summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-07-13 10:41:00 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-07-13 10:41:00 +0300
commit07156681f635a18f0b4e8e76fce60a723c8cddd8 (patch)
tree5491820c9deb03ef02d174fe03bbe1bc6b012b98
parent0076a605540337bd89d37b7887541144e44b20f3 (diff)
GmCerts: Make the server port known
-rw-r--r--src/gmcerts.c15
-rw-r--r--src/gmcerts.h6
-rw-r--r--src/gmrequest.c10
-rw-r--r--src/gmutil.c43
-rw-r--r--src/gmutil.h5
-rw-r--r--src/ui/documentwidget.c12
6 files changed, 74 insertions, 17 deletions
diff --git a/src/gmcerts.c b/src/gmcerts.c
index 8577cf2b..4b84aa05 100644
--- a/src/gmcerts.c
+++ b/src/gmcerts.c
@@ -426,7 +426,7 @@ iBool verifyDomain_GmCerts(const iTlsCertificate *cert, iRangecc domain) {
426 return iFalse; 426 return iFalse;
427} 427}
428 428
429iBool checkTrust_GmCerts(iGmCerts *d, iRangecc domain, const iTlsCertificate *cert) { 429iBool checkTrust_GmCerts(iGmCerts *d, iRangecc domain, uint16_t port, const iTlsCertificate *cert) {
430 if (!cert) { 430 if (!cert) {
431 return iFalse; 431 return iFalse;
432 } 432 }
@@ -441,6 +441,9 @@ iBool checkTrust_GmCerts(iGmCerts *d, iRangecc domain, const iTlsCertificate *ce
441 /* TODO: Could call setTrusted_GmCerts() instead of duplicating the trust-setting. */ 441 /* TODO: Could call setTrusted_GmCerts() instead of duplicating the trust-setting. */
442 /* Good certificate. If not already trusted, add it now. */ 442 /* Good certificate. If not already trusted, add it now. */
443 iString *key = newRange_String(domain); 443 iString *key = newRange_String(domain);
444 if (port && port != GEMINI_DEFAULT_PORT) {
445 appendFormat_String(key, ":%u", port);
446 }
444 iDate until; 447 iDate until;
445 validUntil_TlsCertificate(cert, &until); 448 validUntil_TlsCertificate(cert, &until);
446 iBlock *fingerprint = fingerprint_TlsCertificate(cert); 449 iBlock *fingerprint = fingerprint_TlsCertificate(cert);
@@ -471,10 +474,13 @@ iBool checkTrust_GmCerts(iGmCerts *d, iRangecc domain, const iTlsCertificate *ce
471 return iTrue; 474 return iTrue;
472} 475}
473 476
474void setTrusted_GmCerts(iGmCerts *d, iRangecc domain, const iBlock *fingerprint, 477void setTrusted_GmCerts(iGmCerts *d, iRangecc domain, uint16_t port, const iBlock *fingerprint,
475 const iDate *validUntil) { 478 const iDate *validUntil) {
476 iString *key = collectNew_String(); 479 iString *key = collectNew_String();
477 punyEncodeDomain_Rangecc(domain, key); 480 punyEncodeDomain_Rangecc(domain, key);
481 if (port && port != GEMINI_DEFAULT_PORT) {
482 appendFormat_String(key, ":%u", port);
483 }
478 lock_Mutex(d->mtx); 484 lock_Mutex(d->mtx);
479 iTrustEntry *trust = value_StringHash(d->trusted, key); 485 iTrustEntry *trust = value_StringHash(d->trusted, key);
480 if (trust) { 486 if (trust) {
@@ -488,12 +494,15 @@ void setTrusted_GmCerts(iGmCerts *d, iRangecc domain, const iBlock *fingerprint,
488 unlock_Mutex(d->mtx); 494 unlock_Mutex(d->mtx);
489} 495}
490 496
491iTime domainValidUntil_GmCerts(const iGmCerts *d, iRangecc domain) { 497iTime domainValidUntil_GmCerts(const iGmCerts *d, iRangecc domain, uint16_t port) {
492 iTime expiry; 498 iTime expiry;
493 iZap(expiry); 499 iZap(expiry);
494 lock_Mutex(d->mtx); 500 lock_Mutex(d->mtx);
495 iString key; 501 iString key;
496 initRange_String(&key, domain); 502 initRange_String(&key, domain);
503 if (port && port != GEMINI_DEFAULT_PORT) {
504 appendFormat_String(&key, ":%u", port);
505 }
497 const iTrustEntry *trust = constValue_StringHash(d->trusted, &key); 506 const iTrustEntry *trust = constValue_StringHash(d->trusted, &key);
498 if (trust) { 507 if (trust) {
499 expiry = trust->validUntil; 508 expiry = trust->validUntil;
diff --git a/src/gmcerts.h b/src/gmcerts.h
index a962d8b6..1a9480f7 100644
--- a/src/gmcerts.h
+++ b/src/gmcerts.h
@@ -60,10 +60,10 @@ iDeclareTypeConstructionArgs(GmCerts, const char *saveDir)
60 60
61typedef iBool (*iGmCertsIdentityFilterFunc)(void *context, const iGmIdentity *); 61typedef iBool (*iGmCertsIdentityFilterFunc)(void *context, const iGmIdentity *);
62 62
63iBool checkTrust_GmCerts (iGmCerts *, iRangecc domain, const iTlsCertificate *cert); 63iBool checkTrust_GmCerts (iGmCerts *, iRangecc domain, uint16_t port, const iTlsCertificate *cert);
64void setTrusted_GmCerts (iGmCerts *, iRangecc domain, const iBlock *fingerprint, 64void setTrusted_GmCerts (iGmCerts *, iRangecc domain, uint16_t port, const iBlock *fingerprint,
65 const iDate *validUntil); 65 const iDate *validUntil);
66iTime domainValidUntil_GmCerts(const iGmCerts *, iRangecc domain); 66iTime domainValidUntil_GmCerts(const iGmCerts *, iRangecc domain, uint16_t port);
67 67
68/** 68/**
69 * Create a new self-signed TLS client certificate for identifying the user. 69 * Create a new self-signed TLS client certificate for identifying the user.
diff --git a/src/gmrequest.c b/src/gmrequest.c
index 672614a2..8ae8f736 100644
--- a/src/gmrequest.c
+++ b/src/gmrequest.c
@@ -149,7 +149,11 @@ struct Impl_GmRequest {
149iDefineObjectConstructionArgs(GmRequest, (iGmCerts *certs), certs) 149iDefineObjectConstructionArgs(GmRequest, (iGmCerts *certs), certs)
150iDefineAudienceGetter(GmRequest, updated) 150iDefineAudienceGetter(GmRequest, updated)
151iDefineAudienceGetter(GmRequest, finished) 151iDefineAudienceGetter(GmRequest, finished)
152 152
153static uint16_t port_GmRequest_(iGmRequest *d) {
154 return urlPort_String(&d->url);
155}
156
153static void checkServerCertificate_GmRequest_(iGmRequest *d) { 157static void checkServerCertificate_GmRequest_(iGmRequest *d) {
154 const iTlsCertificate *cert = d->req ? serverCertificate_TlsRequest(d->req) : NULL; 158 const iTlsCertificate *cert = d->req ? serverCertificate_TlsRequest(d->req) : NULL;
155 iGmResponse *resp = d->resp; 159 iGmResponse *resp = d->resp;
@@ -165,7 +169,7 @@ static void checkServerCertificate_GmRequest_(iGmRequest *d) {
165 if (verifyDomain_GmCerts(cert, domain)) { 169 if (verifyDomain_GmCerts(cert, domain)) {
166 resp->certFlags |= domainVerified_GmCertFlag; 170 resp->certFlags |= domainVerified_GmCertFlag;
167 } 171 }
168 if (checkTrust_GmCerts(d->certs, domain, cert)) { 172 if (checkTrust_GmCerts(d->certs, domain, port_GmRequest_(d), cert)) {
169 resp->certFlags |= trusted_GmCertFlag; 173 resp->certFlags |= trusted_GmCertFlag;
170 } 174 }
171 if (verify_TlsCertificate(cert) == authority_TlsCertificateVerifyStatus) { 175 if (verify_TlsCertificate(cert) == authority_TlsCertificateVerifyStatus) {
@@ -836,7 +840,7 @@ void submit_GmRequest(iGmRequest *d) {
836 iConnect(TlsRequest, d->req, readyRead, d, readIncoming_GmRequest_); 840 iConnect(TlsRequest, d->req, readyRead, d, readIncoming_GmRequest_);
837 iConnect(TlsRequest, d->req, finished, d, requestFinished_GmRequest_); 841 iConnect(TlsRequest, d->req, finished, d, requestFinished_GmRequest_);
838 if (port == 0) { 842 if (port == 0) {
839 port = 1965; /* default Gemini port */ 843 port = GEMINI_DEFAULT_PORT; /* default Gemini port */
840 } 844 }
841 setHost_TlsRequest(d->req, host, port); 845 setHost_TlsRequest(d->req, host, port);
842 setContent_TlsRequest(d->req, 846 setContent_TlsRequest(d->req,
diff --git a/src/gmutil.c b/src/gmutil.c
index 846405c3..23f5142f 100644
--- a/src/gmutil.c
+++ b/src/gmutil.c
@@ -74,6 +74,35 @@ void init_Url(iUrl *d, const iString *text) {
74 } 74 }
75} 75}
76 76
77uint16_t port_Url(const iUrl *d) {
78 uint16_t port = 0;
79 if (!isEmpty_Range(&d->port)) {
80 iString portStr;
81 initRange_String(&portStr, d->port);
82 port = toInt_String(&portStr);
83 deinit_String(&portStr);
84 }
85 if (port != 0) {
86 return port;
87 }
88 if (isEmpty_Range(&d->scheme) || equalCase_Rangecc(d->scheme, "gemini")) {
89 port = GEMINI_DEFAULT_PORT;
90 }
91 else if (equalCase_Rangecc(d->scheme, "gopher")) {
92 port = 70;
93 }
94 else if (equalCase_Rangecc(d->scheme, "finger")) {
95 port = 79;
96 }
97 else if (equalCase_Rangecc(d->scheme, "http")) {
98 port = 80;
99 }
100 else if (equalCase_Rangecc(d->scheme, "https")) {
101 port = 443;
102 }
103 return port;
104}
105
77static iRangecc dirPath_(iRangecc path) { 106static iRangecc dirPath_(iRangecc path) {
78 const size_t pos = lastIndexOfCStr_Rangecc(path, "/"); 107 const size_t pos = lastIndexOfCStr_Rangecc(path, "/");
79 if (pos == iInvalidPos) return path; 108 if (pos == iInvalidPos) return path;
@@ -98,7 +127,8 @@ static iRangecc prevPathSeg_(const char *end, const char *start) {
98void stripDefaultUrlPort_String(iString *d) { 127void stripDefaultUrlPort_String(iString *d) {
99 iUrl parts; 128 iUrl parts;
100 init_Url(&parts, d); 129 init_Url(&parts, d);
101 if (equalCase_Rangecc(parts.scheme, "gemini") && equal_Rangecc(parts.port, "1965")) { 130 if (equalCase_Rangecc(parts.scheme, "gemini") &&
131 equal_Rangecc(parts.port, GEMINI_DEFAULT_PORT_CSTR)) {
102 /* Always preceded by a colon. */ 132 /* Always preceded by a colon. */
103 remove_Block(&d->chars, parts.port.start - 1 - constBegin_String(d), 133 remove_Block(&d->chars, parts.port.start - 1 - constBegin_String(d),
104 size_Range(&parts.port) + 1); 134 size_Range(&parts.port) + 1);
@@ -169,6 +199,12 @@ iRangecc urlHost_String(const iString *d) {
169 return url.host; 199 return url.host;
170} 200}
171 201
202uint16_t urlPort_String(const iString *d) {
203 iUrl url;
204 init_Url(&url, d);
205 return port_Url(&url);
206}
207
172iRangecc urlUser_String(const iString *d) { 208iRangecc urlUser_String(const iString *d) {
173 static iRegExp *userPats_[2]; 209 static iRegExp *userPats_[2];
174 if (!userPats_[0]) { 210 if (!userPats_[0]) {
@@ -320,8 +356,9 @@ const iString *absoluteUrl_String(const iString *d, const iString *urlMaybeRelat
320 } 356 }
321 delete_String(decHost); 357 delete_String(decHost);
322 /* Default Gemini port is removed as redundant; normalization. */ 358 /* Default Gemini port is removed as redundant; normalization. */
323 if (!isEmpty_Range(&selHost->port) && (!equalCase_Rangecc(scheme, "gemini") 359 if (!isEmpty_Range(&selHost->port) &&
324 || !equal_Rangecc(selHost->port, "1965"))) { 360 (!equalCase_Rangecc(scheme, "gemini") ||
361 !equal_Rangecc(selHost->port, GEMINI_DEFAULT_PORT_CSTR))) {
325 appendCStr_String(absolute, ":"); 362 appendCStr_String(absolute, ":");
326 appendRange_String(absolute, selHost->port); 363 appendRange_String(absolute, selHost->port);
327 } 364 }
diff --git a/src/gmutil.h b/src/gmutil.h
index be6b471e..40fa1cf9 100644
--- a/src/gmutil.h
+++ b/src/gmutil.h
@@ -93,6 +93,9 @@ const iGmError * get_GmError (enum iGmStatusCode code);
93 93
94iRegExp * newGemtextLink_RegExp (void); 94iRegExp * newGemtextLink_RegExp (void);
95 95
96#define GEMINI_DEFAULT_PORT ((uint16_t) 1965)
97#define GEMINI_DEFAULT_PORT_CSTR "1965"
98
96struct Impl_Url { 99struct Impl_Url {
97 iRangecc scheme; 100 iRangecc scheme;
98 iRangecc host; 101 iRangecc host;
@@ -103,9 +106,11 @@ struct Impl_Url {
103}; 106};
104 107
105void init_Url (iUrl *, const iString *text); 108void init_Url (iUrl *, const iString *text);
109uint16_t port_Url (const iUrl *);
106 110
107iRangecc urlScheme_String (const iString *); 111iRangecc urlScheme_String (const iString *);
108iRangecc urlHost_String (const iString *); 112iRangecc urlHost_String (const iString *);
113uint16_t urlPort_String (const iString *);
109iRangecc urlUser_String (const iString *); 114iRangecc urlUser_String (const iString *);
110iRangecc urlRoot_String (const iString *); 115iRangecc urlRoot_String (const iString *);
111const iString * absoluteUrl_String (const iString *, const iString *urlMaybeRelative); 116const iString * absoluteUrl_String (const iString *, const iString *urlMaybeRelative);
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index 6524d454..962ccc3b 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -2623,8 +2623,9 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)
2623 } 2623 }
2624 else if (equal_Command(cmd, "server.trustcert") && document_App() == d) { 2624 else if (equal_Command(cmd, "server.trustcert") && document_App() == d) {
2625 const iRangecc host = urlHost_String(d->mod.url); 2625 const iRangecc host = urlHost_String(d->mod.url);
2626 const uint16_t port = urlPort_String(d->mod.url);
2626 if (!isEmpty_Block(d->certFingerprint) && !isEmpty_Range(&host)) { 2627 if (!isEmpty_Block(d->certFingerprint) && !isEmpty_Range(&host)) {
2627 setTrusted_GmCerts(certs_App(), host, d->certFingerprint, &d->certExpiry); 2628 setTrusted_GmCerts(certs_App(), host, port, d->certFingerprint, &d->certExpiry);
2628 d->certFlags |= trusted_GmCertFlag; 2629 d->certFlags |= trusted_GmCertFlag;
2629 postCommand_Widget(w, "document.info"); 2630 postCommand_Widget(w, "document.info");
2630 updateTrust_DocumentWidget_(d, NULL); 2631 updateTrust_DocumentWidget_(d, NULL);
@@ -3993,7 +3994,8 @@ static void drawBannerRun_DrawContext_(iDrawContext *d, const iGmRun *run, iInt2
3993 if (certFlags & timeVerified_GmCertFlag && certFlags & domainVerified_GmCertFlag) { 3994 if (certFlags & timeVerified_GmCertFlag && certFlags & domainVerified_GmCertFlag) {
3994 iUrl parts; 3995 iUrl parts;
3995 init_Url(&parts, d->widget->mod.url); 3996 init_Url(&parts, d->widget->mod.url);
3996 const iTime oldUntil = domainValidUntil_GmCerts(certs_App(), parts.host); 3997 const iTime oldUntil =
3998 domainValidUntil_GmCerts(certs_App(), parts.host, port_Url(&parts));
3997 iDate exp; 3999 iDate exp;
3998 init_Date(&exp, &oldUntil); 4000 init_Date(&exp, &oldUntil);
3999 iTime now; 4001 iTime now;
@@ -4192,7 +4194,7 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) {
4192 height_Rect(run->visBounds), 4194 height_Rect(run->visBounds),
4193 tmQuoteIcon_ColorId); 4195 tmQuoteIcon_ColorId);
4194 } 4196 }
4195 drawBoundRange_Text(run->font, visPos, width_Rect(run->bounds), fg, run->text); 4197 drawRange_Text(run->font, visPos, /*width_Rect(run->bounds),*/ fg, run->text);
4196 runDrawn:; 4198 runDrawn:;
4197 } 4199 }
4198 /* Presentation of links. */ 4200 /* Presentation of links. */
@@ -4324,8 +4326,8 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) {
4324 } 4326 }
4325 } 4327 }
4326 } 4328 }
4327// drawRect_Paint(&d->paint, (iRect){ visPos, run->bounds.size }, green_ColorId); 4329 drawRect_Paint(&d->paint, (iRect){ visPos, run->bounds.size }, green_ColorId);
4328// drawRect_Paint(&d->paint, (iRect){ visPos, run->visBounds.size }, red_ColorId); 4330 drawRect_Paint(&d->paint, (iRect){ visPos, run->visBounds.size }, red_ColorId);
4329} 4331}
4330 4332
4331static int drawSideRect_(iPaint *p, iRect rect) { 4333static int drawSideRect_(iPaint *p, iRect rect) {