summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/responder/ifp/ifp_iface.c1
-rw-r--r--src/responder/ifp/ifp_iface.xml5
-rw-r--r--src/responder/ifp/ifp_iface_generated.c49
-rw-r--r--src/responder/ifp/ifp_iface_generated.h5
-rw-r--r--src/responder/ifp/ifp_users.c295
-rw-r--r--src/responder/ifp/ifp_users.h5
6 files changed, 360 insertions, 0 deletions
diff --git a/src/responder/ifp/ifp_iface.c b/src/responder/ifp/ifp_iface.c
index 4fea60565..e413e74f9 100644
--- a/src/responder/ifp/ifp_iface.c
+++ b/src/responder/ifp/ifp_iface.c
@@ -88,6 +88,7 @@ struct iface_ifp_users iface_ifp_users = {
.FindByID = ifp_users_find_by_id,
.FindByCertificate = ifp_users_find_by_cert,
.ListByCertificate = ifp_users_list_by_cert,
+ .FindByNameAndCertificate = ifp_users_find_by_name_and_cert,
.ListByName = ifp_users_list_by_name,
.ListByDomainAndName = ifp_users_list_by_domain_and_name
};
diff --git a/src/responder/ifp/ifp_iface.xml b/src/responder/ifp/ifp_iface.xml
index 93ccf90cb..0a23f5690 100644
--- a/src/responder/ifp/ifp_iface.xml
+++ b/src/responder/ifp/ifp_iface.xml
@@ -157,6 +157,11 @@
<arg name="limit" type="u" direction="in" />
<arg name="result" type="ao" direction="out" />
</method>
+ <method name="FindByNameAndCertificate">
+ <arg name="name" type="s" direction="in" />
+ <arg name="pem_cert" type="s" direction="in" />
+ <arg name="result" type="o" direction="out" />
+ </method>
<method name="ListByName">
<arg name="name_filter" type="s" direction="in" />
<arg name="limit" type="u" direction="in" />
diff --git a/src/responder/ifp/ifp_iface_generated.c b/src/responder/ifp/ifp_iface_generated.c
index 7ad9c34b9..211646b67 100644
--- a/src/responder/ifp/ifp_iface_generated.c
+++ b/src/responder/ifp/ifp_iface_generated.c
@@ -15,6 +15,9 @@ static int invoke_u_method(struct sbus_request *dbus_req, void *function_ptr);
/* invokes a handler with a 'su' DBus signature */
static int invoke_su_method(struct sbus_request *dbus_req, void *function_ptr);
+/* invokes a handler with a 'ss' DBus signature */
+static int invoke_ss_method(struct sbus_request *dbus_req, void *function_ptr);
+
/* invokes a handler with a 'ssu' DBus signature */
static int invoke_ssu_method(struct sbus_request *dbus_req, void *function_ptr);
@@ -762,6 +765,26 @@ int iface_ifp_users_ListByCertificate_finish(struct sbus_request *req, const cha
DBUS_TYPE_INVALID);
}
+/* arguments for org.freedesktop.sssd.infopipe.Users.FindByNameAndCertificate */
+const struct sbus_arg_meta iface_ifp_users_FindByNameAndCertificate__in[] = {
+ { "name", "s" },
+ { "pem_cert", "s" },
+ { NULL, }
+};
+
+/* arguments for org.freedesktop.sssd.infopipe.Users.FindByNameAndCertificate */
+const struct sbus_arg_meta iface_ifp_users_FindByNameAndCertificate__out[] = {
+ { "result", "o" },
+ { NULL, }
+};
+
+int iface_ifp_users_FindByNameAndCertificate_finish(struct sbus_request *req, const char *arg_result)
+{
+ return sbus_request_return_and_finish(req,
+ DBUS_TYPE_OBJECT_PATH, &arg_result,
+ DBUS_TYPE_INVALID);
+}
+
/* arguments for org.freedesktop.sssd.infopipe.Users.ListByName */
const struct sbus_arg_meta iface_ifp_users_ListByName__in[] = {
{ "name_filter", "s" },
@@ -834,6 +857,13 @@ const struct sbus_method_meta iface_ifp_users__methods[] = {
invoke_su_method,
},
{
+ "FindByNameAndCertificate", /* name */
+ iface_ifp_users_FindByNameAndCertificate__in,
+ iface_ifp_users_FindByNameAndCertificate__out,
+ offsetof(struct iface_ifp_users, FindByNameAndCertificate),
+ invoke_ss_method,
+ },
+ {
"ListByName", /* name */
iface_ifp_users_ListByName__in,
iface_ifp_users_ListByName__out,
@@ -1170,6 +1200,25 @@ const struct sbus_interface_meta iface_ifp_groups_group_meta = {
sbus_invoke_get_all, /* GetAll invoker */
};
+/* invokes a handler with a 'ss' DBus signature */
+static int invoke_ss_method(struct sbus_request *dbus_req, void *function_ptr)
+{
+ const char * arg_0;
+ const char * arg_1;
+ int (*handler)(struct sbus_request *, void *, const char *, const char *) = function_ptr;
+
+ if (!sbus_request_parse_or_finish(dbus_req,
+ DBUS_TYPE_STRING, &arg_0,
+ DBUS_TYPE_STRING, &arg_1,
+ DBUS_TYPE_INVALID)) {
+ return EOK; /* request handled */
+ }
+
+ return (handler)(dbus_req, dbus_req->intf->handler_data,
+ arg_0,
+ arg_1);
+}
+
/* invokes a handler with a 'ssu' DBus signature */
static int invoke_ssu_method(struct sbus_request *dbus_req, void *function_ptr)
{
diff --git a/src/responder/ifp/ifp_iface_generated.h b/src/responder/ifp/ifp_iface_generated.h
index 80b9aa290..e69fc3a3e 100644
--- a/src/responder/ifp/ifp_iface_generated.h
+++ b/src/responder/ifp/ifp_iface_generated.h
@@ -73,6 +73,7 @@
#define IFACE_IFP_USERS_FINDBYID "FindByID"
#define IFACE_IFP_USERS_FINDBYCERTIFICATE "FindByCertificate"
#define IFACE_IFP_USERS_LISTBYCERTIFICATE "ListByCertificate"
+#define IFACE_IFP_USERS_FINDBYNAMEANDCERTIFICATE "FindByNameAndCertificate"
#define IFACE_IFP_USERS_LISTBYNAME "ListByName"
#define IFACE_IFP_USERS_LISTBYDOMAINANDNAME "ListByDomainAndName"
@@ -249,6 +250,7 @@ struct iface_ifp_users {
int (*FindByID)(struct sbus_request *req, void *data, uint32_t arg_id);
int (*FindByCertificate)(struct sbus_request *req, void *data, const char *arg_pem_cert);
int (*ListByCertificate)(struct sbus_request *req, void *data, const char *arg_pem_cert, uint32_t arg_limit);
+ int (*FindByNameAndCertificate)(struct sbus_request *req, void *data, const char *arg_name, const char *arg_pem_cert);
int (*ListByName)(struct sbus_request *req, void *data, const char *arg_name_filter, uint32_t arg_limit);
int (*ListByDomainAndName)(struct sbus_request *req, void *data, const char *arg_domain_name, const char *arg_name_filter, uint32_t arg_limit);
};
@@ -265,6 +267,9 @@ int iface_ifp_users_FindByCertificate_finish(struct sbus_request *req, const cha
/* finish function for ListByCertificate */
int iface_ifp_users_ListByCertificate_finish(struct sbus_request *req, const char *arg_result[], int len_result);
+/* finish function for FindByNameAndCertificate */
+int iface_ifp_users_FindByNameAndCertificate_finish(struct sbus_request *req, const char *arg_result);
+
/* finish function for ListByName */
int iface_ifp_users_ListByName_finish(struct sbus_request *req, const char *arg_result[], int len_result);
diff --git a/src/responder/ifp/ifp_users.c b/src/responder/ifp/ifp_users.c
index 26e07aadb..cc78300f3 100644
--- a/src/responder/ifp/ifp_users.c
+++ b/src/responder/ifp/ifp_users.c
@@ -446,6 +446,301 @@ static int ifp_users_list_copy(struct ifp_list_ctx *list_ctx,
return EOK;
}
+struct name_and_cert_ctx {
+ const char *name;
+ char *derb64;
+ struct sbus_request *sbus_req;
+ char *user_opath;
+ struct ifp_list_ctx *list_ctx;
+};
+
+static void ifp_users_find_by_name_and_cert_name_done(struct tevent_req *req);
+static int ifp_users_find_by_name_and_cert_step(
+ struct name_and_cert_ctx *name_and_cert_ctx);
+static void ifp_users_find_by_name_and_cert_done(struct tevent_req *req);
+static void ifp_users_find_by_name_and_cert_reply(
+ struct name_and_cert_ctx *name_and_cert_ctx);
+
+int ifp_users_find_by_name_and_cert(struct sbus_request *sbus_req, void *data,
+ const char *name, const char *pem_cert)
+{
+ struct ifp_ctx *ctx;
+ struct tevent_req *req;
+ int ret;
+ struct name_and_cert_ctx *name_and_cert_ctx = NULL;
+ DBusError *error;
+
+ ctx = talloc_get_type(data, struct ifp_ctx);
+ if (ctx == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n");
+ return ERR_INTERNAL;
+ }
+
+ if ((name == NULL || *name == '\0')
+ && (pem_cert == NULL || *pem_cert == '\0')) {
+ error = sbus_error_new(sbus_req, DBUS_ERROR_INVALID_ARGS,
+ "Missing input");
+ sbus_request_fail_and_finish(sbus_req, error);
+ /* the connection is already terminated with an error message, hence
+ * we have to return EOK to not terminate the connection twice. */
+ return EOK;
+ }
+
+ name_and_cert_ctx = talloc_zero(sbus_req, struct name_and_cert_ctx);
+ if (name_and_cert_ctx == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "talloc failed.\n");
+ return ENOMEM;
+ }
+
+ name_and_cert_ctx->sbus_req = sbus_req;
+
+ if (name != NULL && *name != '\0') {
+ name_and_cert_ctx->name = talloc_strdup(name_and_cert_ctx, name);
+ if (name_and_cert_ctx->name == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
+ return ENOMEM;
+ }
+ }
+
+ if (pem_cert != NULL && *pem_cert != '\0') {
+ ret = sss_cert_pem_to_derb64(name_and_cert_ctx, pem_cert,
+ &(name_and_cert_ctx->derb64));
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "sss_cert_pem_to_derb64 failed.\n");
+
+ if (ret == ENOMEM) {
+ return ret;
+ }
+
+ error = sbus_error_new(sbus_req, DBUS_ERROR_INVALID_ARGS,
+ "Invalid certificate format");
+ sbus_request_fail_and_finish(sbus_req, error);
+ /* the connection is already terminated with an error message, hence
+ * we have to return EOK to not terminate the connection twice. */
+ return EOK;
+ }
+
+ /* FIXME: if unlimted searches with limit=0 will work please replace
+ * 100 with 0. */
+ name_and_cert_ctx->list_ctx = ifp_list_ctx_new(sbus_req, ctx,
+ name_and_cert_ctx->derb64,
+ 100);
+ if (name_and_cert_ctx->list_ctx == NULL) {
+ return ENOMEM;
+ }
+ }
+
+ if (name_and_cert_ctx->name != NULL) {
+ req = cache_req_user_by_name_send(sbus_req, ctx->rctx->ev, ctx->rctx,
+ ctx->rctx->ncache, 0, NULL,
+ name_and_cert_ctx->name);
+ if (req == NULL) {
+ return ENOMEM;
+ }
+
+ tevent_req_set_callback(req, ifp_users_find_by_name_and_cert_name_done,
+ name_and_cert_ctx);
+ } else {
+ ret = ifp_users_find_by_name_and_cert_step(name_and_cert_ctx);
+ if (ret != EOK) {
+ return ret;
+ }
+ }
+
+ return EOK;
+}
+
+static void ifp_users_find_by_name_and_cert_name_done(struct tevent_req *req)
+{
+ DBusError *error;
+ struct name_and_cert_ctx *name_and_cert_ctx = NULL;
+ struct sbus_request *sbus_req;
+ struct cache_req_result *result;
+ errno_t ret;
+
+ name_and_cert_ctx = tevent_req_callback_data(req, struct name_and_cert_ctx);
+ sbus_req = name_and_cert_ctx->sbus_req;
+
+ ret = cache_req_user_by_name_recv(name_and_cert_ctx, req, &result);
+ talloc_zfree(req);
+ if (ret == ENOENT) {
+ error = sbus_error_new(sbus_req, SBUS_ERROR_NOT_FOUND,
+ "User not found");
+ goto fail;
+ } else if (ret != EOK) {
+ error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED,
+ "Failed to fetch user [%d]: %s\n",
+ ret, sss_strerror(ret));
+ goto fail;
+ }
+
+ name_and_cert_ctx->user_opath = ifp_users_build_path_from_msg(
+ name_and_cert_ctx,
+ result->domain,
+ result->msgs[0]);
+ if (name_and_cert_ctx->user_opath == NULL) {
+ error = sbus_error_new(sbus_req, SBUS_ERROR_INTERNAL,
+ "Failed to compose object path");
+ goto fail;
+ }
+
+ if (name_and_cert_ctx->list_ctx != NULL) {
+ ret = ifp_users_find_by_name_and_cert_step(name_and_cert_ctx);
+ if (ret != EOK) {
+ error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED,
+ "Failed to fetch certificate [%d]: %s\n",
+ ret, sss_strerror(ret));
+ goto fail;
+ }
+ } else {
+ ifp_users_find_by_name_and_cert_reply(name_and_cert_ctx);
+ }
+
+ return;
+
+fail:
+ sbus_request_fail_and_finish(sbus_req, error);
+ return;
+}
+
+static int ifp_users_find_by_name_and_cert_step(
+ struct name_and_cert_ctx *name_and_cert_ctx)
+{
+ struct tevent_req *req;
+ struct ifp_list_ctx *list_ctx = name_and_cert_ctx->list_ctx;
+
+ req = cache_req_user_by_cert_send(list_ctx,
+ list_ctx->ctx->rctx->ev,
+ list_ctx->ctx->rctx,
+ list_ctx->ctx->rctx->ncache,
+ 0,
+ list_ctx->dom->name,
+ list_ctx->filter);
+ if (req == NULL) {
+ return ENOMEM;
+ }
+
+ tevent_req_set_callback(req, ifp_users_find_by_name_and_cert_done,
+ name_and_cert_ctx);
+
+ return EOK;
+}
+
+static void ifp_users_find_by_name_and_cert_done(struct tevent_req *req)
+{
+ DBusError *error;
+ struct name_and_cert_ctx *name_and_cert_ctx;
+ struct ifp_list_ctx *list_ctx;
+ struct sbus_request *sbus_req;
+ struct cache_req_result *result;
+ errno_t ret;
+
+ name_and_cert_ctx = tevent_req_callback_data(req, struct name_and_cert_ctx);
+ list_ctx = name_and_cert_ctx->list_ctx;
+ sbus_req = list_ctx->sbus_req;
+
+ ret = cache_req_user_by_cert_recv(name_and_cert_ctx, req, &result);
+ talloc_zfree(req);
+ if (ret != EOK && ret != ENOENT) {
+ error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED,
+ "Failed to fetch user [%d]: %s\n",
+ ret, sss_strerror(ret));
+ sbus_request_fail_and_finish(sbus_req, error);
+ return;
+ }
+
+ if (ret == EOK) {
+ ret = ifp_users_list_copy(list_ctx, result->ldb_result);
+ if (ret != EOK) {
+ error = sbus_error_new(sbus_req, SBUS_ERROR_INTERNAL,
+ "Failed to copy domain result");
+ sbus_request_fail_and_finish(sbus_req, error);
+ return;
+ }
+ }
+
+ list_ctx->dom = get_next_domain(list_ctx->dom, SSS_GND_DESCEND);
+ if (list_ctx->dom == NULL) {
+ return ifp_users_find_by_name_and_cert_reply(name_and_cert_ctx);
+ }
+
+ ret = ifp_users_find_by_name_and_cert_step(name_and_cert_ctx);
+ if (ret != EOK) {
+ error = sbus_error_new(sbus_req, SBUS_ERROR_INTERNAL,
+ "Failed to start next-domain search");
+ sbus_request_fail_and_finish(sbus_req, error);
+ return;
+ }
+ return;
+}
+
+static void ifp_users_find_by_name_and_cert_reply(
+ struct name_and_cert_ctx *name_and_cert_ctx)
+{
+ struct sbus_request *sbus_req = name_and_cert_ctx->sbus_req;
+ struct ifp_list_ctx *list_ctx = name_and_cert_ctx->list_ctx;
+ DBusError *error;
+ size_t c;
+
+ /* If no name was given check if there is only one user mapped to the
+ * certificate and return its object path. Either no or more than one
+ * mapped users are errors in this case.
+ * The case where a given name could not be found is already handled in
+ * ifp_users_find_by_name_and_cert_name_done(). */
+ if (name_and_cert_ctx->user_opath == NULL) {
+ if (list_ctx == NULL || list_ctx->path_count == 0) {
+ error = sbus_error_new(sbus_req, SBUS_ERROR_NOT_FOUND,
+ "User not found");
+ sbus_request_fail_and_finish(sbus_req, error);
+ } else if (list_ctx->path_count == 1) {
+ iface_ifp_users_FindByNameAndCertificate_finish(sbus_req,
+ list_ctx->paths[0]);
+ } else {
+ error = sbus_error_new(sbus_req, SBUS_ERROR_MORE_THAN_ONE,
+ "More than one user found. "
+ "Use ListByCertificate to get all.");
+ sbus_request_fail_and_finish(sbus_req, error);
+ }
+ return;
+ }
+
+ /* If there was no certficate given just return the object path of the
+ * user found by name. If a certificate was given an no mapped user was
+ * found return an error. */
+ if (list_ctx == NULL || list_ctx->path_count == 0) {
+ if (name_and_cert_ctx->derb64 == NULL) {
+ iface_ifp_users_FindByNameAndCertificate_finish(sbus_req,
+ name_and_cert_ctx->user_opath);
+ } else {
+ error = sbus_error_new(sbus_req, SBUS_ERROR_NOT_FOUND,
+ "No user matching name and certificate "
+ "found");
+ sbus_request_fail_and_finish(sbus_req, error);
+ }
+ return;
+ }
+
+ /* Check if the user found by name is one of the users mapped to the
+ * certificate. */
+ for (c = 0; c < list_ctx->path_count; c++) {
+ if (strcmp(name_and_cert_ctx->user_opath, list_ctx->paths[c]) == 0) {
+ iface_ifp_users_FindByNameAndCertificate_finish(sbus_req,
+ name_and_cert_ctx->user_opath);
+ return;
+ }
+ }
+
+ /* A user was found by name but the certificate is mapped to one or more
+ * different users. */
+ error = sbus_error_new(sbus_req, SBUS_ERROR_NOT_FOUND,
+ "No user matching name and certificate found");
+ sbus_request_fail_and_finish(sbus_req, error);
+
+ /* name_and_cert_ctx is already freed because sbus_req (the parent) is
+ * already freed by the DBus finish calls */
+ return;
+}
+
static int ifp_users_list_by_name_step(struct ifp_list_ctx *list_ctx);
static void ifp_users_list_by_name_done(struct tevent_req *req);
static void ifp_users_list_by_name_reply(struct ifp_list_ctx *list_ctx);
diff --git a/src/responder/ifp/ifp_users.h b/src/responder/ifp/ifp_users.h
index 467ebc644..f8fefeb7f 100644
--- a/src/responder/ifp/ifp_users.h
+++ b/src/responder/ifp/ifp_users.h
@@ -49,6 +49,11 @@ int ifp_users_list_by_cert(struct sbus_request *sbus_req,
const char *pem_cert,
uint32_t limit);
+int ifp_users_find_by_name_and_cert(struct sbus_request *sbus_req,
+ void *data,
+ const char *name,
+ const char *pem_cert);
+
int ifp_users_list_by_name(struct sbus_request *sbus_req,
void *data,
const char *filter,