summaryrefslogtreecommitdiffstats
path: root/usr.bin/login/login.c
diff options
context:
space:
mode:
authormarkm <markm@FreeBSD.org>2001-03-27 19:40:51 +0000
committermarkm <markm@FreeBSD.org>2001-03-27 19:40:51 +0000
commitf767ca7e60f2f04f4d7f30da195b56abab4296df (patch)
tree2c45c3c7d9ffb06e8a26fdf6d772beb282ddfad9 /usr.bin/login/login.c
parent51ca15c2dcae271222dd76f75c0c909596323a8c (diff)
downloadFreeBSD-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/login.c')
-rw-r--r--usr.bin/login/login.c122
1 files changed, 93 insertions, 29 deletions
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
OpenPOWER on IntegriCloud