|
version 1.1.1.1, 2012/02/17 15:09:30
|
version 1.1.1.4, 2021/03/17 00:32:36
|
|
Line 2
|
Line 2
|
| * Routines to authenticate access to a daemon (hosts allow/deny). |
* Routines to authenticate access to a daemon (hosts allow/deny). |
| * |
* |
| * Copyright (C) 1998 Andrew Tridgell |
* Copyright (C) 1998 Andrew Tridgell |
| * Copyright (C) 2004-2009 Wayne Davison | * Copyright (C) 2004-2020 Wayne Davison |
| * |
* |
| * This program is free software; you can redistribute it and/or modify |
* This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
* it under the terms of the GNU General Public License as published by |
|
Line 19
|
Line 19
|
| */ |
*/ |
| |
|
| #include "rsync.h" |
#include "rsync.h" |
| |
#include "ifuncs.h" |
| |
|
| static int match_hostname(char *host, char *tok) | static int allow_forward_dns; |
| | |
| | extern const char undetermined_hostname[]; |
| | |
| | static int match_hostname(const char **host_ptr, const char *addr, const char *tok) |
| { |
{ |
| |
struct hostent *hp; |
| |
unsigned int i; |
| |
const char *host = *host_ptr; |
| |
|
| if (!host || !*host) |
if (!host || !*host) |
| return 0; |
return 0; |
| return wildmatch(tok, host); | |
| | #ifdef HAVE_INNETGR |
| | if (*tok == '@' && tok[1]) |
| | return innetgr(tok + 1, host, NULL, NULL); |
| | #endif |
| | |
| | /* First check if the reverse-DNS-determined hostname matches. */ |
| | if (iwildmatch(tok, host)) |
| | return 1; |
| | |
| | if (!allow_forward_dns) |
| | return 0; |
| | |
| | /* Fail quietly if tok is an address or wildcarded entry, not a simple hostname. */ |
| | if (!tok[strspn(tok, ".0123456789")] || tok[strcspn(tok, ":/*?[")]) |
| | return 0; |
| | |
| | /* Now try forward-DNS on the token (config-specified hostname) and see if the IP matches. */ |
| | if (!(hp = gethostbyname(tok))) |
| | return 0; |
| | |
| | for (i = 0; hp->h_addr_list[i] != NULL; i++) { |
| | if (strcmp(addr, inet_ntoa(*(struct in_addr*)(hp->h_addr_list[i]))) == 0) { |
| | /* If reverse lookups are off, we'll use the conf-specified |
| | * hostname in preference to UNDETERMINED. */ |
| | if (host == undetermined_hostname) |
| | *host_ptr = strdup(tok); |
| | return 1; |
| | } |
| | } |
| | |
| | return 0; |
| } |
} |
| |
|
| static int match_binary(char *b1, char *b2, char *mask, int addrlen) | static int match_binary(const char *b1, const char *b2, const char *mask, int addrlen) |
| { |
{ |
| int i; |
int i; |
| |
|
|
Line 56 static void make_mask(char *mask, int plen, int addrle
|
Line 96 static void make_mask(char *mask, int plen, int addrle
|
| return; |
return; |
| } |
} |
| |
|
| static int match_address(char *addr, char *tok) | static int match_address(const char *addr, const char *tok) |
| { |
{ |
| char *p; |
char *p; |
| struct addrinfo hints, *resa, *rest; |
struct addrinfo hints, *resa, *rest; |
|
Line 70 static int match_address(char *addr, char *tok)
|
Line 110 static int match_address(char *addr, char *tok)
|
| #endif |
#endif |
| char mask[16]; |
char mask[16]; |
| char *a = NULL, *t = NULL; |
char *a = NULL, *t = NULL; |
| unsigned int len; |
|
| |
|
| if (!addr || !*addr) |
if (!addr || !*addr) |
| return 0; |
return 0; |
| |
|
| p = strchr(tok,'/'); |
p = strchr(tok,'/'); |
| if (p) { | if (p) |
| *p = '\0'; |
*p = '\0'; |
| len = p - tok; |
|
| } else |
|
| len = strlen(tok); |
|
| |
|
| /* Fail quietly if tok is a hostname (not an address) */ | /* Fail quietly if tok is a hostname, not an address. */ |
| if (strspn(tok, ".0123456789") != len | if (tok[strspn(tok, ".0123456789")] && strchr(tok, ':') == NULL) { |
| #ifdef INET6 | |
| && strchr(tok, ':') == NULL | |
| #endif | |
| ) { | |
| if (p) |
if (p) |
| *p = '/'; |
*p = '/'; |
| return 0; |
return 0; |
|
Line 130 static int match_address(char *addr, char *tok)
|
Line 162 static int match_address(char *addr, char *tok)
|
| break; |
break; |
| |
|
| #ifdef INET6 |
#ifdef INET6 |
| case PF_INET6: | case PF_INET6: { |
| { | |
| struct sockaddr_in6 *sin6a, *sin6t; |
struct sockaddr_in6 *sin6a, *sin6t; |
| |
|
| sin6a = (struct sockaddr_in6 *)resa->ai_addr; |
sin6a = (struct sockaddr_in6 *)resa->ai_addr; |
|
Line 143 static int match_address(char *addr, char *tok)
|
Line 174 static int match_address(char *addr, char *tok)
|
| addrlen = 16; |
addrlen = 16; |
| |
|
| #ifdef HAVE_SOCKADDR_IN6_SCOPE_ID |
#ifdef HAVE_SOCKADDR_IN6_SCOPE_ID |
| if (sin6t->sin6_scope_id && | if (sin6t->sin6_scope_id && sin6a->sin6_scope_id != sin6t->sin6_scope_id) { |
| sin6a->sin6_scope_id != sin6t->sin6_scope_id) { | |
| ret = 0; |
ret = 0; |
| goto out; |
goto out; |
| } |
} |
| #endif |
#endif |
| |
|
| break; |
break; |
| } | } |
| #endif |
#endif |
| default: |
default: |
| rprintf(FLOG, "unknown family %u\n", rest->ai_family); | rprintf(FLOG, "unknown family %u\n", rest->ai_family); |
| ret = 0; | ret = 0; |
| goto out; | goto out; |
| } |
} |
| |
|
| bits = -1; |
bits = -1; |
|
Line 210 static int match_address(char *addr, char *tok)
|
Line 240 static int match_address(char *addr, char *tok)
|
| return ret; |
return ret; |
| } |
} |
| |
|
| static int access_match(char *list, char *addr, char *host) | static int access_match(const char *list, const char *addr, const char **host_ptr) |
| { |
{ |
| char *tok; |
char *tok; |
| char *list2 = strdup(list); |
char *list2 = strdup(list); |
| |
|
| if (!list2) |
|
| out_of_memory("access_match"); |
|
| |
|
| strlower(list2); |
strlower(list2); |
| if (host) |
|
| strlower(host); |
|
| |
|
| for (tok = strtok(list2, " ,\t"); tok; tok = strtok(NULL, " ,\t")) { |
for (tok = strtok(list2, " ,\t"); tok; tok = strtok(NULL, " ,\t")) { |
| if (match_hostname(host, tok) || match_address(addr, tok)) { | if (match_hostname(host_ptr, addr, tok) || match_address(addr, tok)) { |
| free(list2); |
free(list2); |
| return 1; |
return 1; |
| } |
} |
|
Line 233 static int access_match(char *list, char *addr, char *
|
Line 258 static int access_match(char *list, char *addr, char *
|
| return 0; |
return 0; |
| } |
} |
| |
|
| int allow_access(char *addr, char *host, char *allow_list, char *deny_list) | int allow_access(const char *addr, const char **host_ptr, int i) |
| { |
{ |
| |
const char *allow_list = lp_hosts_allow(i); |
| |
const char *deny_list = lp_hosts_deny(i); |
| |
|
| if (allow_list && !*allow_list) |
if (allow_list && !*allow_list) |
| allow_list = NULL; |
allow_list = NULL; |
| if (deny_list && !*deny_list) |
if (deny_list && !*deny_list) |
| deny_list = NULL; |
deny_list = NULL; |
| |
|
| |
allow_forward_dns = lp_forward_lookup(i); |
| |
|
| /* If we match an allow-list item, we always allow access. */ |
/* If we match an allow-list item, we always allow access. */ |
| if (allow_list) { |
if (allow_list) { |
| if (access_match(allow_list, addr, host)) | if (access_match(allow_list, addr, host_ptr)) |
| return 1; |
return 1; |
| /* For an allow-list w/o a deny-list, disallow non-matches. */ |
/* For an allow-list w/o a deny-list, disallow non-matches. */ |
| if (!deny_list) |
if (!deny_list) |
|
Line 251 int allow_access(char *addr, char *host, char *allow_l
|
Line 281 int allow_access(char *addr, char *host, char *allow_l
|
| |
|
| /* If we match a deny-list item (and got past any allow-list |
/* If we match a deny-list item (and got past any allow-list |
| * items), we always disallow access. */ |
* items), we always disallow access. */ |
| if (deny_list && access_match(deny_list, addr, host)) | if (deny_list && access_match(deny_list, addr, host_ptr)) |
| return 0; |
return 0; |
| |
|
| /* Allow all other access. */ |
/* Allow all other access. */ |