💾 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

View Raw

More Information

-=-=-=-=-=-=-

Go Back

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