summaryrefslogtreecommitdiff
path: root/src/gmrequest.c
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2020-08-03 15:28:16 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2020-08-03 15:28:16 +0300
commit856fbf1bf25038997b3dd61fc8707370f085e6da (patch)
tree90c6526fc839184d24bdbd770a956c8568b2956b /src/gmrequest.c
parent922ad3220909b7314ca629949b44d7d3aa0336b2 (diff)
Server certificate TOFU
Diffstat (limited to 'src/gmrequest.c')
-rw-r--r--src/gmrequest.c47
1 files changed, 38 insertions, 9 deletions
diff --git a/src/gmrequest.c b/src/gmrequest.c
index 32b386b2..dc08d23b 100644
--- a/src/gmrequest.c
+++ b/src/gmrequest.c
@@ -1,5 +1,7 @@
1#include "gmrequest.h" 1#include "gmrequest.h"
2#include "gmutil.h" 2#include "gmutil.h"
3#include "gmcerts.h"
4#include "app.h"
3 5
4#include <the_Foundation/file.h> 6#include <the_Foundation/file.h>
5#include <the_Foundation/tlsrequest.h> 7#include <the_Foundation/tlsrequest.h>
@@ -20,7 +22,7 @@ struct Impl_GmRequest {
20 iObject object; 22 iObject object;
21 iMutex mutex; 23 iMutex mutex;
22 enum iGmRequestState state; 24 enum iGmRequestState state;
23 enum iGmRequestCertification certState; 25 int certFlags;
24 iString url; 26 iString url;
25 iTlsRequest *req; 27 iTlsRequest *req;
26 enum iGmStatusCode code; 28 enum iGmStatusCode code;
@@ -38,7 +40,7 @@ iDefineAudienceGetter(GmRequest, finished)
38void init_GmRequest(iGmRequest *d) { 40void init_GmRequest(iGmRequest *d) {
39 init_Mutex(&d->mutex); 41 init_Mutex(&d->mutex);
40 d->state = initialized_GmRequestState; 42 d->state = initialized_GmRequestState;
41 d->certState = notApplicable_GmRequestCertification; 43 d->certFlags = 0;
42 init_String(&d->url); 44 init_String(&d->url);
43 d->req = NULL; 45 d->req = NULL;
44 d->code = none_GmStatusCode; 46 d->code = none_GmStatusCode;
@@ -165,11 +167,25 @@ static void requestFinished_GmRequest_(iAnyObject *obj) {
165 } 167 }
166 SDL_RemoveTimer(d->timeoutId); 168 SDL_RemoveTimer(d->timeoutId);
167 d->timeoutId = 0; 169 d->timeoutId = 0;
168 d->state = finished_GmRequestState; 170 d->state = finished_GmRequestState;
169#if 1 171 d->certFlags = 0;
170 /* Check the server certificate. */ { 172 /* Check the server certificate. */ {
171 d->certState = invalid_GmRequestCertification; /* check trust */
172 const iTlsCertificate *cert = serverCertificate_TlsRequest(d->req); 173 const iTlsCertificate *cert = serverCertificate_TlsRequest(d->req);
174 if (cert) {
175 iGmCerts * certDb = certs_App();
176 const iRangecc domain = urlHost_String(&d->url);
177 d->certFlags |= available_GmRequestCertFlag;
178 if (!isExpired_TlsCertificate(cert)) {
179 d->certFlags |= timeVerified_GmRequestCertFlag;
180 }
181 if (verifyDomain_TlsCertificate(cert, domain)) {
182 d->certFlags |= domainVerified_GmRequestCertFlag;
183 }
184 if (checkTrust_GmCerts(certDb, domain, cert)) {
185 d->certFlags |= trusted_GmRequestCertFlag;
186 }
187 }
188#if 0
173 printf("Server certificate:\n%s\n", cstrLocal_String(pem_TlsCertificate(cert))); 189 printf("Server certificate:\n%s\n", cstrLocal_String(pem_TlsCertificate(cert)));
174 iBlock *sha = fingerprint_TlsCertificate(cert); 190 iBlock *sha = fingerprint_TlsCertificate(cert);
175 printf("Fingerprint: %s\n", 191 printf("Fingerprint: %s\n",
@@ -188,8 +204,8 @@ static void requestFinished_GmRequest_(iAnyObject *obj) {
188 verifyDomain_TlsCertificate(cert, parts.host) ? "valid" : "not valid"); 204 verifyDomain_TlsCertificate(cert, parts.host) ? "valid" : "not valid");
189 } 205 }
190 fflush(stdout); 206 fflush(stdout);
191 }
192#endif 207#endif
208 }
193 unlock_Mutex(&d->mutex); 209 unlock_Mutex(&d->mutex);
194 iNotifyAudience(d, finished, GmRequestFinished); 210 iNotifyAudience(d, finished, GmRequestFinished);
195} 211}
@@ -211,7 +227,7 @@ void submit_GmRequest(iGmRequest *d) {
211 /* TODO: Check supported file types: images, audio */ 227 /* TODO: Check supported file types: images, audio */
212 /* TODO: Detect text files based on contents? E.g., is the content valid UTF-8. */ 228 /* TODO: Detect text files based on contents? E.g., is the content valid UTF-8. */
213 d->code = success_GmStatusCode; 229 d->code = success_GmStatusCode;
214 d->certState = notApplicable_GmRequestCertification; 230 d->certFlags = 0;
215 if (endsWithCase_String(path, ".gmi")) { 231 if (endsWithCase_String(path, ".gmi")) {
216 setCStr_String(&d->header, "text/gemini; charset=utf-8"); 232 setCStr_String(&d->header, "text/gemini; charset=utf-8");
217 } 233 }
@@ -231,6 +247,7 @@ void submit_GmRequest(iGmRequest *d) {
231 setCStr_String(&d->header, "application/octet-stream"); 247 setCStr_String(&d->header, "application/octet-stream");
232 } 248 }
233 set_Block(&d->body, collect_Block(readAll_File(f))); 249 set_Block(&d->body, collect_Block(readAll_File(f)));
250 d->state = receivingBody_GmRequestState;
234 iNotifyAudience(d, updated, GmRequestUpdated); 251 iNotifyAudience(d, updated, GmRequestUpdated);
235 } 252 }
236 else { 253 else {
@@ -238,14 +255,14 @@ void submit_GmRequest(iGmRequest *d) {
238 setCStr_String(&d->header, cstr_String(path)); 255 setCStr_String(&d->header, cstr_String(path));
239 } 256 }
240 iRelease(f); 257 iRelease(f);
258 d->certFlags = 0;
241 d->state = finished_GmRequestState; 259 d->state = finished_GmRequestState;
242 d->certState = notApplicable_GmRequestCertification;
243 iNotifyAudience(d, finished, GmRequestFinished); 260 iNotifyAudience(d, finished, GmRequestFinished);
244 return; 261 return;
245 } 262 }
246 else if (equalCase_Rangecc(&url.protocol, "data")) { 263 else if (equalCase_Rangecc(&url.protocol, "data")) {
247 d->code = success_GmStatusCode; 264 d->code = success_GmStatusCode;
248 d->certState = notApplicable_GmRequestCertification; 265 d->certFlags = 0;
249 iString *src = collectNewCStr_String(url.protocol.start + 5); 266 iString *src = collectNewCStr_String(url.protocol.start + 5);
250 iRangecc header = { constBegin_String(src), constBegin_String(src) }; 267 iRangecc header = { constBegin_String(src), constBegin_String(src) };
251 while (header.end < constEnd_String(src) && *header.end != ',') { 268 while (header.end < constEnd_String(src) && *header.end != ',') {
@@ -269,6 +286,8 @@ void submit_GmRequest(iGmRequest *d) {
269 set_String(src, collect_String(urlDecode_String(src))); 286 set_String(src, collect_String(urlDecode_String(src)));
270 } 287 }
271 set_Block(&d->body, &src->chars); 288 set_Block(&d->body, &src->chars);
289 d->state = receivingBody_GmRequestState;
290 iNotifyAudience(d, updated, GmRequestUpdated);
272 d->state = finished_GmRequestState; 291 d->state = finished_GmRequestState;
273 iNotifyAudience(d, finished, GmRequestFinished); 292 iNotifyAudience(d, finished, GmRequestFinished);
274 return; 293 return;
@@ -314,4 +333,14 @@ const iString *url_GmRequest(const iGmRequest *d) {
314 return &d->url; 333 return &d->url;
315} 334}
316 335
336int certFlags_GmRequest(const iGmRequest *d) {
337 return d->certFlags;
338}
339
340iDate certExpirationDate_GmRequest(const iGmRequest *d) {
341 iDate expiry;
342 validUntil_TlsCertificate(serverCertificate_TlsRequest(d->req), &expiry);
343 return expiry;
344}
345
317iDefineClass(GmRequest) 346iDefineClass(GmRequest)