1266072Sdes/* $OpenBSD: addrmatch.c,v 1.10 2015/07/08 19:04:21 markus Exp $ */ 2266072Sdes 3266072Sdes/* 4266072Sdes * Copyright (c) 2004-2008 Damien Miller <djm@mindrot.org> 5266072Sdes * 6266072Sdes * Permission to use, copy, modify, and distribute this software for any 7266072Sdes * purpose with or without fee is hereby granted, provided that the above 8266072Sdes * copyright notice and this permission notice appear in all copies. 9266072Sdes * 10266072Sdes * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11266072Sdes * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12266072Sdes * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13266072Sdes * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14266072Sdes * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15266072Sdes * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16266072Sdes * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17266072Sdes */ 18266072Sdes 19266072Sdes#include "includes.h" 20266072Sdes 21266072Sdes#include <sys/types.h> 22266072Sdes#include <sys/socket.h> 23266072Sdes#include <netinet/in.h> 24266072Sdes#include <arpa/inet.h> 25266072Sdes 26266072Sdes#include <netdb.h> 27266072Sdes#include <string.h> 28266072Sdes#include <stdlib.h> 29266072Sdes#include <stdio.h> 30266072Sdes#include <stdarg.h> 31266072Sdes 32266072Sdes#include "match.h" 33266072Sdes#include "log.h" 34266072Sdes 35266072Sdesstruct xaddr { 36266072Sdes sa_family_t af; 37266072Sdes union { 38266072Sdes struct in_addr v4; 39266072Sdes struct in6_addr v6; 40266072Sdes u_int8_t addr8[16]; 41266072Sdes u_int32_t addr32[4]; 42266072Sdes } xa; /* 128-bit address */ 43266072Sdes u_int32_t scope_id; /* iface scope id for v6 */ 44266072Sdes#define v4 xa.v4 45266072Sdes#define v6 xa.v6 46266072Sdes#define addr8 xa.addr8 47266072Sdes#define addr32 xa.addr32 48266072Sdes}; 49266072Sdes 50266072Sdesstatic int 51266072Sdesaddr_unicast_masklen(int af) 52266072Sdes{ 53266072Sdes switch (af) { 54266072Sdes case AF_INET: 55266072Sdes return 32; 56266072Sdes case AF_INET6: 57266072Sdes return 128; 58266072Sdes default: 59266072Sdes return -1; 60266072Sdes } 61266072Sdes} 62266072Sdes 63266072Sdesstatic inline int 64266072Sdesmasklen_valid(int af, u_int masklen) 65266072Sdes{ 66266072Sdes switch (af) { 67266072Sdes case AF_INET: 68266072Sdes return masklen <= 32 ? 0 : -1; 69266072Sdes case AF_INET6: 70266072Sdes return masklen <= 128 ? 0 : -1; 71266072Sdes default: 72266072Sdes return -1; 73266072Sdes } 74266072Sdes} 75266072Sdes 76266072Sdes/* 77266072Sdes * Convert struct sockaddr to struct xaddr 78266072Sdes * Returns 0 on success, -1 on failure. 79266072Sdes */ 80266072Sdesstatic int 81266072Sdesaddr_sa_to_xaddr(struct sockaddr *sa, socklen_t slen, struct xaddr *xa) 82266072Sdes{ 83266072Sdes struct sockaddr_in *in4 = (struct sockaddr_in *)sa; 84266072Sdes struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa; 85266072Sdes 86266072Sdes memset(xa, '\0', sizeof(*xa)); 87266072Sdes 88266072Sdes switch (sa->sa_family) { 89266072Sdes case AF_INET: 90266072Sdes if (slen < (socklen_t)sizeof(*in4)) 91266072Sdes return -1; 92266072Sdes xa->af = AF_INET; 93266072Sdes memcpy(&xa->v4, &in4->sin_addr, sizeof(xa->v4)); 94266072Sdes break; 95266072Sdes case AF_INET6: 96266072Sdes if (slen < (socklen_t)sizeof(*in6)) 97266072Sdes return -1; 98266072Sdes xa->af = AF_INET6; 99266072Sdes memcpy(&xa->v6, &in6->sin6_addr, sizeof(xa->v6)); 100266072Sdes#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID 101266072Sdes xa->scope_id = in6->sin6_scope_id; 102266072Sdes#endif 103266072Sdes break; 104266072Sdes default: 105266072Sdes return -1; 106266072Sdes } 107266072Sdes 108266072Sdes return 0; 109266072Sdes} 110266072Sdes 111266072Sdes/* 112266072Sdes * Calculate a netmask of length 'l' for address family 'af' and 113266072Sdes * store it in 'n'. 114266072Sdes * Returns 0 on success, -1 on failure. 115266072Sdes */ 116266072Sdesstatic int 117266072Sdesaddr_netmask(int af, u_int l, struct xaddr *n) 118266072Sdes{ 119266072Sdes int i; 120266072Sdes 121266072Sdes if (masklen_valid(af, l) != 0 || n == NULL) 122266072Sdes return -1; 123266072Sdes 124266072Sdes memset(n, '\0', sizeof(*n)); 125266072Sdes switch (af) { 126266072Sdes case AF_INET: 127266072Sdes n->af = AF_INET; 128266072Sdes if (l == 0) 129266072Sdes return 0; 130266072Sdes n->v4.s_addr = htonl((0xffffffff << (32 - l)) & 0xffffffff); 131266072Sdes return 0; 132266072Sdes case AF_INET6: 133266072Sdes n->af = AF_INET6; 134266072Sdes for (i = 0; i < 4 && l >= 32; i++, l -= 32) 135266072Sdes n->addr32[i] = 0xffffffffU; 136266072Sdes if (i < 4 && l != 0) 137266072Sdes n->addr32[i] = htonl((0xffffffff << (32 - l)) & 138266072Sdes 0xffffffff); 139266072Sdes return 0; 140266072Sdes default: 141266072Sdes return -1; 142266072Sdes } 143266072Sdes} 144266072Sdes 145266072Sdes/* 146266072Sdes * Perform logical AND of addresses 'a' and 'b', storing result in 'dst'. 147266072Sdes * Returns 0 on success, -1 on failure. 148266072Sdes */ 149266072Sdesstatic int 150266072Sdesaddr_and(struct xaddr *dst, const struct xaddr *a, const struct xaddr *b) 151266072Sdes{ 152266072Sdes int i; 153266072Sdes 154266072Sdes if (dst == NULL || a == NULL || b == NULL || a->af != b->af) 155266072Sdes return -1; 156266072Sdes 157266072Sdes memcpy(dst, a, sizeof(*dst)); 158266072Sdes switch (a->af) { 159266072Sdes case AF_INET: 160266072Sdes dst->v4.s_addr &= b->v4.s_addr; 161266072Sdes return 0; 162266072Sdes case AF_INET6: 163266072Sdes dst->scope_id = a->scope_id; 164266072Sdes for (i = 0; i < 4; i++) 165266072Sdes dst->addr32[i] &= b->addr32[i]; 166266072Sdes return 0; 167266072Sdes default: 168266072Sdes return -1; 169266072Sdes } 170266072Sdes} 171266072Sdes 172266072Sdes/* 173266072Sdes * Compare addresses 'a' and 'b' 174266072Sdes * Return 0 if addresses are identical, -1 if (a < b) or 1 if (a > b) 175266072Sdes */ 176266072Sdesstatic int 177266072Sdesaddr_cmp(const struct xaddr *a, const struct xaddr *b) 178266072Sdes{ 179266072Sdes int i; 180266072Sdes 181266072Sdes if (a->af != b->af) 182266072Sdes return a->af == AF_INET6 ? 1 : -1; 183266072Sdes 184266072Sdes switch (a->af) { 185266072Sdes case AF_INET: 186266072Sdes if (a->v4.s_addr == b->v4.s_addr) 187266072Sdes return 0; 188266072Sdes return ntohl(a->v4.s_addr) > ntohl(b->v4.s_addr) ? 1 : -1; 189266072Sdes case AF_INET6: 190266072Sdes for (i = 0; i < 16; i++) 191266072Sdes if (a->addr8[i] - b->addr8[i] != 0) 192266072Sdes return a->addr8[i] > b->addr8[i] ? 1 : -1; 193266072Sdes if (a->scope_id == b->scope_id) 194266072Sdes return 0; 195266072Sdes return a->scope_id > b->scope_id ? 1 : -1; 196266072Sdes default: 197266072Sdes return -1; 198266072Sdes } 199266072Sdes} 200266072Sdes 201266072Sdes/* 202266072Sdes * Parse string address 'p' into 'n' 203266072Sdes * Returns 0 on success, -1 on failure. 204266072Sdes */ 205266072Sdesstatic int 206266072Sdesaddr_pton(const char *p, struct xaddr *n) 207266072Sdes{ 208266072Sdes struct addrinfo hints, *ai; 209266072Sdes 210266072Sdes memset(&hints, '\0', sizeof(hints)); 211266072Sdes hints.ai_flags = AI_NUMERICHOST; 212266072Sdes 213266072Sdes if (p == NULL || getaddrinfo(p, NULL, &hints, &ai) != 0) 214266072Sdes return -1; 215266072Sdes 216266072Sdes if (ai == NULL || ai->ai_addr == NULL) 217266072Sdes return -1; 218266072Sdes 219266072Sdes if (n != NULL && 220266072Sdes addr_sa_to_xaddr(ai->ai_addr, ai->ai_addrlen, n) == -1) { 221266072Sdes freeaddrinfo(ai); 222266072Sdes return -1; 223266072Sdes } 224266072Sdes 225266072Sdes freeaddrinfo(ai); 226266072Sdes return 0; 227266072Sdes} 228266072Sdes 229266072Sdes/* 230266072Sdes * Perform bitwise negation of address 231266072Sdes * Returns 0 on success, -1 on failure. 232266072Sdes */ 233266072Sdesstatic int 234266072Sdesaddr_invert(struct xaddr *n) 235266072Sdes{ 236266072Sdes int i; 237266072Sdes 238266072Sdes if (n == NULL) 239266072Sdes return (-1); 240266072Sdes 241266072Sdes switch (n->af) { 242266072Sdes case AF_INET: 243266072Sdes n->v4.s_addr = ~n->v4.s_addr; 244266072Sdes return (0); 245266072Sdes case AF_INET6: 246266072Sdes for (i = 0; i < 4; i++) 247266072Sdes n->addr32[i] = ~n->addr32[i]; 248266072Sdes return (0); 249266072Sdes default: 250266072Sdes return (-1); 251266072Sdes } 252266072Sdes} 253266072Sdes 254266072Sdes/* 255266072Sdes * Calculate a netmask of length 'l' for address family 'af' and 256266072Sdes * store it in 'n'. 257266072Sdes * Returns 0 on success, -1 on failure. 258266072Sdes */ 259266072Sdesstatic int 260266072Sdesaddr_hostmask(int af, u_int l, struct xaddr *n) 261266072Sdes{ 262266072Sdes if (addr_netmask(af, l, n) == -1 || addr_invert(n) == -1) 263266072Sdes return (-1); 264266072Sdes return (0); 265266072Sdes} 266266072Sdes 267266072Sdes/* 268266072Sdes * Test whether address 'a' is all zeros (i.e. 0.0.0.0 or ::) 269266072Sdes * Returns 0 on if address is all-zeros, -1 if not all zeros or on failure. 270266072Sdes */ 271266072Sdesstatic int 272266072Sdesaddr_is_all0s(const struct xaddr *a) 273266072Sdes{ 274266072Sdes int i; 275266072Sdes 276266072Sdes switch (a->af) { 277266072Sdes case AF_INET: 278266072Sdes return (a->v4.s_addr == 0 ? 0 : -1); 279266072Sdes case AF_INET6:; 280266072Sdes for (i = 0; i < 4; i++) 281266072Sdes if (a->addr32[i] != 0) 282266072Sdes return (-1); 283266072Sdes return (0); 284266072Sdes default: 285266072Sdes return (-1); 286266072Sdes } 287266072Sdes} 288266072Sdes 289266072Sdes/* 290266072Sdes * Test whether host portion of address 'a', as determined by 'masklen' 291266072Sdes * is all zeros. 292266072Sdes * Returns 0 on if host portion of address is all-zeros, 293266072Sdes * -1 if not all zeros or on failure. 294266072Sdes */ 295266072Sdesstatic int 296266072Sdesaddr_host_is_all0s(const struct xaddr *a, u_int masklen) 297266072Sdes{ 298266072Sdes struct xaddr tmp_addr, tmp_mask, tmp_result; 299266072Sdes 300266072Sdes memcpy(&tmp_addr, a, sizeof(tmp_addr)); 301266072Sdes if (addr_hostmask(a->af, masklen, &tmp_mask) == -1) 302266072Sdes return (-1); 303266072Sdes if (addr_and(&tmp_result, &tmp_addr, &tmp_mask) == -1) 304266072Sdes return (-1); 305266072Sdes return (addr_is_all0s(&tmp_result)); 306266072Sdes} 307266072Sdes 308266072Sdes/* 309266072Sdes * Parse a CIDR address (x.x.x.x/y or xxxx:yyyy::/z). 310266072Sdes * Return -1 on parse error, -2 on inconsistency or 0 on success. 311266072Sdes */ 312266072Sdesstatic int 313266072Sdesaddr_pton_cidr(const char *p, struct xaddr *n, u_int *l) 314266072Sdes{ 315266072Sdes struct xaddr tmp; 316266072Sdes long unsigned int masklen = 999; 317266072Sdes char addrbuf[64], *mp, *cp; 318266072Sdes 319266072Sdes /* Don't modify argument */ 320266072Sdes if (p == NULL || strlcpy(addrbuf, p, sizeof(addrbuf)) >= sizeof(addrbuf)) 321266072Sdes return -1; 322266072Sdes 323266072Sdes if ((mp = strchr(addrbuf, '/')) != NULL) { 324266072Sdes *mp = '\0'; 325266072Sdes mp++; 326266072Sdes masklen = strtoul(mp, &cp, 10); 327266072Sdes if (*mp == '\0' || *cp != '\0' || masklen > 128) 328266072Sdes return -1; 329266072Sdes } 330266072Sdes 331266072Sdes if (addr_pton(addrbuf, &tmp) == -1) 332266072Sdes return -1; 333266072Sdes 334266072Sdes if (mp == NULL) 335266072Sdes masklen = addr_unicast_masklen(tmp.af); 336266072Sdes if (masklen_valid(tmp.af, masklen) == -1) 337266072Sdes return -2; 338266072Sdes if (addr_host_is_all0s(&tmp, masklen) != 0) 339266072Sdes return -2; 340266072Sdes 341266072Sdes if (n != NULL) 342266072Sdes memcpy(n, &tmp, sizeof(*n)); 343266072Sdes if (l != NULL) 344266072Sdes *l = masklen; 345266072Sdes 346266072Sdes return 0; 347266072Sdes} 348266072Sdes 349266072Sdesstatic int 350266072Sdesaddr_netmatch(const struct xaddr *host, const struct xaddr *net, u_int masklen) 351266072Sdes{ 352266072Sdes struct xaddr tmp_mask, tmp_result; 353266072Sdes 354266072Sdes if (host->af != net->af) 355266072Sdes return -1; 356266072Sdes 357266072Sdes if (addr_netmask(host->af, masklen, &tmp_mask) == -1) 358266072Sdes return -1; 359266072Sdes if (addr_and(&tmp_result, host, &tmp_mask) == -1) 360266072Sdes return -1; 361266072Sdes return addr_cmp(&tmp_result, net); 362266072Sdes} 363266072Sdes 364266072Sdes/* 365266072Sdes * Match "addr" against list pattern list "_list", which may contain a 366266072Sdes * mix of CIDR addresses and old-school wildcards. 367266072Sdes * 368266072Sdes * If addr is NULL, then no matching is performed, but _list is parsed 369266072Sdes * and checked for well-formedness. 370266072Sdes * 371266072Sdes * Returns 1 on match found (never returned when addr == NULL). 372266072Sdes * Returns 0 on if no match found, or no errors found when addr == NULL. 373266072Sdes * Returns -1 on negated match found (never returned when addr == NULL). 374266072Sdes * Returns -2 on invalid list entry. 375266072Sdes */ 376266072Sdesint 377266072Sdesaddr_match_list(const char *addr, const char *_list) 378266072Sdes{ 379266072Sdes char *list, *cp, *o; 380266072Sdes struct xaddr try_addr, match_addr; 381266072Sdes u_int masklen, neg; 382266072Sdes int ret = 0, r; 383266072Sdes 384266072Sdes if (addr != NULL && addr_pton(addr, &try_addr) != 0) { 385266072Sdes debug2("%s: couldn't parse address %.100s", __func__, addr); 386266072Sdes return 0; 387266072Sdes } 388266072Sdes if ((o = list = strdup(_list)) == NULL) 389266072Sdes return -1; 390266072Sdes while ((cp = strsep(&list, ",")) != NULL) { 391266072Sdes neg = *cp == '!'; 392266072Sdes if (neg) 393266072Sdes cp++; 394266072Sdes if (*cp == '\0') { 395266072Sdes ret = -2; 396266072Sdes break; 397266072Sdes } 398266072Sdes /* Prefer CIDR address matching */ 399266072Sdes r = addr_pton_cidr(cp, &match_addr, &masklen); 400266072Sdes if (r == -2) { 401266072Sdes error("Inconsistent mask length for " 402266072Sdes "network \"%.100s\"", cp); 403266072Sdes ret = -2; 404266072Sdes break; 405266072Sdes } else if (r == 0) { 406266072Sdes if (addr != NULL && addr_netmatch(&try_addr, 407266072Sdes &match_addr, masklen) == 0) { 408266072Sdes foundit: 409266072Sdes if (neg) { 410266072Sdes ret = -1; 411266072Sdes break; 412266072Sdes } 413266072Sdes ret = 1; 414266072Sdes } 415266072Sdes continue; 416266072Sdes } else { 417266072Sdes /* If CIDR parse failed, try wildcard string match */ 418266072Sdes if (addr != NULL && match_pattern(addr, cp) == 1) 419266072Sdes goto foundit; 420266072Sdes } 421266072Sdes } 422266072Sdes free(o); 423266072Sdes 424266072Sdes return ret; 425266072Sdes} 426266072Sdes 427266072Sdes/* 428266072Sdes * Match "addr" against list CIDR list "_list". Lexical wildcards and 429266072Sdes * negation are not supported. If "addr" == NULL, will verify structure 430266072Sdes * of "_list". 431266072Sdes * 432266072Sdes * Returns 1 on match found (never returned when addr == NULL). 433266072Sdes * Returns 0 on if no match found, or no errors found when addr == NULL. 434266072Sdes * Returns -1 on error 435266072Sdes */ 436266072Sdesint 437266072Sdesaddr_match_cidr_list(const char *addr, const char *_list) 438266072Sdes{ 439266072Sdes char *list, *cp, *o; 440266072Sdes struct xaddr try_addr, match_addr; 441266072Sdes u_int masklen; 442266072Sdes int ret = 0, r; 443266072Sdes 444266072Sdes if (addr != NULL && addr_pton(addr, &try_addr) != 0) { 445266072Sdes debug2("%s: couldn't parse address %.100s", __func__, addr); 446266072Sdes return 0; 447266072Sdes } 448266072Sdes if ((o = list = strdup(_list)) == NULL) 449266072Sdes return -1; 450266072Sdes while ((cp = strsep(&list, ",")) != NULL) { 451266072Sdes if (*cp == '\0') { 452266072Sdes error("%s: empty entry in list \"%.100s\"", 453266072Sdes __func__, o); 454266072Sdes ret = -1; 455266072Sdes break; 456266072Sdes } 457266072Sdes 458266072Sdes /* 459266072Sdes * NB. This function is called in pre-auth with untrusted data, 460266072Sdes * so be extra paranoid about junk reaching getaddrino (via 461266072Sdes * addr_pton_cidr). 462266072Sdes */ 463266072Sdes 464266072Sdes /* Stop junk from reaching getaddrinfo. +3 is for masklen */ 465266072Sdes if (strlen(cp) > INET6_ADDRSTRLEN + 3) { 466266072Sdes error("%s: list entry \"%.100s\" too long", 467266072Sdes __func__, cp); 468266072Sdes ret = -1; 469266072Sdes break; 470266072Sdes } 471266072Sdes#define VALID_CIDR_CHARS "0123456789abcdefABCDEF.:/" 472266072Sdes if (strspn(cp, VALID_CIDR_CHARS) != strlen(cp)) { 473266072Sdes error("%s: list entry \"%.100s\" contains invalid " 474266072Sdes "characters", __func__, cp); 475266072Sdes ret = -1; 476266072Sdes } 477266072Sdes 478266072Sdes /* Prefer CIDR address matching */ 479266072Sdes r = addr_pton_cidr(cp, &match_addr, &masklen); 480266072Sdes if (r == -1) { 481266072Sdes error("Invalid network entry \"%.100s\"", cp); 482266072Sdes ret = -1; 483266072Sdes break; 484266072Sdes } else if (r == -2) { 485266072Sdes error("Inconsistent mask length for " 486266072Sdes "network \"%.100s\"", cp); 487266072Sdes ret = -1; 488266072Sdes break; 489266072Sdes } else if (r == 0 && addr != NULL) { 490266072Sdes if (addr_netmatch(&try_addr, &match_addr, 491266072Sdes masklen) == 0) 492266072Sdes ret = 1; 493266072Sdes continue; 494266072Sdes } 495266072Sdes } 496266072Sdes free(o); 497266072Sdes 498266072Sdes return ret; 499266072Sdes} 500266072Sdes