#include "includes.h"
static char *sep = ", \t";
#define FAIL (-1)
static int masked_match(char *tok, char *slash, char *s)
{
uint32 net;
uint32 mask;
uint32 addr;
if ((addr = interpret_addr(s)) == INADDR_NONE)
return (False);
*slash = 0;
net = interpret_addr(tok);
*slash = '/';
if (net == INADDR_NONE ||
(mask = interpret_addr(slash + 1)) == INADDR_NONE) {
DEBUG(0,("access: bad net/mask access control: %s\n", tok));
return (False);
}
return ((addr & mask) == net);
}
static int string_match(char *tok,char *s, char *invalid_char)
{
size_t tok_len;
size_t str_len;
char *cut;
*invalid_char = '\0';
if (tok[0] == '.') {
if ((str_len = strlen(s)) > (tok_len = strlen(tok))
&& strcasecmp(tok, s + str_len - tok_len) == 0)
return (True);
} else if (tok[0] == '@') {
#ifdef HAVE_NETGROUP
static char *mydomain = NULL;
char *hostname = NULL;
BOOL netgroup_ok = False;
if (!mydomain) yp_get_default_domain(&mydomain);
if (!mydomain) {
DEBUG(0,("Unable to get default yp domain.\n"));
return False;
}
if (!(hostname = strdup(s))) {
DEBUG(1,("out of memory for strdup!\n"));
return False;
}
netgroup_ok = innetgr(tok + 1, hostname, (char *) 0, mydomain);
DEBUG(5,("looking for %s of domain %s in netgroup %s gave %s\n",
hostname,
mydomain,
tok+1,
BOOLSTR(netgroup_ok)));
SAFE_FREE(hostname);
if (netgroup_ok) return(True);
#else
DEBUG(0,("access: netgroup support is not configured\n"));
return (False);
#endif
} else if (strcasecmp(tok, "ALL") == 0) {
return (True);
} else if (strcasecmp(tok, "FAIL") == 0) {
return (FAIL);
} else if (strcasecmp(tok, "LOCAL") == 0) {
if (strchr(s, '.') == 0 && strcasecmp(s, "unknown") != 0)
return (True);
} else if (!strcasecmp(tok, s)) {
return (True);
} else if (tok[(tok_len = strlen(tok)) - 1] == '.') {
if (strncmp(tok, s, tok_len) == 0)
return (True);
} else if ((cut = strchr(tok, '/')) != 0) {
if (isdigit((int)s[0]) && masked_match(tok, cut, s))
return (True);
} else if (strchr(tok, '*') != 0) {
*invalid_char = '*';
} else if (strchr(tok, '?') != 0) {
*invalid_char = '?';
}
return (False);
}
static int client_match(char *tok,char *item)
{
char **client = (char **)item;
int match;
char invalid_char = '\0';
if ((match = string_match(tok, client[1], &invalid_char)) == 0) {
if(invalid_char)
DEBUG(0,("client_match: address match failing due to invalid character '%c' found in \
token '%s' in an allow/deny hosts line.\n", invalid_char, tok ));
if (client[0][0] != 0)
match = string_match(tok, client[0], &invalid_char);
if(invalid_char)
DEBUG(0,("client_match: address match failing due to invalid character '%c' found in \
token '%s' in an allow/deny hosts line.\n", invalid_char, tok ));
}
return (match);
}
static int list_match(char *list,char *item, int (*match_fn)(char *, char *))
{
char *tok;
char *listcopy;
int match = False;
listcopy = (list == 0) ? (char *)0 : strdup(list);
for (tok = strtok(listcopy, sep); tok ; tok = strtok(NULL, sep)) {
if (strcasecmp(tok, "EXCEPT") == 0)
break;
if ((match = (*match_fn) (tok, item)))
break;
}
if (match != False) {
while ((tok = strtok((char *) 0, sep)) && strcasecmp(tok, "EXCEPT"))
;
if (tok == 0 || list_match((char *) 0, item, match_fn) == False) {
SAFE_FREE(listcopy);
return (match);
}
}
SAFE_FREE(listcopy);
return (False);
}
BOOL allow_access(char *deny_list,char *allow_list,
char *cname,char *caddr)
{
char *client[2];
client[0] = cname;
client[1] = caddr;
if (strcmp(caddr, "127.0.0.1") == 0) {
if (deny_list &&
list_match(deny_list,(char *)client,client_match) &&
(!allow_list ||
!list_match(allow_list,(char *)client, client_match))) {
return False;
}
return True;
}
if ((!deny_list || *deny_list == 0) &&
(!allow_list || *allow_list == 0)) {
return(True);
}
if (!deny_list || *deny_list == 0)
return(list_match(allow_list,(char *)client,client_match));
if (!allow_list || *allow_list == 0)
return(!list_match(deny_list,(char *)client,client_match));
if (list_match(allow_list,(char *)client,client_match))
return (True);
if (list_match(deny_list,(char *)client,client_match))
return (False);
return (True);
}
static BOOL only_ipaddrs_in_list(const char* list)
{
BOOL only_ip = True;
char *listcopy,
*tok;
listcopy = strdup(list);
for (tok = strtok(listcopy, sep); tok ; tok = strtok(NULL, sep))
{
if (!strcasecmp(tok, "ALL") || !strcasecmp(tok, "FAIL") ||
!strcasecmp(tok, "EXCEPT"))
{
continue;
}
if (!is_ipaddress(tok))
{
if (strchr(tok, '/') == NULL)
{
only_ip = False;
DEBUG(3,("only_ipaddrs_in_list: list [%s] has non-ip address %s\n", list, tok));
break;
}
}
}
SAFE_FREE(listcopy);
return only_ip;
}
BOOL check_access(int sock, char *allow_list, char *deny_list)
{
BOOL ret = False;
BOOL only_ip = False;
char *deny = NULL;
char *allow = NULL;
DEBUG(10,("check_access: allow = %s, deny = %s\n",
allow_list ? allow_list : "NULL",
deny_list ? deny_list : "NULL"));
if (deny_list)
deny = strdup(deny_list);
if (allow_list)
allow = strdup(allow_list);
if ((!deny || *deny==0) && (!allow || *allow==0))
ret = True;
if (!ret) {
if (only_ipaddrs_in_list(allow) && only_ipaddrs_in_list(deny)) {
only_ip = True;
DEBUG (3, ("check_access: no hostnames in host allow/deny list.\n"));
ret = allow_access(deny,allow, "", get_socket_addr(sock));
} else {
DEBUG (3, ("check_access: hostnames in host allow/deny list.\n"));
ret = allow_access(deny,allow, get_socket_name(sock),
get_socket_addr(sock));
}
if (ret) {
DEBUG(2,("Allowed connection from %s (%s)\n",
only_ip ? "" : get_socket_name(sock),
get_socket_addr(sock)));
} else {
DEBUG(0,("Denied connection from %s (%s)\n",
only_ip ? "" : get_socket_name(sock),
get_socket_addr(sock)));
}
}
SAFE_FREE(deny);
SAFE_FREE(allow);
return(ret);
}