forked from uNetworking/uSockets
-
Notifications
You must be signed in to change notification settings - Fork 0
/
peer_verify_test.c
330 lines (251 loc) · 10.7 KB
/
peer_verify_test.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
/* This example, or test, is a moron test where the library is being hammered in all the possible ways randomly over time */
#include <libusockets.h>
const int SSL = 1;
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdbool.h>
int port;
int opened_connections, closed_connections, operations_done;
struct us_socket_context_t *server_context, *client_context;
struct us_listen_socket_t *listen_socket;
char client_msg[] = "Hello from client";
char server_msg[] = "Hello from server";
// also make sure to have socket ext data
// and context ext data
// and loop ext data
bool client_received_data;
bool server_received_data;
struct socket_context {
char *backpressure;
int length;
};
void on_wakeup(struct us_loop_t *loop) {
// note: we expose internal functions to trigger a timeout sweep to find bugs
extern void us_internal_timer_sweep(struct us_loop_t * loop);
us_internal_timer_sweep(loop);
}
// maybe use thse to count spurious wakeups?
// that is, if we get tons of pre/post over and over without any events
// that would point towards 100% cpu usage kind of bugs
void on_pre(struct us_loop_t *loop) {
// printf("PRE\n");
}
void on_post(struct us_loop_t *loop) {
// check if we did perform_random_operation
}
int write_buffered(int SSL, struct us_socket_t *s, const char *data, int length) {
struct socket_context *ctx = (struct socket_context *)us_socket_ext(SSL, s);
int written = us_socket_write(SSL, s, data, length, 0);
if (written != length) {
char *new_buffer = (char *)malloc(ctx->length + length - written);
memcpy(new_buffer, ctx->backpressure, ctx->length);
memcpy(new_buffer + ctx->length, data + written, length - written);
free(ctx->backpressure);
ctx->backpressure = new_buffer;
ctx->length += length - written;
}
return written;
}
void write_backpressure(int SSL, struct us_socket_t *s) {
struct socket_context *ctx = (struct socket_context *)us_socket_ext(SSL, s);
/* Continue writing out our backpressure */
int written = us_socket_write(SSL, s, ctx->backpressure, ctx->length, 0);
if (written != ctx->length) {
char *new_buffer = (char *)malloc(ctx->length - written);
memcpy(new_buffer, ctx->backpressure, ctx->length - written);
free(ctx->backpressure);
ctx->backpressure = new_buffer;
ctx->length -= written;
} else {
free(ctx->backpressure);
ctx->length = 0;
}
}
struct us_socket_t *on_server_socket_writable(struct us_socket_t *s) {
printf("on_server_socket_writable\n");
write_backpressure(SSL, s);
/* Peer is not boring */
us_socket_timeout(SSL, s, 30);
return s;
}
struct us_socket_t *on_client_socket_writable(struct us_socket_t *s) {
printf("on_client_socket_writable\n");
write_backpressure(SSL, s);
/* Peer is not boring */
us_socket_timeout(SSL, s, 30);
return s;
}
struct us_socket_t *on_server_socket_close(struct us_socket_t *s, int code, void *reason) {
printf("on_server_socket_close\n");
us_listen_socket_close(SSL, listen_socket);
return s;
}
struct us_socket_t *on_client_socket_close(struct us_socket_t *s, int code, void *reason) {
printf("on_client_socket_close\n");
return s;
}
struct us_socket_t *on_server_socket_end(struct us_socket_t *s) {
return us_socket_close(SSL, s, 0, NULL);
}
struct us_socket_t *on_client_socket_end(struct us_socket_t *s) {
return us_socket_close(SSL, s, 0, NULL);
}
struct us_socket_t *on_server_socket_data(struct us_socket_t *s, char *data, int length) {
if (length == 0) {
printf("ERROR: Got data event with no data\n");
exit(-1);
}
/* Print the data we received */
printf("on_server_socket_data: received '%.*s'\n", length, data);
server_received_data = true;
write_buffered(SSL, s, server_msg, sizeof(server_msg));
return s;
}
struct us_socket_t *on_client_socket_data(struct us_socket_t *s, char *data, int length) {
if (length == 0) {
printf("ERROR: Got data event with no data\n");
exit(-1);
}
/* Print the data we received */
printf("on_client_socket_data: received '%.*s'\n", length, data);
client_received_data = true;
return us_socket_close(SSL, s, 0, NULL);
}
struct us_socket_t *on_server_socket_open(struct us_socket_t *s, int is_client, char *ip, int ip_length) {
printf("on_server_socket_open\n");
struct socket_context *ctx = (struct socket_context *)us_socket_ext(SSL, s);
ctx->backpressure = 0;
ctx->length = 0;
/* Start a timeout to close the socket if boring */
us_socket_timeout(SSL, s, 30);
printf("Client connected\n");
return s;
}
struct us_socket_t *on_client_socket_open(struct us_socket_t *s, int is_client, char *ip, int ip_length) {
printf("on_client_socket_open\n");
struct socket_context *ctx = (struct socket_context *)us_socket_ext(SSL, s);
ctx->backpressure = 0;
ctx->length = 0;
write_buffered(SSL, s, client_msg, sizeof(client_msg));
return s;
}
struct us_socket_t *on_client_socket_timeout(struct us_socket_t *s) {
return s;
}
struct us_socket_t *on_server_socket_timeout(struct us_socket_t *s) {
return s;
}
int expect_peer_verify(const char *test_name, bool expect_data_exchanged,
struct us_socket_context_options_t server_options,
struct us_socket_context_options_t client_options) {
printf("----------------------------------------\n"
"[[ %s ]]\n"
" server_key: %s\n"
" server_crt: %s\n"
" server_ca: %s\n"
" client_crt: %s\n"
" client_key: %s\n"
" client_ca: %s\n\n",
test_name,
server_options.key_file_name,
server_options.cert_file_name,
server_options.ca_file_name,
client_options.key_file_name,
client_options.cert_file_name,
client_options.ca_file_name);
srand(time(0));
server_received_data = false;
client_received_data = false;
struct us_loop_t *loop = us_create_loop(0, on_wakeup, on_pre, on_post, 0);
server_context = us_create_socket_context(SSL, loop, sizeof(struct socket_context), server_options);
us_socket_context_on_open(SSL, server_context, on_server_socket_open);
us_socket_context_on_data(SSL, server_context, on_server_socket_data);
us_socket_context_on_writable(SSL, server_context, on_server_socket_writable);
us_socket_context_on_close(SSL, server_context, on_server_socket_close);
us_socket_context_on_timeout(SSL, server_context, on_server_socket_timeout);
us_socket_context_on_end(SSL, server_context, on_server_socket_end);
port = 3000;
listen_socket = us_socket_context_listen(SSL, server_context, "127.0.0.1", port, 0, sizeof(struct socket_context));
while (!listen_socket) {
listen_socket = us_socket_context_listen(SSL, server_context, "127.0.0.1", ++port, 0, sizeof(struct socket_context));
}
printf("Server listening on 127.0.0.1:%d\n", port);
client_context = us_create_socket_context(SSL, loop, sizeof(struct socket_context), client_options);
us_socket_context_on_open(SSL, client_context, on_client_socket_open);
us_socket_context_on_data(SSL, client_context, on_client_socket_data);
us_socket_context_on_writable(SSL, client_context, on_client_socket_writable);
us_socket_context_on_close(SSL, client_context, on_client_socket_close);
us_socket_context_on_timeout(SSL, client_context, on_client_socket_timeout);
us_socket_context_on_end(SSL, client_context, on_client_socket_end);
us_socket_context_connect(SSL, client_context, "127.0.0.1", port, NULL, 0, sizeof(struct socket_context));
us_loop_run(loop);
us_socket_context_free(SSL, server_context);
us_socket_context_free(SSL, client_context);
us_loop_free(loop);
bool data_exchanged = server_received_data && client_received_data;
if (!!expect_data_exchanged != !!data_exchanged) {
fprintf(stderr, "\n~ ERROR: expected data_echanged == %s, got %s\n\n",
(expect_data_exchanged ? "true" : "false"),
(data_exchanged ? "true" : "false"));
exit(1);
}
printf("[[ OK ]]\n\n");
return 0;
}
int main() {
expect_peer_verify("trusted client ca", true,
(struct us_socket_context_options_t){
.key_file_name = ".certs/valid_server_key.pem",
.cert_file_name = ".certs/valid_server_crt.pem",
.ca_file_name = ".certs/valid_ca_crt.pem"
},
(struct us_socket_context_options_t){
.key_file_name = ".certs/valid_client_key.pem",
.cert_file_name = ".certs/valid_client_crt.pem",
.ca_file_name = ".certs/valid_ca_crt.pem"
});
expect_peer_verify("untrusted client ca", false,
(struct us_socket_context_options_t){
.key_file_name = ".certs/valid_server_key.pem",
.cert_file_name = ".certs/valid_server_crt.pem",
.ca_file_name = ".certs/valid_ca_crt.pem"
},
(struct us_socket_context_options_t){
.key_file_name = ".certs/invalid_client_key.pem",
.cert_file_name = ".certs/invalid_client_crt.pem",
.ca_file_name = ".certs/valid_ca_crt.pem"
});
expect_peer_verify("trusted selfsigned client", true,
(struct us_socket_context_options_t){
.key_file_name = ".certs/valid_server_key.pem",
.cert_file_name = ".certs/valid_server_crt.pem",
.ca_file_name = ".certs/selfsigned_client_crt.pem"
},
(struct us_socket_context_options_t){
.key_file_name = ".certs/selfsigned_client_key.pem",
.cert_file_name = ".certs/selfsigned_client_crt.pem",
.ca_file_name = ".certs/valid_ca_crt.pem"
});
expect_peer_verify("untrusted selfsigned client", false,
(struct us_socket_context_options_t){
.key_file_name = ".certs/valid_server_key.pem",
.cert_file_name = ".certs/valid_server_crt.pem",
.ca_file_name = ".certs/valid_ca_crt.pem"
},
(struct us_socket_context_options_t){
.key_file_name = ".certs/selfsigned_client_key.pem",
.cert_file_name = ".certs/selfsigned_client_crt.pem",
.ca_file_name = ".certs/valid_ca_crt.pem"
});
expect_peer_verify("peer verify disabled", true,
(struct us_socket_context_options_t){
.key_file_name = ".certs/valid_server_key.pem",
.cert_file_name = ".certs/valid_server_crt.pem"
},
(struct us_socket_context_options_t){
.key_file_name = ".certs/valid_client_key.pem",
.cert_file_name = ".certs/valid_client_crt.pem"
});
}