]> granicus.if.org Git - linux-pam/commitdiff
pam_motd: add support for a motd.d directory (#48)
authorAllison Karlitskaya <allison.karlitskaya@redhat.com>
Wed, 16 May 2018 12:44:41 +0000 (14:44 +0200)
committerTomáš Mráz <t8m@users.noreply.github.com>
Wed, 16 May 2018 12:44:41 +0000 (14:44 +0200)
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
modules/pam_motd/pam_motd.c

index ff92154e9af74af45d7056c0960f7bf9c8747795..906c4ed0ad0a6721ad0e7d05ba93d83bd8032446 100644 (file)
           </para>
         </listitem>
       </varlistentry>
+      <varlistentry>
+        <term>
+          <option>motd_dir=<replaceable>/path/dirname.d</replaceable></option>
+        </term>
+        <listitem>
+          <para>
+            The <filename>/path/dirname.d</filename> directory is scanned
+            and each file contained inside of it is displayed.
+          </para>
+        </listitem>
+      </varlistentry>
     </variablelist>
+    <para>
+      When no options are given, the default is to display both
+      <filename>/etc/motd</filename> and the contents of
+      <filename>/etc/motd.d</filename>.  Specifying either option (or both)
+      will disable this default behavior.
+    </para>
   </refsect1>
 
   <refsect1 id="pam_motd-types">
     <para>
       The suggested usage for <filename>/etc/pam.d/login</filename> is:
       <programlisting>
-session  optional  pam_motd.so  motd=/etc/motd
+session  optional  pam_motd.so
+      </programlisting>
+    </para>
+    <para>
+      To use a <filename>motd</filename> file from a different location:
+      <programlisting>
+session  optional  pam_motd.so motd=/elsewhere/motd
+      </programlisting>
+    </para>
+    <para>
+      To use a <filename>motd</filename> file from elsewhere, along with a
+      corresponding <filename>.d</filename> directory:
+      <programlisting>
+session  optional  pam_motd.so motd=/elsewhere/motd motd_dir=/elsewhere/motd.d
       </programlisting>
     </para>
   </refsect1>
@@ -109,6 +139,10 @@ session  optional  pam_motd.so  motd=/etc/motd
       <para>
         pam_motd was written by Ben Collins &lt;bcollins@debian.org&gt;.
       </para>
+      <para>
+        The <option>motd_dir=</option> option was added by
+        Allison Karlitskaya &lt;allison.karlitskaya@redhat.com&gt;.
+      </para>
   </refsect1>
 
 </refentry>
index 11c7b5656b7f6a1a3fa93dbd9960d5e81caf2f09..cc828d7ee38031142c042f61f41c52774fd9f7d2 100644 (file)
@@ -17,6 +17,7 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <dirent.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <pwd.h>
@@ -33,6 +34,7 @@
 
 #define PAM_SM_SESSION
 #define DEFAULT_MOTD   "/etc/motd"
+#define DEFAULT_MOTD_D "/etc/motd.d"
 
 #include <security/pam_modules.h>
 #include <security/pam_modutil.h>
@@ -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 */