Submitted By: DJ Lucas (dj AT linuxfromscratch DOT org) Date: 2005-07-06 Initial Package Version: 4.0.9 Origin: http://lists.pld.org.pl/mailman/pipermail/shadow/2005-June/000125.html Upstream Status: Accepted Description: Fixes erroneous warning messages when used with Linux-PAM, backported from 4.0.10+ CVS. $LastChangedBy: bdubbs $ $Date: 2005-08-01 13:29:19 -0600 (Mon, 01 Aug 2005) $ diff -Naur shadow-4.0.9-orig/libmisc/setupenv.c shadow-4.0.9/libmisc/setupenv.c --- shadow-4.0.9-orig/libmisc/setupenv.c 2005-03-30 23:14:50.000000000 -0600 +++ shadow-4.0.9/libmisc/setupenv.c 2005-07-06 20:52:18.000000000 -0500 @@ -238,7 +238,17 @@ * Create the PATH environmental variable and export it. */ + /* + * Export the user name. For BSD derived systems, it's "USER", for + * all others it's "LOGNAME". We set both of them. + */ + + addenv ("USER", info->pw_name); + addenv ("LOGNAME", info->pw_name); + +#ifndef USE_PAM cp = getdef_str ((info->pw_uid == 0) ? "ENV_SUPATH" : "ENV_PATH"); + if (!cp) { /* not specified, use a minimal default */ addenv ("PATH=/bin:/usr/bin", NULL); @@ -251,14 +261,6 @@ } /* - * Export the user name. For BSD derived systems, it's "USER", for - * all others it's "LOGNAME". We set both of them. - */ - - addenv ("USER", info->pw_name); - addenv ("LOGNAME", info->pw_name); - - /* * MAILDIR environment variable for Qmail */ if ((cp = getdef_str ("QMAIL_DIR"))) @@ -274,6 +276,7 @@ else if ((cp = getdef_str ("MAIL_FILE"))) addenv_path ("MAIL", info->pw_dir, cp); else { + #if defined(MAIL_SPOOL_FILE) addenv_path ("MAIL", info->pw_dir, MAIL_SPOOL_FILE); #elif defined(MAIL_SPOOL_DIR) @@ -281,11 +284,10 @@ #endif } -#ifndef USE_PAM /* * Read environment from optional config file. --marekm */ if ((envf = getdef_str ("ENVIRON_FILE"))) read_env_file (envf); -#endif +#endif /* !USE_PAM */ } diff -Naur shadow-4.0.9-orig/libmisc/tz.c shadow-4.0.9/libmisc/tz.c --- shadow-4.0.9-orig/libmisc/tz.c 2003-04-22 05:59:22.000000000 -0500 +++ shadow-4.0.9/libmisc/tz.c 2005-07-06 20:52:18.000000000 -0500 @@ -49,8 +49,10 @@ if ((fp = fopen (fname, "r")) == NULL || fgets (tzbuf, sizeof (tzbuf), fp) == NULL) { +#ifndef USE_PAM if (!(def_tz = getdef_str ("ENV_TZ")) || def_tz[0] == '/') def_tz = "TZ=CST6CDT"; +#endif /* !USE_PAM */ strcpy (tzbuf, def_tz); } else diff -Naur shadow-4.0.9-orig/src/login.c shadow-4.0.9/src/login.c --- shadow-4.0.9-orig/src/login.c 2005-04-18 09:10:30.000000000 -0500 +++ shadow-4.0.9/src/login.c 2005-07-06 20:52:18.000000000 -0500 @@ -30,7 +30,7 @@ #include #include "rcsid.h" -RCSID (PKG_VER "$Id: login.c,v 1.52 2005/04/17 15:38:56 kloczek Exp $") +RCSID (PKG_VER "$Id: login.c,v 1.59 2005/06/20 09:36:27 kloczek Exp $") #include "prototypes.h" #include "defines.h" #include @@ -277,9 +277,11 @@ if ((tmp = getenv ("TZ"))) { addenv ("TZ", tmp); - } else if ((cp = getdef_str ("ENV_TZ"))) + } +#ifndef USE_PAM + else if ((cp = getdef_str ("ENV_TZ"))) addenv (*cp == '/' ? tz (cp) : cp, NULL); - +#endif /* !USE_PAM */ /* * Add the clock frequency so that profiling commands work * correctly. @@ -287,8 +289,11 @@ if ((tmp = getenv ("HZ"))) { addenv ("HZ", tmp); - } else if ((cp = getdef_str ("ENV_HZ"))) + } +#ifndef USE_PAM + else if ((cp = getdef_str ("ENV_HZ"))) addenv (cp, NULL); +#endif /* !USE_PAM */ } @@ -347,8 +352,7 @@ int retcode; pid_t child; char *pam_user; -#endif /* USE_PAM */ -#if defined(SHADOWPWD) && !defined(USE_PAM) +#else struct spwd *spwd = NULL; #endif /* @@ -369,7 +373,7 @@ check_flags (argc, argv); - while ((flag = getopt (argc, argv, "d:f:h:pr:")) != EOF) { + while ((flag = getopt (argc, argv, "d:f::h:pr:")) != EOF) { switch (flag) { case 'p': pflg++; @@ -378,11 +382,16 @@ /* * username must be a separate token * (-f root, *not* -froot). --marekm + * + * if -f has an arg, use that, else use the + * normal user name passed after all options + * --benc */ - if (optarg != argv[optind - 1]) + if (optarg != NULL && optarg != argv[optind - 1]) usage (); fflg++; - STRFCPY (username, optarg); + if (optarg) + STRFCPY (username, optarg); break; #ifdef RLOGIN case 'r': @@ -418,7 +427,7 @@ */ if ((rflg || fflg || hflg) && !amroot) { - fprintf (stderr, _("%s: permission denied.\n"), Prog); + fprintf (stderr, _("%s: Permission denied.\n"), Prog); exit (1); } @@ -498,6 +507,8 @@ setup_tty (); +#ifndef USE_PAM + umask (getdef_num ("UMASK", 077)); { @@ -514,6 +525,8 @@ set_filesize_limit (limit); } +#endif /* !USE_PAM */ + /* * The entire environment will be preserved if the -p flag * is used. @@ -535,7 +548,7 @@ init_env (); if (optind < argc) { /* get the user name */ - if (rflg || fflg) + if (rflg || (fflg && username[0])) usage (); STRFCPY (username, argv[optind]); @@ -703,11 +716,14 @@ if (!pwd || setup_groups (pwd)) exit (1); + else + pwent = *pwd; retcode = pam_setcred (pamh, PAM_ESTABLISH_CRED); PAM_FAIL_CHECK; - retcode = pam_open_session (pamh, 0); + retcode = pam_open_session (pamh, + hushed (&pwent) ? PAM_SILENT : 0); PAM_FAIL_CHECK; #else /* ! USE_PAM */ @@ -742,7 +758,6 @@ pwent = *pwd; } #ifndef USE_PAM -#ifdef SHADOWPWD spwd = NULL; if (pwd && strcmp (pwd->pw_passwd, SHADOW_PASSWD_STRING) == 0) { spwd = getspnam (username); @@ -753,7 +768,6 @@ "no shadow password for `%s'%s", username, fromhost)); } -#endif /* SHADOWPWD */ /* * If the encrypted password begins with a "!", the account @@ -918,9 +932,7 @@ subroot++; /* say i was here again */ endpwent (); /* close all of the file which were */ endgrent (); /* open in the original rooted file */ -#ifdef SHADOWPWD endspent (); /* system. they will be re-opened */ -#endif #ifdef SHADOWGRP endsgent (); /* in the new rooted file system */ #endif @@ -938,7 +950,6 @@ * and changes to the user in the child before executing the passwd * program. --marekm */ -#ifdef SHADOWPWD if (spwd) { /* check for age of password */ if (expire (&pwent, spwd)) { pwd = getpwnam (username); @@ -947,11 +958,44 @@ pwent = *pwd; } } -#endif /* SHADOWPWD */ setup_limits (&pwent); /* nice, ulimit etc. */ #endif /* ! USE_PAM */ chown_tty (tty, &pwent); +#ifdef USE_PAM + /* + * We must fork before setuid() because we need to call + * pam_close_session() as root. + * + * Note: not true in other (non-Linux) PAM implementations, where + * the parent process of login (init, telnetd, ...) is responsible + * for calling pam_close_session(). This avoids an extra process for + * each login. Maybe we should do this on Linux too? We let the + * admin configure whether they need to keep login around to close + * sessions. + */ + if (getdef_bool ("CLOSE_SESSIONS")) { + signal (SIGINT, SIG_IGN); + child = fork (); + if (child < 0) { + /* error in fork() */ + fprintf (stderr, + "login: failure forking: %s", + strerror (errno)); + PAM_END; + exit (0); + } else if (child) { + /* + * parent - wait for child to finish, then cleanup + * session + */ + wait (NULL); + PAM_END; + exit (0); + } + /* child */ + } +#endif /* We call set_groups() above because this clobbers pam_groups.so */ #ifndef USE_PAM if (setup_uid_gid (&pwent, is_console)) @@ -1021,11 +1065,7 @@ #endif printf (".\n"); } -#ifdef SHADOWPWD agecheck (&pwent, spwd); -#else - agecheck (&pwent); -#endif mailcheck (); /* report on the status of mail */ #endif /* !USE_PAM */ @@ -1039,55 +1079,22 @@ signal (SIGTERM, SIG_DFL); /* default terminate signal */ signal (SIGALRM, SIG_DFL); /* default alarm signal */ signal (SIGHUP, SIG_DFL); /* added this. --marekm */ - -#ifdef USE_PAM - /* - * We must fork before setuid() because we need to call - * pam_close_session() as root. - * - * Note: not true in other (non-Linux) PAM implementations, where - * the parent process of login (init, telnetd, ...) is responsible - * for calling pam_close_session(). This avoids an extra process for - * each login. Maybe we should do this on Linux too? We let the - * admin configure whether they need to keep login around to close - * sessions. - */ - if (getdef_bool ("CLOSE_SESSIONS")) { - signal (SIGINT, SIG_IGN); - child = fork (); - if (child < 0) { - /* error in fork() */ - fprintf (stderr, - "login: failure forking: %s", - strerror (errno)); - PAM_END; - exit (0); - } else if (child) { - /* - * parent - wait for child to finish, then cleanup - * session - */ - wait (NULL); - PAM_END; - exit (0); - } - /* child */ - } -#endif signal (SIGINT, SIG_DFL); /* default interrupt signal */ endpwent (); /* stop access to password file */ endgrent (); /* stop access to group file */ -#ifdef SHADOWPWD endspent (); /* stop access to shadow passwd file */ -#endif #ifdef SHADOWGRP endsgent (); /* stop access to shadow group file */ #endif if (pwent.pw_uid == 0) SYSLOG ((LOG_NOTICE, "ROOT LOGIN %s", fromhost)); else if (getdef_bool ("LOG_OK_LOGINS")) +#ifdef USE_PAM + SYSLOG ((LOG_INFO, "`%s' logged in %s", pam_user, fromhost)); +#else SYSLOG ((LOG_INFO, "`%s' logged in %s", username, fromhost)); +#endif closelog (); if ((tmp = getdef_str ("FAKE_SHELL")) != NULL) { shell (tmp, pwent.pw_shell); /* fake shell */ diff -Naur shadow-4.0.9-orig/src/su.c shadow-4.0.9/src/su.c --- shadow-4.0.9-orig/src/su.c 2005-04-02 08:09:48.000000000 -0600 +++ shadow-4.0.9/src/su.c 2005-07-06 20:52:18.000000000 -0500 @@ -30,17 +30,11 @@ #include #include "rcsid.h" -RCSID (PKG_VER "$Id: su.c,v 1.30 2005/04/02 14:09:48 kloczek Exp $") +RCSID (PKG_VER "$Id: su.c,v 1.34 2005/06/20 10:17:08 kloczek Exp $") #include #include #ifdef USE_PAM #include "pam_defs.h" -static const struct pam_conv conv = { - misc_conv, - NULL -}; - -static pam_handle_t *pamh = NULL; #endif #include "prototypes.h" @@ -64,8 +58,18 @@ static char name[BUFSIZ]; static char oldname[BUFSIZ]; -static char *Prog; +#ifdef USE_PAM +static const struct pam_conv conv = { + misc_conv, + NULL +}; +static pam_handle_t *pamh = NULL; +#endif + +static int caught = 0; + +static char *Prog; extern struct passwd pwent; /* @@ -73,9 +77,8 @@ */ extern char **newenvp; -extern size_t newenvc; - extern char **environ; +extern size_t newenvc; /* local function prototypes */ @@ -125,7 +128,7 @@ #ifdef USE_SYSLOG if (getdef_bool ("SYSLOG_SU_ENAB")) SYSLOG ((pwent.pw_uid ? LOG_INFO : LOG_NOTICE, - "- %s %s-%s", tty, + "- %s %s:%s", tty, oldname[0] ? oldname : "???", name[0] ? name : "???")); closelog (); #endif @@ -133,9 +136,8 @@ exit (1); } -#ifdef USE_PAM -static int caught = 0; +#ifdef USE_PAM /* Signal handler for parent process later */ static void su_catch_sig (int sig) { @@ -270,9 +272,8 @@ RETSIGTYPE (*oldsig) (); int is_console = 0; -#ifdef SHADOWPWD struct spwd *spwd = 0; -#endif + #ifdef SU_ACCESS char *oldpass; #endif @@ -342,13 +343,6 @@ */ if (fakelogin) { - if ((cp = getdef_str ("ENV_TZ"))) - addenv (*cp == '/' ? tz (cp) : cp, NULL); - /* - * The clock frequency will be reset to the login value if required - */ - if ((cp = getdef_str ("ENV_HZ"))) - addenv (cp, NULL); /* set the default $HZ, if one */ /* * The terminal type will be left alone if it is present in * the environment already. @@ -356,6 +350,13 @@ if ((cp = getenv ("TERM"))) addenv ("TERM", cp); #ifndef USE_PAM + if ((cp = getdef_str ("ENV_TZ"))) + addenv (*cp == '/' ? tz (cp) : cp, NULL); + /* + * The clock frequency will be reset to the login value if required + */ + if ((cp = getdef_str ("ENV_HZ"))) + addenv (cp, NULL); /* set the default $HZ, if one */ /* * Also leave DISPLAY and XAUTHORITY if present, else * pam_xauth will not work. @@ -405,10 +406,8 @@ * Sort out the password of user calling su, in case needed later * -- chris */ -#ifdef SHADOWPWD if ((spwd = getspnam (oldname))) pw->pw_passwd = spwd->sp_pwdp; -#endif oldpass = xstrdup (pw->pw_passwd); #endif /* SU_ACCESS */ @@ -449,12 +448,10 @@ exit (1); } #ifndef USE_PAM -#ifdef SHADOWPWD spwd = NULL; if (strcmp (pw->pw_passwd, SHADOW_PASSWD_STRING) == 0 && (spwd = getspnam (name))) pw->pw_passwd = spwd->sp_pwdp; -#endif #endif /* !USE_PAM */ pwent = *pw; @@ -466,7 +463,7 @@ /* The original Shadow 3.3.2 did this differently. Do it like BSD: * - * - check for uid 0 instead of name "root" - there are systems with + * - check for UID 0 instead of name "root" - there are systems with * several root accounts under different names, * * - check the contents of /etc/group instead of the current group @@ -563,7 +560,6 @@ */ if (!amroot) { -#ifdef SHADOWPWD if (!spwd) spwd = pwd_to_spwd (&pwent); @@ -572,7 +568,6 @@ "Expired account %s", name)); su_failure (tty); } -#endif } /* @@ -593,6 +588,7 @@ #endif /* !USE_PAM */ signal (SIGINT, SIG_DFL); +#ifndef USE_PAM cp = getdef_str ((pwent.pw_uid == 0) ? "ENV_SUPATH" : "ENV_PATH"); /* XXX very similar code duplicated in libmisc/setupenv.c */ @@ -604,10 +600,8 @@ addenv ("PATH", cp); } -/* setup the environment for pam later on, else we run into auth problems */ -#ifndef USE_PAM environ = newenvp; /* make new environment active */ -#endif +#endif /* !USE_PAM */ if (getenv ("IFS")) /* don't export user IFS ... */ addenv ("IFS= \t\n", NULL); /* ... instead, set a safe IFS */ @@ -616,20 +610,16 @@ pwent.pw_shell++; /* skip the '*' */ subsystem (&pwent); /* figure out what to execute */ endpwent (); -#ifdef SHADOWPWD endspent (); -#endif goto top; } sulog (tty, 1, oldname, name); /* save SU information */ endpwent (); -#ifdef SHADOWPWD endspent (); -#endif #ifdef USE_SYSLOG if (getdef_bool ("SYSLOG_SU_ENAB")) - SYSLOG ((LOG_INFO, "+ %s %s-%s", tty, + SYSLOG ((LOG_INFO, "+ %s %s:%s", tty, oldname[0] ? oldname : "???", name[0] ? name : "???")); #endif diff -Naur shadow-4.0.9-orig/src/sulogin.c shadow-4.0.9/src/sulogin.c --- shadow-4.0.9-orig/src/sulogin.c 2005-03-30 23:14:54.000000000 -0600 +++ shadow-4.0.9/src/sulogin.c 2005-07-06 20:52:18.000000000 -0500 @@ -140,10 +140,14 @@ while (*envp) /* add inherited environment, */ addenv (*envp++, NULL); /* some variables change later */ +#ifndef USE_PAM + if ((cp = getdef_str ("ENV_TZ"))) addenv (*cp == '/' ? tz (cp) : cp, NULL); if ((cp = getdef_str ("ENV_HZ"))) addenv (cp, NULL); /* set the default $HZ, if one */ +#endif /* !USE_PAM */ + (void) strcpy (name, "root"); /* KLUDGE!!! */ signal (SIGALRM, catch); /* exit if the timer expires */