summaryrefslogtreecommitdiff
path: root/match.c
diff options
context:
space:
mode:
Diffstat (limited to 'match.c')
-rw-r--r--match.c115
1 files changed, 100 insertions, 15 deletions
diff --git a/match.c b/match.c
index c35e3289..3a8fa9d7 100644
--- a/match.c
+++ b/match.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: match.c,v 1.29 2013/11/20 20:54:10 deraadt Exp $ */
+/* $OpenBSD: match.c,v 1.41 2019/11/13 04:47:52 deraadt Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -42,9 +42,12 @@
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
#include "xmalloc.h"
#include "match.h"
+#include "misc.h"
/*
* Returns true if the given string matches the pattern (which may contain ?
@@ -115,15 +118,13 @@ match_pattern(const char *s, const char *pattern)
* indicate negation). Returns -1 if negation matches, 1 if there is
* a positive match, 0 if there is no match at all.
*/
-
int
-match_pattern_list(const char *string, const char *pattern, u_int len,
- int dolower)
+match_pattern_list(const char *string, const char *pattern, int dolower)
{
char sub[1024];
int negated;
int got_positive;
- u_int i, subi;
+ u_int i, subi, len = strlen(pattern);
got_positive = 0;
for (i = 0; i < len;) {
@@ -147,7 +148,7 @@ match_pattern_list(const char *string, const char *pattern, u_int len,
if (subi >= sizeof(sub) - 1)
return 0;
- /* If the subpattern was terminated by a comma, skip the comma. */
+ /* If the subpattern was terminated by a comma, then skip it. */
if (i < len && pattern[i] == ',')
i++;
@@ -170,6 +171,19 @@ match_pattern_list(const char *string, const char *pattern, u_int len,
return got_positive;
}
+/* Match a list representing users or groups. */
+int
+match_usergroup_pattern_list(const char *string, const char *pattern)
+{
+#ifdef HAVE_CYGWIN
+ /* Windows usernames may be Unicode and are not case sensitive */
+ return cygwin_ug_match_pattern_list(string, pattern);
+#else
+ /* Case sensitive match */
+ return match_pattern_list(string, pattern, 0);
+#endif
+}
+
/*
* Tries to match the host name (which must be in all lowercase) against the
* comma-separated sequence of subpatterns (each possibly preceded by ! to
@@ -177,9 +191,15 @@ match_pattern_list(const char *string, const char *pattern, u_int len,
* a positive match, 0 if there is no match at all.
*/
int
-match_hostname(const char *host, const char *pattern, u_int len)
+match_hostname(const char *host, const char *pattern)
{
- return match_pattern_list(host, pattern, len, 1);
+ char *hostcopy = xstrdup(host);
+ int r;
+
+ lowercase(hostcopy);
+ r = match_pattern_list(hostcopy, pattern, 1);
+ free(hostcopy);
+ return r;
}
/*
@@ -193,14 +213,13 @@ match_host_and_ip(const char *host, const char *ipaddr,
{
int mhost, mip;
- /* error in ipaddr match */
if ((mip = addr_match_list(ipaddr, patterns)) == -2)
- return -1;
- else if (mip == -1) /* negative ip address match */
- return 0;
+ return -1; /* error in ipaddr match */
+ else if (host == NULL || ipaddr == NULL || mip == -1)
+ return 0; /* negative ip address match, or testing pattern */
/* negative hostname match */
- if ((mhost = match_hostname(host, patterns, strlen(patterns))) == -1)
+ if ((mhost = match_hostname(host, patterns)) == -1)
return 0;
/* no match at all */
if (mhost == 0 && mip == 0)
@@ -209,7 +228,9 @@ match_host_and_ip(const char *host, const char *ipaddr,
}
/*
- * match user, user@host_or_ip, user@host_or_ip_list against pattern
+ * Match user, user@host_or_ip, user@host_or_ip_list against pattern.
+ * If user, host and ipaddr are all NULL then validate pattern/
+ * Returns -1 on invalid pattern, 0 on no match, 1 on match.
*/
int
match_user(const char *user, const char *host, const char *ipaddr,
@@ -218,7 +239,15 @@ match_user(const char *user, const char *host, const char *ipaddr,
char *p, *pat;
int ret;
- if ((p = strchr(pattern,'@')) == NULL)
+ /* test mode */
+ if (user == NULL && host == NULL && ipaddr == NULL) {
+ if ((p = strchr(pattern, '@')) != NULL &&
+ match_host_and_ip(NULL, NULL, p + 1) < 0)
+ return -1;
+ return 0;
+ }
+
+ if ((p = strchr(pattern, '@')) == NULL)
return match_pattern(user, pattern);
pat = xstrdup(pattern);
@@ -277,3 +306,59 @@ match_list(const char *client, const char *server, u_int *next)
free(s);
return NULL;
}
+
+/*
+ * Filter proposal using pattern-list filter.
+ * "blacklist" determines sense of filter:
+ * non-zero indicates that items matching filter should be excluded.
+ * zero indicates that only items matching filter should be included.
+ * returns NULL on allocation error, otherwise caller must free result.
+ */
+static char *
+filter_list(const char *proposal, const char *filter, int blacklist)
+{
+ size_t len = strlen(proposal) + 1;
+ char *fix_prop = malloc(len);
+ char *orig_prop = strdup(proposal);
+ char *cp, *tmp;
+ int r;
+
+ if (fix_prop == NULL || orig_prop == NULL) {
+ free(orig_prop);
+ free(fix_prop);
+ return NULL;
+ }
+
+ tmp = orig_prop;
+ *fix_prop = '\0';
+ while ((cp = strsep(&tmp, ",")) != NULL) {
+ r = match_pattern_list(cp, filter, 0);
+ if ((blacklist && r != 1) || (!blacklist && r == 1)) {
+ if (*fix_prop != '\0')
+ strlcat(fix_prop, ",", len);
+ strlcat(fix_prop, cp, len);
+ }
+ }
+ free(orig_prop);
+ return fix_prop;
+}
+
+/*
+ * Filters a comma-separated list of strings, excluding any entry matching
+ * the 'filter' pattern list. Caller must free returned string.
+ */
+char *
+match_filter_blacklist(const char *proposal, const char *filter)
+{
+ return filter_list(proposal, filter, 1);
+}
+
+/*
+ * Filters a comma-separated list of strings, including only entries matching
+ * the 'filter' pattern list. Caller must free returned string.
+ */
+char *
+match_filter_whitelist(const char *proposal, const char *filter)
+{
+ return filter_list(proposal, filter, 0);
+}