diff options
Diffstat (limited to 'server')
-rw-r--r-- | server/db/sysdb.c | 97 | ||||
-rw-r--r-- | server/db/sysdb.h | 13 | ||||
-rw-r--r-- | server/db/sysdb_ops.c | 65 | ||||
-rw-r--r-- | server/providers/ldap/sdap_async_accounts.c | 272 | ||||
-rw-r--r-- | server/providers/proxy.c | 71 | ||||
-rw-r--r-- | server/tests/sysdb-tests.c | 2 |
6 files changed, 299 insertions, 221 deletions
diff --git a/server/db/sysdb.c b/server/db/sysdb.c index 8ff96566..979acf8b 100644 --- a/server/db/sysdb.c +++ b/server/db/sysdb.c @@ -68,6 +68,11 @@ struct ldb_context *sysdb_handle_get_ldb(struct sysdb_handle *handle) return handle->ctx->ldb; } +struct sysdb_ctx *sysdb_handle_get_ctx(struct sysdb_handle *handle) +{ + return handle->ctx; +} + struct sysdb_attrs *sysdb_new_attrs(TALLOC_CTX *memctx) { return talloc_zero(memctx, struct sysdb_attrs); @@ -254,6 +259,98 @@ int sysdb_attrs_add_time_t(struct sysdb_attrs *attrs, return ret; } +int sysdb_attrs_users_from_str_list(struct sysdb_attrs *attrs, + const char *attr_name, + const char *domain, + const char **list) +{ + struct ldb_message_element *el = NULL; + struct ldb_val *vals; + int i, j, num; + char *member; + int ret; + + ret = sysdb_attrs_get_el(attrs, attr_name, &el); + if (!ret) { + return ret; + } + + for (num = 0; list[num]; num++) /* count */ ; + + vals = talloc_realloc(attrs->a, el->values, + struct ldb_val, el->num_values + num); + if (!vals) { + return ENOMEM; + } + el->values = vals; + + DEBUG(9, ("Adding %d members to existing %d ones\n", + num, el->num_values)); + + for (i = 0, j = el->num_values; i < num; i++) { + + member = sysdb_user_strdn(el->values, domain, list[i]); + if (!member) { + DEBUG(4, ("Failed to get user dn for [%s]\n", list[i])); + continue; + } + el->values[j].data = (uint8_t *)member; + el->values[j].length = strlen(member); + j++; + + DEBUG(7, (" member #%d: [%s]\n", i, member)); + } + el->num_values = j; + + return EOK; +} + +int sysdb_attrs_users_from_ldb_vals(struct sysdb_attrs *attrs, + const char *attr_name, + const char *domain, + struct ldb_val *values, + int num_values) +{ + struct ldb_message_element *el = NULL; + struct ldb_val *vals; + int i, j; + char *member; + int ret; + + ret = sysdb_attrs_get_el(attrs, attr_name, &el); + if (!ret) { + return ret; + } + + vals = talloc_realloc(el, el->values, struct ldb_val, + el->num_values + num_values); + if (!vals) { + return ENOMEM; + } + el->values = vals; + + DEBUG(9, ("Adding %d members to existing %d ones\n", + num_values, el->num_values)); + + for (i = 0, j = el->num_values; i < num_values; i++) { + member = sysdb_user_strdn(el->values, domain, + (char *)values[i].data); + if (!member) { + DEBUG(4, ("Failed to get user dn for [%s]\n", + (char *)values[i].data)); + return ENOMEM; + } + el->values[j].data = (uint8_t *)member; + el->values[j].length = strlen(member); + j++; + + DEBUG(7, (" member #%d: [%s]\n", i, member)); + } + el->num_values = j; + + return EOK; +} + static char *build_dom_dn_str_escape(TALLOC_CTX *memctx, const char *template, const char *domain, const char *name) { diff --git a/server/db/sysdb.h b/server/db/sysdb.h index c345caf8..641ec680 100644 --- a/server/db/sysdb.h +++ b/server/db/sysdb.h @@ -175,6 +175,16 @@ int sysdb_attrs_get_string(struct sysdb_attrs *attrs, const char *name, int sysdb_attrs_replace_name(struct sysdb_attrs *attrs, const char *oldname, const char *newname); +int sysdb_attrs_users_from_str_list(struct sysdb_attrs *attrs, + const char *attr_name, + const char *domain, + const char **list); +int sysdb_attrs_users_from_ldb_vals(struct sysdb_attrs *attrs, + const char *attr_name, + const char *domain, + struct ldb_val *values, + int num_values); + /* convert an ldb error into an errno error */ int sysdb_error_to_errno(int ldberr); @@ -200,6 +210,7 @@ char *sysdb_group_strdn(TALLOC_CTX *memctx, struct ldb_context *sysdb_ctx_get_ldb(struct sysdb_ctx *ctx); struct ldb_context *sysdb_handle_get_ldb(struct sysdb_handle *handle); +struct sysdb_ctx *sysdb_handle_get_ctx(struct sysdb_handle *handle); int compare_ldb_dn_comp_num(const void *m1, const void *m2); @@ -497,8 +508,6 @@ struct tevent_req *sysdb_store_group_send(TALLOC_CTX *mem_ctx, struct sss_domain_info *domain, const char *name, gid_t gid, - const char **member_users, - const char **member_groups, struct sysdb_attrs *attrs, uint64_t cache_timeout); int sysdb_store_group_recv(struct tevent_req *req); diff --git a/server/db/sysdb_ops.c b/server/db/sysdb_ops.c index ae95b51b..86a9d33e 100644 --- a/server/db/sysdb_ops.c +++ b/server/db/sysdb_ops.c @@ -2778,8 +2778,6 @@ struct sysdb_store_group_state { const char *name; gid_t gid; - const char **member_users; - const char **member_groups; struct sysdb_attrs *attrs; @@ -2796,8 +2794,6 @@ struct tevent_req *sysdb_store_group_send(TALLOC_CTX *mem_ctx, struct sss_domain_info *domain, const char *name, gid_t gid, - const char **member_users, - const char **member_groups, struct sysdb_attrs *attrs, uint64_t cache_timeout) { @@ -2815,8 +2811,6 @@ struct tevent_req *sysdb_store_group_send(TALLOC_CTX *mem_ctx, state->domain = domain; state->name = name; state->gid = gid; - state->member_users = member_users; - state->member_groups = member_groups; state->attrs = attrs; state->cache_timeout = cache_timeout; @@ -2845,7 +2839,7 @@ static void sysdb_store_group_check(struct tevent_req *subreq) struct ldb_message *msg; time_t now = time(NULL); bool new_group = false; - int ret, i; + int ret; ret = sysdb_search_group_recv(subreq, state, &msg); talloc_zfree(subreq); @@ -2860,63 +2854,6 @@ static void sysdb_store_group_check(struct tevent_req *subreq) /* FIXME: use the remote modification timestamp to know if the * group needs any update */ - if (state->member_users || state->member_groups) { - if (!state->attrs) { - state->attrs = sysdb_new_attrs(state); - if (!state->attrs) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - } - - for (i = 0; state->member_users && state->member_users[i]; i++) { - char *member; - - member = sysdb_user_strdn(state, - state->domain->name, - state->member_users[i]); - if (!member) { - DEBUG(4, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - DEBUG(9, ("adding member: %s to group %s\n", - member, state->name)); - - ret = sysdb_attrs_steal_string(state->attrs, - SYSDB_MEMBER, member); - if (ret) { - DEBUG(4, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - } - - for (i = 0; state->member_groups && state->member_groups[i]; i++) { - char *member; - - member = sysdb_group_strdn(state, - state->domain->name, - state->member_groups[i]); - if (!member) { - DEBUG(4, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - DEBUG(9, ("adding member: %s to group %s\n", - member, state->name)); - - ret = sysdb_attrs_steal_string(state->attrs, - SYSDB_MEMBER, member); - if (ret) { - DEBUG(4, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - } - } - if (new_group) { /* group doesn't exist, turn into adding a group */ subreq = sysdb_add_group_send(state, state->ev, state->handle, diff --git a/server/providers/ldap/sdap_async_accounts.c b/server/providers/ldap/sdap_async_accounts.c index 157ec3e9..e4656cd7 100644 --- a/server/providers/ldap/sdap_async_accounts.c +++ b/server/providers/ldap/sdap_async_accounts.c @@ -624,64 +624,110 @@ int sdap_get_users_recv(struct tevent_req *req, /* ==Group-Parsing Routines=============================================== */ -static int sdap_parse_memberships(TALLOC_CTX *memctx, - struct sysdb_handle *handle, - struct sdap_options *opts, - struct ldb_val *values, - int num_values, - const char ***member_users, - const char ***member_groups) +struct sdap_orig_entry_state { + int done; +}; + +static void sdap_find_entry_by_origDN_done(struct tevent_req *req) +{ + struct sdap_orig_entry_state *state = tevent_req_callback_data(req, + struct sdap_orig_entry_state); + state->done = 1; +} + +/* WARNING: this is a sync routine for now */ +static int sdap_find_entry_by_origDN(TALLOC_CTX *memctx, + struct tevent_context *ev, + struct sysdb_handle *handle, + struct sss_domain_info *domain, + const char *orig_dn, + char **localdn) { - const char **mgs = NULL; - const char **mus = NULL; - int i, u, g; + struct tevent_req *req; + struct sdap_orig_entry_state *state; + static const char *attrs[] = { NULL }; + struct ldb_dn *base_dn; + char *filter; + struct ldb_message **msgs; + size_t num_msgs; int ret; - /* if this is the first time we are called, check if users and - * groups base DNs are set, if not do it */ - if (!opts->users_base) { - opts->users_base = ldb_dn_new_fmt(opts, - sysdb_handle_get_ldb(handle), "%s", - dp_opt_get_string(opts->basic, - SDAP_USER_SEARCH_BASE)); - if (!opts->users_base) { - DEBUG(1, ("Unable to get casefold Users Base DN from [%s]\n", - dp_opt_get_string(opts->basic, - SDAP_USER_SEARCH_BASE))); - DEBUG(1, ("Out of memory?!\n")); - ret = ENOMEM; - goto done; - } + state = talloc_zero(memctx, struct sdap_orig_entry_state); + if (!state) { + ret = ENOMEM; + goto done; } - if (!opts->groups_base) { - opts->groups_base = ldb_dn_new_fmt(opts, - sysdb_handle_get_ldb(handle), "%s", - dp_opt_get_string(opts->basic, - SDAP_GROUP_SEARCH_BASE)); - if (!opts->users_base) { - DEBUG(1, ("Unable to get casefold Users Base DN from [%s]\n", - dp_opt_get_string(opts->basic, - SDAP_GROUP_SEARCH_BASE))); - DEBUG(1, ("Out of memory?!\n")); - ret = ENOMEM; - goto done; - } + + filter = talloc_asprintf(state, "%s=%s", SYSDB_ORIG_DN, orig_dn); + if (!filter) { + ret = ENOMEM; + goto done; + } + + base_dn = sysdb_domain_dn(sysdb_handle_get_ctx(handle), + state, domain->name); + if (!base_dn) { + ret = ENOMEM; + goto done; + } + + req = sysdb_search_entry_send(state, ev, handle, base_dn, + LDB_SCOPE_SUBTREE, filter, attrs); + if (!req) { + ret = ENOMEM; + goto done; + } + tevent_req_set_callback(req, sdap_find_entry_by_origDN_done, state); + + /* WARNING: SYNC LOOP HERE */ + while (state->done == 0) { + tevent_loop_once(ev); + } + + ret = sysdb_search_entry_recv(req, state, &num_msgs, &msgs); + if (ret) { + goto done; + } + if (num_msgs != 1) { + ret = ENOENT; + goto done; + } + + *localdn = talloc_strdup(memctx, ldb_dn_get_linearized(msgs[0]->dn)); + if (!*localdn) { + ret = ENOENT; + goto done; } + ret = EOK; + +done: + talloc_zfree(state); + return ret; +} + +static int sdap_fill_memberships(struct sysdb_attrs *group_attrs, + struct tevent_context *ev, + struct sysdb_handle *handle, + struct sdap_options *opts, + struct sss_domain_info *domain, + struct ldb_val *values, + int num_values) +{ + struct ldb_message_element *el; + int i, j; + int ret; + switch (opts->schema_type) { case SDAP_SCHEMA_RFC2307: DEBUG(9, ("[RFC2307 Schema]\n")); - mus = talloc_array(memctx, const char *, num_values +1); - if (!mus) { - ret = ENOMEM; + ret = sysdb_attrs_users_from_ldb_vals(group_attrs, SYSDB_MEMBER, + domain->name, + values, num_values); + if (ret) { goto done; } - for (i = 0; i < num_values; i++) { - mus[i] = (char *)values[i].data; - DEBUG(7, (" member user %d: [%s]\n", i, mus[i])); - } - mus[i] = NULL; break; @@ -690,93 +736,43 @@ static int sdap_parse_memberships(TALLOC_CTX *memctx, case SDAP_SCHEMA_AD: DEBUG(9, ("[IPA or AD Schema]\n")); - /* Just allocate both big enough to contain all members for now */ - mus = talloc_array(memctx, const char *, num_values +1); - if (!mus) { - ret = ENOMEM; + ret = sysdb_attrs_get_el(group_attrs, SYSDB_MEMBER, &el); + if (ret) { goto done; } - mgs = talloc_array(memctx, const char *, num_values +1); - if (!mgs) { + /* Just allocate both big enough to contain all members for now */ + el->values = talloc_realloc(el, el->values, struct ldb_val, + el->num_values + num_values); + if (!el->values) { ret = ENOMEM; goto done; } - u = 0; - g = 0; - - for (i = 0; i < num_values; i++) { - struct ldb_dn *tmp_dn = NULL; - const struct ldb_val *v; - - /* parse out DN */ - tmp_dn = ldb_dn_new_fmt(mus, - sysdb_handle_get_ldb(handle), - "%.*s", - (int)values[i].length, - (char *)values[i].data); - if (!tmp_dn) { - DEBUG(1, ("Unable to parse DN: [%.*s]\n", - (int)values[i].length, - (char *)values[i].data)); - continue; - } - v = ldb_dn_get_rdn_val(tmp_dn); - if (!v) { - DEBUG(1, ("Unable to parse DN: [%.*s]\n", - (int)values[i].length, - (char *)values[i].data)); - continue; - } - DEBUG(9, ("Member DN [%.*s], RDN [%.*s]\n", - (int)values[i].length, (char *)values[i].data, - (int)v->length, (char *)v->data)); - - if (ldb_dn_compare_base(opts->users_base, tmp_dn) == 0) { - mus[u] = talloc_asprintf(mus, "%.*s", - (int)v->length, - (char *)v->data); - if (!mus[u]) { - DEBUG(1, ("Out of memory?!\n")); - continue; - } - u++; - - DEBUG(7, (" member user %d: [%.*s]\n", i, - (int)v->length, (char *)v->data)); - } else - if (ldb_dn_compare_base(opts->groups_base, tmp_dn) == 0) { - mgs[g] = talloc_asprintf(mgs, "%.*s", - (int)v->length, - (char *)v->data); - if (!mgs[g]) { - DEBUG(1, ("Out of memory?!\n")); - continue; + for (i = 0, j = el->num_values; i < num_values; i++) { + + /* sync search entry with this as origDN */ + ret = sdap_find_entry_by_origDN(el->values, ev, + handle, domain, + (char *)values[i].data, + (char **)&el->values[j].data); + if (ret != EOK) { + if (ret != ENOENT) { + goto done; } - g++; - DEBUG(7, (" member group %d: [%.*s]\n", i, - (int)v->length, (char *)v->data)); + DEBUG(7, (" member #%d (%s): not found!\n", + i, (char *)values[i].data)); } else { - DEBUG(1, ("Unkown Member type for DN: [%.*s]\n", - (int)values[i].length, - (char *)values[i].data)); - continue; - } - } + DEBUG(7, (" member #%d (%s): [%s]\n", + i, (char *)values[i].data, + (char *)el->values[j].data)); - if (g) { - mgs[g] = NULL; - } else { - talloc_zfree(mgs); - } - - if (u) { - mus[u] = NULL; - } else { - talloc_zfree(mus); + el->values[j].length = strlen((char *)el->values[j].data); + j++; + } } + el->num_values = j; break; @@ -790,14 +786,6 @@ static int sdap_parse_memberships(TALLOC_CTX *memctx, ret = EOK; done: - if (ret != EOK) { - talloc_zfree(mus); - talloc_zfree(mgs); - } - - *member_users = mus; - *member_groups = mgs; - return ret; } @@ -830,8 +818,6 @@ static struct tevent_req *sdap_save_group_send(TALLOC_CTX *memctx, struct tevent_req *req, *subreq; struct sdap_save_group_state *state; struct ldb_message_element *el; - const char **member_groups = NULL; - const char **member_users = NULL; struct sysdb_attrs *group_attrs; long int l; gid_t gid; @@ -937,9 +923,8 @@ static struct tevent_req *sdap_save_group_send(TALLOC_CTX *memctx, } else { DEBUG(7, ("Adding member users to group [%s]\n", state->name)); - ret = sdap_parse_memberships(state, handle, opts, - el->values, el->num_values, - &member_users, &member_groups); + ret = sdap_fill_memberships(group_attrs, ev, handle, opts, dom, + el->values, el->num_values); if (ret) { goto fail; } @@ -951,7 +936,6 @@ static struct tevent_req *sdap_save_group_send(TALLOC_CTX *memctx, subreq = sysdb_store_group_send(state, state->ev, state->handle, state->dom, state->name, gid, - member_users, member_groups, group_attrs, dp_opt_get_int(opts->basic, SDAP_ENTRY_CACHE_TIMEOUT)); @@ -1031,8 +1015,7 @@ static struct tevent_req *sdap_save_grpmem_send(TALLOC_CTX *memctx, struct tevent_req *req, *subreq; struct sdap_save_grpmem_state *state; struct ldb_message_element *el; - const char **member_groups = NULL; - const char **member_users = NULL; + struct sysdb_attrs *group_attrs = NULL; int ret; req = tevent_req_create(memctx, &state, struct sdap_save_grpmem_state); @@ -1061,9 +1044,14 @@ static struct tevent_req *sdap_save_grpmem_send(TALLOC_CTX *memctx, } else { DEBUG(7, ("Adding member users to group [%s]\n", state->name)); - ret = sdap_parse_memberships(state, handle, opts, - el->values, el->num_values, - &member_users, &member_groups); + group_attrs = sysdb_new_attrs(state); + if (!group_attrs) { + ret = ENOMEM; + goto fail; + } + + ret = sdap_fill_memberships(group_attrs, ev, handle, opts, dom, + el->values, el->num_values); if (ret) { goto fail; } @@ -1074,8 +1062,7 @@ static struct tevent_req *sdap_save_grpmem_send(TALLOC_CTX *memctx, subreq = sysdb_store_group_send(state, state->ev, state->handle, state->dom, state->name, 0, - member_users, member_groups, - NULL, + group_attrs, dp_opt_get_int(opts->basic, SDAP_ENTRY_CACHE_TIMEOUT)); if (!subreq) { @@ -1982,7 +1969,6 @@ static void sdap_get_initgr_process(struct tevent_req *subreq) struct tevent_req); struct sdap_get_initgr_state *state = tevent_req_data(req, struct sdap_get_initgr_state); - const char *user_dn; int ret; DEBUG(9, ("Process user's groups\n")); diff --git a/server/providers/proxy.c b/server/providers/proxy.c index f55b1c22..ef52ae91 100644 --- a/server/providers/proxy.c +++ b/server/providers/proxy.c @@ -956,7 +956,7 @@ static void get_gr_name_process(struct tevent_req *subreq) char *newbuf; size_t buflen; bool delete_group = false; - const char **members; + struct sysdb_attrs *members; int ret; DEBUG(7, ("Searching group by name (%s)\n", state->name)); @@ -1031,7 +1031,18 @@ again: DEBUG_GR_MEM(7, state); if (state->grp->gr_mem && state->grp->gr_mem[0]) { - members = (const char **)state->grp->gr_mem; + members = sysdb_new_attrs(state); + if (!members) { + tevent_req_error(req, ENOMEM); + return; + } + ret = sysdb_attrs_users_from_str_list(members, SYSDB_MEMBER, + state->domain->name, + (const char **)state->grp->gr_mem); + if (ret) { + tevent_req_error(req, ret); + return; + } } else { members = NULL; } @@ -1040,7 +1051,7 @@ again: state->domain, state->grp->gr_name, state->grp->gr_gid, - members, NULL, NULL, + members, ctx->entry_cache_timeout); if (!subreq) { tevent_req_error(req, ENOMEM); @@ -1178,7 +1189,7 @@ static void get_gr_gid_process(struct tevent_req *subreq) char *newbuf; size_t buflen; bool delete_group = false; - const char **members; + struct sysdb_attrs *members; int ret; DEBUG(7, ("Searching group by gid (%d)\n", state->gid)); @@ -1251,7 +1262,18 @@ again: DEBUG_GR_MEM(7, state); if (state->grp->gr_mem && state->grp->gr_mem[0]) { - members = (const char **)state->grp->gr_mem; + members = sysdb_new_attrs(state); + if (!members) { + tevent_req_error(req, ENOMEM); + return; + } + ret = sysdb_attrs_users_from_str_list(members, SYSDB_MEMBER, + state->domain->name, + (const char **)state->grp->gr_mem); + if (ret) { + tevent_req_error(req, ret); + return; + } } else { members = NULL; } @@ -1260,7 +1282,7 @@ again: state->domain, state->grp->gr_name, state->grp->gr_gid, - members, NULL, NULL, + members, ctx->entry_cache_timeout); if (!subreq) { tevent_req_error(req, ENOMEM); @@ -1405,7 +1427,7 @@ static void enum_groups_process(struct tevent_req *subreq) struct proxy_ctx *ctx = state->ctx; struct sss_domain_info *dom = ctx->be->domain; enum nss_status status; - const char **members; + struct sysdb_attrs *members; char *newbuf; int ret; @@ -1486,7 +1508,18 @@ again: DEBUG_GR_MEM(7, state); if (state->grp->gr_mem && state->grp->gr_mem[0]) { - members = (const char **)state->grp->gr_mem; + members = sysdb_new_attrs(state); + if (!members) { + tevent_req_error(req, ENOMEM); + return; + } + ret = sysdb_attrs_users_from_str_list(members, SYSDB_MEMBER, + state->domain->name, + (const char **)state->grp->gr_mem); + if (ret) { + tevent_req_error(req, ret); + return; + } } else { members = NULL; } @@ -1495,7 +1528,7 @@ again: state->domain, state->grp->gr_name, state->grp->gr_gid, - members, NULL, NULL, + members, ctx->entry_cache_timeout); if (!subreq) { tevent_req_error(req, ENOMEM); @@ -1881,6 +1914,7 @@ static struct tevent_req *get_group_from_gid_send(TALLOC_CTX *mem_ctx, char *newbuf; size_t buflen; bool delete_group = false; + struct sysdb_attrs *members; int ret; req = tevent_req_create(mem_ctx, &state, struct proxy_state); @@ -1948,12 +1982,27 @@ again: break; } + if (state->grp->gr_mem && state->grp->gr_mem[0]) { + members = sysdb_new_attrs(state); + if (!members) { + ret = ENOMEM; + goto fail; + } + ret = sysdb_attrs_users_from_str_list(members, SYSDB_MEMBER, + state->domain->name, + (const char **)state->grp->gr_mem); + if (ret) { + goto fail; + } + } else { + members = NULL; + } + subreq = sysdb_store_group_send(state, state->ev, state->handle, state->domain, state->grp->gr_name, state->grp->gr_gid, - (const char **)state->grp->gr_mem, - NULL, NULL, + members, ctx->entry_cache_timeout); if (!subreq) { ret = ENOMEM; diff --git a/server/tests/sysdb-tests.c b/server/tests/sysdb-tests.c index 3bf6ddc3..84cf8108 100644 --- a/server/tests/sysdb-tests.c +++ b/server/tests/sysdb-tests.c @@ -479,7 +479,7 @@ static void test_store_group(struct tevent_req *req) subreq = sysdb_store_group_send(data, data->ev, data->handle, data->ctx->domain, data->groupname, - data->gid, NULL, NULL, NULL, -1); + data->gid, NULL, -1); if (!subreq) { test_return(data, ret); } |