]> git.pld-linux.org Git - packages/coreutils.git/blame - coreutils-pam.patch
- make sure it won't go to builders without fixing patch8
[packages/coreutils.git] / coreutils-pam.patch
CommitLineData
ca7ee99d
JR
1--- coreutils-6.7/src/Makefile.am.pam 2006-11-24 21:28:10.000000000 +0000
2+++ coreutils-6.7/src/Makefile.am 2007-01-09 17:00:01.000000000 +0000
3@@ -103,7 +103,7 @@
4 # If necessary, add -lm to resolve use of pow in lib/strtod.c.
5 uptime_LDADD = $(LDADD) $(POW_LIB) $(GETLOADAVG_LIBS)
f774849c 6
ca7ee99d
JR
7-su_LDADD = $(LDADD) $(LIB_CRYPT)
8+su_LDADD = $(LDADD) $(LIB_CRYPT) $(LIB_PAM)
9
10 dir_LDADD += $(LIB_ACL)
11 ls_LDADD += $(LIB_ACL)
3c350007
JB
12--- coreutils-6.10/src/su.c.orig 2007-11-25 14:23:31.000000000 +0100
13+++ coreutils-6.10/src/su.c 2008-03-02 02:07:13.568059486 +0100
14@@ -37,6 +37,16 @@
ca7ee99d
JR
15 restricts who can su to UID 0 accounts. RMS considers that to
16 be fascist.
17
18+#ifdef USE_PAM
f774849c 19+
ca7ee99d
JR
20+ Actually, with PAM, su has nothing to do with whether or not a
21+ wheel group is enforced by su. RMS tries to restrict your access
22+ to a su which implements the wheel group, but PAM considers that
23+ to be fascist, and gives the user/sysadmin the opportunity to
24+ enforce a wheel group by proper editing of /etc/pam.conf
25+
26+#endif
27+
28 Compile-time options:
29 -DSYSLOG_SUCCESS Log successful su's (by default, to root) with syslog.
30 -DSYSLOG_FAILURE Log failed su's (by default, to root) with syslog.
3c350007 31@@ -58,6 +68,15 @@
ca7ee99d
JR
32 prototype (returning `int') in <unistd.h>. */
33 #define getusershell _getusershell_sys_proto_
f774849c 34
ca7ee99d
JR
35+#ifdef USE_PAM
36+# include <signal.h>
37+# include <sys/wait.h>
38+# include <sys/fsuid.h>
39+# include <unistd.h>
40+# include <security/pam_appl.h>
41+# include <security/pam_misc.h>
42+#endif /* USE_PAM */
f774849c 43+
ca7ee99d
JR
44 #include "system.h"
45 #include "getpass.h"
f774849c 46
3c350007 47@@ -118,15 +137,22 @@
ca7ee99d
JR
48 /* The user to become if none is specified. */
49 #define DEFAULT_USER "root"
f774849c 50
ca7ee99d
JR
51+#ifndef USE_PAM
52 char *crypt ();
53+#endif
54 char *getusershell ();
55 void endusershell ();
56 void setusershell ();
f774849c 57
58 extern char **environ;
59
c2be74f0 60-static void run_shell (char const *, char const *, char **, size_t)
ca7ee99d
JR
61+static void run_shell (char const *, char const *, char **, size_t,
62+ const struct passwd *)
63+#ifdef USE_PAM
64+ ;
65+#else
f774849c 66 ATTRIBUTE_NORETURN;
ca7ee99d 67+#endif
f774849c 68
69 /* The name this program was run with. */
ca7ee99d 70 char *program_name;
3c350007 71@@ -215,7 +241,26 @@
f774849c 72 }
73 #endif
74
75+#ifdef USE_PAM
76+static pam_handle_t *pamh = NULL;
77+static int retval;
78+static struct pam_conv conv = {
79+ misc_conv,
80+ NULL
81+};
82+
83+#define PAM_BAIL_P if (retval) { \
84+ pam_end(pamh, PAM_SUCCESS); \
85+ return 0; \
86+}
ca7ee99d
JR
87+#define PAM_BAIL_P_VOID if (retval) { \
88+ pam_end(pamh, PAM_SUCCESS); \
89+return; \
90+}
f774849c 91+#endif
92+
93 /* Ask the user for a password.
94+ If PAM is in use, let PAM ask for the password if necessary.
c2be74f0
JB
95 Return true if the user gives the correct password for entry PW,
96 false if not. Return true without asking for a password if run by UID 0
f774849c 97 or if PW has an empty password. */
3c350007 98@@ -223,6 +268,44 @@
c2be74f0 99 static bool
f774849c 100 correct_password (const struct passwd *pw)
101 {
102+#ifdef USE_PAM
ca7ee99d
JR
103+ struct passwd *caller;
104+ char *tty_name, *ttyn;
f774849c 105+ retval = pam_start(PROGRAM_NAME, pw->pw_name, &conv, &pamh);
106+ PAM_BAIL_P;
107+
ca7ee99d
JR
108+ if (getuid() != 0 && !isatty(0)) {
109+ fprintf(stderr, _("standard in must be a tty\n"));
110+ exit(1);
111+ }
112+
113+ caller = getpwuid(getuid());
114+ if(caller != NULL && caller->pw_name != NULL) {
115+ retval = pam_set_item(pamh, PAM_RUSER, caller->pw_name);
116+ PAM_BAIL_P;
117+ }
118+
119+ ttyn = ttyname(0);
120+ if (ttyn) {
121+ if (strncmp(ttyn, "/dev/", 5) == 0)
122+ tty_name = ttyn+5;
123+ else
124+ tty_name = ttyn;
125+ retval = pam_set_item(pamh, PAM_TTY, tty_name);
126+ PAM_BAIL_P;
127+ }
f774849c 128+ retval = pam_authenticate(pamh, 0);
129+ PAM_BAIL_P;
f774849c 130+ retval = pam_acct_mgmt(pamh, 0);
ca7ee99d 131+ if (retval == PAM_NEW_AUTHTOK_REQD && getuid()) {
f774849c 132+ /* password has expired. Offer option to change it. */
ca7ee99d
JR
133+ retval = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
134+ PAM_BAIL_P;
f774849c 135+ }
136+ PAM_BAIL_P;
137+ /* must be authenticated if this point was reached */
138+ return 1;
139+#else /* !USE_PAM */
140 char *unencrypted, *encrypted, *correct;
141 #if HAVE_GETSPNAM && HAVE_STRUCT_SPWD_SP_PWDP
142 /* Shadow passwd stuff for SVR3 and maybe other systems. */
3c350007 143@@ -247,6 +330,7 @@
f774849c 144 encrypted = crypt (unencrypted, correct);
145 memset (unencrypted, 0, strlen (unencrypted));
c2be74f0 146 return STREQ (encrypted, correct);
f774849c 147+#endif /* !USE_PAM */
148 }
149
150 /* Update `environ' for the new shell based on PW, with SHELL being
3c350007 151@@ -260,12 +344,18 @@
ca7ee99d 152 /* Leave TERM unchanged. Set HOME, SHELL, USER, LOGNAME, PATH.
f774849c 153 Unset all other environment variables. */
c2be74f0
JB
154 char const *term = getenv ("TERM");
155+ char const *display = getenv ("DISPLAY");
ca7ee99d 156+ char const *xauthority = getenv ("XAUTHORITY");
c2be74f0
JB
157 if (term)
158 term = xstrdup (term);
ca7ee99d 159 environ = xmalloc ((6 + !!term) * sizeof (char *));
c2be74f0 160 environ[0] = NULL;
f774849c 161 if (term)
c2be74f0 162 xsetenv ("TERM", term);
f774849c 163+ if (display)
c2be74f0 164+ xsetenv ("DISPLAY", display);
ca7ee99d
JR
165+ if (xauthority)
166+ xsetenv ("XAUTHORITY", xauthority);
c2be74f0
JB
167 xsetenv ("HOME", pw->pw_dir);
168 xsetenv ("SHELL", shell);
169 xsetenv ("USER", pw->pw_name);
3c350007 170@@ -298,8 +388,13 @@
ca7ee99d
JR
171 {
172 #ifdef HAVE_INITGROUPS
173 errno = 0;
174- if (initgroups (pw->pw_name, pw->pw_gid) == -1)
175+ if (initgroups (pw->pw_name, pw->pw_gid) == -1) {
176+#ifdef USE_PAM
177+ pam_close_session(pamh, 0);
178+ pam_end(pamh, PAM_ABORT);
179+#endif
3c350007 180 error (EXIT_FAILURE, errno, _("cannot set groups"));
ca7ee99d 181+ }
f774849c 182 endgrent ();
183 #endif
f774849c 184 if (setgid (pw->pw_gid))
3c350007
JB
185@@ -308,6 +403,31 @@
186 error (EXIT_FAILURE, errno, _("cannot set user id"));
f774849c 187 }
188
189+#ifdef USE_PAM
190+static int caught=0;
191+/* Signal handler for parent process later */
192+static void su_catch_sig(int sig)
193+{
194+ ++caught;
195+}
196+
197+int
198+pam_copyenv (pam_handle_t *pamh)
199+{
200+ char **env;
ca7ee99d 201+
f774849c 202+ env = pam_getenvlist(pamh);
203+ if(env) {
204+ while(*env) {
ca7ee99d
JR
205+ if (putenv (*env))
206+ xalloc_die ();
f774849c 207+ env++;
208+ }
209+ }
210+ return(0);
211+}
212+#endif
213+
214 /* Run SHELL, or DEFAULT_SHELL if SHELL is empty.
215 If COMMAND is nonzero, pass it to the shell with the -c option.
c2be74f0 216 Pass ADDITIONAL_ARGS to the shell as more arguments; there
3c350007 217@@ -315,17 +435,49 @@
f774849c 218
219 static void
c2be74f0
JB
220 run_shell (char const *shell, char const *command, char **additional_args,
221- size_t n_additional_args)
222+ size_t n_additional_args, const struct passwd *pw)
f774849c 223 {
c2be74f0
JB
224 size_t n_args = 1 + fast_startup + 2 * !!command + n_additional_args + 1;
225 char const **args = xnmalloc (n_args, sizeof *args);
226 size_t argno = 1;
f774849c 227+#ifdef USE_PAM
228+ int child;
229+ sigset_t ourset;
230+ int status;
231+
232+ retval = pam_open_session(pamh,0);
233+ if (retval != PAM_SUCCESS) {
40ce7301 234+ fprintf (stderr, _("could not open session\n"));
f774849c 235+ exit (1);
236+ }
237+
238+/* do this at the last possible moment, because environment variables may
239+ be passed even in the session phase
240+*/
241+ if(pam_copyenv(pamh) != PAM_SUCCESS)
40ce7301 242+ fprintf (stderr, _("error copying PAM environment\n"));
700628e7 243+
ca7ee99d
JR
244+ /* Credentials should be set in the parent */
245+ if (pam_setcred(pamh, PAM_ESTABLISH_CRED) != PAM_SUCCESS) {
246+ pam_close_session(pamh, 0);
247+ fprintf(stderr, _("could not set PAM credentials\n"));
248+ exit(1);
249+ }
250+
f774849c 251+ child = fork();
252+ if (child == 0) { /* child shell */
253+ change_identity (pw);
254+ pam_end(pamh, 0);
255+#endif
ca7ee99d 256
c2be74f0
JB
257 if (simulate_login)
258 {
259 char *arg0;
ca7ee99d
JR
260 char *shell_basename;
261
262+ if(chdir(pw->pw_dir))
263+ error(0, errno, _("warning: cannot change directory to %s"), pw->pw_dir);
264+
265 shell_basename = last_component (shell);
266 arg0 = xmalloc (strlen (shell_basename) + 2);
267 arg0[0] = '-';
3c350007 268@@ -350,6 +502,66 @@
700628e7
JB
269 error (0, errno, "%s", shell);
270 exit (exit_status);
f774849c 271 }
272+#ifdef USE_PAM
273+ } else if (child == -1) {
ca7ee99d
JR
274+ fprintf(stderr, _("can not fork user shell: %s"), strerror(errno));
275+ pam_setcred(pamh, PAM_DELETE_CRED | PAM_SILENT);
276+ pam_close_session(pamh, 0);
277+ pam_end(pamh, PAM_ABORT);
f774849c 278+ exit(1);
279+ }
280+ /* parent only */
281+ sigfillset(&ourset);
282+ if (sigprocmask(SIG_BLOCK, &ourset, NULL)) {
40ce7301 283+ fprintf(stderr, _("%s: signal malfunction\n"), PROGRAM_NAME);
f774849c 284+ caught = 1;
285+ }
286+ if (!caught) {
287+ struct sigaction action;
288+ action.sa_handler = su_catch_sig;
289+ sigemptyset(&action.sa_mask);
290+ action.sa_flags = 0;
291+ sigemptyset(&ourset);
292+ if (sigaddset(&ourset, SIGTERM)
293+ || sigaddset(&ourset, SIGALRM)
294+ || sigaction(SIGTERM, &action, NULL)
295+ || sigprocmask(SIG_UNBLOCK, &ourset, NULL)) {
40ce7301 296+ fprintf(stderr, _("%s: signal masking malfunction\n"), PROGRAM_NAME);
f774849c 297+ caught = 1;
298+ }
299+ }
300+ if (!caught) {
301+ do {
302+ int pid;
303+
304+ pid = waitpid(-1, &status, WUNTRACED);
305+
306+ if (WIFSTOPPED(status)) {
307+ kill(getpid(), SIGSTOP);
308+ /* once we get here, we must have resumed */
309+ kill(pid, SIGCONT);
310+ }
311+ } while (WIFSTOPPED(status));
312+ }
313+
314+ if (caught) {
40ce7301 315+ fprintf(stderr, _("\nSession terminated, killing shell..."));
f774849c 316+ kill (child, SIGTERM);
317+ }
ca7ee99d
JR
318+ /* Not checking retval on this because we need to call close session */
319+ pam_setcred(pamh, PAM_DELETE_CRED | PAM_SILENT);
f774849c 320+ retval = pam_close_session(pamh, 0);
ca7ee99d 321+ PAM_BAIL_P_VOID;
f774849c 322+ retval = pam_end(pamh, PAM_SUCCESS);
ca7ee99d 323+ PAM_BAIL_P_VOID;
f774849c 324+ if (caught) {
325+ sleep(2);
326+ kill(child, SIGKILL);
ca7ee99d 327+ fprintf(stderr, _(" ...killed.\n"));
f774849c 328+ exit(-1);
329+ }
330+ exit (WEXITSTATUS(status));
331+#endif /* USE_PAM */
332 }
333
c2be74f0 334 /* Return true if SHELL is a restricted shell (one not returned by
3c350007 335@@ -517,9 +729,9 @@
c2be74f0 336 shell = xstrdup (shell ? shell : pw->pw_shell);
f774849c 337 modify_environment (pw, shell);
338
ca7ee99d 339+#ifndef USE_PAM
f774849c 340 change_identity (pw);
ca7ee99d
JR
341- if (simulate_login && chdir (pw->pw_dir) != 0)
342- error (0, errno, _("warning: cannot change directory to %s"), pw->pw_dir);
f774849c 343+#endif
f774849c 344
c2be74f0
JB
345- run_shell (shell, command, argv + optind, MAX (0, argc - optind));
346+ run_shell (shell, command, argv + optind, MAX (0, argc - optind), pw);
f774849c 347 }
ca7ee99d
JR
348--- coreutils-6.7/doc/coreutils.texi.pam 2006-10-27 15:30:48.000000000 +0100
349+++ coreutils-6.7/doc/coreutils.texi 2007-01-09 17:00:01.000000000 +0000
350@@ -13395,8 +13395,11 @@
351 @findex syslog
352 @command{su} can optionally be compiled to use @code{syslog} to report
353 failed, and optionally successful, @command{su} attempts. (If the system
354-supports @code{syslog}.) However, GNU @command{su} does not check if the
355-user is a member of the @code{wheel} group; see below.
356+supports @code{syslog}.)
357+
358+This version of @command{su} has support for using PAM for
359+authentication. You can edit @file{/etc/pam.d/su} to customize its
360+behaviour.
361
362 The program accepts the following options. Also see @ref{Common options}.
363
364@@ -11892,32 +11892,6 @@
365 the exit status of the subshell otherwise
366 @end display
367
368-@cindex wheel group, not supported
369-@cindex group wheel, not supported
370-@cindex fascism
371-@subsection Why GNU @command{su} does not support the @samp{wheel} group
372-
373-(This section is by Richard Stallman.)
374-
375-@cindex Twenex
376-@cindex MIT AI lab
377-Sometimes a few of the users try to hold total power over all the
378-rest. For example, in 1984, a few users at the MIT AI lab decided to
379-seize power by changing the operator password on the Twenex system and
380-keeping it secret from everyone else. (I was able to thwart this coup
381-and give power back to the users by patching the kernel, but I
382-wouldn't know how to do that in Unix.)
383-
384-However, occasionally the rulers do tell someone. Under the usual
385-@command{su} mechanism, once someone learns the root password who
386-sympathizes with the ordinary users, he or she can tell the rest. The
387-``wheel group'' feature would make this impossible, and thus cement the
388-power of the rulers.
389-
390-I'm on the side of the masses, not that of the rulers. If you are
391-used to supporting the bosses and sysadmins in whatever they do, you
392-might find this idea strange at first.
393-
394
395 @node Delaying
396 @chapter Delaying
3c350007
JB
397--- coreutils-6.10/configure.ac.orig 2008-01-13 09:14:23.000000000 +0100
398+++ coreutils-6.10/configure.ac 2008-03-02 02:08:10.027276914 +0100
399@@ -44,6 +44,13 @@
ca7ee99d
JR
400 gl_INIT
401 coreutils_MACROS
402
403+dnl Give the chance to enable PAM
404+AC_ARG_ENABLE(pam, dnl
405+[ --enable-pam Enable use of the PAM libraries],
c1e30285 406+AC_DEFINE(USE_PAM, 1, [Define if you want to use PAM])
ca7ee99d
JR
407+LIB_PAM="-ldl -lpam -lpam_misc"
408+)
409+
3c350007
JB
410 AC_FUNC_FORK
411
412 optional_bin_progs=
413@@ -332,6 +339,13 @@
ca7ee99d
JR
414 AM_GNU_GETTEXT([external], [need-formatstring-macros])
415 AM_GNU_GETTEXT_VERSION([0.15])
416
417+# just in case we want PAM
418+AC_SUBST(LIB_PAM)
419+# with PAM su doesn't need libcrypt
420+if test -n "$LIB_PAM" ; then
421+ LIB_CRYPT=
422+fi
423+
424 AC_CONFIG_FILES(
425 Makefile
426 doc/Makefile
3c350007
JB
427--- coreutils-6.10/po/pl.po.orig 2008-01-16 21:22:08.000000000 +0100
428+++ coreutils-6.10/po/pl.po 2008-03-02 02:09:23.671473657 +0100
429@@ -8875,6 +8875,49 @@
ca7ee99d 430 msgid "Usage: %s [OPTION]... [-] [USER [ARG]...]\n"
e87f5ed5 431