]> err.no Git - dpkg/commitdiff
Add support for PAM sessions in start-stop-daemon.
authorNicolas FRANCOIS <nekral-guest@users.alioth.debian.org>
Sun, 25 Mar 2007 18:32:21 +0000 (18:32 +0000)
committerNicolas FRANCOIS <nekral-guest@users.alioth.debian.org>
Sun, 25 Mar 2007 18:32:21 +0000 (18:32 +0000)
ChangeLog
configure.ac
debian/changelog
debian/control
m4/libs.m4
man/ChangeLog
man/start-stop-daemon.8
utils/Makefile.am
utils/start-stop-daemon.c

index 3a0a4a57935c3f2e66291b73ef8f720c130addb1..92582eebee1d2aa9e83707d8735deff5108ef9be 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2007-03-25  Nicolas François  <nicolas.francois@centraliens.net>
+
+       * utils/start-stop-daemon.c: Add support for PAM sessions.
+       * utils/Makefile.am: Link start-stop-daemon with the PAM libraries.
+       * m4/libs.m4: Add new test: DPKG_LIB_PAM. Defines WITH_PAM (by
+       default) and PAM_LIBS.  Checks for the PAM library and header.
+       * configure.ac: Include PAM test.
+       * debian/control: New build dependency on libpam0g-dev.
+
 2007-03-23  Guillem Jover  <guillem@debian.org>
 
        * debian/pseudo-tags: Renamed to ...
index 8c7873568a19fb9053a00eeeb7e01a5fd4c1f8ec..4992072e9a4039bc4645f8f95ab5436f30800883 100644 (file)
@@ -68,6 +68,7 @@ if test "x$build_dselect" = "xyes"; then
 fi
 if test "x$build_start_stop_daemon" = "xyes"; then
    DPKG_LIB_SSD
+   DPKG_LIB_PAM
 fi
 
 # Checks for header files.
index d32044f9217b1de18ae6cd63e248f6a380dac98b..e6222bbbc680aaddbe57f2b7fb7758f2ce0bd501 100644 (file)
@@ -59,6 +59,10 @@ dpkg (1.14.0) UNRELEASED; urgency=low
     Based on a patch by Jeffrey W. Baker.
   * Switch from pseudo-tags to usertags, and update the documentation.
 
+  [ Nicolas François ]
+  * Add support for PAM sessions in start-stop-daemon.
+    Closes: #376165, #406942
+
   [ Updated dpkg translations ]
   * Romanian (Eddy Petrișor).
   * Traditional Chinese (Anthony Wong). Closes: #415230
index 75517b47a04bbaac6abecc3a9dfe3c29817194ac..b9aa08bf2ee9de1de927f6511675d0d5ee12cc49 100644 (file)
@@ -8,7 +8,8 @@ Bugs: debbugs://bugs.debian.org
 Standards-Version: 3.7.2
 Build-Depends: debhelper (>= 4.1.81), pkg-config, po4a (>= 0.23),
  libncurses5-dev | libncurses-dev, zlib1g-dev (>= 1:1.1.3-19.1), libbz2-dev,
- libselinux1-dev (>= 1.28-4) [!hurd-i386 !kfreebsd-i386 !kfreebsd-amd64]
+ libselinux1-dev (>= 1.28-4) [!hurd-i386 !kfreebsd-i386 !kfreebsd-amd64],
+ libpam0g-dev
 
 Package: dpkg
 Architecture: any
index f834026e9bc4b2dfffcd7e7f0b2f8eb964bd7c46..f6f4b0e9d83adc215da6193b7c990e66282240e1 100644 (file)
@@ -108,3 +108,34 @@ AC_CHECK_LIB([ps], [proc_stat_list_create], [SSD_LIBS="${SSD_LIBS:+$SSD_LIBS }-l
 AC_CHECK_LIB([shouldbeinlibc], [fmt_past_time], [SSD_LIBS="${SSD_LIBS:+$SSD_LIBS }-lshouldbeinlibc"])
 AC_CHECK_LIB([kvm], [kvm_openfiles], [SSD_LIBS="${SSD_LIBS:+$SSD_LIBS }-lkvm"])
 ])# DPKG_LIB_SSD
+
+# DPKG_LIB_PAM
+# ------------
+# Check for pam library.
+AC_DEFUN([DPKG_LIB_PAM],
+[AC_ARG_VAR([PAM_LIBS], [linker flags for pam library])dnl
+AC_ARG_WITH(pam,
+       AS_HELP_STRING([--with-pam],
+                      [use pam library for opening PAM sessions with start-stop-daemon]))
+if test "x$with_pam" != "xno"; then
+       AC_CHECK_LIB([pam], [pam_start],
+               [AC_DEFINE(WITH_PAM, 1,
+                       [Define to 1 to use PAM sessions in start-stop-daemon])
+                if test "x$with_pam" = "xstatic"; then
+                       dpkg_pam_libs="-Wl,-Bstatic -lpam -lpam_misc -Wl,-Bdynamic"
+                else
+                       dpkg_pam_libs="-lpam -lpam_misc"
+                fi
+                PAM_LIBS="${PAM_LIBS:+$PAM_LIBS }$dpkg_pam_libs"
+                with_pam="yes"],
+               [if test -n "$with_pam"; then
+                       AC_MSG_FAILURE([pam library not found])
+                fi])
+
+       AC_CHECK_HEADER([security/pam_appl.h],,
+               [if test -n "$with_pam"; then
+                       AC_MSG_FAILURE([pam header not found])
+                fi])
+fi
+])# DPKG_LIB_PAM
+
index 2b5d77a0fe9dc3197bb604f6541bbb9d0b8162ce..65dd4f4f65c54d83b788a9b320c9216bd74d9565 100644 (file)
@@ -1,3 +1,7 @@
+2007-03-25  Nicolas François  <nicolas.francois@centraliens.net>
+
+       * start-stop-daemon.8: Document the new --pam flag.
+
 2007-03-21  Guillem Jover  <guillem@debian.org>
 
        * po/dpkg-man.pot: Regenerated.
index 6bc249600eadd55d6d8e3121ff88af7eeb757125..0e29935101ce8c81fab0dda165e45449bf419d7c 100644 (file)
@@ -218,6 +218,9 @@ code for them to do this themself.
 .BR \-N ", " \-\-nicelevel " \fIint\fP"
 This alters the priority of the process before starting it.
 .TP
+.BR \-P ", " \-\-pam " \fIpam_service\fP"
+Start a PAM session, using the given PAM service.
+.TP
 .BR \-k ", " \-\-umask " \fImask\fP"
 This sets the umask of the process before starting it.
 .TP
index 9cfd988dddcaed34277fdc2d6777c8acb9706fa3..c7236d7dd136a311922947febb8834663193ac71 100644 (file)
@@ -13,7 +13,7 @@ if WITH_START_STOP_DAEMON
   start_stop_daemon_SOURCES = \
        start-stop-daemon.c
 
-  start_stop_daemon_LDADD = ../getopt/libopt.a $(SSD_LIBS)
+  start_stop_daemon_LDADD = ../getopt/libopt.a $(SSD_LIBS) $(PAM_LIBS)
 endif
 
 
index 76c39a074c749a740d4dd890f096c449acb4320f..4652d5158ae253d6888657584a5203a4dd1a71f9 100644 (file)
@@ -140,6 +140,20 @@ static const char *progname = "";
 static int nicelevel = 0;
 static int umask_value = -1;
 
+#ifdef WITH_PAM
+#include <sys/wait.h>
+#include <security/pam_appl.h>
+#include <security/pam_misc.h>
+
+static pam_handle_t *pamh = NULL;
+static char *pam = NULL;
+
+static struct pam_conv conv = {
+       misc_conv,
+       NULL
+};
+#endif
+
 static struct stat exec_stat;
 #if defined(OSHURD)
 static struct proc_stat_list *procset = NULL;
@@ -224,6 +238,13 @@ fatal(const char *format, ...)
 {
        va_list arglist;
 
+#ifdef WITH_PAM
+       if (pamh) {
+               int retcode = pam_close_session(pamh,0);
+               pam_end(pamh,retcode);
+       }
+#endif
+
        fprintf(stderr, "%s: ", progname);
        va_start(arglist, format);
        vfprintf(stderr, format, arglist);
@@ -306,6 +327,9 @@ do_help(void)
 "  -r|--chroot <directory>       chroot to <directory> before starting\n"
 "  -d|--chdir <directory>        change to <directory> (default is /)\n"
 "  -N|--nicelevel <incr>         add incr to the process's nice level\n"
+#ifdef WITH_PAM
+"  -P|--pam <service>            open a session with this PAM service\n"
+#endif
 "  -k|--umask <mask>             change the umask to <mask> before starting\n"
 "  -b|--background               force the process to detach\n"
 "  -m|--make-pidfile             create the pidfile before starting\n"
@@ -510,8 +534,11 @@ parse_options(int argc, char * const *argv)
                { "umask",        1, NULL, 'k'},
                { "background",   0, NULL, 'b'},
                { "make-pidfile", 0, NULL, 'm'},
-               { "retry",        1, NULL, 'R'},
+               { "retry",        1, NULL, 'R'},
                { "chdir",        1, NULL, 'd'},
+#ifdef WITH_PAM
+               { "pam",          1, NULL, 'P'},
+#endif
                { NULL,         0, NULL, 0}
        };
        const char *umask_str = NULL;
@@ -598,6 +625,11 @@ parse_options(int argc, char * const *argv)
                case 'd':  /* --chdir /new/dir */
                        changedir = optarg;
                        break;
+#ifdef WITH_PAM
+               case 'P':  /* --pam <service> */
+                       pam = optarg;
+                       break;
+#endif
                default:
                        badusage(NULL);  /* message printed by getopt */
                }
@@ -1326,6 +1358,68 @@ main(int argc, char **argv)
 #endif
                devnull_fd=open("/dev/null", O_RDWR);
        }
+#ifdef WITH_PAM
+       /*
+        * If PAM is enabled, start the PAM library, and open a PAM
+        * session.
+        * Set the environment variable set by the PAM modules for the
+        * daemon.
+        */
+       if (pam) {
+               int retcode;
+               char **envcp;
+
+               char *pam_user;
+               struct passwd *pw;
+               pw = getpwuid((-1==runas_uid)?getuid():runas_uid);
+               if (!pw) {
+                       fatal("user ID `%d' not found\n",
+                             (-1==runas_uid)?getuid():runas_uid);
+               }
+               else {
+                       pam_user = strdup(pw->pw_name);
+                       if (!pam_user)
+                               fatal("Unable to allocate memory: %s", strerror(errno));
+               }
+
+               retcode = pam_start (pam, pam_user, &conv, &pamh);
+               if (PAM_SUCCESS != retcode) {
+                       fprintf(stderr, "%s\n", pam_strerror(pamh, retcode));
+                       pam_end(pamh, retcode);
+                       exit(2);
+               }
+
+               /* Some PAM modules may rely on PAM_RUSER */
+               if (pam_user) {
+                       int retcode = pam_set_item(pamh, PAM_RUSER, pam_user);
+                       if (PAM_SUCCESS != retcode) {
+                               fprintf(stderr,
+                                       "%s\n",
+                                       pam_strerror(pamh, retcode));
+                               pam_end(pamh, retcode);
+                               exit(2);
+                       }
+               }
+
+               retcode = pam_open_session(pamh, 0);
+               if (PAM_SUCCESS != retcode) {
+                       fprintf(stderr, "%s\n", pam_strerror(pamh, retcode));
+                       pam_end(pamh, retcode);
+                       exit(2);
+               }
+
+               /* Copy the environment variables set by the PAM modules. */
+               envcp = pam_getenvlist (pamh);
+               if (envcp) {
+                       while (*envcp) {
+                               int err = putenv(*envcp);
+                               if (err)
+                                       fatal("Unable to set the '%s' environment variable: %s", *envcp, strerror(errno));
+                               envcp++;
+                       }
+               }
+       }
+#endif
        if (nicelevel) {
                errno=0;
                if ((nice(nicelevel)==-1) && (errno!=0))
@@ -1386,6 +1480,37 @@ main(int argc, char **argv)
                setpgid(0,0);
 #endif
        }
+#ifdef WITH_PAM
+       /*
+        * If PAM is enabled, fork.
+        *   The parent keeps the PAM session (and will do the cleanup).
+        *   The child will start the daemon.
+        */
+       if (pam) {
+               int parent = fork();
+               if (parent < 0) {
+                       fatal("Unable to fork.\n");
+               }
+               if (parent) {
+                       /* parent: wait for child to finish,
+                        *         then cleanup the PAM session.
+                        */
+                       int retcode;
+                       int status = 1;
+                       wait(&status);
+
+                       retcode = pam_close_session(pamh,0);
+                       pam_end(pamh,retcode);
+
+                       if (WIFSIGNALED(status))
+                               status = 1;
+                       else
+                               status = WEXITSTATUS(status);
+                       exit(status);
+               }
+               /* Only child continue */
+       }
+#endif
        execv(startas, argv);
        fatal("Unable to start %s: %s", startas, strerror(errno));
 }