version 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. */ |