From 1bed72e4faa2734b0eef6a107b2dc24bf052e576 Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Mon, 30 Oct 2017 20:50:41 +0100 Subject: [PATCH 73/83] DP: Create a new handler function getAccountDomain() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a new method getAccountDomain() which is a bit similar to getAccountInfo, except it doesn't fetch, parse and store the entry, but just returns the domain or a subdomain the entry was found in. At the moment, the method only supports requests by ID. A default handler is provided (and in this patch used by all the domains) which returns ERR_GET_ACCT_DOM_NOT_SUPPORTED. This return code should be evaluated by the responder so that this DP method is not called again, because it's not supported by the back end type. Reviewed-by: Pavel Březina Reviewed-by: Sumit Bose (cherry picked from commit c0f9f5a0f6d71a1596ee3cef549b4b02295313c3) --- src/providers/ad/ad_init.c | 4 + src/providers/data_provider/dp.h | 20 ++++ src/providers/data_provider/dp_custom_data.h | 6 ++ src/providers/data_provider/dp_iface.c | 3 +- src/providers/data_provider/dp_iface.h | 17 ++++ src/providers/data_provider/dp_iface.xml | 7 ++ src/providers/data_provider/dp_iface_generated.c | 31 +++++++ src/providers/data_provider/dp_iface_generated.h | 5 + src/providers/data_provider/dp_target_id.c | 113 +++++++++++++++++++++++ src/providers/files/files_init.c | 6 ++ src/providers/ipa/ipa_init.c | 4 + src/providers/ldap/ldap_init.c | 4 + src/providers/proxy/proxy_init.c | 4 + src/util/util_errors.c | 1 + src/util/util_errors.h | 1 + 15 files changed, 225 insertions(+), 1 deletion(-) diff --git a/src/providers/ad/ad_init.c b/src/providers/ad/ad_init.c index e62025d4acd24844a5c7082d00c597516f35de16..7efb6aa71cbd2551422c87e0b0c5c1fe91390375 100644 --- a/src/providers/ad/ad_init.c +++ b/src/providers/ad/ad_init.c @@ -510,6 +510,10 @@ errno_t sssm_ad_id_init(TALLOC_CTX *mem_ctx, sdap_online_check_handler_send, sdap_online_check_handler_recv, id_ctx->sdap_id_ctx, struct sdap_id_ctx, void, struct dp_reply_std); + dp_set_method(dp_methods, DPM_ACCT_DOMAIN_HANDLER, + default_account_domain_send, default_account_domain_recv, NULL, + void, struct dp_get_acct_domain_data, struct dp_reply_std); + return EOK; } diff --git a/src/providers/data_provider/dp.h b/src/providers/data_provider/dp.h index aa5b781158c54545b26034602bb25db46b189e87..ceb49da53b88142924e1792c6f64a22ec369677b 100644 --- a/src/providers/data_provider/dp.h +++ b/src/providers/data_provider/dp.h @@ -82,6 +82,7 @@ enum dp_methods { DPM_HOSTID_HANDLER, DPM_DOMAINS_HANDLER, DPM_SESSION_HANDLER, + DPM_ACCT_DOMAIN_HANDLER, DPM_REFRESH_ACCESS_RULES, @@ -179,4 +180,23 @@ void dp_sbus_reset_users_memcache(struct data_provider *provider); void dp_sbus_reset_groups_memcache(struct data_provider *provider); void dp_sbus_reset_initgr_memcache(struct data_provider *provider); +/* + * A dummy handler for DPM_ACCT_DOMAIN_HANDLER. + * + * Its purpose is to always return ERR_GET_ACCT_DOM_NOT_SUPPORTED + * which the responder should evaluate as "this back end does not + * support locating entries' domain" and never call + * DPM_ACCT_DOMAIN_HANDLER again + * + * This request cannot fail, except for critical errors like OOM. + */ +struct tevent_req * +default_account_domain_send(TALLOC_CTX *mem_ctx, + void *unused_ctx, + struct dp_get_acct_domain_data *data, + struct dp_req_params *params); +errno_t default_account_domain_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + struct dp_reply_std *data); + #endif /* _DP_H_ */ diff --git a/src/providers/data_provider/dp_custom_data.h b/src/providers/data_provider/dp_custom_data.h index d9de288b62f4f6763ceb205dc596876cfc58bf6c..7c64bde4513961e79200e852c7277f77e064d5a3 100644 --- a/src/providers/data_provider/dp_custom_data.h +++ b/src/providers/data_provider/dp_custom_data.h @@ -43,6 +43,12 @@ struct dp_subdomains_data { const char *domain_hint; }; +struct dp_get_acct_domain_data { + uint32_t entry_type; + uint32_t filter_type; + const char *filter_value; +}; + struct dp_id_data { uint32_t entry_type; uint32_t filter_type; diff --git a/src/providers/data_provider/dp_iface.c b/src/providers/data_provider/dp_iface.c index 28d70e686f63a3572ac595f493aa1d59436c563f..124be0048f38a93d06561ff7b0d1916838587103 100644 --- a/src/providers/data_provider/dp_iface.c +++ b/src/providers/data_provider/dp_iface.c @@ -33,7 +33,8 @@ struct iface_dp iface_dp = { .autofsHandler = dp_autofs_handler, .hostHandler = dp_host_handler, .getDomains = dp_subdomains_handler, - .getAccountInfo = dp_get_account_info_handler + .getAccountInfo = dp_get_account_info_handler, + .getAccountDomain = dp_get_account_domain_handler, }; struct iface_dp_backend iface_dp_backend = { diff --git a/src/providers/data_provider/dp_iface.h b/src/providers/data_provider/dp_iface.h index 759b9e6c9eb7f53836ae0b641b34e6c31e65779f..0a2f81eb5c108aa7596c974157b0dfafb041869f 100644 --- a/src/providers/data_provider/dp_iface.h +++ b/src/providers/data_provider/dp_iface.h @@ -58,6 +58,23 @@ errno_t dp_subdomains_handler(struct sbus_request *sbus_req, void *dp_cli, const char *domain_hint); +/* + * Return a domain the account belongs to. + * + * The request uses the dp_reply_std structure for reply, with the following + * semantics: + * - DP_ERR_OK - it is expected that the string message contains the domain name + * the entry was found in. A 'negative' reply where the + * request returns DP_ERR_OK, but no domain should be treated + * as authoritative, as if the entry does not exist. + * - DP_ERR_* - the string message contains error string that corresponds + * to the errno field in dp_reply_std(). + */ +errno_t dp_get_account_domain_handler(struct sbus_request *sbus_req, + void *dp_cli, + uint32_t entry_type, + const char *filter); + /* org.freedesktop.sssd.DataProvider.Backend */ errno_t dp_backend_is_online(struct sbus_request *sbus_req, void *dp_cli, diff --git a/src/providers/data_provider/dp_iface.xml b/src/providers/data_provider/dp_iface.xml index 2bfa9dfa7e9d02d2d12c3358967f6969438a97a2..c2431850bca4baa529fb18e0480e781308b12dd6 100644 --- a/src/providers/data_provider/dp_iface.xml +++ b/src/providers/data_provider/dp_iface.xml @@ -79,5 +79,12 @@ + + + + + + + diff --git a/src/providers/data_provider/dp_iface_generated.c b/src/providers/data_provider/dp_iface_generated.c index 11ee2e24a69cc8d4d19fdbeed613e76081aef15d..4d093444536b15d8a17f7e507b93948e1df6ffee 100644 --- a/src/providers/data_provider/dp_iface_generated.c +++ b/src/providers/data_provider/dp_iface_generated.c @@ -313,6 +313,30 @@ int iface_dp_getAccountInfo_finish(struct sbus_request *req, uint16_t arg_dp_err DBUS_TYPE_INVALID); } +/* arguments for org.freedesktop.sssd.dataprovider.getAccountDomain */ +const struct sbus_arg_meta iface_dp_getAccountDomain__in[] = { + { "entry_type", "u" }, + { "filter", "s" }, + { NULL, } +}; + +/* arguments for org.freedesktop.sssd.dataprovider.getAccountDomain */ +const struct sbus_arg_meta iface_dp_getAccountDomain__out[] = { + { "dp_error", "q" }, + { "error", "u" }, + { "domain_name", "s" }, + { NULL, } +}; + +int iface_dp_getAccountDomain_finish(struct sbus_request *req, uint16_t arg_dp_error, uint32_t arg_error, const char *arg_domain_name) +{ + return sbus_request_return_and_finish(req, + DBUS_TYPE_UINT16, &arg_dp_error, + DBUS_TYPE_UINT32, &arg_error, + DBUS_TYPE_STRING, &arg_domain_name, + DBUS_TYPE_INVALID); +} + /* methods for org.freedesktop.sssd.dataprovider */ const struct sbus_method_meta iface_dp__methods[] = { { @@ -357,6 +381,13 @@ const struct sbus_method_meta iface_dp__methods[] = { offsetof(struct iface_dp, getAccountInfo), invoke_uusss_method, }, + { + "getAccountDomain", /* name */ + iface_dp_getAccountDomain__in, + iface_dp_getAccountDomain__out, + offsetof(struct iface_dp, getAccountDomain), + invoke_us_method, + }, { NULL, } }; diff --git a/src/providers/data_provider/dp_iface_generated.h b/src/providers/data_provider/dp_iface_generated.h index 541a90b0b5a5bc0a346cbd04974d33c8bb0983c5..b629ec77487328a41615f3ca7e812088730f40c4 100644 --- a/src/providers/data_provider/dp_iface_generated.h +++ b/src/providers/data_provider/dp_iface_generated.h @@ -38,6 +38,7 @@ #define IFACE_DP_HOSTHANDLER "hostHandler" #define IFACE_DP_GETDOMAINS "getDomains" #define IFACE_DP_GETACCOUNTINFO "getAccountInfo" +#define IFACE_DP_GETACCOUNTDOMAIN "getAccountDomain" /* ------------------------------------------------------------------------ * DBus handlers @@ -110,6 +111,7 @@ struct iface_dp { int (*hostHandler)(struct sbus_request *req, void *data, uint32_t arg_dp_flags, const char *arg_name, const char *arg_alias); int (*getDomains)(struct sbus_request *req, void *data, const char *arg_domain_hint); int (*getAccountInfo)(struct sbus_request *req, void *data, uint32_t arg_dp_flags, uint32_t arg_entry_type, const char *arg_filter, const char *arg_domain, const char *arg_extra); + int (*getAccountDomain)(struct sbus_request *req, void *data, uint32_t arg_entry_type, const char *arg_filter); }; /* finish function for autofsHandler */ @@ -124,6 +126,9 @@ int iface_dp_getDomains_finish(struct sbus_request *req, uint16_t arg_dp_error, /* finish function for getAccountInfo */ int iface_dp_getAccountInfo_finish(struct sbus_request *req, uint16_t arg_dp_error, uint32_t arg_error, const char *arg_error_message); +/* finish function for getAccountDomain */ +int iface_dp_getAccountDomain_finish(struct sbus_request *req, uint16_t arg_dp_error, uint32_t arg_error, const char *arg_domain_name); + /* ------------------------------------------------------------------------ * DBus Interface Metadata * diff --git a/src/providers/data_provider/dp_target_id.c b/src/providers/data_provider/dp_target_id.c index 820a6574cb3a224cce4b7d8286af306f234454a3..11a36e9ce9b1aefcabb04dfe51395b6f4e4bc899 100644 --- a/src/providers/data_provider/dp_target_id.c +++ b/src/providers/data_provider/dp_target_id.c @@ -490,3 +490,116 @@ done: return ret; } + +static bool +check_and_parse_acct_domain_filter(struct dp_get_acct_domain_data *data, + const char *filter) +{ + /* We will use sizeof() to determine the length of a string so we don't + * call strlen over and over again with each request. Not a bottleneck, + * but unnecessary and simple to avoid. */ + static struct { + const char *name; + size_t lenght; + uint32_t type; + } types[] = {FILTER_TYPE("idnumber", BE_FILTER_IDNUM), + {0, 0, 0}}; + int i; + + if (SBUS_IS_STRING_EMPTY(filter)) { + return false; + } + + for (i = 0; types[i].name != NULL; i++) { + if (strncmp(filter, types[i].name, types[i].lenght) == 0) { + data->filter_type = types[i].type; + data->filter_value = SBUS_SET_STRING(&filter[types[i].lenght]); + return true; + } + } + + if (strcmp(filter, ENUM_INDICATOR) == 0) { + data->filter_type = BE_FILTER_ENUM; + data->filter_value = NULL; + return true; + } + + return false; +} + +errno_t dp_get_account_domain_handler(struct sbus_request *sbus_req, + void *dp_cli, + uint32_t entry_type, + const char *filter) +{ + struct dp_get_acct_domain_data *data; + const char *key = NULL; + errno_t ret; + + data = talloc_zero(sbus_req, struct dp_get_acct_domain_data); + if (data == NULL) { + return ENOMEM; + } + data->entry_type = entry_type; + + if (!check_and_parse_acct_domain_filter(data, filter)) { + ret = EINVAL; + goto done; + } + + dp_req_with_reply(dp_cli, NULL, "AccountDomain", key, sbus_req, + DPT_ID, DPM_ACCT_DOMAIN_HANDLER, 0, data, + dp_req_reply_std, struct dp_reply_std); + + ret = EOK; + +done: + if (ret != EOK) { + talloc_free(data); + } + + return ret; +} + +struct default_account_domain_state { + struct dp_reply_std reply; +}; + +struct tevent_req * +default_account_domain_send(TALLOC_CTX *mem_ctx, + void *unused_ctx, + struct dp_get_acct_domain_data *data, + struct dp_req_params *params) +{ + struct default_account_domain_state *state; + struct tevent_req *req; + + req = tevent_req_create(mem_ctx, &state, + struct default_account_domain_state); + if (req == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n"); + return NULL; + } + + dp_reply_std_set(&state->reply, + DP_ERR_DECIDE, ERR_GET_ACCT_DOM_NOT_SUPPORTED, + NULL); + tevent_req_done(req); + tevent_req_post(req, params->ev); + return req; +} + +errno_t default_account_domain_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + struct dp_reply_std *data) +{ + struct default_account_domain_state *state = NULL; + + state = tevent_req_data(req, struct default_account_domain_state); + + TEVENT_REQ_RETURN_ON_ERROR(req); + + *data = state->reply; + + return EOK; +} diff --git a/src/providers/files/files_init.c b/src/providers/files/files_init.c index b91dfbac9bf9d4b678ebdfa6b1cb0971b4477dd9..8e5cd4cf913b79653616120d6ed6540e62ade932 100644 --- a/src/providers/files/files_init.c +++ b/src/providers/files/files_init.c @@ -88,5 +88,11 @@ int sssm_files_id_init(TALLOC_CTX *mem_ctx, ctx, struct files_id_ctx, struct dp_id_data, struct dp_reply_std); + dp_set_method(dp_methods, DPM_ACCT_DOMAIN_HANDLER, + default_account_domain_send, + default_account_domain_recv, + NULL, void, + struct dp_get_acct_domain_data, struct dp_reply_std); + return EOK; } diff --git a/src/providers/ipa/ipa_init.c b/src/providers/ipa/ipa_init.c index f335d51fd65959d256c54a5d92c594a24e895b7c..754e5315c3a7f84ac2901986ecdda73e4dad26bc 100644 --- a/src/providers/ipa/ipa_init.c +++ b/src/providers/ipa/ipa_init.c @@ -754,6 +754,10 @@ errno_t sssm_ipa_id_init(TALLOC_CTX *mem_ctx, sdap_online_check_handler_send, sdap_online_check_handler_recv, id_ctx->sdap_id_ctx, struct sdap_id_ctx, void, struct dp_reply_std); + dp_set_method(dp_methods, DPM_ACCT_DOMAIN_HANDLER, + default_account_domain_send, default_account_domain_recv, NULL, + void, struct dp_get_acct_domain_data, struct dp_reply_std); + return EOK; } diff --git a/src/providers/ldap/ldap_init.c b/src/providers/ldap/ldap_init.c index 43d905893081c31ed659fd1ef8343f965bdc5af0..c0ede8941ee8480c2ec4765f89d12e903edcf012 100644 --- a/src/providers/ldap/ldap_init.c +++ b/src/providers/ldap/ldap_init.c @@ -531,6 +531,10 @@ errno_t sssm_ldap_id_init(TALLOC_CTX *mem_ctx, sdap_online_check_handler_send, sdap_online_check_handler_recv, id_ctx, struct sdap_id_ctx, void, struct dp_reply_std); + dp_set_method(dp_methods, DPM_ACCT_DOMAIN_HANDLER, + default_account_domain_send, default_account_domain_recv, NULL, + void, struct dp_get_acct_domain_data, struct dp_reply_std); + return EOK; } diff --git a/src/providers/proxy/proxy_init.c b/src/providers/proxy/proxy_init.c index 7c9d3dafbdf1f9448cc8f8b473aea15cf4206afc..7d997cb16ee62f10f4b86c9c3ab373a48676fe75 100644 --- a/src/providers/proxy/proxy_init.c +++ b/src/providers/proxy/proxy_init.c @@ -351,6 +351,10 @@ errno_t sssm_proxy_id_init(TALLOC_CTX *mem_ctx, proxy_account_info_handler_send, proxy_account_info_handler_recv, ctx, struct proxy_id_ctx, struct dp_id_data, struct dp_reply_std); + dp_set_method(dp_methods, DPM_ACCT_DOMAIN_HANDLER, + default_account_domain_send, default_account_domain_recv, NULL, + void, struct dp_get_acct_domain_data, struct dp_reply_std); + ret = EOK; done: diff --git a/src/util/util_errors.c b/src/util/util_errors.c index 5a92a2dcf6e65f93bc9732cebf562756357123b6..9a9ba3f3063cab4afb538c3a58527a2d2ed3fffd 100644 --- a/src/util/util_errors.c +++ b/src/util/util_errors.c @@ -115,6 +115,7 @@ struct err_string error_to_str[] = { { "Unable to initialize SSL" }, /* ERR_SSL_FAILURE */ { "Unable to verify peer" }, /* ERR_UNABLE_TO_VERIFY_PEER */ { "Unable to resolve host" }, /* ERR_UNABLE_TO_RESOLVE_HOST */ + { "GetAccountDomain() not supported" }, /* ERR_GET_ACCT_DOM_NOT_SUPPORTED */ { "ERR_LAST" } /* ERR_LAST */ }; diff --git a/src/util/util_errors.h b/src/util/util_errors.h index 509ccb805fb97e59f9da0ea2f991ece2f2030ca4..5ee9862c3f2f60c078693b1b85a40f15436e818c 100644 --- a/src/util/util_errors.h +++ b/src/util/util_errors.h @@ -137,6 +137,7 @@ enum sssd_errors { ERR_SSL_FAILURE, ERR_UNABLE_TO_VERIFY_PEER, ERR_UNABLE_TO_RESOLVE_HOST, + ERR_GET_ACCT_DOM_NOT_SUPPORTED, ERR_LAST /* ALWAYS LAST */ }; -- 2.14.3