From 78e632ec79d3189cf2495910e0e97079e0194371 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 18 Mar 2010 16:58:02 -0400 Subject: [PATCH 1/2] Store rootdse supported features in sdap_handler --- src/providers/ipa/ipa_access.c | 13 ++--- src/providers/ipa/ipa_auth.c | 2 +- src/providers/ldap/ldap_common.h | 3 - src/providers/ldap/ldap_id.c | 15 ++--- src/providers/ldap/ldap_id_enum.c | 10 +-- src/providers/ldap/sdap.c | 84 ++++++++++++++++++++++------ src/providers/ldap/sdap.h | 23 +++++++- src/providers/ldap/sdap_access.c | 2 +- src/providers/ldap/sdap_async.h | 5 +- src/providers/ldap/sdap_async_connection.c | 45 ++++++--------- 10 files changed, 123 insertions(+), 79 deletions(-) diff --git a/src/providers/ipa/ipa_access.c b/src/providers/ipa/ipa_access.c index 3d66c16..4fbb906 100644 --- a/src/providers/ipa/ipa_access.c +++ b/src/providers/ipa/ipa_access.c @@ -317,8 +317,7 @@ static void hbac_get_services_connect_done(struct tevent_req *subreq) struct hbac_get_service_data_state); int ret; - ret = sdap_cli_connect_recv(subreq, state->sdap_ctx, &state->sdap_ctx->gsh, - NULL); + ret = sdap_cli_connect_recv(subreq, state->sdap_ctx, &state->sdap_ctx->gsh); talloc_zfree(subreq); if (ret) { tevent_req_error(req, ret); @@ -689,7 +688,7 @@ static struct tevent_req *hbac_get_host_info_send(TALLOC_CTX *memctx, if (sdap_ctx->gsh == NULL || ! sdap_ctx->gsh->connected) { subreq = sdap_cli_connect_send(state, ev, sdap_ctx->opts, - sdap_ctx->be, sdap_ctx->service, NULL); + sdap_ctx->be, sdap_ctx->service, false); if (!subreq) { DEBUG(1, ("sdap_cli_connect_send failed.\n")); ret = ENOMEM; @@ -734,8 +733,7 @@ static void hbac_get_host_info_connect_done(struct tevent_req *subreq) struct hbac_get_host_info_state); int ret; - ret = sdap_cli_connect_recv(subreq, state->sdap_ctx, &state->sdap_ctx->gsh, - NULL); + ret = sdap_cli_connect_recv(subreq, state->sdap_ctx, &state->sdap_ctx->gsh); talloc_zfree(subreq); if (ret) { tevent_req_error(req, ret); @@ -1109,7 +1107,7 @@ static struct tevent_req *hbac_get_rules_send(TALLOC_CTX *memctx, if (sdap_ctx->gsh == NULL || ! sdap_ctx->gsh->connected) { subreq = sdap_cli_connect_send(state, ev, sdap_ctx->opts, - sdap_ctx->be, sdap_ctx->service, NULL); + sdap_ctx->be, sdap_ctx->service, false); if (!subreq) { DEBUG(1, ("sdap_cli_connect_send failed.\n")); ret = ENOMEM; @@ -1154,8 +1152,7 @@ static void hbac_get_rules_connect_done(struct tevent_req *subreq) struct hbac_get_rules_state); int ret; - ret = sdap_cli_connect_recv(subreq, state->sdap_ctx, &state->sdap_ctx->gsh, - NULL); + ret = sdap_cli_connect_recv(subreq, state->sdap_ctx, &state->sdap_ctx->gsh); talloc_zfree(subreq); if (ret) { tevent_req_error(req, ret); diff --git a/src/providers/ipa/ipa_auth.c b/src/providers/ipa/ipa_auth.c index 2bd92ba..e8d4ada 100644 --- a/src/providers/ipa/ipa_auth.c +++ b/src/providers/ipa/ipa_auth.c @@ -118,7 +118,7 @@ static void get_password_migration_flag_auth_done(struct tevent_req *subreq) char *search_base; const char **attrs; - ret = sdap_cli_connect_recv(subreq, state, &state->sh, NULL); + ret = sdap_cli_connect_recv(subreq, state, &state->sh); talloc_zfree(subreq); if (ret) { DEBUG(1, ("sdap_auth request failed.\n")); diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h index 1ee7378..a36bdcc 100644 --- a/src/providers/ldap/ldap_common.h +++ b/src/providers/ldap/ldap_common.h @@ -41,9 +41,6 @@ struct sdap_id_ctx { struct fo_service *fo_service; struct sdap_service *service; - /* what rootDSE returns */ - struct sysdb_attrs *rootDSE; - /* global sdap handler */ struct sdap_handle *gsh; diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c index 84483da..8481284 100644 --- a/src/providers/ldap/ldap_id.c +++ b/src/providers/ldap/ldap_id.c @@ -103,7 +103,7 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, * or SASL/GSSAPI, etc ... */ subreq = sdap_cli_connect_send(state, ev, ctx->opts, ctx->be, ctx->service, - &ctx->rootDSE); + false); if (!subreq) { ret = ENOMEM; goto fail; @@ -140,8 +140,7 @@ static void users_get_connect_done(struct tevent_req *subreq) struct users_get_state); int ret; - ret = sdap_cli_connect_recv(subreq, state->ctx, - &state->ctx->gsh, &state->ctx->rootDSE); + ret = sdap_cli_connect_recv(subreq, state->ctx, &state->ctx->gsh); talloc_zfree(subreq); if (ret) { if (ret == ENOTSUP) { @@ -301,7 +300,7 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx, * or SASL/GSSAPI, etc ... */ subreq = sdap_cli_connect_send(state, ev, ctx->opts, ctx->be, ctx->service, - &ctx->rootDSE); + false); if (!subreq) { ret = ENOMEM; goto fail; @@ -338,8 +337,7 @@ static void groups_get_connect_done(struct tevent_req *subreq) struct groups_get_state); int ret; - ret = sdap_cli_connect_recv(subreq, state->ctx, - &state->ctx->gsh, &state->ctx->rootDSE); + ret = sdap_cli_connect_recv(subreq, state->ctx, &state->ctx->gsh); talloc_zfree(subreq); if (ret) { if (ret == ENOTSUP) { @@ -465,7 +463,7 @@ static struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx, * or SASL/GSSAPI, etc ... */ subreq = sdap_cli_connect_send(state, ev, ctx->opts, ctx->be, ctx->service, - &ctx->rootDSE); + false); if (!subreq) { ret = ENOMEM; goto fail; @@ -503,8 +501,7 @@ static void groups_by_user_connect_done(struct tevent_req *subreq) struct groups_by_user_state); int ret; - ret = sdap_cli_connect_recv(subreq, state->ctx, - &state->ctx->gsh, &state->ctx->rootDSE); + ret = sdap_cli_connect_recv(subreq, state->ctx, &state->ctx->gsh); talloc_zfree(subreq); if (ret) { if (ret == ENOTSUP) { diff --git a/src/providers/ldap/ldap_id_enum.c b/src/providers/ldap/ldap_id_enum.c index 95b35e0..c147896 100644 --- a/src/providers/ldap/ldap_id_enum.c +++ b/src/providers/ldap/ldap_id_enum.c @@ -470,7 +470,7 @@ static struct tevent_req *enum_users_send(TALLOC_CTX *memctx, * or SASL/GSSAPI, etc ... */ subreq = sdap_cli_connect_send(state, ev, ctx->opts, ctx->be, ctx->service, - &ctx->rootDSE); + false); if (!subreq) { ret = ENOMEM; goto fail; @@ -509,8 +509,7 @@ static void enum_users_connect_done(struct tevent_req *subreq) struct enum_users_state); int ret; - ret = sdap_cli_connect_recv(subreq, state->ctx, - &state->ctx->gsh, &state->ctx->rootDSE); + ret = sdap_cli_connect_recv(subreq, state->ctx, &state->ctx->gsh); talloc_zfree(subreq); if (ret) { if (ret == ENOTSUP) { @@ -623,7 +622,7 @@ static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx, * or SASL/GSSAPI, etc ... */ subreq = sdap_cli_connect_send(state, ev, ctx->opts, ctx->be, ctx->service, - &ctx->rootDSE); + false); if (!subreq) { ret = ENOMEM; goto fail; @@ -661,8 +660,7 @@ static void enum_groups_connect_done(struct tevent_req *subreq) struct enum_groups_state); int ret; - ret = sdap_cli_connect_recv(subreq, state->ctx, - &state->ctx->gsh, &state->ctx->rootDSE); + ret = sdap_cli_connect_recv(subreq, state->ctx, &state->ctx->gsh); talloc_zfree(subreq); if (ret) { if (ret == ENOTSUP) { diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c index 39c67cc..e0f5038 100644 --- a/src/providers/ldap/sdap.c +++ b/src/providers/ldap/sdap.c @@ -325,37 +325,85 @@ errno_t setup_tls_config(struct dp_option *basic_opts) } -bool sdap_rootdse_sasl_mech_is_supported(struct sysdb_attrs *rootdse, - const char *sasl_mech) +bool sdap_check_sup_list(struct sup_list *l, const char *val) { - struct ldb_message_element *el = NULL; - struct ldb_val *val; int i; - if (!sasl_mech) return false; + if (!val) { + return false; + } - for (i = 0; i < rootdse->num; i++) { - if (strcasecmp(rootdse->a[i].name, "supportedSASLMechanisms")) { + for (i = 0; i < l->num_vals; i++) { + if (strcasecmp(val, (char *)l->vals[i])) { continue; } - el = &rootdse->a[i]; - break; + return true; } - if (!el) { - /* no supported SASL Mechanism at all ? */ - return false; + return false; +} + +static int sdap_init_sup_list(TALLOC_CTX *memctx, + struct sup_list *list, + int num, struct ldb_val *vals) +{ + int i; + + list->vals = talloc_array(memctx, char *, num); + if (!list->vals) { + return ENOMEM; } - for (i = 0; i < el->num_values; i++) { - val = &el->values[i]; - if (strncasecmp(sasl_mech, (const char *)val->data, val->length)) { - continue; + for (i = 0; i < num; i++) { + list->vals[i] = talloc_strndup(list->vals, + (char *)vals[i].data, vals[i].length); + if (!list->vals[i]) { + return ENOMEM; } - return true; } - return false; + list->num_vals = num; + + return EOK; +} + +int sdap_set_rootdse_supported_lists(struct sysdb_attrs *rootdse, + struct sdap_handle *sh) +{ + struct ldb_message_element *el = NULL; + int ret; + int i; + + for (i = 0; i < rootdse->num; i++) { + el = &rootdse->a[i]; + if (strcasecmp(el->name, "supportedControl") == 0) { + + ret = sdap_init_sup_list(sh, &sh->supported_controls, + el->num_values, el->values); + if (ret) { + return ret; + } + } + if (strcasecmp(el->name, "supportedExtension") == 0) { + + ret = sdap_init_sup_list(sh, &sh->supported_extensions, + el->num_values, el->values); + if (ret) { + return ret; + } + } + if (strcasecmp(el->name, "supportedSASLMechanisms") == 0) { + + ret = sdap_init_sup_list(sh, &sh->supported_saslmechs, + el->num_values, el->values); + if (ret) { + return ret; + } + } + } + + return EOK; + } int build_attrs_from_map(TALLOC_CTX *memctx, diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h index ef22cda..54231fd 100644 --- a/src/providers/ldap/sdap.h +++ b/src/providers/ldap/sdap.h @@ -77,12 +77,21 @@ struct ldap_cb_data { struct fd_event_item *fd_list; }; +struct sup_list { + int num_vals; + char **vals; +}; + struct sdap_handle { LDAP *ldap; bool connected; struct sdap_fd_events *sdap_fd_events; + struct sup_list supported_saslmechs; + struct sup_list supported_controls; + struct sup_list supported_extensions; + struct sdap_op *ops; /* during release we need to lock access to the handler @@ -270,8 +279,18 @@ int sdap_get_msg_dn(TALLOC_CTX *memctx, struct sdap_handle *sh, errno_t setup_tls_config(struct dp_option *basic_opts); -bool sdap_rootdse_sasl_mech_is_supported(struct sysdb_attrs *rootdse, - const char *sasl_mech); +int sdap_set_rootdse_supported_lists(struct sysdb_attrs *rootdse, + struct sdap_handle *sh); +bool sdap_check_sup_list(struct sup_list *l, const char *val); + +#define sdap_is_sasl_mech_supported(sh, sasl_mech) \ + sdap_check_sup_list(&((sh)->supported_saslmechs), sasl_mech) + +#define sdap_is_control_supported(sh, ctrl_oid) \ + sdap_check_sup_list(&((sh)->supported_controls), ctrl_oid) + +#define sdap_is_extension_supported(sh, ext_oid) \ + sdap_check_sup_list(&((sh)->supported_extensions), ext_oid) int build_attrs_from_map(TALLOC_CTX *memctx, struct sdap_attr_map *map, diff --git a/src/providers/ldap/sdap_access.c b/src/providers/ldap/sdap_access.c index 8a156bc..b33b548 100644 --- a/src/providers/ldap/sdap_access.c +++ b/src/providers/ldap/sdap_access.c @@ -278,7 +278,7 @@ static void sdap_access_connect_done(struct tevent_req *subreq) tevent_req_data(req, struct sdap_access_req_ctx); ret = sdap_cli_connect_recv(subreq, state->sdap_ctx, - &state->sdap_ctx->gsh, NULL); + &state->sdap_ctx->gsh); talloc_zfree(subreq); if (ret != EOK) { /* Could not connect to LDAP. Mark as offline and return diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h index 1e52c48..7f76418 100644 --- a/src/providers/ldap/sdap_async.h +++ b/src/providers/ldap/sdap_async.h @@ -108,11 +108,10 @@ struct tevent_req *sdap_cli_connect_send(TALLOC_CTX *memctx, struct sdap_options *opts, struct be_ctx *be, struct sdap_service *service, - struct sysdb_attrs **rootdse); + bool skip_rootdse); int sdap_cli_connect_recv(struct tevent_req *req, TALLOC_CTX *memctx, - struct sdap_handle **gsh, - struct sysdb_attrs **rootdse); + struct sdap_handle **gsh); struct tevent_req *sdap_get_generic_send(TALLOC_CTX *memctx, struct tevent_context *ev, diff --git a/src/providers/ldap/sdap_async_connection.c b/src/providers/ldap/sdap_async_connection.c index fd1cc8c..38250d7 100644 --- a/src/providers/ldap/sdap_async_connection.c +++ b/src/providers/ldap/sdap_async_connection.c @@ -853,7 +853,6 @@ struct sdap_cli_connect_state { struct be_ctx *be; bool use_rootdse; - struct sysdb_attrs *rootdse; struct sdap_handle *sh; @@ -875,7 +874,7 @@ struct tevent_req *sdap_cli_connect_send(TALLOC_CTX *memctx, struct sdap_options *opts, struct be_ctx *be, struct sdap_service *service, - struct sysdb_attrs **rootdse) + bool skip_rootdse) { struct sdap_cli_connect_state *state; struct tevent_req *req; @@ -891,12 +890,10 @@ struct tevent_req *sdap_cli_connect_send(TALLOC_CTX *memctx, state->srv = NULL; state->be = be; - if (rootdse) { - state->use_rootdse = true; - state->rootdse = *rootdse; - } else { + if (skip_rootdse) { state->use_rootdse = false; - state->rootdse = NULL; + } else { + state->use_rootdse = true; } ret = sdap_cli_resolve_next(req); @@ -978,7 +975,7 @@ static void sdap_cli_connect_done(struct tevent_req *subreq) return; } - if (state->use_rootdse && !state->rootdse) { + if (state->use_rootdse) { /* fetch the rootDSE this time */ sdap_cli_rootdse_step(req); return; @@ -988,8 +985,7 @@ static void sdap_cli_connect_done(struct tevent_req *subreq) if (sasl_mech && state->use_rootdse) { /* check if server claims to support GSSAPI */ - if (!sdap_rootdse_sasl_mech_is_supported(state->rootdse, - sasl_mech)) { + if (!sdap_is_sasl_mech_supported(state->sh, sasl_mech)) { tevent_req_error(req, ENOTSUP); return; } @@ -1037,10 +1033,11 @@ static void sdap_cli_rootdse_done(struct tevent_req *subreq) struct tevent_req); struct sdap_cli_connect_state *state = tevent_req_data(req, struct sdap_cli_connect_state); + struct sysdb_attrs *rootdse; const char *sasl_mech; int ret; - ret = sdap_get_rootdse_recv(subreq, state, &state->rootdse); + ret = sdap_get_rootdse_recv(subreq, state, &rootdse); talloc_zfree(subreq); if (ret) { if (ret == ETIMEDOUT) { /* retry another server */ @@ -1068,12 +1065,18 @@ static void sdap_cli_rootdse_done(struct tevent_req *subreq) } } + /* save rootdse data about supported features */ + ret = sdap_set_rootdse_supported_lists(rootdse, state->sh); + if (ret) { + tevent_req_error(req, ret); + return; + } + sasl_mech = dp_opt_get_string(state->opts->basic, SDAP_SASL_MECH); if (sasl_mech && state->use_rootdse) { /* check if server claims to support GSSAPI */ - if (!sdap_rootdse_sasl_mech_is_supported(state->rootdse, - sasl_mech)) { + if (!sdap_is_sasl_mech_supported(state->sh, sasl_mech)) { tevent_req_error(req, ENOTSUP); return; } @@ -1202,8 +1205,7 @@ static void sdap_cli_auth_done(struct tevent_req *subreq) int sdap_cli_connect_recv(struct tevent_req *req, TALLOC_CTX *memctx, - struct sdap_handle **gsh, - struct sysdb_attrs **rootdse) + struct sdap_handle **gsh) { struct sdap_cli_connect_state *state = tevent_req_data(req, struct sdap_cli_connect_state); @@ -1236,19 +1238,6 @@ int sdap_cli_connect_recv(struct tevent_req *req, talloc_zfree(state->sh); } - if (rootdse) { - if (state->use_rootdse) { - *rootdse = talloc_steal(memctx, state->rootdse); - if (!*rootdse) { - return ENOMEM; - } - } else { - *rootdse = NULL; - } - } else { - talloc_zfree(rootdse); - } - return EOK; } -- 1.7.1.1