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