From 70fe6e2bb398b8669ad1aebeaf0abcbffc307475 Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Tue, 7 Mar 2017 13:49:43 +0100 Subject: [PATCH 27/97] KCM: Add a in-memory credential storage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements a simple back end for the ccache module that lets the KCM server store credentials directly in memory. Reviewed-by: Michal Židek Reviewed-by: Simo Sorce --- Makefile.am | 1 + src/responder/kcm/kcm.c | 13 +- src/responder/kcm/kcmsrv_ccache.c | 2 +- src/responder/kcm/kcmsrv_ccache_mem.c | 805 ++++++++++++++++++++++++++++++++++ 4 files changed, 817 insertions(+), 4 deletions(-) create mode 100644 src/responder/kcm/kcmsrv_ccache_mem.c diff --git a/Makefile.am b/Makefile.am index a2b9dc49e95fa2d025f5174d2902866fab180a78..5605c1a53c44fd9e83394e80b7f71828df1d39b6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1492,6 +1492,7 @@ sssd_kcm_SOURCES = \ src/responder/kcm/kcm.c \ src/responder/kcm/kcmsrv_cmd.c \ src/responder/kcm/kcmsrv_ccache.c \ + src/responder/kcm/kcmsrv_ccache_mem.c \ src/util/sss_sockets.c \ src/util/sss_krb5.c \ src/util/sss_iobuf.c \ diff --git a/src/responder/kcm/kcm.c b/src/responder/kcm/kcm.c index 90a6999c5e39d48a1a2ea8168d171612a65077d5..2c12ef215ce3967df183e51c20590c5f439d278f 100644 --- a/src/responder/kcm/kcm.c +++ b/src/responder/kcm/kcm.c @@ -22,9 +22,9 @@ #include "config.h" #include -#include #include "responder/kcm/kcm.h" +#include "responder/kcm/kcmsrv_ccache.h" #include "responder/kcm/kcmsrv_pvt.h" #include "responder/common/responder.h" #include "util/util.h" @@ -110,7 +110,8 @@ static int kcm_data_destructor(void *ptr) return 0; } -static struct kcm_resp_ctx *kcm_data_setup(TALLOC_CTX *mem_ctx) +static struct kcm_resp_ctx *kcm_data_setup(TALLOC_CTX *mem_ctx, + struct tevent_context *ev) { struct kcm_resp_ctx *kcm_data; krb5_error_code kret; @@ -121,6 +122,12 @@ static struct kcm_resp_ctx *kcm_data_setup(TALLOC_CTX *mem_ctx) return NULL; } + kcm_data->db = kcm_ccdb_init(kcm_data, ev, CCDB_BE_MEMORY); + if (kcm_data->db == NULL) { + talloc_free(kcm_data); + return NULL; + } + kret = krb5_init_context(&kcm_data->k5c); if (kret != EOK) { talloc_free(kcm_data); @@ -169,7 +176,7 @@ static int kcm_process_init(TALLOC_CTX *mem_ctx, goto fail; } - kctx->kcm_data = kcm_data_setup(kctx); + kctx->kcm_data = kcm_data_setup(kctx, ev); if (kctx->kcm_data == NULL) { DEBUG(SSSDBG_FATAL_FAILURE, "fatal error initializing responder data\n"); diff --git a/src/responder/kcm/kcmsrv_ccache.c b/src/responder/kcm/kcmsrv_ccache.c index 2c565b8378e3ec297faf655d3c48d7ab902713d3..2ae120269b0c62275ba2acdff6d6daa8b7077708 100644 --- a/src/responder/kcm/kcmsrv_ccache.c +++ b/src/responder/kcm/kcmsrv_ccache.c @@ -240,7 +240,7 @@ struct kcm_ccdb *kcm_ccdb_init(TALLOC_CTX *mem_ctx, switch (cc_be) { case CCDB_BE_MEMORY: DEBUG(SSSDBG_FUNC_DATA, "KCM back end: memory\n"); - /* Not implemented yet */ + ccdb->ops = &ccdb_mem_ops; break; case CCDB_BE_SECRETS: DEBUG(SSSDBG_FUNC_DATA, "KCM back end: sssd-secrets\n"); diff --git a/src/responder/kcm/kcmsrv_ccache_mem.c b/src/responder/kcm/kcmsrv_ccache_mem.c new file mode 100644 index 0000000000000000000000000000000000000000..1c4f3df8d3b35b0428a143d4b545562d9cc0e574 --- /dev/null +++ b/src/responder/kcm/kcmsrv_ccache_mem.c @@ -0,0 +1,805 @@ +/* + SSSD + + KCM Server - ccache in-memory storage + + Copyright (C) Red Hat, 2016 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "config.h" + +#include +#include + +#include "util/util.h" +#include "responder/kcm/kcmsrv_ccache_pvt.h" +#include "responder/kcm/kcmsrv_ccache_be.h" + +struct ccdb_mem; + +/* + * The KCM memory database is just a double-linked list of kcm_ccache structures + */ +struct ccache_mem_wrap { + struct kcm_ccache *cc; + bool is_default; + + struct ccache_mem_wrap *next; + struct ccache_mem_wrap *prev; + + struct ccdb_mem *mem_be; +}; + +struct ccdb_mem { + /* Both ccaches and the next-id are kept in memory */ + struct ccache_mem_wrap *head; + unsigned int nextid; +}; + +/* In order to provide a consistent interface, we need to let the caller + * of getbyXXX own the ccache, therefore the memory back end returns a shallow + * copy of the ccache + */ +static struct kcm_ccache *kcm_ccache_dup(TALLOC_CTX *mem_ctx, + struct kcm_ccache *in) +{ + struct kcm_ccache *out; + + out = talloc_zero(mem_ctx, struct kcm_ccache); + if (out == NULL) { + return NULL; + } + memcpy(out, in, sizeof(struct kcm_ccache)); + + return out; +} + +static struct ccache_mem_wrap *memdb_get_by_uuid(struct ccdb_mem *memdb, + struct cli_creds *client, + uuid_t uuid) +{ + uid_t uid; + struct ccache_mem_wrap *ccwrap = NULL; + struct ccache_mem_wrap *out = NULL; + + uid = cli_creds_get_uid(client); + + DLIST_FOR_EACH(ccwrap, memdb->head) { + if (ccwrap->cc == NULL) { + /* since KCM stores ccaches, better not crash.. */ + DEBUG(SSSDBG_CRIT_FAILURE, "BUG: ccwrap contains NULL cc\n"); + continue; + } + + if (ccwrap->cc->owner.uid == uid) { + if (uuid_compare(uuid, ccwrap->cc->uuid) == 0) { + out = ccwrap; + break; + } + } + } + + return out; +} + +static struct ccache_mem_wrap *memdb_get_by_name(struct ccdb_mem *memdb, + struct cli_creds *client, + const char *name) +{ + uid_t uid; + struct ccache_mem_wrap *ccwrap = NULL; + struct ccache_mem_wrap *out = NULL; + + uid = cli_creds_get_uid(client); + + DLIST_FOR_EACH(ccwrap, memdb->head) { + if (ccwrap->cc == NULL) { + /* since KCM stores ccaches, better not crash.. */ + DEBUG(SSSDBG_CRIT_FAILURE, "BUG: ccwrap contains NULL cc\n"); + continue; + } + + if (ccwrap->cc->owner.uid == uid) { + if (strcmp(ccwrap->cc->name, name) == 0) { + out = ccwrap; + break; + } + } + } + + return out; +} + +/* Since with the in-memory database, the database operations are just + * fake-async wrappers around otherwise sync operations, we don't often + * need any state, so we use this empty structure instead + */ +struct ccdb_mem_dummy_state { +}; + +static int ccwrap_destructor(void *ptr) +{ + struct ccache_mem_wrap *ccwrap = talloc_get_type(ptr, struct ccache_mem_wrap); + + if (ccwrap == NULL) { + return 0; + } + + if (ccwrap->cc != NULL) { + if (ccwrap->cc->creds) { + safezero(sss_iobuf_get_data(ccwrap->cc->creds->cred_blob), + sss_iobuf_get_size(ccwrap->cc->creds->cred_blob)); + } + } + + + DLIST_REMOVE(ccwrap->mem_be->head, ccwrap); + + return 0; +} + +static errno_t ccdb_mem_init(struct kcm_ccdb *db) +{ + struct ccdb_mem *memdb = NULL; + + memdb = talloc_zero(db, struct ccdb_mem); + if (memdb == NULL) { + return ENOMEM; + } + db->db_handle = memdb; + + return EOK; +} + +struct ccdb_mem_nextid_state { + unsigned int nextid; +}; + +static struct tevent_req *ccdb_mem_nextid_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct kcm_ccdb *db, + struct cli_creds *client) +{ + struct tevent_req *req = NULL; + struct ccdb_mem_nextid_state *state = NULL; + struct ccdb_mem *memdb = NULL; + errno_t ret; + + req = tevent_req_create(mem_ctx, &state, struct ccdb_mem_nextid_state); + if (req == NULL) { + return NULL; + } + + memdb = talloc_get_type(db->db_handle, struct ccdb_mem); + if (memdb == NULL) { + ret = EIO; + goto immediate; + } + + state->nextid = memdb->nextid++; + + ret = EOK; +immediate: + if (ret == EOK) { + tevent_req_done(req); + } else { + tevent_req_error(req, ret); + } + tevent_req_post(req, ev); + return req; +} + +static errno_t ccdb_mem_nextid_recv(struct tevent_req *req, + unsigned int *_nextid) +{ + struct ccdb_mem_nextid_state *state = tevent_req_data(req, + struct ccdb_mem_nextid_state); + + TEVENT_REQ_RETURN_ON_ERROR(req); + *_nextid = state->nextid; + return EOK; +} + +struct ccdb_mem_list_state { + uuid_t *uuid_list; +}; + +static struct tevent_req *ccdb_mem_list_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct kcm_ccdb *db, + struct cli_creds *client) +{ + struct tevent_req *req = NULL; + struct ccache_mem_wrap *ccwrap = NULL; + struct ccdb_mem_list_state *state = NULL; + struct ccdb_mem *memdb = talloc_get_type(db->db_handle, struct ccdb_mem); + size_t num_ccaches = 0; + size_t cc_index = 0; + errno_t ret; + uid_t uid; + + req = tevent_req_create(mem_ctx, &state, struct ccdb_mem_list_state); + if (req == NULL) { + return NULL; + } + + uid = cli_creds_get_uid(client); + + DLIST_FOR_EACH(ccwrap, memdb->head) { + if (ccwrap->cc->owner.uid == uid) { + num_ccaches++; + } + } + + state->uuid_list = talloc_zero_array(state, uuid_t, num_ccaches+1); + if (state->uuid_list == NULL) { + ret = ENOMEM; + goto immediate; + } + + cc_index = 0; + DLIST_FOR_EACH(ccwrap, memdb->head) { + if (ccwrap->cc->owner.uid == uid) { + uuid_copy(state->uuid_list[cc_index], ccwrap->cc->uuid); + cc_index++; + } + } + uuid_clear(state->uuid_list[num_ccaches]); + + ret = EOK; +immediate: + if (ret == EOK) { + tevent_req_done(req); + } else { + tevent_req_error(req, ret); + } + tevent_req_post(req, ev); + return req; +} + +static errno_t ccdb_mem_list_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + uuid_t **_uuid_list) +{ + struct ccdb_mem_list_state *state = tevent_req_data(req, + struct ccdb_mem_list_state); + + TEVENT_REQ_RETURN_ON_ERROR(req); + *_uuid_list = talloc_steal(mem_ctx, state->uuid_list); + return EOK; +} + +static struct tevent_req *ccdb_mem_set_default_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct kcm_ccdb *db, + struct cli_creds *client, + uuid_t uuid) +{ + struct tevent_req *req = NULL; + struct ccdb_mem_dummy_state *state = NULL; + struct ccdb_mem *memdb = talloc_get_type(db->db_handle, struct ccdb_mem); + struct ccache_mem_wrap *ccwrap = NULL; + uid_t uid = cli_creds_get_uid(client); + + req = tevent_req_create(mem_ctx, &state, struct ccdb_mem_dummy_state); + if (req == NULL) { + return NULL; + } + + /* Reset all ccache defaults first */ + DLIST_FOR_EACH(ccwrap, memdb->head) { + if (ccwrap->cc == NULL) { + /* since KCM stores ccaches, better not crash.. */ + DEBUG(SSSDBG_CRIT_FAILURE, "BUG: ccwrap contains NULL cc\n"); + continue; + } + + if (ccwrap->cc->owner.uid == uid) { + ccwrap->is_default = false; + } + } + + /* Then set the default for the right ccache. This also allows to + * pass a null uuid to just reset the old ccache (for example after + * deleting the default + */ + ccwrap = memdb_get_by_uuid(memdb, client, uuid); + if (ccwrap != NULL) { + ccwrap->is_default = true; + } + + tevent_req_done(req); + tevent_req_post(req, ev); + return req; +} + +static errno_t ccdb_mem_set_default_recv(struct tevent_req *req) +{ + TEVENT_REQ_RETURN_ON_ERROR(req); + return EOK; +} + +struct ccdb_mem_get_default_state { + uuid_t dfl_uuid; +}; + +static struct tevent_req *ccdb_mem_get_default_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct kcm_ccdb *db, + struct cli_creds *client) +{ + struct tevent_req *req = NULL; + struct ccdb_mem_get_default_state *state = NULL; + struct ccache_mem_wrap *ccwrap = NULL; + struct ccdb_mem *memdb = talloc_get_type(db->db_handle, struct ccdb_mem); + uid_t uid = cli_creds_get_uid(client); + + req = tevent_req_create(mem_ctx, &state, struct ccdb_mem_get_default_state); + if (req == NULL) { + return NULL; + } + + + /* Reset all ccache defaults first */ + DLIST_FOR_EACH(ccwrap, memdb->head) { + if (ccwrap->cc == NULL) { + /* since KCM stores ccaches, better not crash.. */ + DEBUG(SSSDBG_CRIT_FAILURE, "BUG: ccwrap contains NULL cc\n"); + continue; + } + + if (ccwrap->cc->owner.uid == uid && ccwrap->is_default == true) { + break; + } + } + + if (ccwrap == NULL) { + DEBUG(SSSDBG_TRACE_FUNC, + "No ccache marked as default, returning null ccache\n"); + uuid_clear(state->dfl_uuid); + } else { + uuid_copy(state->dfl_uuid, ccwrap->cc->uuid); + } + + tevent_req_done(req); + tevent_req_post(req, ev); + return req; +} + +static errno_t ccdb_mem_get_default_recv(struct tevent_req *req, + uuid_t dfl) +{ + struct ccdb_mem_get_default_state *state = tevent_req_data(req, + struct ccdb_mem_get_default_state); + + TEVENT_REQ_RETURN_ON_ERROR(req); + + uuid_copy(dfl, state->dfl_uuid); + return EOK; +} + +struct ccdb_mem_getbyuuid_state { + struct kcm_ccache *cc; +}; + +static struct tevent_req *ccdb_mem_getbyuuid_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct kcm_ccdb *db, + struct cli_creds *client, + uuid_t uuid) +{ + struct tevent_req *req = NULL; + struct ccdb_mem_getbyuuid_state *state = NULL; + struct ccdb_mem *memdb = talloc_get_type(db->db_handle, struct ccdb_mem); + struct ccache_mem_wrap *ccwrap = NULL; + + req = tevent_req_create(mem_ctx, &state, struct ccdb_mem_getbyuuid_state); + if (req == NULL) { + return NULL; + } + + ccwrap = memdb_get_by_uuid(memdb, client, uuid); + if (ccwrap != NULL) { + state->cc = kcm_ccache_dup(state, ccwrap->cc); + } + + tevent_req_done(req); + tevent_req_post(req, ev); + return req; +} + +static errno_t ccdb_mem_getbyuuid_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + struct kcm_ccache **_cc) +{ + struct ccdb_mem_getbyuuid_state *state = tevent_req_data(req, + struct ccdb_mem_getbyuuid_state); + + TEVENT_REQ_RETURN_ON_ERROR(req); + *_cc = talloc_steal(mem_ctx, state->cc); + return EOK; +} + +struct ccdb_mem_getbyname_state { + struct kcm_ccache *cc; +}; + +static struct tevent_req *ccdb_mem_getbyname_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct kcm_ccdb *db, + struct cli_creds *client, + const char *name) +{ + struct tevent_req *req = NULL; + struct ccdb_mem_getbyname_state *state = NULL; + struct ccache_mem_wrap *ccwrap = NULL; + struct ccdb_mem *memdb = talloc_get_type(db->db_handle, struct ccdb_mem); + + req = tevent_req_create(mem_ctx, &state, struct ccdb_mem_getbyname_state); + if (req == NULL) { + return NULL; + } + + ccwrap = memdb_get_by_name(memdb, client, name); + if (ccwrap != NULL) { + state->cc = kcm_ccache_dup(state, ccwrap->cc); + } + + tevent_req_done(req); + tevent_req_post(req, ev); + return req; +} + +static errno_t ccdb_mem_getbyname_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + struct kcm_ccache **_cc) +{ + struct ccdb_mem_getbyname_state *state = tevent_req_data(req, + struct ccdb_mem_getbyname_state); + + TEVENT_REQ_RETURN_ON_ERROR(req); + *_cc = talloc_steal(mem_ctx, state->cc); + return EOK; +} + +struct ccdb_mem_name_by_uuid_state { + const char *name; +}; + +struct tevent_req *ccdb_mem_name_by_uuid_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct kcm_ccdb *db, + struct cli_creds *client, + uuid_t uuid) +{ + struct tevent_req *req = NULL; + struct ccdb_mem_name_by_uuid_state *state = NULL; + struct ccdb_mem *memdb = talloc_get_type(db->db_handle, struct ccdb_mem); + struct ccache_mem_wrap *ccwrap = NULL; + errno_t ret; + + req = tevent_req_create(mem_ctx, &state, struct ccdb_mem_name_by_uuid_state); + if (req == NULL) { + return NULL; + } + + ccwrap = memdb_get_by_uuid(memdb, client, uuid); + if (ccwrap == NULL) { + ret = ERR_KCM_CC_END; + goto immediate; + } + + state->name = talloc_strdup(state, ccwrap->cc->name); + if (state->name == NULL) { + ret = ENOMEM; + goto immediate; + } + + ret = EOK; +immediate: + if (ret == EOK) { + tevent_req_done(req); + } else { + tevent_req_error(req, ret); + } + tevent_req_post(req, ev); + return req; +} + +errno_t ccdb_mem_name_by_uuid_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + const char **_name) +{ + struct ccdb_mem_name_by_uuid_state *state = tevent_req_data(req, + struct ccdb_mem_name_by_uuid_state); + TEVENT_REQ_RETURN_ON_ERROR(req); + *_name = talloc_steal(mem_ctx, state->name); + return EOK; +} + +struct ccdb_mem_uuid_by_name_state { + uuid_t uuid; +}; + +struct tevent_req *ccdb_mem_uuid_by_name_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct kcm_ccdb *db, + struct cli_creds *client, + const char *name) +{ + struct tevent_req *req = NULL; + struct ccdb_mem_uuid_by_name_state *state = NULL; + struct ccdb_mem *memdb = talloc_get_type(db->db_handle, struct ccdb_mem); + struct ccache_mem_wrap *ccwrap = NULL; + errno_t ret; + + req = tevent_req_create(mem_ctx, &state, struct ccdb_mem_uuid_by_name_state); + if (req == NULL) { + return NULL; + } + + ccwrap = memdb_get_by_name(memdb, client, name); + if (ccwrap == NULL) { + ret = ERR_KCM_CC_END; + goto immediate; + } + + uuid_copy(state->uuid, ccwrap->cc->uuid); + + ret = EOK; +immediate: + if (ret == EOK) { + tevent_req_done(req); + } else { + tevent_req_error(req, ret); + } + tevent_req_post(req, ev); + return req; +} + +errno_t ccdb_mem_uuid_by_name_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + uuid_t _uuid) +{ + struct ccdb_mem_uuid_by_name_state *state = tevent_req_data(req, + struct ccdb_mem_uuid_by_name_state); + TEVENT_REQ_RETURN_ON_ERROR(req); + uuid_copy(_uuid, state->uuid); + return EOK; +} + +static struct tevent_req *ccdb_mem_create_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct kcm_ccdb *db, + struct cli_creds *client, + struct kcm_ccache *cc) +{ + struct tevent_req *req = NULL; + struct ccdb_mem_dummy_state *state = NULL; + struct ccache_mem_wrap *ccwrap; + struct ccdb_mem *memdb = talloc_get_type(db->db_handle, struct ccdb_mem); + errno_t ret; + + req = tevent_req_create(mem_ctx, &state, struct ccdb_mem_dummy_state); + if (req == NULL) { + return NULL; + } + + ccwrap = talloc_zero(memdb, struct ccache_mem_wrap); + if (ccwrap == NULL) { + ret = ENOMEM; + goto immediate; + } + ccwrap->cc = cc; + ccwrap->mem_be = memdb; + talloc_steal(ccwrap, cc); + + DLIST_ADD(memdb->head, ccwrap); + talloc_set_destructor((TALLOC_CTX *) ccwrap, ccwrap_destructor); + + ret = EOK; +immediate: + if (ret == EOK) { + tevent_req_done(req); + } else { + tevent_req_error(req, ret); + } + tevent_req_post(req, ev); + return req; +} + +static errno_t ccdb_mem_create_recv(struct tevent_req *req) +{ + TEVENT_REQ_RETURN_ON_ERROR(req); + return EOK; +} + +static struct tevent_req *ccdb_mem_mod_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct kcm_ccdb *db, + struct cli_creds *client, + uuid_t uuid, + struct kcm_mod_ctx *mod_cc) +{ + errno_t ret; + struct tevent_req *req = NULL; + struct ccdb_mem_dummy_state *state = NULL; + struct ccache_mem_wrap *ccwrap = NULL; + struct ccdb_mem *memdb = talloc_get_type(db->db_handle, struct ccdb_mem); + + req = tevent_req_create(mem_ctx, &state, struct ccdb_mem_dummy_state); + if (req == NULL) { + return NULL; + } + + /* UUID is immutable, so search by that */ + ccwrap = memdb_get_by_uuid(memdb, client, uuid); + if (ccwrap == NULL) { + ret = ERR_KCM_CC_END; + goto immediate; + } + + kcm_mod_cc(ccwrap->cc, mod_cc); + + ret = EOK; +immediate: + if (ret == EOK) { + tevent_req_done(req); + } else { + tevent_req_error(req, ret); + } + tevent_req_post(req, ev); + return req; +} + +static errno_t ccdb_mem_mod_recv(struct tevent_req *req) +{ + TEVENT_REQ_RETURN_ON_ERROR(req); + return EOK; +} + +static struct tevent_req *ccdb_mem_store_cred_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct kcm_ccdb *db, + struct cli_creds *client, + uuid_t uuid, + struct sss_iobuf *cred_blob) +{ + struct tevent_req *req = NULL; + struct ccdb_mem_dummy_state *state = NULL; + struct ccdb_mem *memdb = talloc_get_type(db->db_handle, struct ccdb_mem); + struct ccache_mem_wrap *ccwrap = NULL; + errno_t ret; + + req = tevent_req_create(mem_ctx, &state, struct ccdb_mem_dummy_state); + if (req == NULL) { + return NULL; + } + + ccwrap = memdb_get_by_uuid(memdb, client, uuid); + if (ccwrap == NULL) { + ret = ERR_KCM_CC_END; + goto immediate; + } + + ret = kcm_cc_store_cred_blob(ccwrap->cc, cred_blob); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Cannot store credentials to ccache [%d]: %s\n", + ret, sss_strerror(ret)); + goto immediate; + } + + ret = EOK; +immediate: + if (ret == EOK) { + tevent_req_done(req); + } else { + tevent_req_error(req, ret); + } + tevent_req_post(req, ev); + return req; +} + +static errno_t ccdb_mem_store_cred_recv(struct tevent_req *req) +{ + TEVENT_REQ_RETURN_ON_ERROR(req); + return EOK; +} + +static struct tevent_req *ccdb_mem_delete_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct kcm_ccdb *db, + struct cli_creds *client, + uuid_t uuid) +{ + struct tevent_req *req = NULL; + struct ccdb_mem_dummy_state *state = NULL; + struct ccache_mem_wrap *ccwrap; + struct ccdb_mem *memdb = talloc_get_type(db->db_handle, struct ccdb_mem); + errno_t ret; + + req = tevent_req_create(mem_ctx, &state, struct ccdb_mem_dummy_state); + if (req == NULL) { + return NULL; + } + + ccwrap = memdb_get_by_uuid(memdb, client, uuid); + if (ccwrap == NULL) { + DEBUG(SSSDBG_MINOR_FAILURE, + "BUG: Attempting to free unknown ccache\n"); + ret = ERR_KCM_CC_END; + goto immediate; + } + + ret = EOK; + /* Destructor takes care of everything */ + talloc_free(ccwrap); +immediate: + if (ret == EOK) { + tevent_req_done(req); + } else { + tevent_req_error(req, ret); + } + tevent_req_post(req, ev); + return req; +} + +static errno_t ccdb_mem_delete_recv(struct tevent_req *req) +{ + TEVENT_REQ_RETURN_ON_ERROR(req); + return EOK; +} + +const struct kcm_ccdb_ops ccdb_mem_ops = { + .init = ccdb_mem_init, + + .nextid_send = ccdb_mem_nextid_send, + .nextid_recv = ccdb_mem_nextid_recv, + + .set_default_send = ccdb_mem_set_default_send, + .set_default_recv = ccdb_mem_set_default_recv, + + .get_default_send = ccdb_mem_get_default_send, + .get_default_recv = ccdb_mem_get_default_recv, + + .list_send = ccdb_mem_list_send, + .list_recv = ccdb_mem_list_recv, + + .getbyname_send = ccdb_mem_getbyname_send, + .getbyname_recv = ccdb_mem_getbyname_recv, + + .getbyuuid_send = ccdb_mem_getbyuuid_send, + .getbyuuid_recv = ccdb_mem_getbyuuid_recv, + + .name_by_uuid_send = ccdb_mem_name_by_uuid_send, + .name_by_uuid_recv = ccdb_mem_name_by_uuid_recv, + + .uuid_by_name_send = ccdb_mem_uuid_by_name_send, + .uuid_by_name_recv = ccdb_mem_uuid_by_name_recv, + + .create_send = ccdb_mem_create_send, + .create_recv = ccdb_mem_create_recv, + + .mod_send = ccdb_mem_mod_send, + .mod_recv = ccdb_mem_mod_recv, + + .store_cred_send = ccdb_mem_store_cred_send, + .store_cred_recv = ccdb_mem_store_cred_recv, + + .delete_send = ccdb_mem_delete_send, + .delete_recv = ccdb_mem_delete_recv, +}; -- 2.12.2