summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJakub Hrozek <jhrozek@redhat.com>2016-09-20 22:03:30 +0200
committerJakub Hrozek <jhrozek@redhat.com>2017-03-27 09:56:11 +0200
commit1dbf09404e20b6e30a24afe72b6d349734aee62f (patch)
tree690112ab391a03c2e7845e8f04d6f0f857d0a095 /src
parent5f7f45a64bdb9353f15b945db4ad2564b4b28ab2 (diff)
downloadsssd-1dbf09404e20b6e30a24afe72b6d349734aee62f.tar.gz
sssd-1dbf09404e20b6e30a24afe72b6d349734aee62f.tar.xz
sssd-1dbf09404e20b6e30a24afe72b6d349734aee62f.zip
UTIL: krb5 principal (un)marshalling
The KCM responder needs to read the contents of the principal blob that the Kerberos library sends. Since libkrb5 doesn't export any API to do so, we need to implement marshalling and unmarshalling of the principal ourselves. In future, when the KCM server also supports renewals, we will also need to unmarshall the credentials, but until that is not really needed, the credentials will be stored as a blob. Reviewed-by: Michal Židek <mzidek@redhat.com> Reviewed-by: Simo Sorce <simo@redhat.com>
Diffstat (limited to 'src')
-rw-r--r--src/util/sss_krb5.c195
-rw-r--r--src/util/sss_krb5.h9
2 files changed, 204 insertions, 0 deletions
diff --git a/src/util/sss_krb5.c b/src/util/sss_krb5.c
index 4808a7703..d461cf881 100644
--- a/src/util/sss_krb5.c
+++ b/src/util/sss_krb5.c
@@ -24,6 +24,7 @@
#include "config.h"
+#include "util/sss_iobuf.h"
#include "util/util.h"
#include "util/sss_krb5.h"
@@ -1128,3 +1129,197 @@ done:
return res;
}
+
+static errno_t iobuf_read_uint32be(struct sss_iobuf *iobuf,
+ uint32_t *_val)
+{
+ uint32_t beval;
+ errno_t ret;
+
+ ret = sss_iobuf_read_uint32(iobuf, &beval);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ *_val = be32toh(beval);
+ return EOK;
+}
+
+static errno_t iobuf_write_uint32be(struct sss_iobuf *iobuf,
+ uint32_t val)
+{
+ uint32_t beval;
+
+ beval = htobe32(val);
+ return sss_iobuf_write_uint32(iobuf, beval);
+}
+
+static errno_t iobuf_get_len_bytes(TALLOC_CTX *mem_ctx,
+ struct sss_iobuf *iobuf,
+ uint32_t *_nbytes,
+ uint8_t **_bytes)
+{
+ errno_t ret;
+ uint32_t nbytes;
+ uint8_t *bytes = NULL;
+
+ ret = iobuf_read_uint32be(iobuf, &nbytes);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ bytes = talloc_zero_size(mem_ctx, nbytes);
+ if (bytes == NULL) {
+ return ENOMEM;
+ }
+
+ ret = sss_iobuf_read_len(iobuf, nbytes, bytes);
+ if (ret != EOK) {
+ talloc_free(bytes);
+ return ret;
+ }
+
+ *_bytes = bytes;
+ *_nbytes = nbytes;
+ return EOK;
+}
+
+static errno_t get_krb5_data(TALLOC_CTX *mem_ctx,
+ struct sss_iobuf *iobuf,
+ krb5_data *k5data)
+{
+ errno_t ret;
+ uint32_t nbytes;
+ uint8_t *bytes = NULL;
+
+ ret = iobuf_get_len_bytes(mem_ctx, iobuf, &nbytes, &bytes);
+ if (ret != EOK) {
+ talloc_free(bytes);
+ return ret;
+ }
+
+ k5data->data = (char *) bytes; /* FIXME - the cast is ugly */
+ k5data->length = nbytes;
+ return EOK;
+}
+
+static errno_t set_krb5_data(struct sss_iobuf *iobuf,
+ krb5_data *k5data)
+{
+ errno_t ret;
+
+ ret = iobuf_write_uint32be(iobuf, k5data->length);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ if (k5data->length > 0) {
+ ret = sss_iobuf_write_len(iobuf,
+ (uint8_t *) k5data->data,
+ k5data->length);
+ if (ret != EOK) {
+ return ret;
+ }
+ }
+
+ return EOK;
+}
+
+/* FIXME - it would be nice if Kerberos exported these APIs.. */
+krb5_error_code sss_krb5_unmarshal_princ(TALLOC_CTX *mem_ctx,
+ struct sss_iobuf *iobuf,
+ krb5_principal *_princ)
+{
+ krb5_principal princ = NULL;
+ krb5_error_code ret;
+ uint32_t ncomps;
+
+ if (iobuf == NULL || _princ == NULL) {
+ return EINVAL;
+ }
+
+ princ = talloc_zero(mem_ctx, struct krb5_principal_data);
+ if (princ == NULL) {
+ return ENOMEM;
+ }
+
+ princ->magic = KV5M_PRINCIPAL;
+
+ ret = iobuf_read_uint32be(iobuf, (uint32_t *) &princ->type);
+ if (ret != EOK) {
+ goto fail;
+ }
+
+ ret = iobuf_read_uint32be(iobuf, &ncomps);
+ if (ret != EOK) {
+ goto fail;
+ }
+
+ if (ncomps > sss_iobuf_get_capacity(iobuf)) {
+ /* Sanity check to avoid large allocations */
+ ret = EINVAL;
+ goto fail;
+ }
+
+ if (ncomps != 0) {
+ princ->data = talloc_zero_array(princ, krb5_data, ncomps);
+ if (princ->data == NULL) {
+ ret = ENOMEM;
+ goto fail;
+ }
+
+ princ->length = ncomps;
+ }
+
+ ret = get_krb5_data(princ, iobuf, &princ->realm);
+ if (ret != EOK) {
+ goto fail;
+ }
+
+ for (size_t i = 0; i < ncomps; i++) {
+ ret = get_krb5_data(princ->data, iobuf, &princ->data[i]);
+ if (ret != EOK) {
+ goto fail;
+ }
+ }
+
+ *_princ = princ;
+ return 0;
+
+fail:
+ talloc_free(princ);
+ return ret;
+}
+
+krb5_error_code sss_krb5_marshal_princ(krb5_principal princ,
+ struct sss_iobuf *iobuf)
+{
+ krb5_error_code ret;
+
+ if (iobuf == NULL || princ == NULL) {
+ return EINVAL;
+ }
+
+ ret = iobuf_write_uint32be(iobuf, princ->type);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ ret = iobuf_write_uint32be(iobuf, princ->length);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ ret = set_krb5_data(iobuf, &princ->realm);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ for (int i = 0; i < princ->length; i++) {
+ ret = set_krb5_data(iobuf, &princ->data[i]);
+ if (ret != EOK) {
+ return ret;
+ }
+ }
+ return EOK;
+}
diff --git a/src/util/sss_krb5.h b/src/util/sss_krb5.h
index ac0f6082c..0d9043be9 100644
--- a/src/util/sss_krb5.h
+++ b/src/util/sss_krb5.h
@@ -32,6 +32,7 @@
#include <krb5.h>
#endif
+#include "util/sss_iobuf.h"
#include "util/util.h"
#define KRB5_CHILD_LOG_FILE "krb5_child"
@@ -186,4 +187,12 @@ krb5_error_code sss_krb5_kt_have_content(krb5_context context,
krb5_keytab keytab);
bool sss_krb5_realm_has_proxy(const char *realm);
+
+krb5_error_code sss_krb5_marshal_princ(krb5_principal princ,
+ struct sss_iobuf *iobuf);
+
+krb5_error_code sss_krb5_unmarshal_princ(TALLOC_CTX *mem_ctx,
+ struct sss_iobuf *iobuf,
+ krb5_principal *_princ);
+
#endif /* __SSS_KRB5_H__ */