/* Copyright (C) 2011 the GSS-PROXY contributors, see COPYING for license */ #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; } } /* This funciton is used to record internal mech errors that are * generated by the proxy client code */ void gpm_save_internal_status(uint32_t err, char *err_str) { gssx_status status; memset(&status, 0, sizeof(gssx_status)); #define STD_MAJ_ERROR_STR "Internal gssproxy error" status.major_status = GSS_S_FAILURE; status.major_status_string.utf8string_val = strdup(STD_MAJ_ERROR_STR); status.major_status_string.utf8string_len = sizeof(STD_MAJ_ERROR_STR); status.minor_status = err; status.minor_status_string.utf8string_val = err_str; status.minor_status_string.utf8string_len = strlen(err_str) + 1; gpm_save_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) { utf8string tmp; int ret; switch(status_type) { case GSS_C_GSS_CODE: if (tls_last_status && tls_last_status->major_status == status_value && 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 { /* if we do not have it, make it clear */ return GSS_S_UNAVAILABLE; } case GSS_C_MECH_CODE: if (tls_last_status && tls_last_status->minor_status == status_value && tls_last_status->minor_status_string.utf8string_len) { if (*message_context) { /* we do not support multiple messages for now */ *minor_status = EINVAL; return GSS_S_FAILURE; } 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 { /* if we do not have it, make it clear */ return GSS_S_UNAVAILABLE; } *minor_status = 0; return GSS_S_COMPLETE; default: *minor_status = EINVAL; return GSS_S_BAD_STATUS; } }