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