sssd/0012-kcm-use-binary-format-to-store-ccache-instead-of-jso.patch
2020-12-07 17:31:23 +01:00

742 lines
24 KiB
Diff

From 94ceb85465dbf052f681bbd6c8ebced4d2d97f92 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
Date: Tue, 27 Oct 2020 16:21:31 +0100
Subject: [PATCH 12/19] kcm: use binary format to store ccache instead of json
JSON is computationally complex and the parser is a bottleneck which
consumes about 10% of time. It also create the ccache unnecessary
large because it requires lots of unneded character and base64
encoding.
Binary format is fast, simple and small.
This is backwards compatible and there is no need to destroy existing
ccache. It will be stored in binary format at first write to the cache.
Resolves: https://github.com/SSSD/sssd/issues/5349
---
Makefile.am | 2 +
src/responder/kcm/kcmsrv_ccache.h | 16 +-
src/responder/kcm/kcmsrv_ccache_binary.c | 308 ++++++++++++++++++++++
src/responder/kcm/kcmsrv_ccache_json.c | 1 -
src/responder/kcm/kcmsrv_ccache_secdb.c | 49 ++--
src/responder/kcm/kcmsrv_ccache_secrets.c | 2 +-
src/tests/cmocka/test_kcm_marshalling.c | 112 +++++++-
src/tests/multihost/basic/test_kcm.py | 12 +-
src/util/secrets/secrets.c | 2 +-
9 files changed, 476 insertions(+), 28 deletions(-)
create mode 100644 src/responder/kcm/kcmsrv_ccache_binary.c
diff --git a/Makefile.am b/Makefile.am
index ae9bc540a86f2e291dd5b5f66e1ce4f0aacbaf61..430b4e8424d6bde0c7de919c6aceabf3839e3a23 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1817,6 +1817,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_binary.c \
src/responder/kcm/kcmsrv_ccache_mem.c \
src/responder/kcm/kcmsrv_ccache_json.c \
src/responder/kcm/kcmsrv_ccache_key.c \
@@ -3930,6 +3931,7 @@ test_sssd_krb5_locator_plugin_LDADD = \
if BUILD_KCM
test_kcm_marshalling_SOURCES = \
src/tests/cmocka/test_kcm_marshalling.c \
+ src/responder/kcm/kcmsrv_ccache_binary.c \
src/responder/kcm/kcmsrv_ccache_json.c \
src/responder/kcm/kcmsrv_ccache_key.c \
src/responder/kcm/kcmsrv_ccache.c \
diff --git a/src/responder/kcm/kcmsrv_ccache.h b/src/responder/kcm/kcmsrv_ccache.h
index 892067f3170b19c0e55ceaa75b0c01f772c49d3d..b0a7acb9fed8a8f89a3d0e2239ab28c7ce80fa23 100644
--- a/src/responder/kcm/kcmsrv_ccache.h
+++ b/src/responder/kcm/kcmsrv_ccache.h
@@ -352,7 +352,21 @@ errno_t sec_kv_to_ccache_json(TALLOC_CTX *mem_ctx,
/* Convert a kcm_ccache to a key-value pair to be stored in secrets */
errno_t kcm_ccache_to_sec_input_json(TALLOC_CTX *mem_ctx,
struct kcm_ccache *cc,
- struct cli_creds *client,
struct sss_iobuf **_payload);
+/*
+ * sec_key is a concatenation of the ccache's UUID and name
+ * sec_value is the binary representation of ccache.
+ */
+errno_t sec_kv_to_ccache_binary(TALLOC_CTX *mem_ctx,
+ const char *sec_key,
+ struct sss_iobuf *sec_value,
+ struct cli_creds *client,
+ struct kcm_ccache **_cc);
+
+/* Convert a kcm_ccache to its binary representation. */
+errno_t kcm_ccache_to_sec_input_binary(TALLOC_CTX *mem_ctx,
+ struct kcm_ccache *cc,
+ struct sss_iobuf **_payload);
+
#endif /* _KCMSRV_CCACHE_H_ */
diff --git a/src/responder/kcm/kcmsrv_ccache_binary.c b/src/responder/kcm/kcmsrv_ccache_binary.c
new file mode 100644
index 0000000000000000000000000000000000000000..7bfdbf13bfeaa7d45de6352e7b51b781b713b8f2
--- /dev/null
+++ b/src/responder/kcm/kcmsrv_ccache_binary.c
@@ -0,0 +1,308 @@
+/*
+ Authors:
+ Pavel Březina <pbrezina@redhat.com>
+
+ Copyright (C) 2020 Red Hat
+
+ 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 <stdio.h>
+#include <talloc.h>
+
+#include "util/util.h"
+#include "util/util_creds.h"
+#include "util/crypto/sss_crypto.h"
+#include "responder/kcm/kcmsrv_ccache_pvt.h"
+
+static errno_t krb_data_to_bin(krb5_data *data, struct sss_iobuf *buf)
+{
+ return sss_iobuf_write_varlen(buf, (uint8_t *)data->data, data->length);
+}
+
+static errno_t princ_to_bin(krb5_principal princ, struct sss_iobuf *buf)
+{
+ errno_t ret;
+
+ if (princ == NULL) {
+ return sss_iobuf_write_uint8(buf, 0);
+ }
+
+ /* Mark that principal is not empty. */
+ ret = sss_iobuf_write_uint8(buf, 1);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ ret = krb_data_to_bin(&princ->realm, buf);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ ret = sss_iobuf_write_int32(buf, princ->type);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ ret = sss_iobuf_write_int32(buf, princ->length);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ for (krb5_int32 i = 0; i < princ->length; i++) {
+ ret = krb_data_to_bin(&princ->data[i], buf);
+ if (ret != EOK) {
+ return ret;
+ }
+ }
+
+ return EOK;
+}
+
+static errno_t creds_to_bin(struct kcm_cred *creds, struct sss_iobuf *buf)
+{
+ struct kcm_cred *crd;
+ uint32_t count = 0;
+ errno_t ret;
+
+ DLIST_FOR_EACH(crd, creds) {
+ count++;
+ }
+
+ ret = sss_iobuf_write_uint32(buf, count);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ DLIST_FOR_EACH(crd, creds) {
+ ret = sss_iobuf_write_len(buf, (uint8_t *)crd->uuid, sizeof(uuid_t));
+ if (ret != EOK) {
+ return ret;
+ }
+
+ ret = sss_iobuf_write_iobuf(buf, crd->cred_blob);
+ if (ret != EOK) {
+ return ret;
+ }
+ }
+
+ return EOK;
+}
+
+errno_t kcm_ccache_to_sec_input_binary(TALLOC_CTX *mem_ctx,
+ struct kcm_ccache *cc,
+ struct sss_iobuf **_payload)
+{
+ struct sss_iobuf *buf;
+ errno_t ret;
+
+ buf = sss_iobuf_init_empty(mem_ctx, sizeof(krb5_principal_data), 0);
+ if (buf == NULL) {
+ return ENOMEM;
+ }
+
+ ret = sss_iobuf_write_int32(buf, cc->kdc_offset);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ ret = princ_to_bin(cc->client, buf);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ ret = creds_to_bin(cc->creds, buf);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ *_payload = buf;
+
+ ret = EOK;
+
+done:
+ if (ret != EOK) {
+ talloc_free(buf);
+ }
+
+ return ret;
+}
+
+static errno_t bin_to_krb_data(TALLOC_CTX *mem_ctx,
+ struct sss_iobuf *buf,
+ krb5_data *out)
+{
+ uint8_t *data;
+ size_t len;
+ errno_t ret;
+
+ ret = sss_iobuf_read_varlen(mem_ctx, buf, &data, &len);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ out->magic = 0;
+ out->data = (char*)data;
+ out->length = len;
+
+ return EOK;
+}
+
+static errno_t bin_to_princ(TALLOC_CTX *mem_ctx,
+ struct sss_iobuf *buf,
+ krb5_principal *_princ)
+{
+ krb5_principal princ;
+ uint8_t non_empty;
+ krb5_int32 i;
+ errno_t ret;
+
+ ret = sss_iobuf_read_uint8(buf, &non_empty);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ if (non_empty == 0) {
+ *_princ = NULL;
+ return EOK;
+ }
+
+ princ = talloc_zero(mem_ctx, struct krb5_principal_data);
+ if (princ == NULL) {
+ return ENOMEM;
+ }
+ princ->magic = KV5M_PRINCIPAL;
+
+ ret = bin_to_krb_data(princ, buf, &princ->realm);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ ret = sss_iobuf_read_int32(buf, &princ->type);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ ret = sss_iobuf_read_int32(buf, &princ->length);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ princ->data = talloc_zero_array(princ, krb5_data, princ->length);
+ if (princ->length > 0 && princ->data == NULL) {
+ return ENOMEM;
+ }
+
+ for (i = 0; i < princ->length; i++) {
+ ret = bin_to_krb_data(princ, buf, &princ->data[i]);
+ if (ret != EOK) {
+ return ret;
+ }
+ }
+
+ *_princ = princ;
+
+ return EOK;
+}
+
+static errno_t bin_to_creds(TALLOC_CTX *mem_ctx,
+ struct sss_iobuf *buf,
+ struct kcm_cred **_creds)
+{
+ struct kcm_cred *creds = NULL;
+ struct kcm_cred *crd;
+ struct sss_iobuf *cred_blob;
+ uint32_t count;
+ uuid_t uuid;
+ errno_t ret;
+
+ ret = sss_iobuf_read_uint32(buf, &count);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ for (uint32_t i = 0; i < count; i++) {
+ ret = sss_iobuf_read_len(buf, sizeof(uuid_t), (uint8_t*)uuid);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ ret = sss_iobuf_read_iobuf(NULL, buf, &cred_blob);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ crd = kcm_cred_new(mem_ctx, uuid, cred_blob);
+ if (crd == NULL) {
+ talloc_free(cred_blob);
+ return ENOMEM;
+ }
+
+ DLIST_ADD(creds, crd);
+ }
+
+ *_creds = creds;
+
+ return EOK;
+}
+
+errno_t sec_kv_to_ccache_binary(TALLOC_CTX *mem_ctx,
+ const char *sec_key,
+ struct sss_iobuf *sec_value,
+ struct cli_creds *client,
+ struct kcm_ccache **_cc)
+{
+ struct kcm_ccache *cc;
+ errno_t ret;
+
+ cc = talloc_zero(mem_ctx, struct kcm_ccache);
+ if (cc == NULL) {
+ return ENOMEM;
+ }
+
+ ret = kcm_cc_set_header(cc, sec_key, client);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Cannot store ccache header [%d]: %s\n",
+ ret, sss_strerror(ret));
+ goto done;
+ }
+
+ ret = sss_iobuf_read_int32(sec_value, &cc->kdc_offset);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ ret = bin_to_princ(cc, sec_value, &cc->client);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ ret = bin_to_creds(cc, sec_value, &cc->creds);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ *_cc = cc;
+
+ ret = EOK;
+
+done:
+ if (ret != EOK) {
+ talloc_free(cc);
+ }
+
+ return ret;
+}
diff --git a/src/responder/kcm/kcmsrv_ccache_json.c b/src/responder/kcm/kcmsrv_ccache_json.c
index 7f73b56bf6c27417271876a989695ff917c3886e..e790cbea36d57d2ba0d4e25fc8fc249a4e653c3c 100644
--- a/src/responder/kcm/kcmsrv_ccache_json.c
+++ b/src/responder/kcm/kcmsrv_ccache_json.c
@@ -343,7 +343,6 @@ static errno_t ccache_to_sec_val(TALLOC_CTX *mem_ctx,
errno_t kcm_ccache_to_sec_input_json(TALLOC_CTX *mem_ctx,
struct kcm_ccache *cc,
- struct cli_creds *client,
struct sss_iobuf **_payload)
{
errno_t ret;
diff --git a/src/responder/kcm/kcmsrv_ccache_secdb.c b/src/responder/kcm/kcmsrv_ccache_secdb.c
index f5cfe47a7c6deac17031788105ac4235a6aaa9ff..726711ac441c40a6bfc84045e9b3e5b85505c7e0 100644
--- a/src/responder/kcm/kcmsrv_ccache_secdb.c
+++ b/src/responder/kcm/kcmsrv_ccache_secdb.c
@@ -37,11 +37,14 @@
static errno_t sec_get(TALLOC_CTX *mem_ctx,
struct sss_sec_req *req,
- struct sss_iobuf **_buf)
+ struct sss_iobuf **_buf,
+ char **_datatype)
{
errno_t ret;
TALLOC_CTX *tmp_ctx;
- char *secret;
+ char *datatype;
+ uint8_t *data;
+ size_t len;
struct sss_iobuf *buf;
tmp_ctx = talloc_new(mem_ctx);
@@ -49,23 +52,27 @@ static errno_t sec_get(TALLOC_CTX *mem_ctx,
return ENOMEM;
}
- ret = sss_sec_get(tmp_ctx, req, (uint8_t **)&secret, NULL, NULL);
+ ret = sss_sec_get(tmp_ctx, req, &data, &len, &datatype);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"Cannot retrieve the secret [%d]: %s\n", ret, sss_strerror(ret));
goto done;
}
- buf = sss_iobuf_init_readonly(tmp_ctx, (const uint8_t *)secret,
- strlen(secret) + 1);
+ buf = sss_iobuf_init_steal(tmp_ctx, data, len);
if (buf == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Cannot init the iobuf\n");
ret = EIO;
goto done;
}
- ret = EOK;
*_buf = talloc_steal(mem_ctx, buf);
+ if (_datatype != NULL) {
+ *_datatype = talloc_steal(mem_ctx, datatype);
+ }
+
+ ret = EOK;
+
done:
talloc_free(tmp_ctx);
return ret;
@@ -78,7 +85,7 @@ static errno_t sec_put(TALLOC_CTX *mem_ctx,
errno_t ret;
ret = sss_sec_put(req, sss_iobuf_get_data(buf), sss_iobuf_get_size(buf),
- SSS_SEC_PLAINTEXT, "simple");
+ SSS_SEC_PLAINTEXT, "binary");
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"Cannot write the secret [%d]: %s\n", ret, sss_strerror(ret));
@@ -94,7 +101,7 @@ static errno_t sec_update(TALLOC_CTX *mem_ctx,
errno_t ret;
ret = sss_sec_update(req, sss_iobuf_get_data(buf), sss_iobuf_get_size(buf),
- SSS_SEC_PLAINTEXT, "simple");
+ SSS_SEC_PLAINTEXT, "binary");
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"Cannot write the secret [%d]: %s\n", ret, sss_strerror(ret));
@@ -160,7 +167,7 @@ static errno_t kcm_ccache_to_secdb_kv(TALLOC_CTX *mem_ctx,
goto done;
}
- ret = kcm_ccache_to_sec_input_json(mem_ctx, cc, client, &payload);
+ ret = kcm_ccache_to_sec_input_binary(mem_ctx, cc, &payload);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Cannot convert ccache to a secret [%d][%s]\n", ret, sss_strerror(ret));
@@ -434,6 +441,7 @@ static errno_t secdb_get_cc(TALLOC_CTX *mem_ctx,
struct kcm_ccache *cc = NULL;
struct sss_sec_req *sreq = NULL;
struct sss_iobuf *ccbuf;
+ char *datatype;
tmp_ctx = talloc_new(mem_ctx);
if (tmp_ctx == NULL) {
@@ -447,20 +455,23 @@ static errno_t secdb_get_cc(TALLOC_CTX *mem_ctx,
goto done;
}
- ret = sec_get(tmp_ctx, sreq, &ccbuf);
+ ret = sec_get(tmp_ctx, sreq, &ccbuf, &datatype);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"Cannot get the secret [%d][%s]\n", ret, sss_strerror(ret));
goto done;
}
- ret = sec_kv_to_ccache_json(tmp_ctx, secdb_key,
- (const char *)sss_iobuf_get_data(ccbuf),
- client, &cc);
+ if (strcmp(datatype, "binary") == 0) {
+ ret = sec_kv_to_ccache_binary(tmp_ctx, secdb_key, ccbuf, client, &cc);
+ } else {
+ ret = sec_kv_to_ccache_json(tmp_ctx, secdb_key,
+ (const char *)sss_iobuf_get_data(ccbuf),
+ client, &cc);
+ }
if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE,
- "Cannot convert JSON keyval to ccache blob [%d]: %s\n",
- ret, sss_strerror(ret));
+ DEBUG(SSSDBG_OP_FAILURE, "Cannot convert %s data to ccache "
+ "[%d]: %s\n", datatype, ret, sss_strerror(ret));
goto done;
}
@@ -756,7 +767,7 @@ static struct tevent_req *ccdb_secdb_get_default_send(TALLOC_CTX *mem_ctx,
goto immediate;
}
- ret = sec_get(state, sreq, &dfl_iobuf);
+ ret = sec_get(state, sreq, &dfl_iobuf, NULL);
if (ret == ENOENT) {
uuid_clear(state->uuid);
ret = EOK;
@@ -1249,7 +1260,7 @@ static struct tevent_req *ccdb_secdb_mod_send(TALLOC_CTX *mem_ctx,
goto immediate;
}
- ret = kcm_ccache_to_sec_input_json(state, cc, client, &payload);
+ ret = kcm_ccache_to_sec_input_binary(state, cc, &payload);
if (ret != EOK) {
goto immediate;
}
@@ -1325,7 +1336,7 @@ static struct tevent_req *ccdb_secdb_store_cred_send(TALLOC_CTX *mem_ctx,
goto immediate;
}
- ret = kcm_ccache_to_sec_input_json(state, cc, client, &payload);
+ ret = kcm_ccache_to_sec_input_binary(state, cc, &payload);
if (ret != EOK) {
goto immediate;
}
diff --git a/src/responder/kcm/kcmsrv_ccache_secrets.c b/src/responder/kcm/kcmsrv_ccache_secrets.c
index 9d1fe8cad2dc6ed3ab43e181d0db52673d4759cc..f3d69842cf8c230800aaf4fc6554495fcf03f57d 100644
--- a/src/responder/kcm/kcmsrv_ccache_secrets.c
+++ b/src/responder/kcm/kcmsrv_ccache_secrets.c
@@ -195,7 +195,7 @@ static errno_t kcm_ccache_to_sec_kv(TALLOC_CTX *mem_ctx,
goto done;
}
- ret = kcm_ccache_to_sec_input_json(mem_ctx, cc, client, &payload);
+ ret = kcm_ccache_to_sec_input_json(mem_ctx, cc, &payload);
if (ret != EOK) {
goto done;
}
diff --git a/src/tests/cmocka/test_kcm_marshalling.c b/src/tests/cmocka/test_kcm_marshalling.c
index f82129974787bba6883662a732311f3370bcc4f1..cebebac804b0a8a109084b35f58d4aab21e28da2 100644
--- a/src/tests/cmocka/test_kcm_marshalling.c
+++ b/src/tests/cmocka/test_kcm_marshalling.c
@@ -182,7 +182,7 @@ static void test_kcm_ccache_marshall_unmarshall_json(void **state)
&cc);
assert_int_equal(ret, EOK);
- ret = kcm_ccache_to_sec_input_json(test_ctx, cc, &owner, &payload);
+ ret = kcm_ccache_to_sec_input_json(test_ctx, cc, &payload);
assert_int_equal(ret, EOK);
data = sss_iobuf_get_data(payload);
@@ -237,7 +237,7 @@ static void test_kcm_ccache_no_princ_json(void **state)
princ = kcm_cc_get_client_principal(cc);
assert_null(princ);
- ret = kcm_ccache_to_sec_input_json(test_ctx, cc, &owner, &payload);
+ ret = kcm_ccache_to_sec_input_json(test_ctx, cc, &payload);
assert_int_equal(ret, EOK);
data = sss_iobuf_get_data(payload);
@@ -255,6 +255,108 @@ static void test_kcm_ccache_no_princ_json(void **state)
assert_cc_equal(cc, cc2);
}
+static void test_kcm_ccache_marshall_unmarshall_binary(void **state)
+{
+ struct kcm_marshalling_test_ctx *test_ctx = talloc_get_type(*state,
+ struct kcm_marshalling_test_ctx);
+ errno_t ret;
+ struct cli_creds owner;
+ struct kcm_ccache *cc;
+ struct kcm_ccache *cc2;
+ struct sss_iobuf *payload;
+ const char *name;
+ const char *key;
+ uint8_t *data;
+ uuid_t uuid;
+
+ owner.ucred.uid = getuid();
+ owner.ucred.gid = getuid();
+
+ name = talloc_asprintf(test_ctx, "%"SPRIuid, getuid());
+ assert_non_null(name);
+
+ ret = kcm_cc_new(test_ctx,
+ test_ctx->kctx,
+ &owner,
+ name,
+ test_ctx->princ,
+ &cc);
+ assert_int_equal(ret, EOK);
+
+ ret = kcm_ccache_to_sec_input_binary(test_ctx, cc, &payload);
+ assert_int_equal(ret, EOK);
+
+ data = sss_iobuf_get_data(payload);
+ assert_non_null(data);
+
+ ret = kcm_cc_get_uuid(cc, uuid);
+ assert_int_equal(ret, EOK);
+ key = sec_key_create(test_ctx, name, uuid);
+ assert_non_null(key);
+
+ sss_iobuf_cursor_reset(payload);
+ ret = sec_kv_to_ccache_binary(test_ctx, key, payload, &owner, &cc2);
+ assert_int_equal(ret, EOK);
+
+ assert_cc_equal(cc, cc2);
+
+ /* This key is exactly one byte shorter than it should be */
+ sss_iobuf_cursor_reset(payload);
+ ret = sec_kv_to_ccache_binary(test_ctx, TEST_UUID_STR "-", payload, &owner,
+ &cc2);
+ assert_int_equal(ret, EINVAL);
+}
+
+static void test_kcm_ccache_no_princ_binary(void **state)
+{
+ struct kcm_marshalling_test_ctx *test_ctx = talloc_get_type(*state,
+ struct kcm_marshalling_test_ctx);
+ errno_t ret;
+ struct cli_creds owner;
+ const char *name;
+ struct kcm_ccache *cc;
+ krb5_principal princ;
+ struct kcm_ccache *cc2;
+ struct sss_iobuf *payload;
+ const char *key;
+ uint8_t *data;
+ uuid_t uuid;
+
+ owner.ucred.uid = getuid();
+ owner.ucred.gid = getuid();
+
+ name = talloc_asprintf(test_ctx, "%"SPRIuid, getuid());
+ assert_non_null(name);
+
+ ret = kcm_cc_new(test_ctx,
+ test_ctx->kctx,
+ &owner,
+ name,
+ NULL,
+ &cc);
+ assert_int_equal(ret, EOK);
+
+ princ = kcm_cc_get_client_principal(cc);
+ assert_null(princ);
+
+ ret = kcm_ccache_to_sec_input_binary(test_ctx, cc, &payload);
+ assert_int_equal(ret, EOK);
+
+ data = sss_iobuf_get_data(payload);
+ assert_non_null(data);
+
+ ret = kcm_cc_get_uuid(cc, uuid);
+ assert_int_equal(ret, EOK);
+ key = sec_key_create(test_ctx, name, uuid);
+ assert_non_null(key);
+
+ sss_iobuf_cursor_reset(payload);
+ ret = sec_kv_to_ccache_binary(test_ctx, key, payload, &owner, &cc2);
+ assert_int_equal(ret, EOK);
+
+ assert_cc_equal(cc, cc2);
+}
+
void test_sec_key_get_uuid(void **state)
{
errno_t ret;
@@ -325,6 +427,12 @@ int main(int argc, const char *argv[])
};
const struct CMUnitTest tests[] = {
+ cmocka_unit_test_setup_teardown(test_kcm_ccache_marshall_unmarshall_binary,
+ setup_kcm_marshalling,
+ teardown_kcm_marshalling),
+ cmocka_unit_test_setup_teardown(test_kcm_ccache_no_princ_binary,
+ setup_kcm_marshalling,
+ teardown_kcm_marshalling),
cmocka_unit_test_setup_teardown(test_kcm_ccache_marshall_unmarshall_json,
setup_kcm_marshalling,
teardown_kcm_marshalling),
diff --git a/src/tests/multihost/basic/test_kcm.py b/src/tests/multihost/basic/test_kcm.py
index e5d315827b31f205216d6a20768533ef50983537..6f65431f88b0e77110c3a89c24363d28027390f6 100644
--- a/src/tests/multihost/basic/test_kcm.py
+++ b/src/tests/multihost/basic/test_kcm.py
@@ -310,6 +310,12 @@ class TestSanityKCM(object):
set_param(multihost, 'kcm', 'max_ccache_size', '1')
self._restart_kcm(multihost)
- with pytest.raises(paramiko.ssh_exception.AuthenticationException):
- ssh_foo3 = SSHClient(multihost.master[0].sys_hostname,
- username='foo3', password='Secret123')
+ # We use kinit to exceed the maximum ccache size as it creates payload
+ # of 1280 bytes by acquiring tgt and also some control credentials.
+ # SSH authentication is not sufficient as it stores only tgt.
+ ssh_foo3 = SSHClient(multihost.master[0].sys_hostname,
+ username='foo3', password='Secret123')
+ (_, _, exit_status) = ssh_foo3.execute_cmd(
+ 'kinit foo3@EXAMPLE.TEST', 'Secret123'
+ )
+ assert exit_status != 0
diff --git a/src/util/secrets/secrets.c b/src/util/secrets/secrets.c
index 2a7149ae8b1c88623784ffd4f3e7f908be15c662..6fd9e0af5bd9986052efdb8e244ddeb9e4fa50ff 100644
--- a/src/util/secrets/secrets.c
+++ b/src/util/secrets/secrets.c
@@ -36,7 +36,7 @@
#define SECRETS_BASEDN "cn=secrets"
#define KCM_BASEDN "cn=kcm"
-#define LOCAL_SIMPLE_FILTER "(type=simple)"
+#define LOCAL_SIMPLE_FILTER "(|(type=simple)(type=binary))"
#define LOCAL_CONTAINER_FILTER "(type=container)"
typedef int (*url_mapper_fn)(TALLOC_CTX *mem_ctx,
--
2.25.4