Patch to sshd match

Alain Williams addw at phcomp.co.uk
Mon Nov 12 04:41:02 EST 2007


Please find attached a patch against openssh-4.7p1

It extends the Match in sshd_config. The point is that it is sometimes
easier (and more secure) to match on NOT something.

A criterium may be preceded by ! which inverts the condition, thus:
    Match !Group sysadmins
                   ForceCommand /usr/bin/sftp
forces use of sftp on any user who is not a system administrator.

A !! has the same effect as no ! - but I didn't document that.



I am looking at sftp, extend it:
* read a config file - optionally
* commands to restrict a user to their $HOME.

-- 
Alain Williams
Linux Consultant - Mail systems, Web sites, Networking, Programmer, IT Lecturer.
+44 (0) 787 668 0256  http://www.phcomp.co.uk/
Parliament Hill Computers Ltd. Registration Information: http://www.phcomp.co.uk/contact.php
Chairman of UKUUG: http://www.ukuug.org/
#include <std_disclaimer.h>
-------------- next part --------------
--- servconf.c.orig	2007-05-20 06:03:16.000000000 +0100
+++ servconf.c	2007-11-11 17:21:38.000000000 +0000
@@ -498,13 +498,21 @@
  *		PermittedChannelRequests session,forwarded-tcpip
  */
 
+/* Check if user is in the comma separated group list grps. Invert condition if not.
+ * line is the config file line.
+ * Return:
+ * 1	match
+ * 0	not match
+ * -1	error
+ */
 static int
-match_cfg_line_group(const char *grps, int line, const char *user)
+match_cfg_line_group(const char *grps, int line, const char *user, int not)
 {
 	int result = 0;
 	u_int ngrps = 0;
 	char *arg, *p, *cp, *grplist[MAX_MATCH_GROUPS];
 	struct passwd *pw;
+	char* notstr = not ? "!" : "";
 
 	/*
 	 * Even if we do not have a user yet, we still need to check for
@@ -529,12 +537,12 @@
 	} else if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
 		debug("Can't Match group because user %.100s not in any group "
 		    "at line %d", user, line);
-	} else if (ga_match(grplist, ngrps) != 1) {
-		debug("user %.100s does not match group %.100s at line %d",
-		    user, arg, line);
+	} else if (ga_match(grplist, ngrps) == not) {
+		debug("user %.100s does not match %sgroup %.100s at line %d",
+		    user, notstr, arg, line);
 	} else {
-		debug("user %.100s matched group %.100s at line %d", user,
-		    arg, line);
+		debug("user %.100s matched %sgroup %.100s at line %d", user,
+		    notstr, arg, line);
 		result = 1;
 	}
 out:
@@ -550,6 +558,8 @@
 	int result = 1;
 	char *arg, *attrib, *cp = *condition;
 	size_t len;
+	int not = 0;
+	char* notstr;
 
 	if (user == NULL)
 		debug3("checking syntax for 'Match %s'", cp);
@@ -559,6 +569,13 @@
 		    address ? address : "(null)");
 
 	while ((attrib = strdelim(&cp)) && *attrib != '\0') {
+		while(*attrib == '!') {		/* Parse a '!' to mean invert the condition */
+			not ^= 1;
+			attrib++;
+		}
+		if(*attrib == '\0')		/* Maybe a ! was followed by white space */
+			continue;
+		notstr = not ? "!" : "";	/* For debug */
 		if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
 			error("Missing Match criteria for %s", attrib);
 			return -1;
@@ -567,15 +584,16 @@
 		if (strcasecmp(attrib, "user") == 0) {
 			if (!user) {
 				result = 0;
+				not = 0;
 				continue;
 			}
-			if (match_pattern_list(user, arg, len, 0) != 1)
+			if (match_pattern_list(user, arg, len, 0) == not)
 				result = 0;
 			else
-				debug("user %.100s matched 'User %.100s' at "
-				    "line %d", user, arg, line);
+				debug("user %.100s matched '%sUser %.100s' at "
+				    "line %d", user, notstr, arg, line);
 		} else if (strcasecmp(attrib, "group") == 0) {
-			switch (match_cfg_line_group(arg, line, user)) {
+			switch (match_cfg_line_group(arg, line, user, not)) {
 			case -1:
 				return -1;
 			case 0:
@@ -584,27 +602,30 @@
 		} else if (strcasecmp(attrib, "host") == 0) {
 			if (!host) {
 				result = 0;
+				not = 0;
 				continue;
 			}
-			if (match_hostname(host, arg, len) != 1)
+			if (match_hostname(host, arg, len) == not)
 				result = 0;
 			else
-				debug("connection from %.100s matched 'Host "
-				    "%.100s' at line %d", host, arg, line);
+				debug("connection from %.100s matched '%sHost "
+				    "%.100s' at line %d", host, notstr, arg, line);
 		} else if (strcasecmp(attrib, "address") == 0) {
 			if (!address) {
 				result = 0;
+				not = 0;
 				continue;
 			}
-			if (match_hostname(address, arg, len) != 1)
+			if (match_hostname(address, arg, len) == not)
 				result = 0;
 			else
-				debug("connection from %.100s matched 'Address "
-				    "%.100s' at line %d", address, arg, line);
+				debug("connection from %.100s matched '%sAddress "
+				    "%.100s' at line %d", address, notstr, arg, line);
 		} else {
 			error("Unsupported Match attribute %s", attrib);
 			return -1;
 		}
+		not = 0;	/* Reset for next condition */
 	}
 	if (user != NULL)
 		debug3("match %sfound", result ? "" : "not ");
--- sshd_config.5.orig	2007-06-11 05:07:13.000000000 +0100
+++ sshd_config.5	2007-11-11 17:17:16.000000000 +0000
@@ -529,6 +529,16 @@
 .Cm X11Forwarding ,
 and
 .Cm X11UseLocalHost .
+.Pp
+A criterium may be preceded by
+.Cm !
+which inverts the condition, thus:
+.pP
+.Bl -tag -width Ds -compact -offset indent
+.It Match !Group sysadmins
+.It ForceCommand /usr/bin/sftp
+.El
+forces use of sftp on any user who is not a system administrator.
 .It Cm MaxAuthTries
 Specifies the maximum number of authentication attempts permitted per
 connection.


More information about the openssh-unix-dev mailing list