diff options
-rw-r--r-- | server/confdb/confdb.c | 5 | ||||
-rw-r--r-- | server/confdb/confdb.h | 1 | ||||
-rw-r--r-- | server/db/sysdb.c | 5 | ||||
-rw-r--r-- | server/db/sysdb.h | 6 | ||||
-rw-r--r-- | server/db/sysdb_ops.c | 72 | ||||
-rw-r--r-- | server/providers/ldap/sdap.c | 6 | ||||
-rw-r--r-- | server/providers/ldap/sdap.h | 3 | ||||
-rw-r--r-- | server/providers/ldap/sdap_async.c | 207 | ||||
-rw-r--r-- | server/providers/proxy.c | 8 | ||||
-rw-r--r-- | server/tests/sysdb-tests.c | 6 |
10 files changed, 243 insertions, 76 deletions
diff --git a/server/confdb/confdb.c b/server/confdb/confdb.c index 8fbae2f7a..a3bb62c87 100644 --- a/server/confdb/confdb.c +++ b/server/confdb/confdb.c @@ -797,11 +797,6 @@ static int confdb_get_domain_internal(struct confdb_ctx *cdb, DEBUG(1, ("No enumeration for [%s]!\n", domain->name)); } - /* Determine if this is a legacy domain */ - if (ldb_msg_find_attr_as_bool(res->msgs[0], "legacy", 0)) { - domain->legacy = true; - } - /* Determine if this is domain uses MPG */ if (strcasecmp(domain->provider, "local") == 0 || ldb_msg_find_attr_as_bool(res->msgs[0], CONFDB_MPG, 0)) { diff --git a/server/confdb/confdb.h b/server/confdb/confdb.h index d49040fee..a0da9b4f0 100644 --- a/server/confdb/confdb.h +++ b/server/confdb/confdb.h @@ -45,7 +45,6 @@ struct sss_domain_info { int timeout; bool enumerate; bool fqnames; - bool legacy; bool mpg; uint32_t id_min; uint32_t id_max; diff --git a/server/db/sysdb.c b/server/db/sysdb.c index d4f257977..87d0de965 100644 --- a/server/db/sysdb.c +++ b/server/db/sysdb.c @@ -47,6 +47,11 @@ struct ldb_context *sysdb_ctx_get_ldb(struct sysdb_ctx *ctx) return ctx->ldb; } +struct ldb_context *sysdb_handle_get_ldb(struct sysdb_handle *handle) +{ + return handle->ctx->ldb; +} + struct sysdb_attrs *sysdb_new_attrs(TALLOC_CTX *memctx) { return talloc_zero(memctx, struct sysdb_attrs); diff --git a/server/db/sysdb.h b/server/db/sysdb.h index 2d8b3eaea..9afb957f5 100644 --- a/server/db/sysdb.h +++ b/server/db/sysdb.h @@ -177,6 +177,9 @@ struct ldb_dn *sysdb_group_dn(struct sysdb_ctx *ctx, void *memctx, struct ldb_dn *sysdb_domain_dn(struct sysdb_ctx *ctx, void *memctx, const char *domain); +struct ldb_context *sysdb_ctx_get_ldb(struct sysdb_ctx *ctx); +struct ldb_context *sysdb_handle_get_ldb(struct sysdb_handle *handle); + /* function to start and finish a transaction * sysdb_transaction_send() will queue a request for a transaction * when it is done it will call the tevent_req callback, which must @@ -477,7 +480,8 @@ struct tevent_req *sysdb_store_group_send(TALLOC_CTX *mem_ctx, struct sss_domain_info *domain, const char *name, gid_t gid, - const char **members, + const char **member_users, + const char **member_groups, struct sysdb_attrs *attrs); int sysdb_store_group_recv(struct tevent_req *req); diff --git a/server/db/sysdb_ops.c b/server/db/sysdb_ops.c index 57705275b..3a53c9e5e 100644 --- a/server/db/sysdb_ops.c +++ b/server/db/sysdb_ops.c @@ -2771,7 +2771,8 @@ struct sysdb_store_group_state { const char *name; gid_t gid; - const char **members; + const char **member_users; + const char **member_groups; struct sysdb_attrs *attrs; }; @@ -2786,7 +2787,8 @@ struct tevent_req *sysdb_store_group_send(TALLOC_CTX *mem_ctx, struct sss_domain_info *domain, const char *name, gid_t gid, - const char **members, + const char **member_users, + const char **member_groups, struct sysdb_attrs *attrs) { struct tevent_req *req, *subreq; @@ -2803,7 +2805,8 @@ struct tevent_req *sysdb_store_group_send(TALLOC_CTX *mem_ctx, state->domain = domain; state->name = name; state->gid = gid; - state->members = members; + state->member_users = member_users; + state->member_groups = member_groups; state->attrs = attrs; subreq = sysdb_search_group_by_name_send(state, ev, NULL, handle, @@ -2845,7 +2848,7 @@ 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->members) { + if (state->member_users || state->member_groups) { if (!state->attrs) { state->attrs = sysdb_new_attrs(state); if (!state->attrs) { @@ -2855,49 +2858,42 @@ static void sysdb_store_group_check(struct tevent_req *subreq) } } - for (i = 0; state->members[i]; i++) { - struct ldb_dn *tmp = NULL; - const struct ldb_val *val; - const char *mname; + for (i = 0; state->member_users && state->member_users[i]; i++) { char *member; - if (state->domain->legacy) { - mname = state->members[i]; - } else { - - tmp = ldb_dn_new(state, state->handle->ctx->ldb, - state->members[i]); - if (!tmp) { - DEBUG(2, ("Out of memory, converting DN [%s]!\n", - state->members[i])); - continue; - } - val = ldb_dn_get_rdn_val(tmp); - if (!val) { - DEBUG(2, ("Out of memory, converting DN [%s]!\n", - state->members[i])); - continue; - } - mname = talloc_strndup(tmp, - (const char *)val->data, val->length); - if (!mname) { - DEBUG(2, ("Out of memory, converting DN [%s]!\n", - state->members[i])); - continue; - } - } - member = talloc_asprintf(state, SYSDB_TMPL_USER, - mname, state->domain->name); + state->member_users[i], + state->domain->name); if (!member) { DEBUG(6, ("Error: Out of memory\n")); tevent_req_error(req, ENOMEM); return; } - DEBUG(9, ("adding member: %s [orig: %s] to group %s\n", - member, state->members[i], state->name)); + 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(6, ("Error: %d (%s)\n", ret, strerror(ret))); + tevent_req_error(req, ret); + return; + } + } - talloc_zfree(tmp); + for (i = 0; state->member_groups && state->member_groups[i]; i++) { + char *member; + + member = talloc_asprintf(state, SYSDB_TMPL_GROUP, + state->member_users[i], + state->domain->name); + if (!member) { + DEBUG(6, ("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); diff --git a/server/providers/ldap/sdap.c b/server/providers/ldap/sdap.c index dacce9c20..616e4a37c 100644 --- a/server/providers/ldap/sdap.c +++ b/server/providers/ldap/sdap.c @@ -33,10 +33,10 @@ struct sdap_gen_opts default_basic_opts[] = { { "network_timeout", "5", NULL }, { "opt_timeout", "5", NULL }, { "tls_reqcert", "hard", NULL }, - { "userSearchBase", "dc=example,dc=com", NULL }, + { "userSearchBase", "ou=People,dc=example,dc=com", NULL }, { "userSearchScope", "sub", NULL }, { "userSearchFilter", NULL, NULL }, - { "groupSearchBase", "dc=example,dc=com", NULL }, + { "groupSearchBase", "ou=Group,dc=example,dc=com", NULL }, { "groupSearchScope", "sub", NULL }, { "groupSearchFilter", NULL, NULL }, { "ldapSchema", "rfc2307", NULL }, @@ -111,7 +111,7 @@ int sdap_get_options(TALLOC_CTX *memctx, struct sdap_options *opts; int i, ret; - opts = talloc(memctx, struct sdap_options); + opts = talloc_zero(memctx, struct sdap_options); if (!opts) return ENOMEM; opts->basic = talloc_array(opts, struct sdap_gen_opts, SDAP_OPTS_BASIC); diff --git a/server/providers/ldap/sdap.h b/server/providers/ldap/sdap.h index 0145091bf..a39eef515 100644 --- a/server/providers/ldap/sdap.h +++ b/server/providers/ldap/sdap.h @@ -152,6 +152,9 @@ struct sdap_options { SDAP_SCHEMA_RFC2307BIS = 2, /* member = dn */ SDAP_SCHEMA_IPA_V1 = 3 /* member/memberof with unrolling */ } schema_type; + + struct ldb_dn *users_base; + struct ldb_dn *groups_base; }; int sdap_get_options(TALLOC_CTX *memctx, diff --git a/server/providers/ldap/sdap_async.c b/server/providers/ldap/sdap_async.c index 84e13b51a..bcdf22a08 100644 --- a/server/providers/ldap/sdap_async.c +++ b/server/providers/ldap/sdap_async.c @@ -1120,11 +1120,14 @@ 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; - int i, ret; - const char **members; + const char **member_groups = NULL; + const char **member_users = NULL; + struct sysdb_attrs *group_attrs; + int mu, mg; + int i; long int l; gid_t gid; - struct sysdb_attrs *group_attrs; + int ret; req = tevent_req_create(memctx, &state, struct sdap_save_group_state); if (!req) return NULL; @@ -1150,22 +1153,6 @@ static struct tevent_req *sdap_save_group_send(TALLOC_CTX *memctx, state->name = (const char *)el->values[0].data; ret = sysdb_attrs_get_el(state->attrs, - opts->group_map[SDAP_AT_GROUP_MEMBER].sys_name, &el); - if (ret) goto fail; - if (el->num_values == 0) members = NULL; - else { - members = talloc_array(state, const char *, el->num_values +1); - if (!members) { - ret = ENOMEM; - goto fail; - } - for (i = 0; i < el->num_values; i++) { - members[i] = (char *)el->values[i].data; - } - members[i] = NULL; - } - - ret = sysdb_attrs_get_el(state->attrs, opts->group_map[SDAP_AT_GROUP_GID].sys_name, &el); if (ret) goto fail; if (el->num_values == 0) { @@ -1211,11 +1198,182 @@ static struct tevent_req *sdap_save_group_send(TALLOC_CTX *memctx, } } + switch (opts->schema_type) { + case SDAP_SCHEMA_RFC2307: + + ret = sysdb_attrs_get_el(state->attrs, + opts->group_map[SDAP_AT_GROUP_MEMBER].sys_name, &el); + if (ret) goto fail; + if (el->num_values == 0) { + DEBUG(7, ("[RFC2307bis] No members for group [%s]\n", state->name)); + break; + } + + DEBUG(7, ("[RFC2307] Adding member users to group [%s]\n", + state->name)); + + member_users = talloc_array(state, const char *, + el->num_values +1); + if (!member_users) { + ret = ENOMEM; + goto fail; + } + for (i = 0; i < el->num_values; i++) { + member_users[i] = (char *)el->values[i].data; + DEBUG(7, (" member user %d: [%s]\n", i, member_users[i])); + } + member_users[i] = NULL; + + break; + + case SDAP_SCHEMA_RFC2307BIS: + case SDAP_SCHEMA_IPA_V1: + + /* 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(state->handle), "%s", + opts->basic[SDAP_USER_SEARCH_BASE].value); + if (!opts->users_base) { + DEBUG(1, ("Unable to get casefold Users Base DN from [%s]\n", + opts->basic[SDAP_USER_SEARCH_BASE].value)); + DEBUG(1, ("Out of memory?!\n")); + ret = ENOMEM; + goto fail; + } + } + if (!opts->groups_base) { + opts->groups_base = ldb_dn_new_fmt(state->handle, + sysdb_handle_get_ldb(state->handle), "%s", + opts->basic[SDAP_GROUP_SEARCH_BASE].value); + if (!opts->users_base) { + DEBUG(1, ("Unable to get casefold Users Base DN from [%s]\n", + opts->basic[SDAP_USER_SEARCH_BASE].value)); + DEBUG(1, ("Out of memory?!\n")); + ret = ENOMEM; + goto fail; + } + } + + ret = sysdb_attrs_get_el(state->attrs, + opts->group_map[SDAP_AT_GROUP_MEMBER].sys_name, &el); + if (ret) goto fail; + if (el->num_values == 0) { + DEBUG(7, ("[RFC2307bis] No members for group [%s]\n", state->name)); + break; + } + + /* this will hold both lists, + * users filling up from top and groups from bottom, + * so the array will need 2 slots for NULL terminating element */ + member_users = talloc_zero_array(state, const char *, + el->num_values +2); + if (!member_users) { + ret = ENOMEM; + goto fail; + } + + mg = el->num_values; + mu = 0; + + DEBUG(7, ("[RFC2307bis] Adding members to group [%s]\n", state->name)); + + for (i = 0; i < el->num_values; i++) { + + struct ldb_dn *tmp_dn = NULL; + const struct ldb_val *v; + + + /* parse out DN */ + tmp_dn = ldb_dn_new_fmt(member_users, + sysdb_handle_get_ldb(state->handle), + "%.*s", + (int)el->values[i].length, + (char *)el->values[i].data); + if (!tmp_dn) { + DEBUG(1, ("Unable to parse DN: [%.*s]\n", + (int)el->values[i].length, + (char *)el->values[i].data)); + continue; + } + v = ldb_dn_get_rdn_val(tmp_dn); + if (!v) { + DEBUG(1, ("Unable to parse DN: [%.*s]\n", + (int)el->values[i].length, + (char *)el->values[i].data)); + continue; + } + DEBUG(9, ("Member DN [%.*s], RDN [%.*s]\n", + (int)el->values[i].length, (char *)el->values[i].data, + (int)v->length, (char *)v->data)); + + if (ldb_dn_compare_base(opts->users_base, tmp_dn) == 0) { + member_users[mu] = talloc_asprintf(member_users, + "%.*s", + (int)v->length, + (char *)v->data); + if (!member_users[mu]) { + DEBUG(1, ("Out of memory?!\n")); + continue; + } + + DEBUG(7, (" member user %d: [%s]\n", i, member_users[mu])); + + mu++; + + } else if (ldb_dn_compare_base(opts->groups_base, tmp_dn) == 0) { + member_users[mg] = talloc_asprintf(member_users, + "%.*s", + (int)v->length, + (char *)v->data); + if (!member_users[mg]) { + DEBUG(1, ("Out of memory?!\n")); + continue; + } + + DEBUG(7, (" member group %d: [%s]\n", i, member_users[mg])); + + mg--; + + } else { + DEBUG(1, ("Unkown Member type for DN: [%s]\n", + (int)el->values[i].length, + (char *)el->values[i].data)); + continue; + } + if (mu > mg) { /* shouldn't be possible */ + DEBUG(0, ("Fatal Internal error: aborting\n")); + ret = EFAULT; + goto fail; + } + } + + /* if there are groups, set member_groups */ + if (mg != el->num_values) { + member_groups = &member_users[mg+1]; + } + + /* if there are no users, reset member_users */ + if (mu == 0) { + member_users = NULL; + } + + break; + + default: + DEBUG(0, ("FATAL ERROR: Unhandled schema type! (%d)\n", + opts->schema_type)); + ret = EFAULT; + goto fail; + } + DEBUG(6, ("Storing info for group %s\n", state->name)); subreq = sysdb_store_group_send(state, state->ev, state->handle, state->dom, - state->name, gid, members, + state->name, gid, + member_users, member_groups, group_attrs); if (!subreq) { ret = ENOMEM; @@ -1555,7 +1713,14 @@ static void sdap_get_groups_transaction(struct tevent_req *subreq) return; } - DEBUG(5, ("calling ldap_search_ext with [%s].\n", state->filter)); + DEBUG(7, ("calling ldap_search_ext with [%s].\n", state->filter)); + if (debug_level >= 7) { + int i; + + for (i = 0; state->attrs[i]; i++) { + DEBUG(7, ("Requesting attrs: [%s]\n", state->attrs[i])); + } + } lret = ldap_search_ext(state->sh->ldap, state->opts->basic[SDAP_GROUP_SEARCH_BASE].value, diff --git a/server/providers/proxy.c b/server/providers/proxy.c index c308d3f80..5428a6dc8 100644 --- a/server/providers/proxy.c +++ b/server/providers/proxy.c @@ -968,7 +968,7 @@ again: state->grp->gr_name, state->grp->gr_gid, (const char **)state->grp->gr_mem, - NULL); + NULL, NULL); if (!subreq) { tevent_req_error(req, ENOMEM); return; @@ -1162,7 +1162,7 @@ again: state->grp->gr_name, state->grp->gr_gid, (const char **)state->grp->gr_mem, - NULL); + NULL, NULL); if (!subreq) { tevent_req_error(req, ENOMEM); return; @@ -1367,7 +1367,7 @@ again: state->grp->gr_name, state->grp->gr_gid, (const char **)state->grp->gr_mem, - NULL); + NULL, NULL); if (!subreq) { tevent_req_error(req, ENOMEM); return; @@ -1815,7 +1815,7 @@ again: state->grp->gr_name, state->grp->gr_gid, (const char **)state->grp->gr_mem, - NULL); + NULL, NULL); if (!subreq) { ret = ENOMEM; goto fail; diff --git a/server/tests/sysdb-tests.c b/server/tests/sysdb-tests.c index 5250b0883..424393cf3 100644 --- a/server/tests/sysdb-tests.c +++ b/server/tests/sysdb-tests.c @@ -105,7 +105,7 @@ static int setup_sysdb_tests(struct sysdb_test_ctx **ctx) talloc_free(test_ctx); return ret; } -/* + val[0] = "TRUE"; ret = confdb_add_param(test_ctx->confdb, true, "config/domains/LOCAL", "magicPrivateGroups", val); @@ -114,7 +114,7 @@ static int setup_sysdb_tests(struct sysdb_test_ctx **ctx) talloc_free(test_ctx); return ret; } -*/ + val[0] = "TRUE"; ret = confdb_add_param(test_ctx->confdb, true, "config/domains/LOCAL", "enumerate", val); @@ -471,7 +471,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); + data->gid, NULL, NULL, NULL); if (!subreq) { test_return(data, ret); } |