diff options
author | Colin Watson <cjwatson@debian.org> | 2010-03-31 00:48:57 +0100 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2010-03-31 00:48:57 +0100 |
commit | d1a87e462e1db89f19cd960588d0c6b287cb5ccc (patch) | |
tree | f0d13e1687800f36a3c4322b94ac5230ad17bdbf /addrmatch.c | |
parent | 964476f91b66c475d5b8fa1e8b28d39a97a1b56e (diff) | |
parent | 004a7fb9c6a00b13dc98f56599918a54a3506d10 (diff) |
merge 5.4p1
Diffstat (limited to 'addrmatch.c')
-rw-r--r-- | addrmatch.c | 78 |
1 files changed, 77 insertions, 1 deletions
diff --git a/addrmatch.c b/addrmatch.c index d39885b7b..5b6773cce 100644 --- a/addrmatch.c +++ b/addrmatch.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: addrmatch.c,v 1.4 2008/12/10 03:55:20 stevesk Exp $ */ | 1 | /* $OpenBSD: addrmatch.c,v 1.5 2010/02/26 20:29:54 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2004-2008 Damien Miller <djm@mindrot.org> | 4 | * Copyright (c) 2004-2008 Damien Miller <djm@mindrot.org> |
@@ -126,6 +126,8 @@ addr_netmask(int af, u_int l, struct xaddr *n) | |||
126 | switch (af) { | 126 | switch (af) { |
127 | case AF_INET: | 127 | case AF_INET: |
128 | n->af = AF_INET; | 128 | n->af = AF_INET; |
129 | if (l == 0) | ||
130 | return 0; | ||
129 | n->v4.s_addr = htonl((0xffffffff << (32 - l)) & 0xffffffff); | 131 | n->v4.s_addr = htonl((0xffffffff << (32 - l)) & 0xffffffff); |
130 | return 0; | 132 | return 0; |
131 | case AF_INET6: | 133 | case AF_INET6: |
@@ -422,3 +424,77 @@ addr_match_list(const char *addr, const char *_list) | |||
422 | 424 | ||
423 | return ret; | 425 | return ret; |
424 | } | 426 | } |
427 | |||
428 | /* | ||
429 | * Match "addr" against list CIDR list "_list". Lexical wildcards and | ||
430 | * negation are not supported. If "addr" == NULL, will verify structure | ||
431 | * of "_list". | ||
432 | * | ||
433 | * Returns 1 on match found (never returned when addr == NULL). | ||
434 | * Returns 0 on if no match found, or no errors found when addr == NULL. | ||
435 | * Returns -1 on error | ||
436 | */ | ||
437 | int | ||
438 | addr_match_cidr_list(const char *addr, const char *_list) | ||
439 | { | ||
440 | char *list, *cp, *o; | ||
441 | struct xaddr try_addr, match_addr; | ||
442 | u_int masklen; | ||
443 | int ret = 0, r; | ||
444 | |||
445 | if (addr != NULL && addr_pton(addr, &try_addr) != 0) { | ||
446 | debug2("%s: couldn't parse address %.100s", __func__, addr); | ||
447 | return 0; | ||
448 | } | ||
449 | if ((o = list = strdup(_list)) == NULL) | ||
450 | return -1; | ||
451 | while ((cp = strsep(&list, ",")) != NULL) { | ||
452 | if (*cp == '\0') { | ||
453 | error("%s: empty entry in list \"%.100s\"", | ||
454 | __func__, o); | ||
455 | ret = -1; | ||
456 | break; | ||
457 | } | ||
458 | |||
459 | /* | ||
460 | * NB. This function is called in pre-auth with untrusted data, | ||
461 | * so be extra paranoid about junk reaching getaddrino (via | ||
462 | * addr_pton_cidr). | ||
463 | */ | ||
464 | |||
465 | /* Stop junk from reaching getaddrinfo. +3 is for masklen */ | ||
466 | if (strlen(cp) > INET6_ADDRSTRLEN + 3) { | ||
467 | error("%s: list entry \"%.100s\" too long", | ||
468 | __func__, cp); | ||
469 | ret = -1; | ||
470 | break; | ||
471 | } | ||
472 | #define VALID_CIDR_CHARS "0123456789abcdefABCDEF.:/" | ||
473 | if (strspn(cp, VALID_CIDR_CHARS) != strlen(cp)) { | ||
474 | error("%s: list entry \"%.100s\" contains invalid " | ||
475 | "characters", __func__, cp); | ||
476 | ret = -1; | ||
477 | } | ||
478 | |||
479 | /* Prefer CIDR address matching */ | ||
480 | r = addr_pton_cidr(cp, &match_addr, &masklen); | ||
481 | if (r == -1) { | ||
482 | error("Invalid network entry \"%.100s\"", cp); | ||
483 | ret = -1; | ||
484 | break; | ||
485 | } else if (r == -2) { | ||
486 | error("Inconsistent mask length for " | ||
487 | "network \"%.100s\"", cp); | ||
488 | ret = -1; | ||
489 | break; | ||
490 | } else if (r == 0 && addr != NULL) { | ||
491 | if (addr_netmatch(&try_addr, &match_addr, | ||
492 | masklen) == 0) | ||
493 | ret = 1; | ||
494 | continue; | ||
495 | } | ||
496 | } | ||
497 | xfree(o); | ||
498 | |||
499 | return ret; | ||
500 | } | ||