💾 Archived View for gemini.rmf-dev.com › repo › Vaati › Vgmi › files › 54c74ef79e5821ec45aee69ae78f0… captured on 2023-12-28 at 15:45:15. 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 };

39

40 int secure_initialized = 0;

41

42 static const char *_tls_error(struct tls *ctx) {

43 const char *str = tls_error(ctx);

44 return str ? str : "Success";

45 }

46

47 static const char *_tls_config_error(struct tls_config *config) {

48 const char *str = tls_config_error(config);

49 return str ? str : "Success";

50 }

51

52 int secure_init(struct secure *secure, const char *hostname) {

53

54 if (!secure_initialized) {

55 if (tls_init()) {

56 STRLCPY(error_tls, strerror(errno));

57 return ERROR_TLS_FAILURE;

58 }

59 secure_initialized = 1;

60 }

61

62 if (!secure->ctx) {

63 secure->ctx = tls_client();

64 if (!secure->ctx) {

65 return ERROR_MEMORY_FAILURE;

66 }

67 }

68

69 if (!secure->config) {

70 secure->config = tls_config_new();

71 if (!secure->config) {

72 return ERROR_MEMORY_FAILURE;

73 }

74

75 tls_config_insecure_noverifycert(secure->config);

76 if (tls_configure(secure->ctx, secure->config)) {

77 STRLCPY(error_tls, _tls_config_error(secure->config));

78 return ERROR_TLS_FAILURE;

79 }

80

81 if (hostname) {

82 char cert_path[1024], key_path[1024];

83 char cert[4096], key[4096];

84 size_t cert_len, key_len;

85

86 int ret = certificate_getpath(hostname,

87 V(cert_path), V(key_path));

88 /* TODO: handle errors properly */

89 if (ret < 0) return 0;

90 if (storage_read(cert_path, V(cert), &cert_len))

91 return 0;

92 if (storage_read(key_path, V(key), &key_len))

93 return 0;

94 tls_config_set_keypair_mem(secure->config,

95 (unsigned char*)cert, cert_len,

96 (unsigned char*)key, key_len);

97 }

98 }

99

100 return 0;

101 }

102

103 struct secure *secure_new() {

104 struct secure *secure = calloc(1, sizeof(struct secure));

105 return secure;

106 }

107

108 int secure_connect(struct secure *secure, struct request request) {

109

110 int ret, sockfd;

111 struct sockaddr *addr;

112

113 if ((ret = secure_init(secure, request.name))) return ret;

114

115 sockfd = socket(AF_INET, SOCK_STREAM, 0);

116 if (sockfd == -1) return ERROR_SOCKET_CREATION;

117

118 addr = request.addr;

119 ret = -1;

120 switch (addr->sa_family) {

121 case AF_INET:

122 ((struct sockaddr_in*)addr)->sin_port = htons(request.port);

123 ret = connect(sockfd, addr, sizeof(struct sockaddr_in));

124 break;

125 case AF_INET6:

126 ((struct sockaddr_in6*)addr)->sin6_port = request.port;

127 ret = connect(sockfd, addr, sizeof(struct sockaddr_in6));

128 break;

129 }

130 if (ret) {

131 ret = ERROR_SOCKET_CONNECTION;

132 goto error;

133 }

134

135 if (tls_connect_socket(secure->ctx, sockfd, request.name)) {

136 ret = ERROR_TLS_FAILURE;

137 STRLCPY(error_tls, _tls_error(secure->ctx));

138 goto error;

139 }

140

141 if (tls_handshake(secure->ctx)) {

142 ret = ERROR_TLS_FAILURE;

143 STRLCPY(error_tls, _tls_error(secure->ctx));

144 goto error;

145 }

146

147 {

148 const char *hash = tls_peer_cert_hash(secure->ctx);

149 time_t start = tls_peer_cert_notbefore(secure->ctx);

150 time_t end = tls_peer_cert_notafter(secure->ctx);

151 ret = known_hosts_verify(request.name, hash, start, end);

152 if (ret) goto error;

153 }

154

155 return 0;

156 error:

157 close(sockfd);

158 return ret;

159 }

160

161 int secure_send(struct secure *secure, const char *data, size_t len) {

162 if (tls_write(secure->ctx, data, len) == (ssize_t)len) return 0;

163 STRLCPY(error_tls, _tls_error(secure->ctx));

164 return ERROR_TLS_FAILURE;

165 }

166

167 int secure_read(struct secure *secure, char **data, size_t *length) {

168

169 const size_t pad = 16; /* pad the end with null-bytes in case the data

170 ends with an incomplete unicode character */

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 + pad);

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 memset(&ptr[len], 0, pad);

204 *length = len;

205 if (readonly(ptr, *length, data)) return ERROR_ERRNO;

206 free(ptr);

207 return 0;

208 }

209

210 int secure_free(struct secure *secure) {

211 tls_config_free(secure->config);

212 tls_free(secure->ctx);

213 free(secure);

214 return 0;

215 }

216