tmpdir: Allow trusting of particular groups.
authorMark Wooding <mdw@chiark.greenend.org.uk>
Sun, 13 Apr 2008 15:10:20 +0000 (16:10 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Sun, 13 Apr 2008 16:32:15 +0000 (17:32 +0100)
One site has a group-root-writable root directory, which buggers the
whole thing.  If we can trust the root group (and in this case at least
there's no reason not to) then we can win.

tmpdir.1
tmpdir.c

index 71f8544..4023ed9 100644 (file)
--- a/tmpdir.1
+++ b/tmpdir.1
@@ -5,6 +5,8 @@ tmpdir \- choose, or check a choice of, temporary directory
 .SH SYNOPSIS
 .B tmpdir
 .RB [ \-bcv ]
+.RB [ \-g
+.IR group ]
 .RB [ \-C
 .IR dir ]
 .SH USAGE
@@ -71,6 +73,11 @@ examine the user's shell and decide which syntax to use based on that.
 .B "\-c, \-\-cshell"
 Output an assignment using C shell syntax.
 .TP
+.BI "\-g, \-\-group " group
+Trust (the members of)
+.IR group :
+consider directories they can write to be safe.
+.TP
 .B "-v, \-\-verbose"
 Report problems to standard error.  Repeat for more verbosity.
 .TP
index 8e704e6..e4cdde5 100644 (file)
--- a/tmpdir.c
+++ b/tmpdir.c
@@ -27,6 +27,7 @@
 /*----- Header files ------------------------------------------------------*/
 
 #include <errno.h>
+#include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -35,6 +36,7 @@
 #include <sys/stat.h>
 #include <unistd.h>
 #include <pwd.h>
+#include <grp.h>
 
 #include <mLib/alloc.h>
 #include <mLib/dstr.h>
@@ -265,6 +267,7 @@ Options supported:\n\
 -b, --bourne           Output a `TMPDIR' setting for Bourne shell users.\n\
 -c, --cshell           Output a `TMPDIR' setting for C shell users.\n\
 -v, --verbose          Report problems to standard error.\n\
+-g, --group NAME       Trust group NAME to be honest and true.\n\
 -C, --check PATH       Check whether PATH is good, setting exit status.\n\
 \n\
 The default action is to examine the caller's shell and output a suitable\n\
@@ -273,6 +276,46 @@ setting for that shell type.\n\
        fp);
 }
 
+/* --- @allowgroup@ --- *
+ *
+ * Arguments:  @const char *gname@ = trust group @gname@
+ *
+ * Returns:    ---
+ *
+ * Use:                Adds the gid corresponding to @gname@ (which may be a number)
+ *             to the list of things we trust.
+ */
+
+static void allowgroup(const char *gname)
+{
+  struct group *gr;
+  const char *p;
+  gid_t g;
+
+  /* --- Check for numeric group spec --- */
+
+  for (p = gname; *p; p++) {
+    if (!isdigit((unsigned char)*p))
+      goto lookup;
+  }
+  g = atoi(gname);
+  goto insert;
+
+  /* --- Look up a group by name --- */
+
+lookup:
+  if ((gr = getgrnam(gname)) == 0)
+    die(1, "group %s not found", gname);
+  g = gr->gr_gid;
+
+  /* --- Insert the group into the table --- */
+
+insert:
+  if (cp.cp_gids >= N(cp.cp_gid))
+    die(1, "too many groups");
+  cp.cp_gid[cp.cp_gids++] = g;
+}
+
 /* --- @main@ --- *
  *
  * Arguments:  @int argc@ = number of command line arguments
@@ -299,10 +342,12 @@ int main(int argc, char *argv[])
 
   ego(argv[0]);
   me = getuid();
-  cp.cp_what = CP_WRWORLD | CP_WRGRP | CP_WROTHUSR | CP_STICKYOK | CP_REPORT;
+  cp.cp_what = (CP_WRWORLD | CP_WROTHGRP | CP_WROTHUSR |
+               CP_STICKYOK | CP_REPORT);
   cp.cp_verbose = 0;
   cp.cp_report = report;
   checkpath_setids(&cp);
+  cp.cp_gids = 0;                      /* ignore group membership */
   pw = getpwuid(me);
   if (!pw)
     die(1, "you don't exist");
@@ -319,9 +364,11 @@ int main(int argc, char *argv[])
       { "check",       OPTF_ARGREQ,    0,      'C' },
       { "verify",      OPTF_ARGREQ,    0,      'C' },
       { "verbose",     0,              0,      'v' },
+      { "trust-groups",        0,              0,      't' },
+      { "group",       OPTF_ARGREQ,    0,      'g' },
       { 0,             0,              0,      0 }
     };
-    int i = mdwopt(argc, argv, "hVu bcvc:", opts, 0, 0, 0);
+    int i = mdwopt(argc, argv, "hVu bcvtg:c:", opts, 0, 0, 0);
 
     if (i < 0)
       break;
@@ -344,6 +391,9 @@ int main(int argc, char *argv[])
       case 'C':
        return (!fullcheck(optarg));
        break;
+      case 'g':
+       allowgroup(optarg);
+       break;
       case 'v':
        cp.cp_verbose++;
        break;