From 1bed72e4faa2734b0eef6a107b2dc24bf052e576 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek@redhat.com>
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 <pbrezina@redhat.com>
Reviewed-by: Sumit Bose <sbose@redhat.com>
(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 @@
<arg name="error" type="u" direction="out" />
<arg name="error_message" type="s" direction="out" />
</method>
+ <method name="getAccountDomain">
+ <arg name="entry_type" type="u" direction="in" />
+ <arg name="filter" type="s" direction="in" />
+ <arg name="dp_error" type="q" direction="out" />
+ <arg name="error" type="u" direction="out" />
+ <arg name="domain_name" type="s" direction="out" />
+ </method>
</interface>
</node>
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