summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Zeleny <jzeleny@redhat.com>2012-07-24 15:36:10 -0400
committerJakub Hrozek <jhrozek@redhat.com>2012-07-27 10:37:06 +0200
commit7016947229edcaa268a82bf69fde37e521b13233 (patch)
tree0e763d33622f8173b8c2e89986707a3ae7d0e6e4
parent38e2ec1c757955ab557fd95807afa58042d09482 (diff)
downloadsssd-7016947229edcaa268a82bf69fde37e521b13233.tar.gz
sssd-7016947229edcaa268a82bf69fde37e521b13233.tar.bz2
sssd-7016947229edcaa268a82bf69fde37e521b13233.zip
Move SELinux processing from session to account PAM stack
The idea is to rename session provider to selinux provider. Processing of SELinux rules has to be performed in account stack in order to ensure that pam_selinux (which is the first module in PAM session stack) will get the correct input from SSSD. Processing of account PAM stack is bound to access provider. That means we need to have two providers executed when SSS_PAM_ACCT_MGMT message is received from PAM responder. Change in data_provider_be.c ensures just that - after access provider finishes its actions, the control is given to selinux provider and only after this provider finishes is the result returned to PAM responder.
-rw-r--r--src/providers/data_provider_be.c25
-rw-r--r--src/providers/dp_backend.h8
-rw-r--r--src/responder/pam/pamsrv_cmd.c3
-rw-r--r--src/sss_client/pam_sss.c110
4 files changed, 90 insertions, 56 deletions
diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c
index 114fde52..9571d095 100644
--- a/src/providers/data_provider_be.c
+++ b/src/providers/data_provider_be.c
@@ -753,10 +753,12 @@ static void be_pam_handler_callback(struct be_req *req,
int errnum,
const char *errstr)
{
+ struct be_client *becli = req->becli;
struct pam_data *pd;
DBusMessage *reply;
DBusConnection *dbus_conn;
dbus_bool_t dbret;
+ errno_t ret;
DEBUG(4, ("Backend returned: (%d, %d, %s) [%s]\n",
dp_err_type, errnum, errstr?errstr:"<NULL>",
@@ -764,6 +766,28 @@ static void be_pam_handler_callback(struct be_req *req,
pd = talloc_get_type(req->req_data, struct pam_data);
+ if (pd->cmd == SSS_PAM_ACCT_MGMT &&
+ req->phase == REQ_PHASE_ACCESS &&
+ dp_err_type == DP_ERR_OK) {
+ if (!becli->bectx->bet_info[BET_SELINUX].bet_ops) {
+ DEBUG(SSSDBG_TRACE_FUNC,
+ ("SELinux provider doesn't exist, "
+ "not sending the request to it.\n"));
+ } else {
+ req->phase = REQ_PHASE_SELINUX;
+
+ /* Now is the time to call SELinux provider */
+ ret = be_file_request(becli->bectx->bet_info[BET_SELINUX].pvt_bet_data,
+ req,
+ becli->bectx->bet_info[BET_SELINUX].bet_ops->handler);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("be_file_request failed.\n"));
+ goto done;
+ }
+ return;
+ }
+ }
+
DEBUG(4, ("Sending result [%d][%s]\n", pd->pam_status, pd->domain));
reply = (DBusMessage *)req->pvt;
dbret = dp_pack_pam_response(reply, pd);
@@ -852,6 +876,7 @@ static int be_pam_handler(DBusMessage *message, struct sbus_connection *conn)
break;
case SSS_PAM_ACCT_MGMT:
target = BET_ACCESS;
+ be_req->phase = REQ_PHASE_ACCESS;
break;
case SSS_PAM_CHAUTHTOK:
case SSS_PAM_CHAUTHTOK_PRELIM:
diff --git a/src/providers/dp_backend.h b/src/providers/dp_backend.h
index 4c703326..53a382ac 100644
--- a/src/providers/dp_backend.h
+++ b/src/providers/dp_backend.h
@@ -132,6 +132,8 @@ struct bet_ops {
};
#define MAX_BE_REQ_RESTARTS 2
+#define REQ_PHASE_ACCESS 0
+#define REQ_PHASE_SELINUX 1
struct be_req {
struct be_client *becli;
@@ -143,6 +145,12 @@ struct be_req {
int restarts;
+ /* This is utilized in access provider
+ * request handling to indicate if access or
+ * selinux provider is calling the callback.
+ */
+ int phase;
+
struct sss_domain_info *domain;
struct sysdb_ctx *sysdb;
};
diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c
index 006edcd3..9c4c7706 100644
--- a/src/responder/pam/pamsrv_cmd.c
+++ b/src/responder/pam/pamsrv_cmd.c
@@ -582,6 +582,7 @@ static void pam_reply_delay(struct tevent_context *ev, struct tevent_timer *te,
pam_reply(preq);
}
+static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd);
static void pam_cache_auth_done(struct pam_auth_req *preq, int ret,
time_t expire_date, time_t delayed_until);
@@ -700,7 +701,7 @@ static void pam_reply(struct pam_auth_req *preq)
return;
}
- if (pd->cmd == SSS_PAM_OPEN_SESSION &&
+ if (pd->cmd == SSS_PAM_ACCT_MGMT &&
pd->pam_status == PAM_SUCCESS) {
/* Try to fetch data from sysdb
* (auth already passed -> we should have them) */
diff --git a/src/sss_client/pam_sss.c b/src/sss_client/pam_sss.c
index 50c5048b..3fecfabe 100644
--- a/src/sss_client/pam_sss.c
+++ b/src/sss_client/pam_sss.c
@@ -1180,71 +1180,71 @@ static int send_and_receive(pam_handle_t *pamh, struct pam_items *pi,
pi->pam_user, pam_status,
pam_strerror(pamh,pam_status));
}
- }
- break;
- case SSS_PAM_OPEN_SESSION:
- if (pi->selinux_user == NULL) {
- pam_status = PAM_SUCCESS;
- break;
- }
+ } 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;
- }
+ 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;
- }
+ 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;
- }
+ /* 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;
- }
+ 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);
- if (written != len) {
- logger(pamh, LOG_ERR, "Expected to write %d bytes, wrote %d",
- written, len);
- goto done;
- }
+ 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);
+ close(fd);
- rename(tmp_path, path);
+ rename(tmp_path, path);
#endif /* HAVE_SELINUX */
+ }
break;
+ case SSS_PAM_OPEN_SESSION:
case SSS_PAM_SETCRED:
case SSS_PAM_CLOSE_SESSION:
break;