summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2020-08-03 18:27:45 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2020-08-03 18:27:45 +0300
commitc5f7132d637f0186433cccb4da7b9283a4dd5d9a (patch)
treec5e912733437e307fb894366cc8bf648776a53ce
parent8f62f251ee5e49447c0950719ba6629bc1a23257 (diff)
GmCerts: Thread safety; fixed notifications
Must update the status before notifying.
-rw-r--r--src/gmcerts.c18
-rw-r--r--src/gmrequest.c40
2 files changed, 36 insertions, 22 deletions
diff --git a/src/gmcerts.c b/src/gmcerts.c
index 0aa084a4..11e9ce2c 100644
--- a/src/gmcerts.c
+++ b/src/gmcerts.c
@@ -1,6 +1,7 @@
1#include "gmcerts.h" 1#include "gmcerts.h"
2 2
3#include <the_Foundation/file.h> 3#include <the_Foundation/file.h>
4#include <the_Foundation/mutex.h>
4#include <the_Foundation/path.h> 5#include <the_Foundation/path.h>
5#include <the_Foundation/regexp.h> 6#include <the_Foundation/regexp.h>
6#include <the_Foundation/stringhash.h> 7#include <the_Foundation/stringhash.h>
@@ -32,6 +33,7 @@ iDefineClass(TrustEntry)
32/*-----------------------------------------------------------------------------------------------*/ 33/*-----------------------------------------------------------------------------------------------*/
33 34
34struct Impl_GmCerts { 35struct Impl_GmCerts {
36 iMutex mtx;
35 iString saveDir; 37 iString saveDir;
36 iStringHash *trusted; 38 iStringHash *trusted;
37}; 39};
@@ -87,14 +89,18 @@ static void load_GmCerts_(iGmCerts *d) {
87} 89}
88 90
89void init_GmCerts(iGmCerts *d, const char *saveDir) { 91void init_GmCerts(iGmCerts *d, const char *saveDir) {
92 init_Mutex(&d->mtx);
90 initCStr_String(&d->saveDir, saveDir); 93 initCStr_String(&d->saveDir, saveDir);
91 d->trusted = new_StringHash(); 94 d->trusted = new_StringHash();
92 load_GmCerts_(d); 95 load_GmCerts_(d);
93} 96}
94 97
95void deinit_GmCerts(iGmCerts *d) { 98void deinit_GmCerts(iGmCerts *d) {
96 iRelease(d->trusted); 99 iGuardMutex(&d->mtx, {
97 deinit_String(&d->saveDir); 100 iRelease(d->trusted);
101 deinit_String(&d->saveDir);
102 });
103 deinit_Mutex(&d->mtx);
98} 104}
99 105
100iBool checkTrust_GmCerts(iGmCerts *d, iRangecc domain, const iTlsCertificate *cert) { 106iBool checkTrust_GmCerts(iGmCerts *d, iRangecc domain, const iTlsCertificate *cert) {
@@ -112,6 +118,7 @@ iBool checkTrust_GmCerts(iGmCerts *d, iRangecc domain, const iTlsCertificate *ce
112 iDate until; 118 iDate until;
113 validUntil_TlsCertificate(cert, &until); 119 validUntil_TlsCertificate(cert, &until);
114 iBlock *fingerprint = collect_Block(fingerprint_TlsCertificate(cert)); 120 iBlock *fingerprint = collect_Block(fingerprint_TlsCertificate(cert));
121 lock_Mutex(&d->mtx);
115 iTrustEntry *trust = value_StringHash(d->trusted, key); 122 iTrustEntry *trust = value_StringHash(d->trusted, key);
116 if (trust) { 123 if (trust) {
117 /* We already have it, check if it matches the one we trust for this domain (if it's 124 /* We already have it, check if it matches the one we trust for this domain (if it's
@@ -120,7 +127,9 @@ iBool checkTrust_GmCerts(iGmCerts *d, iRangecc domain, const iTlsCertificate *ce
120 initCurrent_Time(&now); 127 initCurrent_Time(&now);
121 if (secondsSince_Time(&trust->validUntil, &now) > 0) { 128 if (secondsSince_Time(&trust->validUntil, &now) > 0) {
122 /* Trusted cert is still valid. */ 129 /* Trusted cert is still valid. */
123 return cmp_Block(fingerprint, &trust->fingerprint) == 0; 130 const iBool isTrusted = cmp_Block(fingerprint, &trust->fingerprint) == 0;
131 unlock_Mutex(&d->mtx);
132 return isTrusted;
124 } 133 }
125 /* Update the trusted cert. */ 134 /* Update the trusted cert. */
126 init_Time(&trust->validUntil, &until); 135 init_Time(&trust->validUntil, &until);
@@ -130,5 +139,6 @@ iBool checkTrust_GmCerts(iGmCerts *d, iRangecc domain, const iTlsCertificate *ce
130 insert_StringHash(d->trusted, key, iClob(new_TrustEntry(fingerprint, &until))); 139 insert_StringHash(d->trusted, key, iClob(new_TrustEntry(fingerprint, &until)));
131 } 140 }
132 save_GmCerts_(d); 141 save_GmCerts_(d);
142 unlock_Mutex(&d->mtx);
133 return iTrue; 143 return iTrue;
134} 144}
diff --git a/src/gmrequest.c b/src/gmrequest.c
index dc08d23b..c0697f49 100644
--- a/src/gmrequest.c
+++ b/src/gmrequest.c
@@ -98,6 +98,25 @@ static void restartTimeout_GmRequest_(iGmRequest *d) {
98 d->timeoutId = SDL_AddTimer(BODY_TIMEOUT, timedOutWhileReceivingBody_GmRequest_, d); 98 d->timeoutId = SDL_AddTimer(BODY_TIMEOUT, timedOutWhileReceivingBody_GmRequest_, d);
99} 99}
100 100
101static void checkServerCertificate_GmRequest_(iGmRequest *d) {
102 const iTlsCertificate *cert = serverCertificate_TlsRequest(d->req);
103 d->certFlags = 0;
104 if (cert) {
105 iGmCerts * certDb = certs_App();
106 const iRangecc domain = urlHost_String(&d->url);
107 d->certFlags |= available_GmRequestCertFlag;
108 if (!isExpired_TlsCertificate(cert)) {
109 d->certFlags |= timeVerified_GmRequestCertFlag;
110 }
111 if (verifyDomain_TlsCertificate(cert, domain)) {
112 d->certFlags |= domainVerified_GmRequestCertFlag;
113 }
114 if (checkTrust_GmCerts(certDb, domain, cert)) {
115 d->certFlags |= trusted_GmRequestCertFlag;
116 }
117 }
118}
119
101static void readIncoming_GmRequest_(iAnyObject *obj) { 120static void readIncoming_GmRequest_(iAnyObject *obj) {
102 iGmRequest *d = (iGmRequest *) obj; 121 iGmRequest *d = (iGmRequest *) obj;
103 iBool notifyUpdate = iFalse; 122 iBool notifyUpdate = iFalse;
@@ -136,6 +155,7 @@ static void readIncoming_GmRequest_(iAnyObject *obj) {
136 } 155 }
137 d->code = code; 156 d->code = code;
138 d->state = receivingBody_GmRequestState; 157 d->state = receivingBody_GmRequestState;
158 checkServerCertificate_GmRequest_(d);
139 notifyUpdate = iTrue; 159 notifyUpdate = iTrue;
140 /* Start a timeout for the remainder of the response, in case the connection 160 /* Start a timeout for the remainder of the response, in case the connection
141 remains open. */ 161 remains open. */
@@ -168,23 +188,7 @@ static void requestFinished_GmRequest_(iAnyObject *obj) {
168 SDL_RemoveTimer(d->timeoutId); 188 SDL_RemoveTimer(d->timeoutId);
169 d->timeoutId = 0; 189 d->timeoutId = 0;
170 d->state = finished_GmRequestState; 190 d->state = finished_GmRequestState;
171 d->certFlags = 0; 191 checkServerCertificate_GmRequest_(d);
172 /* Check the server certificate. */ {
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 192#if 0
189 printf("Server certificate:\n%s\n", cstrLocal_String(pem_TlsCertificate(cert))); 193 printf("Server certificate:\n%s\n", cstrLocal_String(pem_TlsCertificate(cert)));
190 iBlock *sha = fingerprint_TlsCertificate(cert); 194 iBlock *sha = fingerprint_TlsCertificate(cert);
@@ -205,7 +209,6 @@ static void requestFinished_GmRequest_(iAnyObject *obj) {
205 } 209 }
206 fflush(stdout); 210 fflush(stdout);
207#endif 211#endif
208 }
209 unlock_Mutex(&d->mutex); 212 unlock_Mutex(&d->mutex);
210 iNotifyAudience(d, finished, GmRequestFinished); 213 iNotifyAudience(d, finished, GmRequestFinished);
211} 214}
@@ -218,6 +221,7 @@ void submit_GmRequest(iGmRequest *d) {
218 d->code = none_GmStatusCode; 221 d->code = none_GmStatusCode;
219 clear_String(&d->header); 222 clear_String(&d->header);
220 clear_Block(&d->body); 223 clear_Block(&d->body);
224 d->certFlags = 0;
221 iUrl url; 225 iUrl url;
222 init_Url(&url, &d->url); 226 init_Url(&url, &d->url);
223 if (equalCase_Rangecc(&url.protocol, "file")) { 227 if (equalCase_Rangecc(&url.protocol, "file")) {