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