Blob Blame History Raw
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;
 }