1 /* 	$OpenBSD: test_iterate.c,v 1.6 2018/07/16 03:09:59 djm Exp $ */
2 /*
3  * Regress test for hostfile.h hostkeys_foreach()
4  *
5  * Placed in the public domain
6  */
7 
8 #include "includes.h"
9 
10 #include <sys/types.h>
11 #include <sys/param.h>
12 #include <stdio.h>
13 #ifdef HAVE_STDINT_H
14 #include <stdint.h>
15 #endif
16 #include <stdlib.h>
17 #include <string.h>
18 
19 #include "../test_helper/test_helper.h"
20 
21 #include "sshkey.h"
22 #include "authfile.h"
23 #include "hostfile.h"
24 
25 struct expected {
26 	const char *key_file;		/* Path for key, NULL for none */
27 	int no_parse_status;		/* Expected status w/o key parsing */
28 	int no_parse_keytype;		/* Expected keytype w/o key parsing */
29 	int match_host_p;		/* Match 'prometheus.example.com' */
30 	int match_host_s;		/* Match 'sisyphus.example.com' */
31 	int match_ipv4;			/* Match '192.0.2.1' */
32 	int match_ipv6;			/* Match '2001:db8::1' */
33 	int match_flags;		/* Expected flags from match */
34 	struct hostkey_foreach_line l;	/* Expected line contents */
35 };
36 
37 struct cbctx {
38 	const struct expected *expected;
39 	size_t nexpected;
40 	size_t i;
41 	int flags;
42 	int match_host_p;
43 	int match_host_s;
44 	int match_ipv4;
45 	int match_ipv6;
46 };
47 
48 /*
49  * hostkeys_foreach() iterator callback that verifies the line passed
50  * against an array of expected entries.
51  */
52 static int
check(struct hostkey_foreach_line * l,void * _ctx)53 check(struct hostkey_foreach_line *l, void *_ctx)
54 {
55 	struct cbctx *ctx = (struct cbctx *)_ctx;
56 	const struct expected *expected;
57 	int parse_key = (ctx->flags & HKF_WANT_PARSE_KEY) != 0;
58 	const int matching = (ctx->flags & HKF_WANT_MATCH) != 0;
59 	u_int expected_status, expected_match;
60 	int expected_keytype, skip = 0;
61 
62 	test_subtest_info("entry %zu/%zu, file line %ld",
63 	    ctx->i + 1, ctx->nexpected, l->linenum);
64 
65 	for (;;) {
66 		ASSERT_SIZE_T_LT(ctx->i, ctx->nexpected);
67 		expected = ctx->expected + ctx->i++;
68 		/* If we are matching host/IP then skip entries that don't */
69 		if (!matching)
70 			break;
71 		if (ctx->match_host_p && expected->match_host_p)
72 			break;
73 		if (ctx->match_host_s && expected->match_host_s)
74 			break;
75 		if (ctx->match_ipv4 && expected->match_ipv4)
76 			break;
77 		if (ctx->match_ipv6 && expected->match_ipv6)
78 			break;
79 	}
80 	expected_status = (parse_key || expected->no_parse_status < 0) ?
81 	    expected->l.status : (u_int)expected->no_parse_status;
82 	expected_match = expected->l.match;
83 #define UPDATE_MATCH_STATUS(x) do { \
84 		if (ctx->x && expected->x) { \
85 			expected_match |= expected->x; \
86 			if (expected_status == HKF_STATUS_OK) \
87 				expected_status = HKF_STATUS_MATCHED; \
88 		} \
89 	} while (0)
90 	expected_keytype = (parse_key || expected->no_parse_keytype < 0) ?
91 	    expected->l.keytype : expected->no_parse_keytype;
92 
93 #ifndef OPENSSL_HAS_ECC
94 	if (expected->l.keytype == KEY_ECDSA ||
95 	    expected->no_parse_keytype == KEY_ECDSA)
96 		skip = 1;
97 #endif /* OPENSSL_HAS_ECC */
98 #ifndef WITH_OPENSSL
99 	if (expected->l.keytype == KEY_DSA ||
100 	    expected->no_parse_keytype == KEY_DSA ||
101 	    expected->l.keytype == KEY_RSA ||
102 	    expected->no_parse_keytype == KEY_RSA ||
103 	    expected->l.keytype == KEY_ECDSA ||
104 	    expected->no_parse_keytype == KEY_ECDSA)
105 		skip = 1;
106 #endif /* WITH_OPENSSL */
107 	if (skip) {
108 		expected_status = HKF_STATUS_INVALID;
109 		expected_keytype = KEY_UNSPEC;
110 		parse_key = 0;
111 	}
112 	UPDATE_MATCH_STATUS(match_host_p);
113 	UPDATE_MATCH_STATUS(match_host_s);
114 	UPDATE_MATCH_STATUS(match_ipv4);
115 	UPDATE_MATCH_STATUS(match_ipv6);
116 
117 	ASSERT_PTR_NE(l->path, NULL); /* Don't care about path */
118 	ASSERT_LONG_LONG_EQ(l->linenum, expected->l.linenum);
119 	ASSERT_U_INT_EQ(l->status, expected_status);
120 	ASSERT_U_INT_EQ(l->match, expected_match);
121 	/* Not all test entries contain fulltext */
122 	if (expected->l.line != NULL)
123 		ASSERT_STRING_EQ(l->line, expected->l.line);
124 	ASSERT_INT_EQ(l->marker, expected->l.marker);
125 	/* XXX we skip hashed hostnames for now; implement checking */
126 	if (expected->l.hosts != NULL)
127 		ASSERT_STRING_EQ(l->hosts, expected->l.hosts);
128 	/* Not all test entries contain raw keys */
129 	if (expected->l.rawkey != NULL)
130 		ASSERT_STRING_EQ(l->rawkey, expected->l.rawkey);
131 	/* XXX synthesise raw key for cases lacking and compare */
132 	ASSERT_INT_EQ(l->keytype, expected_keytype);
133 	if (parse_key) {
134 		if (expected->l.key == NULL)
135 			ASSERT_PTR_EQ(l->key, NULL);
136 		if (expected->l.key != NULL) {
137 			ASSERT_PTR_NE(l->key, NULL);
138 			ASSERT_INT_EQ(sshkey_equal(l->key, expected->l.key), 1);
139 		}
140 	}
141 	if (parse_key && !(l->comment == NULL && expected->l.comment == NULL))
142 		ASSERT_STRING_EQ(l->comment, expected->l.comment);
143 	return 0;
144 }
145 
146 /* Loads public keys for a set of expected results */
147 static void
prepare_expected(struct expected * expected,size_t n)148 prepare_expected(struct expected *expected, size_t n)
149 {
150 	size_t i;
151 
152 	for (i = 0; i < n; i++) {
153 		if (expected[i].key_file == NULL)
154 			continue;
155 #ifndef OPENSSL_HAS_ECC
156 		if (expected[i].l.keytype == KEY_ECDSA)
157 			continue;
158 #endif /* OPENSSL_HAS_ECC */
159 #ifndef WITH_OPENSSL
160 		switch (expected[i].l.keytype) {
161 		case KEY_RSA:
162 		case KEY_DSA:
163 		case KEY_ECDSA:
164 			continue;
165 		}
166 #endif /* WITH_OPENSSL */
167 		ASSERT_INT_EQ(sshkey_load_public(
168 		    test_data_file(expected[i].key_file), &expected[i].l.key,
169 		    NULL), 0);
170 	}
171 }
172 
173 static void
cleanup_expected(struct expected * expected,size_t n)174 cleanup_expected(struct expected *expected, size_t n)
175 {
176 	size_t i;
177 
178 	for (i = 0; i < n; i++) {
179 		sshkey_free(expected[i].l.key);
180 		expected[i].l.key = NULL;
181 	}
182 }
183 
184 struct expected expected_full[] = {
185 	{ NULL, -1, -1, 0, 0, 0, 0, -1, {
186 		NULL,				/* path, don't care */
187 		1,				/* line number */
188 		HKF_STATUS_COMMENT,		/* status */
189 		0,				/* match flags */
190 		"# Plain host keys, plain host names", /* full line, optional */
191 		MRK_NONE,			/* marker (CA / revoked) */
192 		NULL,				/* hosts text */
193 		NULL,				/* raw key, optional */
194 		KEY_UNSPEC,			/* key type */
195 		NULL,				/* deserialised key */
196 		NULL,				/* comment */
197 	} },
198 	{ "dsa_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
199 		NULL,
200 		2,
201 		HKF_STATUS_OK,
202 		0,
203 		NULL,
204 		MRK_NONE,
205 		"sisyphus.example.com",
206 		NULL,
207 		KEY_DSA,
208 		NULL,	/* filled at runtime */
209 		"DSA #1",
210 	} },
211 	{ "ecdsa_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
212 		NULL,
213 		3,
214 		HKF_STATUS_OK,
215 		0,
216 		NULL,
217 		MRK_NONE,
218 		"sisyphus.example.com",
219 		NULL,
220 		KEY_ECDSA,
221 		NULL,	/* filled at runtime */
222 		"ECDSA #1",
223 	} },
224 	{ "ed25519_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
225 		NULL,
226 		4,
227 		HKF_STATUS_OK,
228 		0,
229 		NULL,
230 		MRK_NONE,
231 		"sisyphus.example.com",
232 		NULL,
233 		KEY_ED25519,
234 		NULL,	/* filled at runtime */
235 		"ED25519 #1",
236 	} },
237 	{ "rsa_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
238 		NULL,
239 		5,
240 		HKF_STATUS_OK,
241 		0,
242 		NULL,
243 		MRK_NONE,
244 		"sisyphus.example.com",
245 		NULL,
246 		KEY_RSA,
247 		NULL,	/* filled at runtime */
248 		"RSA #1",
249 	} },
250 	{ NULL, -1, -1, 0, 0, 0, 0, -1, {
251 		NULL,
252 		6,
253 		HKF_STATUS_COMMENT,
254 		0,
255 		"",
256 		MRK_NONE,
257 		NULL,
258 		NULL,
259 		KEY_UNSPEC,
260 		NULL,
261 		NULL,
262 	} },
263 	{ NULL, -1, -1, 0, 0, 0, 0, -1, {
264 		NULL,
265 		7,
266 		HKF_STATUS_COMMENT,
267 		0,
268 		"# Plain host keys, hostnames + addresses",
269 		MRK_NONE,
270 		NULL,
271 		NULL,
272 		KEY_UNSPEC,
273 		NULL,
274 		NULL,
275 	} },
276 	{ "dsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
277 		NULL,
278 		8,
279 		HKF_STATUS_OK,
280 		0,
281 		NULL,
282 		MRK_NONE,
283 		"prometheus.example.com,192.0.2.1,2001:db8::1",
284 		NULL,
285 		KEY_DSA,
286 		NULL,	/* filled at runtime */
287 		"DSA #2",
288 	} },
289 	{ "ecdsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
290 		NULL,
291 		9,
292 		HKF_STATUS_OK,
293 		0,
294 		NULL,
295 		MRK_NONE,
296 		"prometheus.example.com,192.0.2.1,2001:db8::1",
297 		NULL,
298 		KEY_ECDSA,
299 		NULL,	/* filled at runtime */
300 		"ECDSA #2",
301 	} },
302 	{ "ed25519_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
303 		NULL,
304 		10,
305 		HKF_STATUS_OK,
306 		0,
307 		NULL,
308 		MRK_NONE,
309 		"prometheus.example.com,192.0.2.1,2001:db8::1",
310 		NULL,
311 		KEY_ED25519,
312 		NULL,	/* filled at runtime */
313 		"ED25519 #2",
314 	} },
315 	{ "rsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
316 		NULL,
317 		11,
318 		HKF_STATUS_OK,
319 		0,
320 		NULL,
321 		MRK_NONE,
322 		"prometheus.example.com,192.0.2.1,2001:db8::1",
323 		NULL,
324 		KEY_RSA,
325 		NULL,	/* filled at runtime */
326 		"RSA #2",
327 	} },
328 	{ NULL, -1, -1, 0, 0, 0, 0, -1, {
329 		NULL,
330 		12,
331 		HKF_STATUS_COMMENT,
332 		0,
333 		"",
334 		MRK_NONE,
335 		NULL,
336 		NULL,
337 		KEY_UNSPEC,
338 		NULL,
339 		NULL,
340 	} },
341 	{ NULL, -1, -1, 0, 0, 0, 0, -1, {
342 		NULL,
343 		13,
344 		HKF_STATUS_COMMENT,
345 		0,
346 		"# Some hosts with wildcard names / IPs",
347 		MRK_NONE,
348 		NULL,
349 		NULL,
350 		KEY_UNSPEC,
351 		NULL,
352 		NULL,
353 	} },
354 	{ "dsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
355 		NULL,
356 		14,
357 		HKF_STATUS_OK,
358 		0,
359 		NULL,
360 		MRK_NONE,
361 		"*.example.com,192.0.2.*,2001:*",
362 		NULL,
363 		KEY_DSA,
364 		NULL,	/* filled at runtime */
365 		"DSA #3",
366 	} },
367 	{ "ecdsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
368 		NULL,
369 		15,
370 		HKF_STATUS_OK,
371 		0,
372 		NULL,
373 		MRK_NONE,
374 		"*.example.com,192.0.2.*,2001:*",
375 		NULL,
376 		KEY_ECDSA,
377 		NULL,	/* filled at runtime */
378 		"ECDSA #3",
379 	} },
380 	{ "ed25519_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
381 		NULL,
382 		16,
383 		HKF_STATUS_OK,
384 		0,
385 		NULL,
386 		MRK_NONE,
387 		"*.example.com,192.0.2.*,2001:*",
388 		NULL,
389 		KEY_ED25519,
390 		NULL,	/* filled at runtime */
391 		"ED25519 #3",
392 	} },
393 	{ "rsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
394 		NULL,
395 		17,
396 		HKF_STATUS_OK,
397 		0,
398 		NULL,
399 		MRK_NONE,
400 		"*.example.com,192.0.2.*,2001:*",
401 		NULL,
402 		KEY_RSA,
403 		NULL,	/* filled at runtime */
404 		"RSA #3",
405 	} },
406 	{ NULL, -1, -1, 0, 0, 0, 0, -1, {
407 		NULL,
408 		18,
409 		HKF_STATUS_COMMENT,
410 		0,
411 		"",
412 		MRK_NONE,
413 		NULL,
414 		NULL,
415 		KEY_UNSPEC,
416 		NULL,
417 		NULL,
418 	} },
419 	{ NULL, -1, -1, 0, 0, 0, 0, -1, {
420 		NULL,
421 		19,
422 		HKF_STATUS_COMMENT,
423 		0,
424 		"# Hashed hostname and address entries",
425 		MRK_NONE,
426 		NULL,
427 		NULL,
428 		KEY_UNSPEC,
429 		NULL,
430 		NULL,
431 	} },
432 	{ "dsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, {
433 		NULL,
434 		20,
435 		HKF_STATUS_OK,
436 		0,
437 		NULL,
438 		MRK_NONE,
439 		NULL,
440 		NULL,
441 		KEY_DSA,
442 		NULL,	/* filled at runtime */
443 		"DSA #5",
444 	} },
445 	{ "ecdsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, {
446 		NULL,
447 		21,
448 		HKF_STATUS_OK,
449 		0,
450 		NULL,
451 		MRK_NONE,
452 		NULL,
453 		NULL,
454 		KEY_ECDSA,
455 		NULL,	/* filled at runtime */
456 		"ECDSA #5",
457 	} },
458 	{ "ed25519_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, {
459 		NULL,
460 		22,
461 		HKF_STATUS_OK,
462 		0,
463 		NULL,
464 		MRK_NONE,
465 		NULL,
466 		NULL,
467 		KEY_ED25519,
468 		NULL,	/* filled at runtime */
469 		"ED25519 #5",
470 	} },
471 	{ "rsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, {
472 		NULL,
473 		23,
474 		HKF_STATUS_OK,
475 		0,
476 		NULL,
477 		MRK_NONE,
478 		NULL,
479 		NULL,
480 		KEY_RSA,
481 		NULL,	/* filled at runtime */
482 		"RSA #5",
483 	} },
484 	{ NULL, -1, -1, 0, 0, 0, 0, -1, {
485 		NULL,
486 		24,
487 		HKF_STATUS_COMMENT,
488 		0,
489 		"",
490 		MRK_NONE,
491 		NULL,
492 		NULL,
493 		KEY_UNSPEC,
494 		NULL,
495 		NULL,
496 	} },
497 	/*
498 	 * The next series have each key listed multiple times, as the
499 	 * hostname and addresses in the pre-hashed known_hosts are split
500 	 * to separate lines.
501 	 */
502 	{ "dsa_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, {
503 		NULL,
504 		25,
505 		HKF_STATUS_OK,
506 		0,
507 		NULL,
508 		MRK_NONE,
509 		NULL,
510 		NULL,
511 		KEY_DSA,
512 		NULL,	/* filled at runtime */
513 		"DSA #6",
514 	} },
515 	{ "dsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, {
516 		NULL,
517 		26,
518 		HKF_STATUS_OK,
519 		0,
520 		NULL,
521 		MRK_NONE,
522 		NULL,
523 		NULL,
524 		KEY_DSA,
525 		NULL,	/* filled at runtime */
526 		"DSA #6",
527 	} },
528 	{ "dsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, {
529 		NULL,
530 		27,
531 		HKF_STATUS_OK,
532 		0,
533 		NULL,
534 		MRK_NONE,
535 		NULL,
536 		NULL,
537 		KEY_DSA,
538 		NULL,	/* filled at runtime */
539 		"DSA #6",
540 	} },
541 	{ "ecdsa_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, {
542 		NULL,
543 		28,
544 		HKF_STATUS_OK,
545 		0,
546 		NULL,
547 		MRK_NONE,
548 		NULL,
549 		NULL,
550 		KEY_ECDSA,
551 		NULL,	/* filled at runtime */
552 		"ECDSA #6",
553 	} },
554 	{ "ecdsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, {
555 		NULL,
556 		29,
557 		HKF_STATUS_OK,
558 		0,
559 		NULL,
560 		MRK_NONE,
561 		NULL,
562 		NULL,
563 		KEY_ECDSA,
564 		NULL,	/* filled at runtime */
565 		"ECDSA #6",
566 	} },
567 	{ "ecdsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, {
568 		NULL,
569 		30,
570 		HKF_STATUS_OK,
571 		0,
572 		NULL,
573 		MRK_NONE,
574 		NULL,
575 		NULL,
576 		KEY_ECDSA,
577 		NULL,	/* filled at runtime */
578 		"ECDSA #6",
579 	} },
580 	{ "ed25519_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, {
581 		NULL,
582 		31,
583 		HKF_STATUS_OK,
584 		0,
585 		NULL,
586 		MRK_NONE,
587 		NULL,
588 		NULL,
589 		KEY_ED25519,
590 		NULL,	/* filled at runtime */
591 		"ED25519 #6",
592 	} },
593 	{ "ed25519_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, {
594 		NULL,
595 		32,
596 		HKF_STATUS_OK,
597 		0,
598 		NULL,
599 		MRK_NONE,
600 		NULL,
601 		NULL,
602 		KEY_ED25519,
603 		NULL,	/* filled at runtime */
604 		"ED25519 #6",
605 	} },
606 	{ "ed25519_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, {
607 		NULL,
608 		33,
609 		HKF_STATUS_OK,
610 		0,
611 		NULL,
612 		MRK_NONE,
613 		NULL,
614 		NULL,
615 		KEY_ED25519,
616 		NULL,	/* filled at runtime */
617 		"ED25519 #6",
618 	} },
619 	{ "rsa_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, {
620 		NULL,
621 		34,
622 		HKF_STATUS_OK,
623 		0,
624 		NULL,
625 		MRK_NONE,
626 		NULL,
627 		NULL,
628 		KEY_RSA,
629 		NULL,	/* filled at runtime */
630 		"RSA #6",
631 	} },
632 	{ "rsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, {
633 		NULL,
634 		35,
635 		HKF_STATUS_OK,
636 		0,
637 		NULL,
638 		MRK_NONE,
639 		NULL,
640 		NULL,
641 		KEY_RSA,
642 		NULL,	/* filled at runtime */
643 		"RSA #6",
644 	} },
645 	{ "rsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, {
646 		NULL,
647 		36,
648 		HKF_STATUS_OK,
649 		0,
650 		NULL,
651 		MRK_NONE,
652 		NULL,
653 		NULL,
654 		KEY_RSA,
655 		NULL,	/* filled at runtime */
656 		"RSA #6",
657 	} },
658 	{ NULL, -1, -1, 0, 0, 0, 0, -1, {
659 		NULL,
660 		37,
661 		HKF_STATUS_COMMENT,
662 		0,
663 		"",
664 		MRK_NONE,
665 		NULL,
666 		NULL,
667 		KEY_UNSPEC,
668 		NULL,
669 		NULL,
670 	} },
671 	{ NULL, -1, -1, 0, 0, 0, 0, -1, {
672 		NULL,
673 		38,
674 		HKF_STATUS_COMMENT,
675 		0,
676 		"",
677 		MRK_NONE,
678 		NULL,
679 		NULL,
680 		KEY_UNSPEC,
681 		NULL,
682 		NULL,
683 	} },
684 	{ NULL, -1, -1, 0, 0, 0, 0, -1, {
685 		NULL,
686 		39,
687 		HKF_STATUS_COMMENT,
688 		0,
689 		"# Revoked and CA keys",
690 		MRK_NONE,
691 		NULL,
692 		NULL,
693 		KEY_UNSPEC,
694 		NULL,
695 		NULL,
696 	} },
697 	{ "ed25519_4.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
698 		NULL,
699 		40,
700 		HKF_STATUS_OK,
701 		0,
702 		NULL,
703 		MRK_REVOKE,
704 		"sisyphus.example.com",
705 		NULL,
706 		KEY_ED25519,
707 		NULL,	/* filled at runtime */
708 		"ED25519 #4",
709 	} },
710 	{ "ecdsa_4.pub" , -1, -1, HKF_MATCH_HOST, 0, 0, 0, -1, {
711 		NULL,
712 		41,
713 		HKF_STATUS_OK,
714 		0,
715 		NULL,
716 		MRK_CA,
717 		"prometheus.example.com",
718 		NULL,
719 		KEY_ECDSA,
720 		NULL,	/* filled at runtime */
721 		"ECDSA #4",
722 	} },
723 	{ "dsa_4.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, 0, 0, -1, {
724 		NULL,
725 		42,
726 		HKF_STATUS_OK,
727 		0,
728 		NULL,
729 		MRK_CA,
730 		"*.example.com",
731 		NULL,
732 		KEY_DSA,
733 		NULL,	/* filled at runtime */
734 		"DSA #4",
735 	} },
736 	{ NULL, -1, -1, 0, 0, 0, 0, -1, {
737 		NULL,
738 		43,
739 		HKF_STATUS_COMMENT,
740 		0,
741 		"",
742 		MRK_NONE,
743 		NULL,
744 		NULL,
745 		KEY_UNSPEC,
746 		NULL,
747 		NULL,
748 	} },
749 	{ NULL, -1, -1, 0, 0, 0, 0, -1, {
750 		NULL,
751 		44,
752 		HKF_STATUS_COMMENT,
753 		0,
754 		"# Some invalid lines",
755 		MRK_NONE,
756 		NULL,
757 		NULL,
758 		KEY_UNSPEC,
759 		NULL,
760 		NULL,
761 	} },
762 	{ NULL, -1, -1, 0, 0, 0, 0, -1, {
763 		NULL,
764 		45,
765 		HKF_STATUS_INVALID,
766 		0,
767 		NULL,
768 		MRK_ERROR,
769 		NULL,
770 		NULL,
771 		KEY_UNSPEC,
772 		NULL,
773 		NULL,
774 	} },
775 	{ NULL, -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
776 		NULL,
777 		46,
778 		HKF_STATUS_INVALID,
779 		0,
780 		NULL,
781 		MRK_NONE,
782 		"sisyphus.example.com",
783 		NULL,
784 		KEY_UNSPEC,
785 		NULL,
786 		NULL,
787 	} },
788 	{ NULL, -1, -1, HKF_MATCH_HOST, 0, 0, 0, -1, {
789 		NULL,
790 		47,
791 		HKF_STATUS_INVALID,
792 		0,
793 		NULL,
794 		MRK_NONE,
795 		"prometheus.example.com",
796 		NULL,
797 		KEY_UNSPEC,
798 		NULL,
799 		NULL,
800 	} },
801 	{ NULL, -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
802 		NULL,
803 		48,
804 		HKF_STATUS_INVALID,	/* Would be ok if key not parsed */
805 		0,
806 		NULL,
807 		MRK_NONE,
808 		"sisyphus.example.com",
809 		NULL,
810 		KEY_UNSPEC,
811 		NULL,
812 		NULL,
813 	} },
814 	{ NULL, -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
815 		NULL,
816 		49,
817 		HKF_STATUS_INVALID,
818 		0,
819 		NULL,
820 		MRK_NONE,
821 		"sisyphus.example.com",
822 		NULL,
823 		KEY_UNSPEC,
824 		NULL,	/* filled at runtime */
825 		NULL,
826 	} },
827 	{ NULL, HKF_STATUS_OK, KEY_RSA, HKF_MATCH_HOST, 0, 0, 0, -1, {
828 		NULL,
829 		50,
830 		HKF_STATUS_INVALID,	/* Would be ok if key not parsed */
831 		0,
832 		NULL,
833 		MRK_NONE,
834 		"prometheus.example.com",
835 		NULL,
836 		KEY_UNSPEC,
837 		NULL,	/* filled at runtime */
838 		NULL,
839 	} },
840 };
841 
842 void test_iterate(void);
843 
844 void
test_iterate(void)845 test_iterate(void)
846 {
847 	struct cbctx ctx;
848 
849 	TEST_START("hostkeys_iterate all with key parse");
850 	memset(&ctx, 0, sizeof(ctx));
851 	ctx.expected = expected_full;
852 	ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
853 	ctx.flags = HKF_WANT_PARSE_KEY;
854 	prepare_expected(expected_full, ctx.nexpected);
855 	ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
856 	    check, &ctx, NULL, NULL, ctx.flags), 0);
857 	cleanup_expected(expected_full, ctx.nexpected);
858 	TEST_DONE();
859 
860 	TEST_START("hostkeys_iterate all without key parse");
861 	memset(&ctx, 0, sizeof(ctx));
862 	ctx.expected = expected_full;
863 	ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
864 	ctx.flags = 0;
865 	prepare_expected(expected_full, ctx.nexpected);
866 	ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
867 	    check, &ctx, NULL, NULL, ctx.flags), 0);
868 	cleanup_expected(expected_full, ctx.nexpected);
869 	TEST_DONE();
870 
871 	TEST_START("hostkeys_iterate specify host 1");
872 	memset(&ctx, 0, sizeof(ctx));
873 	ctx.expected = expected_full;
874 	ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
875 	ctx.flags = 0;
876 	ctx.match_host_p = 1;
877 	prepare_expected(expected_full, ctx.nexpected);
878 	ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
879 	    check, &ctx, "prometheus.example.com", NULL, ctx.flags), 0);
880 	cleanup_expected(expected_full, ctx.nexpected);
881 	TEST_DONE();
882 
883 	TEST_START("hostkeys_iterate specify host 2");
884 	memset(&ctx, 0, sizeof(ctx));
885 	ctx.expected = expected_full;
886 	ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
887 	ctx.flags = 0;
888 	ctx.match_host_s = 1;
889 	prepare_expected(expected_full, ctx.nexpected);
890 	ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
891 	    check, &ctx, "sisyphus.example.com", NULL, ctx.flags), 0);
892 	cleanup_expected(expected_full, ctx.nexpected);
893 	TEST_DONE();
894 
895 	TEST_START("hostkeys_iterate match host 1");
896 	memset(&ctx, 0, sizeof(ctx));
897 	ctx.expected = expected_full;
898 	ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
899 	ctx.flags = HKF_WANT_MATCH;
900 	ctx.match_host_p = 1;
901 	prepare_expected(expected_full, ctx.nexpected);
902 	ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
903 	    check, &ctx, "prometheus.example.com", NULL, ctx.flags), 0);
904 	cleanup_expected(expected_full, ctx.nexpected);
905 	TEST_DONE();
906 
907 	TEST_START("hostkeys_iterate match host 2");
908 	memset(&ctx, 0, sizeof(ctx));
909 	ctx.expected = expected_full;
910 	ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
911 	ctx.flags = HKF_WANT_MATCH;
912 	ctx.match_host_s = 1;
913 	prepare_expected(expected_full, ctx.nexpected);
914 	ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
915 	    check, &ctx, "sisyphus.example.com", NULL, ctx.flags), 0);
916 	cleanup_expected(expected_full, ctx.nexpected);
917 	TEST_DONE();
918 
919 	TEST_START("hostkeys_iterate specify host missing");
920 	memset(&ctx, 0, sizeof(ctx));
921 	ctx.expected = expected_full;
922 	ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
923 	ctx.flags = 0;
924 	prepare_expected(expected_full, ctx.nexpected);
925 	ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
926 	    check, &ctx, "actaeon.example.org", NULL, ctx.flags), 0);
927 	cleanup_expected(expected_full, ctx.nexpected);
928 	TEST_DONE();
929 
930 	TEST_START("hostkeys_iterate match host missing");
931 	memset(&ctx, 0, sizeof(ctx));
932 	ctx.expected = expected_full;
933 	ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
934 	ctx.flags = HKF_WANT_MATCH;
935 	prepare_expected(expected_full, ctx.nexpected);
936 	ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
937 	    check, &ctx, "actaeon.example.org", NULL, ctx.flags), 0);
938 	cleanup_expected(expected_full, ctx.nexpected);
939 	TEST_DONE();
940 
941 	TEST_START("hostkeys_iterate specify IPv4");
942 	memset(&ctx, 0, sizeof(ctx));
943 	ctx.expected = expected_full;
944 	ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
945 	ctx.flags = 0;
946 	ctx.match_ipv4 = 1;
947 	prepare_expected(expected_full, ctx.nexpected);
948 	ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
949 	    check, &ctx, "tiresias.example.org", "192.0.2.1", ctx.flags), 0);
950 	cleanup_expected(expected_full, ctx.nexpected);
951 	TEST_DONE();
952 
953 	TEST_START("hostkeys_iterate specify IPv6");
954 	memset(&ctx, 0, sizeof(ctx));
955 	ctx.expected = expected_full;
956 	ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
957 	ctx.flags = 0;
958 	ctx.match_ipv6 = 1;
959 	prepare_expected(expected_full, ctx.nexpected);
960 	ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
961 	    check, &ctx, "tiresias.example.org", "2001:db8::1", ctx.flags), 0);
962 	cleanup_expected(expected_full, ctx.nexpected);
963 	TEST_DONE();
964 
965 	TEST_START("hostkeys_iterate match IPv4");
966 	memset(&ctx, 0, sizeof(ctx));
967 	ctx.expected = expected_full;
968 	ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
969 	ctx.flags = HKF_WANT_MATCH;
970 	ctx.match_ipv4 = 1;
971 	prepare_expected(expected_full, ctx.nexpected);
972 	ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
973 	    check, &ctx, "tiresias.example.org", "192.0.2.1", ctx.flags), 0);
974 	cleanup_expected(expected_full, ctx.nexpected);
975 	TEST_DONE();
976 
977 	TEST_START("hostkeys_iterate match IPv6");
978 	memset(&ctx, 0, sizeof(ctx));
979 	ctx.expected = expected_full;
980 	ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
981 	ctx.flags = HKF_WANT_MATCH;
982 	ctx.match_ipv6 = 1;
983 	prepare_expected(expected_full, ctx.nexpected);
984 	ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
985 	    check, &ctx, "tiresias.example.org", "2001:db8::1", ctx.flags), 0);
986 	cleanup_expected(expected_full, ctx.nexpected);
987 	TEST_DONE();
988 
989 	TEST_START("hostkeys_iterate specify addr missing");
990 	memset(&ctx, 0, sizeof(ctx));
991 	ctx.expected = expected_full;
992 	ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
993 	ctx.flags = 0;
994 	prepare_expected(expected_full, ctx.nexpected);
995 	ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
996 	    check, &ctx, "tiresias.example.org", "192.168.0.1", ctx.flags), 0);
997 	cleanup_expected(expected_full, ctx.nexpected);
998 	TEST_DONE();
999 
1000 	TEST_START("hostkeys_iterate match addr missing");
1001 	memset(&ctx, 0, sizeof(ctx));
1002 	ctx.expected = expected_full;
1003 	ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
1004 	ctx.flags = HKF_WANT_MATCH;
1005 	prepare_expected(expected_full, ctx.nexpected);
1006 	ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
1007 	    check, &ctx, "tiresias.example.org", "::1", ctx.flags), 0);
1008 	cleanup_expected(expected_full, ctx.nexpected);
1009 	TEST_DONE();
1010 
1011 	TEST_START("hostkeys_iterate specify host 2 and IPv4");
1012 	memset(&ctx, 0, sizeof(ctx));
1013 	ctx.expected = expected_full;
1014 	ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
1015 	ctx.flags = 0;
1016 	ctx.match_host_s = 1;
1017 	ctx.match_ipv4 = 1;
1018 	prepare_expected(expected_full, ctx.nexpected);
1019 	ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
1020 	    check, &ctx, "sisyphus.example.com", "192.0.2.1", ctx.flags), 0);
1021 	cleanup_expected(expected_full, ctx.nexpected);
1022 	TEST_DONE();
1023 
1024 	TEST_START("hostkeys_iterate match host 1 and IPv6");
1025 	memset(&ctx, 0, sizeof(ctx));
1026 	ctx.expected = expected_full;
1027 	ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
1028 	ctx.flags = HKF_WANT_MATCH;
1029 	ctx.match_host_p = 1;
1030 	ctx.match_ipv6 = 1;
1031 	prepare_expected(expected_full, ctx.nexpected);
1032 	ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
1033 	    check, &ctx, "prometheus.example.com",
1034 	    "2001:db8::1", ctx.flags), 0);
1035 	cleanup_expected(expected_full, ctx.nexpected);
1036 	TEST_DONE();
1037 
1038 	TEST_START("hostkeys_iterate specify host 2 and IPv4 w/ key parse");
1039 	memset(&ctx, 0, sizeof(ctx));
1040 	ctx.expected = expected_full;
1041 	ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
1042 	ctx.flags = HKF_WANT_PARSE_KEY;
1043 	ctx.match_host_s = 1;
1044 	ctx.match_ipv4 = 1;
1045 	prepare_expected(expected_full, ctx.nexpected);
1046 	ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
1047 	    check, &ctx, "sisyphus.example.com", "192.0.2.1", ctx.flags), 0);
1048 	cleanup_expected(expected_full, ctx.nexpected);
1049 	TEST_DONE();
1050 
1051 	TEST_START("hostkeys_iterate match host 1 and IPv6 w/ key parse");
1052 	memset(&ctx, 0, sizeof(ctx));
1053 	ctx.expected = expected_full;
1054 	ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
1055 	ctx.flags = HKF_WANT_MATCH|HKF_WANT_PARSE_KEY;
1056 	ctx.match_host_p = 1;
1057 	ctx.match_ipv6 = 1;
1058 	prepare_expected(expected_full, ctx.nexpected);
1059 	ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
1060 	    check, &ctx, "prometheus.example.com",
1061 	    "2001:db8::1", ctx.flags), 0);
1062 	cleanup_expected(expected_full, ctx.nexpected);
1063 	TEST_DONE();
1064 }
1065 
1066