diff options
Diffstat (limited to 'source/lib/access.c')
-rw-r--r-- | source/lib/access.c | 133 |
1 files changed, 68 insertions, 65 deletions
diff --git a/source/lib/access.c b/source/lib/access.c index 4e524735e49..8bf3ba19337 100644 --- a/source/lib/access.c +++ b/source/lib/access.c @@ -10,6 +10,9 @@ #include "includes.h" +/* Delimiters for lists of daemons or clients. */ +static char *sep = ", \t"; + #define FAIL (-1) #define ALLONES ((uint32)0xFFFFFFFF) @@ -60,8 +63,7 @@ static int string_match(char *tok,char *s, char *invalid_char) * return True if the string is a (host) member of the * netgroup. Return True if the token fully matches the * string. If the token is a netnumber/netmask pair, return - * True if the address is a member of the specified subnet. - */ + * True if the address is a member of the specified subnet. */ if (tok[0] == '.') { /* domain: match last fields */ if ((str_len = strlen(s)) > (tok_len = strlen(tok)) @@ -104,19 +106,19 @@ static int string_match(char *tok,char *s, char *invalid_char) } else if (strcasecmp(tok, "FAIL") == 0) { /* fail: match any */ return (FAIL); } else if (strcasecmp(tok, "LOCAL") == 0) { /* local: no dots */ - if (strchr_m(s, '.') == 0 && strcasecmp(s, "unknown") != 0) + if (strchr(s, '.') == 0 && strcasecmp(s, "unknown") != 0) return (True); } else if (!strcasecmp(tok, s)) { /* match host name or address */ return (True); } else if (tok[(tok_len = strlen(tok)) - 1] == '.') { /* network */ if (strncmp(tok, s, tok_len) == 0) return (True); - } else if ((cut = strchr_m(tok, '/')) != 0) { /* netnumber/netmask */ + } else if ((cut = strchr(tok, '/')) != 0) { /* netnumber/netmask */ if (isdigit((int)s[0]) && masked_match(tok, cut, s)) return (True); - } else if (strchr_m(tok, '*') != 0) { + } else if (strchr(tok, '*') != 0) { *invalid_char = '*'; - } else if (strchr_m(tok, '?') != 0) { + } else if (strchr(tok, '?') != 0) { *invalid_char = '?'; } return (False); @@ -152,11 +154,20 @@ token '%s' in an allow/deny hosts line.\n", invalid_char, tok )); } /* list_match - match an item against a list of tokens with exceptions */ -static int list_match(char **list,char *item, int (*match_fn)(char *, char *)) +/* (All modifications are marked with the initials "jkf") */ +static int list_match(char *list,char *item, int (*match_fn)(char *, char *)) { + char *tok; + char *listcopy; /* jkf */ int match = False; - if (!list) return False; + /* + * jkf@soton.ac.uk -- 31 August 1994 -- Stop list_match() + * overwriting the list given as its first parameter. + */ + + /* jkf -- can get called recursively with NULL list */ + listcopy = (list == 0) ? (char *)0 : strdup(list); /* * Process tokens one at a time. We have exhausted all possible matches @@ -165,30 +176,30 @@ static int list_match(char **list,char *item, int (*match_fn)(char *, char *)) * the match is affected by any exceptions. */ - for (; *list ; list++) { - if (strcasecmp(*list, "EXCEPT") == 0) /* EXCEPT: give up */ + for (tok = strtok(listcopy, sep); tok ; tok = strtok(NULL, sep)) { + if (strcasecmp(tok, "EXCEPT") == 0) /* EXCEPT: give up */ break; - if ((match = (*match_fn) (*list, item))) /* True or FAIL */ + if ((match = (*match_fn) (tok, item))) /* True or FAIL */ break; } /* Process exceptions to True or FAIL matches. */ if (match != False) { - while (*list && strcasecmp(*list, "EXCEPT")) - list++; - - for (; *list; list++) { - if ((*match_fn) (*list, item)) /* Exception Found */ - return False; + while ((tok = strtok((char *) 0, sep)) && strcasecmp(tok, "EXCEPT")) + /* VOID */ ; + if (tok == 0 || list_match((char *) 0, item, match_fn) == False) { + SAFE_FREE(listcopy); /* jkf */ + return (match); } } - return (match); + SAFE_FREE(listcopy); /* jkf */ + return (False); } /* return true if access should be allowed */ -static BOOL allow_access_internal(char **deny_list,char **allow_list, +BOOL allow_access(char *deny_list,char *allow_list, char *cname,char *caddr) { char *client[2]; @@ -227,12 +238,12 @@ static BOOL allow_access_internal(char **deny_list,char **allow_list, if (!allow_list || *allow_list == 0) return(!list_match(deny_list,(char *)client,client_match)); - /* if there are both types of list then allow all hosts on the + /* if there are both type of list then allow all hosts on the allow list */ if (list_match(allow_list,(char *)client,client_match)) return (True); - /* if there are both types of list and it's not on the allow then + /* if there are both type of list and it's not on the allow then allow it if its not on the deny */ if (list_match(deny_list,(char *)client,client_match)) return (False); @@ -240,99 +251,91 @@ static BOOL allow_access_internal(char **deny_list,char **allow_list, return (True); } -/* return true if access should be allowed */ -BOOL allow_access(char **deny_list,char **allow_list, - const char *cname, const char *caddr) -{ - BOOL ret; - - char *nc_cname = smb_xstrdup(cname); - char *nc_caddr = smb_xstrdup(caddr); - - ret = allow_access_internal(deny_list, allow_list, nc_cname, nc_caddr); - - SAFE_FREE(nc_cname); - SAFE_FREE(nc_caddr); - return ret; -} - /* return true if the char* contains ip addrs only. Used to avoid gethostbyaddr() calls */ -static BOOL only_ipaddrs_in_list(char** list) +static BOOL only_ipaddrs_in_list(const char* list) { BOOL only_ip = True; - - if (!list) return True; + char *listcopy, + *tok; - for (; *list ; list++) + listcopy = strdup(list); + + for (tok = strtok(listcopy, sep); tok ; tok = strtok(NULL, sep)) { /* factor out the special strings */ - if (!strcasecmp(*list, "ALL") || !strcasecmp(*list, "FAIL") || - !strcasecmp(*list, "EXCEPT")) + if (!strcasecmp(tok, "ALL") || !strcasecmp(tok, "FAIL") || + !strcasecmp(tok, "EXCEPT")) { continue; } - if (!is_ipaddress(*list)) + if (!is_ipaddress(tok)) { - char *p; /* * if we failed, make sure that it was not because the token * was a network/netmask pair. Only network/netmask pairs * have a '/' in them */ - if ((p=strchr_m(*list, '/')) == NULL) + if (strchr(tok, '/') == NULL) { only_ip = False; - DEBUG(3,("only_ipaddrs_in_list: list has non-ip address (%s)\n", *list)); + DEBUG(3,("only_ipaddrs_in_list: list [%s] has non-ip address %s\n", list, tok)); break; } } } + SAFE_FREE(listcopy); + return only_ip; } /* return true if access should be allowed to a service for a socket */ -BOOL check_access(int sock, char **allow_list, char **deny_list) +BOOL check_access(int sock, char *allow_list, char *deny_list) { BOOL ret = False; BOOL only_ip = False; + char *deny = NULL; + char *allow = NULL; - if ((!deny_list || *deny_list==0) && (!allow_list || *allow_list==0)) - { + 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 (!ret) { /* bypass gethostbyaddr() calls if the lists only contain IP addrs */ - if (only_ipaddrs_in_list(allow_list) && only_ipaddrs_in_list(deny_list)) - { + 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_list,allow_list, "", get_socket_addr(sock)); - } - else - { + 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_list,allow_list, get_socket_name(sock), + ret = allow_access(deny,allow, get_socket_name(sock), get_socket_addr(sock)); } - if (ret) - { + if (ret) { DEBUG(2,("Allowed connection from %s (%s)\n", only_ip ? "" : get_socket_name(sock), get_socket_addr(sock))); - } - else - { + } 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); } |