local.c revision a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce Secrets Responder
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce Copyright (C) Simo Sorce <ssorce@redhat.com> 2016
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce This program is free software; you can redistribute it and/or modify
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce it under the terms of the GNU General Public License as published by
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce the Free Software Foundation; either version 3 of the License, or
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce (at your option) any later version.
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce This program is distributed in the hope that it will be useful,
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce but WITHOUT ANY WARRANTY; without even the implied warranty of
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce GNU General Public License for more details.
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce You should have received a copy of the GNU General Public License
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce along with this program. If not, see <http://www.gnu.org/licenses/>.
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorceint local_decrypt(struct local_context *lctx, TALLOC_CTX *mem_ctx,
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce if (enctype && strcmp(enctype, "masterkey") == 0) {
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce _secret.data = (char *)sss_base64_decode(mem_ctx, secret,
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce ret = sss_decrypt(mem_ctx, AES256CBC_HMAC_SHA256,
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorceint local_encrypt(struct local_context *lctx, TALLOC_CTX *mem_ctx,
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce if (!enctype || strcmp(enctype, "masterkey") != 0) return EINVAL;
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce ret = sss_encrypt(mem_ctx, AES256CBC_HMAC_SHA256,
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce const char *s, *e;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce while (s && *s) {
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce if (e == s) {
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce if (!ldb_dn_add_child_fmt(dn, "cn=%.*s", (int)(e - s), s)) {
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce path = talloc_strndup_append_buffer(path, (char *)val->data,
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce path = talloc_strndup(mem_ctx, (char *)val->data, val->length);
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce static const char *attrs[] = { "secret", "enctype", NULL };
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce ret = local_db_dn(tmp_ctx, lctx->ldb, req_path, &dn);
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce ret = ldb_search(lctx->ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE,
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce attr_secret = ldb_msg_find_attr_as_string(res->msgs[0], "secret", NULL);
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce attr_enctype = ldb_msg_find_attr_as_string(res->msgs[0], "enctype", NULL);
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce ret = local_decrypt(lctx, mem_ctx, attr_secret, attr_enctype, secret);
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce ret = local_db_dn(tmp_ctx, lctx->ldb, req_path, &dn);
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce ret = ldb_search(lctx->ldb, tmp_ctx, &res, dn, LDB_SCOPE_SUBTREE,
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce keys = talloc_array(mem_ctx, char *, res->count);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce keys[i] = local_dn_to_path(keys, dn, res->msgs[i]->dn);
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorceint local_db_check_containers(TALLOC_CTX *mem_ctx,
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce /* We need to exclude the leaf as that will be the new child entry,
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce * We also do not care for the synthetic containers that constitute the
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce * base path (cn=<uidnumber>,cn=users,cn=secrets), so in total we remove
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce * 4 components */
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce for (int i = 0; i < num; i++) {
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce /* remove the child first (we do not want to check the leaf) */
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce if (!ldb_dn_remove_child_components(dn, 1)) return EFAULT;
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce /* and check the parent container exists */
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce ret = ldb_search(lctx->ldb, mem_ctx, &res, dn, LDB_SCOPE_BASE,
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce const char *secret)
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce ret = local_db_dn(msg, lctx->ldb, req_path, &msg->dn);
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce /* make sure containers exist */
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce ret = local_db_check_containers(msg, lctx, msg->dn);
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce ret = local_encrypt(lctx, msg, secret, enctype, &enc_secret);
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce ret = ldb_msg_add_string(msg, "enctype", enctype);
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce ret = ldb_msg_add_string(msg, "secret", enc_secret);
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce ret = ldb_msg_add_fmt(msg, "creationTime", "%lu", time(NULL));
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) ret = EEXIST;
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce ret = local_db_dn(mem_ctx, lctx->ldb, req_path, &dn);
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce ret = local_db_dn(msg, lctx->ldb, req_path, &msg->dn);
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce /* make sure containers exist */
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce ret = local_db_check_containers(msg, lctx, msg->dn);
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce ret = ldb_msg_add_string(msg, "type", "container");
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce ret = ldb_msg_add_fmt(msg, "creationTime", "%lu", time(NULL));
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) ret = EEXIST;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce /* be strict for now */
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce "Unrecognized URI fragments: [%s]\n",
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce "Unrecognized URI userinfo: [%s]\n",
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce /* only type simple for now */
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce ret = strcmp(secreq->parsed_url.query, "type=simple");
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce "Invalid URI query: [%s]\n",
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce /* drop SEC_BASEPATH prefix */
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce talloc_strdup(mem_ctx, &secreq->mapped_path[sizeof(SEC_BASEPATH) - 1]);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce "Failed to map request to local db path\n");
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorcestruct tevent_req *local_secret_req(TALLOC_CTX *mem_ctx,
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce req = tevent_req_create(mem_ctx, &state, struct local_secret_state);
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce lctx = talloc_get_type(provider_ctx, struct local_context);
e625eb47a3091d92eda2271b123f8aab06227b63Simo Sorce } else if (sec_req_has_header(secreq, "Content-Type",
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce ret = local_secrets_map_path(state, secreq, &req_path);
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce ret = local_db_list_keys(state, lctx, req_path, &keys, &nkeys);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce ret = sec_array_to_json(state, keys, nkeys, &body.data);
e625eb47a3091d92eda2271b123f8aab06227b63Simo Sorce ret = local_db_get_simple(state, lctx, req_path, &secret);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce ret = sec_simple_secret_to_json(state, secret, &body.data);
e625eb47a3091d92eda2271b123f8aab06227b63Simo Sorce body.data = (void *)sss_base64_decode(state, secret, &body.length);
e625eb47a3091d92eda2271b123f8aab06227b63Simo Sorce ret = sec_json_to_simple_secret(state, secreq->body.data,
e625eb47a3091d92eda2271b123f8aab06227b63Simo Sorce secret = sss_base64_encode(state, (uint8_t *)secreq->body.data,
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce ret = local_db_put_simple(state, lctx, req_path, secret);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce ret = sec_http_reply_with_body(secreq, &secreq->reply, STATUS_200,
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce ret = sec_http_status_reply(secreq, &secreq->reply, STATUS_200);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce /* shortcircuit the request here as all called functions are
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce * synchronous and final and no further subrequests are made */
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorceint generate_master_key(const char *filename, size_t size)
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce fd = open(filename, O_CREAT|O_EXCL|O_WRONLY, 0600);
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorceint local_secrets_provider_handle(struct sec_ctx *sctx,
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce const char *mkey = SECRETS_DB_PATH"/.secrets.mkey";
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce const char *dbpath = SECRETS_DB_PATH"/secrets.ldb";
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce handle = talloc_zero(sctx, struct provider_handle);
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce lctx = talloc_zero(handle, struct local_context);
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce lctx->master_key.data = talloc_size(lctx, MKEY_SIZE);
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce size = sss_atomic_io_s(mfd, lctx->master_key.data,
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce if (size < 0 || size != lctx->master_key.length) return EIO;