]> granicus.if.org Git - sudo/commitdiff
When running a login shell with a login_class specified, use
authorTodd C. Miller <Todd.Miller@courtesan.com>
Thu, 8 Dec 2011 22:17:25 +0000 (17:17 -0500)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Thu, 8 Dec 2011 22:17:25 +0000 (17:17 -0500)
LOGIN_SETENV instead of rolling our own login.conf setenv support
since FreeBSD's login.conf has more than just setenv capabilities.
This requires us to swap the plugin-provided envp for the global
environ before calling setusercontext() and then stash the resulting
environ pointer back into the command details, which is kind of a
hack.

MANIFEST
configure
configure.in
mkdep.pl
plugins/sudoers/Makefile.in
plugins/sudoers/env.c
plugins/sudoers/login_class.c [deleted file]
plugins/sudoers/sudoers.c
plugins/sudoers/sudoers.h
src/sudo.c

index 7f2ff00d7fe1351133ec939d11af213ee1e5a7fd..e3d6f352a0c01cc8245df6f78fa69b05f05e3a80 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -179,7 +179,6 @@ plugins/sudoers/linux_audit.c
 plugins/sudoers/linux_audit.h
 plugins/sudoers/logging.c
 plugins/sudoers/logging.h
-plugins/sudoers/login_class.c
 plugins/sudoers/logwrap.c
 plugins/sudoers/match.c
 plugins/sudoers/match_addr.c
index 7561536ea67cccddabb25b6421453160bd66db4d..718013fdf27012f4963257b3da2528128b243dd0 100755 (executable)
--- a/configure
+++ b/configure
@@ -15445,7 +15445,6 @@ _ACEOF
                SUDOERS_LIBS="${SUDOERS_LIBS} -lutil"
                ;;
        esac
-       SUDOERS_OBJS="${SUDOERS_OBJS} login_class.lo"
 
 fi
 
index 57374bbca2686c6c72601b63e097597a36d514fd..86512b3d07c4c4f9eb1673ba55a097cfa2b10958 100644 (file)
@@ -1990,7 +1990,6 @@ if test ${with_logincap-'no'} != "no"; then
                SUDOERS_LIBS="${SUDOERS_LIBS} -lutil"
                ;;
        esac
-       SUDOERS_OBJS="${SUDOERS_OBJS} login_class.lo"
     ])
 fi
 if test ${with_project-'no'} != "no"; then
index abf46f51933b62d7a7463fd9b56d3ca7cc103c6b..55006ba998b637ce1b902cd873d892166d24b845 100755 (executable)
--- a/mkdep.pl
+++ b/mkdep.pl
@@ -52,7 +52,7 @@ sub mkdep {
     $makefile =~ s:\@DEV\@::g;
     $makefile =~ s:\@COMMON_OBJS\@:aix.lo:;
     $makefile =~ s:\@SUDO_OBJS\@:preload.o selinux.o sesh.o sudo_noexec.lo:;
-    $makefile =~ s:\@SUDOERS_OBJS\@:bsm_audit.lo linux_audit.lo ldap.lo plugin_error.lo login_class.lo:;
+    $makefile =~ s:\@SUDOERS_OBJS\@:bsm_audit.lo linux_audit.lo ldap.lo plugin_error.lo:;
     # XXX - fill in AUTH_OBJS from contents of the auth dir instead
     $makefile =~ s:\@AUTH_OBJS\@:afs.lo aix_auth.lo bsdauth.lo dce.lo fwtk.lo getspwuid.lo kerb5.lo pam.lo passwd.lo rfc1938.lo secureware.lo securid5.lo sia.lo:;
     $makefile =~ s:\@LTLIBOBJS\@:closefrom.lo dlopen.lo fnmatch.lo getcwd.lo getgrouplist.lo getline.lo getprogname.lo glob.lo isblank.lo memrchr.lo mksiglist.lo mktemp.lo nanosleep.lo setenv.lo siglist.lo snprintf.lo strlcat.lo strlcpy.lo strsignal.lo unsetenv.lo utimes.lo globtest.o fnm_test.o:;
index 7438586a8d441805ed3eee9c213a1caa55a0ea5a..3881a6143dfc74cb78644f658ae54aed3be6c33a 100644 (file)
@@ -579,15 +579,6 @@ logging.lo: $(srcdir)/logging.c $(top_builddir)/config.h $(srcdir)/sudoers.h \
             $(devdir)/def_data.h $(srcdir)/logging.h $(srcdir)/sudo_nss.h \
             $(incdir)/sudo_plugin.h $(incdir)/sudo_debug.h $(incdir)/gettext.h
        $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/logging.c
-login_class.lo: $(srcdir)/login_class.c $(top_builddir)/config.h \
-                $(srcdir)/sudoers.h $(top_srcdir)/compat/stdbool.h \
-                $(top_builddir)/pathnames.h $(incdir)/missing.h \
-                $(incdir)/error.h $(incdir)/alloc.h $(incdir)/list.h \
-                $(incdir)/fileops.h $(srcdir)/defaults.h $(devdir)/def_data.h \
-                $(srcdir)/logging.h $(srcdir)/sudo_nss.h \
-                $(incdir)/sudo_plugin.h $(incdir)/sudo_debug.h \
-                $(incdir)/gettext.h
-       $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/login_class.c
 logwrap.lo: $(srcdir)/logwrap.c $(top_builddir)/config.h $(srcdir)/sudoers.h \
             $(top_srcdir)/compat/stdbool.h $(top_builddir)/pathnames.h \
             $(incdir)/missing.h $(incdir)/error.h $(incdir)/alloc.h \
index 66bcd5e48adb853eed9c159c21edad431e186a87..7252120360f380e37e11ef97260623d0fcf5f66e 100644 (file)
@@ -98,6 +98,7 @@ struct environment {
 /*
  * Prototypes
  */
+static void sudo_setenv(const char *, const char *, int);
 static void sudo_putenv(char *, int, int);
 
 /*
@@ -239,7 +240,7 @@ env_get(void)
  * (not environ) and it always overwrites.  The dupcheck param determines
  * whether we need to verify that the variable is not already set.
  */
-void
+static void
 sudo_setenv(const char *var, const char *val, int dupcheck)
 {
     char *estring;
diff --git a/plugins/sudoers/login_class.c b/plugins/sudoers/login_class.c
deleted file mode 100644 (file)
index 34270d5..0000000
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * Copyright (c) 2004, 2011 Todd C. Miller <Todd.Miller@courtesan.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <config.h>
-
-#include <sys/types.h>
-#include <stdio.h>
-#ifdef STDC_HEADERS
-# include <stdlib.h>
-# include <stddef.h>
-#else
-# ifdef HAVE_STDLIB_H
-#  include <stdlib.h>
-# endif
-#endif /* STDC_HEADERS */
-#ifdef HAVE_STRING_H
-# include <string.h>
-#endif /* HAVE_STRING_H */
-#ifdef HAVE_STRINGS_H
-# include <strings.h>
-#endif /* HAVE_STRING_H */
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-#include <pwd.h>
-
-#include <login_cap.h>
-
-#include "sudoers.h"
-
-/*
- * Check whether or not a tilde in a string should be expanded.
- * We only do expansion for things like "~", "~/...", ~me", "~me/...".
- */
-#define tilde_valid(s, u, l) \
-    ((s)[1] == '/' || (s)[1] == '\0' || \
-    (strncmp((s)+1, u, l) == 0 && ((s)[l+1] == '/' || (s)[l+1] == '\0')))
-
-/*
- * Make a copy of a string, expanding '~' to the user's homedir, '$' to the
- * login name and other escape sequences as per cgetstr(3).
- */
-static char *
-expandstr(const char *ostr, const struct passwd *pwd)
-{
-       size_t n, olen, nlen, ulen, dlen;
-       const char *ep, *eo, *op;
-       char *nstr, *np;
-       int ch;
-
-       /* calculate the size of the new string */
-       ulen = strlen(pwd->pw_name);
-       dlen = strlen(pwd->pw_dir);
-       olen = nlen = strlen(ostr);
-       for (op = ostr, ep = ostr + olen; op < ep; op++) {
-               switch (*op) {
-               case '~':
-                       if (!tilde_valid(op, pwd->pw_name, ulen))
-                               break;
-                       if (op[1] != '/' && op[1] != '\0') {
-                               op += ulen;     /* ~username */
-                               nlen = nlen - ulen - 1 + dlen;
-                       } else
-                               nlen += dlen - 1;
-                       break;
-               case '$':
-                       nlen += ulen - 1;
-                       break;
-               case '^':
-                       /* control char */
-                       if (*++op != '\0')
-                               nlen--;
-                       break;
-               case '\\':
-                       if (op[1] == '\0')
-                               break;
-                       /*
-                        * Byte in octal notation (\123) or an escaped char (\t)
-                        */
-                       eo = op + 4;
-                       do {
-                               op++;
-                               nlen--;
-                       } while (op < eo && *op >= '0' && *op <= '7');
-                       break;
-               }
-       }
-       np = nstr = emalloc(++nlen);
-
-       for (op = ostr, ep = ostr + olen; op < ep; op++) {
-               switch ((ch = *op)) {
-               case '~':
-                       if (!tilde_valid(op, pwd->pw_name, ulen))
-                               break;
-                       if (op[1] != '/' && op[1] != '\0')
-                               op += ulen;     /* ~username */
-                       strlcpy(np, pwd->pw_dir, nlen);
-                       nlen -= dlen;
-                       np += dlen;
-                       continue;
-               case '$':
-                       strlcpy(np, pwd->pw_name, nlen);
-                       nlen -= ulen;
-                       np += ulen;
-                       continue;
-               case '^':
-                       if (op[1] != '\0')
-                               ch = *++op & 037;
-                       break;
-               case '\\':
-                       if (op[1] == '\0')
-                               break;
-                       switch(*++op) {
-                       case '0': case '1': case '2': case '3':
-                       case '4': case '5': case '6': case '7':
-                               /* byte in octal up to 3 digits long */
-                               ch = 0;
-                               n = 3;
-                               do {
-                                       ch = ch * 8 + (*op++ - '0');
-                               } while (--n && *op >= '0' && *op <= '7');
-                               break;
-                       case 'b': case 'B':
-                               ch = '\b';
-                               break;
-                       case 't': case 'T':
-                               ch = '\t';
-                               break;
-                       case 'n': case 'N':
-                               ch = '\n';
-                               break;
-                       case 'f': case 'F':
-                               ch = '\f';
-                               break;
-                       case 'r': case 'R':
-                               ch = '\r';
-                               break;
-                       case 'e': case 'E':
-                               ch = '\033';
-                               break;
-                       case 'c': case 'C':
-                               ch = ':';
-                               break;
-                       default:
-                               ch = *op;
-                               break;
-                       }
-                       break;
-               }
-               *np++ = ch;
-               nlen--;
-       }
-       *np = '\0';
-       return (nstr);
-}
-
-/*
- * Set an environment variable, substituting for ~ and $
- */
-static void
-login_setenv(char *name, char *ovalue, const struct passwd *pwd)
-{
-       char *value = NULL;
-
-       if (*ovalue != '\0')
-               value = expandstr(ovalue, pwd);
-       sudo_setenv(name, value ? value : ovalue, 1);
-       efree(value);
-}
-
-/*
- * Look up "setenv" for this user in login.conf and set the comma-separated
- * list of environment variables, expanding '~' and '$'.
- */
-int
-sudo_login_setenv(login_cap_t *lc, const struct passwd *pwd)
-{
-       char *beg, *end, *ep, *list, *value;
-       int len;
-
-       if (lc == NULL || lc->lc_cap == NULL)
-               return (-1);            /* impossible */
-
-       if ((len = cgetustr(lc->lc_cap, "setenv", &list)) <= 0)
-               return (0);
-
-       for (beg = end = list, ep = list + len + 1; end < ep; end++) {
-               switch (*end) {
-               case '\\':
-                       if (*(end + 1) == ',')
-                               end++;  /* skip escaped comma */
-                       continue;
-               case ',':
-               case '\0':
-                       *end = '\0';
-                       if (beg == end) {
-                               beg++;
-                               continue;
-                       }
-                       break;
-               default:
-                       continue;
-               }
-
-               if ((value = strchr(beg, '=')) != NULL)
-                       *value++ = '\0';
-               else
-                       value = "";
-               login_setenv(beg, value, pwd);
-               beg = end + 1;
-       }
-       efree(list);
-       return (0);
-}
index 6d64ac613646c3e81c7dc33409181e8f0c57a3df..3dd6b856b4f039f493a2cc3321ecc575f87487ed 100644 (file)
@@ -127,9 +127,6 @@ static char *runas_group;
 static struct sudo_nss_list *snl;
 static const char *interfaces_string;
 static sigaction_t saved_sa_int, saved_sa_quit, saved_sa_tstp;
-#ifdef HAVE_LOGIN_CAP_H
-static login_cap_t *lc;
-#endif
 
 /* XXX - must be extern for audit bits of sudo_auth.c */
 int NewArgc;
@@ -595,16 +592,8 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
 #if defined(__linux__) || defined(_AIX)
        /* Insert system-wide environment variables. */
        read_env_file(_PATH_ENVIRONMENT, true);
-#elif defined(HAVE_LOGIN_CAP_H)
-       /* Insert login class-specific environment variables. */
-       if (lc != NULL)
-           sudo_login_setenv(lc, runas_pw);
 #endif
     }
-#ifdef HAVE_LOGIN_CAP_H
-    login_close(lc);
-    lc = NULL;
-#endif
 
     /* Insert system-wide environment variables. */
     if (def_env_file)
@@ -1015,6 +1004,7 @@ static void
 set_loginclass(struct passwd *pw)
 {
     int errflags;
+    login_cap_t *lc;
     debug_decl(set_loginclass, SUDO_DEBUG_PLUGIN)
 
     if (!def_use_loginclass)
@@ -1047,6 +1037,7 @@ set_loginclass(struct passwd *pw)
        log_error(errflags, _("unknown login class: %s"), login_class);
        def_use_loginclass = false;
     }
+    login_close(lc);
     debug_return;
 }
 #else
index 6c7878b28d5e308f5653d18b7fdc8f2e0948c9e4..1d4f3e9d410a14c775263fc8d1446aafbd9194be 100644 (file)
@@ -197,7 +197,6 @@ struct lbuf;
 struct passwd;
 struct stat;
 struct timeval;
-struct login_cap;
 
 /*
  * Function prototypes
@@ -306,7 +305,6 @@ void init_envtables(void);
 void insert_env_vars(char * const envp[]);
 void read_env_file(const char *, int);
 void rebuild_env(void);
-void sudo_setenv(const char *var, const char *val, int dupcheck);
 void validate_env_vars(char * const envp[]);
 
 /* fmt_string.c */
@@ -330,9 +328,6 @@ int group_plugin_query(const char *user, const char *group,
 /* setgroups.c */
 int sudo_setgroups(int ngids, const GETGROUPS_T *gids);
 
-/* login_cap.c */
-int sudo_login_setenv(struct login_cap *lc, const struct passwd *pwd);
-
 #ifndef _SUDO_MAIN
 extern struct sudo_user sudo_user;
 extern struct passwd *list_pw;
index b0b81d5b0ffe96b62de122f81462974755c8dba9..e7924cdba294b9771bce41bca9092ac3db1e7127 100644 (file)
@@ -103,6 +103,7 @@ struct plugin_container_list io_plugins;
 struct user_details user_details;
 const char *list_user, *runas_user, *runas_group; /* extern for parse_args.c */
 int debug_level;
+static int sudo_mode;
 
 /*
  * Local functions
@@ -153,10 +154,14 @@ static struct rlimit corelimit;
 static struct rlimit nproclimit;
 #endif
 
+#ifdef HAVE_LOGIN_CAP_H
+extern char **environ;
+#endif
+
 int
 main(int argc, char *argv[], char *envp[])
 {
-    int nargc, ok, sudo_mode, exitcode = 0;
+    int nargc, ok, exitcode = 0;
     char **nargv, **settings, **env_add;
     char **user_info, **command_info, **argv_out, **user_env_out;
     struct plugin_container *plugin, *next;
@@ -951,7 +956,8 @@ exec_setup(struct command_details *details, const char *ptyname, int ptyfd)
            login_cap_t *lc;
 
            /*
-            * We only use setusercontext() to set the nice value and rlimits.
+            * We only use setusercontext() to set the nice value and rlimits
+            * unless this is a login shell (sudo -i).
             */
            lc = login_getclass((char *)details->login_class);
            if (!lc) {
@@ -959,7 +965,16 @@ exec_setup(struct command_details *details, const char *ptyname, int ptyfd)
                errno = ENOENT;
                goto done;
            }
-           flags = LOGIN_SETRESOURCES|LOGIN_SETPRIORITY;
+           if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) {
+               /* Set everything except user, group and login name. */
+               flags = LOGIN_SETALL;
+               CLR(flags, LOGIN_SETGROUP|LOGIN_SETLOGIN|LOGIN_SETUSER);
+               CLR(details->flags, CD_SET_UMASK); /* LOGIN_UMASK instead */
+               /* Swap in the plugin-supplied environment for LOGIN_SETENV */
+               environ = details->envp;
+           } else {
+               flags = LOGIN_SETRESOURCES|LOGIN_SETPRIORITY;
+           }
            if (setusercontext(lc, pw, pw->pw_uid, flags)) {
                if (pw->pw_uid != ROOT_UID) {
                    warning(_("unable to set user context"));
@@ -967,6 +982,10 @@ exec_setup(struct command_details *details, const char *ptyname, int ptyfd)
                } else
                    warning(_("unable to set user context"));
            }
+           if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) {
+               /* Stash the updated environment pointer in command details */
+               details->envp = environ;
+           }
        }
 #endif /* HAVE_LOGIN_CAP_H */
     }