diff options
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | src/sss_client/pam_sss.c | 61 |
2 files changed, 61 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am index 90b6d8139..69c1ef857 100644 --- a/Makefile.am +++ b/Makefile.am @@ -908,6 +908,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 582a96f70..a7eb60309 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,51 @@ 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) { + logger(pamh, LOG_ERR, "creating the temp file for SELinux " + "data failed. %s", tmp_path); + 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) { + logger(pamh, LOG_ERR, "writing to SELinux data file " + "failed. %s", tmp_path); + 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: |