Index: src/init.sample =================================================================== --- src/init.sample (revision 0) +++ src/init.sample (revision 0) @@ -0,0 +1,9 @@ +#%PAM-1.0 +# +# The PAM configuration file for /sbin/init +# Used for updating the lastlog logging file +# +auth sufficient pam_rootok.so +account include common-account +session include common-session +session requisite pam_lastlog.so silent Index: src/init.c =================================================================== --- src/init.c (revision 56) +++ src/init.c (working copy) @@ -76,6 +76,10 @@ #include "reboot.h" #include "set.h" +#ifdef USE_PAM +extern void notify_pam_dead_session(const char *id); +#endif + #ifndef SIGPWR # define SIGPWR SIGUSR2 #endif @@ -1129,6 +1133,9 @@ } dup(f); dup(f); +#ifdef USE_PAM + notify_pam_dead_session(ch->id); +#endif } /* @@ -1548,6 +1555,9 @@ INITDBG(L_VB, "Updating utmp for pid %d [id %s]", ch->pid, ch->id); ch->flags &= ~RUNNING; +#ifdef USE_PAM + notify_pam_dead_session(ch->id); +#endif if (ch->process[0] != '+') write_utmp_wtmp("", ch->id, ch->pid, DEAD_PROCESS, NULL); } @@ -2009,6 +2019,9 @@ if (ch->flags & ZOMBIE) { INITDBG(L_VB, "Child died, PID= %d", ch->pid); ch->flags &= ~(RUNNING|ZOMBIE|WAITING); +#ifdef USE_PAM + notify_pam_dead_session(ch->id); +#endif if (ch->process[0] != '+') write_utmp_wtmp("", ch->id, ch->pid, DEAD_PROCESS, NULL); } @@ -2453,6 +2466,9 @@ if (ch->flags & ZOMBIE) { INITDBG(L_VB, "Child died, PID= %d", ch->pid); ch->flags &= ~(RUNNING|ZOMBIE|WAITING); +#ifdef USE_PAM + notify_pam_dead_session(ch->id); +#endif if (ch->process[0] != '+') write_utmp_wtmp("", ch->id, ch->pid, DEAD_PROCESS, NULL); } Index: src/utmp.c =================================================================== --- src/utmp.c (revision 51) +++ src/utmp.c (working copy) @@ -34,10 +34,18 @@ #include #include +#if defined(USE_PAM) && defined(INIT_MAIN) +# include +# include +#endif + #include "init.h" #include "initreq.h" #include "paths.h" +#ifndef _PATH_DEV +# define _PATH_DEV "/dev/" +#endif #if defined(__GLIBC__) # if (__GLIBC__ == 2) && (__GLIBC_MINOR__ == 0) && defined(__powerpc__) @@ -127,9 +135,9 @@ strncpy(utmp.ut_name, user, sizeof(utmp.ut_name)); strncpy(utmp.ut_id , id , sizeof(utmp.ut_id )); strncpy(utmp.ut_line, line, sizeof(utmp.ut_line)); - - /* Put the OS version in place of the hostname */ - if (uname(&uname_buf) == 0) + + /* Put the OS version in place of the hostname */ + if (uname(&uname_buf) == 0) strncpy(utmp.ut_host, uname_buf.release, sizeof(utmp.ut_host)); #if HAVE_UPDWTMP @@ -262,3 +270,75 @@ write_wtmp(user, id, pid, type, line && line[0] ? line : oldline); } +#if defined(USE_PAM) && defined(INIT_MAIN) +static pam_handle_t *pamh = NULL; +# ifdef __GNUC__ +static int +null_conv(int num_msg, const struct pam_message **msgm, + struct pam_response **response __attribute__((unused)), + void *appdata_ptr __attribute__((unused))) +# else +static int +null_conv(int num_msg, const struct pam_message **msgm, + struct pam_response **response, void *appdata_ptr) +# endif +{ + int i; + for (i = 0; i < num_msg; i++) { + const struct pam_message *msg = msgm[i]; + if (msg == (const struct pam_message*)0) + continue; + if (msg->msg == (char*)0) + continue; + switch (msg->msg_style) { + case PAM_ERROR_MSG: + case PAM_TEXT_INFO: + initlog(L_VB, "pam_message %s", msg->msg); + default: + break; + } + } + return 0; +} +static const struct pam_conv conv = { null_conv, NULL }; +# define PAM_FAIL_CHECK(func, args...) \ + { \ + if ((pam_ret = (func)(args)) != PAM_SUCCESS) { \ + initlog(L_VB, "%s", pam_strerror(pamh, pam_ret)); \ + goto pam_error; \ + } \ + } + +void notify_pam_dead_session(const char *id) +{ + struct utmp *oldut, ut; + + setutent(); + + memset(&ut, 0, sizeof(ut)); + ut.ut_type = DEAD_PROCESS; + strncpy(ut.ut_id, id, sizeof(ut.ut_id)); + + if ((oldut = getutid(&ut)) && (oldut->ut_type == USER_PROCESS)) { + int pam_ret; + char tty[UT_LINESIZE+ strlen(_PATH_DEV) + 1]; + + if (strncmp(oldut->ut_line, _PATH_DEV, strlen(_PATH_DEV))) + snprintf(tty, sizeof(tty), _PATH_DEV "%.*s", + UT_LINESIZE, oldut->ut_line); + else + snprintf(tty, sizeof(tty), "%.*s", + UT_LINESIZE, oldut->ut_line); + + PAM_FAIL_CHECK(pam_start, "init", oldut->ut_user, &conv, &pamh); + PAM_FAIL_CHECK(pam_set_item, pamh, PAM_TTY, tty); + PAM_FAIL_CHECK(pam_set_item, pamh, PAM_RHOST, oldut->ut_host); + PAM_FAIL_CHECK(pam_close_session, pamh, PAM_SILENT); + pam_error: + pam_end(pamh, pam_ret); + } + + endutent(); +} +#endif /* USE_PAM && INIT_MAIN */ + Index: src/Makefile =================================================================== --- src/Makefile (revision 58) +++ src/Makefile (working copy) @@ -8,7 +8,7 @@ # Version: @(#)Makefile 2.85-13 23-Mar-2004 miquels@cistron.nl # -CPPFLAGS = +CPPFLAGS = -DUSE_PAM CFLAGS ?= -ansi -O2 -fomit-frame-pointer override CFLAGS += -W -Wall -D_GNU_SOURCE STATIC = @@ -79,6 +79,13 @@ endif # Additional libs for GNU libc. +ifneq ($(findstring -DUSE_PAM,$(CPPFLAGS)),) + INITLIBS += -lpam + PAMDOTD = /etc/pam.d + PAMINIT = $(PAMDOTD)/init +endif + +# Additional libs for GNU libc. ifneq ($(wildcard /usr/lib*/libcrypt.a),) SULOGINLIBS += -lcrypt endif @@ -153,6 +160,11 @@ $(STRIP) $$i ; \ $(INSTALL_EXEC) $$i $(ROOT)/usr/bin/ ; \ done +ifneq ($(findstring -DUSE_PAM,$(CPPFLAGS)),) + $(INSTALL_DIR) $(ROOT)$(PAMDOTD) + test -s $(ROOT)$(PAMINIT) || \ + $(INSTALL_DATA) init.sample $(ROOT)$(PAMINIT) +endif # $(INSTALL_DIR) $(ROOT)/etc/ # $(INSTALL_EXEC) initscript.sample $(ROOT)/etc/ ln -sf halt $(ROOT)/sbin/reboot