bug-coreutils
[Top][All Lists]
Advanced

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

[PATCH]: pam support for coreutils 5.0


From: Arkadiusz Miskiewicz
Subject: [PATCH]: pam support for coreutils 5.0
Date: Mon, 7 Apr 2003 21:28:45 +0200
User-agent: Mutt/1.4.1i

Patch adds pam support to coreutils 5.0 (same as for sh-utils).


diff -Nur sh-utils-2.0.12.orig/configure.ac sh-utils-2.0.12/configure.ac
--- sh-utils-2.0.12.orig/configure.ac   Sun Apr 28 11:29:18 2002
+++ sh-utils-2.0.12/configure.ac        Mon May 27 23:10:36 2002
@@ -8,6 +8,13 @@
 
 AM_INIT_AUTOMAKE([1.6b gnits dist-bzip2])
 
+dnl Give the chance to enable PAM
+AC_ARG_ENABLE(pam, dnl
+[  --enable-pam            Enable use of the PAM libraries],
+AC_DEFINE(USE_PAM,,[Use PAM?])
+LIB_PAM="-ldl -lpam -lpam_misc"
+)
+
 AC_GNU_SOURCE
 jm_PERL
 AC_PROG_CC
@@ -238,6 +245,13 @@
 
 AM_GNU_GETTEXT([external])
 
+# just in case we want PAM
+AC_SUBST(LIB_PAM)
+# with PAM su doesn't need libcrypt
+if test -n "$LIB_PAM" ; then
+  LIB_CRYPT=
+fi
+
 AC_CONFIG_FILES(
   Makefile
   doc/Makefile
diff -Nur sh-utils-2.0.12.orig/doc/coreutils.texi 
sh-utils-2.0.12/doc/coreutils.texi
--- sh-utils-2.0.12.orig/doc/coreutils.texi     Sun Apr 28 23:55:31 2002
+++ sh-utils-2.0.12/doc/coreutils.texi  Mon May 27 23:11:49 2002
@@ -10898,32 +10898,6 @@
 
 @end table
 
address@hidden wheel group, not supported
address@hidden group wheel, not supported
address@hidden fascism
address@hidden Why GNU @command{su} does not support the @samp{wheel} group
-
-(This section is by Richard Stallman.)
-
address@hidden Twenex
address@hidden MIT AI lab
-Sometimes a few of the users try to hold total power over all the
-rest.  For example, in 1984, a few users at the MIT AI lab decided to
-seize power by changing the operator password on the Twenex system and
-keeping it secret from everyone else.  (I was able to thwart this coup
-and give power back to the users by patching the kernel, but I
-wouldn't know how to do that in Unix.)
-
-However, occasionally the rulers do tell someone.  Under the usual
address@hidden mechanism, once someone learns the root password who
-sympathizes with the ordinary users, he or she can tell the rest.  The
-``wheel group'' feature would make this impossible, and thus cement the
-power of the rulers.
-
-I'm on the side of the masses, not that of the rulers.  If you are
-used to supporting the bosses and sysadmins in whatever they do, you
-might find this idea strange at first.
-
 
 @node Process control
 @chapter Process control
diff -Nur sh-utils-2.0.12.orig/src/Makefile.am sh-utils-2.0.12/src/Makefile.am
--- sh-utils-2.0.12.orig/src/Makefile.am        Mon May 27 23:06:24 2002
+++ sh-utils-2.0.12/src/Makefile.am     Mon May 27 23:09:22 2002
@@ -47,7 +47,7 @@
 
 uptime_LDADD = $(LDADD) @GETLOADAVG_LIBS@
 
-su_LDADD = $(LDADD) @LIB_CRYPT@
+su_LDADD = $(LDADD) @LIB_CRYPT@ @LIB_PAM@
 
 $(PROGRAMS): ../lib/libfetish.a
 
diff -Nur sh-utils-2.0.12.orig/src/su.c sh-utils-2.0.12/src/su.c
--- sh-utils-2.0.12.orig/src/su.c       Mon May 27 23:06:24 2002
+++ sh-utils-2.0.12/src/su.c    Mon May 27 23:08:28 2002
@@ -38,6 +38,16 @@
    restricts who can su to UID 0 accounts.  RMS considers that to
    be fascist.
 
+#ifdef USE_PAM
+
+   Actually, with PAM, su has nothing to do with whether or not a
+   wheel group is enforced by su.  RMS tries to restrict your access
+   to a su which implements the wheel group, but PAM considers that
+   to be fascist, and gives the user/sysadmin the opportunity to
+   enforce a wheel group by proper editing of /etc/pam.conf
+
+#endif
+
    Options:
    -, -l, --login      Make the subshell a login shell.
                        Unset all environment variables except
@@ -81,6 +91,14 @@
    prototype (returning `int') in <unistd.h>.  */
 #define getusershell _getusershell_sys_proto_
 
+#ifdef USE_PAM
+# include <security/pam_appl.h>
+# include <security/pam_misc.h>
+# include <signal.h>
+# include <sys/wait.h>
+# include <sys/fsuid.h>
+#endif /* USE_PAM */
+
 #include "system.h"
 #include "closeout.h"
 #include "dirname.h"
@@ -151,7 +169,9 @@
 /* The user to become if none is specified.  */
 #define DEFAULT_USER "root"
 
+#ifndef USE_PAM
 char *crypt ();
+#endif
 char *getpass ();
 char *getusershell ();
 void endusershell ();
@@ -159,7 +179,7 @@
 
 extern char **environ;
 
-static void run_shell (const char *, const char *, char **)
+static void run_shell (const char *, const char *, char **, const struct 
passwd *)
      ATTRIBUTE_NORETURN;
 
 /* The name this program was run with.  */
@@ -272,7 +292,22 @@
 }
 #endif
 
+#ifdef USE_PAM
+static pam_handle_t *pamh = NULL;
+static int retval;
+static struct pam_conv conv = {
+  misc_conv,
+  NULL
+};
+
+#define PAM_BAIL_P if (retval) { \
+  pam_end(pamh, PAM_SUCCESS); \
+  return 0; \
+}
+#endif
+
 /* Ask the user for a password.
+   If PAM is in use, let PAM ask for the password if necessary.
    Return 1 if the user gives the correct password for entry PW,
    0 if not.  Return 1 without asking for a password if run by UID 0
    or if PW has an empty password.  */
@@ -280,6 +315,29 @@
 static int
 correct_password (const struct passwd *pw)
 {
+#ifdef USE_PAM
+  /* root always succeeds; this isn't an authentication question (no
+   * extra privs are being granted) so it shouldn't authenticate with PAM.
+   * However, we want to create the pam_handle so that proper credentials
+   * are created later with pam_setcred(). */
+  retval = pam_start(PROGRAM_NAME, pw->pw_name, &conv, &pamh);
+  PAM_BAIL_P;
+
+  retval = pam_authenticate(pamh, 0);
+  PAM_BAIL_P;
+
+  retval = pam_acct_mgmt(pamh, 0);
+  if (retval == PAM_NEW_AUTHTOK_REQD) {
+    /* password has expired.  Offer option to change it. */
+    if (getuid()) {
+           retval = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
+           PAM_BAIL_P;
+    } else retval = PAM_SUCCESS;
+  }
+  PAM_BAIL_P;
+  /* must be authenticated if this point was reached */
+  return 1;
+#else /* !USE_PAM */
   char *unencrypted, *encrypted, *correct;
 #if HAVE_GETSPNAM && HAVE_STRUCT_SPWD_SP_PWDP
   /* Shadow passwd stuff for SVR3 and maybe other systems.  */
@@ -304,6 +362,7 @@
   encrypted = crypt (unencrypted, correct);
   memset (unencrypted, 0, strlen (unencrypted));
   return strcmp (encrypted, correct) == 0;
+#endif /* !USE_PAM */
 }
 
 /* Update `environ' for the new shell based on PW, with SHELL being
@@ -313,16 +372,20 @@
 modify_environment (const struct passwd *pw, const char *shell)
 {
   char *term;
+  char *display;
 
   if (simulate_login)
     {
-      /* Leave TERM unchanged.  Set HOME, SHELL, USER, LOGNAME, PATH.
+      /* Leave TERM, DISPLAY unchanged.  Set HOME, SHELL, USER, LOGNAME, PATH.
          Unset all other environment variables.  */
       term = getenv ("TERM");
+      display = getenv ("DISPLAY");
       environ = (char **) xmalloc (2 * sizeof (char *));
       environ[0] = 0;
       if (term)
        xputenv (concat ("TERM", "=", term));
+      if (display)
+       xputenv (concat ("DISPLAY", "=", display));
       xputenv (concat ("HOME", "=", pw->pw_dir));
       xputenv (concat ("SHELL", "=", shell));
       xputenv (concat ("USER", "=", pw->pw_name));
@@ -359,23 +422,73 @@
     error (EXIT_FAILURE, errno, _("cannot set groups"));
   endgrent ();
 #endif
+#ifdef USE_PAM
+  retval = pam_setcred(pamh, PAM_ESTABLISH_CRED);
+  if (retval != PAM_SUCCESS)
+    error (1, 0, pam_strerror(pamh, retval));
+#endif /* USE_PAM */
   if (setgid (pw->pw_gid))
     error (EXIT_FAILURE, errno, _("cannot set group id"));
   if (setuid (pw->pw_uid))
     error (EXIT_FAILURE, errno, _("cannot set user id"));
 }
 
+#ifdef USE_PAM
+static int caught=0;
+/* Signal handler for parent process later */
+static void su_catch_sig(int sig)
+{
+  ++caught;
+}
+
+int
+pam_copyenv (pam_handle_t *pamh)
+{
+  char **env;
+
+  env = pam_getenvlist(pamh);
+  if(env) {
+    while(*env) {
+       xputenv(*env);
+       env++;
+    }
+  }
+  return(0);
+}
+#endif
+
 /* Run SHELL, or DEFAULT_SHELL if SHELL is empty.
    If COMMAND is nonzero, pass it to the shell with the -c option.
    If ADDITIONAL_ARGS is nonzero, pass it to the shell as more
    arguments.  */
 
 static void
-run_shell (const char *shell, const char *command, char **additional_args)
+run_shell (const char *shell, const char *command, char **additional_args, 
const struct passwd *pw)
 {
   const char **args;
   int argno = 1;
+#ifdef USE_PAM
+  int child;
+  sigset_t ourset;
+  int status;
+
+  retval = pam_open_session(pamh,0);
+  if (retval != PAM_SUCCESS) {
+    fprintf (stderr, _("could not open session\n"));
+    exit (1);
+  }
+
+/* do this at the last possible moment, because environment variables may
+   be passed even in the session phase
+*/
+  if(pam_copyenv(pamh) != PAM_SUCCESS)
+     fprintf (stderr, _("error copying PAM environment\n"));
 
+  child = fork();
+  if (child == 0) {  /* child shell */
+  change_identity (pw);
+  pam_end(pamh, 0);
+#endif
   if (additional_args)
     args = (const char **) xmalloc (sizeof (char *)
                                    * (10 + elements (additional_args)));
@@ -408,6 +521,61 @@
    error (0, errno, "%s", shell);
    exit (exit_status);
   }
+#ifdef USE_PAM
+  } else if (child == -1) {
+      fprintf(stderr, _("cannot fork user shell: %s"), strerror(errno));
+      exit(1);
+  }
+  /* parent only */
+  sigfillset(&ourset);
+  if (sigprocmask(SIG_BLOCK, &ourset, NULL)) {
+    fprintf(stderr, _("%s: signal malfunction\n"), PROGRAM_NAME);
+    caught = 1;
+  }
+  if (!caught) {
+    struct sigaction action;
+    action.sa_handler = su_catch_sig;
+    sigemptyset(&action.sa_mask);
+    action.sa_flags = 0;
+    sigemptyset(&ourset);
+    if (sigaddset(&ourset, SIGTERM)
+        || sigaddset(&ourset, SIGALRM)
+        || sigaction(SIGTERM, &action, NULL)
+        || sigprocmask(SIG_UNBLOCK, &ourset, NULL)) {
+      fprintf(stderr, _("%s: signal masking malfunction\n"), PROGRAM_NAME);
+      caught = 1;
+    }
+  }
+  if (!caught) {
+    do {
+      int pid;
+
+      pid = waitpid(-1, &status, WUNTRACED);
+
+      if (WIFSTOPPED(status)) {
+          kill(getpid(), SIGSTOP);
+          /* once we get here, we must have resumed */
+          kill(pid, SIGCONT);
+      }
+    } while (WIFSTOPPED(status));
+  }
+
+  if (caught) {
+    fprintf(stderr, _("\nSession terminated, killing shell..."));
+    kill (child, SIGTERM);
+  }
+  retval = pam_close_session(pamh, 0);
+  PAM_BAIL_P;
+  retval = pam_end(pamh, PAM_SUCCESS);
+  PAM_BAIL_P;
+  if (caught) {
+    sleep(2);
+    kill(child, SIGKILL);
+    fprintf(stderr, _(" killed.\n"));
+    exit(-1);
+  }
+  exit (WEXITSTATUS(status));
+#endif /* USE_PAM */
 }
 
 /* Return 1 if SHELL is a restricted shell (one not returned by
@@ -580,9 +748,14 @@
     }
   modify_environment (pw, shell);
 
+
+#ifdef USE_PAM
+  setfsuid(pw->pw_uid);
+#else
   change_identity (pw);
+#endif
   if (simulate_login && chdir (pw->pw_dir))
     error (0, errno, _("warning: cannot change directory to %s"), pw->pw_dir);
 
-  run_shell (shell, command, additional_args);
+  run_shell (shell, command, additional_args, pw);
 }
--- coreutils-4.5.3.orig/po/pl.po       Fri Nov  1 01:55:42 2002
+++ coreutils-4.5.3/po/pl.po    Fri Nov  1 02:11:20 2002
@@ -6491,6 +6491,41 @@
 msgid "cannot set user id"
 msgstr "nie można ustawić identyfikatora użytkownika"
 
+#: src/su.c:468
+msgid "could not open session\n"
+msgstr "nie można otworzyć sesji\n"
+
+#: src/su.c:476
+msgid "error copying PAM environment\n"
+msgstr "błąd podczas kopiowania środowiska PAM\n"
+
+#: src/su.c:521
+#, c-format
+msgid "cannot fork user shell: %s"
+msgstr "nie można utworzyć procesu powłoki użytkownika: %s"
+
+#: src/su.c:527
+#, c-format
+msgid "%s: signal malfunction\n"
+msgstr "%s: błędne działanie sygnałów\n"
+
+#: src/su.c:540
+#, c-format
+msgid "%s: signal masking malfunction\n"
+msgstr "%s: błędne działanie maskowania sygnałów\n"
+
+#: src/su.c:559
+msgid ""
+"\n"
+"Session terminated, killing shell..."
+msgstr ""
+"\n"
+"Sesja zakończona, zabijanie powłoki..."
+
+#: src/su.c:569
+msgid " killed.\n"
+msgstr " zabito.\n"
+
 #: src/su.c:437
 #, c-format
 msgid "Usage: %s [OPTION]... [-] [USER [ARG]...]\n"
-- 
Arkadiusz Miśkiewicz    CS at FoE, Wroclaw University of Technology
address@hidden   AM2-6BONE, 1024/3DB19BBD, arekm(at)ircnet, PLD/Linux




reply via email to

[Prev in Thread] Current Thread [Next in Thread]