From 9532d85871990d41ccd3d851fff10386a4925270 Mon Sep 17 00:00:00 2001 From: Allison Karlitskaya Date: Wed, 16 May 2018 14:44:41 +0200 Subject: pam_motd: add support for a motd.d directory (#48) Add a new feature to pam_motd to allow packages to install their own message files in a "motd.d" directory, to be displayed after the primary motd. Add an option motd_d= to specify the location of this directory. Modify the defaults, in the case where no options are given, to display both /etc/motd and /etc/motd.d. Fixes #47 * modules/pam_motd/pam_motd.c: add support for motd.d * modules/pam_motd/pam_motd.8.xml: update the manpage --- modules/pam_motd/pam_motd.8.xml | 36 ++++++++++++++- modules/pam_motd/pam_motd.c | 100 +++++++++++++++++++++++++++++----------- 2 files changed, 108 insertions(+), 28 deletions(-) (limited to 'modules') diff --git a/modules/pam_motd/pam_motd.8.xml b/modules/pam_motd/pam_motd.8.xml index ff92154e..906c4ed0 100644 --- a/modules/pam_motd/pam_motd.8.xml +++ b/modules/pam_motd/pam_motd.8.xml @@ -52,7 +52,24 @@ + + + + + + + The /path/dirname.d directory is scanned + and each file contained inside of it is displayed. + + + + + When no options are given, the default is to display both + /etc/motd and the contents of + /etc/motd.d. Specifying either option (or both) + will disable this default behavior. + @@ -81,7 +98,20 @@ The suggested usage for /etc/pam.d/login is: -session optional pam_motd.so motd=/etc/motd +session optional pam_motd.so + + + + To use a motd file from a different location: + +session optional pam_motd.so motd=/elsewhere/motd + + + + To use a motd file from elsewhere, along with a + corresponding .d directory: + +session optional pam_motd.so motd=/elsewhere/motd motd_dir=/elsewhere/motd.d @@ -109,6 +139,10 @@ session optional pam_motd.so motd=/etc/motd pam_motd was written by Ben Collins <bcollins@debian.org>. + + The option was added by + Allison Karlitskaya <allison.karlitskaya@redhat.com>. + diff --git a/modules/pam_motd/pam_motd.c b/modules/pam_motd/pam_motd.c index 11c7b565..cc828d7e 100644 --- a/modules/pam_motd/pam_motd.c +++ b/modules/pam_motd/pam_motd.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -33,6 +34,7 @@ #define PAM_SM_SESSION #define DEFAULT_MOTD "/etc/motd" +#define DEFAULT_MOTD_D "/etc/motd.d" #include #include @@ -47,14 +49,60 @@ pam_sm_close_session (pam_handle_t *pamh UNUSED, int flags UNUSED, } static char default_motd[] = DEFAULT_MOTD; +static char default_motd_dir[] = DEFAULT_MOTD_D; + +static void try_to_display_fd(pam_handle_t *pamh, int fd) +{ + struct stat st; + char *mtmp = NULL; + + /* fill in message buffer with contents of motd */ + if ((fstat(fd, &st) < 0) || !st.st_size || st.st_size > 0x10000) + return; + + if (!(mtmp = malloc(st.st_size+1))) + return; + + if (pam_modutil_read(fd, mtmp, st.st_size) == st.st_size) { + if (mtmp[st.st_size-1] == '\n') + mtmp[st.st_size-1] = '\0'; + else + mtmp[st.st_size] = '\0'; + + pam_info (pamh, "%s", mtmp); + } + + _pam_drop(mtmp); +} + +static void try_to_display_directory(pam_handle_t *pamh, const char *dirname) +{ + DIR *dirp; + + dirp = opendir(dirname); + + if (dirp != NULL) { + struct dirent *entry; + + while ((entry = readdir(dirp))) { + int fd = openat(dirfd(dirp), entry->d_name, O_RDONLY); + + if (fd >= 0) { + try_to_display_fd(pamh, fd); + close(fd); + } + } + + closedir(dirp); + } +} int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv) { int retval = PAM_IGNORE; - int fd; const char *motd_path = NULL; - char *mtmp = NULL; + const char *motd_dir_path = NULL; if (flags & PAM_SILENT) { return retval; @@ -72,41 +120,39 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags, "motd= specification missing argument - ignored"); } } + else if (!strncmp(*argv,"motd_dir=",9)) { + + motd_dir_path = 9 + *argv; + if (*motd_dir_path != '\0') { + D(("set motd.d path: %s", motd_dir_path)); + } else { + motd_dir_path = NULL; + pam_syslog(pamh, LOG_ERR, + "motd_dir= specification missing argument - ignored"); + } + } else pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv); } - if (motd_path == NULL) + if (motd_path == NULL && motd_dir_path == NULL) { motd_path = default_motd; + motd_dir_path = default_motd_dir; + } - while ((fd = open(motd_path, O_RDONLY, 0)) >= 0) { - struct stat st; - - /* fill in message buffer with contents of motd */ - if ((fstat(fd, &st) < 0) || !st.st_size || st.st_size > 0x10000) - break; - - if (!(mtmp = malloc(st.st_size+1))) - break; - - if (pam_modutil_read(fd, mtmp, st.st_size) != st.st_size) - break; + if (motd_path != NULL) { + int fd = open(motd_path, O_RDONLY, 0); - if (mtmp[st.st_size-1] == '\n') - mtmp[st.st_size-1] = '\0'; - else - mtmp[st.st_size] = '\0'; - - pam_info (pamh, "%s", mtmp); - break; + if (fd >= 0) { + try_to_display_fd(pamh, fd); + close(fd); + } } - _pam_drop (mtmp); - - if (fd >= 0) - close(fd); + if (motd_dir_path != NULL) + try_to_display_directory(pamh, motd_dir_path); - return retval; + return retval; } /* end of module definition */ -- cgit v1.2.3