- djm@cvs.openbsd.org 2008/07/04 03:44:59
     [servconf.c groupaccess.h groupaccess.c]
     support negation of groups in "Match group" block (bz#1315); ok dtucker@
diff --git a/ChangeLog b/ChangeLog
index dad3f2a..56ee5d4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -12,6 +12,9 @@
    - otto@cvs.openbsd.org 2008/07/03 21:46:58
      [auth2-pubkey.c]
      avoid nasty double free; ok dtucker@ djm@
+   - djm@cvs.openbsd.org 2008/07/04 03:44:59
+     [servconf.c groupaccess.h groupaccess.c]
+     support negation of groups in "Match group" block (bz#1315); ok dtucker@
 
 20080702
  - (dtucker) OpenBSD CVS Sync
@@ -4547,4 +4550,4 @@
    OpenServer 6 and add osr5bigcrypt support so when someone migrates
    passwords between UnixWare and OpenServer they will still work. OK dtucker@
 
-$Id: ChangeLog,v 1.5051 2008/07/04 02:54:25 dtucker Exp $
+$Id: ChangeLog,v 1.5052 2008/07/04 03:51:12 dtucker Exp $
diff --git a/groupaccess.c b/groupaccess.c
index e73f62b..2381aeb 100644
--- a/groupaccess.c
+++ b/groupaccess.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: groupaccess.c,v 1.12 2006/08/03 03:34:42 deraadt Exp $ */
+/* $OpenBSD: groupaccess.c,v 1.13 2008/07/04 03:44:59 djm Exp $ */
 /*
  * Copyright (c) 2001 Kevin Steves.  All rights reserved.
  *
@@ -31,6 +31,7 @@
 #include <grp.h>
 #include <unistd.h>
 #include <stdarg.h>
+#include <string.h>
 
 #include "xmalloc.h"
 #include "groupaccess.h"
@@ -88,6 +89,30 @@
 }
 
 /*
+ * Return 1 if one of user's groups matches group_pattern list.
+ * Return 0 on negated or no match.
+ */
+int
+ga_match_pattern_list(const char *group_pattern)
+{
+	int i, found = 0;
+	size_t len = strlen(group_pattern);
+
+	for (i = 0; i < ngroups; i++) {
+		switch (match_pattern_list(groups_byname[i],
+		    group_pattern, len, 0)) {
+		case -1:
+			return 0;	/* Negated match wins */
+		case 0:
+			continue;
+		case 1:
+			found = 1;
+		}
+	}
+	return found;
+}
+
+/*
  * Free memory allocated for group access list.
  */
 void
diff --git a/groupaccess.h b/groupaccess.h
index 04b4498..000578e 100644
--- a/groupaccess.h
+++ b/groupaccess.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: groupaccess.h,v 1.7 2006/08/03 03:34:42 deraadt Exp $ */
+/* $OpenBSD: groupaccess.h,v 1.8 2008/07/04 03:44:59 djm Exp $ */
 
 /*
  * Copyright (c) 2001 Kevin Steves.  All rights reserved.
@@ -29,6 +29,7 @@
 
 int	 ga_init(const char *, gid_t);
 int	 ga_match(char * const *, int);
+int	 ga_match_pattern_list(const char *);
 void	 ga_free(void);
 
 #endif
diff --git a/servconf.c b/servconf.c
index 9d9c950..66e2297 100644
--- a/servconf.c
+++ b/servconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: servconf.c,v 1.185 2008/07/02 02:24:18 djm Exp $ */
+/* $OpenBSD: servconf.c,v 1.186 2008/07/04 03:44:59 djm Exp $ */
 /*
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
  *                    All rights reserved
@@ -525,24 +525,8 @@
 match_cfg_line_group(const char *grps, int line, const char *user)
 {
 	int result = 0;
-	u_int ngrps = 0;
-	char *arg, *p, *cp, *grplist[MAX_MATCH_GROUPS];
 	struct passwd *pw;
 
-	/*
-	 * Even if we do not have a user yet, we still need to check for
-	 * valid syntax.
-	 */
-	arg = cp = xstrdup(grps);
-	while ((p = strsep(&cp, ",")) != NULL && *p != '\0') {
-		if (ngrps >= MAX_MATCH_GROUPS) {
-			error("line %d: too many groups in Match Group", line);
-			result = -1;
-			goto out;
-		}
-		grplist[ngrps++] = p;
-	}
-
 	if (user == NULL)
 		goto out;
 
@@ -552,17 +536,16 @@
 	} 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_pattern_list(grps) != 1) {
+		debug("user %.100s does not match group list %.100s at line %d",
+		    user, grps, line);
 	} else {
-		debug("user %.100s matched group %.100s at line %d", user,
-		    arg, line);
+		debug("user %.100s matched group list %.100s at line %d", user,
+		    grps, line);
 		result = 1;
 	}
 out:
 	ga_free();
-	xfree(arg);
 	return result;
 }