local.c revision e625eb47a3091d92eda2271b123f8aab06227b63
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan Secrets Responder
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher Copyright (C) Simo Sorce <ssorce@redhat.com> 2016
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan This program is free software; you can redistribute it and/or modify
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan it under the terms of the GNU General Public License as published by
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher the Free Software Foundation; either version 3 of the License, or
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan (at your option) any later version.
e5c33e0bd03a2deb8e5011deeb3ae93f960910eeJakub Hrozek This program is distributed in the hope that it will be useful,
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher but WITHOUT ANY WARRANTY; without even the implied warranty of
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher GNU General Public License for more details.
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan You should have received a copy of the GNU General Public License
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher along with this program. If not, see <http://www.gnu.org/licenses/>.
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#include "responder/secrets/secsrv_private.h"
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivanint local_decrypt(struct local_context *lctx, TALLOC_CTX *mem_ctx,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (enctype && strcmp(enctype, "masterkey") == 0) {
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher _secret.data = (char *)sss_base64_decode(mem_ctx, secret,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan ret = sss_decrypt(mem_ctx, AES256CBC_HMAC_SHA256,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (((strnlen(output, outlen) + 1) != outlen) ||
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozekint local_encrypt(struct local_context *lctx, TALLOC_CTX *mem_ctx,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (!enctype || strcmp(enctype, "masterkey") != 0) return EINVAL;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan ret = sss_encrypt(mem_ctx, AES256CBC_HMAC_SHA256,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan (const uint8_t *)secret, strlen(secret) + 1,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan (uint8_t **)&_secret.data, &_secret.length);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher const char *s, *e;
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher dn = ldb_dn_new(mem_ctx, ldb, "cn=secrets");
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan while (s && *s) {
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan if (e == s) {
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (!ldb_dn_add_child_fmt(dn, "cn=%.*s", (int)(e - s), s)) {
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (!ldb_dn_add_child_fmt(dn, "cn=%s", s)) {
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagherchar *local_dn_to_path(TALLOC_CTX *mem_ctx,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan for (int i = dncomps - basecomps; i > 0; i--) {
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher path = talloc_strdup_append_buffer(path, "/");
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan path = talloc_strndup_append_buffer(path, (char *)val->data,
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher path = talloc_strndup(mem_ctx, (char *)val->data, val->length);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher static const char *attrs[] = { "secret", "enctype", NULL };
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher ret = local_db_dn(tmp_ctx, lctx->ldb, req_path, &dn);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher ret = ldb_search(lctx->ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE,
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher attr_secret = ldb_msg_find_attr_as_string(res->msgs[0], "secret", NULL);
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher attr_enctype = ldb_msg_find_attr_as_string(res->msgs[0], "enctype", NULL);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher ret = local_decrypt(lctx, mem_ctx, attr_secret, attr_enctype, secret);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan *secret = talloc_strdup(mem_ctx, attr_secret);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan static const char *attrs[] = { "secret", NULL };
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan ret = local_db_dn(tmp_ctx, lctx->ldb, req_path, &dn);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan ret = ldb_search(lctx->ldb, tmp_ctx, &res, dn, LDB_SCOPE_SUBTREE,
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher keys = talloc_array(mem_ctx, char *, res->count);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan keys[i] = local_dn_to_path(keys, dn, res->msgs[i]->dn);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan /* FIXME: verify containers (except for user's namespace) exists */
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher ret = local_encrypt(lctx, msg, secret, enctype, &enc_secret);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan ret = local_db_dn(msg, lctx->ldb, req_path, &msg->dn);
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher ret = ldb_msg_add_string(msg, "type", "simple");
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan ret = ldb_msg_add_string(msg, "enctype", enctype);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan ret = ldb_msg_add_string(msg, "secret", enc_secret);
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) ret = EEXIST;
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek ret = local_db_dn(mem_ctx, lctx->ldb, req_path, &dn);
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivanint local_secrets_map_path(TALLOC_CTX *mem_ctx,
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher /* be strict for now */
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher if (secreq->parsed_url.fragment != NULL) {
7797e361155f7ce937085fd98e360469d7baf1b6Jakub Hrozek "Unrecognized URI fragments: [%s]\n",
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher "Unrecognized URI userinfo: [%s]\n",
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan /* only type simple for now */
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek ret = strcmp(secreq->parsed_url.query, "type=simple");
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan "Invalid URI query: [%s]\n",
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan /* drop SEC_BASEPATH prefix */
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan talloc_strdup(mem_ctx, &secreq->mapped_path[sizeof(SEC_BASEPATH) - 1]);
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan "Failed to map request to local db path\n");
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagherstruct tevent_req *local_secret_req(TALLOC_CTX *mem_ctx,
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan req = tevent_req_create(mem_ctx, &state, struct local_secret_state);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher lctx = talloc_get_type(provider_ctx, struct local_context);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (sec_req_has_header(secreq, "Content-Type",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher } else if (sec_req_has_header(secreq, "Content-Type",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher content_type = "application/octet-stream";
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = local_secrets_map_path(state, secreq, &req_path);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (req_path[strlen(req_path) - 1] == '/') {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = local_db_list_keys(state, lctx, req_path, &keys, &nkeys);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = sec_array_to_json(state, keys, nkeys, &body.data);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek ret = local_db_get_simple(state, lctx, req_path, &secret);
e5c33e0bd03a2deb8e5011deeb3ae93f960910eeJakub Hrozek ret = sec_simple_secret_to_json(state, secret, &body.data);
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek body.data = (void *)sss_base64_decode(state, secret, &body.length);
e5c33e0bd03a2deb8e5011deeb3ae93f960910eeJakub Hrozek ret = sec_json_to_simple_secret(state, secreq->body.data,
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek secret = sss_base64_encode(state, (uint8_t *)secreq->body.data,
e5c33e0bd03a2deb8e5011deeb3ae93f960910eeJakub Hrozek ret = local_db_put_simple(state, lctx, req_path, secret);
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek ret = sec_http_reply_with_body(secreq, &secreq->reply, STATUS_200,
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher ret = sec_http_status_reply(secreq, &secreq->reply, STATUS_200);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher /* shortcircuit the request here as all called functions are
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan * synchronous and final and no further subrequests are made */
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivanint generate_master_key(const char *filename, size_t size)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan fd = open(filename, O_CREAT|O_EXCL|O_WRONLY, 0600);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan rsize = sss_atomic_io_s(fd, buf, size, false);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivanint local_secrets_provider_handle(struct sec_ctx *sctx,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan const char *mkey = SECRETS_DB_PATH"/.secrets.mkey";
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan const char *dbpath = SECRETS_DB_PATH"/secrets.ldb";
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher handle = talloc_zero(sctx, struct provider_handle);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek lctx = talloc_zero(handle, struct local_context);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher lctx->master_key.data = talloc_size(lctx, MKEY_SIZE);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = check_and_open_readonly(mkey, &mfd, 0, 0,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = generate_master_key(mkey, MKEY_SIZE);
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher ret = check_and_open_readonly(mkey, &mfd, 0, 0,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek size = sss_atomic_io_s(mfd, lctx->master_key.data,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (size < 0 || size != lctx->master_key.length) return EIO;