From 5dec1aeb0a6080ea661061b52248e60afc969426 Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Tue, 16 Apr 2019 16:08:32 -0400
Subject: [PATCH] Include length when using krb5_c_decrypt()
For some enctypes, krb5_c_decrypt() will add padding bytes which are
included in the returned length. However, functions which use the
objects we're storing aren't always prepared for that: in particular,
gss_import_cred() will declare a token invalid if there's trailing
garbage.
Work around this by including 4 bytes of length on encrypted objects.
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
Reviewed-by: Simo Sorce <simo@redhat.com>
Merges: #244
(cherry picked from commit 87957caf541114f6f15a495dd7d30556dc5801d9)
---
src/gp_export.c | 35 +++++++++++++++++++++++++++++++----
1 file changed, 31 insertions(+), 4 deletions(-)
diff --git a/src/gp_export.c b/src/gp_export.c
index 7ad8037..aa0a8ec 100644
--- a/src/gp_export.c
+++ b/src/gp_export.c
@@ -193,6 +193,9 @@ done:
return ret_maj;
}
+/* We need to include a length in our payloads because krb5_c_decrypt() will
+ * pad the contents for some enctypes, and gss_import_cred() doesn't like
+ * having extra bytes on tokens. */
static int gp_encrypt_buffer(krb5_context context, krb5_keyblock *key,
size_t len, void *buf, octet_string *out)
{
@@ -200,9 +203,27 @@ static int gp_encrypt_buffer(krb5_context context, krb5_keyblock *key,
krb5_data data_in;
krb5_enc_data enc_handle;
size_t cipherlen;
+ char *packed = NULL;
+ uint32_t netlen;
- data_in.length = len;
- data_in.data = buf;
+ if (len > (uint32_t)(-1)) {
+ /* Needs to fit in 4 bytes of payload, so... */
+ ret = ENOMEM;
+ goto done;
+ }
+
+ packed = malloc(len);
+ if (!packed) {
+ ret = errno;
+ goto done;
+ }
+
+ netlen = htonl(len);
+ memcpy(packed, (uint8_t *)&netlen, 4);
+ memcpy(packed + 4, buf, len);
+
+ data_in.length = len + 4;
+ data_in.data = packed;
memset(&enc_handle, '\0', sizeof(krb5_enc_data));
@@ -240,16 +261,19 @@ static int gp_encrypt_buffer(krb5_context context, krb5_keyblock *key,
}
done:
+ free(packed);
free(enc_handle.ciphertext.data);
return ret;
}
+/* See comment above on gp_encrypt_buffer(). */
static int gp_decrypt_buffer(krb5_context context, krb5_keyblock *key,
- octet_string *in, size_t *len, void *buf)
+ octet_string *in, size_t *len, char *buf)
{
int ret;
krb5_data data_out;
krb5_enc_data enc_handle;
+ uint32_t netlen;
memset(&enc_handle, '\0', sizeof(krb5_enc_data));
@@ -270,7 +294,10 @@ static int gp_decrypt_buffer(krb5_context context, krb5_keyblock *key,
return ret;
}
- *len = data_out.length;
+ /* And handle the padding. */
+ memcpy(&netlen, buf, 4);
+ *len = ntohl(netlen);
+ memmove(buf, buf + 4, *len);
return 0;
}