diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-08-03 09:26:29 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-08-03 09:26:29 +0300 |
commit | 922ad3220909b7314ca629949b44d7d3aa0336b2 (patch) | |
tree | 7e049981dd15e896d10d44b443228f00425b1a6f | |
parent | e4681eca785d1b090da2d26dc2a0e32abf0217b9 (diff) |
Working on server certificates
-rw-r--r-- | CMakeLists.txt | 3 | ||||
-rw-r--r-- | src/app.c | 4 | ||||
-rw-r--r-- | src/app.h | 4 | ||||
-rw-r--r-- | src/gemini.h | 43 | ||||
-rw-r--r-- | src/gmcerts.c | 15 | ||||
-rw-r--r-- | src/gmcerts.h | 6 | ||||
-rw-r--r-- | src/gmrequest.c | 6 | ||||
-rw-r--r-- | src/gmrequest.h | 7 | ||||
-rw-r--r-- | src/gmutil.h | 39 | ||||
-rw-r--r-- | src/ui/documentwidget.c | 15 |
10 files changed, 82 insertions, 60 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index de97bf0a..c6a8c666 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
@@ -41,7 +41,8 @@ set (SOURCES | |||
41 | src/main.c | 41 | src/main.c |
42 | src/app.c | 42 | src/app.c |
43 | src/app.h | 43 | src/app.h |
44 | src/gemini.h | 44 | src/gmcerts.c |
45 | src/gmcerts.h | ||
45 | src/gmdocument.c | 46 | src/gmdocument.c |
46 | src/gmdocument.h | 47 | src/gmdocument.h |
47 | src/gmrequest.c | 48 | src/gmrequest.c |
@@ -1,5 +1,6 @@ | |||
1 | #include "app.h" | 1 | #include "app.h" |
2 | #include "embedded.h" | 2 | #include "embedded.h" |
3 | #include "gmcerts.h" | ||
3 | #include "history.h" | 4 | #include "history.h" |
4 | #include "ui/command.h" | 5 | #include "ui/command.h" |
5 | #include "ui/window.h" | 6 | #include "ui/window.h" |
@@ -51,6 +52,7 @@ struct Impl_App { | |||
51 | iWindow * window; | 52 | iWindow * window; |
52 | iSortedArray tickers; | 53 | iSortedArray tickers; |
53 | iBool pendingRefresh; | 54 | iBool pendingRefresh; |
55 | iGmCerts * certs; | ||
54 | iHistory * history; | 56 | iHistory * history; |
55 | /* Preferences: */ | 57 | /* Preferences: */ |
56 | iBool retainWindowSize; | 58 | iBool retainWindowSize; |
@@ -144,6 +146,7 @@ static void init_App_(iApp *d, int argc, char **argv) { | |||
144 | d->window = NULL; | 146 | d->window = NULL; |
145 | d->retainWindowSize = iTrue; | 147 | d->retainWindowSize = iTrue; |
146 | d->pendingRefresh = iFalse; | 148 | d->pendingRefresh = iFalse; |
149 | d->certs = new_GmCerts(dataDir_App_); | ||
147 | d->history = new_History(); | 150 | d->history = new_History(); |
148 | loadPrefs_App_(d); | 151 | loadPrefs_App_(d); |
149 | load_History(d->history, dataDir_App_); | 152 | load_History(d->history, dataDir_App_); |
@@ -165,6 +168,7 @@ static void deinit_App(iApp *d) { | |||
165 | savePrefs_App_(d); | 168 | savePrefs_App_(d); |
166 | save_History(d->history, dataDir_App_); | 169 | save_History(d->history, dataDir_App_); |
167 | delete_History(d->history); | 170 | delete_History(d->history); |
171 | delete_GmCerts(d->certs); | ||
168 | deinit_SortedArray(&d->tickers); | 172 | deinit_SortedArray(&d->tickers); |
169 | delete_Window(d->window); | 173 | delete_Window(d->window); |
170 | d->window = NULL; | 174 | d->window = NULL; |
@@ -5,8 +5,9 @@ | |||
5 | #include <the_Foundation/string.h> | 5 | #include <the_Foundation/string.h> |
6 | #include <the_Foundation/time.h> | 6 | #include <the_Foundation/time.h> |
7 | 7 | ||
8 | iDeclareType(Window) | 8 | iDeclareType(GmCerts) |
9 | iDeclareType(History) | 9 | iDeclareType(History) |
10 | iDeclareType(Window) | ||
10 | 11 | ||
11 | enum iAppEventMode { | 12 | enum iAppEventMode { |
12 | waitForNewEvents_AppEventMode, | 13 | waitForNewEvents_AppEventMode, |
@@ -25,6 +26,7 @@ void processEvents_App (enum iAppEventMode mode); | |||
25 | iBool handleCommand_App (const char *cmd); | 26 | iBool handleCommand_App (const char *cmd); |
26 | void refresh_App (void); | 27 | void refresh_App (void); |
27 | 28 | ||
29 | iGmCerts * certs_App (void); | ||
28 | const iHistory *history_App (void); | 30 | const iHistory *history_App (void); |
29 | 31 | ||
30 | iAny * findWidget_App (const char *id); | 32 | iAny * findWidget_App (const char *id); |
diff --git a/src/gemini.h b/src/gemini.h deleted file mode 100644 index 564de65b..00000000 --- a/src/gemini.h +++ /dev/null | |||
@@ -1,43 +0,0 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include <the_Foundation/string.h> | ||
4 | |||
5 | /* Response status codes. */ | ||
6 | enum iGmStatusCode { | ||
7 | clientSide_GmStatusCode = -100, /* clientside status codes */ | ||
8 | invalidRedirect_GmStatusCode, | ||
9 | invalidHeader_GmStatusCode, | ||
10 | unsupportedMimeType_GmStatusCode, | ||
11 | failedToOpenFile_GmStatusCode, | ||
12 | unknownStatusCode_GmStatusCode, | ||
13 | none_GmStatusCode = 0, | ||
14 | input_GmStatusCode = 10, | ||
15 | sensitiveInput_GmStatusCode = 11, | ||
16 | success_GmStatusCode = 20, | ||
17 | redirectTemporary_GmStatusCode = 30, | ||
18 | redirectPermanent_GmStatusCode = 31, | ||
19 | temporaryFailure_GmStatusCode = 40, | ||
20 | serverUnavailable_GmStatusCode = 41, | ||
21 | cgiError_GmStatusCode = 42, | ||
22 | proxyError_GmStatusCode = 43, | ||
23 | slowDown_GmStatusCode = 44, | ||
24 | permanentFailure_GmStatusCode = 50, | ||
25 | notFound_GmStatusCode = 51, | ||
26 | gone_GmStatusCode = 52, | ||
27 | proxyRequestRefused_GmStatusCode = 53, | ||
28 | badRequest_GmStatusCode = 59, | ||
29 | clientCertificateRequired_GmStatusCode = 60, | ||
30 | certificateNotAuthorized_GmStatusCode = 61, | ||
31 | certificateNotValid_GmStatusCode = 62, | ||
32 | }; | ||
33 | |||
34 | iDeclareType(GmError) | ||
35 | |||
36 | struct Impl_GmError { | ||
37 | iChar icon; | ||
38 | const char *title; | ||
39 | const char *info; | ||
40 | }; | ||
41 | |||
42 | iBool isDefined_GmError (enum iGmStatusCode code); | ||
43 | const iGmError * get_GmError (enum iGmStatusCode code); | ||
diff --git a/src/gmcerts.c b/src/gmcerts.c new file mode 100644 index 00000000..cb4d8477 --- /dev/null +++ b/src/gmcerts.c | |||
@@ -0,0 +1,15 @@ | |||
1 | #include "gmcerts.h" | ||
2 | |||
3 | struct Impl_GmCerts { | ||
4 | iString saveDir; | ||
5 | }; | ||
6 | |||
7 | iDefineTypeConstructionArgs(GmCerts, (const char *saveDir), saveDir) | ||
8 | |||
9 | void init_GmCerts(iGmCerts *d, const char *saveDir) { | ||
10 | initCStr_String(&d->saveDir, saveDir); | ||
11 | } | ||
12 | |||
13 | void deinit_GmCerts(iGmCerts *d) { | ||
14 | deinit_String(&d->saveDir); | ||
15 | } | ||
diff --git a/src/gmcerts.h b/src/gmcerts.h new file mode 100644 index 00000000..1990463c --- /dev/null +++ b/src/gmcerts.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include <the_Foundation/tlsrequest.h> | ||
4 | |||
5 | iDeclareType(GmCerts) | ||
6 | iDeclareTypeConstructionArgs(GmCerts, const char *saveDir) | ||
diff --git a/src/gmrequest.c b/src/gmrequest.c index f43e4220..32b386b2 100644 --- a/src/gmrequest.c +++ b/src/gmrequest.c | |||
@@ -20,6 +20,7 @@ struct Impl_GmRequest { | |||
20 | iObject object; | 20 | iObject object; |
21 | iMutex mutex; | 21 | iMutex mutex; |
22 | enum iGmRequestState state; | 22 | enum iGmRequestState state; |
23 | enum iGmRequestCertification certState; | ||
23 | iString url; | 24 | iString url; |
24 | iTlsRequest *req; | 25 | iTlsRequest *req; |
25 | enum iGmStatusCode code; | 26 | enum iGmStatusCode code; |
@@ -37,6 +38,7 @@ iDefineAudienceGetter(GmRequest, finished) | |||
37 | void init_GmRequest(iGmRequest *d) { | 38 | void init_GmRequest(iGmRequest *d) { |
38 | init_Mutex(&d->mutex); | 39 | init_Mutex(&d->mutex); |
39 | d->state = initialized_GmRequestState; | 40 | d->state = initialized_GmRequestState; |
41 | d->certState = notApplicable_GmRequestCertification; | ||
40 | init_String(&d->url); | 42 | init_String(&d->url); |
41 | d->req = NULL; | 43 | d->req = NULL; |
42 | d->code = none_GmStatusCode; | 44 | d->code = none_GmStatusCode; |
@@ -166,6 +168,7 @@ static void requestFinished_GmRequest_(iAnyObject *obj) { | |||
166 | d->state = finished_GmRequestState; | 168 | d->state = finished_GmRequestState; |
167 | #if 1 | 169 | #if 1 |
168 | /* Check the server certificate. */ { | 170 | /* Check the server certificate. */ { |
171 | d->certState = invalid_GmRequestCertification; /* check trust */ | ||
169 | const iTlsCertificate *cert = serverCertificate_TlsRequest(d->req); | 172 | const iTlsCertificate *cert = serverCertificate_TlsRequest(d->req); |
170 | printf("Server certificate:\n%s\n", cstrLocal_String(pem_TlsCertificate(cert))); | 173 | printf("Server certificate:\n%s\n", cstrLocal_String(pem_TlsCertificate(cert))); |
171 | iBlock *sha = fingerprint_TlsCertificate(cert); | 174 | iBlock *sha = fingerprint_TlsCertificate(cert); |
@@ -208,6 +211,7 @@ void submit_GmRequest(iGmRequest *d) { | |||
208 | /* TODO: Check supported file types: images, audio */ | 211 | /* TODO: Check supported file types: images, audio */ |
209 | /* TODO: Detect text files based on contents? E.g., is the content valid UTF-8. */ | 212 | /* TODO: Detect text files based on contents? E.g., is the content valid UTF-8. */ |
210 | d->code = success_GmStatusCode; | 213 | d->code = success_GmStatusCode; |
214 | d->certState = notApplicable_GmRequestCertification; | ||
211 | if (endsWithCase_String(path, ".gmi")) { | 215 | if (endsWithCase_String(path, ".gmi")) { |
212 | setCStr_String(&d->header, "text/gemini; charset=utf-8"); | 216 | setCStr_String(&d->header, "text/gemini; charset=utf-8"); |
213 | } | 217 | } |
@@ -235,11 +239,13 @@ void submit_GmRequest(iGmRequest *d) { | |||
235 | } | 239 | } |
236 | iRelease(f); | 240 | iRelease(f); |
237 | d->state = finished_GmRequestState; | 241 | d->state = finished_GmRequestState; |
242 | d->certState = notApplicable_GmRequestCertification; | ||
238 | iNotifyAudience(d, finished, GmRequestFinished); | 243 | iNotifyAudience(d, finished, GmRequestFinished); |
239 | return; | 244 | return; |
240 | } | 245 | } |
241 | else if (equalCase_Rangecc(&url.protocol, "data")) { | 246 | else if (equalCase_Rangecc(&url.protocol, "data")) { |
242 | d->code = success_GmStatusCode; | 247 | d->code = success_GmStatusCode; |
248 | d->certState = notApplicable_GmRequestCertification; | ||
243 | iString *src = collectNewCStr_String(url.protocol.start + 5); | 249 | iString *src = collectNewCStr_String(url.protocol.start + 5); |
244 | iRangecc header = { constBegin_String(src), constBegin_String(src) }; | 250 | iRangecc header = { constBegin_String(src), constBegin_String(src) }; |
245 | while (header.end < constEnd_String(src) && *header.end != ',') { | 251 | while (header.end < constEnd_String(src) && *header.end != ',') { |
diff --git a/src/gmrequest.h b/src/gmrequest.h index 270f976a..37f324eb 100644 --- a/src/gmrequest.h +++ b/src/gmrequest.h | |||
@@ -16,6 +16,13 @@ iDeclareAudienceGetter(GmRequest, finished) | |||
16 | void setUrl_GmRequest (iGmRequest *, const iString *url); | 16 | void setUrl_GmRequest (iGmRequest *, const iString *url); |
17 | void submit_GmRequest (iGmRequest *); | 17 | void submit_GmRequest (iGmRequest *); |
18 | 18 | ||
19 | enum iGmRequestCertification { | ||
20 | notApplicable_GmRequestCertification, | ||
21 | invalid_GmRequestCertification, | ||
22 | valid_GmRequestCertification, | ||
23 | expired_GmRequestCertification, | ||
24 | }; | ||
25 | |||
19 | iBool isFinished_GmRequest (const iGmRequest *); | 26 | iBool isFinished_GmRequest (const iGmRequest *); |
20 | enum iGmStatusCode status_GmRequest (const iGmRequest *); | 27 | enum iGmStatusCode status_GmRequest (const iGmRequest *); |
21 | const iString * meta_GmRequest (const iGmRequest *); | 28 | const iString * meta_GmRequest (const iGmRequest *); |
diff --git a/src/gmutil.h b/src/gmutil.h index 4a1fdee9..3342b262 100644 --- a/src/gmutil.h +++ b/src/gmutil.h | |||
@@ -3,8 +3,47 @@ | |||
3 | #include <the_Foundation/range.h> | 3 | #include <the_Foundation/range.h> |
4 | #include <the_Foundation/string.h> | 4 | #include <the_Foundation/string.h> |
5 | 5 | ||
6 | iDeclareType(GmError) | ||
6 | iDeclareType(Url) | 7 | iDeclareType(Url) |
7 | 8 | ||
9 | /* Response status codes. */ | ||
10 | enum iGmStatusCode { | ||
11 | clientSide_GmStatusCode = -100, /* clientside status codes */ | ||
12 | invalidRedirect_GmStatusCode, | ||
13 | invalidHeader_GmStatusCode, | ||
14 | unsupportedMimeType_GmStatusCode, | ||
15 | failedToOpenFile_GmStatusCode, | ||
16 | unknownStatusCode_GmStatusCode, | ||
17 | none_GmStatusCode = 0, | ||
18 | input_GmStatusCode = 10, | ||
19 | sensitiveInput_GmStatusCode = 11, | ||
20 | success_GmStatusCode = 20, | ||
21 | redirectTemporary_GmStatusCode = 30, | ||
22 | redirectPermanent_GmStatusCode = 31, | ||
23 | temporaryFailure_GmStatusCode = 40, | ||
24 | serverUnavailable_GmStatusCode = 41, | ||
25 | cgiError_GmStatusCode = 42, | ||
26 | proxyError_GmStatusCode = 43, | ||
27 | slowDown_GmStatusCode = 44, | ||
28 | permanentFailure_GmStatusCode = 50, | ||
29 | notFound_GmStatusCode = 51, | ||
30 | gone_GmStatusCode = 52, | ||
31 | proxyRequestRefused_GmStatusCode = 53, | ||
32 | badRequest_GmStatusCode = 59, | ||
33 | clientCertificateRequired_GmStatusCode = 60, | ||
34 | certificateNotAuthorized_GmStatusCode = 61, | ||
35 | certificateNotValid_GmStatusCode = 62, | ||
36 | }; | ||
37 | |||
38 | struct Impl_GmError { | ||
39 | iChar icon; | ||
40 | const char *title; | ||
41 | const char *info; | ||
42 | }; | ||
43 | |||
44 | iBool isDefined_GmError (enum iGmStatusCode code); | ||
45 | const iGmError * get_GmError (enum iGmStatusCode code); | ||
46 | |||
8 | struct Impl_Url { | 47 | struct Impl_Url { |
9 | iRangecc protocol; | 48 | iRangecc protocol; |
10 | iRangecc host; | 49 | iRangecc host; |
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index f8a2e330..954ded0c 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -145,21 +145,6 @@ void deinit_DocumentWidget(iDocumentWidget *d) { | |||
145 | SDL_FreeCursor(d->handCursor); | 145 | SDL_FreeCursor(d->handCursor); |
146 | } | 146 | } |
147 | 147 | ||
148 | #if 0 | ||
149 | static iString *cleanUrl_(const iString *url) { | ||
150 | iString *clean = copy_String(url); | ||
151 | if (startsWith_String(url, "//")) { | ||
152 | prependCStr_String(clean, "gemini:"); | ||
153 | } | ||
154 | else if (indexOfCStr_String(url, "://") == iInvalidPos && !startsWithCase_String(url, "gemini:") | ||
155 | && !startsWithCase_String(url, "data:")) { | ||
156 | /* Prepend default protocol. */ | ||
157 | prependCStr_String(clean, "gemini://"); | ||
158 | } | ||
159 | return clean; | ||
160 | } | ||
161 | #endif | ||
162 | |||
163 | static int documentWidth_DocumentWidget_(const iDocumentWidget *d) { | 148 | static int documentWidth_DocumentWidget_(const iDocumentWidget *d) { |
164 | const iWidget *w = constAs_Widget(d); | 149 | const iWidget *w = constAs_Widget(d); |
165 | const iRect bounds = bounds_Widget(w); | 150 | const iRect bounds = bounds_Widget(w); |