]> git.armaanb.net Git - opendoas.git/blobdiff - doas.c
correct some unveil(2) violations due to "login.conf.db" access (the .db version...
[opendoas.git] / doas.c
diff --git a/doas.c b/doas.c
index 1fd0e9a9c455ab62e32b738019cc2f3fbb14a947..71f955a76afc65b7a328ff9b2963f6b8537eaf2f 100644 (file)
--- a/doas.c
+++ b/doas.c
@@ -249,6 +249,46 @@ good:
 }
 #endif
 
+#ifdef __OpenBSD__
+int
+unveilcommands(const char *ipath, const char *cmd)
+{
+       char *path = NULL, *p;
+       int unveils = 0;
+
+       if (strchr(cmd, '/') != NULL) {
+               if (unveil(cmd, "x") != -1)
+                       unveils++;
+               goto done;
+       }
+
+       if (!ipath) {
+               errno = ENOENT;
+               goto done;
+       }
+       path = strdup(ipath);
+       if (!path) {
+               errno = ENOENT;
+               goto done;
+       }
+       for (p = path; p && *p; ) {
+               char buf[PATH_MAX];
+               char *cp = strsep(&p, ":");
+
+               if (cp) {
+                       int r = snprintf(buf, sizeof buf, "%s/%s", cp, cmd);
+                       if (r >= 0 && r < sizeof buf) {
+                               if (unveil(buf, "x") != -1)
+                                       unveils++;
+                       }
+               }
+       }
+done:
+       free(path);
+       return (unveils);
+}
+#endif
+
 int
 main(int argc, char **argv)
 {
@@ -257,6 +297,7 @@ main(int argc, char **argv)
        const char *confpath = NULL;
        char *shargv[] = { NULL, NULL };
        char *sh;
+       const char *p;
        const char *cmd;
        char cmdline[LINE_MAX];
 #ifdef __OpenBSD__
@@ -411,7 +452,24 @@ main(int argc, char **argv)
 # endif
        }
 
+       if ((p = getenv("PATH")) != NULL)
+               formerpath = strdup(p);
+       if (formerpath == NULL)
+               formerpath = "";
+
 # ifdef __OpenBSD__
+       if (unveil(_PATH_LOGIN_CONF, "r") == -1 ||
+           unveil(_PATH_LOGIN_CONF ".db", "r") == -1)
+               err(1, "unveil");
+# endif
+       if (rule->cmd) {
+               if (setenv("PATH", safepath, 1) == -1)
+                       err(1, "failed to set PATH '%s'", safepath);
+       }
+# ifdef __OpenBSD__
+       if (unveilcommands(getenv("PATH"), cmd) == 0)
+               goto fail;
+
        if (pledge("stdio rpath getpw exec id", NULL) == -1)
                err(1, "pledge");
 # endif
@@ -449,6 +507,7 @@ main(int argc, char **argv)
 
 #ifdef HAVE_SETUSERCONTEXT
        if (setusercontext(NULL, targpw, target, LOGIN_SETGROUP |
+           LOGIN_SETPATH |
            LOGIN_SETPRIORITY | LOGIN_SETRESOURCES | LOGIN_SETUMASK |
            LOGIN_SETUSER) != 0)
                errx(1, "failed to set user context for target");
@@ -479,11 +538,15 @@ main(int argc, char **argv)
        syslog(LOG_AUTHPRIV | LOG_INFO, "%s ran command %s as %s from %s",
            mypw->pw_name, cmdline, targpw->pw_name, cwd);
 
-       envp = prepenv(rule);
+       envp = prepenv(rule, mypw, targpw);
 
+       /* setusercontext set path for the next process, so reset it for us */
        if (rule->cmd) {
                if (setenv("PATH", safepath, 1) == -1)
                        err(1, "failed to set PATH '%s'", safepath);
+       } else {
+               if (setenv("PATH", formerpath, 1) == -1)
+                       err(1, "failed to set PATH '%s'", formerpath);
        }
        execvpe(cmd, argv, envp);
        if (errno == ENOENT)