summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSumit Bose <sbose@redhat.com>2015-05-26 14:29:17 +0200
committerJakub Hrozek <jhrozek@redhat.com>2015-06-19 18:48:13 +0200
commit827a016a07d5f911cc4195be89896a376fd71f59 (patch)
treecffbe41134143e97a2a073041e7d760dae1af112
parenta99845006f96f9d1e7af871ec67c71cee8408a62 (diff)
downloadsssd-827a016a07d5f911cc4195be89896a376fd71f59.tar.gz
sssd-827a016a07d5f911cc4195be89896a376fd71f59.tar.xz
sssd-827a016a07d5f911cc4195be89896a376fd71f59.zip
IFP: add FindByCertificate method for User objects
Related to https://fedorahosted.org/sssd/ticket/2596 Reviewed-by: Pavel Březina <pbrezina@redhat.com>
-rw-r--r--Makefile.am4
-rw-r--r--src/responder/common/responder.h3
-rw-r--r--src/responder/common/responder_cache_req.c88
-rw-r--r--src/responder/common/responder_cache_req.h19
-rw-r--r--src/responder/common/responder_dp.c11
-rw-r--r--src/responder/ifp/ifp_iface.c1
-rw-r--r--src/responder/ifp/ifp_iface.xml4
-rw-r--r--src/responder/ifp/ifp_iface_generated.c26
-rw-r--r--src/responder/ifp/ifp_iface_generated.h5
-rw-r--r--src/responder/ifp/ifp_users.c87
-rw-r--r--src/responder/ifp/ifp_users.h4
-rw-r--r--src/responder/ifp/ifpsrv_cmd.c4
12 files changed, 242 insertions, 14 deletions
diff --git a/Makefile.am b/Makefile.am
index 1d80c3671..93a32dbdb 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1139,7 +1139,9 @@ sssd_ifp_CFLAGS = \
$(AM_CFLAGS)
sssd_ifp_LDADD = \
$(SSSD_LIBS) \
- $(SSSD_INTERNAL_LTLIBS)
+ $(SSSD_INTERNAL_LTLIBS) \
+ libsss_cert.la \
+ $(NULL)
dist_dbuspolicy_DATA = \
src/responder/ifp/org.freedesktop.sssd.infopipe.conf
dist_dbusservice_DATA = \
diff --git a/src/responder/common/responder.h b/src/responder/common/responder.h
index 9c7a73809..bd0250d52 100644
--- a/src/responder/common/responder.h
+++ b/src/responder/common/responder.h
@@ -281,7 +281,8 @@ enum sss_dp_acct_type {
SSS_DP_NETGR,
SSS_DP_SERVICES,
SSS_DP_SECID,
- SSS_DP_USER_AND_GROUP
+ SSS_DP_USER_AND_GROUP,
+ SSS_DP_CERT
};
struct tevent_req *
diff --git a/src/responder/common/responder_cache_req.c b/src/responder/common/responder_cache_req.c
index 7ba257276..dd81abadf 100644
--- a/src/responder/common/responder_cache_req.c
+++ b/src/responder/common/responder_cache_req.c
@@ -34,6 +34,7 @@ struct cache_req_input {
/* Provided input. */
const char *orig_name;
uint32_t id;
+ const char *cert;
/* Data Provider request type resolved from @type.
* FIXME: This is currently needed for data provider calls. We should
@@ -56,7 +57,8 @@ struct cache_req_input *
cache_req_input_create(TALLOC_CTX *mem_ctx,
enum cache_req_type type,
const char *name,
- uint32_t id)
+ uint32_t id,
+ const char *cert)
{
struct cache_req_input *input;
@@ -82,6 +84,17 @@ cache_req_input_create(TALLOC_CTX *mem_ctx,
goto fail;
}
break;
+ case CACHE_REQ_USER_BY_CERT:
+ if (cert == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: certificate cannot be NULL!\n");
+ goto fail;
+ }
+
+ input->cert = talloc_strdup(input, cert);
+ if (input->cert == NULL) {
+ goto fail;
+ }
+ break;
case CACHE_REQ_USER_BY_ID:
case CACHE_REQ_GROUP_BY_ID:
if (id == 0) {
@@ -108,6 +121,9 @@ cache_req_input_create(TALLOC_CTX *mem_ctx,
case CACHE_REQ_INITGROUPS:
input->dp_type = SSS_DP_INITGROUPS;
break;
+ case CACHE_REQ_USER_BY_CERT:
+ input->dp_type = SSS_DP_CERT;
+ break;
}
return input;
@@ -192,6 +208,17 @@ cache_req_input_set_domain(struct cache_req_input *input,
goto done;
}
break;
+ case CACHE_REQ_USER_BY_CERT:
+ /* certificates might be quite long, only use the last 10 charcters
+ * for logging */
+ fqn = talloc_asprintf(tmp_ctx, "CERT:%s@%s",
+ get_last_x_chars(input->cert, 10),
+ domain->name);
+ if (fqn == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ break;
}
input->domain = domain;
@@ -227,6 +254,9 @@ static errno_t cache_req_check_ncache(struct cache_req_input *input,
case CACHE_REQ_GROUP_BY_ID:
ret = sss_ncache_check_gid(ncache, neg_timeout, input->id);
break;
+ case CACHE_REQ_USER_BY_CERT:
+ ret = sss_ncache_check_cert(ncache, neg_timeout, input->cert);
+ break;
}
if (ret == EEXIST) {
@@ -254,6 +284,7 @@ static void cache_req_add_to_ncache(struct cache_req_input *input,
break;
case CACHE_REQ_USER_BY_ID:
case CACHE_REQ_GROUP_BY_ID:
+ case CACHE_REQ_USER_BY_CERT:
/* Nothing to do. Those types must be unique among all domains so
* the don't contain domain part. Therefore they must be set only
* if all domains are search and the entry is not found. */
@@ -290,6 +321,9 @@ static void cache_req_add_to_ncache_global(struct cache_req_input *input,
case CACHE_REQ_GROUP_BY_ID:
ret = sss_ncache_set_gid(ncache, false, input->id);
break;
+ case CACHE_REQ_USER_BY_CERT:
+ ret = sss_ncache_set_cert(ncache, false, input->cert);
+ break;
}
if (ret != EOK) {
@@ -338,6 +372,11 @@ static errno_t cache_req_get_object(TALLOC_CTX *mem_ctx,
ret = sysdb_initgroups_with_views(mem_ctx, input->domain,
input->dom_objname, &result);
break;
+ case CACHE_REQ_USER_BY_CERT:
+ one_item_only = true;
+ ret = sysdb_search_user_by_cert(mem_ctx, input->domain,
+ input->cert, &result);
+ break;
}
if (ret != EOK) {
@@ -461,6 +500,7 @@ static errno_t cache_req_cache_check(struct tevent_req *req)
const char *extra_flag = NULL;
uint64_t cache_expire = 0;
errno_t ret;
+ const char *search_str;
state = tevent_req_data(req, struct cache_req_cache_state);
@@ -479,6 +519,10 @@ static errno_t cache_req_cache_check(struct tevent_req *req)
state->cache_refresh_percent, cache_expire);
}
+ search_str = state->input->dom_objname;
+ if (state->input->type == CACHE_REQ_USER_BY_CERT) {
+ search_str = state->input->cert;
+ }
switch (ret) {
case EOK:
DEBUG(SSSDBG_TRACE_FUNC, "Cached entry is valid, returning...\n");
@@ -492,7 +536,7 @@ static errno_t cache_req_cache_check(struct tevent_req *req)
subreq = sss_dp_get_account_send(state, state->rctx,
state->input->domain, true,
state->input->dp_type,
- state->input->dom_objname,
+ search_str,
state->input->id, NULL);
if (subreq == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory sending out-of-band "
@@ -514,7 +558,7 @@ static errno_t cache_req_cache_check(struct tevent_req *req)
subreq = sss_dp_get_account_send(state, state->rctx,
state->input->domain, true,
state->input->dp_type,
- state->input->dom_objname,
+ search_str,
state->input->id, extra_flag);
if (subreq == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE,
@@ -890,7 +934,8 @@ cache_req_user_by_name_send(TALLOC_CTX *mem_ctx,
{
struct cache_req_input *input;
- input = cache_req_input_create(mem_ctx, CACHE_REQ_USER_BY_NAME, name, 0);
+ input = cache_req_input_create(mem_ctx, CACHE_REQ_USER_BY_NAME, name, 0,
+ NULL);
if (input == NULL) {
return NULL;
}
@@ -912,7 +957,31 @@ cache_req_user_by_id_send(TALLOC_CTX *mem_ctx,
{
struct cache_req_input *input;
- input = cache_req_input_create(mem_ctx, CACHE_REQ_USER_BY_ID, NULL, uid);
+ input = cache_req_input_create(mem_ctx, CACHE_REQ_USER_BY_ID, NULL, uid,
+ NULL);
+ if (input == NULL) {
+ return NULL;
+ }
+
+ return cache_req_steal_input_and_send(mem_ctx, ev, rctx, ncache,
+ neg_timeout, cache_refresh_percent,
+ domain, input);
+}
+
+struct tevent_req *
+cache_req_user_by_cert_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct resp_ctx *rctx,
+ struct sss_nc_ctx *ncache,
+ int neg_timeout,
+ int cache_refresh_percent,
+ const char *domain,
+ const char *pem_cert)
+{
+ struct cache_req_input *input;
+
+ input = cache_req_input_create(mem_ctx, CACHE_REQ_USER_BY_CERT,
+ NULL, 0, pem_cert);
if (input == NULL) {
return NULL;
}
@@ -934,7 +1003,8 @@ cache_req_group_by_name_send(TALLOC_CTX *mem_ctx,
{
struct cache_req_input *input;
- input = cache_req_input_create(mem_ctx, CACHE_REQ_GROUP_BY_NAME, name, 0);
+ input = cache_req_input_create(mem_ctx, CACHE_REQ_GROUP_BY_NAME, name, 0,
+ NULL);
if (input == NULL) {
return NULL;
}
@@ -956,7 +1026,8 @@ cache_req_group_by_id_send(TALLOC_CTX *mem_ctx,
{
struct cache_req_input *input;
- input = cache_req_input_create(mem_ctx, CACHE_REQ_GROUP_BY_ID, NULL, gid);
+ input = cache_req_input_create(mem_ctx, CACHE_REQ_GROUP_BY_ID, NULL, gid,
+ NULL);
if (input == NULL) {
return NULL;
}
@@ -978,7 +1049,8 @@ cache_req_initgr_by_name_send(TALLOC_CTX *mem_ctx,
{
struct cache_req_input *input;
- input = cache_req_input_create(mem_ctx, CACHE_REQ_INITGROUPS, name, 0);
+ input = cache_req_input_create(mem_ctx, CACHE_REQ_INITGROUPS, name, 0,
+ NULL);
if (input == NULL) {
return NULL;
}
diff --git a/src/responder/common/responder_cache_req.h b/src/responder/common/responder_cache_req.h
index 088e8efe0..84a9dde7d 100644
--- a/src/responder/common/responder_cache_req.h
+++ b/src/responder/common/responder_cache_req.h
@@ -32,7 +32,8 @@ enum cache_req_type {
CACHE_REQ_USER_BY_ID,
CACHE_REQ_GROUP_BY_NAME,
CACHE_REQ_GROUP_BY_ID,
- CACHE_REQ_INITGROUPS
+ CACHE_REQ_INITGROUPS,
+ CACHE_REQ_USER_BY_CERT
};
struct cache_req_input;
@@ -41,7 +42,8 @@ struct cache_req_input *
cache_req_input_create(TALLOC_CTX *mem_ctx,
enum cache_req_type type,
const char *name,
- uint32_t id);
+ uint32_t id,
+ const char *cert);
/**
* Currently only SSS_DP_USER and SSS_DP_INITGROUPS are supported.
@@ -90,6 +92,19 @@ cache_req_user_by_id_send(TALLOC_CTX *mem_ctx,
cache_req_recv(mem_ctx, req, _result, _domain, NULL)
struct tevent_req *
+cache_req_user_by_cert_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct resp_ctx *rctx,
+ struct sss_nc_ctx *ncache,
+ int neg_timeout,
+ int cache_refresh_percent,
+ const char *domain,
+ const char *pem_cert);
+
+#define cache_req_user_by_cert_recv(mem_ctx, req, _result, _domain, _name) \
+ cache_req_recv(mem_ctx, req, _result, _domain, _name)
+
+struct tevent_req *
cache_req_group_by_name_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct resp_ctx *rctx,
diff --git a/src/responder/common/responder_dp.c b/src/responder/common/responder_dp.c
index 853b3eae3..f752c94c3 100644
--- a/src/responder/common/responder_dp.c
+++ b/src/responder/common/responder_dp.c
@@ -548,6 +548,9 @@ sss_dp_get_account_msg(void *pvt)
case SSS_DP_USER_AND_GROUP:
be_type = BE_REQ_USER_AND_GROUP;
break;
+ case SSS_DP_CERT:
+ be_type = BE_REQ_BY_CERT;
+ break;
}
if (info->fast_reply) {
@@ -563,6 +566,14 @@ sss_dp_get_account_msg(void *pvt)
filter = talloc_asprintf(info, "%s=%s", DP_SEC_ID,
info->opt_name);
}
+ } else if (info->type == SSS_DP_CERT) {
+ if (info->extra) {
+ filter = talloc_asprintf(info, "%s=%s:%s", DP_CERT,
+ info->opt_name, info->extra);
+ } else {
+ filter = talloc_asprintf(info, "%s=%s", DP_CERT,
+ info->opt_name);
+ }
} else {
if (info->extra) {
filter = talloc_asprintf(info, "name=%s:%s",
diff --git a/src/responder/ifp/ifp_iface.c b/src/responder/ifp/ifp_iface.c
index 015c66dc5..86d8d338c 100644
--- a/src/responder/ifp/ifp_iface.c
+++ b/src/responder/ifp/ifp_iface.c
@@ -82,6 +82,7 @@ struct iface_ifp_users iface_ifp_users = {
{ &iface_ifp_users_meta, 0 },
.FindByName = ifp_users_find_by_name,
.FindByID = ifp_users_find_by_id,
+ .FindByCertificate = ifp_users_find_by_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 628692af6..5a56b624a 100644
--- a/src/responder/ifp/ifp_iface.xml
+++ b/src/responder/ifp/ifp_iface.xml
@@ -136,6 +136,10 @@
<arg name="id" type="u" direction="in" />
<arg name="result" type="o" direction="out" />
</method>
+ <method name="FindByCertificate">
+ <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 8255cbea7..a4fdd5d12 100644
--- a/src/responder/ifp/ifp_iface_generated.c
+++ b/src/responder/ifp/ifp_iface_generated.c
@@ -685,6 +685,25 @@ int iface_ifp_users_FindByID_finish(struct sbus_request *req, const char *arg_re
DBUS_TYPE_INVALID);
}
+/* arguments for org.freedesktop.sssd.infopipe.Users.FindByCertificate */
+const struct sbus_arg_meta iface_ifp_users_FindByCertificate__in[] = {
+ { "pem_cert", "s" },
+ { NULL, }
+};
+
+/* arguments for org.freedesktop.sssd.infopipe.Users.FindByCertificate */
+const struct sbus_arg_meta iface_ifp_users_FindByCertificate__out[] = {
+ { "result", "o" },
+ { NULL, }
+};
+
+int iface_ifp_users_FindByCertificate_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" },
@@ -743,6 +762,13 @@ const struct sbus_method_meta iface_ifp_users__methods[] = {
invoke_u_method,
},
{
+ "FindByCertificate", /* name */
+ iface_ifp_users_FindByCertificate__in,
+ iface_ifp_users_FindByCertificate__out,
+ offsetof(struct iface_ifp_users, FindByCertificate),
+ invoke_s_method,
+ },
+ {
"ListByName", /* name */
iface_ifp_users_ListByName__in,
iface_ifp_users_ListByName__out,
diff --git a/src/responder/ifp/ifp_iface_generated.h b/src/responder/ifp/ifp_iface_generated.h
index d2e5cdd3a..4dfe61ddf 100644
--- a/src/responder/ifp/ifp_iface_generated.h
+++ b/src/responder/ifp/ifp_iface_generated.h
@@ -68,6 +68,7 @@
#define IFACE_IFP_USERS "org.freedesktop.sssd.infopipe.Users"
#define IFACE_IFP_USERS_FINDBYNAME "FindByName"
#define IFACE_IFP_USERS_FINDBYID "FindByID"
+#define IFACE_IFP_USERS_FINDBYCERTIFICATE "FindByCertificate"
#define IFACE_IFP_USERS_LISTBYNAME "ListByName"
#define IFACE_IFP_USERS_LISTBYDOMAINANDNAME "ListByDomainAndName"
@@ -235,6 +236,7 @@ struct iface_ifp_users {
struct sbus_vtable vtable; /* derive from sbus_vtable */
int (*FindByName)(struct sbus_request *req, void *data, const char *arg_name);
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 (*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);
};
@@ -245,6 +247,9 @@ int iface_ifp_users_FindByName_finish(struct sbus_request *req, const char *arg_
/* finish function for FindByID */
int iface_ifp_users_FindByID_finish(struct sbus_request *req, const char *arg_result);
+/* finish function for FindByCertificate */
+int iface_ifp_users_FindByCertificate_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 fa6f47f0d..2ec74c30b 100644
--- a/src/responder/ifp/ifp_users.c
+++ b/src/responder/ifp/ifp_users.c
@@ -25,6 +25,7 @@
#include "db/sysdb.h"
#include "util/util.h"
#include "util/strtonum.h"
+#include "util/cert.h"
#include "sbus/sssd_dbus_errors.h"
#include "responder/common/responder.h"
#include "responder/common/responder_cache_req.h"
@@ -222,6 +223,92 @@ done:
return;
}
+static void ifp_users_find_by_cert_done(struct tevent_req *req);
+
+int ifp_users_find_by_cert(struct sbus_request *sbus_req, void *data,
+ const char *pem_cert)
+{
+ struct ifp_ctx *ctx;
+ struct tevent_req *req;
+ int ret;
+ char *derb64;
+ DBusError *error;
+
+ ctx = talloc_get_type(data, struct ifp_ctx);
+ if (ctx == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n");
+ return ERR_INTERNAL;
+ }
+
+ ret = sss_cert_pem_to_derb64(sbus_req, pem_cert, &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;
+ }
+
+ req = cache_req_user_by_cert_send(sbus_req, ctx->rctx->ev, ctx->rctx,
+ ctx->ncache, ctx->neg_timeout, 0,
+ NULL, derb64);
+ if (req == NULL) {
+ return ENOMEM;
+ }
+
+ tevent_req_set_callback(req, ifp_users_find_by_cert_done, sbus_req);
+
+ return EOK;
+}
+
+static void ifp_users_find_by_cert_done(struct tevent_req *req)
+{
+ DBusError *error;
+ struct sbus_request *sbus_req;
+ struct sss_domain_info *domain;
+ struct ldb_result *result;
+ char *object_path;
+ errno_t ret;
+
+ sbus_req = tevent_req_callback_data(req, struct sbus_request);
+
+ ret = cache_req_user_by_cert_recv(sbus_req, req, &result, &domain, NULL);
+ talloc_zfree(req);
+ if (ret == ENOENT) {
+ error = sbus_error_new(sbus_req, SBUS_ERROR_NOT_FOUND,
+ "User not found");
+ goto done;
+ } 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 done;
+ }
+
+ object_path = ifp_users_build_path_from_msg(sbus_req, domain,
+ result->msgs[0]);
+ if (object_path == NULL) {
+ error = sbus_error_new(sbus_req, SBUS_ERROR_INTERNAL,
+ "Failed to compose object path");
+ goto done;
+ }
+
+done:
+ if (ret != EOK) {
+ sbus_request_fail_and_finish(sbus_req, error);
+ return;
+ }
+
+ iface_ifp_users_FindByCertificate_finish(sbus_req, object_path);
+ return;
+}
+
int ifp_users_list_by_name(struct sbus_request *sbus_req,
void *data,
const char *filter,
diff --git a/src/responder/ifp/ifp_users.h b/src/responder/ifp/ifp_users.h
index 4da0a7347..471c3fb01 100644
--- a/src/responder/ifp/ifp_users.h
+++ b/src/responder/ifp/ifp_users.h
@@ -43,6 +43,10 @@ int ifp_users_find_by_id(struct sbus_request *sbus_req,
void *data,
uint32_t id);
+int ifp_users_find_by_cert(struct sbus_request *sbus_req,
+ void *data,
+ const char *pem_cert);
+
int ifp_users_list_by_name(struct sbus_request *sbus_req,
void *data,
const char *filter,
diff --git a/src/responder/ifp/ifpsrv_cmd.c b/src/responder/ifp/ifpsrv_cmd.c
index d4d5dc640..ab6156fd6 100644
--- a/src/responder/ifp/ifpsrv_cmd.c
+++ b/src/responder/ifp/ifpsrv_cmd.c
@@ -497,11 +497,11 @@ ifp_user_get_attr_lookup(struct tevent_req *subreq)
switch (state->search_type) {
case SSS_DP_USER:
input = cache_req_input_create(state, CACHE_REQ_USER_BY_NAME,
- state->name, 0);
+ state->name, 0, NULL);
break;
case SSS_DP_INITGROUPS:
input = cache_req_input_create(state, CACHE_REQ_INITGROUPS,
- state->name, 0);
+ state->name, 0, NULL);
break;
default:
DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported search type [%d]!\n",