summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2016-03-17 17:18:02 -0400
committerSimo Sorce <simo@redhat.com>2016-04-05 14:34:14 -0400
commit4183a02c43eee1f74397e0f8eeedc7f66d2db46b (patch)
treed5ecc97f85fd14e90de06e429c0bf26f1f5bfe0e
parentd694dc007a8520ecf0f6d22a1a8f1795047f9b54 (diff)
downloadsssd-4183a02c43eee1f74397e0f8eeedc7f66d2db46b.tar.gz
sssd-4183a02c43eee1f74397e0f8eeedc7f66d2db46b.tar.xz
sssd-4183a02c43eee1f74397e0f8eeedc7f66d2db46b.zip
Secrets: Add local container entries support
The protocol requires a user to creat a container efore trying to store an entry in it. Do the same in the local provider so that no surprises arise when admins route request to a remote storage server. Signed-off-by: Simo Sorce <simo@redhat.com>
-rw-r--r--src/responder/secrets/local.c109
1 files changed, 102 insertions, 7 deletions
diff --git a/src/responder/secrets/local.c b/src/responder/secrets/local.c
index 314dff8f..f2158446 100644
--- a/src/responder/secrets/local.c
+++ b/src/responder/secrets/local.c
@@ -21,6 +21,7 @@
#include "responder/secrets/secsrv_private.h"
#include "util/crypto/sss_crypto.h"
+#include <time.h>
#include <ldb.h>
#define MKEY_SIZE (256 / 8)
@@ -166,6 +167,8 @@ char *local_dn_to_path(TALLOC_CTX *mem_ctx,
return path;
}
+#define LOCAL_SIMPLE_FILTER "(type=simple)"
+
int local_db_get_simple(TALLOC_CTX *mem_ctx,
struct local_context *lctx,
const char *req_path,
@@ -173,7 +176,6 @@ int local_db_get_simple(TALLOC_CTX *mem_ctx,
{
TALLOC_CTX *tmp_ctx;
static const char *attrs[] = { "secret", "enctype", NULL };
- const char *filter = "(type=simple)";
struct ldb_result *res;
struct ldb_dn *dn;
const char *attr_secret;
@@ -187,7 +189,7 @@ int local_db_get_simple(TALLOC_CTX *mem_ctx,
if (ret != EOK) goto done;
ret = ldb_search(lctx->ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE,
- attrs, filter);
+ attrs, LOCAL_SIMPLE_FILTER);
if (ret != EOK) {
ret = ENOENT;
goto done;
@@ -233,7 +235,6 @@ int local_db_list_keys(TALLOC_CTX *mem_ctx,
{
TALLOC_CTX *tmp_ctx;
static const char *attrs[] = { "secret", NULL };
- const char *filter = "(type=simple)";
struct ldb_result *res;
struct ldb_dn *dn;
char **keys;
@@ -246,7 +247,7 @@ int local_db_list_keys(TALLOC_CTX *mem_ctx,
if (ret != EOK) goto done;
ret = ldb_search(lctx->ldb, tmp_ctx, &res, dn, LDB_SCOPE_SUBTREE,
- attrs, filter);
+ attrs, LOCAL_SIMPLE_FILTER);
if (ret != EOK) {
ret = ENOENT;
goto done;
@@ -280,6 +281,40 @@ done:
return ret;
}
+int local_db_check_containers(TALLOC_CTX *mem_ctx,
+ struct local_context *lctx,
+ struct ldb_dn *leaf_dn)
+{
+ static const char *attrs[] = { NULL};
+ struct ldb_result *res = NULL;
+ struct ldb_dn *dn;
+ int num;
+ int ret;
+
+ dn = ldb_dn_copy(mem_ctx, leaf_dn);
+ if (!dn) return ENOMEM;
+
+ /* We need to exclude the leaf as that will be the new child entry,
+ * We also do not care for the synthetic containers that constitute the
+ * base path (cn=<uidnumber>,cn=users,cn=secrets), so in total we remove
+ * 4 components */
+ num = ldb_dn_get_comp_num(dn) - 4;
+
+ for (int i = 0; i < num; i++) {
+ /* remove the child first (we do not want to check the leaf) */
+ if (!ldb_dn_remove_child_components(dn, 1)) return EFAULT;
+
+ /* and check the parent container exists */
+ ret = ldb_search(lctx->ldb, mem_ctx, &res, dn, LDB_SCOPE_BASE,
+ attrs, LOCAL_SIMPLE_FILTER);
+ if (ret != LDB_SUCCESS) return ENOENT;
+ if (res->count != 1) return ENOENT;
+ talloc_free(res);
+ }
+
+ return EOK;
+}
+
int local_db_put_simple(TALLOC_CTX *mem_ctx,
struct local_context *lctx,
const char *req_path,
@@ -296,12 +331,14 @@ int local_db_put_simple(TALLOC_CTX *mem_ctx,
goto done;
}
- /* FIXME: verify containers (except for user's namespace) exists */
+ ret = local_db_dn(msg, lctx->ldb, req_path, &msg->dn);
+ if (ret != EOK) goto done;
- ret = local_encrypt(lctx, msg, secret, enctype, &enc_secret);
+ /* make sure containers exist */
+ ret = local_db_check_containers(msg, lctx, msg->dn);
if (ret != EOK) goto done;
- ret = local_db_dn(msg, lctx->ldb, req_path, &msg->dn);
+ ret = local_encrypt(lctx, msg, secret, enctype, &enc_secret);
if (ret != EOK) goto done;
ret = ldb_msg_add_string(msg, "type", "simple");
@@ -313,6 +350,9 @@ int local_db_put_simple(TALLOC_CTX *mem_ctx,
ret = ldb_msg_add_string(msg, "secret", enc_secret);
if (ret != EOK) goto done;
+ ret = ldb_msg_add_fmt(msg, "creationTime", "%lu", time(NULL));
+ if (ret != EOK) goto done;
+
ret = ldb_add(lctx->ldb, msg);
if (ret != EOK) {
if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) ret = EEXIST;
@@ -346,6 +386,46 @@ done:
return ret;
}
+int local_db_create(TALLOC_CTX *mem_ctx,
+ struct local_context *lctx,
+ const char *req_path)
+{
+ struct ldb_message *msg;
+ int ret;
+
+ msg = ldb_msg_new(mem_ctx);
+ if (!msg) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = local_db_dn(msg, lctx->ldb, req_path, &msg->dn);
+ if (ret != EOK) goto done;
+
+ /* make sure containers exist */
+ ret = local_db_check_containers(msg, lctx, msg->dn);
+ if (ret != EOK) goto done;
+
+ ret = ldb_msg_add_string(msg, "type", "container");
+ if (ret != EOK) goto done;
+
+ ret = ldb_msg_add_fmt(msg, "creationTime", "%lu", time(NULL));
+ if (ret != EOK) goto done;
+
+ ret = ldb_add(lctx->ldb, msg);
+ if (ret != EOK) {
+ if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) ret = EEXIST;
+ else ret = EIO;
+ goto done;
+ }
+
+ ret = EOK;
+
+done:
+ talloc_free(msg);
+ return ret;
+}
+
int local_secrets_map_path(TALLOC_CTX *mem_ctx,
struct sec_req_ctx *secreq,
char **local_db_path)
@@ -411,6 +491,7 @@ struct tevent_req *local_secret_req(TALLOC_CTX *mem_ctx,
char *secret;
char **keys;
int nkeys;
+ int plen;
int ret;
req = tevent_req_create(mem_ctx, &state, struct local_secret_state);
@@ -490,6 +571,20 @@ struct tevent_req *local_secret_req(TALLOC_CTX *mem_ctx,
if (ret) goto done;
break;
+ case HTTP_POST:
+ plen = strlen(req_path);
+
+ if (req_path[plen - 1] != '/') {
+ ret = EINVAL;
+ goto done;
+ }
+
+ req_path[plen - 1] = '\0';
+
+ ret = local_db_create(state, lctx, req_path);
+ if (ret) goto done;
+ break;
+
default:
ret = EINVAL;
goto done;