💾 Archived View for gemini.rmf-dev.com › repo › Vaati › Vgmi › files › 7ecb2ac1e338ab2b72fa0505a0563… captured on 2024-02-05 at 10:02:53. Gemini links have been rewritten to link to archived content
-=-=-=-=-=-=-
0 /*
1 * ISC License
2 * Copyright (c) 2023 RMF <rawmonk@firemail.cc>
3 */
4 /* socket */
5 #include <arpa/inet.h>
6 #include <netdb.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <sys/socket.h>
11 #ifdef __FreeBSD__
12 #include <netinet/in.h>
13 #include "sandbox.h"
14 #define connect sandbox_connect
15 #endif
16 /* tls */
17 #include <tls.h>
18
19 #include <errno.h>
20 #include <unistd.h>
21
22 #include "macro.h"
23 #include "strlcpy.h"
24 #include "error.h"
25 #include "client.h"
26 #include "page.h"
27 #include "request.h"
28 #include "known_hosts.h"
29 #include "secure.h"
30 #include "certificate.h"
31 #include "storage.h"
32 #include "memory.h"
33 #include "config.h"
34
35 struct secure {
36 struct tls *ctx;
37 struct tls_config *config;
38 int socket;
39 };
40
41 int secure_initialized = 0;
42
43 static const char *_tls_error(struct tls *ctx) {
44 const char *str = tls_error(ctx);
45 return str ? str : "Success";
46 }
47
48 static const char *_tls_config_error(struct tls_config *config) {
49 const char *str = tls_config_error(config);
50 return str ? str : "Success";
51 }
52
53 int secure_init(struct secure *secure, const char *hostname) {
54
55 if (!secure_initialized) {
56 if (tls_init()) {
57 STRLCPY(error_tls, strerror(errno));
58 return ERROR_TLS_FAILURE;
59 }
60 secure_initialized = 1;
61 }
62
63 if (!secure->ctx) {
64 secure->ctx = tls_client();
65 if (!secure->ctx) {
66 return ERROR_MEMORY_FAILURE;
67 }
68 }
69
70 if (!secure->config) {
71 secure->config = tls_config_new();
72 if (!secure->config) {
73 return ERROR_MEMORY_FAILURE;
74 }
75
76 tls_config_insecure_noverifycert(secure->config);
77 if (tls_configure(secure->ctx, secure->config)) {
78 STRLCPY(error_tls, _tls_config_error(secure->config));
79 return ERROR_TLS_FAILURE;
80 }
81
82 if (hostname) {
83 char cert_path[1024], key_path[1024];
84 char cert[4096], key[4096];
85 size_t cert_len, key_len;
86
87 int ret = certificate_getpath(hostname,
88 V(cert_path), V(key_path));
89 /* TODO: handle errors properly */
90 if (ret < 0) return 0;
91 if (storage_read(cert_path, V(cert), &cert_len))
92 return 0;
93 if (storage_read(key_path, V(key), &key_len))
94 return 0;
95 tls_config_set_keypair_mem(secure->config,
96 (unsigned char*)cert, cert_len,
97 (unsigned char*)key, key_len);
98 }
99 }
100
101 return 0;
102 }
103
104 struct secure *secure_new(void) {
105 struct secure *secure = calloc(1, sizeof(struct secure));
106 return secure;
107 }
108
109 int secure_connect(struct secure *secure, struct request request) {
110
111 int ret, sockfd;
112 struct sockaddr *addr;
113
114 if ((ret = secure_init(secure, request.name))) return ret;
115
116 sockfd = socket(AF_INET, SOCK_STREAM, 0);
117 if (sockfd == -1) return ERROR_SOCKET_CREATION;
118
119 addr = request.addr;
120 ret = -1;
121 switch (addr->sa_family) {
122 case AF_INET:
123 ((struct sockaddr_in*)addr)->sin_port = htons(request.port);
124 ret = connect(sockfd, addr, sizeof(struct sockaddr_in));
125 break;
126 case AF_INET6:
127 ((struct sockaddr_in6*)addr)->sin6_port = request.port;
128 ret = connect(sockfd, addr, sizeof(struct sockaddr_in6));
129 break;
130 }
131 if (ret) {
132 ret = ERROR_SOCKET_CONNECTION;
133 goto error;
134 }
135
136 if (tls_connect_socket(secure->ctx, sockfd, request.name)) {
137 ret = ERROR_TLS_FAILURE;
138 STRLCPY(error_tls, _tls_error(secure->ctx));
139 goto error;
140 }
141
142 if (tls_handshake(secure->ctx)) {
143 ret = ERROR_TLS_FAILURE;
144 STRLCPY(error_tls, _tls_error(secure->ctx));
145 goto error;
146 }
147
148 {
149 const char *hash = tls_peer_cert_hash(secure->ctx);
150 time_t start = tls_peer_cert_notbefore(secure->ctx);
151 time_t end = tls_peer_cert_notafter(secure->ctx);
152 ret = known_hosts_verify(request.name, hash, start, end);
153 if (ret) goto error;
154 }
155
156 secure->socket = sockfd;
157 return 0;
158 error:
159 close(sockfd);
160 return ret;
161 }
162
163 int secure_send(struct secure *secure, const char *data, size_t len) {
164 if (tls_write(secure->ctx, data, len) == (ssize_t)len) return 0;
165 STRLCPY(error_tls, _tls_error(secure->ctx));
166 return ERROR_TLS_FAILURE;
167 }
168
169 int secure_read(struct secure *secure, char **data, size_t *length) {
170
171 char buf[1024], *ptr;
172 size_t len, allocated;
173 int i;
174
175 ptr = NULL;
176 i = len = allocated = 0;
177 while (len < config.maximumBodyLength) {
178 if (len + sizeof(buf) > allocated) {
179 char *tmp;
180 allocated += sizeof(buf);
181 tmp = realloc(ptr, allocated);
182 if (!tmp) {
183 free(ptr);
184 return ERROR_MEMORY_FAILURE;
185 }
186 ptr = tmp;
187 }
188 i = tls_read(secure->ctx, buf, sizeof(buf));
189 if (i == TLS_WANT_POLLIN) continue;
190 if (i < 1) break;
191 memcpy(&ptr[len], buf, i);
192 len += i;
193 }
194 if (len >= config.maximumBodyLength) {
195 free(ptr);
196 return ERROR_RESPONSE_TOO_LARGE;
197 }
198 if (i < 0) {
199 free(ptr);
200 STRLCPY(error_tls, _tls_error(secure->ctx));
201 return ERROR_TLS_FAILURE;
202 }
203 *length = len;
204 if (readonly(ptr, *length, data)) return ERROR_ERRNO;
205 free(ptr);
206 return 0;
207 }
208
209 int secure_free(struct secure *secure) {
210 if (secure->ctx) {
211 close(secure->socket);
212 tls_close(secure->ctx);
213 }
214 tls_config_free(secure->config);
215 tls_free(secure->ctx);
216 free(secure);
217 return 0;
218 }
219