Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.bin/su If SU_INDIRECT_GROUP is defined (it is by default...



details:   https://anonhg.NetBSD.org/src/rev/200c5dba018b
branches:  trunk
changeset: 502030:200c5dba018b
user:      sjg <sjg%NetBSD.org@localhost>
date:      Wed Jan 10 21:33:13 2001 +0000

description:
If SU_INDIRECT_GROUP is defined (it is by default), then su will
consider that SUGROUP and ROOTAUTH group contain the names of
users and groups.  If user is not found in the list check_ingroup()
recurses on each member until either user is found or end of chain
is reached.

The above allows su's use of the wheel group to be extended to a large
number of users without necessarily putting them in group wheel, and
in a way that will work over NIS that simply extending the line length
limit in getgrent.c cannot.

diffstat:

 usr.bin/su/Makefile |    7 ++-
 usr.bin/su/su.1     |   10 ++++-
 usr.bin/su/su.c     |  108 +++++++++++++++++++++++++++++++++++++--------------
 3 files changed, 93 insertions(+), 32 deletions(-)

diffs (216 lines):

diff -r dc2526e7aa4f -r 200c5dba018b usr.bin/su/Makefile
--- a/usr.bin/su/Makefile       Wed Jan 10 21:30:05 2001 +0000
+++ b/usr.bin/su/Makefile       Wed Jan 10 21:33:13 2001 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: Makefile,v 1.24 2000/10/18 00:24:19 simonb Exp $
+#      $NetBSD: Makefile,v 1.25 2001/01/10 21:33:13 sjg Exp $
 #      from: @(#)Makefile      8.1 (Berkeley) 7/19/93
 
 .include <bsd.own.mk>
@@ -14,6 +14,11 @@
 #
 #CPPFLAGS+=-DSUGROUP=\"sugroup\"
 
+# Comment out the following line to prevent su
+# from assuming that group wheel (or SUGROUP) can be an indirect
+# list of groups.
+CPPFLAGS+=-DSU_INDIRECT_GROUP
+
 .if (${MKKERBEROS} != "no")
 .ifdef AFS
 DPADD+= ${LIBKAFS}
diff -r dc2526e7aa4f -r 200c5dba018b usr.bin/su/su.1
--- a/usr.bin/su/su.1   Wed Jan 10 21:30:05 2001 +0000
+++ b/usr.bin/su/su.1   Wed Jan 10 21:33:13 2001 +0000
@@ -30,7 +30,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\"    from: @(#)su.1  8.2 (Berkeley) 4/18/94
-.\"    $NetBSD: su.1,v 1.19 2000/05/10 19:04:36 jdolecek Exp $
+.\"    $NetBSD: su.1,v 1.20 2001/01/10 21:33:13 sjg Exp $
 .\"
 .Dd January 14, 2000
 .Dt SU 1
@@ -175,6 +175,14 @@
 .Dq wheel ,
 which is the default.)
 .Pp
+For sites with very large user populations, group
+.Dq wheel
+can contain the names of other groups that will be considered authorized
+to
+.Nm
+to
+.Dq root .
+.Pp
 By default (unless the prompt is reset by a startup file) the super-user
 prompt is set to
 .Dq Sy \&#
diff -r dc2526e7aa4f -r 200c5dba018b usr.bin/su/su.c
--- a/usr.bin/su/su.c   Wed Jan 10 21:30:05 2001 +0000
+++ b/usr.bin/su/su.c   Wed Jan 10 21:33:13 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: su.c,v 1.45 2001/01/10 12:30:19 lukem Exp $    */
+/*     $NetBSD: su.c,v 1.46 2001/01/10 21:33:13 sjg Exp $      */
 
 /*
  * Copyright (c) 1988 The Regents of the University of California.
@@ -44,7 +44,7 @@
 #if 0
 static char sccsid[] = "@(#)su.c       8.3 (Berkeley) 4/2/94";*/
 #else
-__RCSID("$NetBSD: su.c,v 1.45 2001/01/10 12:30:19 lukem Exp $");
+__RCSID("$NetBSD: su.c,v 1.46 2001/01/10 21:33:13 sjg Exp $");
 #endif
 #endif /* not lint */
 
@@ -112,6 +112,7 @@
 
 static int chshell __P((const char *));
 static char *ontty __P((void));
+static int check_ingroup __P((int, const char *, const char *, int));
 
 
 int
@@ -123,7 +124,6 @@
        extern char **environ;
        struct passwd *pwd;
        char *p;
-       struct group *gr;
 #ifdef BSD4_4
        struct timeval tp;
 #endif
@@ -238,26 +238,18 @@
            ) {
                char *pass = pwd->pw_passwd;
                int ok = pwd->pw_uid != 0;
-               char **g;
 
 #ifdef ROOTAUTH
                /*
                 * Allow those in group rootauth to su to root, by supplying
                 * their own password.
                 */
-               if (!ok && (gr = getgrnam(ROOTAUTH)))
-                       for (g = gr->gr_mem;; ++g) {
-                               if (!*g) {
-                                       ok = 0;
-                                       break;
-                               }
-                               if (!strcmp(username, *g)) {
-                                       pass = userpass;
-                                       user = username;
-                                       ok = 1;
-                                       break;
-                               }
+               if (!ok) {
+                       if ((ok = check_ingroup(-1, ROOTAUTH, username, 0))) {
+                               pass = userpass;
+                               user = username;
                        }
+               }
 #endif
                /*
                 * Only allow those in group SUGROUP to su to root,
@@ -265,19 +257,7 @@
                 * If SUGROUP has no members, allow anyone to su root
                 */
                if (!ok) {
-                       if ( !(gr = getgrnam(SUGROUP)) || !*gr->gr_mem)
-                               ok = 1;
-                       else
-                               for (g = gr->gr_mem; ; g++) {
-                                       if (*g == NULL) {
-                                               ok = 0;
-                                               break;
-                                       }
-                                       if (strcmp(username, *g) == 0) {
-                                               ok = 1;
-                                               break;
-                                       }
-                               }
+                       ok = check_ingroup(-1, SUGROUP, username, 1);
                }
                if (!ok)
                        errx(1,
@@ -352,7 +332,7 @@
                        p = getenv("TERM");
                        /* Create an empty environment */
                        if ((environ = malloc(sizeof(char *))) == NULL)
-                               err(1, NULL);
+                               err(1, "fuck");
                        environ[0] = NULL;
 #ifdef LOGIN_CAP
                        if (setusercontext(lc, pwd, pwd->pw_uid, LOGIN_SETPATH))
@@ -686,3 +666,71 @@
                           toname);
 }
 #endif
+
+static int
+check_ingroup (gid, gname, user, ifempty)
+       int gid;
+       const char *gname;
+       const char *user;
+       int ifempty;
+{
+       struct group *gr;
+       char **g;
+#ifdef SU_INDIRECT_GROUP
+       char **gr_mem;
+       int n = 0;
+       int i = 0;
+#endif
+       int ok = 0;
+
+       if (gname == NULL)
+               gr = getgrgid((gid_t) gid);
+       else
+               gr = getgrnam(gname);
+
+       /*
+        * XXX we are relying on the fact that we only set ifempty when
+        * calling to check for SUGROUP and that is the only time a
+        * missing group is acceptable.
+        */
+       if (gr == NULL)
+               return ifempty;
+       if (!*gr->gr_mem)               /* empty */
+               return ifempty;
+
+       /*
+        * Ok, first see if user is in gr_mem
+        */
+       for (g = gr->gr_mem; *g; ++g) {
+               if (strcmp(*g, user) == 0)
+                       return 1;       /* ok */
+#ifdef SU_INDIRECT_GROUP
+               ++n;                    /* count them */
+#endif
+       }
+#ifdef SU_INDIRECT_GROUP
+       /*
+        * No.
+        * Now we need to duplicate the gr_mem list, and recurse for
+        * each member to see if it is a group, and if so whether user is
+        * in it.
+        */
+       gr_mem = malloc((n + 1) * sizeof (char *));
+       for  (g = gr->gr_mem, i = 0; *g; ++g) {
+               gr_mem[i++] = strdup(*g);
+       }
+       gr_mem[i++] = NULL;
+    
+       for  (g = gr_mem; ok == 0 && *g; ++g) {
+               /*
+                * If we get this far we don't accept empty/missing groups.
+                */
+               ok = check_ingroup(-1, *g, user, 0);
+       }
+       for  (g = gr_mem; *g; ++g) {
+               free(*g);
+       }
+       free(gr_mem);
+#endif
+       return ok;
+}



Home | Main Index | Thread Index | Old Index