From e7aa9061532b1ac139e155e7e9881c2447675e3c Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek@redhat.com>
Date: Tue, 7 Mar 2017 13:49:43 +0100
Subject: [PATCH 25/36] 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 <mzidek@redhat.com>
Reviewed-by: Simo Sorce <simo@redhat.com>
---
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 <popt.h>
-#include <krb5/krb5.h>
#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 <http://www.gnu.org/licenses/>.
+*/
+
+#include "config.h"
+
+#include <talloc.h>
+#include <stdio.h>
+
+#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.9.3