local.c revision 7128fadade544efcd86b113a5090b00d20993671
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/*
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen SSSD
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen Secrets Responder
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen Copyright (C) Simo Sorce <ssorce@redhat.com> 2016
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen This program is free software; you can redistribute it and/or modify
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen it under the terms of the GNU General Public License as published by
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen the Free Software Foundation; either version 3 of the License, or
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen (at your option) any later version.
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen This program is distributed in the hope that it will be useful,
2cd2518bab14292a67cf8a490b58ab9ef89879daTimo Sirainen but WITHOUT ANY WARRANTY; without even the implied warranty of
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen GNU General Public License for more details.
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen You should have received a copy of the GNU General Public License
6ec925f52d04ec8700e47cb005bd7ddc65ac5614Timo Sirainen along with this program. If not, see <http://www.gnu.org/licenses/>.
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen*/
4d4d6d4745682790c20d759ba93dbea46b812c5dTimo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "responder/secrets/secsrv_private.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "util/crypto/sss_crypto.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include <time.h>
cf2e6953d03a1c22f272ec19432fc03c136ac1bbTimo Sirainen#include <ldb.h>
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#define MKEY_SIZE (256 / 8)
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstruct local_context {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct ldb_context *ldb;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct sec_data master_key;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen int containers_nest_level;
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen};
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic int local_decrypt(struct local_context *lctx, TALLOC_CTX *mem_ctx,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const char *secret, const char *enctype,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen char **plain_secret)
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen{
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen char *output;
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen if (enctype && strcmp(enctype, "masterkey") == 0) {
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen DEBUG(SSSDBG_TRACE_INTERNAL, "Decrypting with masterkey\n");
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen struct sec_data _secret;
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen size_t outlen;
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen int ret;
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen _secret.data = (char *)sss_base64_decode(mem_ctx, secret,
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen &_secret.length);
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen if (!_secret.data) {
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen DEBUG(SSSDBG_OP_FAILURE, "sss_base64_decode failed\n");
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen return EINVAL;
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen }
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen ret = sss_decrypt(mem_ctx, AES256CBC_HMAC_SHA256,
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen (uint8_t *)lctx->master_key.data,
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen lctx->master_key.length,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen (uint8_t *)_secret.data, _secret.length,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen (uint8_t **)&output, &outlen);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (ret) {
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen DEBUG(SSSDBG_OP_FAILURE,
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen "sss_decrypt failed [%d]: %s\n", ret, sss_strerror(ret));
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen return ret;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (((strnlen(output, outlen) + 1) != outlen) ||
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen output[outlen - 1] != '\0') {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "Output length mismatch or output not NULL-terminated\n");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return EIO;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen } else {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen output = talloc_strdup(mem_ctx, secret);
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen if (!output) return ENOMEM;
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen }
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen *plain_secret = output;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen return EOK;
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen}
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainenstatic int local_encrypt(struct local_context *lctx, TALLOC_CTX *mem_ctx,
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen const char *secret, const char *enctype,
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen char **ciphertext)
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen{
230ef558135f16a66b86cbe3762524eaa9ae9d81Timo Sirainen struct sec_data _secret;
230ef558135f16a66b86cbe3762524eaa9ae9d81Timo Sirainen char *output;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen int ret;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen if (enctype == NULL) {
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "No encryption type\n");
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen return EINVAL;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen }
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen if (strcmp(enctype, "masterkey") != 0) {
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "Uknown encryption type '%s'\n", enctype);
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen return EINVAL;
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen }
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen ret = sss_encrypt(mem_ctx, AES256CBC_HMAC_SHA256,
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen (uint8_t *)lctx->master_key.data,
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen lctx->master_key.length,
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen (const uint8_t *)secret, strlen(secret) + 1,
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen (uint8_t **)&_secret.data, &_secret.length);
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen if (ret) {
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen DEBUG(SSSDBG_OP_FAILURE,
d03a871a77f8ec36f48f5fea98d810e51b186fdbTimo Sirainen "sss_encrypt failed [%d]: %s\n", ret, sss_strerror(ret));
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen return ret;
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen }
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen output = sss_base64_encode(mem_ctx,
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen (uint8_t *)_secret.data, _secret.length);
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen if (!output) return ENOMEM;
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen *ciphertext = output;
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen return EOK;
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen}
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen
d03a871a77f8ec36f48f5fea98d810e51b186fdbTimo Sirainenstatic int local_db_dn(TALLOC_CTX *mem_ctx,
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen struct ldb_context *ldb,
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen const char *req_path,
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen struct ldb_dn **req_dn)
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen{
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen struct ldb_dn *dn;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const char *s, *e;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen int ret;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen dn = ldb_dn_new(mem_ctx, ldb, "cn=secrets");
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen if (!dn) {
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen ret = ENOMEM;
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen goto done;
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen }
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen s = req_path;
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen while (s && *s) {
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen e = strchr(s, '/');
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen if (e) {
dc07b75b7ea83ff5f447970a20419032725271a7Timo Sirainen if (e == s) {
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen s++;
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen continue;
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen }
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen if (!ldb_dn_add_child_fmt(dn, "cn=%.*s", (int)(e - s), s)) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = ENOMEM;
29f32cdcf44cda9688576bfdc7450a8a15e90e86Timo Sirainen goto done;
29f32cdcf44cda9688576bfdc7450a8a15e90e86Timo Sirainen }
29f32cdcf44cda9688576bfdc7450a8a15e90e86Timo Sirainen s = e + 1;
29f32cdcf44cda9688576bfdc7450a8a15e90e86Timo Sirainen } else {
29f32cdcf44cda9688576bfdc7450a8a15e90e86Timo Sirainen if (!ldb_dn_add_child_fmt(dn, "cn=%s", s)) {
29f32cdcf44cda9688576bfdc7450a8a15e90e86Timo Sirainen ret = ENOMEM;
29f32cdcf44cda9688576bfdc7450a8a15e90e86Timo Sirainen goto done;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
b955a1c1b6d466977d971c029a9305bee492f73cTimo Sirainen s = NULL;
b955a1c1b6d466977d971c029a9305bee492f73cTimo Sirainen }
b955a1c1b6d466977d971c029a9305bee492f73cTimo Sirainen }
b955a1c1b6d466977d971c029a9305bee492f73cTimo Sirainen
b955a1c1b6d466977d971c029a9305bee492f73cTimo Sirainen DEBUG(SSSDBG_TRACE_INTERNAL,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "Local path for [%s] is [%s]\n",
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen req_path, ldb_dn_get_linearized(dn));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *req_dn = dn;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = EOK;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainendone:
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return ret;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic char *local_dn_to_path(TALLOC_CTX *mem_ctx,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct ldb_dn *basedn,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct ldb_dn *dn)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen int basecomps;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen int dncomps;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen char *path = NULL;
601b455f4d5e780044b9e4fac5f687c1b07ae145Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen basecomps = ldb_dn_get_comp_num(basedn);
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen dncomps = ldb_dn_get_comp_num(dn);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen for (int i = dncomps - basecomps; i > 0; i--) {
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen const struct ldb_val *val;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen val = ldb_dn_get_component_val(dn, i - 1);
fb7ac3e31c92627efe076318319976ac1c27ae2aTimo Sirainen if (!val) return NULL;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (path) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen path = talloc_strdup_append_buffer(path, "/");
72cc352b25ad401b923436c6ed0f1f3adaffa737Timo Sirainen if (!path) return NULL;
e1f866daa1bd1a5cd7516f3b19c6f197bcf6cc8aTimo Sirainen path = talloc_strndup_append_buffer(path, (char *)val->data,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen val->length);
614529ee060755c0b282102b70daf56bcd64222dTimo Sirainen } else {
9ebd0c59de5f8240c0dbc58773fe5679391199dbTimo Sirainen path = talloc_strndup(mem_ctx, (char *)val->data, val->length);
6ec925f52d04ec8700e47cb005bd7ddc65ac5614Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (!path) return NULL;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DEBUG(SSSDBG_TRACE_INTERNAL,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "Secrets path for [%s] is [%s]\n",
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ldb_dn_get_linearized(dn), path);
e1f866daa1bd1a5cd7516f3b19c6f197bcf6cc8aTimo Sirainen return path;
e1f866daa1bd1a5cd7516f3b19c6f197bcf6cc8aTimo Sirainen}
e1f866daa1bd1a5cd7516f3b19c6f197bcf6cc8aTimo Sirainen
e1f866daa1bd1a5cd7516f3b19c6f197bcf6cc8aTimo Sirainen#define LOCAL_SIMPLE_FILTER "(type=simple)"
e1f866daa1bd1a5cd7516f3b19c6f197bcf6cc8aTimo Sirainen#define LOCAL_CONTAINER_FILTER "(type=container)"
e1f866daa1bd1a5cd7516f3b19c6f197bcf6cc8aTimo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic int local_db_get_simple(TALLOC_CTX *mem_ctx,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct local_context *lctx,
4b2a1030f9b51e90f6ff4cdbc115871a398c1e0fTimo Sirainen const char *req_path,
72cc352b25ad401b923436c6ed0f1f3adaffa737Timo Sirainen char **secret)
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen{
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen TALLOC_CTX *tmp_ctx;
72cc352b25ad401b923436c6ed0f1f3adaffa737Timo Sirainen static const char *attrs[] = { "secret", "enctype", NULL };
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct ldb_result *res;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct ldb_dn *dn;
9e291f6a7ca67b86d1d65a730ffb71fb9a334fb0Timo Sirainen const char *attr_secret;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const char *attr_enctype;
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen int ret;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DEBUG(SSSDBG_TRACE_FUNC, "Retrieving a secret from [%s]\n", req_path);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen tmp_ctx = talloc_new(mem_ctx);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (!tmp_ctx) return ENOMEM;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = local_db_dn(tmp_ctx, lctx->ldb, req_path, &dn);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (ret != EOK) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DEBUG(SSSDBG_OP_FAILURE,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "local_db_dn failed [%d]: %s\n", ret, sss_strerror(ret));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen goto done;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
f5e1d3d6b34ec152aa1ff15c7bd3d3552e9227eaTimo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DEBUG(SSSDBG_TRACE_INTERNAL,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "Searching for [%s] at [%s] with scope=base\n",
f29756821a4c6b12b73e4a2a3e1c230117a43773Timo Sirainen LOCAL_SIMPLE_FILTER, ldb_dn_get_linearized(dn));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = ldb_search(lctx->ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen attrs, "%s", LOCAL_SIMPLE_FILTER);
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen if (ret != EOK) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DEBUG(SSSDBG_TRACE_LIBS,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "ldb_search returned [%d]: %s\n", ret, ldb_strerror(ret));
5d46f4d076fc13ae2779c365cf4bd9bda3a5bc69Timo Sirainen ret = ENOENT;
5d46f4d076fc13ae2779c365cf4bd9bda3a5bc69Timo Sirainen goto done;
5d46f4d076fc13ae2779c365cf4bd9bda3a5bc69Timo Sirainen }
5d46f4d076fc13ae2779c365cf4bd9bda3a5bc69Timo Sirainen
5d46f4d076fc13ae2779c365cf4bd9bda3a5bc69Timo Sirainen switch (res->count) {
5d46f4d076fc13ae2779c365cf4bd9bda3a5bc69Timo Sirainen case 0:
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DEBUG(SSSDBG_TRACE_LIBS, "No secret found\n");
d482079eb385cd071bbc9637cacee225e4aff968Timo Sirainen ret = ENOENT;
9e291f6a7ca67b86d1d65a730ffb71fb9a334fb0Timo Sirainen goto done;
3a0f9aa9504497e4e47f32df54fbf47fdc7423b6Timo Sirainen case 1:
3a0f9aa9504497e4e47f32df54fbf47fdc7423b6Timo Sirainen break;
1ffb2afe6d7e8860a2231a4827078cf2ef9c22cdTimo Sirainen default:
1ffb2afe6d7e8860a2231a4827078cf2ef9c22cdTimo Sirainen DEBUG(SSSDBG_OP_FAILURE,
d4845c4245638fd6f02dc0cb92c3465fae763cbbTimo Sirainen "Too many secrets returned with BASE search\n");
d4845c4245638fd6f02dc0cb92c3465fae763cbbTimo Sirainen ret = E2BIG;
0161376aac025266d8654577c4b9ce371ffc87eaTimo Sirainen goto done;
0161376aac025266d8654577c4b9ce371ffc87eaTimo Sirainen }
788f275469ad9ed530e440d6690d0e4381a323b2Timo Sirainen
788f275469ad9ed530e440d6690d0e4381a323b2Timo Sirainen attr_secret = ldb_msg_find_attr_as_string(res->msgs[0], "secret", NULL);
788f275469ad9ed530e440d6690d0e4381a323b2Timo Sirainen if (!attr_secret) {
788f275469ad9ed530e440d6690d0e4381a323b2Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "The 'secret' attribute is missing\n");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = ENOENT;
a8aec60b5359e5ea7fc7a9464217ae3626df8785Timo Sirainen goto done;
a8aec60b5359e5ea7fc7a9464217ae3626df8785Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen attr_enctype = ldb_msg_find_attr_as_string(res->msgs[0], "enctype", NULL);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
43d7e7ce608f5451e4907b5f5c48c00beb265802Timo Sirainen if (attr_enctype) {
0547a828ee9647fc5fd2e359b145774740a697feTimo Sirainen ret = local_decrypt(lctx, mem_ctx, attr_secret, attr_enctype, secret);
43d7e7ce608f5451e4907b5f5c48c00beb265802Timo Sirainen if (ret) goto done;
43d7e7ce608f5451e4907b5f5c48c00beb265802Timo Sirainen } else {
43d7e7ce608f5451e4907b5f5c48c00beb265802Timo Sirainen *secret = talloc_strdup(mem_ctx, attr_secret);
43d7e7ce608f5451e4907b5f5c48c00beb265802Timo Sirainen }
43d7e7ce608f5451e4907b5f5c48c00beb265802Timo Sirainen ret = EOK;
5d46f4d076fc13ae2779c365cf4bd9bda3a5bc69Timo Sirainen
5d46f4d076fc13ae2779c365cf4bd9bda3a5bc69Timo Sirainendone:
5d46f4d076fc13ae2779c365cf4bd9bda3a5bc69Timo Sirainen talloc_free(tmp_ctx);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return ret;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic int local_db_list_keys(TALLOC_CTX *mem_ctx,
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen struct local_context *lctx,
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen const char *req_path,
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen char ***_keys,
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen int *num_keys)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen TALLOC_CTX *tmp_ctx;
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen static const char *attrs[] = { "secret", NULL };
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct ldb_result *res;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct ldb_dn *dn;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen char **keys;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen int ret;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen tmp_ctx = talloc_new(mem_ctx);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (!tmp_ctx) return ENOMEM;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DEBUG(SSSDBG_TRACE_FUNC, "Listing keys at [%s]\n", req_path);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen ret = local_db_dn(tmp_ctx, lctx->ldb, req_path, &dn);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (ret != EOK) {
601b455f4d5e780044b9e4fac5f687c1b07ae145Timo Sirainen DEBUG(SSSDBG_OP_FAILURE,
601b455f4d5e780044b9e4fac5f687c1b07ae145Timo Sirainen "local_db_dn failed [%d]: %s\n", ret, sss_strerror(ret));
cdc8485491045d82bb98405d4b995f277d12838eTimo Sirainen goto done;
cdc8485491045d82bb98405d4b995f277d12838eTimo Sirainen }
b2ed2b25c4c457ec1c99ebe5e9bd66a2e2f89cfdTimo Sirainen
b2ed2b25c4c457ec1c99ebe5e9bd66a2e2f89cfdTimo Sirainen DEBUG(SSSDBG_TRACE_INTERNAL,
e5097d2c8efecdd274272b222cf2b30a8ae4ca2aTimo Sirainen "Searching for [%s] at [%s] with scope=subtree\n",
e5097d2c8efecdd274272b222cf2b30a8ae4ca2aTimo Sirainen LOCAL_SIMPLE_FILTER, ldb_dn_get_linearized(dn));
e5097d2c8efecdd274272b222cf2b30a8ae4ca2aTimo Sirainen
e5097d2c8efecdd274272b222cf2b30a8ae4ca2aTimo Sirainen ret = ldb_search(lctx->ldb, tmp_ctx, &res, dn, LDB_SCOPE_SUBTREE,
e5097d2c8efecdd274272b222cf2b30a8ae4ca2aTimo Sirainen attrs, "%s", LOCAL_SIMPLE_FILTER);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (ret != EOK) {
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen DEBUG(SSSDBG_TRACE_LIBS,
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen "ldb_search returned [%d]: %s\n", ret, ldb_strerror(ret));
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen ret = ENOENT;
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen goto done;
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen }
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen if (res->count == 0) {
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen DEBUG(SSSDBG_TRACE_LIBS, "No secrets found\n");
e7a4c77db3a37224b91e16d139fa80ce67dc37ffTimo Sirainen ret = ENOENT;
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen goto done;
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen keys = talloc_array(mem_ctx, char *, res->count);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (!keys) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = ENOMEM;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen goto done;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen for (unsigned i = 0; i < res->count; i++) {
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen keys[i] = local_dn_to_path(keys, dn, res->msgs[i]->dn);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen if (!keys[i]) {
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen ret = ENOMEM;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen goto done;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen }
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *_keys = keys;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DEBUG(SSSDBG_TRACE_LIBS, "Returning %d secrets\n", res->count);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *num_keys = res->count;
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen ret = EOK;
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainendone:
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen talloc_free(tmp_ctx);
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen return ret;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
3a0f9aa9504497e4e47f32df54fbf47fdc7423b6Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic int local_db_check_containers(TALLOC_CTX *mem_ctx,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct local_context *lctx,
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen struct ldb_dn *leaf_dn)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen TALLOC_CTX *tmp_ctx;
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen static const char *attrs[] = { NULL};
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen struct ldb_result *res = NULL;
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen struct ldb_dn *dn;
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen int num;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen int ret;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen tmp_ctx = talloc_new(mem_ctx);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (!tmp_ctx) return ENOMEM;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen dn = ldb_dn_copy(tmp_ctx, leaf_dn);
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen if (!dn) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = ENOMEM;
2cd2518bab14292a67cf8a490b58ab9ef89879daTimo Sirainen goto done;
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* We need to exclude the leaf as that will be the new child entry,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen * We also do not care for the synthetic containers that constitute the
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen * base path (cn=<uidnumber>,cn=users,cn=secrets), so in total we remove
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen * 4 components */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen num = ldb_dn_get_comp_num(dn) - 4;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen for (int i = 0; i < num; i++) {
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen /* remove the child first (we do not want to check the leaf) */
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen if (!ldb_dn_remove_child_components(dn, 1)) return EFAULT;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen /* and check the parent container exists */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DEBUG(SSSDBG_TRACE_INTERNAL,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "Searching for [%s] at [%s] with scope=base\n",
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen LOCAL_CONTAINER_FILTER, ldb_dn_get_linearized(dn));
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen ret = ldb_search(lctx->ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE,
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen attrs, LOCAL_CONTAINER_FILTER);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen if (ret != LDB_SUCCESS || res->count != 1) {
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen DEBUG(SSSDBG_TRACE_LIBS,
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen "DN [%s] does not exist\n", ldb_dn_get_linearized(dn));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return ENOENT;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = EOK;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainendone:
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen talloc_free(tmp_ctx);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return ret;
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic int local_db_check_containers_nest_level(struct local_context *lctx,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct ldb_dn *leaf_dn)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen int nest_level;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* We need do not care for the synthetic containers that constitute the
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen * base path (cn=<uidnumber>,cn=user,cn=secrets). */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen nest_level = ldb_dn_get_comp_num(leaf_dn) - 3;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (nest_level > lctx->containers_nest_level) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DEBUG(SSSDBG_OP_FAILURE,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "Cannot create a nested container of depth %d as the maximum"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "allowed number of nested containers is %d.\n",
077ab4470660b791c2b76eb4bb5663bbafc8177fTimo Sirainen nest_level, lctx->containers_nest_level);
077ab4470660b791c2b76eb4bb5663bbafc8177fTimo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return ERR_SEC_INVALID_CONTAINERS_NEST_LEVEL;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return EOK;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic int local_db_put_simple(TALLOC_CTX *mem_ctx,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct local_context *lctx,
077ab4470660b791c2b76eb4bb5663bbafc8177fTimo Sirainen const char *req_path,
077ab4470660b791c2b76eb4bb5663bbafc8177fTimo Sirainen const char *secret)
077ab4470660b791c2b76eb4bb5663bbafc8177fTimo Sirainen{
077ab4470660b791c2b76eb4bb5663bbafc8177fTimo Sirainen struct ldb_message *msg;
077ab4470660b791c2b76eb4bb5663bbafc8177fTimo Sirainen const char *enctype = "masterkey";
077ab4470660b791c2b76eb4bb5663bbafc8177fTimo Sirainen char *enc_secret;
077ab4470660b791c2b76eb4bb5663bbafc8177fTimo Sirainen int ret;
077ab4470660b791c2b76eb4bb5663bbafc8177fTimo Sirainen
077ab4470660b791c2b76eb4bb5663bbafc8177fTimo Sirainen msg = ldb_msg_new(mem_ctx);
077ab4470660b791c2b76eb4bb5663bbafc8177fTimo Sirainen if (!msg) {
077ab4470660b791c2b76eb4bb5663bbafc8177fTimo Sirainen ret = ENOMEM;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen goto done;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DEBUG(SSSDBG_TRACE_FUNC, "Adding a secret to [%s]\n", req_path);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = local_db_dn(msg, lctx->ldb, req_path, &msg->dn);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (ret != EOK) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DEBUG(SSSDBG_OP_FAILURE,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "local_db_dn failed [%d]: %s\n", ret, sss_strerror(ret));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen goto done;
129db31de1780783a175633eba5811e44c361a81Timo Sirainen }
129db31de1780783a175633eba5811e44c361a81Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* make sure containers exist */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = local_db_check_containers(msg, lctx, msg->dn);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (ret != EOK) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DEBUG(SSSDBG_OP_FAILURE,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "local_db_check_containers failed for [%s]: [%d]: %s\n",
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ldb_dn_get_linearized(msg->dn), ret, sss_strerror(ret));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen goto done;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = local_encrypt(lctx, msg, secret, enctype, &enc_secret);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (ret != EOK) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DEBUG(SSSDBG_OP_FAILURE,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "local_encrypt failed [%d]: %s\n", ret, sss_strerror(ret));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen goto done;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = ldb_msg_add_string(msg, "type", "simple");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (ret != EOK) {
63849db64682675a2fd3e1aea05c10ecbc6d473aTimo Sirainen DEBUG(SSSDBG_OP_FAILURE,
114162093a3eb36c23a4ce4d4f2a43541dc18cc2Timo Sirainen "ldb_msg_add_string failed adding type:simple [%d]: %s\n",
ca502ca792708238ac2c23481c3bf94eda1f743fTimo Sirainen ret, sss_strerror(ret));
ca502ca792708238ac2c23481c3bf94eda1f743fTimo Sirainen goto done;
ca502ca792708238ac2c23481c3bf94eda1f743fTimo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = ldb_msg_add_string(msg, "enctype", enctype);
114162093a3eb36c23a4ce4d4f2a43541dc18cc2Timo Sirainen if (ret != EOK) {
ca502ca792708238ac2c23481c3bf94eda1f743fTimo Sirainen DEBUG(SSSDBG_OP_FAILURE,
ca502ca792708238ac2c23481c3bf94eda1f743fTimo Sirainen "ldb_msg_add_string failed adding enctype [%d]: %s\n",
ca502ca792708238ac2c23481c3bf94eda1f743fTimo Sirainen ret, sss_strerror(ret));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen goto done;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
63849db64682675a2fd3e1aea05c10ecbc6d473aTimo Sirainen
129db31de1780783a175633eba5811e44c361a81Timo Sirainen ret = ldb_msg_add_string(msg, "secret", enc_secret);
129db31de1780783a175633eba5811e44c361a81Timo Sirainen if (ret != EOK) {
dfcc56dc6c485fe45a3fa18325f047bfaae65019Timo Sirainen DEBUG(SSSDBG_OP_FAILURE,
dfcc56dc6c485fe45a3fa18325f047bfaae65019Timo Sirainen "ldb_msg_add_string failed adding secret [%d]: %s\n",
63849db64682675a2fd3e1aea05c10ecbc6d473aTimo Sirainen ret, sss_strerror(ret));
63849db64682675a2fd3e1aea05c10ecbc6d473aTimo Sirainen goto done;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = ldb_msg_add_fmt(msg, "creationTime", "%lu", time(NULL));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (ret != EOK) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DEBUG(SSSDBG_OP_FAILURE,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "ldb_msg_add_string failed adding creationTime [%d]: %s\n",
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret, sss_strerror(ret));
9c8f854d95d8d895022a75f140a0a500eb200d39Timo Sirainen goto done;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = ldb_add(lctx->ldb, msg);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (ret != EOK) {
9c8f854d95d8d895022a75f140a0a500eb200d39Timo Sirainen if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DEBUG(SSSDBG_OP_FAILURE,
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen "Secret %s already exists\n", ldb_dn_get_linearized(msg->dn));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = EEXIST;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen } else {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "Failed to add secret [%s]: [%d]: %s\n",
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ldb_dn_get_linearized(msg->dn), ret, ldb_strerror(ret));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = EIO;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen goto done;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = EOK;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainendone:
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen talloc_free(msg);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return ret;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic int local_db_delete(TALLOC_CTX *mem_ctx,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct local_context *lctx,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const char *req_path)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen TALLOC_CTX *tmp_ctx;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct ldb_dn *dn;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen static const char *attrs[] = { NULL };
9c8f854d95d8d895022a75f140a0a500eb200d39Timo Sirainen struct ldb_result *res;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen int ret;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DEBUG(SSSDBG_TRACE_FUNC, "Removing a secret from [%s]\n", req_path);
9c8f854d95d8d895022a75f140a0a500eb200d39Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen tmp_ctx = talloc_new(mem_ctx);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (!tmp_ctx) return ENOMEM;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
800fc30be46bc6f8380f6de04aea7c19ea839ddfTimo Sirainen ret = local_db_dn(mem_ctx, lctx->ldb, req_path, &dn);
9c8f854d95d8d895022a75f140a0a500eb200d39Timo Sirainen if (ret != EOK) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DEBUG(SSSDBG_OP_FAILURE,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "local_db_dn failed [%d]: %s\n", ret, sss_strerror(ret));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen goto done;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
800fc30be46bc6f8380f6de04aea7c19ea839ddfTimo Sirainen DEBUG(SSSDBG_TRACE_INTERNAL,
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen "Searching for [%s] at [%s] with scope=base\n",
800fc30be46bc6f8380f6de04aea7c19ea839ddfTimo Sirainen LOCAL_CONTAINER_FILTER, ldb_dn_get_linearized(dn));
800fc30be46bc6f8380f6de04aea7c19ea839ddfTimo Sirainen
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen ret = ldb_search(lctx->ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE,
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen attrs, LOCAL_CONTAINER_FILTER);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (ret != EOK) {
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen DEBUG(SSSDBG_TRACE_LIBS,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "ldb_search returned %d: %s\n", ret, ldb_strerror(ret));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen goto done;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (res->count == 1) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DEBUG(SSSDBG_TRACE_INTERNAL,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "Searching for children of [%s]\n", ldb_dn_get_linearized(dn));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = ldb_search(lctx->ldb, tmp_ctx, &res, dn, LDB_SCOPE_ONELEVEL,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen attrs, NULL);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (ret != EOK) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DEBUG(SSSDBG_TRACE_LIBS,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "ldb_search returned %d: %s\n", ret, ldb_strerror(ret));
9c8f854d95d8d895022a75f140a0a500eb200d39Timo Sirainen goto done;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
9c8f854d95d8d895022a75f140a0a500eb200d39Timo Sirainen
9c8f854d95d8d895022a75f140a0a500eb200d39Timo Sirainen if (res->count > 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = EEXIST;
9c8f854d95d8d895022a75f140a0a500eb200d39Timo Sirainen DEBUG(SSSDBG_OP_FAILURE,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "Failed to remove '%s': Container is not empty\n",
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ldb_dn_get_linearized(dn));
goto done;
}
}
ret = ldb_delete(lctx->ldb, dn);
if (ret != EOK) {
DEBUG(SSSDBG_TRACE_LIBS,
"ldb_delete returned %d: %s\n", ret, ldb_strerror(ret));
/* fallthrough */
}
ret = sysdb_error_to_errno(ret);
done:
talloc_free(tmp_ctx);
return ret;
}
static 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;
}
DEBUG(SSSDBG_TRACE_FUNC, "Creating a container at [%s]\n", req_path);
ret = local_db_dn(msg, lctx->ldb, req_path, &msg->dn);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"local_db_dn failed [%d]: %s\n", ret, sss_strerror(ret));
goto done;
}
/* make sure containers exist */
ret = local_db_check_containers(msg, lctx, msg->dn);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"local_db_check_containers failed for [%s]: [%d]: %s\n",
ldb_dn_get_linearized(msg->dn), ret, sss_strerror(ret));
goto done;
}
ret = local_db_check_containers_nest_level(lctx, msg->dn);
if (ret != EOK) goto done;
ret = ldb_msg_add_string(msg, "type", "container");
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"ldb_msg_add_string failed adding type:container [%d]: %s\n",
ret, sss_strerror(ret));
goto done;
}
ret = ldb_msg_add_fmt(msg, "creationTime", "%lu", time(NULL));
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"ldb_msg_add_string failed adding creationTime [%d]: %s\n",
ret, sss_strerror(ret));
goto done;
}
ret = ldb_add(lctx->ldb, msg);
if (ret != EOK) {
if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
DEBUG(SSSDBG_OP_FAILURE,
"Secret %s already exists\n", ldb_dn_get_linearized(msg->dn));
ret = EEXIST;
} else {
DEBUG(SSSDBG_CRIT_FAILURE,
"Failed to add secret [%s]: [%d]: %s\n",
ldb_dn_get_linearized(msg->dn), ret, ldb_strerror(ret));
ret = EIO;
}
goto done;
}
ret = EOK;
done:
talloc_free(msg);
return ret;
}
static 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;
}
DEBUG(SSSDBG_TRACE_LIBS, "Local DB path is %s\n", *local_db_path);
return EOK;
}
struct local_secret_state {
struct tevent_context *ev;
struct sec_req_ctx *secreq;
};
static 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;
}
DEBUG(SSSDBG_TRACE_INTERNAL, "Received a local secrets request\n");
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 {
DEBUG(SSSDBG_OP_FAILURE, "No or uknown Content-Type\n");
ret = EINVAL;
goto done;
}
DEBUG(SSSDBG_TRACE_LIBS, "Content-Type: %s\n", content_type);
ret = local_secrets_map_path(state, secreq, &req_path);
if (ret) goto done;
switch (secreq->method) {
case HTTP_GET:
DEBUG(SSSDBG_TRACE_LIBS, "Processing HTTP GET at [%s]\n", req_path);
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:
DEBUG(SSSDBG_TRACE_LIBS, "Processing HTTP PUT at [%s]\n", req_path);
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:
DEBUG(SSSDBG_TRACE_LIBS, "Processing HTTP POST at [%s]\n", req_path);
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) {
if (ret == ENOENT) {
DEBUG(SSSDBG_TRACE_LIBS, "Did not find the requested data\n");
} else {
DEBUG(SSSDBG_OP_FAILURE,
"Local secrets request error [%d]: %s\n",
ret, sss_strerror(ret));
}
tevent_req_error(req, ret);
} else {
/* shortcircuit the request here as all called functions are
* synchronous and final and no further subrequests are made */
DEBUG(SSSDBG_TRACE_INTERNAL, "Local secrets request done\n");
tevent_req_done(req);
}
return tevent_req_post(req, state->ev);
}
static 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) {
DEBUG(SSSDBG_OP_FAILURE,
"generate_csprng_buffer failed [%d]: %s\n",
ret, sss_strerror(ret));
return ret;
}
fd = open(filename, O_CREAT|O_EXCL|O_WRONLY, 0600);
if (fd == -1) {
ret = errno;
DEBUG(SSSDBG_OP_FAILURE,
"open(%s) failed [%d]: %s\n",
filename, ret, strerror(ret));
return ret;
}
rsize = sss_atomic_write_s(fd, buf, size);
close(fd);
if (rsize != size) {
ret = errno;
DEBUG(SSSDBG_OP_FAILURE,
"sss_atomic_write_s failed [%d]: %s\n",
ret, strerror(ret));
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;
DEBUG(SSSDBG_TRACE_INTERNAL, "Creating a local provider handle\n");
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) {
DEBUG(SSSDBG_TRACE_LIBS,
"ldb_connect(%s) returned %d: %s\n",
dbpath, ret, ldb_strerror(ret));
talloc_free(lctx->ldb);
return EIO;
}
lctx->containers_nest_level = sctx->containers_nest_level;
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) {
DEBUG(SSSDBG_TRACE_FUNC, "No master key, generating a new one..\n");
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) {
DEBUG(SSSDBG_OP_FAILURE, "Cannot generate a master key: %d\n", 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) {
DEBUG(SSSDBG_OP_FAILURE, "Cannot read a master key: %d\n", ret);
return EIO;
}
handle->context = lctx;
*out_handle = handle;
DEBUG(SSSDBG_TRACE_INTERNAL, "Local provider handle created\n");
return EOK;
}