sdap_async_initgroups_ad.c revision d0e0e73e86f2afdb7f8fefbed70fda8d77b1c25a
/*
SSSD
Authors:
Stephen Gallagher <sgallagh@redhat.com>
Copyright (C) 2012 Red Hat
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.h"
#include "providers/ldap/ldap_common.h"
#include "providers/ldap/sdap_async_private.h"
#include "providers/ldap/sdap_idmap.h"
#include "lib/idmap/sss_idmap.h"
struct sdap_ad_match_rule_initgr_state {
struct tevent_context *ev;
struct sdap_options *opts;
struct sdap_handle *sh;
const char *name;
const char *orig_dn;
const char **attrs;
int timeout;
const char *base_filter;
char *filter;
struct sysdb_attrs **groups;
struct sdap_search_base **search_bases;
};
static errno_t
static void
struct tevent_req *
struct tevent_context *ev,
struct sdap_options *opts,
struct sdap_handle *sh,
const char *name,
const char *orig_dn,
int timeout)
{
struct tevent_req *req;
struct sdap_ad_match_rule_initgr_state *state;
const char **filter_members;
char *sanitized_user_dn;
struct sdap_ad_match_rule_initgr_state);
/* Request all of the group attributes that we know
* about, except for 'member' because that wastes a
* lot of bandwidth here and we only really
* care about a single member (the one we already
* have).
*/
if (!filter_members) {
goto immediate;
}
("Could not build attribute map: [%s]\n",
goto immediate;
}
/* Sanitize the user DN in case we have special characters in DN */
("Could not sanitize user DN: %s\n",
goto immediate;
}
/* Craft a special filter according to
*/
state->base_filter =
"(&(%s:%s:=%s)(objectClass=%s))",
if (!state->base_filter) {
goto immediate;
}
/* Start the loop through the search bases to get all of the
* groups to which this user belongs.
*/
("sdap_get_ad_match_rule_members_next_base failed: [%s]\n",
goto immediate;
}
return req;
return req;
}
static errno_t
{
struct tevent_req *subreq;
struct sdap_ad_match_rule_initgr_state *state;
return ENOMEM;
}
("Searching for groups with base [%s]\n",
if (!subreq) {
return ENOMEM;
}
req);
return EOK;
}
static void
{
struct tevent_req *req =
struct sdap_ad_match_rule_initgr_state *state =
struct sysdb_attrs **groups;
char **sysdb_grouplist;
goto error;
}
("Search for users returned %d results\n", count));
/* Add this batch of groups to the list */
if (count > 0) {
struct sysdb_attrs *,
return;
}
/* Copy the new groups into the list */
for (i = 0; i < count; i++) {
}
}
/* Continue checking other search bases */
/* There are more search bases to try */
goto error;
}
return;
}
/* No more search bases. Save the groups. */
("User is not a member of any group in the search bases\n"));
}
/* Get the current sysdb group list for this user
* so we can update it.
*/
("Could not get the list of groups for [%s] in the sysdb: "
"[%s]\n",
goto error;
}
/* The extensibleMatch search rule eliminates the need for
* nested group searches, so we can just update the
* memberships now.
*/
("Could not store groups for user [%s]: [%s]\n",
goto error;
}
return;
}
{
return EOK;
}
struct sdap_ad_tokengroups_initgr_state {
struct tevent_context *ev;
struct sdap_options *opts;
struct sdap_handle *sh;
const char *username;
};
static void
struct tevent_req *
struct tevent_context *ev,
struct sdap_options *opts,
struct sdap_handle *sh,
const char *name,
const char *orig_dn,
int timeout)
{
struct tevent_req *req;
struct tevent_req *subreq;
struct sdap_ad_tokengroups_initgr_state *state;
struct sdap_ad_tokengroups_initgr_state);
if (!subreq) {
return req;
}
req);
return req;
}
static void
{
enum idmap_error_code err;
bool in_transaction = false;
char *sid_str;
struct sysdb_attrs **users;
struct ldb_message_element *el;
struct ldb_message *msg;
char **ldap_grouplist;
char **sysdb_grouplist;
char **add_groups;
char **del_groups;
const char *group_name;
struct tevent_req *req =
struct sdap_ad_tokengroups_initgr_state *state =
if (!tmp_ctx) {
goto done;
}
goto done;
}
if (user_count != 1) {
("More than one result on a base search!\n"));
goto done;
}
/* Get the list of group SIDs */
false, &el);
("No tokenGroups entries for [%s]\n",
/* No groups in LDAP. We need to ensure that the
* sysdb matches.
*/
if (!el) {
goto done;
}
el->num_values = 0;
/* This will skip the group-processing loop below
* and proceed to removing any sysdb groups.
*/
} else {
("Could not read tokenGroups attribute: [%s]\n",
goto done;
}
}
/* Process the groups */
in_transaction = true;
if (!ldap_grouplist) {
goto done;
}
group_count = 0;
for (i = 0; i < el->num_values; i++) {
/* Get the SID and convert it to a GID */
&sid_str);
if (err != IDMAP_SUCCESS) {
("Could not convert binary SID to string: [%s]. Skipping\n",
continue;
}
("Processing membership SID [%s]\n",
sid_str));
&gid);
("Could not convert SID to GID: [%s]. Skipping\n",
continue;
}
("Processing membership GID [%lu]\n",
gid));
/* Check whether this GID already exists in the sysdb */
if (!group_name) {
("Could not retrieve group name from sysdb\n"));
goto done;
}
/* This is a new group. For now, we will store it
* under the name of its SID. When a direct lookup of
* the group or its GID occurs, it will replace this
* temporary entry.
*/
("Could not create incomplete group: [%s]\n",
goto done;
}
}
if (!ldap_grouplist[group_count]) {
goto done;
}
group_count++;
}
/* Get the current sysdb group list for this user
* so we can update it.
*/
("Could not get the list of groups for [%s] in the sysdb: "
"[%s]\n",
goto done;
}
/* Find the differences between the sysdb and LDAP lists
* Groups in the sysdb only must be removed.
*/
(const char *const *) add_groups,
(const char *const *) del_groups);
("Membership update failed [%d]: %s\n",
goto done;
}
("Could not commit transaction! [%s]\n",
goto done;
}
in_transaction = false;
done:
if (in_transaction) {
("Could not cancel transaction! [%s]\n",
sret));
}
} else {
}
return;
}
{
return EOK;
}