sdap_async_accounts.c revision c6257286e9a31dfd42d28c99a22a69e2c4717a61
/*
SSSD
Async LDAP Helper routines
Copyright (C) Simo Sorce <ssorce@redhat.com> - 2009
Copyright (C) 2010, Ralf Haferkamp <rhafer@suse.de>, Novell Inc.
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "providers/ldap/sdap_async_private.h"
#include "providers/ldap/ldap_common.h"
/* ==Save-User-Entry====================================================== */
/* FIXME: support storing additional attributes */
struct sdap_options *opts,
struct sss_domain_info *dom,
struct sysdb_attrs *attrs,
const char **ldap_attrs,
bool is_initgr,
char **_usn_value)
{
struct ldb_message_element *el;
int ret;
const char *name;
const char *pwd;
const char *gecos;
const char *homedir;
const char *shell;
struct sysdb_attrs *user_attrs;
int i;
int cache_timeout;
size_t c;
if (el->num_values == 0) {
}
if (ret) {
return ret;
}
&uid);
goto fail;
}
/* check that the uid is valid for this domain */
name));
goto fail;
}
&gid);
goto fail;
}
/* check that the gid is valid for this domain */
name));
goto fail;
}
if (user_attrs == NULL) {
goto fail;
}
if (ret) {
goto fail;
}
if (el->num_values == 0) {
} else {
if (ret) {
goto fail;
}
}
if (ret) {
goto fail;
}
if (el->num_values == 0) {
name));
} else {
name));
for (i = 0; i < el->num_values; i++) {
if (ret) {
goto fail;
}
}
}
if (ret) {
goto fail;
}
if (el->num_values == 0) {
name));
} else {
if (ret) {
goto fail;
}
}
if (ret) {
goto fail;
}
if (el->num_values == 0) {
name));
} else {
if (ret) {
goto fail;
}
if (!usn_value) {
goto fail;
}
}
if (ret) {
goto fail;
}
if (el->num_values == 0) {
} else {
if (!upn) {
goto fail;
}
}
if (ret) {
goto fail;
}
}
for (i = SDAP_FIRST_EXTRA_USER_AT; i < SDAP_OPTS_USER; i++) {
if (ret) {
goto fail;
}
if (el->num_values > 0) {
for (c = 0; c < el->num_values; c++) {
goto fail;
}
if (ret) {
goto fail;
}
}
}
}
if (is_initgr) {
if (ret) {
goto fail;
}
}
/* Make sure that any attributes we requested from LDAP that we
* did not receive are also removed from the sysdb
*/
goto fail;
}
/* Remove missing attributes */
/* Nothing to remove */
}
if (_usn_value) {
*_usn_value = usn_value;
}
return EOK;
fail:
return ret;
}
/* ==Generic-Function-to-save-multiple-users============================= */
const char **attrs,
struct sss_domain_info *dom,
struct sdap_options *opts,
struct sysdb_attrs **users,
int num_users,
char **_usn_value)
{
char *higher_usn = NULL;
char *usn_value;
int ret;
int i;
if (num_users == 0) {
/* Nothing to do if there are no users */
return EOK;
}
if (!tmpctx) {
return ENOMEM;
}
if (ret) {
goto done;
}
for (i = 0; i < num_users; i++) {
&usn_value);
/* Do not fail completely on errors.
* Just report the failure to save and go on */
if (ret) {
} else {
}
if (usn_value) {
if (higher_usn) {
} else {
}
} else {
}
}
}
if (ret) {
goto done;
}
if (_usn_value) {
}
done:
return ret;
}
/* ==Search-Users-with-filter============================================= */
struct sdap_get_users_state {
struct tevent_context *ev;
struct sdap_options *opts;
struct sdap_handle *sh;
struct sss_domain_info *dom;
const char **attrs;
const char *filter;
char *higher_usn;
struct sysdb_attrs **users;
};
struct tevent_context *ev,
struct sss_domain_info *dom,
struct sdap_options *opts,
struct sdap_handle *sh,
const char **attrs,
const char *filter,
int timeout)
{
struct sdap_get_users_state *state;
timeout);
if (!subreq) {
return NULL;
}
return req;
}
{
struct tevent_req);
struct sdap_get_users_state);
int ret;
if (ret) {
return;
}
return;
}
&state->higher_usn);
if (ret) {
return;
}
}
{
struct sdap_get_users_state);
if (usn_value) {
}
return EOK;
}
/* ==Group-Parsing Routines=============================================== */
struct sss_domain_info *domain,
const char *orig_dn,
char **localdn)
{
char *filter;
struct ldb_message **msgs;
int ret;
if (!tmpctx) {
return ENOMEM;
}
if (!filter) {
goto done;
}
if (!base_dn) {
goto done;
}
if (ret) {
goto done;
}
if (num_msgs != 1) {
goto done;
}
if (!*localdn) {
goto done;
}
done:
return ret;
}
struct sdap_options *opts,
struct sss_domain_info *domain,
int num_values)
{
struct ldb_message_element *el;
int i, j;
int ret;
switch (opts->schema_type) {
case SDAP_SCHEMA_RFC2307:
values, num_values);
if (ret) {
goto done;
}
break;
case SDAP_SCHEMA_RFC2307BIS:
case SDAP_SCHEMA_IPA_V1:
case SDAP_SCHEMA_AD:
if (ret) {
goto done;
}
/* Just allocate both big enough to contain all members for now */
goto done;
}
/* sync search entry with this as origDN */
goto done;
}
} else {
j++;
}
}
el->num_values = j;
break;
default:
DEBUG(0, ("FATAL ERROR: Unhandled schema type! (%d)\n",
opts->schema_type));
goto done;
}
done:
return ret;
}
/* ==Save-Group-Entry===================================================== */
/* FIXME: support non legacy */
/* FIXME: support storing additional attributes */
struct sdap_options *opts,
struct sss_domain_info *dom,
struct sysdb_attrs *attrs,
bool store_members,
bool populate_members,
char **_usn_value)
{
struct ldb_message_element *el;
struct sysdb_attrs *group_attrs;
int ret;
if (el->num_values == 0) {
goto fail;
}
&gid);
goto fail;
}
/* check that the gid is valid for this domain */
name));
goto fail;
}
if (!group_attrs) {
goto fail;
}
if (ret) {
goto fail;
}
if (el->num_values == 0) {
} else {
if (ret) {
goto fail;
}
}
if (ret) {
goto fail;
}
if (el->num_values == 0) {
name));
} else {
if (ret) {
goto fail;
}
}
if (ret) {
goto fail;
}
if (el->num_values == 0) {
name));
} else {
if (ret) {
goto fail;
}
if (!usn_value) {
goto fail;
}
}
if (populate_members) {
struct ldb_message_element *el1;
goto fail;
}
goto fail;
}
} else if (store_members) {
goto fail;
}
if (el->num_values == 0) {
} else {
if (ret) {
goto fail;
}
}
}
if (_usn_value) {
*_usn_value = usn_value;
}
return EOK;
fail:
return ret;
}
/* ==Save-Group-Memebrs=================================================== */
/* FIXME: support non legacy */
/* FIXME: support storing additional attributes */
struct sdap_options *opts,
struct sss_domain_info *dom,
struct sysdb_attrs *attrs)
{
struct ldb_message_element *el;
const char *name;
int ret;
&name);
goto fail;
}
goto fail;
}
if (el->num_values == 0) {
} else {
if (!group_attrs) {
goto fail;
}
if (ret) {
goto fail;
}
}
name, 0, group_attrs,
return EOK;
fail:
return ret;
}
/* ==Generic-Function-to-save-multiple-groups============================= */
struct sss_domain_info *dom,
struct sdap_options *opts,
struct sysdb_attrs **groups,
int num_groups,
bool populate_members,
char **_usn_value)
{
char *higher_usn = NULL;
char *usn_value;
bool twopass;
int ret;
int i;
switch (opts->schema_type) {
case SDAP_SCHEMA_RFC2307:
twopass = false;
break;
case SDAP_SCHEMA_RFC2307BIS:
case SDAP_SCHEMA_IPA_V1:
case SDAP_SCHEMA_AD:
twopass = true;
break;
default:
return EINVAL;
}
if (!tmpctx) {
return ENOMEM;
}
if (ret) {
goto done;
}
for (i = 0; i < num_groups; i++) {
/* if 2 pass savemembers = false */
/* Do not fail completely on errors.
* Just report the failure to save and go on */
if (ret) {
} else {
}
if (usn_value) {
if (higher_usn) {
} else {
}
} else {
}
}
}
if (twopass && !populate_members) {
for (i = 0; i < num_groups; i++) {
/* Do not fail completely on errors.
* Just report the failure to save and go on */
if (ret) {
} else {
}
}
}
if (ret) {
goto done;
}
if (_usn_value) {
}
done:
return ret;
}
/* ==Process-Groups======================================================= */
struct sdap_process_group_state {
struct tevent_context *ev;
struct sdap_options *opts;
struct sdap_handle *sh;
struct sss_domain_info *dom;
struct sysdb_attrs *group;
struct sysdb_attrs **new_members;
struct ldb_message_element* sysdb_dns;
char **queued_members;
int queue_len;
const char **attrs;
const char *filter;
bool enumeration;
};
#define GROUPMEMBER_REQ_PARALLEL 50
struct sdap_process_group_state *state,
struct ldb_message_element *memberel);
struct ldb_message_element *memberel);
struct tevent_context *ev,
struct sss_domain_info *dom,
struct sdap_options *opts,
struct sdap_handle *sh,
struct sysdb_attrs *group,
bool enumeration)
{
struct ldb_message_element *el;
struct sdap_process_group_state *grp_state;
const char **attrs;
char* filter;
int ret;
struct sdap_process_group_state);
if (ret) {
goto done;
}
/* FIXME: we ignore nested rfc2307bis groups for now */
if (!filter) {
return NULL;
}
grp_state->check_count = 0;
grp_state->member_idx = 0;
&el);
if (ret) {
goto done;
}
/* Group without members */
if (el->num_values == 0) {
goto done;
}
return NULL;
}
el->num_values);
return NULL;
}
switch (opts->schema_type) {
case SDAP_SCHEMA_RFC2307:
break;
case SDAP_SCHEMA_IPA_V1:
case SDAP_SCHEMA_AD:
case SDAP_SCHEMA_RFC2307BIS:
break;
default:
break;
}
done:
/* We managed to process all the entries */
/* EBUSY means we need to wait for entries in LDAP */
}
}
return req;
}
static int
char *user_dn,
int num_users);
static int
struct sdap_process_group_state *state,
struct ldb_message_element *memberel)
{
char *member_dn;
char *strdn;
int ret;
int i;
for (i=0; i < memberel->num_values; i++) {
&strdn);
/*
* User already cached in sysdb. Remember the sysdb DN for later
* use by sdap_save_groups()
*/
if (!state->enumeration) {
/* The user is not in sysdb, need to add it
* We don't need to do this if we're in an enumeration,
* because all real members should all be populated
* already by the first pass of the enumeration.
* Also, we don't want to be holding the sysdb
* transaction while we're performing LDAP lookups.
*/
i, member_dn));
return ret;
}
}
} else {
return ret;
}
}
}
if (state->check_count == 0) {
/*
* All group members are already cached in sysdb, we are done
* with this group. To avoid redundant sysdb lookups, populate the
* "member" attribute of the group entry with the sysdb DNs of
* the members.
*/
} else {
struct sysdb_attrs *,
if (!state->new_members) {
return ENOMEM;
}
}
return ret;
}
static int
char *username, bool *in_transaction);
static int
struct ldb_message_element *memberel)
{
struct ldb_message *msg;
bool in_transaction = false;
char *member_name;
char *strdn;
int ret;
int i;
for (i=0; i < memberel->num_values; i++) {
if (!strdn) {
goto done;
}
/*
* User already cached in sysdb. Remember the sysdb DN for later
* use by sdap_save_groups()
*/
/* The user is not in sysdb, need to add it */
i, member_name));
i, member_name));
goto done;
}
} else {
goto done;
}
}
/* sdap_process_missing_member_2307 starts transaction */
if (in_transaction) {
if (ret) {
goto done;
}
}
done:
return ret;
}
static int
char *user_dn,
int num_users)
{
struct sdap_process_group_state *grp_state =
struct tevent_req *subreq;
/*
* Issue at most GROUPMEMBER_REQ_PARALLEL LDAP searches at once.
* The rest is sent while the results are being processed.
* We limit the number as of request here, as the Server might
* enforce limits on the number of pending operations per
* connection.
*/
if (!grp_state->queued_members) {
if (!grp_state->queued_members) {
return ENOMEM;
}
}
} else {
if (!subreq) {
return ENOMEM;
}
}
grp_state->check_count++;
return EOK;
}
static int
char *username, bool *in_transaction)
{
int ret;
char* dn_string;
if (!in_transaction) return EINVAL;
if (!*in_transaction) {
return ret;
}
*in_transaction = true;
}
goto fail;
}
/*
* Convert the just received DN into the corresponding sysdb DN
* for saving into member attribute of the group
*/
(char*) username);
if (!dn) {
goto fail;
}
if (!dn_string) {
goto fail;
}
return EOK;
fail:
if (*in_transaction) {
}
return ret;
}
{
struct sysdb_attrs **usr_attrs;
int ret;
struct tevent_req *req =
struct sdap_process_group_state *state =
struct ldb_message_element *el;
char* dn_string;
state->check_count--;
if (ret) {
goto next;
}
if (count != 1) {
goto next;
}
if (el->num_values == 0) {
}
if (ret) {
goto next;
}
/*
* Convert the just received DN into the corresponding sysdb DN
* for later usage by sdap_save_groups()
*/
if (!dn) {
return;
}
if (!dn_string) {
return;
}
state->member_idx++;
next:
if (ret) {
}
/* Are there more searches for uncached users to submit ? */
if (!subreq) {
return;
}
}
if (state->check_count == 0) {
if (ret) {
return;
}
/*
* To avoid redundant sysdb lookups, populate the "member" attribute
* of the group entry with the sysdb DNs of the members.
*/
}
}
{
return EOK;
}
/* ==Search-Groups-with-filter============================================ */
struct sdap_get_groups_state {
struct tevent_context *ev;
struct sdap_options *opts;
struct sdap_handle *sh;
struct sss_domain_info *dom;
const char **attrs;
const char *filter;
char *higher_usn;
struct sysdb_attrs **groups;
};
struct tevent_context *ev,
struct sss_domain_info *dom,
struct sdap_options *opts,
struct sdap_handle *sh,
const char **attrs,
const char *filter,
int timeout)
{
struct sdap_get_groups_state *state;
timeout);
if (!subreq) {
return NULL;
}
return req;
}
static struct tevent_req *sdap_nested_group_process_send(
struct sss_domain_info *domain,
{
struct tevent_req *req =
struct sdap_get_groups_state *state =
int ret;
int i;
bool enumeration = false;
if (ret) {
return;
}
case 0:
return;
case 1:
/* Single group search */
/* Either this is RFC2307 or we have disabled nested group
* support for RFC2307bis. Either way, we'll process the
* groups in single-level, multiple-request mode.
*/
break;
}
/* Prepare hashes for nested user processing */
return;
}
return;
}
0);
if (!subreq) {
return;
}
return;
default:
/* Enumeration */
enumeration = true;
break;
}
DEBUG(0, ("Failed to start transaction\n"));
return;
}
"to allow unrolling of nested groups.\n"));
if (ret) {
return;
}
}
if (!subreq) {
return;
}
}
}
{
struct tevent_req *req =
struct sdap_get_groups_state *state =
int ret;
if (ret) {
DEBUG(0, ("Could not cancel sysdb transaction\n"));
}
return;
}
state->check_count--;
if (state->check_count == 0) {
&state->higher_usn);
if (ret) {
return;
}
DEBUG(0, ("Couldn't commit transaction\n"));
} else {
}
}
}
{
struct sdap_get_groups_state);
if (usn_value) {
}
return EOK;
}
{
int hret;
unsigned long i;
unsigned long count;
struct tevent_req);
struct sdap_get_groups_state);
return;
}
if (hret != HASH_SUCCESS) {
}
if (count) {
if (!users) {
return;
}
for (i = 0; i < count; i++) {
}
}
/* Save all of the users first so that they are in
* place for the groups to add them.
*/
return;
}
/* Users are all saved. Now save groups */
if (hret != HASH_SUCCESS) {
return;
}
if (!groups) {
return;
}
for (i = 0; i < count; i++) {
}
return;
}
/* Processing complete */
}
/* ==Save-fake-group-list=====================================*/
struct sss_domain_info *dom,
char **groupnames,
struct sysdb_attrs **ldap_groups,
int ldap_groups_count)
{
struct ldb_message *msg;
const char *name;
char **missing;
int ret;
bool in_transaction = false;
/* There are no groups in LDAP but we should add user to groups ?? */
if (ldap_groups_count == 0) return EOK;
if (!missing) {
goto fail;
}
mi = 0;
goto fail;
}
in_transaction = true;
for (i=0; groupnames[i]; i++) {
continue;
i, groupnames[i]));
mi++;
continue;
goto fail;
}
}
/* All groups are cached, nothing to do */
if (mi == 0) {
goto done;
}
for (i=0; missing[i]; i++) {
/* The group is not in sysdb, need to add a fake entry */
&name);
if (ret) {
goto fail;
}
&gid);
if (ret) {
goto fail;
}
goto fail;
}
break;
}
}
if (ai == ldap_groups_count) {
goto fail;
}
}
done:
goto fail;
}
in_transaction = false;
fail:
if (in_transaction) {
}
return ret;
}
/* ==Initgr-call-(groups-a-user-is-member-of)-RFC2307-Classic/BIS========= */
struct sdap_initgr_rfc2307_state {
struct tevent_context *ev;
struct sdap_options *opts;
struct sss_domain_info *dom;
struct sdap_handle *sh;
const char *name;
struct sysdb_attrs **ldap_groups;
};
struct tevent_context *ev,
struct sdap_options *opts,
struct sss_domain_info *dom,
struct sdap_handle *sh,
const char *base_dn,
const char *name)
{
struct sdap_initgr_rfc2307_state *state;
const char *filter;
const char **attrs;
char *clean_name;
return NULL;
}
SDAP_OPTS_GROUP, &attrs);
return NULL;
}
return NULL;
}
if (!filter) {
return NULL;
}
if (!subreq) {
return NULL;
}
return req;
}
{
struct tevent_req *req;
struct sdap_initgr_rfc2307_state *state;
struct sysdb_attrs **ldap_groups;
char **ldap_grouplist = NULL;
char **sysdb_grouplist = NULL;
char **add_groups;
char **del_groups;
struct ldb_message *msg;
struct ldb_message_element *groups;
const char *attrs[2];
int ret;
int i;
if (ret) {
return;
}
if (count == 0) {
/* No groups for this user in LDAP.
* We need to ensure that there are no groups
* in the sysdb either.
*/
} else {
return;
}
}
/* Search for all groups for which this user is a member */
attrs[0] = SYSDB_MEMBEROF;
return;
}
/* No groups for this user in sysdb currently */
} else {
if (!sysdb_grouplist) {
return;
}
/* Get a list of the groups by groupname only */
for (i=0; i < groups->num_values; i++) {
&sysdb_grouplist[i]);
return;
}
}
}
/* Find the differences between the sysdb and LDAP lists
* Groups in LDAP only must be added to the sysdb;
* groups in the sysdb only must be removed.
*/
return;
}
/* Add fake entries for any groups the user should be added as
* member of but that are not cached in sysdb
*/
if (add_groups && add_groups[0]) {
return;
}
}
(const char *const *)add_groups,
(const char *const *)del_groups);
return;
}
}
{
return EOK;
}
/* ==Initgr-call-(groups-a-user-is-member-of)-nested-groups=============== */
struct sdap_initgr_nested_state {
struct tevent_context *ev;
struct sdap_options *opts;
struct sss_domain_info *dom;
struct sdap_handle *sh;
const char **grp_attrs;
char *filter;
char **group_dns;
int count;
int cur;
struct sysdb_attrs **groups;
int groups_cur;
};
struct tevent_context *ev,
struct sdap_options *opts,
struct sss_domain_info *dom,
struct sdap_handle *sh,
struct sysdb_attrs *user,
const char **grp_attrs)
{
struct sdap_initgr_nested_state *state;
struct ldb_message_element *el;
int i, ret;
return NULL;
}
/* TODO: test rootDSE for deref support and use it if available */
/* TODO: or test rootDSE for ASQ support and use it if available */
/* user with no groups ? */
return req;
}
return NULL;
}
state->groups_cur = 0;
return NULL;
}
return NULL;
}
}
if (!subreq) {
return NULL;
}
return req;
}
{
struct tevent_req *req;
struct sdap_initgr_nested_state *state;
struct sysdb_attrs **groups;
int ret;
if (ret) {
return;
}
if (count == 1) {
state->groups_cur++;
} else {
}
if (!subreq) {
return;
}
} else {
}
}
{
struct sdap_initgr_nested_state *state;
int ret;
if (ret) {
return;
}
}
{
return EOK;
}
/* ==Initgr-call-(groups-a-user-is-member-of)============================= */
struct sdap_get_initgr_state {
struct tevent_context *ev;
struct sdap_options *opts;
struct sss_domain_info *dom;
struct sdap_handle *sh;
struct sdap_id_ctx *id_ctx;
const char *name;
const char **grp_attrs;
const char **ldap_attrs;
struct sysdb_attrs *orig_user;
};
struct tevent_context *ev,
struct sdap_handle *sh,
struct sdap_id_ctx *id_ctx,
const char *name,
const char **grp_attrs)
{
struct sdap_get_initgr_state *state;
const char *base_dn;
char *filter;
int ret;
if (!filter) {
return NULL;
}
if (!base_dn) {
return NULL;
}
if (ret) {
return NULL;
}
if (!subreq) {
return NULL;
}
return req;
}
static struct tevent_req *sdap_initgr_rfc2307bis_send(
struct tevent_context *ev,
struct sdap_options *opts,
struct sss_domain_info *dom,
struct sdap_handle *sh,
const char *base_dn,
const char *name,
const char *orig_dn);
{
struct tevent_req);
struct sdap_get_initgr_state);
struct sysdb_attrs **usr_attrs;
int ret;
const char *orig_dn;
if (ret) {
return;
}
if (count != 1) {
return;
}
if (ret) {
return;
}
true, NULL);
if (ret) {
return;
}
if (ret) {
return;
}
case SDAP_SCHEMA_RFC2307:
if (!subreq) {
return;
}
break;
case SDAP_SCHEMA_RFC2307BIS:
&orig_dn);
return;
}
if (!subreq) {
return;
}
break;
case SDAP_SCHEMA_IPA_V1:
case SDAP_SCHEMA_AD:
* We need an AD specific call that is able to unroll
* nested groups by doing extensive recursive searches */
if (!subreq) {
return;
}
return;
default:
return;
}
}
{
struct tevent_req);
struct sdap_get_initgr_state);
int ret;
char *gid;
case SDAP_SCHEMA_RFC2307:
break;
case SDAP_SCHEMA_RFC2307BIS:
break;
case SDAP_SCHEMA_IPA_V1:
case SDAP_SCHEMA_AD:
break;
default:
break;
}
if (ret) {
return;
}
/* We also need to update the user's primary group, since
* the user may not be an explicit member of that group
*/
return;
}
return;
}
if (!subreq) {
return;
}
}
{
struct tevent_req *req =
return;
}
}
{
return EOK;
}
struct sdap_nested_group_ctx {
struct tevent_context *ev;
struct sss_domain_info *domain;
struct sdap_options *opts;
struct sdap_handle *sh;
struct ldb_message_element *members;
char *member_dn;
};
static struct tevent_req *sdap_nested_group_process_send(
struct sss_domain_info *domain,
{
int hret;
struct tevent_req *req;
struct sdap_nested_group_ctx *state;
const char *groupname;
if (!req) {
return NULL;
}
/* If this is too many levels deep, just return success */
goto immediate;
}
/* Add the current group to the groups hash so we don't
* look it up more than once
*/
&groupname);
goto immediate;
}
/* This group has already been processed
* (or is in progress)
* Skip it and just return success
*/
goto immediate;
}
if (hret != HASH_SUCCESS) {
goto immediate;
}
/* Process group memberships */
/* TODO: future enhancement, check for memberuid as well
*/
/* No members to process */
}
goto immediate;
}
state->member_index = 0;
return req;
} else {
}
return req;
}
{
struct sdap_nested_group_ctx *state =
char *member_dn;
char *filter;
static const char *attrs[] = SYSDB_PW_ATTRS;
struct ldb_message **msgs;
bool has_key = false;
while (true) {
/* Continue to loop through until all entries have been
* processed.
*/
do {
/* No more entries to check. Return success */
return EOK;
}
/* First check whether this origDN is present (and not expired)
* in the sysdb
*/
goto error;
}
/* Check the user hash
* If it's there, we can save ourselves a trip to the
* sysdb and possibly LDAP as well
*/
if (has_key) {
state->member_index++;
continue;
}
} while (has_key);
goto error;
}
/* Check for the specified origDN in the sysdb */
if (!filter) {
goto error;
}
/* Try users first */
goto error;
/* It wasn't a user. Check whether it's a group */
if (!filter) {
goto error;
}
goto error;
/* It wasn't found in the groups either
* We'll have to do a blind lookup for both
*/
/* Try users first */
}
return EAGAIN;
}
/* We found a group with this origDN in the sysdb */
/* Check whether the entry is valid */
if (count != 1) {
state->member_index++;
continue;
}
0);
state->member_index++;
continue;
}
/* Refresh the group from LDAP */
return EAGAIN;
}
/* We found a user with this origDN in the sysdb */
/* Check whether the entry is valid */
if (count != 1) {
state->member_index++;
continue;
}
0);
state->member_index++;
continue;
}
/* Refresh the user from LDAP */
return EAGAIN;
} /* while (true) */
return ret;
}
{
const char **sdap_attrs;
char *filter;
struct tevent_req *subreq;
struct sdap_nested_group_ctx *state =
return ret;
}
sdap_attrs, "(objectclass=%s)",
if (!filter) {
return ENOMEM;
}
if (!subreq) {
return EIO;
}
return EOK;
}
{
const char **sdap_attrs;
char *filter;
struct tevent_req *subreq;
struct sdap_nested_group_ctx *state =
return ret;
}
sdap_attrs, "(objectclass=%s)",
if (!filter) {
return ENOMEM;
}
if (!subreq) {
return EIO;
}
return EOK;
}
{
struct tevent_req *req =
struct sdap_nested_group_ctx *state =
struct sysdb_attrs **replies;
int hret;
if (!tmp_ctx) {
return;
}
goto done;
/* Nothing to do if the user doesn't exist */
goto skip;
}
if (count != 1) {
/* There should only ever be one reply for a
* BASE search. If otherwise, it's a serious
* error.
*/
goto done;
}
/* Save the user attributes to the user hash so we can store
* them all at once later.
*/
if (hret != HASH_SUCCESS) {
goto done;
}
skip:
state->member_index++;
/* EOK means it's complete */
}
/* EAGAIN means that we should re-enter
* the mainloop
*/
done:
}
{
struct tevent_req *req =
struct sdap_nested_group_ctx *state =
struct sysdb_attrs **replies;
if (!tmp_ctx) {
return;
}
goto done;
/* Nothing to do if the group doesn't exist */
goto skip;
}
if (count != 1) {
/* There should only ever be one reply for a
* BASE search. If otherwise, it's a serious
* error.
*/
goto done;
}
/* Recurse down into the member group */
if (!subreq) {
goto done;
}
return;
skip:
state->member_index++;
/* EOK means it's complete */
}
/* EAGAIN means that we should re-enter
* the mainloop
*/
done:
}
{
struct tevent_req *req =
struct sdap_nested_group_ctx *state =
}
state->member_index++;
/* EOK means it's complete */
}
/* EAGAIN means that we should re-enter
* the mainloop
*/
}
{
struct tevent_req *req =
struct sdap_nested_group_ctx *state =
struct sysdb_attrs **replies;
int hret;
if (!tmp_ctx) {
return;
}
goto done;
/* No user found. Assume it's a group */
}
goto done;
}
if (count != 1) {
/* There should only ever be one reply for a
* BASE search. If otherwise, it's a serious
* error.
*/
goto done;
}
/* Save the user attributes to the user hash so we can store
* them all at once later.
*/
if (hret != HASH_SUCCESS) {
goto done;
}
/* Move on to the next member */
state->member_index++;
/* EOK means it's complete */
}
/* EAGAIN means that we should re-enter
* the mainloop
*/
done:
}
{
return EOK;
}
static struct tevent_req *sdap_initgr_rfc2307bis_send(
struct tevent_context *ev,
struct sdap_options *opts,
struct sss_domain_info *dom,
struct sdap_handle *sh,
const char *base_dn,
const char *name,
const char *orig_dn)
{
struct tevent_req *req;
struct tevent_req *subreq;
struct sdap_initgr_rfc2307_state *state;
const char *filter;
const char **attrs;
char *clean_orig_dn;
SDAP_OPTS_GROUP, &attrs);
return NULL;
}
return NULL;
}
if (!filter) {
return NULL;
}
if (!subreq) {
return NULL;
}
return req;
}
struct sdap_initgr_rfc2307_state *state);
struct tevent_req *rfc2307bis_nested_groups_send(
{
struct tevent_req *req;
struct sdap_initgr_rfc2307_state *state;
int ret;
&state->ldap_groups);
if (ret) {
return;
}
if (state->ldap_groups_count == 0) {
/* Start a transaction to look up the groups in the sysdb
* and update them with LDAP data
*/
} else {
}
return;
}
state->ldap_groups_count, 0);
if (!subreq) {
return;
}
}
struct sdap_initgr_rfc2307_state *state)
{
char *member_dn;
char *filter;
const char **attrs;
size_t reply_count, i;
struct ldb_message **replies;
char **ldap_grouplist;
char **sysdb_grouplist;
char **add_groups;
char **del_groups;
const char *tmp_str;
bool in_transaction = false;
if(!tmp_ctx) {
return ENOMEM;
}
goto error;
}
in_transaction = true;
/* Save this user and their memberships */
if (!attrs) {
goto error;
}
attrs[0] = SYSDB_NAME;
if (!member_dn) {
goto error;
}
if (!filter) {
goto error;
}
goto error;
reply_count = 0;
}
if (reply_count == 0) {
} else {
if (!sysdb_grouplist) {
goto error;
}
for (i = 0; i < reply_count; i++) {
NULL);
if (!tmp_str) {
/* This should never happen, but if it
* does, just skip it.
*/
continue;
}
if (!sysdb_grouplist[i]) {
goto error;
}
}
sysdb_grouplist[i] = NULL;
}
if (state->ldap_groups_count == 0) {
}
else {
goto error;
}
}
/* Find the differences between the sysdb and ldap lists
* Groups in ldap only must be added to the sysdb;
* groups in the sysdb only must be removed.
*/
goto error;
}
(const char *const *)add_groups,
(const char *const *)del_groups);
goto error;
}
goto error;
}
return EOK;
if (in_transaction) {
}
}
return ret;
}
{
struct tevent_req *req =
struct sdap_initgr_rfc2307_state *state =
return;
}
/* save the user memberships */
} else {
}
return;
}
struct sdap_rfc2307bis_nested_ctx {
struct tevent_context *ev;
struct sdap_options *opts;
struct sss_domain_info *dom;
struct sdap_handle *sh;
struct sysdb_attrs **groups;
struct sysdb_attrs **ldap_groups;
struct sysdb_handle *handle;
};
struct tevent_req *rfc2307bis_nested_groups_send(
{
struct tevent_req *req;
struct sdap_rfc2307bis_nested_ctx *state;
struct sdap_rfc2307bis_nested_ctx);
if ((num_groups == 0) ||
/* No parent groups to process or too deep*/
return req;
}
state->group_iter = 0;
}
return req;
}
{
struct tevent_req *subreq;
const char *name;
struct sysdb_attrs **grouplist;
char **groupnamelist;
bool in_transaction = false;
char *filter;
const char *orig_dn;
const char **attrs;
char *clean_orig_dn;
struct sdap_rfc2307bis_nested_ctx *state =
if (!tmp_ctx) {
goto error;
}
SYSDB_NAME, &name);
goto error;
}
goto error;
}
in_transaction = true;
/* First, save the group we're processing to the sysdb
* sdap_add_incomplete_groups_send will add them if needed
*/
/* sdap_add_incomplete_groups_send expects a list of groups */
if (!grouplist) {
goto error;
}
if (!groupnamelist) {
goto error;
}
if (!groupnamelist[0]) {
goto error;
}
groupnamelist[0]));
grouplist, 1);
goto error;
}
goto error;
}
/* Get any parent groups for this group */
&orig_dn);
goto error;
}
SDAP_OPTS_GROUP, &attrs);
goto error;
}
goto error;
}
tmp_ctx, "(&(%s=%s)(objectclass=%s))",
if (!filter) {
goto error;
}
if (!subreq) {
goto error;
}
req);
return EOK;
if (in_transaction) {
}
}
return ret;
}
struct sdap_rfc2307bis_nested_ctx *state);
{
struct tevent_req *req =
struct sdap_rfc2307bis_nested_ctx *state =
&state->ldap_groups);
if (ret) {
return;
}
if (state->ldap_groups_count == 0) {
/* No parent groups for this group in LDAP
* We need to ensure that there are no groups
* in the sysdb either.
*/
}
state->group_iter++;
}
} else {
}
return;
}
/* Otherwise, recurse into the groups */
if (!subreq) {
return;
}
}
{
return EOK;
}
{
struct tevent_req *req =
struct sdap_rfc2307bis_nested_ctx *state =
return;
}
/* All of the parent groups have been added
* Now add the memberships
*/
return;
}
state->group_iter++;
}
} else {
}
}
struct sdap_rfc2307bis_nested_ctx *state)
{
const char *name;
bool in_transaction = false;
char *member_dn;
char *filter;
const char **attrs;
size_t reply_count, i;
struct ldb_message **replies;
char **sysdb_grouplist;
char **ldap_grouplist;
char **add_groups;
char **del_groups;
const char *tmp_str;
if (!tmp_ctx) {
return ENOMEM;
}
/* Start a transaction to look up the groups in the sysdb
* and update them with LDAP data
*/
goto error;
}
in_transaction = true;
SYSDB_NAME, &name);
goto error;
}
if (!attrs) {
goto error;
}
attrs[0] = SYSDB_NAME;
if (!member_dn) {
goto error;
}
if (!filter) {
goto error;
}
&reply_count, &replies);
goto error;
reply_count = 0;
}
if (reply_count == 0) {
} else {
if (!sysdb_grouplist) {
goto error;
}
for (i = 0; i < reply_count; i++) {
NULL);
if (!tmp_str) {
/* This should never happen, but if it
* does, just skip it.
*/
continue;
}
if (!sysdb_grouplist[i]) {
goto error;
}
}
sysdb_grouplist[i] = NULL;
}
if (state->ldap_groups_count == 0) {
}
else {
goto error;
}
}
/* Find the differences between the sysdb and ldap lists
* Groups in ldap only must be added to the sysdb;
* groups in the sysdb only must be removed.
*/
goto error;
}
(const char *const *)add_groups,
(const char *const *)del_groups);
goto error;
}
goto error;
}
in_transaction = false;
if (in_transaction) {
}
}
return ret;
}
{
return EOK;
}