local.c revision 7128fadade544efcd86b113a5090b00d20993671
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen Secrets Responder
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen Copyright (C) Simo Sorce <ssorce@redhat.com> 2016
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.
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 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/>.
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic int local_decrypt(struct local_context *lctx, TALLOC_CTX *mem_ctx,
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen if (enctype && strcmp(enctype, "masterkey") == 0) {
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen DEBUG(SSSDBG_TRACE_INTERNAL, "Decrypting with masterkey\n");
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen _secret.data = (char *)sss_base64_decode(mem_ctx, secret,
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen DEBUG(SSSDBG_OP_FAILURE, "sss_base64_decode failed\n");
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen ret = sss_decrypt(mem_ctx, AES256CBC_HMAC_SHA256,
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen "sss_decrypt failed [%d]: %s\n", ret, sss_strerror(ret));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (((strnlen(output, outlen) + 1) != outlen) ||
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "Output length mismatch or output not NULL-terminated\n");
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainenstatic int local_encrypt(struct local_context *lctx, TALLOC_CTX *mem_ctx,
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "No encryption type\n");
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "Uknown encryption type '%s'\n", enctype);
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen ret = sss_encrypt(mem_ctx, AES256CBC_HMAC_SHA256,
d03a871a77f8ec36f48f5fea98d810e51b186fdbTimo Sirainen "sss_encrypt failed [%d]: %s\n", ret, sss_strerror(ret));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const char *s, *e;
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen while (s && *s) {
dc07b75b7ea83ff5f447970a20419032725271a7Timo Sirainen if (e == s) {
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen if (!ldb_dn_add_child_fmt(dn, "cn=%.*s", (int)(e - s), s)) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "Local path for [%s] is [%s]\n",
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic char *local_dn_to_path(TALLOC_CTX *mem_ctx,
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen for (int i = dncomps - basecomps; i > 0; i--) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen path = talloc_strdup_append_buffer(path, "/");
e1f866daa1bd1a5cd7516f3b19c6f197bcf6cc8aTimo Sirainen path = talloc_strndup_append_buffer(path, (char *)val->data,
9ebd0c59de5f8240c0dbc58773fe5679391199dbTimo Sirainen path = talloc_strndup(mem_ctx, (char *)val->data, val->length);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "Secrets path for [%s] is [%s]\n",
e1f866daa1bd1a5cd7516f3b19c6f197bcf6cc8aTimo Sirainen#define LOCAL_CONTAINER_FILTER "(type=container)"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic int local_db_get_simple(TALLOC_CTX *mem_ctx,
72cc352b25ad401b923436c6ed0f1f3adaffa737Timo Sirainen static const char *attrs[] = { "secret", "enctype", NULL };
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DEBUG(SSSDBG_TRACE_FUNC, "Retrieving a secret from [%s]\n", req_path);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = local_db_dn(tmp_ctx, lctx->ldb, req_path, &dn);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "local_db_dn failed [%d]: %s\n", ret, sss_strerror(ret));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "Searching for [%s] at [%s] with scope=base\n",
f29756821a4c6b12b73e4a2a3e1c230117a43773Timo Sirainen LOCAL_SIMPLE_FILTER, ldb_dn_get_linearized(dn));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = ldb_search(lctx->ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "ldb_search returned [%d]: %s\n", ret, ldb_strerror(ret));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DEBUG(SSSDBG_TRACE_LIBS, "No secret found\n");
d4845c4245638fd6f02dc0cb92c3465fae763cbbTimo Sirainen "Too many secrets returned with BASE search\n");
788f275469ad9ed530e440d6690d0e4381a323b2Timo Sirainen attr_secret = ldb_msg_find_attr_as_string(res->msgs[0], "secret", NULL);
788f275469ad9ed530e440d6690d0e4381a323b2Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "The 'secret' attribute is missing\n");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen attr_enctype = ldb_msg_find_attr_as_string(res->msgs[0], "enctype", NULL);
0547a828ee9647fc5fd2e359b145774740a697feTimo Sirainen ret = local_decrypt(lctx, mem_ctx, attr_secret, attr_enctype, secret);
43d7e7ce608f5451e4907b5f5c48c00beb265802Timo Sirainen *secret = talloc_strdup(mem_ctx, attr_secret);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic int local_db_list_keys(TALLOC_CTX *mem_ctx,
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen static const char *attrs[] = { "secret", NULL };
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DEBUG(SSSDBG_TRACE_FUNC, "Listing keys at [%s]\n", req_path);
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen ret = local_db_dn(tmp_ctx, lctx->ldb, req_path, &dn);
601b455f4d5e780044b9e4fac5f687c1b07ae145Timo Sirainen "local_db_dn failed [%d]: %s\n", ret, sss_strerror(ret));
e5097d2c8efecdd274272b222cf2b30a8ae4ca2aTimo Sirainen "Searching for [%s] at [%s] with scope=subtree\n",
e5097d2c8efecdd274272b222cf2b30a8ae4ca2aTimo Sirainen LOCAL_SIMPLE_FILTER, ldb_dn_get_linearized(dn));
e5097d2c8efecdd274272b222cf2b30a8ae4ca2aTimo Sirainen ret = ldb_search(lctx->ldb, tmp_ctx, &res, dn, LDB_SCOPE_SUBTREE,
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen "ldb_search returned [%d]: %s\n", ret, ldb_strerror(ret));
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen DEBUG(SSSDBG_TRACE_LIBS, "No secrets found\n");
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen keys = talloc_array(mem_ctx, char *, res->count);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen keys[i] = local_dn_to_path(keys, dn, res->msgs[i]->dn);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DEBUG(SSSDBG_TRACE_LIBS, "Returning %d secrets\n", res->count);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic int local_db_check_containers(TALLOC_CTX *mem_ctx,
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 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 /* and check the parent container exists */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "Searching for [%s] at [%s] with scope=base\n",
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen LOCAL_CONTAINER_FILTER, ldb_dn_get_linearized(dn));
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen ret = ldb_search(lctx->ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE,
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen "DN [%s] does not exist\n", ldb_dn_get_linearized(dn));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic int local_db_check_containers_nest_level(struct local_context *lctx,
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 "Cannot create a nested container of depth %d as the maximum"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "allowed number of nested containers is %d.\n",
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic int local_db_put_simple(TALLOC_CTX *mem_ctx,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DEBUG(SSSDBG_TRACE_FUNC, "Adding a secret to [%s]\n", req_path);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = local_db_dn(msg, lctx->ldb, req_path, &msg->dn);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "local_db_dn failed [%d]: %s\n", ret, sss_strerror(ret));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* make sure containers exist */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = local_db_check_containers(msg, lctx, msg->dn);
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 ret = local_encrypt(lctx, msg, secret, enctype, &enc_secret);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "local_encrypt failed [%d]: %s\n", ret, sss_strerror(ret));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = ldb_msg_add_string(msg, "type", "simple");
114162093a3eb36c23a4ce4d4f2a43541dc18cc2Timo Sirainen "ldb_msg_add_string failed adding type:simple [%d]: %s\n",
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = ldb_msg_add_string(msg, "enctype", enctype);
ca502ca792708238ac2c23481c3bf94eda1f743fTimo Sirainen "ldb_msg_add_string failed adding enctype [%d]: %s\n",
129db31de1780783a175633eba5811e44c361a81Timo Sirainen ret = ldb_msg_add_string(msg, "secret", enc_secret);
dfcc56dc6c485fe45a3fa18325f047bfaae65019Timo Sirainen "ldb_msg_add_string failed adding secret [%d]: %s\n",
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = ldb_msg_add_fmt(msg, "creationTime", "%lu", time(NULL));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "ldb_msg_add_string failed adding creationTime [%d]: %s\n",
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen "Secret %s already exists\n", ldb_dn_get_linearized(msg->dn));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "Failed to add secret [%s]: [%d]: %s\n",
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ldb_dn_get_linearized(msg->dn), ret, ldb_strerror(ret));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic int local_db_delete(TALLOC_CTX *mem_ctx,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DEBUG(SSSDBG_TRACE_FUNC, "Removing a secret from [%s]\n", req_path);
800fc30be46bc6f8380f6de04aea7c19ea839ddfTimo Sirainen ret = local_db_dn(mem_ctx, lctx->ldb, req_path, &dn);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "local_db_dn failed [%d]: %s\n", ret, sss_strerror(ret));
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen "Searching for [%s] at [%s] with scope=base\n",
800fc30be46bc6f8380f6de04aea7c19ea839ddfTimo Sirainen LOCAL_CONTAINER_FILTER, ldb_dn_get_linearized(dn));
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen ret = ldb_search(lctx->ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "ldb_search returned %d: %s\n", ret, ldb_strerror(ret));
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 "ldb_search returned %d: %s\n", ret, ldb_strerror(ret));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "Failed to remove '%s': Container is not empty\n",
goto done;
done:
return ret;
const char *req_path)
int ret;
if (!msg) {
goto done;
goto done;
goto done;
goto done;
goto done;
goto done;
done:
return ret;
char **local_db_path)
int ret;
return EINVAL;
return EINVAL;
if (ret != 0) {
return EINVAL;
if (!*local_db_path) {
return ENOMEM;
return EOK;
struct local_secret_state {
void *provider_ctx,
const char *content_type;
bool body_is_json;
char *req_path;
char *secret;
char **keys;
int nkeys;
int plen;
int ret;
if (!lctx) {
goto done;
"application/json")) {
body_is_json = true;
"application/octet-stream")) {
body_is_json = false;
goto done;
case HTTP_GET:
if (body_is_json) {
case HTTP_PUT:
if (body_is_json) {
&secret);
case HTTP_DELETE:
case HTTP_POST:
goto done;
goto done;
done:
int ret;
int fd;
if (ret) {
return ret;
return ret;
return EFAULT;
return EOK;
int mfd;
int ret;
return EIO;
if (ret) {
return EFAULT;
return EIO;
return EOK;