char *username; /* from command line or PAM */
+ struct passwd *pwd; /* user info */
+
#ifdef LOGIN_CHOWN_VCS
char vcsn[VCS_PATH_MAX]; /* virtual console name */
char vcsan[VCS_PATH_MAX];
*/
int timeout = LOGIN_TIMEOUT;
-struct passwd *pwd;
-
-static struct passwd pwdcopy;
-
static void timedout(int);
static void sigint(int);
static void motd(void);
}
#ifdef HAVE_LIBAUDIT
-static void log_audit(struct login_context *cxt, struct passwd *pwd, int status)
+static void log_audit(struct login_context *cxt, int status)
{
int audit_fd;
+ struct passwd *pwd = cxt->pwd;
audit_fd = audit_open();
if (audit_fd == -1)
close(audit_fd);
}
-#else /* ! HAVE_LIBAUDIT */
-#define log_audit(cxt, pwd, status)
+#else /* !HAVE_LIBAUDIT */
+# define log_audit(cxt, status)
#endif /* HAVE_LIBAUDIT */
static void log_lastlog(struct login_context *cxt)
time_t t;
int fd;
+ if (!cxt->pwd)
+ return;
+
fd = open(_PATH_LASTLOG, O_RDWR, 0);
if (fd < 0)
return;
- lseek(fd, (off_t) pwd->pw_uid * sizeof(ll), SEEK_SET);
+ lseek(fd, (off_t) cxt->pwd->pw_uid * sizeof(ll), SEEK_SET);
/*
* Print last log message
printf(_("on %.*s\n"),
(int)sizeof(ll.ll_line), ll.ll_line);
}
- lseek(fd, (off_t) pwd->pw_uid * sizeof(ll), SEEK_SET);
+ lseek(fd, (off_t) cxt->pwd->pw_uid * sizeof(ll), SEEK_SET);
}
memset((char *)&ll, 0, sizeof(ll));
updwtmp(_PATH_WTMP, &ut);
}
+static struct passwd *get_passwd_entry(const char *username,
+ char **pwdbuf,
+ struct passwd *pwd)
+{
+ struct passwd *res = NULL;
+ size_t sz;
+ char *tmp;
+ int x;
+
+ if (!pwdbuf || !username)
+ return NULL;
+
+#ifdef _SC_GETPW_R_SIZE_MAX
+ sz = sysconf(_SC_GETPW_R_SIZE_MAX);
+ if (sz <= 0)
+#endif
+ sz = 16384;
+
+ tmp = realloc(*pwdbuf, sz);
+ if (!tmp) {
+ free(*pwdbuf);
+ *pwdbuf = NULL;
+ return NULL;
+ }
+ *pwdbuf = tmp;
+
+ x = getpwnam_r(username, pwd, *pwdbuf, sz, &res);
+ if (!res) {
+ errno = x;
+ return NULL;
+ }
+ return res;
+}
+
/* encapsulate stupid "void **" pam_get_item() API */
static int loginpam_get_username(pam_handle_t * pamh, char **name)
{
struct pam_conv conv = { misc_conv, NULL };
struct sigaction sa, oldsa_hup, oldsa_term;
+ char *pwdbuf = NULL;
+ struct passwd *pwd = NULL, _pwd;
+
struct login_context cxt = {
.pid = getpid()
};
failcount, cxt.hostname, cxt.username, pam_strerror(pamh,
retcode));
logbtmp(&cxt);
- log_audit(&cxt, NULL, 0);
+ log_audit(&cxt, 0);
fprintf(stderr, _("Login incorrect\n\n"));
pam_set_item(pamh, PAM_USER, NULL);
cxt.hostname, cxt.username, pam_strerror(pamh,
retcode));
logbtmp(&cxt);
- log_audit(&cxt, NULL, 0);
+ log_audit(&cxt, 0);
fprintf(stderr, _("\nLogin incorrect\n"));
pam_end(pamh, retcode);
pam_end(pamh, PAM_SYSTEM_ERR);
exit(EXIT_FAILURE);
}
- if (!(pwd = getpwnam(cxt.username))) {
+ if (!(cxt.pwd = get_passwd_entry(cxt.username, &pwdbuf, &_pwd))) {
warnx(_("\nSession setup problem, abort."));
syslog(LOG_ERR, _("Invalid user name \"%s\" in %s:%d. Abort."),
cxt.username, __FUNCTION__, __LINE__);
exit(EXIT_FAILURE);
}
- /*
- * Create a copy of the pwd struct - otherwise it may get
- * clobbered by PAM
- */
- memcpy(&pwdcopy, pwd, sizeof(*pwd));
- pwd = &pwdcopy;
- pwd->pw_name = strdup(pwd->pw_name);
- pwd->pw_passwd = strdup(pwd->pw_passwd);
- pwd->pw_gecos = strdup(pwd->pw_gecos);
- pwd->pw_dir = strdup(pwd->pw_dir);
- pwd->pw_shell = strdup(pwd->pw_shell);
- if (!pwd->pw_name || !pwd->pw_passwd || !pwd->pw_gecos ||
- !pwd->pw_dir || !pwd->pw_shell) {
- warnx(_("out of memory"));
- syslog(LOG_ERR, "Out of memory");
- pam_end(pamh, PAM_SYSTEM_ERR);
- exit(EXIT_FAILURE);
- }
+ pwd = cxt.pwd;
cxt.username = pwd->pw_name;
/*
}
log_utmp(&cxt);
- log_audit(&cxt, pwd, 1);
+ log_audit(&cxt, 1);
log_lastlog(&cxt);
if (fchown(0, pwd->pw_uid,