Changeset View
Changeset View
Standalone View
Standalone View
match.c
/* $OpenBSD: match.c,v 1.39 2019/03/06 22:14:23 dtucker Exp $ */ | /* $OpenBSD: match.c,v 1.42 2020/07/05 23:59:45 djm Exp $ */ | ||||
/* | /* | ||||
* Author: Tatu Ylonen <ylo@cs.hut.fi> | * Author: Tatu Ylonen <ylo@cs.hut.fi> | ||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | ||||
* All rights reserved | * All rights reserved | ||||
* Simple pattern matching, with '*' and '?' as wildcards. | * Simple pattern matching, with '*' and '?' as wildcards. | ||||
* | * | ||||
* As far as I am concerned, the code I have written for this software | * As far as I am concerned, the code I have written for this software | ||||
* can be used freely for any purpose. Any derived versions of this | * can be used freely for any purpose. Any derived versions of this | ||||
Show All 27 Lines | |||||
#include "includes.h" | #include "includes.h" | ||||
#include <sys/types.h> | #include <sys/types.h> | ||||
#include <ctype.h> | #include <ctype.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <stdarg.h> | |||||
#include <stdio.h> | #include <stdio.h> | ||||
#include "xmalloc.h" | #include "xmalloc.h" | ||||
#include "match.h" | #include "match.h" | ||||
#include "misc.h" | #include "misc.h" | ||||
/* | /* | ||||
* Returns true if the given string matches the pattern (which may contain ? | * Returns true if the given string matches the pattern (which may contain ? | ||||
▲ Show 20 Lines • Show All 120 Lines • ▼ Show 20 Lines | |||||
/* Match a list representing users or groups. */ | /* Match a list representing users or groups. */ | ||||
int | int | ||||
match_usergroup_pattern_list(const char *string, const char *pattern) | match_usergroup_pattern_list(const char *string, const char *pattern) | ||||
{ | { | ||||
#ifdef HAVE_CYGWIN | #ifdef HAVE_CYGWIN | ||||
/* Windows usernames may be Unicode and are not case sensitive */ | /* Windows usernames may be Unicode and are not case sensitive */ | ||||
return cygwin_ug_match_pattern_list(string, pattern); | return cygwin_ug_match_pattern_list(string, pattern); | ||||
#else | #else | ||||
/* Case insensitive match */ | /* Case sensitive match */ | ||||
return match_pattern_list(string, pattern, 0); | return match_pattern_list(string, pattern, 0); | ||||
#endif | #endif | ||||
} | } | ||||
/* | /* | ||||
* Tries to match the host name (which must be in all lowercase) against the | * Tries to match the host name (which must be in all lowercase) against the | ||||
* comma-separated sequence of subpatterns (each possibly preceded by ! to | * comma-separated sequence of subpatterns (each possibly preceded by ! to | ||||
* indicate negation). Returns -1 if negation matches, 1 if there is | * indicate negation). Returns -1 if negation matches, 1 if there is | ||||
▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | match_user(const char *user, const char *host, const char *ipaddr, | ||||
/* test mode */ | /* test mode */ | ||||
if (user == NULL && host == NULL && ipaddr == NULL) { | if (user == NULL && host == NULL && ipaddr == NULL) { | ||||
if ((p = strchr(pattern, '@')) != NULL && | if ((p = strchr(pattern, '@')) != NULL && | ||||
match_host_and_ip(NULL, NULL, p + 1) < 0) | match_host_and_ip(NULL, NULL, p + 1) < 0) | ||||
return -1; | return -1; | ||||
return 0; | return 0; | ||||
} | } | ||||
if ((p = strchr(pattern,'@')) == NULL) | if ((p = strchr(pattern, '@')) == NULL) | ||||
return match_pattern(user, pattern); | return match_pattern(user, pattern); | ||||
pat = xstrdup(pattern); | pat = xstrdup(pattern); | ||||
p = strchr(pat, '@'); | p = strchr(pat, '@'); | ||||
*p++ = '\0'; | *p++ = '\0'; | ||||
if ((ret = match_pattern(user, pat)) == 1) | if ((ret = match_pattern(user, pat)) == 1) | ||||
ret = match_host_and_ip(host, ipaddr, p); | ret = match_host_and_ip(host, ipaddr, p); | ||||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | if (next != NULL) | ||||
*next = strlen(c); | *next = strlen(c); | ||||
free(c); | free(c); | ||||
free(s); | free(s); | ||||
return NULL; | return NULL; | ||||
} | } | ||||
/* | /* | ||||
* Filter proposal using pattern-list filter. | * Filter proposal using pattern-list filter. | ||||
* "blacklist" determines sense of filter: | * "denylist" determines sense of filter: | ||||
* non-zero indicates that items matching filter should be excluded. | * non-zero indicates that items matching filter should be excluded. | ||||
* zero indicates that only items matching filter should be included. | * zero indicates that only items matching filter should be included. | ||||
* returns NULL on allocation error, otherwise caller must free result. | * returns NULL on allocation error, otherwise caller must free result. | ||||
*/ | */ | ||||
static char * | static char * | ||||
filter_list(const char *proposal, const char *filter, int blacklist) | filter_list(const char *proposal, const char *filter, int denylist) | ||||
{ | { | ||||
size_t len = strlen(proposal) + 1; | size_t len = strlen(proposal) + 1; | ||||
char *fix_prop = malloc(len); | char *fix_prop = malloc(len); | ||||
char *orig_prop = strdup(proposal); | char *orig_prop = strdup(proposal); | ||||
char *cp, *tmp; | char *cp, *tmp; | ||||
int r; | int r; | ||||
if (fix_prop == NULL || orig_prop == NULL) { | if (fix_prop == NULL || orig_prop == NULL) { | ||||
free(orig_prop); | free(orig_prop); | ||||
free(fix_prop); | free(fix_prop); | ||||
return NULL; | return NULL; | ||||
} | } | ||||
tmp = orig_prop; | tmp = orig_prop; | ||||
*fix_prop = '\0'; | *fix_prop = '\0'; | ||||
while ((cp = strsep(&tmp, ",")) != NULL) { | while ((cp = strsep(&tmp, ",")) != NULL) { | ||||
r = match_pattern_list(cp, filter, 0); | r = match_pattern_list(cp, filter, 0); | ||||
if ((blacklist && r != 1) || (!blacklist && r == 1)) { | if ((denylist && r != 1) || (!denylist && r == 1)) { | ||||
if (*fix_prop != '\0') | if (*fix_prop != '\0') | ||||
strlcat(fix_prop, ",", len); | strlcat(fix_prop, ",", len); | ||||
strlcat(fix_prop, cp, len); | strlcat(fix_prop, cp, len); | ||||
} | } | ||||
} | } | ||||
free(orig_prop); | free(orig_prop); | ||||
return fix_prop; | return fix_prop; | ||||
} | } | ||||
/* | /* | ||||
* Filters a comma-separated list of strings, excluding any entry matching | * Filters a comma-separated list of strings, excluding any entry matching | ||||
* the 'filter' pattern list. Caller must free returned string. | * the 'filter' pattern list. Caller must free returned string. | ||||
*/ | */ | ||||
char * | char * | ||||
match_filter_blacklist(const char *proposal, const char *filter) | match_filter_denylist(const char *proposal, const char *filter) | ||||
{ | { | ||||
return filter_list(proposal, filter, 1); | return filter_list(proposal, filter, 1); | ||||
} | } | ||||
/* | /* | ||||
* Filters a comma-separated list of strings, including only entries matching | * Filters a comma-separated list of strings, including only entries matching | ||||
* the 'filter' pattern list. Caller must free returned string. | * the 'filter' pattern list. Caller must free returned string. | ||||
*/ | */ | ||||
char * | char * | ||||
match_filter_whitelist(const char *proposal, const char *filter) | match_filter_allowlist(const char *proposal, const char *filter) | ||||
{ | { | ||||
return filter_list(proposal, filter, 0); | return filter_list(proposal, filter, 0); | ||||
} | } |