From c37db5de3c961d2f3b8584ee93026c2e4cb1f4c4 Mon Sep 17 00:00:00 2001
From: SATOH Fumiyasu <fumiyas@osstech.co.jp>
Date: Fri, 1 Jan 2016 23:01:30 +0900
Subject: [PATCH] setuidgid: Call pam_setcred() to establish user credentials

This patch is required to grant RBAC privileges to the user on Solaris.
---
 setuidgid.c | 38 ++++++++++++++++++++++++++++++++++++++
 setuidgid=x |  1 +
 2 files changed, 39 insertions(+)

diff --git a/setuidgid.c b/setuidgid.c
index e8d1e3f..457995f 100644
--- a/setuidgid.c
+++ b/setuidgid.c
@@ -1,10 +1,24 @@
 #include <sys/types.h>
 #include <pwd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <security/pam_appl.h>
 #include "prot.h"
 #include "strerr.h"
 #include "pathexec.h"
 #include "sgetopt.h"
 
+#ifndef PAM_DATA_SILENT
+#  define PAM_DATA_SILENT 0
+#endif
+
+#ifndef SETUIDGID_PAM_SERVICE_NAME_ENV
+#  define SETUIDGID_PAM_SERVICE_NAME_ENV "SETUIDGID_PAM_SERVICE"
+#endif
+#ifndef SETUIDGID_PAM_SERVICE_NAME_DEFAULT
+#  define SETUIDGID_PAM_SERVICE_NAME_DEFAULT "other"
+#endif
+
 #define FATAL "setuidgid: fatal: "
 
 void usage() {
@@ -15,6 +29,28 @@ const char *account;
 struct passwd *pw;
 int flag2ndgids = 0;
 
+static void pam_prep_user(void)
+{
+  pam_handle_t *pamh;
+  const char *pam_service_name = getenv(SETUIDGID_PAM_SERVICE_NAME_ENV);
+  struct pam_conv pam_conv;
+
+  if (!pam_service_name)
+    pam_service_name = SETUIDGID_PAM_SERVICE_NAME_DEFAULT;
+
+  /* FIXME: Is this OK? */
+  memset(&pam_conv, 0, sizeof(pam_conv));
+
+  if (pam_start(pam_service_name, pw->pw_name, &pam_conv, &pamh) != PAM_SUCCESS)
+    strerr_die2x(111,FATAL,"unable to initialize PAM");
+
+  pam_set_item(pamh, PAM_USER, pw->pw_name);
+  pam_setcred(pamh, PAM_ESTABLISH_CRED);
+
+  if (pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT) != PAM_SUCCESS)
+    strerr_die2x(111,FATAL,"unable to finish PAM");
+}
+
 int main(int argc,const char *const *argv,const char *const *envp)
 {
   int opt;
@@ -34,6 +70,8 @@ int main(int argc,const char *const *argv,const char *const *envp)
   if (!pw)
     strerr_die3x(111,FATAL,"unknown account ",account);
 
+  pam_prep_user();
+
   if (prot_gid(pw->pw_gid) == -1)
     strerr_die2sys(111,FATAL,"unable to setgid");
   if (flag2ndgids && prot_gids(pw->pw_name, pw->pw_gid) == -1)
diff --git a/setuidgid=x b/setuidgid=x
index 09db56a..c319519 100644
--- a/setuidgid=x
+++ b/setuidgid=x
@@ -1,2 +1,3 @@
 unix.a
 byte.a
+-lpam