summaryrefslogtreecommitdiffstats
path: root/src/back-sch-sssd.c
diff options
context:
space:
mode:
authorAlexander Bokovoy <abokovoy@redhat.com>2013-07-23 21:08:56 +0300
committerAlexander Bokovoy <abokovoy@redhat.com>2013-07-26 16:10:05 +0300
commitd862fc6fc65f1fb5ff0582e3561a7ab988af9432 (patch)
treea175494a22ae321ea89c410afb53d79d14d9f375 /src/back-sch-sssd.c
parent633c4c92b73efeb3d660b70480108b0db41fa3bd (diff)
downloadslapi-nis-freeipa-nss-compat.tar.gz
slapi-nis-freeipa-nss-compat.tar.xz
slapi-nis-freeipa-nss-compat.zip
WIP compat plugin: solve deadlock when looking up SSSD usersfreeipa-nss-compat
Diffstat (limited to 'src/back-sch-sssd.c')
-rw-r--r--src/back-sch-sssd.c273
1 files changed, 199 insertions, 74 deletions
diff --git a/src/back-sch-sssd.c b/src/back-sch-sssd.c
index 8168675..2a02f90 100644
--- a/src/back-sch-sssd.c
+++ b/src/back-sch-sssd.c
@@ -47,18 +47,21 @@
#include "plugin.h"
#include "map.h"
#include "back-sch.h"
+#include "format.h"
struct backend_search_filter_config {
bool_t search_user;
bool_t search_group;
bool_t search_uid;
bool_t search_gid;
+ bool_t search_members;
bool_t name_set;
+ bool_t wrong_search;
char *name;
};
/* Check simple filter to see if it has
- * (cn|uid|uidNumber|gidNumber=<value>) or (objectClass=posixGroup)
+ * (cn|uid|uidNumber|gidNumber|memberUid=<value>) or (objectClass=posixGroup|shadowAccount)
* Called by slapi_filter_apply(). */
static int
backend_search_filter_has_cn_uid(Slapi_Filter *filter, void *arg)
@@ -82,13 +85,19 @@ backend_search_filter_has_cn_uid(Slapi_Filter *filter, void *arg)
config->name_set = TRUE;
} else if (0 == strcasecmp(filter_type, "cn")) {
config->name_set = TRUE;
+ } else if (0 == strcasecmp(filter_type, "memberUid")) {
+ config->name_set = TRUE;
+ config->search_members = TRUE;
} else if ((0 == strcasecmp(filter_type, "objectClass")) &&
(0 == strcasecmp(bval->bv_val, "posixGroup"))) {
config->search_group = TRUE;
+ } else if ((0 == strcasecmp(filter_type, "objectClass")) &&
+ (0 == strcasecmp(bval->bv_val, "shadowAccount"))) {
+ config->wrong_search = TRUE;
}
if ((NULL == config->name) && config->name_set) {
- config->name = bval->bv_val;
+ config->name = format_strdupbv(bval);
}
}
@@ -103,27 +112,27 @@ backend_search_filter_has_cn_uid(Slapi_Filter *filter, void *arg)
static Slapi_Entry *
backend_retrieve_user_entry_from_sssd(char *user_name, bool_t is_uid,
- struct backend_set_data *set_data,
- struct backend_search_cbdata *cbdata)
+ char *container_sdn,
+ struct backend_search_cbdata *cbdata)
{
struct passwd pwd, *result;
Slapi_Entry *entry;
int rc;
enum sss_id_type id_type;
- char *sid_str;
+ char *sid_str, *dn;
- if (set_data->sssd_buffer == NULL) {
+ if (cbdata->sssd_buffer == NULL) {
return NULL;
}
if (is_uid) {
rc = getpwuid_r(atoi(user_name), &pwd,
- set_data->sssd_buffer,
- set_data->sssd_buffer_len, &result);
+ cbdata->sssd_buffer,
+ cbdata->sssd_buffer_len, &result);
} else {
rc = getpwnam_r(user_name, &pwd,
- set_data->sssd_buffer,
- set_data->sssd_buffer_len, &result);
+ cbdata->sssd_buffer,
+ cbdata->sssd_buffer_len, &result);
}
if ((result == NULL) || (rc != 0)) {
return NULL;
@@ -138,6 +147,14 @@ backend_retrieve_user_entry_from_sssd(char *user_name, bool_t is_uid,
return NULL;
}
+ dn = slapi_ch_smprintf("uid=%s,%s",
+ slapi_escape_filter_value(pwd.pw_name, -1),
+ container_sdn);
+ if (dn == NULL) {
+ slapi_entry_free(entry);
+ return NULL;
+ }
+
slapi_entry_add_string(entry,
"objectClass", "top");
slapi_entry_add_string(entry,
@@ -145,7 +162,7 @@ backend_retrieve_user_entry_from_sssd(char *user_name, bool_t is_uid,
slapi_entry_add_string(entry,
"objectClass", "extensibleObject");
slapi_entry_add_string(entry,
- "uid", user_name);
+ "uid", pwd.pw_name);
slapi_entry_attr_set_int(entry,
"uidNumber", pwd.pw_uid);
slapi_entry_attr_set_int(entry,
@@ -157,16 +174,15 @@ backend_retrieve_user_entry_from_sssd(char *user_name, bool_t is_uid,
"cn", pwd.pw_gecos);
} else {
slapi_entry_add_string(entry,
- "cn", user_name);
+ "cn", pwd.pw_name);
}
slapi_entry_add_string(entry,
"homeDirectory", pwd.pw_dir);
slapi_entry_add_string(entry,
"loginShell", pwd.pw_shell);
- slapi_entry_set_sdn(entry, set_data->container_sdn);
- slapi_entry_set_dn(entry, slapi_ch_smprintf("uid=%s,%s",
- user_name, slapi_sdn_get_dn(set_data->container_sdn)));
+
+ slapi_entry_set_dn(entry, dn);
rc = sss_nss_getsidbyid(pwd.pw_uid, &sid_str, &id_type);
if ((rc == 0) && (sid_str != NULL)) {
@@ -175,35 +191,33 @@ backend_retrieve_user_entry_from_sssd(char *user_name, bool_t is_uid,
free(sid_str);
}
-
return entry;
}
static Slapi_Entry *
backend_retrieve_group_entry_from_sssd(char *group_name, bool_t is_gid,
- struct backend_set_data *set_data,
- struct backend_search_cbdata *cbdata)
+ char *container_sdn,
+ struct backend_search_cbdata *cbdata)
{
struct group grp, *result;
- const char *sdn;
Slapi_Entry *entry;
int rc, i;
enum sss_id_type id_type;
- char *sid_str;
+ char *sid_str, *dn;
- if (set_data->sssd_buffer == NULL) {
+ if (cbdata->sssd_buffer == NULL) {
return NULL;
}
if (is_gid) {
rc = getgrgid_r(atoi(group_name), &grp,
- set_data->sssd_buffer,
- set_data->sssd_buffer_len, &result);
+ cbdata->sssd_buffer,
+ cbdata->sssd_buffer_len, &result);
} else {
rc = getgrnam_r(group_name, &grp,
- set_data->sssd_buffer,
- set_data->sssd_buffer_len, &result);
+ cbdata->sssd_buffer,
+ cbdata->sssd_buffer_len, &result);
}
if ((result == NULL) || (rc != 0)) {
return NULL;
@@ -218,6 +232,14 @@ backend_retrieve_group_entry_from_sssd(char *group_name, bool_t is_gid,
return NULL;
}
+ dn = slapi_ch_smprintf("cn=%s,%s",
+ slapi_escape_filter_value(grp.gr_name, -1),
+ container_sdn);
+ if (dn == NULL) {
+ slapi_entry_free(entry);
+ return NULL;
+ }
+
slapi_entry_add_string(entry,
"objectClass", "top");
slapi_entry_add_string(entry,
@@ -225,27 +247,18 @@ backend_retrieve_group_entry_from_sssd(char *group_name, bool_t is_gid,
slapi_entry_add_string(entry,
"objectClass", "extensibleObject");
slapi_entry_add_string(entry,
- "cn", group_name);
+ "cn", grp.gr_name);
slapi_entry_attr_set_int(entry,
"gidNumber", grp.gr_gid);
- slapi_entry_set_sdn(entry, set_data->container_sdn);
- slapi_entry_set_dn(entry,
- slapi_ch_smprintf("cn=%s,%s", group_name,
- slapi_sdn_get_dn(set_data->container_sdn)));
-
if (grp.gr_mem) {
- if (set_data->sssd_relevant_set != NULL) {
- sdn = slapi_sdn_get_dn(set_data->sssd_relevant_set->container_sdn);
- } else {
- sdn = slapi_sdn_get_dn(set_data->container_sdn);
- }
for (i=0; grp.gr_mem[i]; i++) {
- slapi_entry_add_string(entry, "memberUid",
- slapi_ch_smprintf("uid=%s,%s", grp.gr_mem[i], sdn));
+ slapi_entry_add_string(entry, "memberUid", grp.gr_mem[i]);
}
}
+ slapi_entry_set_dn(entry, dn);
+
rc = sss_nss_getsidbyid(grp.gr_gid, &sid_str, &id_type);
if ((rc == 0) && (sid_str != NULL)) {
slapi_entry_add_string(entry, "objectClass", "ipaNTGroupAttrs");
@@ -256,42 +269,89 @@ backend_retrieve_group_entry_from_sssd(char *group_name, bool_t is_gid,
return entry;
}
-static void
-backend_search_sssd_send_entry(struct backend_set_data *set_data,
- struct backend_search_cbdata *cbdata,
- Slapi_Entry *entry)
+static Slapi_Entry **
+backend_retrieve_group_list_from_sssd(char *user_name, char *container_sdn,
+ struct backend_search_cbdata *cbdata,
+ int *count)
{
- char *ndn;
- if (entry) {
- slapi_entry_add_string(entry,
- "schema-compat-origin", "sssd");
- cbdata->matched = TRUE;
- ndn = slapi_entry_get_ndn(entry);
- backend_set_entry(cbdata->pb, entry, set_data);
- slapi_send_ldap_search_entry(cbdata->pb, entry,
- NULL, cbdata->attrs,
- cbdata->attrsonly);
- cbdata->n_entries++;
- if (cbdata->closest_match) {
- free(cbdata->closest_match);
+ struct passwd pwd, *pwd_result;
+ gid_t *grouplist;
+ Slapi_Entry **entries, *entry;
+ int rc, ngroups, i, idx;
+ /* gid_t is unsigned int */
+#define GROUP_LEN_MAX (sizeof("4294967295") + 1)
+ char group[GROUP_LEN_MAX];
+
+ if (cbdata->sssd_buffer == NULL) {
+ return NULL;
+ }
+
+ rc = getpwnam_r(user_name, &pwd,
+ cbdata->sssd_buffer,
+ cbdata->sssd_buffer_len, &pwd_result);
+
+ if ((pwd_result == NULL) || (rc != 0)) {
+ return NULL;
+ }
+
+ if (pwd.pw_uid < cbdata->sssd_min_id) {
+ return NULL;
+ }
+
+ ngroups = 32;
+ grouplist = malloc(sizeof(gid_t) * ngroups);
+ if (grouplist == NULL) {
+ return NULL;
+ }
+
+ do {
+ rc = getgrouplist(user_name, pwd.pw_gid, grouplist, &ngroups);
+ if (rc < ngroups) {
+ grouplist = realloc(grouplist, ngroups * sizeof(gid_t));
}
- cbdata->closest_match = strdup(ndn);
- /* Entry is created, cache it via map.
- * Next request will be served from the cache */
- //backend_set_entry(cbdata->pb, entry, set_data);
- slapi_entry_free(entry);
+ } while (rc != ngroups);
+
+ entries = malloc(sizeof(Slapi_Entry *) * ngroups);
+ if (entries == NULL) {
+ free(grouplist);
+ return NULL;
+ }
+
+ idx = 0;
+ /* At this point we are not interested in the buffer used in pwd anymore
+ * so the next function can take it over for getgrid_r() */
+ for (i = 0; i < ngroups; i++) {
+ rc = snprintf(group, GROUP_LEN_MAX, "%u", grouplist[i]);
+ if ((rc > 0) && (rc <= GROUP_LEN_MAX)) {
+ entry = backend_retrieve_group_entry_from_sssd(group, TRUE, container_sdn, cbdata);
+ if (entry) {
+ entries[idx] = entry;
+ idx++;
+ }
+ }
+ }
+
+ if (idx != ngroups) {
+ entries = realloc(entries, idx * sizeof(Slapi_Entry *));
}
+
+ *count = idx;
+
+ free(grouplist);
+
+ return entries;
+
}
/* Check filter for a component like (uid=<value>) and if found,
- * perform look up against SSSD and create entry based on that */
+ * stage SSSD lookup. Lookup will be performed later, with call to backend_retrieve_from_sssd */
void
backend_search_sssd(struct backend_set_data *set_data,
struct backend_search_cbdata *cbdata)
{
int result, rc;
- Slapi_Entry *entry;
- struct backend_search_filter_config config = {FALSE, FALSE, FALSE, FALSE, FALSE, NULL};
+ struct backend_search_filter_config config = {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL};
+ struct backend_staged_data *staged = NULL;
/* There was no match but we asked to check SSSD */
/* First, we search the filter to see if it includes cn|uid=<value> check */
@@ -302,6 +362,10 @@ backend_search_sssd(struct backend_set_data *set_data,
return;
}
+ if (config.wrong_search) {
+ return;
+ }
+
/* Drop irrelevant requests. Each set only works with a single type */
if ((cbdata->check_sssd == SCH_SSSD_GROUP) &&
(config.search_uid || config.search_user)) {
@@ -314,22 +378,83 @@ backend_search_sssd(struct backend_set_data *set_data,
}
if ((config.search_gid || config.search_uid) &&
- (atol(config.name) < set_data->sssd_min_id)) {
+ (atol(config.name) < cbdata->sssd_min_id)) {
return;
}
- if ((config.search_group || config.search_gid) &&
- (NULL != config.name)) {
- entry = backend_retrieve_group_entry_from_sssd(config.name,
- config.search_gid, set_data, cbdata);
- backend_search_sssd_send_entry(set_data, cbdata, entry);
+
+ staged = malloc(sizeof(struct backend_staged_data));
+ if (staged == NULL) {
+ free(config.name);
return;
}
- if ((config.search_user || config.search_uid) &&
- (NULL != config.name)) {
- entry = backend_retrieve_user_entry_from_sssd(config.name,
- config.search_uid, set_data, cbdata);
- backend_search_sssd_send_entry(set_data, cbdata, entry);
+ staged->map_group = slapi_ch_strdup(set_data->common.group);
+ staged->map_set = slapi_ch_strdup(set_data->common.set);
+ staged->set_data_fixup = NULL;
+ staged->count = 0;
+ staged->entries = NULL;
+
+ staged->container_sdn = slapi_ch_strdup(slapi_sdn_get_dn(set_data->container_sdn));
+
+ staged->type = cbdata->check_sssd;
+ staged->name = config.name;
+ staged->is_id = config.search_gid || config.search_uid;
+ staged->search_members = config.search_members;
+
+ staged->next = cbdata->staged;
+ cbdata->staged = staged;
+}
+
+ /* perform look up against SSSD and create entry based on that */
+bool_t
+backend_retrieve_from_sssd(struct backend_staged_data *staged,
+ struct backend_search_cbdata *cbdata)
+{
+ Slapi_Entry *entry, **entries;
+ int i;
+
+ if (((staged->type == SCH_SSSD_GROUP) && staged->search_members) &&
+ (NULL != staged->name)) {
+ entries = backend_retrieve_group_list_from_sssd(staged->name, staged->container_sdn,
+ cbdata, &staged->count);
+ if (entries != NULL) {
+ staged->entries = entries;
+ for (i = 0; i < staged->count; i++) {
+ slapi_entry_add_string(entries[i], "schema-compat-origin", "sssd");
+ }
+ return TRUE;
+ }
+ return FALSE;
}
+
+ if ((staged->type == SCH_SSSD_GROUP) && (NULL != staged->name)) {
+ entry = backend_retrieve_group_entry_from_sssd(staged->name, staged->is_id,
+ staged->container_sdn,
+ cbdata);
+ if (entry) {
+ slapi_entry_add_string(entry, "schema-compat-origin", "sssd");
+ staged->count = 1;
+ staged->entries = malloc(sizeof(Slapi_Entry *));
+ staged->entries[0] = entry;
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ if ((staged->type == SCH_SSSD_USER) && (NULL != staged->name)) {
+ entry = backend_retrieve_user_entry_from_sssd(staged->name, staged->is_id,
+ staged->container_sdn,
+ cbdata);
+ if (entry) {
+ slapi_entry_add_string(entry, "schema-compat-origin", "sssd");
+ staged->count = 1;
+ staged->entries = malloc(sizeof(Slapi_Entry *));
+ staged->entries[0] = entry;
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ return FALSE;
}