summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSumit Bose <sbose@redhat.com>2016-03-04 16:32:49 +0100
committerJakub Hrozek <jhrozek@redhat.com>2016-04-13 10:43:19 +0200
commitc371993cce13edb9185a5f0db76fbee03f0edc04 (patch)
tree7876c89826eccded98b7359f585c1accc8b0c74c
parent1df6751f81f7d9c225463f76b9789b0cc7a0de8b (diff)
downloadsssd-c371993cce13edb9185a5f0db76fbee03f0edc04.tar.gz
sssd-c371993cce13edb9185a5f0db76fbee03f0edc04.tar.xz
sssd-c371993cce13edb9185a5f0db76fbee03f0edc04.zip
IPA: resolve PAC for trusted users on IPA clients
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
-rw-r--r--src/providers/ipa/ipa_id.h9
-rw-r--r--src/providers/ipa/ipa_s2n_exop.c181
-rw-r--r--src/providers/ipa/ipa_subdomains_id.c36
3 files changed, 225 insertions, 1 deletions
diff --git a/src/providers/ipa/ipa_id.h b/src/providers/ipa/ipa_id.h
index 91a941153..f59bc6a8e 100644
--- a/src/providers/ipa/ipa_id.h
+++ b/src/providers/ipa/ipa_id.h
@@ -120,4 +120,13 @@ ipa_initgr_get_overrides_send(TALLOC_CTX *memctx,
struct ldb_message **groups,
const char *groups_id_attr);
int ipa_initgr_get_overrides_recv(struct tevent_req *req, int *dp_error);
+
+struct tevent_req *ipa_get_subdom_acct_process_pac_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sdap_handle *sh,
+ struct ipa_id_ctx *ipa_ctx,
+ struct sss_domain_info *dom,
+ struct ldb_message *user_msg);
+
+errno_t ipa_get_subdom_acct_process_pac_recv(struct tevent_req *req);
#endif
diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
index 95af34a09..c1bc42ff1 100644
--- a/src/providers/ipa/ipa_s2n_exop.c
+++ b/src/providers/ipa/ipa_s2n_exop.c
@@ -22,11 +22,14 @@
#include "util/util.h"
#include "util/sss_nss.h"
#include "util/strtonum.h"
-#include "db/sysdb.h"
#include "providers/ldap/sdap_async_private.h"
+#include "providers/ldap/sdap_async_ad.h"
#include "providers/ldap/ldap_common.h"
+#include "providers/ldap/sdap_idmap.h"
#include "providers/ipa/ipa_id.h"
#include "providers/ipa/ipa_subdomains.h"
+#include "providers/ad/ad_pac.h"
+#include "db/sysdb.h"
enum input_types {
INP_SID = 1,
@@ -2401,3 +2404,179 @@ int ipa_s2n_get_acct_info_recv(struct tevent_req *req)
return EOK;
}
+
+struct ipa_get_subdom_acct_process_pac_state {
+ struct tevent_context *ev;
+ struct sdap_handle *sh;
+ struct sss_domain_info *dom;
+ char *username;
+
+ size_t num_missing_sids;
+ char **missing_sids;
+ size_t num_cached_groups;
+ char **cached_groups;
+};
+
+static void ipa_get_subdom_acct_process_pac_done(struct tevent_req *subreq);
+
+struct tevent_req *ipa_get_subdom_acct_process_pac_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sdap_handle *sh,
+ struct ipa_id_ctx *ipa_ctx,
+ struct sss_domain_info *dom,
+ struct ldb_message *user_msg)
+{
+ int ret;
+ struct ipa_get_subdom_acct_process_pac_state *state;
+ struct tevent_req *req;
+ struct tevent_req *subreq;
+ char *user_sid;
+ char *primary_group_sid;
+ size_t num_sids;
+ char **group_sids;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct ipa_get_subdom_acct_process_pac_state);
+ if (req == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "tevent_req_create failed.\n");
+ return NULL;
+ }
+
+ state->ev = ev;
+ state->sh = sh;
+ state->dom = dom;
+
+ ret = ad_get_pac_data_from_user_entry(state, user_msg,
+ ipa_ctx->sdap_id_ctx->opts->idmap_ctx->map,
+ &state->username,
+ &user_sid, &primary_group_sid,
+ &num_sids, &group_sids);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "ad_get_pac_data_from_user_entry failed.\n");
+ goto done;
+ }
+
+ ret = sdap_ad_tokengroups_get_posix_members(state, state->dom,
+ num_sids, group_sids,
+ &state->num_missing_sids,
+ &state->missing_sids,
+ &state->num_cached_groups,
+ &state->cached_groups);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "sdap_ad_tokengroups_get_posix_members failed.\n");
+ goto done;
+ }
+
+
+ if (state->num_missing_sids == 0) {
+ ret = sdap_ad_tokengroups_update_members(state->username,
+ state->dom->sysdb,
+ state->dom,
+ state->cached_groups);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_MINOR_FAILURE, "Membership update failed [%d]: %s\n",
+ ret, strerror(ret));
+ }
+
+ goto done;
+ }
+
+
+ subreq = ipa_s2n_get_list_send(state, state->ev, ipa_ctx, state->dom,
+ state->sh,
+ dp_opt_get_int(ipa_ctx->sdap_id_ctx->opts->basic,
+ SDAP_SEARCH_TIMEOUT),
+ BE_REQ_BY_SECID, REQ_FULL, REQ_INP_SECID,
+ state->missing_sids);
+ if (subreq == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_get_list_send failed.\n");
+ ret = ENOMEM;
+ goto done;
+ }
+ tevent_req_set_callback(subreq, ipa_get_subdom_acct_process_pac_done, req);
+
+ return req;
+
+done:
+ if (ret == EOK) {
+ tevent_req_done(req);
+ } else {
+ tevent_req_error(req, ret);
+ }
+ tevent_req_post(req, ev);
+
+ return req;
+}
+
+static void ipa_get_subdom_acct_process_pac_done(struct tevent_req *subreq)
+{
+ int ret;
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct ipa_get_subdom_acct_process_pac_state *state = tevent_req_data(req,
+ struct ipa_get_subdom_acct_process_pac_state);
+ char **cached_groups;
+ size_t num_cached_groups;
+
+ ret = ipa_s2n_get_list_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "s2n get_fqlist request failed.\n");
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ /* from ad_pac.c */
+ ret = sdap_ad_tokengroups_get_posix_members(state, state->dom,
+ state->num_missing_sids,
+ state->missing_sids,
+ NULL, NULL,
+ &num_cached_groups,
+ &cached_groups);
+ if (ret != EOK){
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ "sdap_ad_tokengroups_get_posix_members failed [%d]: %s\n",
+ ret, strerror(ret));
+ goto done;
+ }
+
+ state->cached_groups = concatenate_string_array(state,
+ state->cached_groups,
+ state->num_cached_groups,
+ cached_groups,
+ num_cached_groups);
+ if (state->cached_groups == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ /* update membership of existing groups */
+ ret = sdap_ad_tokengroups_update_members(state->username,
+ state->dom->sysdb,
+ state->dom,
+ state->cached_groups);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_MINOR_FAILURE, "Membership update failed [%d]: %s\n",
+ ret, strerror(ret));
+ goto done;
+ }
+
+ ret = EOK;
+
+done:
+ if (ret == EOK) {
+ tevent_req_done(req);
+ } else {
+ tevent_req_error(req, ret);
+ }
+
+ return;
+}
+
+errno_t ipa_get_subdom_acct_process_pac_recv(struct tevent_req *req)
+{
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ return EOK;
+}
diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c
index 70a1b6a12..f98f8bf8e 100644
--- a/src/providers/ipa/ipa_subdomains_id.c
+++ b/src/providers/ipa/ipa_subdomains_id.c
@@ -30,8 +30,10 @@
#include "db/sysdb.h"
#include "providers/ldap/ldap_common.h"
#include "providers/ldap/sdap_async.h"
+#include "providers/ldap/sdap_async_ad.h"
#include "providers/ipa/ipa_id.h"
#include "providers/ad/ad_id.h"
+#include "providers/ad/ad_pac.h"
#include "providers/ipa/ipa_subdomains.h"
static struct tevent_req *
@@ -346,6 +348,8 @@ struct ipa_get_subdom_acct {
int entry_type;
const char *filter;
int filter_type;
+ bool use_pac;
+ struct ldb_message *user_msg;
int dp_error;
};
@@ -372,6 +376,7 @@ struct tevent_req *ipa_get_subdom_acct_send(TALLOC_CTX *memctx,
state->ctx = ipa_ctx->sdap_id_ctx;
state->dp_error = DP_ERR_FATAL;
state->override_attrs = override_attrs;
+ state->use_pac = false;
state->op = sdap_id_op_create(state, state->ctx->conn->conn_cache);
if (!state->op) {
@@ -398,7 +403,15 @@ struct tevent_req *ipa_get_subdom_acct_send(TALLOC_CTX *memctx,
case BE_REQ_GROUP:
case BE_REQ_BY_SECID:
case BE_REQ_USER_AND_GROUP:
+ ret = EOK;
+ break;
case BE_REQ_INITGROUPS:
+ ret = check_if_pac_is_available(state, state->domain, ar,
+ &state->user_msg);
+ if (ret == EOK) {
+ state->use_pac = true;
+ }
+
ret = EOK;
break;
default:
@@ -447,6 +460,29 @@ static void ipa_get_subdom_acct_connected(struct tevent_req *subreq)
EXOP_SID2NAME_V1_OID)) {
state->entry_type = BE_REQ_USER;
} else {
+ if (state->use_pac && state->user_msg != NULL) {
+ /* This means the user entry is already in the cache and has
+ * the pac attached, we only have look up the missing groups
+ * and add the user to all groups. */
+
+ subreq = ipa_get_subdom_acct_process_pac_send(state, state->ev,
+ sdap_id_op_handle(state->op),
+ state->ipa_ctx,
+ state->domain,
+ state->user_msg);
+ if (subreq == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "ipa_get_subdom_acct_process_pac failed.\n");
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ tevent_req_set_callback(subreq, ipa_get_subdom_acct_done, req);
+
+ return;
+ }
+
+ /* Fall through if there is no PAC */
+
DEBUG(SSSDBG_TRACE_FUNC, "Initgroups requests are not handled " \
"by the IPA provider but are resolved " \
"by the responder directly from the " \