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