local.c revision ab7b33fd7d820688545d5994a402cedf4bcdb6e1
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn/*
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn SSSD
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser Secrets Responder
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn Copyright (C) Simo Sorce <ssorce@redhat.com> 2016
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn
acbb59f50d5196facde837ea377f70e98ce1e6f8Serge Hallyn This program is free software; you can redistribute it and/or modify
acbb59f50d5196facde837ea377f70e98ce1e6f8Serge Hallyn it under the terms of the GNU General Public License as published by
acbb59f50d5196facde837ea377f70e98ce1e6f8Serge Hallyn the Free Software Foundation; either version 3 of the License, or
acbb59f50d5196facde837ea377f70e98ce1e6f8Serge Hallyn (at your option) any later version.
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn
acbb59f50d5196facde837ea377f70e98ce1e6f8Serge Hallyn This program is distributed in the hope that it will be useful,
acbb59f50d5196facde837ea377f70e98ce1e6f8Serge Hallyn but WITHOUT ANY WARRANTY; without even the implied warranty of
acbb59f50d5196facde837ea377f70e98ce1e6f8Serge Hallyn MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
acbb59f50d5196facde837ea377f70e98ce1e6f8Serge Hallyn GNU General Public License for more details.
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn
acbb59f50d5196facde837ea377f70e98ce1e6f8Serge Hallyn You should have received a copy of the GNU General Public License
acbb59f50d5196facde837ea377f70e98ce1e6f8Serge Hallyn along with this program. If not, see <http://www.gnu.org/licenses/>.
acbb59f50d5196facde837ea377f70e98ce1e6f8Serge Hallyn*/
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn#include "responder/secrets/secsrv_private.h"
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn#include "util/crypto/sss_crypto.h"
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser#include <time.h>
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser#include <ldb.h>
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser
f2a95ee1bf54c949614a68bf152ea9a8e1d3a172Stéphane Graber#define MKEY_SIZE (256 / 8)
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallynstruct local_context {
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn struct ldb_context *ldb;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn struct sec_data master_key;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn};
1aad9e44d65e7c20dabc4c99f57bcf532db66c68Serge Hallyn
1aad9e44d65e7c20dabc4c99f57bcf532db66c68Serge Hallynint local_decrypt(struct local_context *lctx, TALLOC_CTX *mem_ctx,
1aad9e44d65e7c20dabc4c99f57bcf532db66c68Serge Hallyn const char *secret, const char *enctype,
1aad9e44d65e7c20dabc4c99f57bcf532db66c68Serge Hallyn char **plain_secret)
1aad9e44d65e7c20dabc4c99f57bcf532db66c68Serge Hallyn{
1aad9e44d65e7c20dabc4c99f57bcf532db66c68Serge Hallyn char *output;
1aad9e44d65e7c20dabc4c99f57bcf532db66c68Serge Hallyn
1aad9e44d65e7c20dabc4c99f57bcf532db66c68Serge Hallyn if (enctype && strcmp(enctype, "masterkey") == 0) {
1aad9e44d65e7c20dabc4c99f57bcf532db66c68Serge Hallyn struct sec_data _secret;
1aad9e44d65e7c20dabc4c99f57bcf532db66c68Serge Hallyn size_t outlen;
1aad9e44d65e7c20dabc4c99f57bcf532db66c68Serge Hallyn int ret;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn _secret.data = (char *)sss_base64_decode(mem_ctx, secret,
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn &_secret.length);
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn if (!_secret.data) return EINVAL;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn ret = sss_decrypt(mem_ctx, AES256CBC_HMAC_SHA256,
42ff5f0f8767114d060f5031055038a1a1c3759aSerge Hallyn (uint8_t *)lctx->master_key.data,
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn lctx->master_key.length,
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn (uint8_t *)_secret.data, _secret.length,
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn (uint8_t **)&output, &outlen);
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn if (ret) return ret;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn if (((strnlen(output, outlen) + 1) != outlen) ||
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn output[outlen - 1] != '\0') {
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn return EIO;
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn }
daaf41b36790bdaae855048e56ed090b17a77c97Stéphane Graber } else {
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn output = talloc_strdup(mem_ctx, secret);
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn if (!output) return ENOMEM;
f2a95ee1bf54c949614a68bf152ea9a8e1d3a172Stéphane Graber }
f2a95ee1bf54c949614a68bf152ea9a8e1d3a172Stéphane Graber
f2a95ee1bf54c949614a68bf152ea9a8e1d3a172Stéphane Graber *plain_secret = output;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn return EOK;
f2a95ee1bf54c949614a68bf152ea9a8e1d3a172Stéphane Graber}
f2a95ee1bf54c949614a68bf152ea9a8e1d3a172Stéphane Graber
9313e1e628160ca64f9e7fcec6500056c9a0725fStéphane Graberint local_encrypt(struct local_context *lctx, TALLOC_CTX *mem_ctx,
f2a95ee1bf54c949614a68bf152ea9a8e1d3a172Stéphane Graber const char *secret, const char *enctype,
f2a95ee1bf54c949614a68bf152ea9a8e1d3a172Stéphane Graber char **ciphertext)
f02ce27d4b1a9d01b88d0ffaf626e5bafa671bf0Stéphane Graber{
f2a95ee1bf54c949614a68bf152ea9a8e1d3a172Stéphane Graber struct sec_data _secret;
f2a95ee1bf54c949614a68bf152ea9a8e1d3a172Stéphane Graber char *output;
f2a95ee1bf54c949614a68bf152ea9a8e1d3a172Stéphane Graber int ret;
f2a95ee1bf54c949614a68bf152ea9a8e1d3a172Stéphane Graber
f2a95ee1bf54c949614a68bf152ea9a8e1d3a172Stéphane Graber if (!enctype || strcmp(enctype, "masterkey") != 0) return EINVAL;
f2a95ee1bf54c949614a68bf152ea9a8e1d3a172Stéphane Graber
f2a95ee1bf54c949614a68bf152ea9a8e1d3a172Stéphane Graber ret = sss_encrypt(mem_ctx, AES256CBC_HMAC_SHA256,
f2a95ee1bf54c949614a68bf152ea9a8e1d3a172Stéphane Graber (uint8_t *)lctx->master_key.data,
f2a95ee1bf54c949614a68bf152ea9a8e1d3a172Stéphane Graber lctx->master_key.length,
f2a95ee1bf54c949614a68bf152ea9a8e1d3a172Stéphane Graber (const uint8_t *)secret, strlen(secret) + 1,
f2a95ee1bf54c949614a68bf152ea9a8e1d3a172Stéphane Graber (uint8_t **)&_secret.data, &_secret.length);
57d116ab501594c2e50ab45f1cf2fae48c5eab09Serge Hallyn if (ret) return ret;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn
f2a95ee1bf54c949614a68bf152ea9a8e1d3a172Stéphane Graber output = sss_base64_encode(mem_ctx,
f2a95ee1bf54c949614a68bf152ea9a8e1d3a172Stéphane Graber (uint8_t *)_secret.data, _secret.length);
f2a95ee1bf54c949614a68bf152ea9a8e1d3a172Stéphane Graber if (!output) return ENOMEM;
f2a95ee1bf54c949614a68bf152ea9a8e1d3a172Stéphane Graber
f2a95ee1bf54c949614a68bf152ea9a8e1d3a172Stéphane Graber *ciphertext = output;
f2a95ee1bf54c949614a68bf152ea9a8e1d3a172Stéphane Graber return EOK;
f2a95ee1bf54c949614a68bf152ea9a8e1d3a172Stéphane Graber}
f2a95ee1bf54c949614a68bf152ea9a8e1d3a172Stéphane Graber
f2a95ee1bf54c949614a68bf152ea9a8e1d3a172Stéphane Graberint local_db_dn(TALLOC_CTX *mem_ctx,
bf7d76cf3ae180820c0a29e0bfbaa97c20ce6a3dSerge Hallyn struct ldb_context *ldb,
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn const char *req_path,
f2a95ee1bf54c949614a68bf152ea9a8e1d3a172Stéphane Graber struct ldb_dn **req_dn)
f2a95ee1bf54c949614a68bf152ea9a8e1d3a172Stéphane Graber{
f2a95ee1bf54c949614a68bf152ea9a8e1d3a172Stéphane Graber struct ldb_dn *dn;
f2a95ee1bf54c949614a68bf152ea9a8e1d3a172Stéphane Graber const char *s, *e;
f2a95ee1bf54c949614a68bf152ea9a8e1d3a172Stéphane Graber int ret;
1aad9e44d65e7c20dabc4c99f57bcf532db66c68Serge Hallyn
0a3673e80732ab83d807d406fb2fd3c3b7f54ad3Stéphane Graber dn = ldb_dn_new(mem_ctx, ldb, "cn=secrets");
0a3673e80732ab83d807d406fb2fd3c3b7f54ad3Stéphane Graber if (!dn) {
0a3673e80732ab83d807d406fb2fd3c3b7f54ad3Stéphane Graber ret = ENOMEM;
0a3673e80732ab83d807d406fb2fd3c3b7f54ad3Stéphane Graber goto done;
0a3673e80732ab83d807d406fb2fd3c3b7f54ad3Stéphane Graber }
0a3673e80732ab83d807d406fb2fd3c3b7f54ad3Stéphane Graber
0a3673e80732ab83d807d406fb2fd3c3b7f54ad3Stéphane Graber s = req_path;
0a3673e80732ab83d807d406fb2fd3c3b7f54ad3Stéphane Graber
0a3673e80732ab83d807d406fb2fd3c3b7f54ad3Stéphane Graber while (s && *s) {
0a3673e80732ab83d807d406fb2fd3c3b7f54ad3Stéphane Graber e = strchr(s, '/');
0a3673e80732ab83d807d406fb2fd3c3b7f54ad3Stéphane Graber if (e) {
0a3673e80732ab83d807d406fb2fd3c3b7f54ad3Stéphane Graber if (e == s) {
542939c31bb73bab55f2fd71243b98f5559597d1Stéphane Graber s++;
42ff5f0f8767114d060f5031055038a1a1c3759aSerge Hallyn continue;
42ff5f0f8767114d060f5031055038a1a1c3759aSerge Hallyn }
42ff5f0f8767114d060f5031055038a1a1c3759aSerge Hallyn if (!ldb_dn_add_child_fmt(dn, "cn=%.*s", (int)(e - s), s)) {
5ff337745e4a705293b056ab58f6ea7a92cabbc8Stéphane Graber ret = ENOMEM;
542939c31bb73bab55f2fd71243b98f5559597d1Stéphane Graber goto done;
5ff337745e4a705293b056ab58f6ea7a92cabbc8Stéphane Graber }
42ff5f0f8767114d060f5031055038a1a1c3759aSerge Hallyn s = e + 1;
42ff5f0f8767114d060f5031055038a1a1c3759aSerge Hallyn } else {
42ff5f0f8767114d060f5031055038a1a1c3759aSerge Hallyn if (!ldb_dn_add_child_fmt(dn, "cn=%s", s)) {
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn ret = ENOMEM;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn goto done;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn }
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn s = NULL;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn }
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn }
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn *req_dn = dn;
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn ret = EOK;
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn
1897e3bcd36af9f3fe6d3649910a9adb93e5e988Serge Hallyndone:
3f5f5d99b0ea1c204699b13d4a0caf4d9e745449Stéphane Graber return ret;
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn}
52c8f624b5f9ef665f33a7aa80e0aa18b91daa4aSerge Hallyn
427bffc7a10c9015dc78ef52543f7b8cb9414359Serge Hallynchar *local_dn_to_path(TALLOC_CTX *mem_ctx,
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn struct ldb_dn *basedn,
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser struct ldb_dn *dn)
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser{
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser int basecomps;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn int dncomps;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn char *path = NULL;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn basecomps = ldb_dn_get_comp_num(basedn);
57d116ab501594c2e50ab45f1cf2fae48c5eab09Serge Hallyn dncomps = ldb_dn_get_comp_num(dn);
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn for (int i = dncomps - basecomps; i > 0; i--) {
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn const struct ldb_val *val;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn val = ldb_dn_get_component_val(dn, i - 1);
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn if (!val) return NULL;
57d116ab501594c2e50ab45f1cf2fae48c5eab09Serge Hallyn
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser if (path) {
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser path = talloc_strdup_append_buffer(path, "/");
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn if (!path) return NULL;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn path = talloc_strndup_append_buffer(path, (char *)val->data,
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser val->length);
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser } else {
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser path = talloc_strndup(mem_ctx, (char *)val->data, val->length);
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser }
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser if (!path) return NULL;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn }
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn return path;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn}
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn#define LOCAL_SIMPLE_FILTER "(type=simple)"
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn#define LOCAL_CONTAINER_FILTER "(type=container)"
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn
ed4616b1cfbc84dd01caa8546d813e8c5d482921Christian Bühlerint local_db_get_simple(TALLOC_CTX *mem_ctx,
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn struct local_context *lctx,
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn const char *req_path,
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn char **secret)
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn{
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn TALLOC_CTX *tmp_ctx;
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn static const char *attrs[] = { "secret", "enctype", NULL };
b8bced69a80a8be95fdbbb6b4e9ad7fa85464b1eSerge Hallyn struct ldb_result *res;
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn struct ldb_dn *dn;
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn const char *attr_secret;
8a63c0a9d9089e6365e5a696455476febed39d6aStéphane Graber const char *attr_enctype;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn int ret;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn tmp_ctx = talloc_new(mem_ctx);
52c8f624b5f9ef665f33a7aa80e0aa18b91daa4aSerge Hallyn if (!tmp_ctx) return ENOMEM;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn ret = local_db_dn(tmp_ctx, lctx->ldb, req_path, &dn);
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn if (ret != EOK) goto done;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn
427bffc7a10c9015dc78ef52543f7b8cb9414359Serge Hallyn ret = ldb_search(lctx->ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE,
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser attrs, "%s", LOCAL_SIMPLE_FILTER);
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn if (ret != EOK) {
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn ret = ENOENT;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn goto done;
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn }
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn switch (res->count) {
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn case 0:
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn ret = ENOENT;
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn goto done;
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn case 1:
52c8f624b5f9ef665f33a7aa80e0aa18b91daa4aSerge Hallyn break;
427bffc7a10c9015dc78ef52543f7b8cb9414359Serge Hallyn default:
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser ret = E2BIG;
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser goto done;
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser }
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser attr_secret = ldb_msg_find_attr_as_string(res->msgs[0], "secret", NULL);
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser if (!attr_secret) {
57d116ab501594c2e50ab45f1cf2fae48c5eab09Serge Hallyn ret = ENOENT;
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn goto done;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn }
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn attr_enctype = ldb_msg_find_attr_as_string(res->msgs[0], "enctype", NULL);
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn
57d116ab501594c2e50ab45f1cf2fae48c5eab09Serge Hallyn if (attr_enctype) {
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser ret = local_decrypt(lctx, mem_ctx, attr_secret, attr_enctype, secret);
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser if (ret) goto done;
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn } else {
52c8f624b5f9ef665f33a7aa80e0aa18b91daa4aSerge Hallyn *secret = talloc_strdup(mem_ctx, attr_secret);
52c8f624b5f9ef665f33a7aa80e0aa18b91daa4aSerge Hallyn }
52c8f624b5f9ef665f33a7aa80e0aa18b91daa4aSerge Hallyn ret = EOK;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyndone:
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn talloc_free(tmp_ctx);
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn return ret;
8a63c0a9d9089e6365e5a696455476febed39d6aStéphane Graber}
8a63c0a9d9089e6365e5a696455476febed39d6aStéphane Graber
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallynint local_db_list_keys(TALLOC_CTX *mem_ctx,
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn struct local_context *lctx,
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn const char *req_path,
8a63c0a9d9089e6365e5a696455476febed39d6aStéphane Graber char ***_keys,
8a63c0a9d9089e6365e5a696455476febed39d6aStéphane Graber int *num_keys)
8a63c0a9d9089e6365e5a696455476febed39d6aStéphane Graber{
8a63c0a9d9089e6365e5a696455476febed39d6aStéphane Graber TALLOC_CTX *tmp_ctx;
8a63c0a9d9089e6365e5a696455476febed39d6aStéphane Graber static const char *attrs[] = { "secret", NULL };
8a63c0a9d9089e6365e5a696455476febed39d6aStéphane Graber struct ldb_result *res;
8a63c0a9d9089e6365e5a696455476febed39d6aStéphane Graber struct ldb_dn *dn;
8a63c0a9d9089e6365e5a696455476febed39d6aStéphane Graber char **keys;
8a63c0a9d9089e6365e5a696455476febed39d6aStéphane Graber int ret;
8a63c0a9d9089e6365e5a696455476febed39d6aStéphane Graber
8a63c0a9d9089e6365e5a696455476febed39d6aStéphane Graber tmp_ctx = talloc_new(mem_ctx);
8a63c0a9d9089e6365e5a696455476febed39d6aStéphane Graber if (!tmp_ctx) return ENOMEM;
8a63c0a9d9089e6365e5a696455476febed39d6aStéphane Graber
8a63c0a9d9089e6365e5a696455476febed39d6aStéphane Graber ret = local_db_dn(tmp_ctx, lctx->ldb, req_path, &dn);
8a63c0a9d9089e6365e5a696455476febed39d6aStéphane Graber if (ret != EOK) goto done;
8a63c0a9d9089e6365e5a696455476febed39d6aStéphane Graber
8a63c0a9d9089e6365e5a696455476febed39d6aStéphane Graber ret = ldb_search(lctx->ldb, tmp_ctx, &res, dn, LDB_SCOPE_SUBTREE,
8a63c0a9d9089e6365e5a696455476febed39d6aStéphane Graber attrs, "%s", LOCAL_SIMPLE_FILTER);
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn if (ret != EOK) {
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn ret = ENOENT;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn goto done;
427bffc7a10c9015dc78ef52543f7b8cb9414359Serge Hallyn }
427bffc7a10c9015dc78ef52543f7b8cb9414359Serge Hallyn
427bffc7a10c9015dc78ef52543f7b8cb9414359Serge Hallyn if (res->count == 0) {
427bffc7a10c9015dc78ef52543f7b8cb9414359Serge Hallyn ret = ENOENT;
427bffc7a10c9015dc78ef52543f7b8cb9414359Serge Hallyn goto done;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn }
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn keys = talloc_array(mem_ctx, char *, res->count);
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn if (!keys) {
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn ret = ENOMEM;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn goto done;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn }
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn for (unsigned i = 0; i < res->count; i++) {
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn keys[i] = local_dn_to_path(keys, dn, res->msgs[i]->dn);
1881820ae4ff9004beef1bf7f04553580840441dSerge Hallyn if (!keys[i]) {
1881820ae4ff9004beef1bf7f04553580840441dSerge Hallyn ret = ENOMEM;
1897e3bcd36af9f3fe6d3649910a9adb93e5e988Serge Hallyn goto done;
1897e3bcd36af9f3fe6d3649910a9adb93e5e988Serge Hallyn }
853d58fdf5af0960b7b6edc9dea0fadddb8535f1Elan Ruusamäe }
1897e3bcd36af9f3fe6d3649910a9adb93e5e988Serge Hallyn
1897e3bcd36af9f3fe6d3649910a9adb93e5e988Serge Hallyn *_keys = keys;
1897e3bcd36af9f3fe6d3649910a9adb93e5e988Serge Hallyn *num_keys = res->count;
1881820ae4ff9004beef1bf7f04553580840441dSerge Hallyn ret = EOK;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyndone:
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn talloc_free(tmp_ctx);
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn return ret;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn}
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moserint local_db_check_containers(TALLOC_CTX *mem_ctx,
57d116ab501594c2e50ab45f1cf2fae48c5eab09Serge Hallyn struct local_context *lctx,
57d116ab501594c2e50ab45f1cf2fae48c5eab09Serge Hallyn struct ldb_dn *leaf_dn)
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn{
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn static const char *attrs[] = { NULL};
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn struct ldb_result *res = NULL;
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn struct ldb_dn *dn;
b942e67226af9e690bd63ac440b99aedb6becbb3Scott Moser int num;
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn int ret;
b942e67226af9e690bd63ac440b99aedb6becbb3Scott Moser
b942e67226af9e690bd63ac440b99aedb6becbb3Scott Moser dn = ldb_dn_copy(mem_ctx, leaf_dn);
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn if (!dn) return ENOMEM;
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn /* We need to exclude the leaf as that will be the new child entry,
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn * We also do not care for the synthetic containers that constitute the
f1ccde27c038e7fb7e538913505248b36ddd9e65Serge Hallyn * base path (cn=<uidnumber>,cn=users,cn=secrets), so in total we remove
f1ccde27c038e7fb7e538913505248b36ddd9e65Serge Hallyn * 4 components */
b942e67226af9e690bd63ac440b99aedb6becbb3Scott Moser num = ldb_dn_get_comp_num(dn) - 4;
f1ccde27c038e7fb7e538913505248b36ddd9e65Serge Hallyn
f1ccde27c038e7fb7e538913505248b36ddd9e65Serge Hallyn for (int i = 0; i < num; i++) {
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn /* remove the child first (we do not want to check the leaf) */
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn if (!ldb_dn_remove_child_components(dn, 1)) return EFAULT;
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn /* and check the parent container exists */
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn ret = ldb_search(lctx->ldb, mem_ctx, &res, dn, LDB_SCOPE_BASE,
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn attrs, LOCAL_CONTAINER_FILTER);
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn if (ret != LDB_SUCCESS) return ENOENT;
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn if (res->count != 1) return ENOENT;
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn talloc_free(res);
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn }
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn return EOK;
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn}
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallynint local_db_put_simple(TALLOC_CTX *mem_ctx,
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn struct local_context *lctx,
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn const char *req_path,
edd3810e951ec1b20af761955e6100ab75a66534Serge Hallyn const char *secret)
f1ccde27c038e7fb7e538913505248b36ddd9e65Serge Hallyn{
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn struct ldb_message *msg;
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn const char *enctype = "masterkey";
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn char *enc_secret;
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn int ret;
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn msg = ldb_msg_new(mem_ctx);
9c3bc32c5789b76b8c42b75d7625377d61e052c1Stéphane Graber if (!msg) {
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn ret = ENOMEM;
9c3bc32c5789b76b8c42b75d7625377d61e052c1Stéphane Graber goto done;
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn }
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn ret = local_db_dn(msg, lctx->ldb, req_path, &msg->dn);
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn if (ret != EOK) goto done;
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn
f1ccde27c038e7fb7e538913505248b36ddd9e65Serge Hallyn /* make sure containers exist */
f1ccde27c038e7fb7e538913505248b36ddd9e65Serge Hallyn ret = local_db_check_containers(msg, lctx, msg->dn);
f1ccde27c038e7fb7e538913505248b36ddd9e65Serge Hallyn if (ret != EOK) goto done;
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn ret = local_encrypt(lctx, msg, secret, enctype, &enc_secret);
1aad9e44d65e7c20dabc4c99f57bcf532db66c68Serge Hallyn if (ret != EOK) goto done;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn ret = ldb_msg_add_string(msg, "type", "simple");
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn if (ret != EOK) goto done;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn ret = ldb_msg_add_string(msg, "enctype", enctype);
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn if (ret != EOK) goto done;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn
f1ccde27c038e7fb7e538913505248b36ddd9e65Serge Hallyn ret = ldb_msg_add_string(msg, "secret", enc_secret);
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn if (ret != EOK) goto done;
b942e67226af9e690bd63ac440b99aedb6becbb3Scott Moser
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn ret = ldb_msg_add_fmt(msg, "creationTime", "%lu", time(NULL));
f1ccde27c038e7fb7e538913505248b36ddd9e65Serge Hallyn if (ret != EOK) goto done;
f1ccde27c038e7fb7e538913505248b36ddd9e65Serge Hallyn
f1ccde27c038e7fb7e538913505248b36ddd9e65Serge Hallyn ret = ldb_add(lctx->ldb, msg);
f1ccde27c038e7fb7e538913505248b36ddd9e65Serge Hallyn if (ret != EOK) {
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) ret = EEXIST;
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn else ret = EIO;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn goto done;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn }
57d116ab501594c2e50ab45f1cf2fae48c5eab09Serge Hallyn
57d116ab501594c2e50ab45f1cf2fae48c5eab09Serge Hallyn ret = EOK;
2b142295afb3cac8c4be2a233e51ab5a9f7e10e9Serge Hallyn
57d116ab501594c2e50ab45f1cf2fae48c5eab09Serge Hallyndone:
57d116ab501594c2e50ab45f1cf2fae48c5eab09Serge Hallyn talloc_free(msg);
57d116ab501594c2e50ab45f1cf2fae48c5eab09Serge Hallyn return ret;
1aad9e44d65e7c20dabc4c99f57bcf532db66c68Serge Hallyn}
1aad9e44d65e7c20dabc4c99f57bcf532db66c68Serge Hallyn
1aad9e44d65e7c20dabc4c99f57bcf532db66c68Serge Hallynint local_db_delete(TALLOC_CTX *mem_ctx,
1aad9e44d65e7c20dabc4c99f57bcf532db66c68Serge Hallyn struct local_context *lctx,
1aad9e44d65e7c20dabc4c99f57bcf532db66c68Serge Hallyn const char *req_path)
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser{
1aad9e44d65e7c20dabc4c99f57bcf532db66c68Serge Hallyn TALLOC_CTX *tmp_ctx;
1aad9e44d65e7c20dabc4c99f57bcf532db66c68Serge Hallyn struct ldb_dn *dn;
1aad9e44d65e7c20dabc4c99f57bcf532db66c68Serge Hallyn static const char *attrs[] = { NULL };
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser struct ldb_result *res;
1aad9e44d65e7c20dabc4c99f57bcf532db66c68Serge Hallyn int ret;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn
42ff5f0f8767114d060f5031055038a1a1c3759aSerge Hallyn tmp_ctx = talloc_new(mem_ctx);
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn if (!tmp_ctx) return ENOMEM;
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser ret = local_db_dn(mem_ctx, lctx->ldb, req_path, &dn);
57d116ab501594c2e50ab45f1cf2fae48c5eab09Serge Hallyn if (ret != EOK) goto done;
c01c25fcdd1e0cacad8075bcfcef4c8e8d4b8cb6Stéphane Graber
c01c25fcdd1e0cacad8075bcfcef4c8e8d4b8cb6Stéphane Graber ret = ldb_search(lctx->ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE,
c01c25fcdd1e0cacad8075bcfcef4c8e8d4b8cb6Stéphane Graber attrs, LOCAL_CONTAINER_FILTER);
57d116ab501594c2e50ab45f1cf2fae48c5eab09Serge Hallyn if (ret != EOK) goto done;
57d116ab501594c2e50ab45f1cf2fae48c5eab09Serge Hallyn
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn if (res->count == 1) {
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn ret = ldb_search(lctx->ldb, tmp_ctx, &res, dn, LDB_SCOPE_ONELEVEL,
b942e67226af9e690bd63ac440b99aedb6becbb3Scott Moser attrs, NULL);
b942e67226af9e690bd63ac440b99aedb6becbb3Scott Moser if (ret != EOK) goto done;
if (res->count > 0) {
ret = EEXIST;
DEBUG(SSSDBG_OP_FAILURE,
"Failed to remove '%s': Container is not empty\n",
ldb_dn_get_linearized(dn));
goto done;
}
}
ret = ldb_delete(lctx->ldb, dn);
ret = sysdb_error_to_errno(ret);
done:
talloc_free(tmp_ctx);
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)
{
int ret;
/* be strict for now */
if (secreq->parsed_url.fragment != NULL) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Unrecognized URI fragments: [%s]\n",
secreq->parsed_url.fragment);
return EINVAL;
}
if (secreq->parsed_url.userinfo != NULL) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Unrecognized URI userinfo: [%s]\n",
secreq->parsed_url.userinfo);
return EINVAL;
}
/* only type simple for now */
if (secreq->parsed_url.query != NULL) {
ret = strcmp(secreq->parsed_url.query, "type=simple");
if (ret != 0) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Invalid URI query: [%s]\n",
secreq->parsed_url.query);
return EINVAL;
}
}
/* drop SEC_BASEPATH prefix */
*local_db_path =
talloc_strdup(mem_ctx, &secreq->mapped_path[sizeof(SEC_BASEPATH) - 1]);
if (!*local_db_path) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Failed to map request to local db path\n");
return ENOMEM;
}
return EOK;
}
struct local_secret_state {
struct tevent_context *ev;
struct sec_req_ctx *secreq;
};
struct tevent_req *local_secret_req(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
void *provider_ctx,
struct sec_req_ctx *secreq)
{
struct tevent_req *req;
struct local_secret_state *state;
struct local_context *lctx;
struct sec_data body = { 0 };
const char *content_type;
bool body_is_json;
char *req_path;
char *secret;
char **keys;
int nkeys;
int plen;
int ret;
req = tevent_req_create(mem_ctx, &state, struct local_secret_state);
if (!req) return NULL;
state->ev = ev;
state->secreq = secreq;
lctx = talloc_get_type(provider_ctx, struct local_context);
if (!lctx) {
ret = EIO;
goto done;
}
if (sec_req_has_header(secreq, "Content-Type",
"application/json")) {
body_is_json = true;
content_type = "application/json";
} else if (sec_req_has_header(secreq, "Content-Type",
"application/octet-stream")) {
body_is_json = false;
content_type = "application/octet-stream";
} else {
ret = EINVAL;
goto done;
}
ret = local_secrets_map_path(state, secreq, &req_path);
if (ret) goto done;
switch (secreq->method) {
case HTTP_GET:
if (req_path[strlen(req_path) - 1] == '/') {
ret = local_db_list_keys(state, lctx, req_path, &keys, &nkeys);
if (ret) goto done;
ret = sec_array_to_json(state, keys, nkeys, &body.data);
if (ret) goto done;
body.length = strlen(body.data);
break;
}
ret = local_db_get_simple(state, lctx, req_path, &secret);
if (ret) goto done;
if (body_is_json) {
ret = sec_simple_secret_to_json(state, secret, &body.data);
if (ret) goto done;
body.length = strlen(body.data);
} else {
body.data = (void *)sss_base64_decode(state, secret, &body.length);
ret = body.data ? EOK : ENOMEM;
}
if (ret) goto done;
break;
case HTTP_PUT:
if (body_is_json) {
ret = sec_json_to_simple_secret(state, secreq->body.data,
&secret);
} else {
secret = sss_base64_encode(state, (uint8_t *)secreq->body.data,
secreq->body.length);
ret = secret ? EOK : ENOMEM;
}
if (ret) goto done;
ret = local_db_put_simple(state, lctx, req_path, secret);
if (ret) goto done;
break;
case HTTP_DELETE:
ret = local_db_delete(state, lctx, req_path);
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;
}
if (body.data) {
ret = sec_http_reply_with_body(secreq, &secreq->reply, STATUS_200,
content_type, &body);
} else {
ret = sec_http_status_reply(secreq, &secreq->reply, STATUS_200);
}
done:
if (ret != EOK) {
tevent_req_error(req, ret);
} else {
/* shortcircuit the request here as all called functions are
* synchronous and final and no further subrequests are made */
tevent_req_done(req);
}
return tevent_req_post(req, state->ev);
}
int generate_master_key(const char *filename, size_t size)
{
uint8_t buf[size];
ssize_t rsize;
int ret;
int fd;
ret = generate_csprng_buffer(buf, size);
if (ret) return ret;
fd = open(filename, O_CREAT|O_EXCL|O_WRONLY, 0600);
if (fd == -1) return errno;
rsize = sss_atomic_write_s(fd, buf, size);
close(fd);
if (rsize != size) {
ret = unlink(filename);
/* non-fatal failure */
if (ret != EOK) {
ret = errno;
DEBUG(SSSDBG_MINOR_FAILURE,
"Failed to remove file: %s - %d [%s]!\n",
filename, ret, sss_strerror(ret));
}
return EFAULT;
}
return EOK;
}
int local_secrets_provider_handle(struct sec_ctx *sctx,
struct provider_handle **out_handle)
{
const char *mkey = SECRETS_DB_PATH"/.secrets.mkey";
const char *dbpath = SECRETS_DB_PATH"/secrets.ldb";
struct provider_handle *handle;
struct local_context *lctx;
ssize_t size;
int mfd;
int ret;
handle = talloc_zero(sctx, struct provider_handle);
if (!handle) return ENOMEM;
handle->name = "LOCAL";
handle->fn = local_secret_req;
lctx = talloc_zero(handle, struct local_context);
if (!lctx) return ENOMEM;
lctx->ldb = ldb_init(lctx, NULL);
if (!lctx->ldb) return ENOMEM;
ret = ldb_connect(lctx->ldb, dbpath, 0, NULL);
if (ret != LDB_SUCCESS) {
talloc_free(lctx->ldb);
return EIO;
}
lctx->master_key.data = talloc_size(lctx, MKEY_SIZE);
if (!lctx->master_key.data) return ENOMEM;
lctx->master_key.length = MKEY_SIZE;
ret = check_and_open_readonly(mkey, &mfd, 0, 0,
S_IFREG|S_IRUSR|S_IWUSR, 0);
if (ret == ENOENT) {
ret = generate_master_key(mkey, MKEY_SIZE);
if (ret) return EFAULT;
ret = check_and_open_readonly(mkey, &mfd, 0, 0,
S_IFREG|S_IRUSR|S_IWUSR, 0);
}
if (ret) return EFAULT;
size = sss_atomic_read_s(mfd, lctx->master_key.data,
lctx->master_key.length);
close(mfd);
if (size < 0 || size != lctx->master_key.length) return EIO;
handle->context = lctx;
*out_handle = handle;
return EOK;
}