1c19800e8SDoug Rabson /* 2*ae771770SStanislav Sedov * Copyright (c) 1998 - 2006 Kungliga Tekniska Högskolan 3c19800e8SDoug Rabson * (Royal Institute of Technology, Stockholm, Sweden). 4c19800e8SDoug Rabson * All rights reserved. 5c19800e8SDoug Rabson * 6c19800e8SDoug Rabson * Redistribution and use in source and binary forms, with or without 7c19800e8SDoug Rabson * modification, are permitted provided that the following conditions 8c19800e8SDoug Rabson * are met: 9c19800e8SDoug Rabson * 10c19800e8SDoug Rabson * 1. Redistributions of source code must retain the above copyright 11c19800e8SDoug Rabson * notice, this list of conditions and the following disclaimer. 12c19800e8SDoug Rabson * 13c19800e8SDoug Rabson * 2. Redistributions in binary form must reproduce the above copyright 14c19800e8SDoug Rabson * notice, this list of conditions and the following disclaimer in the 15c19800e8SDoug Rabson * documentation and/or other materials provided with the distribution. 16c19800e8SDoug Rabson * 17c19800e8SDoug Rabson * 3. Neither the name of the Institute nor the names of its contributors 18c19800e8SDoug Rabson * may be used to endorse or promote products derived from this software 19c19800e8SDoug Rabson * without specific prior written permission. 20c19800e8SDoug Rabson * 21c19800e8SDoug Rabson * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22c19800e8SDoug Rabson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23c19800e8SDoug Rabson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24c19800e8SDoug Rabson * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25c19800e8SDoug Rabson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26c19800e8SDoug Rabson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27c19800e8SDoug Rabson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28c19800e8SDoug Rabson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29c19800e8SDoug Rabson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30c19800e8SDoug Rabson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31c19800e8SDoug Rabson * SUCH DAMAGE. 32c19800e8SDoug Rabson */ 33c19800e8SDoug Rabson 34*ae771770SStanislav Sedov #include "gsskrb5_locl.h" 35c19800e8SDoug Rabson 36c19800e8SDoug Rabson static const char * 37c19800e8SDoug Rabson calling_error(OM_uint32 v) 38c19800e8SDoug Rabson { 39c19800e8SDoug Rabson static const char *msgs[] = { 40c19800e8SDoug Rabson NULL, /* 0 */ 41c19800e8SDoug Rabson "A required input parameter could not be read.", /* */ 42c19800e8SDoug Rabson "A required output parameter could not be written.", /* */ 43c19800e8SDoug Rabson "A parameter was malformed" 44c19800e8SDoug Rabson }; 45c19800e8SDoug Rabson 46c19800e8SDoug Rabson v >>= GSS_C_CALLING_ERROR_OFFSET; 47c19800e8SDoug Rabson 48c19800e8SDoug Rabson if (v == 0) 49c19800e8SDoug Rabson return ""; 50c19800e8SDoug Rabson else if (v >= sizeof(msgs)/sizeof(*msgs)) 51c19800e8SDoug Rabson return "unknown calling error"; 52c19800e8SDoug Rabson else 53c19800e8SDoug Rabson return msgs[v]; 54c19800e8SDoug Rabson } 55c19800e8SDoug Rabson 56c19800e8SDoug Rabson static const char * 57c19800e8SDoug Rabson routine_error(OM_uint32 v) 58c19800e8SDoug Rabson { 59c19800e8SDoug Rabson static const char *msgs[] = { 60c19800e8SDoug Rabson NULL, /* 0 */ 61c19800e8SDoug Rabson "An unsupported mechanism was requested", 62c19800e8SDoug Rabson "An invalid name was supplied", 63c19800e8SDoug Rabson "A supplied name was of an unsupported type", 64c19800e8SDoug Rabson "Incorrect channel bindings were supplied", 65c19800e8SDoug Rabson "An invalid status code was supplied", 66c19800e8SDoug Rabson "A token had an invalid MIC", 67c19800e8SDoug Rabson "No credentials were supplied, " 68c19800e8SDoug Rabson "or the credentials were unavailable or inaccessible.", 69c19800e8SDoug Rabson "No context has been established", 70c19800e8SDoug Rabson "A token was invalid", 71c19800e8SDoug Rabson "A credential was invalid", 72c19800e8SDoug Rabson "The referenced credentials have expired", 73c19800e8SDoug Rabson "The context has expired", 74c19800e8SDoug Rabson "Miscellaneous failure (see text)", 75c19800e8SDoug Rabson "The quality-of-protection requested could not be provide", 76c19800e8SDoug Rabson "The operation is forbidden by local security policy", 77c19800e8SDoug Rabson "The operation or option is not available", 78c19800e8SDoug Rabson "The requested credential element already exists", 79c19800e8SDoug Rabson "The provided name was not a mechanism name.", 80c19800e8SDoug Rabson }; 81c19800e8SDoug Rabson 82c19800e8SDoug Rabson v >>= GSS_C_ROUTINE_ERROR_OFFSET; 83c19800e8SDoug Rabson 84c19800e8SDoug Rabson if (v == 0) 85c19800e8SDoug Rabson return ""; 86c19800e8SDoug Rabson else if (v >= sizeof(msgs)/sizeof(*msgs)) 87c19800e8SDoug Rabson return "unknown routine error"; 88c19800e8SDoug Rabson else 89c19800e8SDoug Rabson return msgs[v]; 90c19800e8SDoug Rabson } 91c19800e8SDoug Rabson 92c19800e8SDoug Rabson static const char * 93c19800e8SDoug Rabson supplementary_error(OM_uint32 v) 94c19800e8SDoug Rabson { 95c19800e8SDoug Rabson static const char *msgs[] = { 96c19800e8SDoug Rabson "normal completion", 97c19800e8SDoug Rabson "continuation call to routine required", 98c19800e8SDoug Rabson "duplicate per-message token detected", 99c19800e8SDoug Rabson "timed-out per-message token detected", 100c19800e8SDoug Rabson "reordered (early) per-message token detected", 101c19800e8SDoug Rabson "skipped predecessor token(s) detected" 102c19800e8SDoug Rabson }; 103c19800e8SDoug Rabson 104c19800e8SDoug Rabson v >>= GSS_C_SUPPLEMENTARY_OFFSET; 105c19800e8SDoug Rabson 106c19800e8SDoug Rabson if (v >= sizeof(msgs)/sizeof(*msgs)) 107c19800e8SDoug Rabson return "unknown routine error"; 108c19800e8SDoug Rabson else 109c19800e8SDoug Rabson return msgs[v]; 110c19800e8SDoug Rabson } 111c19800e8SDoug Rabson 112c19800e8SDoug Rabson void 113c19800e8SDoug Rabson _gsskrb5_clear_status (void) 114c19800e8SDoug Rabson { 115c19800e8SDoug Rabson krb5_context context; 116c19800e8SDoug Rabson 117c19800e8SDoug Rabson if (_gsskrb5_init (&context) != 0) 118c19800e8SDoug Rabson return; 119*ae771770SStanislav Sedov krb5_clear_error_message(context); 120c19800e8SDoug Rabson } 121c19800e8SDoug Rabson 122c19800e8SDoug Rabson void 123*ae771770SStanislav Sedov _gsskrb5_set_status (int ret, const char *fmt, ...) 124c19800e8SDoug Rabson { 125c19800e8SDoug Rabson krb5_context context; 126c19800e8SDoug Rabson va_list args; 127c19800e8SDoug Rabson char *str; 128*ae771770SStanislav Sedov int e; 129c19800e8SDoug Rabson 130c19800e8SDoug Rabson if (_gsskrb5_init (&context) != 0) 131c19800e8SDoug Rabson return; 132c19800e8SDoug Rabson 133c19800e8SDoug Rabson va_start(args, fmt); 134*ae771770SStanislav Sedov e = vasprintf(&str, fmt, args); 135c19800e8SDoug Rabson va_end(args); 136*ae771770SStanislav Sedov if (e >= 0 && str) { 137*ae771770SStanislav Sedov krb5_set_error_message(context, ret, "%s", str); 138c19800e8SDoug Rabson free(str); 139c19800e8SDoug Rabson } 140c19800e8SDoug Rabson } 141c19800e8SDoug Rabson 142*ae771770SStanislav Sedov OM_uint32 GSSAPI_CALLCONV _gsskrb5_display_status 143c19800e8SDoug Rabson (OM_uint32 *minor_status, 144c19800e8SDoug Rabson OM_uint32 status_value, 145c19800e8SDoug Rabson int status_type, 146c19800e8SDoug Rabson const gss_OID mech_type, 147c19800e8SDoug Rabson OM_uint32 *message_context, 148c19800e8SDoug Rabson gss_buffer_t status_string) 149c19800e8SDoug Rabson { 150c19800e8SDoug Rabson krb5_context context; 151*ae771770SStanislav Sedov char *buf = NULL; 152*ae771770SStanislav Sedov int e = 0; 153c19800e8SDoug Rabson 154c19800e8SDoug Rabson GSSAPI_KRB5_INIT (&context); 155c19800e8SDoug Rabson 156c19800e8SDoug Rabson status_string->length = 0; 157c19800e8SDoug Rabson status_string->value = NULL; 158c19800e8SDoug Rabson 159c19800e8SDoug Rabson if (gss_oid_equal(mech_type, GSS_C_NO_OID) == 0 && 160c19800e8SDoug Rabson gss_oid_equal(mech_type, GSS_KRB5_MECHANISM) == 0) { 161c19800e8SDoug Rabson *minor_status = 0; 162c19800e8SDoug Rabson return GSS_C_GSS_CODE; 163c19800e8SDoug Rabson } 164c19800e8SDoug Rabson 165c19800e8SDoug Rabson if (status_type == GSS_C_GSS_CODE) { 166c19800e8SDoug Rabson if (GSS_SUPPLEMENTARY_INFO(status_value)) 167*ae771770SStanislav Sedov e = asprintf(&buf, "%s", 168c19800e8SDoug Rabson supplementary_error(GSS_SUPPLEMENTARY_INFO(status_value))); 169c19800e8SDoug Rabson else 170*ae771770SStanislav Sedov e = asprintf (&buf, "%s %s", 171c19800e8SDoug Rabson calling_error(GSS_CALLING_ERROR(status_value)), 172c19800e8SDoug Rabson routine_error(GSS_ROUTINE_ERROR(status_value))); 173c19800e8SDoug Rabson } else if (status_type == GSS_C_MECH_CODE) { 174*ae771770SStanislav Sedov const char *buf2 = krb5_get_error_message(context, status_value); 175*ae771770SStanislav Sedov if (buf2) { 176*ae771770SStanislav Sedov buf = strdup(buf2); 177*ae771770SStanislav Sedov krb5_free_error_message(context, buf2); 178*ae771770SStanislav Sedov } else { 179*ae771770SStanislav Sedov e = asprintf(&buf, "unknown mech error-code %u", 180c19800e8SDoug Rabson (unsigned)status_value); 181c19800e8SDoug Rabson } 182c19800e8SDoug Rabson } else { 183c19800e8SDoug Rabson *minor_status = EINVAL; 184c19800e8SDoug Rabson return GSS_S_BAD_STATUS; 185c19800e8SDoug Rabson } 186c19800e8SDoug Rabson 187*ae771770SStanislav Sedov if (e < 0 || buf == NULL) { 188c19800e8SDoug Rabson *minor_status = ENOMEM; 189c19800e8SDoug Rabson return GSS_S_FAILURE; 190c19800e8SDoug Rabson } 191c19800e8SDoug Rabson 192c19800e8SDoug Rabson *message_context = 0; 193c19800e8SDoug Rabson *minor_status = 0; 194c19800e8SDoug Rabson 195c19800e8SDoug Rabson status_string->length = strlen(buf); 196c19800e8SDoug Rabson status_string->value = buf; 197c19800e8SDoug Rabson 198c19800e8SDoug Rabson return GSS_S_COMPLETE; 199c19800e8SDoug Rabson } 200