>From ec9c48595627cdd8a9e22c63a9ba4b9357c7873b Mon Sep 17 00:00:00 2001
From: Jan Zeleny <jzeleny@redhat.com>
Date: Fri, 27 Jul 2012 03:35:38 -0400
Subject: [PATCH] Write SELinux config files in responder instead of PAM
 module

---
 Makefile.am                    |    2 +-
 src/responder/pam/pamsrv_cmd.c |  100 ++++++++++++++++++++++++++++++++++++++--
 src/sss_client/pam_sss.c       |   95 --------------------------------------
 src/sss_client/sss_cli.h       |    4 --
 4 files changed, 96 insertions(+), 105 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 15e34720a0f13b19b237dc709ddd080b3a6b1bed..d14bb7a993c1144fc8df7a36de253075536a37c9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -566,6 +566,7 @@ sssd_pam_SOURCES = \
 sssd_pam_LDADD = \
     $(TDB_LIBS) \
     $(SSSD_LIBS) \
+    $(SELINUX_LIBS) \
     libsss_util.la
 
 if BUILD_SUDO
@@ -1128,7 +1129,6 @@ pam_sss_la_SOURCES = \
 
 pam_sss_la_LDFLAGS = \
     -lpam \
-    $(SELINUX_LIBS) \
     -module \
     -avoid-version \
     -Wl,--version-script,$(srcdir)/src/sss_client/sss_pam.exports
diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c
index 9c4c77060b1289352f58113ab221a6ae3acfb3e1..31040787a776d53296020c28648b228c91e3944d 100644
--- a/src/responder/pam/pamsrv_cmd.c
+++ b/src/responder/pam/pamsrv_cmd.c
@@ -33,6 +33,7 @@
 #include "responder/pam/pam_helpers.h"
 #include "db/sysdb.h"
 #include "db/sysdb_selinux.h"
+#include <selinux/selinux.h>
 
 enum pam_verbosity {
     PAM_VERBOSITY_NO_MESSAGES = 0,
@@ -353,6 +354,99 @@ fail:
     return ret;
 }
 
+#define ALL_SERVICES "*"
+
+static errno_t write_selinux_string(const char *username, char *string)
+{
+    char *path = NULL;
+    char *tmp_path = NULL;
+    ssize_t written;
+    int len;
+    int fd = 0;
+    mode_t oldmask;
+    TALLOC_CTX *tmp_ctx;
+    char *full_string = NULL;
+    errno_t ret = EOK;
+
+    len = strlen(string);
+    if (len == 0) {
+        return EINVAL;
+    }
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new() failed\n"));
+        return ENOMEM;
+    }
+
+    path = talloc_asprintf(tmp_ctx, "%s/logins/%s", selinux_policy_root(),
+                           username);
+    if (path == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    tmp_path = talloc_asprintf(tmp_ctx, "%sXXXXXX", path);
+    if (path == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    oldmask = umask(022);
+    fd = mkstemp(tmp_path);
+    umask(oldmask);
+    if (fd < 0) {
+        DEBUG(SSSDBG_OP_FAILURE, ("creating the temp file for SELinux "
+                                  "data failed. %s", tmp_path));
+        ret = EIO;
+        goto done;
+    }
+
+    full_string = talloc_asprintf(tmp_ctx, "%s:%s", ALL_SERVICES, string);
+    if (full_string == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    len = strlen(full_string);
+
+    errno = 0;
+    written = sss_atomic_write_s(fd, full_string, len);
+    if (written == -1) {
+        ret = errno;
+        DEBUG(SSSDBG_OP_FAILURE, ("writing to SELinux data file %s"
+                                  "failed [%d]: %s", tmp_path, ret,
+                                  strerror(ret)));
+        goto done;
+    }
+
+    if (written != len) {
+        DEBUG(SSSDBG_OP_FAILURE, ("Expected to write %d bytes, wrote %d",
+                                  written, len));
+        ret = EIO;
+        goto done;
+    }
+
+    errno = 0;
+    if (rename(tmp_path, path) < 0) {
+        ret = errno;
+    } else {
+        ret = EOK;
+    }
+
+done:
+    if (fd > 0) {
+        close(fd);
+        if (unlink(tmp_path) < 0) {
+            DEBUG(SSSDBG_MINOR_FAILURE, ("Could not remove file [%s]",
+                                         tmp_path));
+        }
+    }
+
+    talloc_free(tmp_ctx);
+    return ret;
+}
+
 static errno_t get_selinux_string(struct pam_auth_req *preq)
 {
     struct sysdb_ctx *sysdb;
@@ -494,11 +588,7 @@ static errno_t get_selinux_string(struct pam_auth_req *preq)
     }
 
     if (file_content) {
-        len = strlen(file_content)+1;
-        if (len > 0) {
-            ret = pam_add_response(pd, SSS_PAM_SELINUX_MAP, len,
-                                   (uint8_t *)file_content);
-        }
+        ret = write_selinux_string(pd->user, file_content);
     }
 
 done:
diff --git a/src/sss_client/pam_sss.c b/src/sss_client/pam_sss.c
index 3fecfabe24c9e119c0989602562d73e5938f2d3e..efbc48b6ef0458bb79dad53f81c584611f2be22d 100644
--- a/src/sss_client/pam_sss.c
+++ b/src/sss_client/pam_sss.c
@@ -41,9 +41,6 @@
 #include <security/pam_modules.h>
 #include <security/pam_ext.h>
 #include <security/pam_modutil.h>
-#ifdef HAVE_SELINUX
-#include <selinux/selinux.h>
-#endif
 #include "sss_pam_macros.h"
 
 #include "sss_cli.h"
@@ -57,8 +54,6 @@
 #define FLAGS_USE_AUTHTOK    (1 << 2)
 
 #define PWEXP_FLAG "pam_sss:password_expired_flag"
-#define ALL_SERVICES "*:"
-#define ALL_SERVICES_LEN 2
 
 #define PW_RESET_MSG_FILENAME_TEMPLATE SSSD_CONF_DIR"/customize/%s/pam_sss_pw_reset_message.%s"
 #define PW_RESET_MSG_MAX_SIZE 4096
@@ -87,7 +82,6 @@ struct pam_items {
     pid_t cli_pid;
     const char *login_name;
     char *domain_name;
-    char *selinux_user;
 };
 
 #define DEBUG_MGS_LEN 1024
@@ -967,17 +961,6 @@ 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);
-                if (!pi->selinux_user) {
-                    D(("Insufficient memory."));
-                    return PAM_SYSTEM_ERR;
-                }
-                memcpy(pi->selinux_user, &buf[p], len + 1);
-                break;
             default:
                 D(("Unknown response type [%d]", type));
         }
@@ -999,7 +982,6 @@ 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;
@@ -1083,16 +1065,6 @@ static int send_and_receive(pam_handle_t *pamh, struct pam_items *pi,
     size_t replen;
     int pam_status = PAM_SYSTEM_ERR;
 
-#ifdef HAVE_SELINUX
-    char *path = NULL;
-    char *tmp_path = NULL;
-    char *services = NULL;
-    ssize_t written;
-    int len;
-    int fd;
-    mode_t oldmask;
-#endif /* HAVE_SELINUX */
-
     print_pam_items(pi);
 
     ret = pack_message_v3(pi, &rd.len, &buf);
@@ -1180,68 +1152,6 @@ static int send_and_receive(pam_handle_t *pamh, struct pam_items *pi,
                           pi->pam_user, pam_status,
                           pam_strerror(pamh,pam_status));
                 }
-            } else {
-                if (pi->selinux_user == NULL) {
-                    pam_status = PAM_SUCCESS;
-                    break;
-                }
-
-#ifdef HAVE_SELINUX
-                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);
-                umask(oldmask);
-                if (fd < 0) {
-                    logger(pamh, LOG_ERR, "creating the temp file for SELinux "
-                           "data failed. %s", tmp_path);
-                    pam_status = PAM_SYSTEM_ERR;
-                    goto done;
-                }
-
-                /* First write filter for all services */
-                services = strdup(ALL_SERVICES);
-                if (services == NULL) {
-                    pam_status = PAM_SYSTEM_ERR;
-                    goto done;
-                }
-
-                errno = 0;
-                written = sss_atomic_write_s(fd, (void *)services, ALL_SERVICES_LEN);
-                if (written == -1) {
-                    ret = errno;
-                    logger(pamh, LOG_ERR, "writing to SELinux data file %s"
-                            "failed [%d]: %s", tmp_path, ret, strerror(ret));
-                    pam_status = PAM_SYSTEM_ERR;
-                    goto done;
-                }
-                len = strlen(pi->selinux_user);
-
-                errno = 0;
-                written = sss_atomic_write_s(fd, pi->selinux_user, len);
-                if (written == -1) {
-                    ret = errno;
-                    logger(pamh, LOG_ERR, "writing to SELinux data file %s"
-                            "failed [%d]: %s", tmp_path, ret, strerror(ret));
-                    pam_status = PAM_SYSTEM_ERR;
-                    goto done;
-                }
-
-                if (written != len) {
-                    logger(pamh, LOG_ERR, "Expected to write %d bytes, wrote %d",
-                           written, len);
-                    goto done;
-                }
-
-                close(fd);
-
-                rename(tmp_path, path);
-#endif /* HAVE_SELINUX */
             }
             break;
         case SSS_PAM_OPEN_SESSION:
@@ -1259,11 +1169,6 @@ done:
         free(buf);
     }
     free(repbuf);
-#ifdef HAVE_SELINUX
-    free(path);
-    free(tmp_path);
-    free(services);
-#endif /* HAVE_SELINUX */
 
     return pam_status;
 }
diff --git a/src/sss_client/sss_cli.h b/src/sss_client/sss_cli.h
index b634e499530bdabf015ce18b4dd219da801d12dc..f60bd99121dd45f7811699da64eec8b106b20bf3 100644
--- a/src/sss_client/sss_cli.h
+++ b/src/sss_client/sss_cli.h
@@ -368,10 +368,6 @@ enum response_type {
                           * the user.This should only be used in the case where
                           * it is not possile to use SSS_PAM_USER_INFO.
                           * @param A zero terminated string. */
-    SSS_PAM_SELINUX_MAP, /**< A content of a SELinux user mapping file. This
-                          * file should be then written to a particular
-                          * subdir in /etc/selinux for pam_selinux to read
-                          * @param A zero terminated string. */
 };
 
 /**
-- 
1.7.7.6

