Home | History | Annotate | Download | only in hostkeys
      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 
     25 struct 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 
     37 struct 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  */
     52 static int
     53 check(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 */
    145 static void
    146 prepare_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 
    167 struct 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 
    968 void test_iterate(void);
    969 
    970 void
    971 test_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