login: optional support for PAM

This commit is contained in:
Denis Vlasenko 2007-08-21 10:58:18 +00:00
parent 18f2a6bc5e
commit d6e81c7762
3 changed files with 71 additions and 10 deletions

View File

@ -60,18 +60,20 @@ LDFLAGS += -static
endif endif
BBOX_LIB_LIST = m crypt BBOX_LIB_LIST = m crypt
ifeq ($(CONFIG_PAM),y)
BBOX_LIB_LIST += pam pam_misc
endif
ifeq ($(CONFIG_SELINUX),y) ifeq ($(CONFIG_SELINUX),y)
#LDLIBS += -lselinux -lsepol
BBOX_LIB_LIST += selinux sepol BBOX_LIB_LIST += selinux sepol
endif endif
ifeq ($(CONFIG_EFENCE),y) ifeq ($(CONFIG_EFENCE),y)
#LDLIBS += -lefence
BBOX_LIB_LIST += efence BBOX_LIB_LIST += efence
endif endif
ifeq ($(CONFIG_DMALLOC),y) ifeq ($(CONFIG_DMALLOC),y)
#LDLIBS += -ldmalloc
BBOX_LIB_LIST += dmalloc BBOX_LIB_LIST += dmalloc
endif endif

View File

@ -128,6 +128,13 @@ config LOGIN
Note that Busybox binary must be setuid root for this applet to Note that Busybox binary must be setuid root for this applet to
work properly. work properly.
config PAM
bool "Support for PAM (Pluggable Authentication Modules)"
default n
depends on LOGIN
help
Use PAM in login(1) instead of direct access to password database.
config LOGIN_SCRIPTS config LOGIN_SCRIPTS
bool "Support for login scripts" bool "Support for login scripts"
depends on LOGIN depends on LOGIN

View File

@ -14,6 +14,15 @@
#include <selinux/flask.h> /* for security class definitions */ #include <selinux/flask.h> /* for security class definitions */
#endif #endif
#if ENABLE_PAM
#include <pam/pam_appl.h>
#include <pam/pam_misc.h>
static const struct pam_conv conv = {
misc_conv,
NULL
};
#endif
enum { enum {
TIMEOUT = 60, TIMEOUT = 60,
EMPTY_USERNAME_COUNT = 10, EMPTY_USERNAME_COUNT = 10,
@ -125,7 +134,7 @@ static void die_if_nologin_and_non_root(int amroot)
static ALWAYS_INLINE void die_if_nologin_and_non_root(int amroot) {} static ALWAYS_INLINE void die_if_nologin_and_non_root(int amroot) {}
#endif #endif
#if ENABLE_FEATURE_SECURETTY #if ENABLE_FEATURE_SECURETTY && !ENABLE_PAM
static int check_securetty(void) static int check_securetty(void)
{ {
FILE *fp; FILE *fp;
@ -214,7 +223,7 @@ int login_main(int argc, char **argv)
LOGIN_OPT_h = (1<<1), LOGIN_OPT_h = (1<<1),
LOGIN_OPT_p = (1<<2), LOGIN_OPT_p = (1<<2),
}; };
char fromhost[512]; char *fromhost;
char username[USERNAME_SIZE]; char username[USERNAME_SIZE];
const char *tmp; const char *tmp;
int amroot; int amroot;
@ -226,6 +235,9 @@ int login_main(int argc, char **argv)
char full_tty[TTYNAME_SIZE]; char full_tty[TTYNAME_SIZE];
USE_SELINUX(security_context_t user_sid = NULL;) USE_SELINUX(security_context_t user_sid = NULL;)
USE_FEATURE_UTMP(struct utmp utent;) USE_FEATURE_UTMP(struct utmp utent;)
USE_PAM(pam_handle_t *pamh;)
USE_PAM(int pamret;)
USE_PAM(const char *failed_msg;)
short_tty = full_tty; short_tty = full_tty;
username[0] = '\0'; username[0] = '\0';
@ -265,13 +277,12 @@ int login_main(int argc, char **argv)
USE_FEATURE_UTMP( USE_FEATURE_UTMP(
safe_strncpy(utent.ut_host, opt_host, sizeof(utent.ut_host)); safe_strncpy(utent.ut_host, opt_host, sizeof(utent.ut_host));
) )
snprintf(fromhost, sizeof(fromhost)-1, " on '%.100s' from " fromhost = xasprintf(" on '%s' from '%s'", short_tty, opt_host);
"'%.200s'", short_tty, opt_host);
} else } else
snprintf(fromhost, sizeof(fromhost)-1, " on '%.100s'", short_tty); fromhost = xasprintf(" on '%s'", short_tty);
// Was breaking "login <username>" from shell command line: /* Was breaking "login <username>" from shell command line: */
// bb_setpgrp(); /*bb_setpgrp();*/
openlog(applet_name, LOG_PID | LOG_CONS | LOG_NOWAIT, LOG_AUTH); openlog(applet_name, LOG_PID | LOG_CONS | LOG_NOWAIT, LOG_AUTH);
@ -279,6 +290,46 @@ int login_main(int argc, char **argv)
if (!username[0]) if (!username[0])
get_username_or_die(username, sizeof(username)); get_username_or_die(username, sizeof(username));
#if ENABLE_PAM
pamret = pam_start("login", username, &conv, &pamh);
if (pamret != PAM_SUCCESS) {
failed_msg = "pam_start";
goto pam_auth_failed;
}
/* set TTY (so things like securetty work) */
pamret = pam_set_item(pamh, PAM_TTY, short_tty);
if (pamret != PAM_SUCCESS) {
failed_msg = "pam_set_item(TTY)";
goto pam_auth_failed;
}
pamret = pam_authenticate(pamh, 0);
if (pamret == PAM_SUCCESS) {
char *pamuser;
/* check that the account is healthy. */
pamret = pam_acct_mgmt(pamh, 0);
if (pamret != PAM_SUCCESS) {
failed_msg = "account setup";
goto pam_auth_failed;
}
/* read user back */
/* gcc: "dereferencing type-punned pointer breaks aliasing rules..."
* thus we use double cast */
if (pam_get_item(pamh, PAM_USER, (const void **)(void*)&pamuser) != PAM_SUCCESS) {
failed_msg = "pam_get_item(USER)";
goto pam_auth_failed;
}
safe_strncpy(username, pamuser, sizeof(username));
}
/* If we get here, the user was authenticated, and is
* granted access. */
pw = getpwnam(username);
if (pw)
break;
goto auth_failed;
pam_auth_failed:
bb_error_msg("%s failed: %s", failed_msg, pam_strerror(pamh, pamret));
safe_strncpy(username, "UNKNOWN", sizeof(username));
#else /* not PAM */
pw = getpwnam(username); pw = getpwnam(username);
if (!pw) { if (!pw) {
strcpy(username, "UNKNOWN"); strcpy(username, "UNKNOWN");
@ -301,6 +352,7 @@ int login_main(int argc, char **argv)
/* authorization takes place here */ /* authorization takes place here */
if (correct_password(pw)) if (correct_password(pw))
break; break;
#endif /* ENABLE_PAM */
auth_failed: auth_failed:
opt &= ~LOGIN_OPT_f; opt &= ~LOGIN_OPT_f;
bb_do_delay(FAIL_DELAY); bb_do_delay(FAIL_DELAY);