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
+
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;
{
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);
" -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"
{ "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;
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 */
}
#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))
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));
}