From 926461ce085ea40730c29520d2a1d45cb63cb08c Mon Sep 17 00:00:00 2001
From: Jan Zeleny <jzeleny@redhat.com>
Date: Mon, 30 Jan 2012 06:31:51 -0500
Subject: [PATCH 10/10] SELinux support in PAM module

---
 Makefile.am              |    1 +
 src/sss_client/pam_sss.c |   57 +++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 57 insertions(+), 1 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index f4169d91eaea0cd6f7f1db162dcc1e188d91668a..02a80d21d66b0045aeca9174b32e34cee42ec4ce 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -878,6 +878,7 @@ pam_sss_la_SOURCES = \
 
 pam_sss_la_LDFLAGS = \
     -lpam \
+    -lselinux \
     -module \
     -avoid-version \
     -Wl,--version-script,$(srcdir)/src/sss_client/sss_pam.exports
diff --git a/src/sss_client/pam_sss.c b/src/sss_client/pam_sss.c
index 582a96f70bb7a8c2894ec94425a9fba1ddd54d18..27a71676096d02c12aeeaccbe53e6c9c115f2a23 100644
--- a/src/sss_client/pam_sss.c
+++ b/src/sss_client/pam_sss.c
@@ -41,6 +41,7 @@
 #include <security/pam_modules.h>
 #include <security/pam_ext.h>
 #include <security/pam_modutil.h>
+#include <selinux/selinux.h>
 #include "sss_pam_macros.h"
 
 #include "sss_cli.h"
@@ -81,6 +82,7 @@ struct pam_items {
     pid_t cli_pid;
     const char *login_name;
     char *domain_name;
+    char *selinux_user;
 };
 
 #define DEBUG_MGS_LEN 1024
@@ -965,6 +967,13 @@ static int eval_response(pam_handle_t *pamh, size_t buflen, uint8_t *buf,
                     D(("do_pam_conversation failed."));
                 }
                 break;
+            case SSS_PAM_SELINUX_MAP:
+                if (pi->selinux_user) {
+                    free(pi->selinux_user);
+                }
+                pi->selinux_user = (char *)malloc(len + 1);
+                memcpy(pi->selinux_user, &buf[p], len + 1);
+                break;
             default:
                 D(("Unknown response type [%d]", type));
         }
@@ -986,6 +995,7 @@ static int get_pam_items(pam_handle_t *pamh, struct pam_items *pi)
     pi->pam_newauthtok_type = SSS_AUTHTOK_TYPE_EMPTY;
     pi->pam_newauthtok = NULL;
     pi->pam_newauthtok_size = 0;
+    pi->selinux_user = NULL;
 
     ret = pam_get_item(pamh, PAM_SERVICE, (const void **) &(pi->pam_service));
     if (ret != PAM_SUCCESS) return ret;
@@ -1069,6 +1079,12 @@ static int send_and_receive(pam_handle_t *pamh, struct pam_items *pi,
     size_t replen;
     int pam_status = PAM_SYSTEM_ERR;
 
+    char *path = NULL;
+    char *tmp_path = NULL;
+    int pos, len;
+    int fd;
+    mode_t oldmask;
+
     print_pam_items(pi);
 
     ret = pack_message_v3(pi, &rd.len, &buf);
@@ -1158,8 +1174,47 @@ static int send_and_receive(pam_handle_t *pamh, struct pam_items *pi,
                 }
             }
             break;
-        case SSS_PAM_SETCRED:
         case SSS_PAM_OPEN_SESSION:
+            if (pi->selinux_user == NULL) {
+                pam_status = PAM_SUCCESS;
+                break;
+            }
+
+            if (asprintf(&path, "%s/logins/%s", selinux_policy_root(),
+                         pi->pam_user) <  0 ||
+                asprintf(&tmp_path, "%sXXXXXX", path) < 0) {
+                pam_status = PAM_SYSTEM_ERR;
+                goto done;
+            }
+
+            oldmask = umask(022);
+            fd = mkstemp(tmp_path);
+            if (fd < 0) {
+                pam_status = PAM_SYSTEM_ERR;
+                goto done;
+            }
+
+            pos = 0;
+            len = strlen(pi->selinux_user);
+            while (pos < len) {
+                ret = write(fd, pi->selinux_user + pos, len-pos);
+                if (ret < 0) {
+                    if (errno != EINTR) {
+                        pam_status = PAM_SYSTEM_ERR;
+                        goto done;
+                    }
+                    continue;
+                }
+                pos += ret;
+            }
+            close(fd);
+
+            rename(tmp_path, path);
+            free(path);
+            free(tmp_path);
+            umask(oldmask);
+            break;
+        case SSS_PAM_SETCRED:
         case SSS_PAM_CLOSE_SESSION:
             break;
         default:
-- 
1.7.6.4

