|
|
bb7cd1 |
From 91c099a993252680f103084431b1d0f5798d8a24 Mon Sep 17 00:00:00 2001
|
|
|
bb7cd1 |
From: Jakub Hrozek <jhrozek@redhat.com>
|
|
|
bb7cd1 |
Date: Tue, 21 Mar 2017 14:14:42 +0100
|
|
|
bb7cd1 |
Subject: [PATCH 31/36] SECRETS: Store ccaches in secrets for the KCM responder
|
|
|
bb7cd1 |
MIME-Version: 1.0
|
|
|
bb7cd1 |
Content-Type: text/plain; charset=UTF-8
|
|
|
bb7cd1 |
Content-Transfer-Encoding: 8bit
|
|
|
bb7cd1 |
|
|
|
bb7cd1 |
Adds a new "hive" to the secrets responder whose base path is /kcm. Only
|
|
|
bb7cd1 |
root can contact the /kcm hive, because the KCM responder only runs as
|
|
|
bb7cd1 |
root and it must impersonate other users and store ccaches on their behalf.
|
|
|
bb7cd1 |
|
|
|
bb7cd1 |
Reviewed-by: Michal Židek <mzidek@redhat.com>
|
|
|
bb7cd1 |
Reviewed-by: Simo Sorce <simo@redhat.com>
|
|
|
bb7cd1 |
---
|
|
|
bb7cd1 |
src/responder/secrets/local.c | 16 +++++++-
|
|
|
bb7cd1 |
src/responder/secrets/providers.c | 71 ++++++++++++++++++++++++++++++----
|
|
|
bb7cd1 |
src/responder/secrets/secsrv_private.h | 10 ++++-
|
|
|
bb7cd1 |
3 files changed, 86 insertions(+), 11 deletions(-)
|
|
|
bb7cd1 |
|
|
|
bb7cd1 |
diff --git a/src/responder/secrets/local.c b/src/responder/secrets/local.c
|
|
|
bb7cd1 |
index 26c97a2849febbf0ac482d526cf927bfc103b4f2..02007ada8b673071ecba033df0eb3f81af93fcbd 100644
|
|
|
bb7cd1 |
--- a/src/responder/secrets/local.c
|
|
|
bb7cd1 |
+++ b/src/responder/secrets/local.c
|
|
|
bb7cd1 |
@@ -26,6 +26,9 @@
|
|
|
bb7cd1 |
|
|
|
bb7cd1 |
#define MKEY_SIZE (256 / 8)
|
|
|
bb7cd1 |
|
|
|
bb7cd1 |
+#define SECRETS_BASEDN "cn=secrets"
|
|
|
bb7cd1 |
+#define KCM_BASEDN "cn=kcm"
|
|
|
bb7cd1 |
+
|
|
|
bb7cd1 |
struct local_context {
|
|
|
bb7cd1 |
struct ldb_context *ldb;
|
|
|
bb7cd1 |
struct sec_data master_key;
|
|
|
bb7cd1 |
@@ -119,6 +122,7 @@ static int local_encrypt(struct local_context *lctx, TALLOC_CTX *mem_ctx,
|
|
|
bb7cd1 |
|
|
|
bb7cd1 |
static int local_db_dn(TALLOC_CTX *mem_ctx,
|
|
|
bb7cd1 |
struct ldb_context *ldb,
|
|
|
bb7cd1 |
+ const char *basedn,
|
|
|
bb7cd1 |
const char *req_path,
|
|
|
bb7cd1 |
struct ldb_dn **req_dn)
|
|
|
bb7cd1 |
{
|
|
|
bb7cd1 |
@@ -126,7 +130,7 @@ static int local_db_dn(TALLOC_CTX *mem_ctx,
|
|
|
bb7cd1 |
const char *s, *e;
|
|
|
bb7cd1 |
int ret;
|
|
|
bb7cd1 |
|
|
|
bb7cd1 |
- dn = ldb_dn_new(mem_ctx, ldb, "cn=secrets");
|
|
|
bb7cd1 |
+ dn = ldb_dn_new(mem_ctx, ldb, basedn);
|
|
|
bb7cd1 |
if (!dn) {
|
|
|
bb7cd1 |
ret = ENOMEM;
|
|
|
bb7cd1 |
goto done;
|
|
|
bb7cd1 |
@@ -738,6 +742,11 @@ static int local_secrets_map_path(TALLOC_CTX *mem_ctx,
|
|
|
bb7cd1 |
lc_req->path = talloc_strdup(lc_req,
|
|
|
bb7cd1 |
secreq->mapped_path + (sizeof(SEC_BASEPATH) - 1));
|
|
|
bb7cd1 |
basedn = SECRETS_BASEDN;
|
|
|
bb7cd1 |
+ } else if (strncmp(secreq->mapped_path,
|
|
|
bb7cd1 |
+ SEC_KCM_BASEPATH, sizeof(SEC_KCM_BASEPATH) - 1) == 0) {
|
|
|
bb7cd1 |
+ lc_req->path = talloc_strdup(lc_req,
|
|
|
bb7cd1 |
+ secreq->mapped_path + (sizeof(SEC_KCM_BASEPATH) - 1));
|
|
|
bb7cd1 |
+ basedn = KCM_BASEDN;
|
|
|
bb7cd1 |
} else {
|
|
|
bb7cd1 |
ret = EINVAL;
|
|
|
bb7cd1 |
goto done;
|
|
|
bb7cd1 |
@@ -820,7 +829,10 @@ static struct tevent_req *local_secret_req(TALLOC_CTX *mem_ctx,
|
|
|
bb7cd1 |
DEBUG(SSSDBG_TRACE_LIBS, "Content-Type: %s\n", content_type);
|
|
|
bb7cd1 |
|
|
|
bb7cd1 |
ret = local_secrets_map_path(state, lctx->ldb, secreq, &lc_req);
|
|
|
bb7cd1 |
- if (ret) goto done;
|
|
|
bb7cd1 |
+ if (ret) {
|
|
|
bb7cd1 |
+ DEBUG(SSSDBG_OP_FAILURE, "Cannot map request path to local path\n");
|
|
|
bb7cd1 |
+ goto done;
|
|
|
bb7cd1 |
+ }
|
|
|
bb7cd1 |
|
|
|
bb7cd1 |
switch (secreq->method) {
|
|
|
bb7cd1 |
case HTTP_GET:
|
|
|
bb7cd1 |
diff --git a/src/responder/secrets/providers.c b/src/responder/secrets/providers.c
|
|
|
bb7cd1 |
index eba555d2e422d08db211979422a2957e48b51589..94831c73036d269addca45c0117811a2c68873fd 100644
|
|
|
bb7cd1 |
--- a/src/responder/secrets/providers.c
|
|
|
bb7cd1 |
+++ b/src/responder/secrets/providers.c
|
|
|
bb7cd1 |
@@ -24,6 +24,14 @@
|
|
|
bb7cd1 |
#include "responder/secrets/secsrv_proxy.h"
|
|
|
bb7cd1 |
#include <jansson.h>
|
|
|
bb7cd1 |
|
|
|
bb7cd1 |
+typedef int (*url_mapper_fn)(struct sec_req_ctx *secreq,
|
|
|
bb7cd1 |
+ char **mapped_path);
|
|
|
bb7cd1 |
+
|
|
|
bb7cd1 |
+struct url_pfx_router {
|
|
|
bb7cd1 |
+ const char *prefix;
|
|
|
bb7cd1 |
+ url_mapper_fn mapper_fn;
|
|
|
bb7cd1 |
+};
|
|
|
bb7cd1 |
+
|
|
|
bb7cd1 |
static int sec_map_url_to_user_path(struct sec_req_ctx *secreq,
|
|
|
bb7cd1 |
char **mapped_path)
|
|
|
bb7cd1 |
{
|
|
|
bb7cd1 |
@@ -42,10 +50,43 @@ static int sec_map_url_to_user_path(struct sec_req_ctx *secreq,
|
|
|
bb7cd1 |
return ENOMEM;
|
|
|
bb7cd1 |
}
|
|
|
bb7cd1 |
|
|
|
bb7cd1 |
- DEBUG(SSSDBG_TRACE_LIBS, "User-specific path is [%s]\n", *mapped_path);
|
|
|
bb7cd1 |
+ DEBUG(SSSDBG_TRACE_LIBS,
|
|
|
bb7cd1 |
+ "User-specific secrets path is [%s]\n", *mapped_path);
|
|
|
bb7cd1 |
return EOK;
|
|
|
bb7cd1 |
}
|
|
|
bb7cd1 |
|
|
|
bb7cd1 |
+static int kcm_map_url_to_path(struct sec_req_ctx *secreq,
|
|
|
bb7cd1 |
+ char **mapped_path)
|
|
|
bb7cd1 |
+{
|
|
|
bb7cd1 |
+ uid_t c_euid;
|
|
|
bb7cd1 |
+
|
|
|
bb7cd1 |
+ c_euid = client_euid(secreq->cctx->creds);
|
|
|
bb7cd1 |
+ if (c_euid != KCM_PEER_UID) {
|
|
|
bb7cd1 |
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
|
|
bb7cd1 |
+ "UID %"SPRIuid" is not allowed to access "
|
|
|
bb7cd1 |
+ "the "SEC_KCM_BASEPATH" hive\n",
|
|
|
bb7cd1 |
+ c_euid);
|
|
|
bb7cd1 |
+ return EPERM;
|
|
|
bb7cd1 |
+ }
|
|
|
bb7cd1 |
+
|
|
|
bb7cd1 |
+ *mapped_path = talloc_strdup(secreq, secreq->parsed_url.path );
|
|
|
bb7cd1 |
+ if (!*mapped_path) {
|
|
|
bb7cd1 |
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
|
|
bb7cd1 |
+ "Failed to map request to user specific url\n");
|
|
|
bb7cd1 |
+ return ENOMEM;
|
|
|
bb7cd1 |
+ }
|
|
|
bb7cd1 |
+
|
|
|
bb7cd1 |
+ DEBUG(SSSDBG_TRACE_LIBS,
|
|
|
bb7cd1 |
+ "User-specific KCM path is [%s]\n", *mapped_path);
|
|
|
bb7cd1 |
+ return EOK;
|
|
|
bb7cd1 |
+}
|
|
|
bb7cd1 |
+
|
|
|
bb7cd1 |
+static struct url_pfx_router secrets_url_mapping[] = {
|
|
|
bb7cd1 |
+ { SEC_BASEPATH, sec_map_url_to_user_path },
|
|
|
bb7cd1 |
+ { SEC_KCM_BASEPATH, kcm_map_url_to_path },
|
|
|
bb7cd1 |
+ { NULL, NULL },
|
|
|
bb7cd1 |
+};
|
|
|
bb7cd1 |
+
|
|
|
bb7cd1 |
int sec_req_routing(TALLOC_CTX *mem_ctx, struct sec_req_ctx *secreq,
|
|
|
bb7cd1 |
struct provider_handle **handle)
|
|
|
bb7cd1 |
{
|
|
|
bb7cd1 |
@@ -55,21 +96,35 @@ int sec_req_routing(TALLOC_CTX *mem_ctx, struct sec_req_ctx *secreq,
|
|
|
bb7cd1 |
char *provider;
|
|
|
bb7cd1 |
int num_sections;
|
|
|
bb7cd1 |
int ret;
|
|
|
bb7cd1 |
+ url_mapper_fn mapper_fn = NULL;
|
|
|
bb7cd1 |
|
|
|
bb7cd1 |
sctx = talloc_get_type(secreq->cctx->rctx->pvt_ctx, struct sec_ctx);
|
|
|
bb7cd1 |
|
|
|
bb7cd1 |
- /* patch must start with /secrets/ for now */
|
|
|
bb7cd1 |
- ret = strncasecmp(secreq->parsed_url.path,
|
|
|
bb7cd1 |
- SEC_BASEPATH, sizeof(SEC_BASEPATH) - 1);
|
|
|
bb7cd1 |
- if (ret != 0) {
|
|
|
bb7cd1 |
+ for (int i = 0; secrets_url_mapping[i].prefix != NULL; i++) {
|
|
|
bb7cd1 |
+ if (strncasecmp(secreq->parsed_url.path,
|
|
|
bb7cd1 |
+ secrets_url_mapping[i].prefix,
|
|
|
bb7cd1 |
+ strlen(secrets_url_mapping[i].prefix)) == 0) {
|
|
|
bb7cd1 |
+ DEBUG(SSSDBG_TRACE_LIBS,
|
|
|
bb7cd1 |
+ "Mapping prefix %s\n", secrets_url_mapping[i].prefix);
|
|
|
bb7cd1 |
+ mapper_fn = secrets_url_mapping[i].mapper_fn;
|
|
|
bb7cd1 |
+ break;
|
|
|
bb7cd1 |
+ }
|
|
|
bb7cd1 |
+ }
|
|
|
bb7cd1 |
+
|
|
|
bb7cd1 |
+ if (mapper_fn == NULL) {
|
|
|
bb7cd1 |
DEBUG(SSSDBG_CRIT_FAILURE,
|
|
|
bb7cd1 |
- "Path [%s] does not start with "SEC_BASEPATH"\n",
|
|
|
bb7cd1 |
+ "Path [%s] does not start with any allowed prefix\n",
|
|
|
bb7cd1 |
secreq->parsed_url.path);
|
|
|
bb7cd1 |
return EPERM;
|
|
|
bb7cd1 |
}
|
|
|
bb7cd1 |
|
|
|
bb7cd1 |
- ret = sec_map_url_to_user_path(secreq, &secreq->mapped_path);
|
|
|
bb7cd1 |
- if (ret) return ret;
|
|
|
bb7cd1 |
+ ret = mapper_fn(secreq, &secreq->mapped_path);
|
|
|
bb7cd1 |
+ if (ret != EOK) {
|
|
|
bb7cd1 |
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
|
|
bb7cd1 |
+ "Failed to map the user path [%d]: %s\n",
|
|
|
bb7cd1 |
+ ret, sss_strerror(ret));
|
|
|
bb7cd1 |
+ return ret;
|
|
|
bb7cd1 |
+ }
|
|
|
bb7cd1 |
|
|
|
bb7cd1 |
/* source default provider */
|
|
|
bb7cd1 |
ret = confdb_get_string(secreq->cctx->rctx->cdb, mem_ctx,
|
|
|
bb7cd1 |
diff --git a/src/responder/secrets/secsrv_private.h b/src/responder/secrets/secsrv_private.h
|
|
|
bb7cd1 |
index 1c3fbd8eadb237551233f048503ddc01b4ba00ae..a8544f656517a17fe4576247779bff4850beaf97 100644
|
|
|
bb7cd1 |
--- a/src/responder/secrets/secsrv_private.h
|
|
|
bb7cd1 |
+++ b/src/responder/secrets/secsrv_private.h
|
|
|
bb7cd1 |
@@ -101,7 +101,15 @@ int sec_get_provider(struct sec_ctx *sctx, const char *name,
|
|
|
bb7cd1 |
struct provider_handle **out_handle);
|
|
|
bb7cd1 |
int sec_add_provider(struct sec_ctx *sctx, struct provider_handle *handle);
|
|
|
bb7cd1 |
|
|
|
bb7cd1 |
-#define SEC_BASEPATH "/secrets/"
|
|
|
bb7cd1 |
+#define SEC_BASEPATH "/secrets/"
|
|
|
bb7cd1 |
+#define SEC_KCM_BASEPATH "/kcm/"
|
|
|
bb7cd1 |
+
|
|
|
bb7cd1 |
+/* The KCM responder must "impersonate" the owner of the credentials.
|
|
|
bb7cd1 |
+ * Only a trusted UID can do that -- root by default, but unit
|
|
|
bb7cd1 |
+ * tests might choose otherwise */
|
|
|
bb7cd1 |
+#ifndef KCM_PEER_UID
|
|
|
bb7cd1 |
+#define KCM_PEER_UID 0
|
|
|
bb7cd1 |
+#endif /* KCM_PEER_UID */
|
|
|
bb7cd1 |
|
|
|
bb7cd1 |
/* providers.c */
|
|
|
bb7cd1 |
int sec_req_routing(TALLOC_CTX *mem_ctx, struct sec_req_ctx *secreq,
|
|
|
bb7cd1 |
--
|
|
|
bb7cd1 |
2.9.3
|
|
|
bb7cd1 |
|