summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSumit Bose <sbose@redhat.com>2013-04-24 11:36:04 +0200
committerJakub Hrozek <jhrozek@redhat.com>2013-05-03 20:06:28 +0200
commite2f6326ea56217afab7623c542a237ee84eb74da (patch)
tree089642c7e2feb9fab7ce6d5311b9b4e1823e6a19
parentb24e4bec819b29f1ec8e77083d4e7610c5dd9c77 (diff)
downloadsssd2-e2f6326ea56217afab7623c542a237ee84eb74da.tar.gz
sssd2-e2f6326ea56217afab7623c542a237ee84eb74da.tar.xz
sssd2-e2f6326ea56217afab7623c542a237ee84eb74da.zip
Add SID related lookups to IPA subdomains
This patch add the functionality to handle lookup by SIDs and lookups for SIDs to the subdomain branch of the IPA ID provider.
-rw-r--r--src/providers/ipa/ipa_s2n_exop.c231
-rw-r--r--src/providers/ipa/ipa_subdomains_id.c11
2 files changed, 213 insertions, 29 deletions
diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
index c668598a..02a7bc22 100644
--- a/src/providers/ipa/ipa_s2n_exop.c
+++ b/src/providers/ipa/ipa_s2n_exop.c
@@ -280,6 +280,7 @@ done:
static errno_t s2n_encode_request(TALLOC_CTX *mem_ctx,
const char *domain_name,
int entry_type,
+ enum request_types request_type,
struct req_input *req_input,
struct berval **_bv)
{
@@ -293,25 +294,48 @@ static errno_t s2n_encode_request(TALLOC_CTX *mem_ctx,
switch (entry_type) {
case BE_REQ_USER:
+ case BE_REQ_USER_AND_GROUP: /* the extdom exop does not care if the
+ ID belongs to a user or a group */
if (req_input->type == REQ_INP_NAME) {
- ret = ber_printf(ber, "{ee{ss}}", INP_NAME, REQ_FULL,
+ ret = ber_printf(ber, "{ee{ss}}", INP_NAME, request_type,
domain_name,
req_input->inp.name);
- } else {
- ret = ber_printf(ber, "{ee{si}}", INP_POSIX_UID, REQ_FULL,
+ } else if (req_input->type == REQ_INP_ID) {
+ ret = ber_printf(ber, "{ee{si}}", INP_POSIX_UID, request_type,
domain_name,
req_input->inp.id);
+ } else {
+ DEBUG(SSSDBG_OP_FAILURE, ("Unexpected input type [%d].\n",
+ req_input->type == REQ_INP_ID));
+ ret = EINVAL;
+ goto done;
}
break;
case BE_REQ_GROUP:
if (req_input->type == REQ_INP_NAME) {
- ret = ber_printf(ber, "{ee{ss}}", INP_NAME, REQ_FULL,
+ ret = ber_printf(ber, "{ee{ss}}", INP_NAME, request_type,
domain_name,
req_input->inp.name);
- } else {
- ret = ber_printf(ber, "{ee{si}}", INP_POSIX_GID, REQ_FULL,
+ } else if (req_input->type == REQ_INP_ID) {
+ ret = ber_printf(ber, "{ee{si}}", INP_POSIX_GID, request_type,
domain_name,
req_input->inp.id);
+ } else {
+ DEBUG(SSSDBG_OP_FAILURE, ("Unexpected input type [%d].\n",
+ req_input->type == REQ_INP_ID));
+ ret = EINVAL;
+ goto done;
+ }
+ break;
+ case BE_REQ_BY_SECID:
+ if (req_input->type == REQ_INP_SECID) {
+ ret = ber_printf(ber, "{ees}", INP_SID, request_type,
+ req_input->inp.secid);
+ } else {
+ DEBUG(SSSDBG_OP_FAILURE, ("Unexpected input type [%d].\n",
+ req_input->type == REQ_INP_ID));
+ ret = EINVAL;
+ goto done;
}
break;
default:
@@ -375,9 +399,6 @@ done:
* gid INTEGER
* }
*
- * Since we always request the full data set (REQ_FULL), i.e user/group name,
- * domain name and corresponding unix id, only PosixUser (RESP_USER) and
- * PosixGroup (RESP_GROUP) are handled by s2n_response_to_attrs().
*/
struct resp_attrs {
@@ -386,6 +407,8 @@ struct resp_attrs {
union {
struct passwd user;
struct group group;
+ char *sid_str;
+ char *name;
} a;
};
@@ -403,6 +426,7 @@ static errno_t s2n_response_to_attrs(TALLOC_CTX *mem_ctx,
uid_t uid;
gid_t gid;
struct resp_attrs *attrs = NULL;
+ char *sid_str;
if (retoid == NULL || retdata == NULL) {
DEBUG(SSSDBG_OP_FAILURE, ("Missing OID or data.\n"));
@@ -469,7 +493,12 @@ static errno_t s2n_response_to_attrs(TALLOC_CTX *mem_ctx,
goto done;
}
- attrs->a.group.gr_name = talloc_strdup(attrs, name);
+ /* Winbind is not consistent with the case of the returned user
+ * name. In general all names should be lower case but there are
+ * bug in some version of winbind which might lead to upper case
+ * letters in the name. To be on the safe side we explicitly
+ * lowercase the name. */
+ attrs->a.group.gr_name = sss_tc_utf8_str_tolower(attrs, name);
if (attrs->a.group.gr_name == NULL) {
DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n"));
ret = ENOMEM;
@@ -479,6 +508,36 @@ static errno_t s2n_response_to_attrs(TALLOC_CTX *mem_ctx,
attrs->a.group.gr_gid = gid;
break;
+ case RESP_SID:
+ tag = ber_scanf(ber, "a}", &sid_str);
+ if (tag == LBER_ERROR) {
+ DEBUG(SSSDBG_OP_FAILURE, ("ber_scanf failed.\n"));
+ ret = EINVAL;
+ goto done;
+ }
+
+ attrs->a.sid_str = talloc_strdup(attrs, sid_str);
+ if (attrs->a.sid_str == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+ break;
+ case RESP_NAME:
+ tag = ber_scanf(ber, "{aa}", &domain_name, &name);
+ if (tag == LBER_ERROR) {
+ DEBUG(SSSDBG_OP_FAILURE, ("ber_scanf failed.\n"));
+ ret = EINVAL;
+ goto done;
+ }
+
+ attrs->a.name = sss_tc_utf8_str_tolower(attrs, name);
+ if (attrs->a.name == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("sss_tc_utf8_str_tolower failed.\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+ break;
default:
DEBUG(SSSDBG_OP_FAILURE, ("Unexpected response type [%d].\n",
type));
@@ -487,11 +546,13 @@ static errno_t s2n_response_to_attrs(TALLOC_CTX *mem_ctx,
}
attrs->response_type = type;
- attrs->domain_name = talloc_strdup(attrs, domain_name);
- if (attrs->domain_name == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n"));
- ret = ENOMEM;
- goto done;
+ if (type != RESP_SID) {
+ attrs->domain_name = talloc_strdup(attrs, domain_name);
+ if (attrs->domain_name == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n"));
+ ret = ENOMEM;
+ goto done;
+ }
}
ret = EOK;
@@ -515,6 +576,10 @@ struct ipa_s2n_get_user_state {
struct sdap_options *opts;
struct sss_domain_info *dom;
struct sdap_handle *sh;
+ struct req_input *req_input;
+ int entry_type;
+ enum request_types request_type;
+ struct resp_attrs *attrs;
};
static void ipa_s2n_get_user_done(struct tevent_req *subreq);
@@ -542,8 +607,12 @@ struct tevent_req *ipa_s2n_get_acct_info_send(TALLOC_CTX *mem_ctx,
state->opts = opts;
state->dom = dom;
state->sh = sh;
+ state->req_input = req_input;
+ state->entry_type = entry_type;
+ state->request_type = REQ_FULL;
- ret = s2n_encode_request(state, dom->name, entry_type, req_input, &bv_req);
+ ret = s2n_encode_request(state, dom->name, entry_type, state->request_type,
+ req_input, &bv_req);
if (ret != EOK) {
goto fail;
}
@@ -575,13 +644,16 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq)
char *retoid = NULL;
struct berval *retdata = NULL;
struct resp_attrs *attrs = NULL;
+ struct resp_attrs *simple_attrs = NULL;
time_t now;
uint64_t timeout = 10*60*60; /* FIXME: find a better timeout ! */
const char *homedir = NULL;
struct sysdb_attrs *user_attrs = NULL;
+ struct sysdb_attrs *group_attrs = NULL;
char *name;
char *realm;
char *upn;
+ struct berval *bv_req = NULL;
ret = ipa_s2n_exop_recv(subreq, state, &retoid, &retdata);
talloc_zfree(subreq);
@@ -590,22 +662,73 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq)
goto done;
}
- ret = s2n_response_to_attrs(state, retoid, retdata, &attrs);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, ("s2n_response_to_attrs failed.\n"));
+ switch (state->request_type) {
+ case REQ_FULL:
+ ret = s2n_response_to_attrs(state, retoid, retdata, &attrs);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("s2n_response_to_attrs failed.\n"));
+ goto done;
+ }
+
+ if (!(strcasecmp(state->dom->name, attrs->domain_name) == 0 ||
+ (state->dom->flat_name != NULL &&
+ strcasecmp(state->dom->flat_name, attrs->domain_name) == 0))) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Unexpected domain name returned, "
+ "expected [%s] or [%s], got [%s].\n",
+ state->dom->name,
+ state->dom->flat_name == NULL ? "" :
+ state->dom->flat_name,
+ attrs->domain_name));
+ ret = EINVAL;
+ goto done;
+ }
+
+ state->attrs = attrs;
+
+ if (state->req_input->type == REQ_INP_SECID) {
+ /* We already know the SID, we do not have to read it. */
+ break;
+ }
+
+ state->request_type = REQ_SIMPLE;
+
+ ret = s2n_encode_request(state, state->dom->name, state->entry_type,
+ state->request_type, state->req_input,
+ &bv_req);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ subreq = ipa_s2n_exop_send(state, state->ev, state->sh, bv_req);
+ if (subreq == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("ipa_s2n_exop_send failed.\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+ tevent_req_set_callback(subreq, ipa_s2n_get_user_done, req);
+
+ return;
+
+ case REQ_SIMPLE:
+ ret = s2n_response_to_attrs(state, retoid, retdata, &simple_attrs);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("s2n_response_to_attrs failed.\n"));
+ goto done;
+ }
+
+ break;
+ default:
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Unexpected request type.\n"));
+ ret = EINVAL;
goto done;
}
- if (!(strcasecmp(state->dom->name, attrs->domain_name) == 0 ||
- (state->dom->flat_name != NULL &&
- strcasecmp(state->dom->flat_name, attrs->domain_name) == 0))) {
- DEBUG(SSSDBG_OP_FAILURE, ("Unexpected domain name returned, "
- "expected [%s] or [%s], got [%s].\n",
- state->dom->name,
- state->dom->flat_name == NULL ? "" : state->dom->flat_name,
- attrs->domain_name));
+ if (state->attrs == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Missing data of full request.\n"));
ret = EINVAL;
goto done;
+ } else {
+ attrs = state->attrs;
}
now = time(NULL);
@@ -674,6 +797,24 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq)
goto done;
}
+ if (state->req_input->type == REQ_INP_SECID) {
+ ret = sysdb_attrs_add_string(user_attrs, SYSDB_SID_STR,
+ state->req_input->inp.secid);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_add_string failed.\n"));
+ goto done;
+ }
+ }
+
+ if (simple_attrs != NULL && simple_attrs->response_type == RESP_SID) {
+ ret = sysdb_attrs_add_string(user_attrs, SYSDB_SID_STR,
+ simple_attrs->a.sid_str);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_add_string failed.\n"));
+ goto done;
+ }
+ }
+
ret = sysdb_store_user(state->dom->sysdb, state->dom, name, NULL,
attrs->a.user.pw_uid, 0, NULL, /* gecos */
homedir, NULL, NULL, user_attrs, NULL,
@@ -689,8 +830,41 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq)
goto done;
}
+ group_attrs = sysdb_new_attrs(state);
+ if (group_attrs == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("sysdb_new_attrs failed.\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = sysdb_attrs_add_string(group_attrs, SYSDB_NAME_ALIAS,
+ name);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_add_string failed.\n"));
+ goto done;
+ }
+
+ if (state->req_input->type == REQ_INP_SECID) {
+ ret = sysdb_attrs_add_string(group_attrs, SYSDB_SID_STR,
+ state->req_input->inp.secid);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_add_string failed.\n"));
+ goto done;
+ }
+ }
+
+ if (simple_attrs != NULL && simple_attrs->response_type == RESP_SID) {
+ ret = sysdb_attrs_add_string(group_attrs, SYSDB_SID_STR,
+ simple_attrs->a.sid_str);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_add_string failed.\n"));
+ goto done;
+ }
+ }
+
ret = sysdb_store_group(state->dom->sysdb, state->dom, name,
- attrs->a.group.gr_gid, NULL, timeout, now);
+ attrs->a.group.gr_gid, group_attrs,
+ timeout, now);
break;
default:
DEBUG(SSSDBG_OP_FAILURE, ("Unexpected response type [%d].\n",
@@ -699,7 +873,6 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq)
goto done;
}
-
done:
talloc_free(user_attrs);
if (ret == EOK) {
diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c
index 06194837..ea313cba 100644
--- a/src/providers/ipa/ipa_subdomains_id.c
+++ b/src/providers/ipa/ipa_subdomains_id.c
@@ -91,6 +91,8 @@ struct tevent_req *ipa_get_subdom_acct_send(TALLOC_CTX *memctx,
switch (state->entry_type) {
case BE_REQ_USER:
case BE_REQ_GROUP:
+ case BE_REQ_BY_SECID:
+ case BE_REQ_USER_AND_GROUP:
ret = EOK;
break;
case BE_REQ_INITGROUPS:
@@ -164,6 +166,15 @@ static void ipa_get_subdom_acct_connected(struct tevent_req *subreq)
return;
}
break;
+ case BE_FILTER_SECID:
+ req_input->type = REQ_INP_SECID;
+ req_input->inp.secid = talloc_strdup(req_input, state->filter);
+ if (req_input->inp.secid == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n"));
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ break;
default:
DEBUG(SSSDBG_OP_FAILURE, ("Invalid sub-domain filter type.\n"));
state->dp_error = dp_error;