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