From d535ea0d4b3cfa8e1cc26a060ec2ed818f2b69ac Mon Sep 17 00:00:00 2001 From: Robbie Harwood 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 Reviewed-by: Simo Sorce Merges: #244 (cherry picked from commit 87957caf541114f6f15a495dd7d30556dc5801d9) --- proxy/src/gp_export.c | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/proxy/src/gp_export.c b/proxy/src/gp_export.c index 7ad8037..aa0a8ec 100644 --- a/proxy/src/gp_export.c +++ b/proxy/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; }