summaryrefslogtreecommitdiffstats
path: root/src/responder/kcm/kcmsrv_ccache_binary.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 05:31:45 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 05:31:45 +0000
commit74aa0bc6779af38018a03fd2cf4419fe85917904 (patch)
tree9cb0681aac9a94a49c153d5823e7a55d1513d91f /src/responder/kcm/kcmsrv_ccache_binary.c
parentInitial commit. (diff)
downloadsssd-74aa0bc6779af38018a03fd2cf4419fe85917904.tar.xz
sssd-74aa0bc6779af38018a03fd2cf4419fe85917904.zip
Adding upstream version 2.9.4.upstream/2.9.4
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/responder/kcm/kcmsrv_ccache_binary.c')
-rw-r--r--src/responder/kcm/kcmsrv_ccache_binary.c308
1 files changed, 308 insertions, 0 deletions
diff --git a/src/responder/kcm/kcmsrv_ccache_binary.c b/src/responder/kcm/kcmsrv_ccache_binary.c
new file mode 100644
index 0000000..cc4191a
--- /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;
+}
+
+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_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;
+}