From 5c21c9e55374915114852398d5d5eb466a6bc148 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 30 Jan 2012 09:39:17 -0500 Subject: Add gpm_display_status function to mechglue library Also add method to save status per-thread Uses gccism for thread-local storage for now. --- proxy/Makefile.am | 4 +- proxy/src/gp_conv.c | 69 ++++++++++++++++++++ proxy/src/gp_conv.h | 3 + proxy/src/mechglue/gpm_display_status.c | 112 ++++++++++++++++++++++++++++++++ proxy/src/mechglue/gssapi_gpm.h | 9 +++ 5 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 proxy/src/mechglue/gpm_display_status.c diff --git a/proxy/Makefile.am b/proxy/Makefile.am index eb77bd3..af07ce4 100644 --- a/proxy/Makefile.am +++ b/proxy/Makefile.am @@ -81,7 +81,9 @@ if BUILD_SELINUX endif GP_RPCGEN_OBJ = rpcgen/gp_rpc_xdr.c rpcgen/gss_proxy_xdr.c -GP_MECHGLUE_OBJ = src/mechglue/gpm_common.c +GP_MECHGLUE_OBJ = \ + src/mechglue/gpm_display_status.c \ + src/mechglue/gpm_common.c dist_noinst_HEADERS = diff --git a/proxy/src/gp_conv.c b/proxy/src/gp_conv.c index 99b1c05..0d4d276 100644 --- a/proxy/src/gp_conv.c +++ b/proxy/src/gp_conv.c @@ -454,3 +454,72 @@ int gp_conv_status_to_gssx(struct gssx_call_ctx *call_ctx, done: return ret; } + +int gp_copy_utf8string(utf8string *in, utf8string *out) +{ + out->utf8string_val = strdup(in->utf8string_val); + if (!out->utf8string_val) { + return ENOMEM; + } + out->utf8string_len = in->utf8string_len; + return 0; +} + +int gp_copy_gssx_status_alloc(gssx_status *in, gssx_status **out) +{ + gssx_status *o; + int ret; + + o = calloc(1, sizeof(gssx_status)); + if (!o) { + return ENOMEM; + } + + o->major_status = in->major_status; + o->minor_status = in->minor_status; + + if (in->mech.octet_string_len) { + ret = gp_conv_octet_string(in->mech.octet_string_len, + in->mech.octet_string_val, + &o->mech); + if (ret) { + goto done; + } + } + + if (in->major_status_string.utf8string_len) { + ret = gp_copy_utf8string(&in->major_status_string, + &o->major_status_string); + if (ret) { + goto done; + } + } + + if (in->minor_status_string.utf8string_len) { + ret = gp_copy_utf8string(&in->minor_status_string, + &o->minor_status_string); + if (ret) { + goto done; + } + } + + if (in->server_ctx.octet_string_len) { + ret = gp_conv_octet_string(in->server_ctx.octet_string_len, + in->server_ctx.octet_string_val, + &o->server_ctx); + if (ret) { + goto done; + } + } + + *out = o; + ret = 0; + +done: + if (ret) { + xdr_free((xdrproc_t)xdr_gssx_status, (char *)o); + free(o); + } + return ret; +} + diff --git a/proxy/src/gp_conv.h b/proxy/src/gp_conv.h index f738ad7..fddeddd 100644 --- a/proxy/src/gp_conv.h +++ b/proxy/src/gp_conv.h @@ -60,4 +60,7 @@ int gp_conv_status_to_gssx(struct gssx_call_ctx *call_ctx, uint32_t ret_maj, uint32_t ret_min, gss_OID mech, struct gssx_status *status); +int gp_copy_utf8string(utf8string *in, utf8string *out); +int gp_copy_gssx_status_alloc(gssx_status *in, gssx_status **out); + #endif /* _GSS_CONV_H_ */ diff --git a/proxy/src/mechglue/gpm_display_status.c b/proxy/src/mechglue/gpm_display_status.c new file mode 100644 index 0000000..633b18a --- /dev/null +++ b/proxy/src/mechglue/gpm_display_status.c @@ -0,0 +1,112 @@ +/* + GSS-PROXY + + Copyright (C) 2011 Red Hat, Inc. + Copyright (C) 2011 Simo Sorce + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "gssapi_gpm.h" + +__thread gssx_status *tls_last_status = NULL; + +/* Thread local storage for return status. + * FIXME: it's not the most portable construct, so may need fixing in future */ +void gpm_save_status(gssx_status *status) +{ + int ret; + + if (tls_last_status) { + xdr_free((xdrproc_t)xdr_gssx_status, (char *)tls_last_status); + free(tls_last_status); + } + + ret = gp_copy_gssx_status_alloc(status, &tls_last_status); + if (ret) { + /* make sure tls_last_status is zeored on error */ + tls_last_status = NULL; + } +} + +OM_uint32 gpm_display_status(OM_uint32 *minor_status, + OM_uint32 status_value, + int status_type, + const gss_OID mech_type, + OM_uint32 *message_context, + gss_buffer_t status_string) +{ + utf8string tmp; + int ret; + + switch(status_type) { + case GSS_C_GSS_CODE: + if (tls_last_status && + tls_last_status->major_status_string.utf8string_len) { + ret = gp_copy_utf8string(&tls_last_status->major_status_string, + &tmp); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + status_string->value = tmp.utf8string_val; + status_string->length = tmp.utf8string_len; + *minor_status = 0; + return GSS_S_COMPLETE; + } else { + return gss_display_status(minor_status, + status_value, + GSS_C_GSS_CODE, + GSS_C_NO_OID, + message_context, + status_string); + } + case GSS_C_MECH_CODE: + if (*message_context) { + /* we do not support multiple messages for now */ + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + if (tls_last_status && + tls_last_status->minor_status_string.utf8string_len) { + ret = gp_copy_utf8string(&tls_last_status->minor_status_string, + &tmp); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + status_string->value = tmp.utf8string_val; + status_string->length = tmp.utf8string_len; + } else { + status_string->value = strdup(strerror(status_value)); + if (!status_string->value) { + status_string->length = 0; + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } else { + status_string->length = strlen(status_string->value) + 1; + } + } + *minor_status = 0; + return GSS_S_COMPLETE; + default: + *minor_status = EINVAL; + return GSS_S_BAD_STATUS; + } +} diff --git a/proxy/src/mechglue/gssapi_gpm.h b/proxy/src/mechglue/gssapi_gpm.h index 388ff33..579a4cf 100644 --- a/proxy/src/mechglue/gssapi_gpm.h +++ b/proxy/src/mechglue/gssapi_gpm.h @@ -44,4 +44,13 @@ OM_uint32 gpm_release_name(OM_uint32 *minor_status, OM_uint32 gpm_release_buffer(OM_uint32 *minor_status, gss_buffer_t buffer); +void gpm_save_status(gssx_status *status); + +OM_uint32 gpm_display_status(OM_uint32 *minor_status, + OM_uint32 status_value, + int status_type, + const gss_OID mech_type, + OM_uint32 *message_context, + gss_buffer_t status_string); + #endif /* _GSSAPI_GPM_H_ */ -- cgit