summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/regress/lib/libssl/unit/ssl_set_alpn_protos.c292
1 files changed, 291 insertions, 1 deletions
diff --git a/src/regress/lib/libssl/unit/ssl_set_alpn_protos.c b/src/regress/lib/libssl/unit/ssl_set_alpn_protos.c
index 87dd4d9e5a..6f3fcfbc2a 100644
--- a/src/regress/lib/libssl/unit/ssl_set_alpn_protos.c
+++ b/src/regress/lib/libssl/unit/ssl_set_alpn_protos.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssl_set_alpn_protos.c,v 1.2 2022/07/21 03:59:04 tb Exp $ */ 1/* $OpenBSD: ssl_set_alpn_protos.c,v 1.3 2024/06/28 14:50:37 tb Exp $ */
2/* 2/*
3 * Copyright (c) 2022 Theo Buehler <tb@openbsd.org> 3 * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
4 * 4 *
@@ -20,6 +20,21 @@
20 20
21#include <openssl/ssl.h> 21#include <openssl/ssl.h>
22 22
23static void
24hexdump(const unsigned char *buf, size_t len)
25{
26 size_t i;
27
28 if (buf == NULL) {
29 fprintf(stderr, "(null), len %zu\n", len);
30 return;
31 }
32 for (i = 1; i <= len; i++)
33 fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n");
34 if (len % 8)
35 fprintf(stderr, "\n");
36}
37
23struct alpn_test { 38struct alpn_test {
24 const char *description; 39 const char *description;
25 const uint8_t protocols[24]; 40 const uint8_t protocols[24];
@@ -186,6 +201,279 @@ test_ssl_set_alpn_protos_edge_cases(void)
186 return failed; 201 return failed;
187} 202}
188 203
204static const struct select_next_proto_test {
205 const unsigned char *server_list;
206 size_t server_list_len;
207 const unsigned char *client_list;
208 size_t client_list_len;
209 int want_ret;
210 const unsigned char *want_out;
211 unsigned char want_out_len; /* yes, unsigned char */
212} select_next_proto_tests[] = {
213 {
214 .server_list = "\x01" "a" "\x01" "b" "\x01" "c",
215 .server_list_len = 6,
216 .client_list = "\x01" "a",
217 .client_list_len = 2,
218 .want_ret = OPENSSL_NPN_NEGOTIATED,
219 .want_out = "a",
220 .want_out_len = 1,
221 },
222 {
223 .server_list = "\x01" "a" "\x01" "b" "\x01" "c",
224 .server_list_len = 6,
225 .client_list = "\x02" "aa" "\x01" "b" "\x01" "c",
226 .client_list_len = 7,
227 .want_ret = OPENSSL_NPN_NEGOTIATED,
228 .want_out = "b",
229 .want_out_len = 1,
230 },
231 {
232 /* Use server preference. */
233 .server_list = "\x01" "a" "\x01" "b" "\x01" "c",
234 .server_list_len = 6,
235 .client_list = "\x01" "c" "\x01" "b" "\x01" "a",
236 .client_list_len = 6,
237 .want_ret = OPENSSL_NPN_NEGOTIATED,
238 .want_out = "a",
239 .want_out_len = 1,
240 },
241 {
242 /* Again server preference wins. */
243 .server_list = "\x01" "a" "\x03" "bbb" "\x02" "cc",
244 .server_list_len = 9,
245 .client_list = "\x01" "z" "\x02" "cc" "\x03" "bbb",
246 .client_list_len = 9,
247 .want_ret = OPENSSL_NPN_NEGOTIATED,
248 .want_out = "bbb",
249 .want_out_len = 3,
250 },
251 {
252 /* No overlap fails with first client protocol. */
253 .server_list = "\x01" "a" "\x01" "b" "\x01" "c",
254 .server_list_len = 6,
255 .client_list = "\x01" "z" "\x01" "y",
256 .client_list_len = 4,
257 .want_ret = OPENSSL_NPN_NO_OVERLAP,
258 .want_out = "z",
259 .want_out_len = 1,
260 },
261 {
262 /*
263 * No server protocols is a misconfiguration, but should fail
264 * cleanly.
265 */
266 .server_list = "",
267 .server_list_len = 0,
268 .client_list = "\x01" "a" "\x01" "b" "\x01" "c",
269 .client_list_len = 6,
270 .want_out = "a",
271 .want_out_len = 1,
272 .want_ret = OPENSSL_NPN_NO_OVERLAP,
273 },
274 {
275 /*
276 * NULL server protocols is a programming error that fails
277 * cleanly.
278 */
279 .server_list = NULL,
280 .server_list_len = 0,
281 .client_list = "\x01" "a" "\x01" "b" "\x01" "c",
282 .client_list_len = 6,
283 .want_out = "a",
284 .want_out_len = 1,
285 .want_ret = OPENSSL_NPN_NO_OVERLAP,
286 },
287 {
288 /*
289 * Malformed server protocols is a misconfiguration, but it
290 * should fail cleanly.
291 */
292 .server_list = "\x00",
293 .server_list_len = 1,
294 .client_list = "\x01" "a" "\x01" "b" "\x01" "c",
295 .client_list_len = 6,
296 .want_out = "a",
297 .want_out_len = 1,
298 .want_ret = OPENSSL_NPN_NO_OVERLAP,
299 },
300 {
301 /*
302 * Malformed server protocols is a misconfiguration, but it
303 * should fail cleanly.
304 */
305 .server_list = "\x01" "a" "\x03" "bb",
306 .server_list_len = 5,
307 .client_list = "\x01" "a" "\x01" "b" "\x01" "c",
308 .client_list_len = 6,
309 .want_out = "a",
310 .want_out_len = 1,
311 .want_ret = OPENSSL_NPN_NO_OVERLAP,
312 },
313 {
314 /*
315 * Empty client protocols is not reachable from the ALPN
316 * callback. It fails cleanly with NULL protocol and 0 length.
317 */
318 .server_list = "\x01" "a",
319 .server_list_len = 2,
320 .client_list = "",
321 .client_list_len = 0,
322 .want_out = NULL,
323 .want_out_len = 0,
324 .want_ret = OPENSSL_NPN_NO_OVERLAP,
325 },
326 {
327 /*
328 * NULL client protocols is not reachable from the ALPN
329 * callback. It fails cleanly with NULL protocol and 0 length.
330 */
331 .server_list = "\x01" "a",
332 .server_list_len = 2,
333 .client_list = NULL,
334 .client_list_len = 0,
335 .want_out = NULL,
336 .want_out_len = 0,
337 .want_ret = OPENSSL_NPN_NO_OVERLAP,
338 },
339 {
340 /*
341 * Malformed client list fails cleanly with NULL protocol and
342 * 0 length.
343 */
344 .server_list = "\x01" "a",
345 .server_list_len = 2,
346 .client_list = "\x01" "a" "\x02" "bb" "\x03" "cc" "\x04" "ddd",
347 .client_list_len = 12,
348 .want_out = NULL,
349 .want_out_len = 0,
350 .want_ret = OPENSSL_NPN_NO_OVERLAP,
351 },
352 {
353 /*
354 * Malformed client list fails cleanly with NULL protocol and
355 * 0 length.
356 */
357 .server_list = "\x01" "a",
358 .server_list_len = 2,
359 .client_list = "\x01" "a" "\x02" "bb" "\x00" "\x03" "ddd",
360 .client_list_len = 10,
361 .want_out = NULL,
362 .want_out_len = 0,
363 .want_ret = OPENSSL_NPN_NO_OVERLAP,
364 },
365
366 /*
367 * Some non-toy examples.
368 */
369
370 {
371 .server_list = "\x08" "http/1.1" "\x06" "spdy/1",
372 .server_list_len = 16,
373 .client_list = "\x08" "http/2.0" "\x08" "http/1.1",
374 .client_list_len = 18,
375 .want_out = "http/1.1",
376 .want_out_len = 8,
377 .want_ret = OPENSSL_NPN_NEGOTIATED,
378 },
379 {
380 .server_list = "\x08" "http/2.0" "\x06" "spdy/1",
381 .server_list_len = 16,
382 .client_list = "\x08" "http/1.0" "\x08" "http/1.1",
383 .client_list_len = 18,
384 .want_out = "http/1.0",
385 .want_out_len = 8,
386 .want_ret = OPENSSL_NPN_NO_OVERLAP,
387 },
388 {
389 .server_list = "\x08" "http/1.1" "\x08" "http/1.0",
390 .server_list_len = 18,
391 .client_list = "\x08" "http/1.0" "\x08" "http/1.1",
392 .client_list_len = 18,
393 .want_out = "http/1.1",
394 .want_out_len = 8,
395 .want_ret = OPENSSL_NPN_NEGOTIATED,
396 },
397 {
398 /* Server malformed. */
399 .server_list = "\x08" "http/1.1" "\x07" "http/1.0",
400 .server_list_len = 18,
401 .client_list = "\x08" "http/1.0" "\x08" "http/1.1",
402 .client_list_len = 18,
403 .want_out = "http/1.0",
404 .want_out_len = 8,
405 .want_ret = OPENSSL_NPN_NO_OVERLAP,
406 },
407 {
408 /* Server malformed. */
409 .server_list = "\x07" "http/1.1" "\x08" "http/1.0",
410 .server_list_len = 18,
411 .client_list = "\x08" "http/1.0" "\x08" "http/1.1",
412 .client_list_len = 18,
413 .want_out = "http/1.0",
414 .want_out_len = 8,
415 .want_ret = OPENSSL_NPN_NO_OVERLAP,
416 },
417 {
418 /* Client has trailing bytes. */
419 .server_list = "\x08" "http/1.1" "\x08" "http/1.0",
420 .server_list_len = 18,
421 .client_list = "\x08" "http/1.0" "\x07" "http/1.1",
422 .client_list_len = 18,
423 .want_out = NULL,
424 .want_out_len = 0,
425 .want_ret = OPENSSL_NPN_NO_OVERLAP,
426 },
427};
428
429#define N_SELECT_NEXT_PROTO_TESTS \
430 (sizeof(select_next_proto_tests) / sizeof(select_next_proto_tests[0]))
431
432static int
433select_next_proto_testcase(const struct select_next_proto_test *test)
434{
435 unsigned char *out;
436 unsigned char out_len;
437 int ret;
438 int failed = 0;
439
440 ret = SSL_select_next_proto(&out, &out_len, test->server_list,
441 test->server_list_len, test->client_list, test->client_list_len);
442
443 if (ret != test->want_ret || out_len != test->want_out_len ||
444 (out == NULL && test->want_out != NULL) ||
445 (out != NULL && test->want_out == NULL) ||
446 (out != NULL && test->want_out != NULL &&
447 memcmp(out, test->want_out, out_len) != 0)) {
448 fprintf(stderr, "FAIL: ret: %u (want %u), out_len: %u (want %u)\n",
449 ret, test->want_ret, out_len, test->want_out_len);
450 fprintf(stderr, "\ngot:\n");
451 hexdump(out, out_len);
452 fprintf(stderr, "\nwant:\n");
453 hexdump(test->want_out, test->want_out_len);
454 fprintf(stderr, "\nserver:\n");
455 hexdump(test->server_list, test->server_list_len);
456 fprintf(stderr, "\nclient:\n");
457 hexdump(test->client_list, test->client_list_len);
458 fprintf(stderr, "\n");
459 failed = 1;
460 }
461
462 return failed;
463}
464
465static int
466test_ssl_select_next_proto(void)
467{
468 size_t i;
469 int failed = 0;
470
471 for (i = 0; i < N_SELECT_NEXT_PROTO_TESTS; i++)
472 failed |= select_next_proto_testcase(&select_next_proto_tests[i]);
473
474 return failed;
475}
476
189int 477int
190main(void) 478main(void)
191{ 479{
@@ -197,6 +485,8 @@ main(void)
197 485
198 failed |= test_ssl_set_alpn_protos_edge_cases(); 486 failed |= test_ssl_set_alpn_protos_edge_cases();
199 487
488 failed |= test_ssl_select_next_proto();
489
200 if (!failed) 490 if (!failed)
201 printf("PASS %s\n", __FILE__); 491 printf("PASS %s\n", __FILE__);
202 492