diff options
author | markm <markm@FreeBSD.org> | 2001-03-27 19:40:51 +0000 |
---|---|---|
committer | markm <markm@FreeBSD.org> | 2001-03-27 19:40:51 +0000 |
commit | f767ca7e60f2f04f4d7f30da195b56abab4296df (patch) | |
tree | 2c45c3c7d9ffb06e8a26fdf6d772beb282ddfad9 /usr.bin/login | |
parent | 51ca15c2dcae271222dd76f75c0c909596323a8c (diff) | |
download | FreeBSD-src-f767ca7e60f2f04f4d7f30da195b56abab4296df.zip FreeBSD-src-f767ca7e60f2f04f4d7f30da195b56abab4296df.tar.gz |
Add full PAM support for account management and sessions.
The PAM_FAIL_CHECK and PAM_END macros in su.c came from the util-linux
package's PAM patches to the BSD login.c
Submitted by: "David J. MacKenzie" <djm@web.us.uu.net>
Diffstat (limited to 'usr.bin/login')
-rw-r--r-- | usr.bin/login/Makefile | 5 | ||||
-rw-r--r-- | usr.bin/login/login.1 | 7 | ||||
-rw-r--r-- | usr.bin/login/login.c | 122 |
3 files changed, 102 insertions, 32 deletions
diff --git a/usr.bin/login/Makefile b/usr.bin/login/Makefile index a9a42bc..970e591 100644 --- a/usr.bin/login/Makefile +++ b/usr.bin/login/Makefile @@ -10,9 +10,8 @@ CFLAGS+=-Wall -DLOGIN_ACCESS -DLOGALL DPADD= ${LIBUTIL} ${LIBCRYPT} LDADD= -lutil -lcrypt -.if defined(NOPAM) -CFLAGS+= -DNO_PAM -.else +.if !defined(NOPAM) +CFLAGS+= -DUSE_PAM DPADD+= ${LIBPAM} LDADD+= ${MINUSLPAM} .endif diff --git a/usr.bin/login/login.1 b/usr.bin/login/login.1 index 492b983..4b1b66c 100644 --- a/usr.bin/login/login.1 +++ b/usr.bin/login/login.1 @@ -177,6 +177,13 @@ system mailboxes makes login quieter .It Pa /etc/auth.conf configure authentication services +.It Pa /etc/pam.conf +if +.Nm +is configured with PAM support, it uses +.Pa /etc/pam.conf +entries with service name +.Dq login .El .Sh SEE ALSO .Xr builtin 1 , diff --git a/usr.bin/login/login.c b/usr.bin/login/login.c index 7f7a09b..7ddc948 100644 --- a/usr.bin/login/login.c +++ b/usr.bin/login/login.c @@ -78,10 +78,11 @@ static const char rcsid[] = #include <unistd.h> #include <utmp.h> -#ifndef NO_PAM +#ifdef USE_PAM #include <security/pam_appl.h> #include <security/pam_misc.h> -#endif +#include <sys/wait.h> +#endif /* USE_PAM */ #include "pathnames.h" @@ -104,11 +105,23 @@ void timedout __P((int)); int login_access __P((char *, char *)); void login_fbtab __P((char *, uid_t, gid_t)); -#ifndef NO_PAM +#ifdef USE_PAM static int auth_pam __P((void)); static int export_pam_environment __P((void)); static int ok_to_export __P((const char *)); -#endif + +static pam_handle_t *pamh = NULL; +static char **environ_pam; + +#define PAM_END { \ + if ((e = pam_setcred(pamh, PAM_DELETE_CRED)) != PAM_SUCCESS) \ + syslog(LOG_ERR, "pam_setcred: %s", pam_strerror(pamh, e)); \ + if ((e = pam_close_session(pamh,0)) != PAM_SUCCESS) \ + syslog(LOG_ERR, "pam_close_session: %s", pam_strerror(pamh, e)); \ + if ((e = pam_end(pamh, e)) != PAM_SUCCESS) \ + syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e)); \ +} +#endif /* USE_PAM */ static int auth_traditional __P((void)); extern void login __P((struct utmp *)); static void usage __P((void)); @@ -130,9 +143,6 @@ struct passwd *pwd; int failures; char *term, *envinit[1], *hostname, *username, *tty; char full_hostname[MAXHOSTNAMELEN]; -#ifndef NO_PAM -static char **environ_pam; -#endif int main(argc, argv) @@ -155,6 +165,10 @@ main(argc, argv) char tname[sizeof(_PATH_TTY) + 10]; char *shell = NULL; login_cap_t *lc = NULL; +#ifdef USE_PAM + pid_t pid; + int e; +#endif /* USE_PAM */ (void)signal(SIGQUIT, SIG_IGN); (void)signal(SIGINT, SIG_IGN); @@ -314,19 +328,19 @@ main(argc, argv) (void)setpriority(PRIO_PROCESS, 0, -4); -#ifndef NO_PAM +#ifdef USE_PAM /* * Try to authenticate using PAM. If a PAM system error * occurs, perhaps because of a botched configuration, * then fall back to using traditional Unix authentication. */ if ((rval = auth_pam()) == -1) -#endif /* NO_PAM */ +#endif /* USE_PAM */ rval = auth_traditional(); (void)setpriority(PRIO_PROCESS, 0, 0); -#ifndef NO_PAM +#ifdef USE_PAM /* * PAM authentication may have changed "pwd" to the * entry for the template user. Check again to see if @@ -334,7 +348,7 @@ main(argc, argv) */ if (pwd != NULL && pwd->pw_uid == 0) rootlogin = 1; -#endif /* NO_PAM */ +#endif /* USE_PAM */ ttycheck: /* @@ -553,14 +567,54 @@ main(argc, argv) if (!pflag) environ = envinit; -#ifndef NO_PAM +#ifdef USE_PAM /* * Add any environmental variables that the * PAM modules may have set. */ - if (environ_pam) - export_pam_environment(); -#endif + if (pamh) { + environ_pam = pam_getenvlist(pamh); + if (environ_pam) + export_pam_environment(); + } +#endif /* USE_PAM */ + + /* + * PAM modules might add supplementary groups during pam_setcred(). + */ + if (setusercontext(lc, pwd, pwd->pw_uid, LOGIN_SETGROUP) != 0) { + syslog(LOG_ERR, "setusercontext() failed - exiting"); + exit(1); + } + +#ifdef USE_PAM + if (pamh) { + if ((e = pam_open_session(pamh, 0)) != PAM_SUCCESS) { + syslog(LOG_ERR, "pam_open_session: %s", pam_strerror(pamh, e)); + } else if ((e = pam_setcred(pamh, PAM_ESTABLISH_CRED)) != PAM_SUCCESS) { + syslog(LOG_ERR, "pam_setcred: %s", pam_strerror(pamh, e)); + } + + /* + * We must fork() before setuid() because we need to call + * pam_close_session() as root. + */ + pid = fork(); + if (pid < 0) { + err(1, "fork"); + PAM_END; + exit(0); + } else if (pid) { + /* parent - wait for child to finish, then cleanup session */ + wait(NULL); + PAM_END; + exit(0); + } else { + if ((e = pam_end(pamh, PAM_DATA_SILENT)) != PAM_SUCCESS) + syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e)); + } + } +#endif /* USE_PAM */ /* * We don't need to be root anymore, so @@ -571,7 +625,7 @@ main(argc, argv) exit(1); } if (setusercontext(lc, pwd, pwd->pw_uid, - LOGIN_SETALL & ~LOGIN_SETLOGIN) != 0) { + LOGIN_SETALL & ~(LOGIN_SETLOGIN|LOGIN_SETGROUP)) != 0) { syslog(LOG_ERR, "setusercontext() failed - exiting"); exit(1); } @@ -666,7 +720,7 @@ auth_traditional() return rval; } -#ifndef NO_PAM +#ifdef USE_PAM /* * Attempt to authenticate the user using PAM. Returns 0 if the user is * authenticated, or 1 if not authenticated. If some sort of PAM system @@ -677,7 +731,6 @@ auth_traditional() static int auth_pam() { - pam_handle_t *pamh = NULL; const char *tmpl_user; const void *item; int rval; @@ -728,11 +781,6 @@ auth_pam() } else syslog(LOG_ERR, "Couldn't get PAM_USER: %s", pam_strerror(pamh, e)); - if ((e = pam_setcred(pamh, PAM_ESTABLISH_CRED)) != - PAM_SUCCESS) - syslog(LOG_ERR, "Couldn't establish credentials: %s", - pam_strerror(pamh, e)); - environ_pam = pam_getenvlist(pamh); rval = 0; break; @@ -743,13 +791,29 @@ auth_pam() break; default: - syslog(LOG_ERR, "auth_pam: %s", pam_strerror(pamh, e)); + syslog(LOG_ERR, "pam_authenticate: %s", pam_strerror(pamh, e)); rval = -1; break; } - if ((e = pam_end(pamh, e)) != PAM_SUCCESS) { - syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e)); - rval = -1; + + if (rval == 0) { + e = pam_acct_mgmt(pamh, 0); + if (e == PAM_NEW_AUTHTOK_REQD) { + e = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK); + if (e != PAM_SUCCESS) { + syslog(LOG_ERR, "pam_chauthtok: %s", pam_strerror(pamh, e)); + rval = 1; + } + } else if (e != PAM_SUCCESS) { + rval = 1; + } + } + + if (rval != 0) { + if ((e = pam_end(pamh, e)) != PAM_SUCCESS) { + syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e)); + } + pamh = NULL; } return rval; } @@ -796,7 +860,7 @@ ok_to_export(s) } return 1; } -#endif /* NO_PAM */ +#endif /* USE_PAM */ static void usage() @@ -807,7 +871,7 @@ usage() /* * Allow for authentication style and/or kerberos instance - * */ + */ #define NBUFSIZ UT_NAMESIZE + 64 |