From 2555d76fe3e5ce7b3a04f137054da0ba1f1a9374 Mon Sep 17 00:00:00 2001 From: Robbie Harwood Date: Apr 16 2019 19:11:59 +0000 Subject: [PATCH 1/3] Always initialize out cred in gp_import_gssx_cred() Signed-off-by: Robbie Harwood --- diff --git a/src/gp_export.c b/src/gp_export.c index 5e8e160..403e339 100644 --- a/src/gp_export.c +++ b/src/gp_export.c @@ -449,6 +449,8 @@ uint32_t gp_import_gssx_cred(uint32_t *min, struct gp_call_ctx *gpcall, uint32_t ret_min = 0; int ret; + *out = GSS_C_NO_CREDENTIAL; + handle = gp_service_get_creds_handle(gpcall->service); if (!handle) { ret_maj = GSS_S_FAILURE; @@ -470,7 +472,6 @@ uint32_t gp_import_gssx_cred(uint32_t *min, struct gp_call_ctx *gpcall, if (ret) { /* Allow for re-issuance of the keytab. */ GPDEBUG("Stored ccache failed to decrypt; treating as empty\n"); - *out = GSS_C_NO_CREDENTIAL; goto done; } From d5e68e9d1776eb0d1d3deaae461a376a42bda3a5 Mon Sep 17 00:00:00 2001 From: Robbie Harwood Date: Apr 16 2019 19:12:03 +0000 Subject: [PATCH 2/3] Handle gss_import_cred() failure when importing gssx creds Otherwise, we might attempt to set options on a non-existent handle, leading to a segfault. Signed-off-by: Robbie Harwood --- diff --git a/src/gp_export.c b/src/gp_export.c index 403e339..7ad8037 100644 --- a/src/gp_export.c +++ b/src/gp_export.c @@ -476,6 +476,10 @@ uint32_t gp_import_gssx_cred(uint32_t *min, struct gp_call_ctx *gpcall, } ret_maj = gss_import_cred(&ret_min, &token, out); + if (ret_maj) { + GPDEBUG("gss_import_cred failed when importing gssx cred\n"); + goto done; + } /* check if there is any client option we need to set on credentials */ gp_set_cred_options(cred, *out); From 25ff6504f18b12ee1a65215808c661518802b832 Mon Sep 17 00:00:00 2001 From: Robbie Harwood Date: Apr 16 2019 20:52:13 +0000 Subject: [PATCH 3/3] 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 --- 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; }