File openssh-6.6p1-verify_CIDR_address_ranges.patch of Package openssh.10219

# HG changeset patch
# Parent  7c087cbaa12c93fbdb812254f3050bf84df18783
Check for invalid CIDR adress masks.
bsc#1005893

upstream commit 010359b32659f455fddd2bd85fd7cc4d7a3b994a (7.4)
Author: djm@openbsd.org <djm@openbsd.org>
Date:   Sun Nov 6 05:46:37 2016 +0000

    upstream commit

    Validate address ranges for AllowUser/DenyUsers at
    configuration load time and refuse to accept bad ones. It was previously
    possible to specify invalid CIDR address ranges (e.g. djm@127.1.2.3/55) and
    these would always match.

    Thanks to Laurence Parry for a detailed bug report. ok markus (for
    a previous diff version)

    Upstream-ID: 9dfcdd9672b06e65233ea4434c38226680d40bfb

diff --git a/openssh-6.6p1/auth.c b/openssh-6.6p1/auth.c
--- a/openssh-6.6p1/auth.c
+++ b/openssh-6.6p1/auth.c
@@ -94,16 +94,17 @@ int auth_debug_init;
  * Otherwise true is returned.
  */
 int
 allowed_user(struct passwd * pw)
 {
 	struct stat st;
 	const char *hostname = NULL, *ipaddr = NULL, *passwd = NULL;
 	u_int i;
+	int r;
 #ifdef USE_SHADOW
 	struct spwd *spw = NULL;
 #endif
 
 	/* Shouldn't be called if pw is NULL, but better safe than sorry... */
 	if (!pw || !pw->pw_name)
 		return 0;
 
@@ -182,31 +183,41 @@ allowed_user(struct passwd * pw)
 	if (options.num_deny_users > 0 || options.num_allow_users > 0 ||
 	    options.num_deny_groups > 0 || options.num_allow_groups > 0) {
 		hostname = get_canonical_hostname(options.use_dns);
 		ipaddr = get_remote_ipaddr();
 	}
 
 	/* Return false if user is listed in DenyUsers */
 	if (options.num_deny_users > 0) {
-		for (i = 0; i < options.num_deny_users; i++)
-			if (match_user(pw->pw_name, hostname, ipaddr,
-			    options.deny_users[i])) {
+		for (i = 0; i < options.num_deny_users; i++) {
+			r = match_user(pw->pw_name, hostname, ipaddr,
+			    options.deny_users[i]);
+			if (r < 0) {
+				fatal("Invalid DenyUsers pattern \"%.100s\"",
+				    options.deny_users[i]);
+			} else if (r != 0) {
 				logit("User %.100s from %.100s not allowed "
 				    "because listed in DenyUsers",
 				    pw->pw_name, hostname);
 				return 0;
 			}
+		}
 	}
 	/* Return false if AllowUsers isn't empty and user isn't listed there */
 	if (options.num_allow_users > 0) {
-		for (i = 0; i < options.num_allow_users; i++)
-			if (match_user(pw->pw_name, hostname, ipaddr,
-			    options.allow_users[i]))
+		for (i = 0; i < options.num_allow_users; i++) {
+			r = match_user(pw->pw_name, hostname, ipaddr,
+			    options.allow_users[i]);
+			if (r < 0) {
+				fatal("Invalid AllowUsers pattern \"%.100s\"",
+				    options.allow_users[i]);
+			} else if (r == 1)
 				break;
+		}
 		/* i < options.num_allow_users iff we break for loop */
 		if (i >= options.num_allow_users) {
 			logit("User %.100s from %.100s not allowed because "
 			    "not listed in AllowUsers", pw->pw_name, hostname);
 			return 0;
 		}
 	}
 	if (options.num_deny_groups > 0 || options.num_allow_groups > 0) {
diff --git a/openssh-6.6p1/match.c b/openssh-6.6p1/match.c
--- a/openssh-6.6p1/match.c
+++ b/openssh-6.6p1/match.c
@@ -190,39 +190,49 @@ match_hostname(const char *host, const c
 int
 match_host_and_ip(const char *host, const char *ipaddr,
     const char *patterns)
 {
 	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)
 		return 0;
 	/* no match at all */
 	if (mhost == 0 && mip == 0)
 		return 0;
 	return 1;
 }
 
 /*
- * 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,
     const char *pattern)
 {
 	char *p, *pat;
 	int ret;
 
+	/* 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);
 	p = strchr(pat, '@');
 	*p++ = '\0';
 
 	if ((ret = match_pattern(user, pat)) == 1)
diff --git a/openssh-6.6p1/servconf.c b/openssh-6.6p1/servconf.c
--- a/openssh-6.6p1/servconf.c
+++ b/openssh-6.6p1/servconf.c
@@ -1296,28 +1296,34 @@ process_server_config_line(ServerOptions
 		multistate_ptr = multistate_privsep;
 		goto parse_multistate;
 
 	case sAllowUsers:
 		while ((arg = strdelim(&cp)) && *arg != '\0') {
 			if (options->num_allow_users >= MAX_ALLOW_USERS)
 				fatal("%s line %d: too many allow users.",
 				    filename, linenum);
+			if (match_user(NULL, NULL, NULL, arg) == -1)
+				fatal("%s line %d: invalid AllowUsers pattern: "
+				    "\"%.100s\"", filename, linenum, arg);
 			if (!*activep)
 				continue;
 			options->allow_users[options->num_allow_users++] =
 			    xstrdup(arg);
 		}
 		break;
 
 	case sDenyUsers:
 		while ((arg = strdelim(&cp)) && *arg != '\0') {
 			if (options->num_deny_users >= MAX_DENY_USERS)
 				fatal("%s line %d: too many deny users.",
 				    filename, linenum);
+			if (match_user(NULL, NULL, NULL, arg) == -1)
+				fatal("%s line %d: invalid DenyUsers pattern: "
+				    "\"%.100s\"", filename, linenum, arg);
 			if (!*activep)
 				continue;
 			options->deny_users[options->num_deny_users++] =
 			    xstrdup(arg);
 		}
 		break;
 
 	case sAllowGroups:
openSUSE Build Service is sponsored by