|
|
71e593 |
From 7c441a13215dfd87f9facdaf5f6bcc19a25ec472 Mon Sep 17 00:00:00 2001
|
|
|
71e593 |
From: Jakub Hrozek <jhrozek@redhat.com>
|
|
|
71e593 |
Date: Wed, 16 Jan 2019 13:02:01 +0100
|
|
|
71e593 |
Subject: [PATCH 97/99] KCM: Allow representing ccaches with a NULL principal
|
|
|
71e593 |
MIME-Version: 1.0
|
|
|
71e593 |
Content-Type: text/plain; charset=UTF-8
|
|
|
71e593 |
Content-Transfer-Encoding: 8bit
|
|
|
71e593 |
|
|
|
71e593 |
Related:
|
|
|
71e593 |
https://pagure.io/SSSD/sssd/issue/3873
|
|
|
71e593 |
|
|
|
71e593 |
We need to make it possible to create an internal ccache representation
|
|
|
71e593 |
without passing in a principal. The principal is only assigned to the
|
|
|
71e593 |
ccache with krb5_cc_initialize(), but some programs like openssh use the
|
|
|
71e593 |
following sequence of calls:
|
|
|
71e593 |
krb5_cc_new_unique
|
|
|
71e593 |
krb5_cc_switch
|
|
|
71e593 |
krb5_cc_initialize
|
|
|
71e593 |
|
|
|
71e593 |
Reviewed-by: Michal Židek <mzidek@redhat.com>
|
|
|
71e593 |
Reviewed-by: Simo Sorce <simo@redhat.com>
|
|
|
71e593 |
---
|
|
|
71e593 |
src/responder/kcm/kcmsrv_ccache.c | 18 +++--
|
|
|
71e593 |
src/responder/kcm/kcmsrv_ccache_json.c | 79 ++++++++++++++++---
|
|
|
71e593 |
src/tests/cmocka/test_kcm_json_marshalling.c | 83 ++++++++++++++++++--
|
|
|
71e593 |
3 files changed, 153 insertions(+), 27 deletions(-)
|
|
|
71e593 |
|
|
|
71e593 |
diff --git a/src/responder/kcm/kcmsrv_ccache.c b/src/responder/kcm/kcmsrv_ccache.c
|
|
|
71e593 |
index af2bcf8bb..e7800662a 100644
|
|
|
71e593 |
--- a/src/responder/kcm/kcmsrv_ccache.c
|
|
|
71e593 |
+++ b/src/responder/kcm/kcmsrv_ccache.c
|
|
|
71e593 |
@@ -68,14 +68,16 @@ errno_t kcm_cc_new(TALLOC_CTX *mem_ctx,
|
|
|
71e593 |
|
|
|
71e593 |
uuid_generate(cc->uuid);
|
|
|
71e593 |
|
|
|
71e593 |
- kret = krb5_copy_principal(k5c, princ, &cc->client);
|
|
|
71e593 |
- if (kret != 0) {
|
|
|
71e593 |
- const char *err_msg = sss_krb5_get_error_message(k5c, kret);
|
|
|
71e593 |
- DEBUG(SSSDBG_OP_FAILURE,
|
|
|
71e593 |
- "krb5_copy_principal failed: [%d][%s]\n", kret, err_msg);
|
|
|
71e593 |
- sss_krb5_free_error_message(k5c, err_msg);
|
|
|
71e593 |
- ret = ERR_INTERNAL;
|
|
|
71e593 |
- goto done;
|
|
|
71e593 |
+ if (princ) {
|
|
|
71e593 |
+ kret = krb5_copy_principal(k5c, princ, &cc->client);
|
|
|
71e593 |
+ if (kret != 0) {
|
|
|
71e593 |
+ const char *err_msg = sss_krb5_get_error_message(k5c, kret);
|
|
|
71e593 |
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
|
71e593 |
+ "krb5_copy_principal failed: [%d][%s]\n", kret, err_msg);
|
|
|
71e593 |
+ sss_krb5_free_error_message(k5c, err_msg);
|
|
|
71e593 |
+ ret = ERR_INTERNAL;
|
|
|
71e593 |
+ goto done;
|
|
|
71e593 |
+ }
|
|
|
71e593 |
}
|
|
|
71e593 |
|
|
|
71e593 |
cc->owner.uid = cli_creds_get_uid(owner);
|
|
|
71e593 |
diff --git a/src/responder/kcm/kcmsrv_ccache_json.c b/src/responder/kcm/kcmsrv_ccache_json.c
|
|
|
71e593 |
index 6341530ee..72e24c430 100644
|
|
|
71e593 |
--- a/src/responder/kcm/kcmsrv_ccache_json.c
|
|
|
71e593 |
+++ b/src/responder/kcm/kcmsrv_ccache_json.c
|
|
|
71e593 |
@@ -229,6 +229,20 @@ static json_t *princ_to_json(TALLOC_CTX *mem_ctx,
|
|
|
71e593 |
json_error_t error;
|
|
|
71e593 |
char *str_realm_data;
|
|
|
71e593 |
|
|
|
71e593 |
+ if (princ == NULL) {
|
|
|
71e593 |
+ jprinc = json_pack_ex(&error,
|
|
|
71e593 |
+ JSON_STRICT,
|
|
|
71e593 |
+ "{}");
|
|
|
71e593 |
+ if (jprinc == NULL) {
|
|
|
71e593 |
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
|
|
71e593 |
+ "Failed to pack JSON princ structure on line %d: %s\n",
|
|
|
71e593 |
+ error.line, error.text);
|
|
|
71e593 |
+ return NULL;
|
|
|
71e593 |
+ }
|
|
|
71e593 |
+
|
|
|
71e593 |
+ return jprinc;
|
|
|
71e593 |
+ }
|
|
|
71e593 |
+
|
|
|
71e593 |
components = princ_data_to_json(mem_ctx, princ);
|
|
|
71e593 |
if (components == NULL) {
|
|
|
71e593 |
DEBUG(SSSDBG_CRIT_FAILURE,
|
|
|
71e593 |
@@ -587,13 +601,12 @@ static errno_t json_array_to_krb5_data(TALLOC_CTX *mem_ctx,
|
|
|
71e593 |
return EOK;
|
|
|
71e593 |
}
|
|
|
71e593 |
|
|
|
71e593 |
-static errno_t json_to_princ(TALLOC_CTX *mem_ctx,
|
|
|
71e593 |
- json_t *js_princ,
|
|
|
71e593 |
- krb5_principal *_princ)
|
|
|
71e593 |
+static errno_t json_to_nonempty_princ(TALLOC_CTX *mem_ctx,
|
|
|
71e593 |
+ json_t *js_princ,
|
|
|
71e593 |
+ krb5_principal *_princ)
|
|
|
71e593 |
{
|
|
|
71e593 |
errno_t ret;
|
|
|
71e593 |
json_t *components = NULL;
|
|
|
71e593 |
- int ok;
|
|
|
71e593 |
krb5_principal princ = NULL;
|
|
|
71e593 |
TALLOC_CTX *tmp_ctx = NULL;
|
|
|
71e593 |
char *realm_str;
|
|
|
71e593 |
@@ -601,13 +614,6 @@ static errno_t json_to_princ(TALLOC_CTX *mem_ctx,
|
|
|
71e593 |
size_t comp_count;
|
|
|
71e593 |
json_error_t error;
|
|
|
71e593 |
|
|
|
71e593 |
- ok = json_is_object(js_princ);
|
|
|
71e593 |
- if (!ok) {
|
|
|
71e593 |
- DEBUG(SSSDBG_CRIT_FAILURE, "Json principal is not an object.\n");
|
|
|
71e593 |
- ret = ERR_JSON_DECODING;
|
|
|
71e593 |
- goto done;
|
|
|
71e593 |
- }
|
|
|
71e593 |
-
|
|
|
71e593 |
tmp_ctx = talloc_new(mem_ctx);
|
|
|
71e593 |
if (tmp_ctx == NULL) {
|
|
|
71e593 |
ret = ENOMEM;
|
|
|
71e593 |
@@ -684,6 +690,57 @@ done:
|
|
|
71e593 |
return ret;
|
|
|
71e593 |
}
|
|
|
71e593 |
|
|
|
71e593 |
+static bool is_nonempty_principal(json_t *js_princ)
|
|
|
71e593 |
+{
|
|
|
71e593 |
+ errno_t ret;
|
|
|
71e593 |
+ json_error_t error;
|
|
|
71e593 |
+
|
|
|
71e593 |
+ ret = json_unpack_ex(js_princ,
|
|
|
71e593 |
+ &error,
|
|
|
71e593 |
+ JSON_VALIDATE_ONLY,
|
|
|
71e593 |
+ "{s:i, s:s, s:o}",
|
|
|
71e593 |
+ "type",
|
|
|
71e593 |
+ "realm",
|
|
|
71e593 |
+ "components");
|
|
|
71e593 |
+
|
|
|
71e593 |
+ return ret == 0 ? true : false;
|
|
|
71e593 |
+}
|
|
|
71e593 |
+
|
|
|
71e593 |
+static bool is_empty_principal(json_t *js_princ)
|
|
|
71e593 |
+{
|
|
|
71e593 |
+ errno_t ret;
|
|
|
71e593 |
+ json_error_t error;
|
|
|
71e593 |
+
|
|
|
71e593 |
+ ret = json_unpack_ex(js_princ,
|
|
|
71e593 |
+ &error,
|
|
|
71e593 |
+ JSON_VALIDATE_ONLY,
|
|
|
71e593 |
+ "{}");
|
|
|
71e593 |
+
|
|
|
71e593 |
+ return ret == 0 ? true : false;
|
|
|
71e593 |
+}
|
|
|
71e593 |
+
|
|
|
71e593 |
+static errno_t json_to_princ(TALLOC_CTX *mem_ctx,
|
|
|
71e593 |
+ json_t *js_princ,
|
|
|
71e593 |
+ krb5_principal *_princ)
|
|
|
71e593 |
+{
|
|
|
71e593 |
+ int ok;
|
|
|
71e593 |
+
|
|
|
71e593 |
+ ok = json_is_object(js_princ);
|
|
|
71e593 |
+ if (!ok) {
|
|
|
71e593 |
+ DEBUG(SSSDBG_CRIT_FAILURE, "Json principal is not an object.\n");
|
|
|
71e593 |
+ return ERR_JSON_DECODING;
|
|
|
71e593 |
+ }
|
|
|
71e593 |
+
|
|
|
71e593 |
+ if (is_nonempty_principal(js_princ)) {
|
|
|
71e593 |
+ return json_to_nonempty_princ(mem_ctx, js_princ, _princ);
|
|
|
71e593 |
+ } else if (is_empty_principal(js_princ)) {
|
|
|
71e593 |
+ *_princ = NULL;
|
|
|
71e593 |
+ return EOK;
|
|
|
71e593 |
+ }
|
|
|
71e593 |
+
|
|
|
71e593 |
+ return ERR_JSON_DECODING;
|
|
|
71e593 |
+}
|
|
|
71e593 |
+
|
|
|
71e593 |
static errno_t json_elem_to_cred(TALLOC_CTX *mem_ctx,
|
|
|
71e593 |
json_t *element,
|
|
|
71e593 |
struct kcm_cred **_crd)
|
|
|
71e593 |
diff --git a/src/tests/cmocka/test_kcm_json_marshalling.c b/src/tests/cmocka/test_kcm_json_marshalling.c
|
|
|
71e593 |
index 05d472499..48ee92bd6 100644
|
|
|
71e593 |
--- a/src/tests/cmocka/test_kcm_json_marshalling.c
|
|
|
71e593 |
+++ b/src/tests/cmocka/test_kcm_json_marshalling.c
|
|
|
71e593 |
@@ -116,14 +116,22 @@ static void assert_cc_princ_equal(struct kcm_ccache *cc1,
|
|
|
71e593 |
p1 = kcm_cc_get_client_principal(cc1);
|
|
|
71e593 |
p2 = kcm_cc_get_client_principal(cc2);
|
|
|
71e593 |
|
|
|
71e593 |
- kerr = krb5_unparse_name(NULL, p1, &name1);
|
|
|
71e593 |
- assert_int_equal(kerr, 0);
|
|
|
71e593 |
- kerr = krb5_unparse_name(NULL, p2, &name2);
|
|
|
71e593 |
- assert_int_equal(kerr, 0);
|
|
|
71e593 |
-
|
|
|
71e593 |
- assert_string_equal(name1, name2);
|
|
|
71e593 |
- krb5_free_unparsed_name(NULL, name1);
|
|
|
71e593 |
- krb5_free_unparsed_name(NULL, name2);
|
|
|
71e593 |
+ if (p1 != NULL && p2 != NULL) {
|
|
|
71e593 |
+ kerr = krb5_unparse_name(NULL, p1, &name1);
|
|
|
71e593 |
+ assert_int_equal(kerr, 0);
|
|
|
71e593 |
+ kerr = krb5_unparse_name(NULL, p2, &name2);
|
|
|
71e593 |
+ assert_int_equal(kerr, 0);
|
|
|
71e593 |
+
|
|
|
71e593 |
+ assert_string_equal(name1, name2);
|
|
|
71e593 |
+ krb5_free_unparsed_name(NULL, name1);
|
|
|
71e593 |
+ krb5_free_unparsed_name(NULL, name2);
|
|
|
71e593 |
+ } else {
|
|
|
71e593 |
+ /* Either both principals must be NULL or both
|
|
|
71e593 |
+ * non-NULL and represent the same principals
|
|
|
71e593 |
+ */
|
|
|
71e593 |
+ assert_null(p1);
|
|
|
71e593 |
+ assert_null(p2);
|
|
|
71e593 |
+ }
|
|
|
71e593 |
}
|
|
|
71e593 |
|
|
|
71e593 |
static void assert_cc_offset_equal(struct kcm_ccache *cc1,
|
|
|
71e593 |
@@ -206,6 +214,62 @@ static void test_kcm_ccache_marshall_unmarshall(void **state)
|
|
|
71e593 |
assert_int_equal(ret, EINVAL);
|
|
|
71e593 |
}
|
|
|
71e593 |
|
|
|
71e593 |
+static void test_kcm_ccache_no_princ(void **state)
|
|
|
71e593 |
+{
|
|
|
71e593 |
+ struct kcm_marshalling_test_ctx *test_ctx = talloc_get_type(*state,
|
|
|
71e593 |
+ struct kcm_marshalling_test_ctx);
|
|
|
71e593 |
+ errno_t ret;
|
|
|
71e593 |
+ struct cli_creds owner;
|
|
|
71e593 |
+ const char *name;
|
|
|
71e593 |
+ struct kcm_ccache *cc;
|
|
|
71e593 |
+ krb5_principal princ;
|
|
|
71e593 |
+ struct kcm_ccache *cc2;
|
|
|
71e593 |
+ struct sss_iobuf *payload;
|
|
|
71e593 |
+ const char *key;
|
|
|
71e593 |
+ uint8_t *data;
|
|
|
71e593 |
+ uuid_t uuid;
|
|
|
71e593 |
+
|
|
|
71e593 |
+ owner.ucred.uid = getuid();
|
|
|
71e593 |
+ owner.ucred.gid = getuid();
|
|
|
71e593 |
+
|
|
|
71e593 |
+ name = talloc_asprintf(test_ctx, "%"SPRIuid, getuid());
|
|
|
71e593 |
+ assert_non_null(name);
|
|
|
71e593 |
+
|
|
|
71e593 |
+ ret = kcm_cc_new(test_ctx,
|
|
|
71e593 |
+ test_ctx->kctx,
|
|
|
71e593 |
+ &owner,
|
|
|
71e593 |
+ name,
|
|
|
71e593 |
+ NULL,
|
|
|
71e593 |
+ &cc);
|
|
|
71e593 |
+ assert_int_equal(ret, EOK);
|
|
|
71e593 |
+
|
|
|
71e593 |
+ princ = kcm_cc_get_client_principal(cc);
|
|
|
71e593 |
+ assert_null(princ);
|
|
|
71e593 |
+
|
|
|
71e593 |
+ ret = kcm_ccache_to_sec_input(test_ctx,
|
|
|
71e593 |
+ cc,
|
|
|
71e593 |
+ &owner,
|
|
|
71e593 |
+ &payload);
|
|
|
71e593 |
+ assert_int_equal(ret, EOK);
|
|
|
71e593 |
+
|
|
|
71e593 |
+ data = sss_iobuf_get_data(payload);
|
|
|
71e593 |
+ assert_non_null(data);
|
|
|
71e593 |
+
|
|
|
71e593 |
+ ret = kcm_cc_get_uuid(cc, uuid);
|
|
|
71e593 |
+ assert_int_equal(ret, EOK);
|
|
|
71e593 |
+ key = sec_key_create(test_ctx, name, uuid);
|
|
|
71e593 |
+ assert_non_null(key);
|
|
|
71e593 |
+
|
|
|
71e593 |
+ ret = sec_kv_to_ccache(test_ctx,
|
|
|
71e593 |
+ key,
|
|
|
71e593 |
+ (const char *) data,
|
|
|
71e593 |
+ &owner,
|
|
|
71e593 |
+ &cc2;;
|
|
|
71e593 |
+ assert_int_equal(ret, EOK);
|
|
|
71e593 |
+
|
|
|
71e593 |
+ assert_cc_equal(cc, cc2);
|
|
|
71e593 |
+}
|
|
|
71e593 |
+
|
|
|
71e593 |
void test_sec_key_get_uuid(void **state)
|
|
|
71e593 |
{
|
|
|
71e593 |
errno_t ret;
|
|
|
71e593 |
@@ -279,6 +343,9 @@ int main(int argc, const char *argv[])
|
|
|
71e593 |
cmocka_unit_test_setup_teardown(test_kcm_ccache_marshall_unmarshall,
|
|
|
71e593 |
setup_kcm_marshalling,
|
|
|
71e593 |
teardown_kcm_marshalling),
|
|
|
71e593 |
+ cmocka_unit_test_setup_teardown(test_kcm_ccache_no_princ,
|
|
|
71e593 |
+ setup_kcm_marshalling,
|
|
|
71e593 |
+ teardown_kcm_marshalling),
|
|
|
71e593 |
cmocka_unit_test(test_sec_key_get_uuid),
|
|
|
71e593 |
cmocka_unit_test(test_sec_key_get_name),
|
|
|
71e593 |
cmocka_unit_test(test_sec_key_match_name),
|
|
|
71e593 |
--
|
|
|
71e593 |
2.19.1
|
|
|
71e593 |
|