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