1178825Sdfr/* 2233294Sstas * Copyright (c) 1998 - 2006 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 5178825Sdfr * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 9178825Sdfr * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 12178825Sdfr * 13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 14233294Sstas * notice, this list of conditions and the following disclaimer in the 15233294Sstas * documentation and/or other materials provided with the distribution. 16178825Sdfr * 17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 18233294Sstas * may be used to endorse or promote products derived from this software 19233294Sstas * without specific prior written permission. 20178825Sdfr * 21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31233294Sstas * SUCH DAMAGE. 32178825Sdfr */ 33178825Sdfr 34233294Sstas#include "gsskrb5_locl.h" 35178825Sdfr 36178825Sdfrstatic const char * 37178825Sdfrcalling_error(OM_uint32 v) 38178825Sdfr{ 39178825Sdfr static const char *msgs[] = { 40178825Sdfr NULL, /* 0 */ 41178825Sdfr "A required input parameter could not be read.", /* */ 42178825Sdfr "A required output parameter could not be written.", /* */ 43178825Sdfr "A parameter was malformed" 44178825Sdfr }; 45178825Sdfr 46178825Sdfr v >>= GSS_C_CALLING_ERROR_OFFSET; 47178825Sdfr 48178825Sdfr if (v == 0) 49178825Sdfr return ""; 50178825Sdfr else if (v >= sizeof(msgs)/sizeof(*msgs)) 51178825Sdfr return "unknown calling error"; 52178825Sdfr else 53178825Sdfr return msgs[v]; 54178825Sdfr} 55178825Sdfr 56178825Sdfrstatic const char * 57178825Sdfrroutine_error(OM_uint32 v) 58178825Sdfr{ 59178825Sdfr static const char *msgs[] = { 60178825Sdfr NULL, /* 0 */ 61178825Sdfr "An unsupported mechanism was requested", 62178825Sdfr "An invalid name was supplied", 63178825Sdfr "A supplied name was of an unsupported type", 64178825Sdfr "Incorrect channel bindings were supplied", 65178825Sdfr "An invalid status code was supplied", 66178825Sdfr "A token had an invalid MIC", 67178825Sdfr "No credentials were supplied, " 68178825Sdfr "or the credentials were unavailable or inaccessible.", 69178825Sdfr "No context has been established", 70178825Sdfr "A token was invalid", 71178825Sdfr "A credential was invalid", 72178825Sdfr "The referenced credentials have expired", 73178825Sdfr "The context has expired", 74178825Sdfr "Miscellaneous failure (see text)", 75178825Sdfr "The quality-of-protection requested could not be provide", 76178825Sdfr "The operation is forbidden by local security policy", 77178825Sdfr "The operation or option is not available", 78178825Sdfr "The requested credential element already exists", 79178825Sdfr "The provided name was not a mechanism name.", 80178825Sdfr }; 81178825Sdfr 82178825Sdfr v >>= GSS_C_ROUTINE_ERROR_OFFSET; 83178825Sdfr 84178825Sdfr if (v == 0) 85178825Sdfr return ""; 86178825Sdfr else if (v >= sizeof(msgs)/sizeof(*msgs)) 87178825Sdfr return "unknown routine error"; 88178825Sdfr else 89178825Sdfr return msgs[v]; 90178825Sdfr} 91178825Sdfr 92178825Sdfrstatic const char * 93178825Sdfrsupplementary_error(OM_uint32 v) 94178825Sdfr{ 95178825Sdfr static const char *msgs[] = { 96178825Sdfr "normal completion", 97178825Sdfr "continuation call to routine required", 98178825Sdfr "duplicate per-message token detected", 99178825Sdfr "timed-out per-message token detected", 100178825Sdfr "reordered (early) per-message token detected", 101178825Sdfr "skipped predecessor token(s) detected" 102178825Sdfr }; 103178825Sdfr 104178825Sdfr v >>= GSS_C_SUPPLEMENTARY_OFFSET; 105178825Sdfr 106178825Sdfr if (v >= sizeof(msgs)/sizeof(*msgs)) 107178825Sdfr return "unknown routine error"; 108178825Sdfr else 109178825Sdfr return msgs[v]; 110178825Sdfr} 111178825Sdfr 112178825Sdfrvoid 113178825Sdfr_gsskrb5_clear_status (void) 114178825Sdfr{ 115178825Sdfr krb5_context context; 116178825Sdfr 117178825Sdfr if (_gsskrb5_init (&context) != 0) 118178825Sdfr return; 119233294Sstas krb5_clear_error_message(context); 120178825Sdfr} 121178825Sdfr 122178825Sdfrvoid 123233294Sstas_gsskrb5_set_status (int ret, const char *fmt, ...) 124178825Sdfr{ 125178825Sdfr krb5_context context; 126178825Sdfr va_list args; 127178825Sdfr char *str; 128233294Sstas int e; 129178825Sdfr 130178825Sdfr if (_gsskrb5_init (&context) != 0) 131178825Sdfr return; 132178825Sdfr 133178825Sdfr va_start(args, fmt); 134233294Sstas e = vasprintf(&str, fmt, args); 135178825Sdfr va_end(args); 136233294Sstas if (e >= 0 && str) { 137233294Sstas krb5_set_error_message(context, ret, "%s", str); 138178825Sdfr free(str); 139178825Sdfr } 140178825Sdfr} 141178825Sdfr 142233294SstasOM_uint32 GSSAPI_CALLCONV _gsskrb5_display_status 143178825Sdfr(OM_uint32 *minor_status, 144178825Sdfr OM_uint32 status_value, 145178825Sdfr int status_type, 146178825Sdfr const gss_OID mech_type, 147178825Sdfr OM_uint32 *message_context, 148178825Sdfr gss_buffer_t status_string) 149178825Sdfr{ 150178825Sdfr krb5_context context; 151233294Sstas char *buf = NULL; 152233294Sstas int e = 0; 153178825Sdfr 154178825Sdfr GSSAPI_KRB5_INIT (&context); 155178825Sdfr 156178825Sdfr status_string->length = 0; 157178825Sdfr status_string->value = NULL; 158178825Sdfr 159178825Sdfr if (gss_oid_equal(mech_type, GSS_C_NO_OID) == 0 && 160178825Sdfr gss_oid_equal(mech_type, GSS_KRB5_MECHANISM) == 0) { 161178825Sdfr *minor_status = 0; 162178825Sdfr return GSS_C_GSS_CODE; 163178825Sdfr } 164178825Sdfr 165178825Sdfr if (status_type == GSS_C_GSS_CODE) { 166178825Sdfr if (GSS_SUPPLEMENTARY_INFO(status_value)) 167233294Sstas e = asprintf(&buf, "%s", 168233294Sstas supplementary_error(GSS_SUPPLEMENTARY_INFO(status_value))); 169178825Sdfr else 170233294Sstas e = asprintf (&buf, "%s %s", 171233294Sstas calling_error(GSS_CALLING_ERROR(status_value)), 172233294Sstas routine_error(GSS_ROUTINE_ERROR(status_value))); 173178825Sdfr } else if (status_type == GSS_C_MECH_CODE) { 174233294Sstas const char *buf2 = krb5_get_error_message(context, status_value); 175233294Sstas if (buf2) { 176233294Sstas buf = strdup(buf2); 177233294Sstas krb5_free_error_message(context, buf2); 178233294Sstas } else { 179233294Sstas e = asprintf(&buf, "unknown mech error-code %u", 180178825Sdfr (unsigned)status_value); 181178825Sdfr } 182178825Sdfr } else { 183178825Sdfr *minor_status = EINVAL; 184178825Sdfr return GSS_S_BAD_STATUS; 185178825Sdfr } 186178825Sdfr 187233294Sstas if (e < 0 || buf == NULL) { 188178825Sdfr *minor_status = ENOMEM; 189178825Sdfr return GSS_S_FAILURE; 190178825Sdfr } 191178825Sdfr 192178825Sdfr *message_context = 0; 193178825Sdfr *minor_status = 0; 194178825Sdfr 195178825Sdfr status_string->length = strlen(buf); 196178825Sdfr status_string->value = buf; 197233294Sstas 198178825Sdfr return GSS_S_COMPLETE; 199178825Sdfr} 200