Blame SOURCES/0021-UTIL-krb5-principal-un-marshalling.patch

bb7cd1
From aa309f35905951c6fdd12d286bb3aeeb61a62088 Mon Sep 17 00:00:00 2001
bb7cd1
From: Jakub Hrozek <jhrozek@redhat.com>
bb7cd1
Date: Tue, 20 Sep 2016 22:03:30 +0200
bb7cd1
Subject: [PATCH 21/36] UTIL: krb5 principal (un)marshalling
bb7cd1
MIME-Version: 1.0
bb7cd1
Content-Type: text/plain; charset=UTF-8
bb7cd1
Content-Transfer-Encoding: 8bit
bb7cd1
bb7cd1
The KCM responder needs to read the contents of the principal blob that
bb7cd1
the Kerberos library sends. Since libkrb5 doesn't export any API to do
bb7cd1
so, we need to implement marshalling and unmarshalling of the principal
bb7cd1
ourselves.
bb7cd1
bb7cd1
In future, when the KCM server also supports renewals, we will also need
bb7cd1
to unmarshall the credentials, but until that is not really needed, the
bb7cd1
credentials will be stored as a blob.
bb7cd1
bb7cd1
Reviewed-by: Michal Židek <mzidek@redhat.com>
bb7cd1
Reviewed-by: Simo Sorce <simo@redhat.com>
bb7cd1
---
bb7cd1
 src/util/sss_krb5.c | 195 ++++++++++++++++++++++++++++++++++++++++++++++++++++
bb7cd1
 src/util/sss_krb5.h |   9 +++
bb7cd1
 2 files changed, 204 insertions(+)
bb7cd1
bb7cd1
diff --git a/src/util/sss_krb5.c b/src/util/sss_krb5.c
bb7cd1
index 4808a7703d07bb4eba91f14a7a515aadaec1774b..d461cf881566af37f31524c16f6a5f1511a5dc89 100644
bb7cd1
--- a/src/util/sss_krb5.c
bb7cd1
+++ b/src/util/sss_krb5.c
bb7cd1
@@ -24,6 +24,7 @@
bb7cd1
 
bb7cd1
 #include "config.h"
bb7cd1
 
bb7cd1
+#include "util/sss_iobuf.h"
bb7cd1
 #include "util/util.h"
bb7cd1
 #include "util/sss_krb5.h"
bb7cd1
 
bb7cd1
@@ -1128,3 +1129,197 @@ done:
bb7cd1
 
bb7cd1
     return res;
bb7cd1
 }
bb7cd1
+
bb7cd1
+static errno_t iobuf_read_uint32be(struct sss_iobuf *iobuf,
bb7cd1
+                                   uint32_t *_val)
bb7cd1
+{
bb7cd1
+    uint32_t beval;
bb7cd1
+    errno_t ret;
bb7cd1
+
bb7cd1
+    ret = sss_iobuf_read_uint32(iobuf, &beval);
bb7cd1
+    if (ret != EOK) {
bb7cd1
+        return ret;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    *_val = be32toh(beval);
bb7cd1
+    return EOK;
bb7cd1
+}
bb7cd1
+
bb7cd1
+static errno_t iobuf_write_uint32be(struct sss_iobuf *iobuf,
bb7cd1
+                                    uint32_t val)
bb7cd1
+{
bb7cd1
+    uint32_t beval;
bb7cd1
+
bb7cd1
+    beval = htobe32(val);
bb7cd1
+    return sss_iobuf_write_uint32(iobuf, beval);
bb7cd1
+}
bb7cd1
+
bb7cd1
+static errno_t iobuf_get_len_bytes(TALLOC_CTX *mem_ctx,
bb7cd1
+                                   struct sss_iobuf *iobuf,
bb7cd1
+                                   uint32_t *_nbytes,
bb7cd1
+                                   uint8_t **_bytes)
bb7cd1
+{
bb7cd1
+    errno_t ret;
bb7cd1
+    uint32_t nbytes;
bb7cd1
+    uint8_t *bytes = NULL;
bb7cd1
+
bb7cd1
+    ret = iobuf_read_uint32be(iobuf, &nbytes);
bb7cd1
+    if (ret != EOK) {
bb7cd1
+        return ret;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    bytes = talloc_zero_size(mem_ctx, nbytes);
bb7cd1
+    if (bytes == NULL) {
bb7cd1
+        return ENOMEM;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    ret = sss_iobuf_read_len(iobuf, nbytes, bytes);
bb7cd1
+    if (ret != EOK) {
bb7cd1
+        talloc_free(bytes);
bb7cd1
+        return ret;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    *_bytes = bytes;
bb7cd1
+    *_nbytes = nbytes;
bb7cd1
+    return EOK;
bb7cd1
+}
bb7cd1
+
bb7cd1
+static errno_t get_krb5_data(TALLOC_CTX *mem_ctx,
bb7cd1
+                             struct sss_iobuf *iobuf,
bb7cd1
+                             krb5_data *k5data)
bb7cd1
+{
bb7cd1
+    errno_t ret;
bb7cd1
+    uint32_t nbytes;
bb7cd1
+    uint8_t *bytes = NULL;
bb7cd1
+
bb7cd1
+    ret = iobuf_get_len_bytes(mem_ctx, iobuf,  &nbytes, &bytes);
bb7cd1
+    if (ret != EOK) {
bb7cd1
+        talloc_free(bytes);
bb7cd1
+        return ret;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    k5data->data = (char *) bytes; /* FIXME - the cast is ugly */
bb7cd1
+    k5data->length = nbytes;
bb7cd1
+    return EOK;
bb7cd1
+}
bb7cd1
+
bb7cd1
+static errno_t set_krb5_data(struct sss_iobuf *iobuf,
bb7cd1
+                             krb5_data *k5data)
bb7cd1
+{
bb7cd1
+    errno_t ret;
bb7cd1
+
bb7cd1
+    ret = iobuf_write_uint32be(iobuf, k5data->length);
bb7cd1
+    if (ret != EOK) {
bb7cd1
+        return ret;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    if (k5data->length > 0) {
bb7cd1
+        ret = sss_iobuf_write_len(iobuf,
bb7cd1
+                                  (uint8_t *) k5data->data,
bb7cd1
+                                  k5data->length);
bb7cd1
+        if (ret != EOK) {
bb7cd1
+            return ret;
bb7cd1
+        }
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    return EOK;
bb7cd1
+}
bb7cd1
+
bb7cd1
+/* FIXME - it would be nice if Kerberos exported these APIs.. */
bb7cd1
+krb5_error_code sss_krb5_unmarshal_princ(TALLOC_CTX *mem_ctx,
bb7cd1
+                                         struct sss_iobuf *iobuf,
bb7cd1
+                                         krb5_principal *_princ)
bb7cd1
+{
bb7cd1
+    krb5_principal princ = NULL;
bb7cd1
+    krb5_error_code ret;
bb7cd1
+    uint32_t ncomps;
bb7cd1
+
bb7cd1
+    if (iobuf == NULL || _princ == NULL) {
bb7cd1
+        return EINVAL;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    princ = talloc_zero(mem_ctx, struct krb5_principal_data);
bb7cd1
+    if (princ == NULL) {
bb7cd1
+        return ENOMEM;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    princ->magic = KV5M_PRINCIPAL;
bb7cd1
+
bb7cd1
+    ret = iobuf_read_uint32be(iobuf, (uint32_t *) &princ->type);
bb7cd1
+    if (ret != EOK) {
bb7cd1
+        goto fail;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    ret = iobuf_read_uint32be(iobuf, &ncomps);
bb7cd1
+    if (ret != EOK) {
bb7cd1
+        goto fail;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    if (ncomps > sss_iobuf_get_capacity(iobuf)) {
bb7cd1
+        /* Sanity check to avoid large allocations */
bb7cd1
+        ret = EINVAL;
bb7cd1
+        goto fail;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    if (ncomps != 0) {
bb7cd1
+        princ->data = talloc_zero_array(princ, krb5_data, ncomps);
bb7cd1
+        if (princ->data == NULL) {
bb7cd1
+            ret = ENOMEM;
bb7cd1
+            goto fail;
bb7cd1
+        }
bb7cd1
+
bb7cd1
+        princ->length = ncomps;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    ret = get_krb5_data(princ, iobuf, &princ->realm);
bb7cd1
+    if (ret != EOK) {
bb7cd1
+        goto fail;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    for (size_t i = 0; i < ncomps; i++) {
bb7cd1
+        ret = get_krb5_data(princ->data, iobuf, &princ->data[i]);
bb7cd1
+        if (ret != EOK) {
bb7cd1
+            goto fail;
bb7cd1
+        }
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    *_princ = princ;
bb7cd1
+    return 0;
bb7cd1
+
bb7cd1
+fail:
bb7cd1
+    talloc_free(princ);
bb7cd1
+    return ret;
bb7cd1
+}
bb7cd1
+
bb7cd1
+krb5_error_code sss_krb5_marshal_princ(krb5_principal princ,
bb7cd1
+                                       struct sss_iobuf *iobuf)
bb7cd1
+{
bb7cd1
+    krb5_error_code ret;
bb7cd1
+
bb7cd1
+    if (iobuf == NULL || princ == NULL) {
bb7cd1
+        return EINVAL;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    ret = iobuf_write_uint32be(iobuf, princ->type);
bb7cd1
+    if (ret != EOK) {
bb7cd1
+        return ret;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    ret = iobuf_write_uint32be(iobuf, princ->length);
bb7cd1
+    if (ret != EOK) {
bb7cd1
+        return ret;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    ret = set_krb5_data(iobuf, &princ->realm);
bb7cd1
+    if (ret != EOK) {
bb7cd1
+        return ret;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    for (int i = 0; i < princ->length; i++) {
bb7cd1
+        ret = set_krb5_data(iobuf, &princ->data[i]);
bb7cd1
+        if (ret != EOK) {
bb7cd1
+            return ret;
bb7cd1
+        }
bb7cd1
+    }
bb7cd1
+    return EOK;
bb7cd1
+}
bb7cd1
diff --git a/src/util/sss_krb5.h b/src/util/sss_krb5.h
bb7cd1
index ac0f6082c75a8878f72346733e592b7575d44089..0d9043be98749b1a21a1b74c68f07298fa27f230 100644
bb7cd1
--- a/src/util/sss_krb5.h
bb7cd1
+++ b/src/util/sss_krb5.h
bb7cd1
@@ -32,6 +32,7 @@
bb7cd1
 #include <krb5.h>
bb7cd1
 #endif
bb7cd1
 
bb7cd1
+#include "util/sss_iobuf.h"
bb7cd1
 #include "util/util.h"
bb7cd1
 
bb7cd1
 #define KRB5_CHILD_LOG_FILE     "krb5_child"
bb7cd1
@@ -186,4 +187,12 @@ krb5_error_code sss_krb5_kt_have_content(krb5_context context,
bb7cd1
                                          krb5_keytab keytab);
bb7cd1
 
bb7cd1
 bool sss_krb5_realm_has_proxy(const char *realm);
bb7cd1
+
bb7cd1
+krb5_error_code sss_krb5_marshal_princ(krb5_principal princ,
bb7cd1
+                                       struct sss_iobuf *iobuf);
bb7cd1
+
bb7cd1
+krb5_error_code sss_krb5_unmarshal_princ(TALLOC_CTX *mem_ctx,
bb7cd1
+                                         struct sss_iobuf *iobuf,
bb7cd1
+                                         krb5_principal *_princ);
bb7cd1
+
bb7cd1
 #endif /* __SSS_KRB5_H__ */
bb7cd1
-- 
bb7cd1
2.9.3
bb7cd1