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