diff options
Diffstat (limited to 'src/back-sch.c')
-rw-r--r-- | src/back-sch.c | 341 |
1 files changed, 192 insertions, 149 deletions
diff --git a/src/back-sch.c b/src/back-sch.c index a235998..c2b7d41 100644 --- a/src/back-sch.c +++ b/src/back-sch.c @@ -85,18 +85,9 @@ backend_set_config_free_config_contents(void *data) format_free_ref_attr_list(set_data->common.ref_attr_list); format_free_ref_attr_list(set_data->common.inref_attr_list); free(set_data->common.entry_filter); - if (set_data->check_sssd != SCH_SSSD_NONE) { - /* Remove association to another set (groups/users) */ - if ((set_data->sssd_relevant_set != NULL) && - (set_data->sssd_relevant_set->sssd_relevant_set == set_data)) { - set_data->sssd_relevant_set->sssd_relevant_set = NULL; - set_data->sssd_relevant_set = NULL; - } - } slapi_sdn_free(&set_data->container_sdn); free(set_data->rdn_format); backend_shr_free_strlist(set_data->attribute_format); - free(set_data->sssd_buffer); } } void @@ -144,9 +135,6 @@ backend_copy_set_config(const struct backend_set_data *data) ret->check_access = data->check_access; ret->check_sssd = data->check_sssd; ret->sssd_min_id = data->sssd_min_id; - ret->sssd_buffer = data->sssd_buffer; - ret->sssd_buffer_len = data->sssd_buffer_len; - ret->sssd_relevant_set = data->sssd_relevant_set; if ((ret->common.group == NULL) || (ret->common.set == NULL) || @@ -231,7 +219,6 @@ backend_set_config_read_config(struct plugin_state *state, Slapi_Entry *e, } else { ret.check_sssd = SCH_SSSD_NONE; } - ret.sssd_buffer = NULL; /* Make sure we don't return system users/groups * by limiting lower bound on searches */ @@ -251,19 +238,8 @@ backend_set_config_read_config(struct plugin_state *state, Slapi_Entry *e, backend_shr_add_strlist(&ret.attribute_format, "objectClass=extensibleObject"); backend_shr_add_strlist(&ret.attribute_format, "schema-compat-origin=%{schema-compat-origin}"); backend_shr_add_strlist(&ret.attribute_format, "ipaNTSecurityIdentifier=%{ipaNTSecurityIdentifier}"); - - /* Allocate buffer to be used for getpwnam_r/getgrnam_r requests */ - if (ret.check_sssd == SCH_SSSD_USER) { - ret.sssd_buffer_len = sysconf(_SC_GETPW_R_SIZE_MAX); - } else { - ret.sssd_buffer_len = sysconf(_SC_GETGR_R_SIZE_MAX); - } - if ((long) ret.sssd_buffer_len == -1 ) - ret.sssd_buffer_len = 16384; - ret.sssd_buffer = malloc(ret.sssd_buffer_len); } - ret.sssd_relevant_set = NULL; *pret = backend_copy_set_config(&ret); free(ret.common.group); free(ret.common.set); @@ -1082,6 +1058,10 @@ backend_search_set_cb(const char *group, const char *set, bool_t flag, if (slapi_sdn_compare(set_data->container_sdn, cbdata->target_dn) == 0) { cbdata->matched = TRUE; + slapi_log_error(SLAPI_LOG_PLUGIN, + cbdata->state->plugin_desc->spd_id, + "search set actual match: %d, check_sssd=%d\n", + cbdata->matched, cbdata->check_sssd); } /* Walk the set of entries in this set if they're in scope. */ @@ -1090,16 +1070,15 @@ backend_search_set_cb(const char *group, const char *set, bool_t flag, cbdata->scope)) { map_data_foreach_entry_id(cbdata->state, group, set, NULL, backend_search_entry_cb, cbdata); - } - #ifdef HAVE_SSS_NSS_IDMAP - /* If we didn't find an exact match for the entry but asked to look up SSSD, - * then try to search SSSD and if successful, return that entry */ - if ((n_entries_sssd == cbdata->n_entries) && - (cbdata->check_sssd != SCH_SSSD_NONE)) { - backend_search_sssd(set_data, cbdata); - } + /* If we didn't find an exact match for the entry but asked to look up SSSD, + * then try to search SSSD and if successful, return that entry */ + if ((n_entries_sssd == cbdata->n_entries) && + (cbdata->check_sssd != SCH_SSSD_NONE)) { + backend_search_sssd(set_data, cbdata); + } #endif + } /* If we didn't find an exact match for the entry, then store this * container's DN as the closest match. */ @@ -1114,6 +1093,36 @@ backend_search_set_cb(const char *group, const char *set, bool_t flag, } static bool_t +backend_search_find_set_data_in_group_cb(const char *group, const char *set, bool_t flag, + void *backend_data, void *cb_data) +{ + struct backend_search_cbdata *cbdata; + struct backend_set_data *set_data; + + cbdata = cb_data; + set_data = backend_data; + + if ((0 == strcmp(group, cbdata->cur_staged->map_group)) && + (0 == strcmp(set, cbdata->cur_staged->map_set))) { + cbdata->cur_staged->set_data_fixup = set_data; + } + + return TRUE; + +} + +static bool_t +backend_search_find_set_data_cb(const char *group, void *cb_data) +{ + struct backend_search_cbdata *cbdata; + + cbdata = cb_data; + map_data_foreach_map(cbdata->state, group, + backend_search_find_set_data_in_group_cb, cbdata); + return TRUE; +} + +static bool_t backend_search_group_cb(const char *group, void *cb_data) { struct backend_search_cbdata *cbdata; @@ -1216,6 +1225,9 @@ static int backend_search_cb(Slapi_PBlock *pb) { struct backend_search_cbdata cbdata; + struct backend_staged_data *staged, *next; + int i; + if (wrap_get_call_level() > 0) { return 0; } @@ -1240,6 +1252,8 @@ backend_search_cb(Slapi_PBlock *pb) cbdata.closest_match = NULL; cbdata.text = NULL; cbdata.n_entries = 0; + cbdata.staged = NULL; + cbdata.cur_staged = NULL; /* Okay, we can search. */ slapi_log_error(SLAPI_LOG_PLUGIN, cbdata.state->plugin_desc->spd_id, "searching from \"%s\" for \"%s\" with scope %d%s\n", @@ -1261,14 +1275,66 @@ backend_search_cb(Slapi_PBlock *pb) map_data_foreach_domain(cbdata.state, backend_search_group_cb, &cbdata); map_unlock(); wrap_dec_call_level(); +#ifdef HAVE_SSS_NSS_IDMAP + /* Search caused some data to be staged for addition */ + if (cbdata.staged != NULL) { + /* Allocate buffer to be used for getpwnam_r/getgrnam_r requests */ + cbdata.sssd_buffer_len = MAX(sysconf(_SC_GETPW_R_SIZE_MAX), sysconf(_SC_GETGR_R_SIZE_MAX)); + if ((long) cbdata.sssd_buffer_len == -1) + cbdata.sssd_buffer_len = 16384; + cbdata.sssd_buffer = malloc(cbdata.sssd_buffer_len); + staged = cbdata.staged; + while (staged) { + if (staged->entries == NULL) { + backend_retrieve_from_sssd(staged, &cbdata); + } + next = staged->next; + staged = next; + } + staged = cbdata.staged; + wrap_inc_call_level(); + map_wrlock(); + while (staged) { + if (staged->entries) { + cbdata.cur_staged = staged; + map_data_foreach_domain(cbdata.state, backend_search_find_set_data_cb, &cbdata); + if (cbdata.cur_staged->set_data_fixup != NULL) { + for (i = 0; i < staged->count ; i++) { + if ((staged->entries[i] != NULL) && + !map_data_check_entry(cbdata.state, + staged->map_group, staged->map_set, + slapi_sdn_get_ndn(staged->entries[i]))) { + backend_set_entry(cbdata.pb, staged->entries[i], staged->set_data_fixup); + slapi_entry_free(staged->entries[i]); + } + } + } + free(staged->entries); + staged->count = 0; + staged->entries = NULL; + } + free(staged->map_group); + free(staged->map_set); + free(staged->name); + free(staged->container_sdn); + next = staged->next; + free(staged); + staged = next; + } + cbdata.staged = NULL; + map_unlock(); + cbdata.sssd_buffer_len = 0; + free(cbdata.sssd_buffer); + /* Perform search again, this time to send out staged data */ + map_rdlock(); + map_data_foreach_domain(cbdata.state, backend_search_group_cb, &cbdata); + map_unlock(); + wrap_dec_call_level(); + } +#endif /* If we "own" the search target DN, then we need to send a response. */ if (cbdata.answer) { - if (cbdata.matched || (cbdata.n_entries > 0)) { - /* Just in case, free the closest-match that we've - * recorded. */ - free(cbdata.closest_match); - cbdata.closest_match = NULL; - } else { + if (!(cbdata.matched || (cbdata.n_entries > 0))) { /* Return a no-such-object error because the target DN * was not found. */ cbdata.result = LDAP_NO_SUCH_OBJECT; @@ -1294,6 +1360,12 @@ backend_search_cb(Slapi_PBlock *pb) send_ldap_result(cbdata.pb, cbdata.result, cbdata.closest_match, cbdata.text, cbdata.n_entries, NULL); + if (cbdata.matched || (cbdata.n_entries > 0)) { + /* Just in case, free the closest-match that we've + * recorded. */ + free(cbdata.closest_match); + cbdata.closest_match = NULL; + } } slapi_sdn_free(&cbdata.target_dn); free(cbdata.closest_match); @@ -1448,6 +1520,61 @@ backend_betxn_pre_write_cb(Slapi_PBlock *pb) return state->use_be_txns ? backend_write_cb(pb) : 0; } +#ifdef HAVE_SSS_NSS_IDMAP +static int +backend_bind_cb_pam(Slapi_PBlock *pb, const char *username, char *ndn) +{ + int ret = 0; + LDAPControl **reqctrls = NULL; + struct plugin_state *state; + slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state); + + /* PAM API is thread-unsafe, we need to lock exclusively */ + wrap_rwlock_wrlock(state->pam_lock); + ret = backend_sch_do_pam_auth(pb, username); + wrap_rwlock_unlock(state->pam_lock); + + if (ret != 0) { + slapi_send_ldap_result(pb, LDAP_INVALID_CREDENTIALS, + NULL, NULL, 0, NULL); + ret = -1; + free(ndn); + } else { + /* + * If bind succeeded, change authentication information associated + * with this connection. + */ + if (ret == LDAP_SUCCESS) { + if ((slapi_pblock_set(pb, SLAPI_CONN_DN, (void*) ndn) != 0) || + (slapi_pblock_set(pb, SLAPI_CONN_AUTHMETHOD, SLAPD_AUTH_SIMPLE) != 0)) { + ret = LDAP_OPERATIONS_ERROR; + } else { + slapi_pblock_get(pb, SLAPI_REQCONTROLS, &reqctrls); + if (slapi_control_present(reqctrls, LDAP_CONTROL_AUTH_REQUEST, NULL, NULL)) { + slapi_add_auth_response_control(pb, ndn); + } + } + } + + if (ret == LDAP_SUCCESS) { + /* we are handling the result */ + slapi_send_ldap_result(pb, ret, NULL, NULL, 0, NULL); + /* tell bind code we handled the result */ + ret = 0; + } + } + return ret; +} +#else +static int +backend_bind_cb_pam(Slapi_PBlock *pb, const char *username, char *ndn) +{ + slapi_send_ldap_result(pb, LDAP_INVALID_CREDENTIALS, NULL, NULL, 0, NULL); + free(ndn); + return -1; +} +#endif + static int backend_bind_cb(Slapi_PBlock *pb) { @@ -1457,6 +1584,7 @@ backend_bind_cb(Slapi_PBlock *pb) struct berval *urls[] = {&ref, NULL}; const char *ndn; char *is_sssd_origin = NULL; + char *username = NULL; if (wrap_get_call_level() > 0) { return 0; @@ -1466,61 +1594,41 @@ backend_bind_cb(Slapi_PBlock *pb) map_rdlock(); backend_locate(pb, &data); if (data != NULL) { -#ifdef HAVE_SSS_NSS_IDMAP is_sssd_origin = slapi_entry_attr_get_charptr(data->e, "schema-compat-origin"); + ndn = slapi_ch_strdup(slapi_sdn_get_ndn(data->original_entry_dn)); + username = slapi_entry_attr_get_charptr(data->e, "uid"); + map_unlock(); + wrap_dec_call_level(); + + /* If user comes from SSSD, it will get authentication handled by PAM. */ if ((is_sssd_origin != NULL) && (strcasecmp(is_sssd_origin, "sssd") == 0)) { - ret = backend_sch_do_pam_auth(pb, data->e); - if (ret != 0) { - slapi_send_ldap_result(pb, LDAP_INVALID_CREDENTIALS, - NULL, NULL, 0, NULL); - ret = -1; - } else { - /* - * If bind succeeded, change authentication information associated - * with this connection. - */ - if (ret == LDAP_SUCCESS) { - ndn = slapi_ch_strdup(slapi_sdn_get_ndn(data->original_entry_dn)); - if ((slapi_pblock_set(pb, SLAPI_CONN_DN, (void*)ndn) != 0) || - (slapi_pblock_set(pb, SLAPI_CONN_AUTHMETHOD, SLAPD_AUTH_SIMPLE) != 0)) { - ret = LDAP_OPERATIONS_ERROR; - } else { - LDAPControl **reqctrls = NULL; - slapi_pblock_get(pb, SLAPI_REQCONTROLS, &reqctrls); - if (slapi_control_present(reqctrls, LDAP_CONTROL_AUTH_REQUEST, NULL, NULL)) { - slapi_add_auth_response_control(pb, ndn); - } - } - } - - if (ret == LDAP_SUCCESS) { - /* we are handling the result */ - slapi_send_ldap_result(pb, ret, NULL, NULL, 0, NULL); - /* tell bind code we handled the result */ - ret = 0; - } - } + /* backend_bind_cb_pam() takes over ndn */ + ret = backend_bind_cb_pam(pb, username, ndn); } else { -#endif - ndn = slapi_sdn_get_ndn(data->original_entry_dn); - ref.bv_len = strlen("ldap:///") + strlen(ndn); - ref.bv_val = malloc(ref.bv_len + 1); - if (ref.bv_val != NULL) { - sprintf(ref.bv_val, "ldap:///%s", ndn); - slapi_send_ldap_result(pb, LDAP_REFERRAL, - NULL, NULL, 0, urls); - free(ref.bv_val); + if (username != NULL) { + ret = backend_bind_cb_pam(pb, username, ndn); } else { - slapi_send_ldap_result(pb, LDAP_BUSY, - NULL, NULL, 0, NULL); + ref.bv_len = strlen("ldap:///") + strlen(ndn); + ref.bv_val = malloc(ref.bv_len + 1); + if (ref.bv_val != NULL) { + sprintf(ref.bv_val, "ldap:///%s", ndn); + slapi_send_ldap_result(pb, LDAP_REFERRAL, + NULL, NULL, 0, urls); + free(ref.bv_val); + } else { + slapi_send_ldap_result(pb, LDAP_BUSY, + NULL, NULL, 0, NULL); + } + ret = -1; + free(ndn); } -#ifdef HAVE_SSS_NSS_IDMAP } + free(username); free(is_sssd_origin); -#endif - ret = -1; } else { + map_unlock(); + wrap_dec_call_level(); if (backend_check_scope_pb(pb)) { slapi_send_ldap_result(pb, LDAP_INVALID_CREDENTIALS, NULL, NULL, 0, NULL); @@ -1529,8 +1637,6 @@ backend_bind_cb(Slapi_PBlock *pb) ret = 0; } } - map_unlock(); - wrap_dec_call_level(); return ret; } @@ -1577,74 +1683,11 @@ backend_check_empty(struct plugin_state *state, } } -struct backend_start_fixup_cbdata { - Slapi_PBlock *pb; - struct plugin_state *state; - struct backend_set_data *groups; - struct backend_set_data *users; -}; - -static bool_t -backend_start_fixup_sssd_cb(const char *group, const char *set, bool_t flag, - void *backend_data, void *cb_data) -{ - struct backend_start_fixup_cbdata *cbdata; - struct backend_set_data *set_data; - - cbdata = cb_data; - set_data = backend_data; - - switch (set_data->check_sssd) { - case SCH_SSSD_NONE: - break; - case SCH_SSSD_USER: - cbdata->groups = set_data; - break; - case SCH_SSSD_GROUP: - cbdata->users = set_data; - break; - default: - break; - } - - return TRUE; -} - -static bool_t -backend_start_fixup_cb(const char *group, void *cb_data) -{ - struct backend_start_fixup_cbdata *cbdata; - cbdata = cb_data; - map_data_foreach_map(cbdata->state, group, - backend_start_fixup_sssd_cb, cbdata); - if ((cbdata->groups != NULL) && - (cbdata->users != NULL)) { - cbdata->groups->sssd_relevant_set = cbdata->users; - cbdata->users->sssd_relevant_set = cbdata->groups; - } - return TRUE; -} - /* Populate our data cache. */ void backend_startup(Slapi_PBlock *pb, struct plugin_state *state) { - struct backend_start_fixup_cbdata cbdata; backend_shr_startup(state, pb, SCH_CONTAINER_CONFIGURATION_FILTER); - /* Walk the list of groups and perform fixups for the cases where - * some sets depend on others. Right now following fixups are done: - * -- SSSD searches for the group tree should know user tree DN to - * produce proper membership - */ - cbdata.state = state; - cbdata.pb = pb; - cbdata.groups = NULL; - cbdata.users = NULL; - wrap_inc_call_level(); - map_rdlock(); - map_data_foreach_domain(state, backend_start_fixup_cb, &cbdata); - map_unlock(); - wrap_dec_call_level(); } int |