summaryrefslogtreecommitdiff
path: root/addrmatch.c
diff options
context:
space:
mode:
Diffstat (limited to 'addrmatch.c')
-rw-r--r--addrmatch.c78
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 */
437int
438addr_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}