Blame SOURCES/0025-KCM-Add-a-in-memory-credential-storage.patch

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