> We can do more than drop id, we can use the same minimal pledge
> that will be enforced later since root doesn't need to call
> auth_userokay().
> 
> In fact, root doesn't need proc or exec.  Is this going too far?

That's a nice observation.  Your diff looks fine to me as it is.

In the patch below I tried to refactor the code a little, so there is a
bit less branching depending on getuid() == 0 and argv == 1.  The result
seems a bit easier to follow this way.

Index: skeyinit.c
===================================================================
RCS file: /var/cvs/src/usr.bin/skeyinit/skeyinit.c,v
retrieving revision 1.69
diff -u -p -r1.69 skeyinit.c
--- skeyinit.c  21 Feb 2016 22:53:40 -0000      1.69
+++ skeyinit.c  17 May 2016 18:46:44 -0000
@@ -39,6 +39,7 @@
 #endif
 
 void   usage(void);
+void   isskeyenabled(const char *, const char *, int);
 void   secure_mode(int *, char *, char *, size_t, char *, size_t);
 void   normal_mode(char *, int, char *, char *);
 void   enable_db(int);
@@ -50,7 +51,7 @@ main(int argc, char **argv)
        char    hostname[HOST_NAME_MAX+1];
        char    seed[SKEY_MAX_SEED_LEN + 1];
        char    buf[256], key[SKEY_BINKEY_SIZE], filename[PATH_MAX], *ht;
-       char    lastc, me[UT_NAMESIZE + 1], *p, *auth_type;
+       char    lastc, *p, *auth_type;
        const char *errstr;
        struct skey skey;
        struct passwd *pp;
@@ -117,41 +118,47 @@ main(int argc, char **argv)
                exit(0);
        }
 
-       if (pledge("stdio rpath wpath cpath fattr flock tty proc exec getpw",
-           NULL) == -1)
-               err(1, "pledge");
+       if (getuid() != 0) {
+               if (pledge("stdio rpath wpath cpath fattr flock tty proc exec "
+                   "getpw", NULL) == -1)
+                       err(1, "pledge");
 
-       /* Build up a default seed based on the hostname and some randomness */
-       if (gethostname(hostname, sizeof(hostname)) < 0)
-               err(1, "gethostname");
-       for (i = 0, p = seed; hostname[i] && i < SKEY_NAMELEN; i++) {
-               if (isalnum((unsigned char)hostname[i]))
-                       *p++ = tolower((unsigned char)hostname[i]);
-       }
-       for (i = 0; i < 5; i++)
-               *p++ = arc4random_uniform(10) + '0';
-       *p = '\0';
+               if ((pp = getpwuid(getuid())) == NULL)
+                       err(1, "no user with uid %u", getuid());
+
+               if (argc == 1) {
+                       char me[UT_NAMESIZE + 1]; 
+
+                       (void)strlcpy(me, pp->pw_name, sizeof me);
+                       if ((pp = getpwnam(argv[0])) == NULL)
+                               errx(1, "User unknown: %s", argv[0]);
+                       if (strcmp(pp->pw_name, me) != 0)
+                               errx(1, "Permission denied.");
+               }
+       } else {
+               if (pledge("stdio rpath wpath cpath fattr flock tty getpw id",
+                   NULL) == -1)
+                       err(1, "pledge");
 
-       if ((pp = getpwuid(getuid())) == NULL)
-               err(1, "no user with uid %u", getuid());
-       (void)strlcpy(me, pp->pw_name, sizeof me);
-
-       /* Check for optional user string. */
-       if (argc == 1) {
-               if ((pp = getpwnam(argv[0])) == NULL) {
-                       if (getuid() == 0) {
+               if (argc == 1) {
+                       if ((pp = getpwnam(argv[0])) == NULL) {
                                static struct passwd _pp;
 
                                _pp.pw_name = argv[0];
                                pp = &_pp;
                                warnx("Warning, user unknown: %s", argv[0]);
                        } else {
-                               errx(1, "User unknown: %s", argv[0]);
+                               /* So the file ends up owned by the proper ID */
+                               if (setresuid(-1, pp->pw_uid, -1) != 0)
+                                   errx(1, "unable to change user ID to %u",
+                                       pp->pw_uid);
                        }
-               } else if (strcmp(pp->pw_name, me) != 0 && getuid() != 0) {
-                       /* Only root can change other's S/Keys. */
-                       errx(1, "Permission denied.");
-               }
+               } else if ((pp = getpwuid(0)) == NULL)
+                       err(1, "no user with uid %u", getuid());
+
+               if (pledge("stdio rpath wpath cpath fattr flock tty", NULL)
+                   == -1)
+                       err(1, "pledge");
        }
 
        switch (skey_haskey(pp->pw_name)) {
@@ -188,6 +195,17 @@ main(int argc, char **argv)
 
        if (pledge("stdio rpath wpath cpath fattr flock tty", NULL) == -1)
                err(1, "pledge");
+
+       /* Build up a default seed based on the hostname and some randomness */
+       if (gethostname(hostname, sizeof(hostname)) < 0)
+               err(1, "gethostname");
+       for (i = 0, p = seed; hostname[i] && i < SKEY_NAMELEN; i++) {
+               if (isalnum((unsigned char)hostname[i]))
+                       *p++ = tolower((unsigned char)hostname[i]);
+       }
+       for (i = 0; i < 5; i++)
+               *p++ = arc4random_uniform(10) + '0';
+       *p = '\0';
 
        /*
         * Lookup and lock the record we are about to modify.

Reply via email to