1c0b9f4feSDoug Rabson /*- 2c0b9f4feSDoug Rabson * Copyright (c) 2005 Doug Rabson 3c0b9f4feSDoug Rabson * All rights reserved. 4c0b9f4feSDoug Rabson * 5c0b9f4feSDoug Rabson * Redistribution and use in source and binary forms, with or without 6c0b9f4feSDoug Rabson * modification, are permitted provided that the following conditions 7c0b9f4feSDoug Rabson * are met: 8c0b9f4feSDoug Rabson * 1. Redistributions of source code must retain the above copyright 9c0b9f4feSDoug Rabson * notice, this list of conditions and the following disclaimer. 10c0b9f4feSDoug Rabson * 2. Redistributions in binary form must reproduce the above copyright 11c0b9f4feSDoug Rabson * notice, this list of conditions and the following disclaimer in the 12c0b9f4feSDoug Rabson * documentation and/or other materials provided with the distribution. 13c0b9f4feSDoug Rabson * 14c0b9f4feSDoug Rabson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15c0b9f4feSDoug Rabson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16c0b9f4feSDoug Rabson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17c0b9f4feSDoug Rabson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18c0b9f4feSDoug Rabson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19c0b9f4feSDoug Rabson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20c0b9f4feSDoug Rabson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21c0b9f4feSDoug Rabson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22c0b9f4feSDoug Rabson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23c0b9f4feSDoug Rabson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24c0b9f4feSDoug Rabson * SUCH DAMAGE. 25c0b9f4feSDoug Rabson * 26c0b9f4feSDoug Rabson * $FreeBSD$ 27c0b9f4feSDoug Rabson */ 2822a25490SDoug Rabson /* 29bf3f9db6SUlrich Spörlein * Copyright (c) 1998 - 2005 Kungliga Tekniska Högskolan 3022a25490SDoug Rabson * (Royal Institute of Technology, Stockholm, Sweden). 3122a25490SDoug Rabson * All rights reserved. 3222a25490SDoug Rabson * 3322a25490SDoug Rabson * Redistribution and use in source and binary forms, with or without 3422a25490SDoug Rabson * modification, are permitted provided that the following conditions 3522a25490SDoug Rabson * are met: 3622a25490SDoug Rabson * 3722a25490SDoug Rabson * 1. Redistributions of source code must retain the above copyright 3822a25490SDoug Rabson * notice, this list of conditions and the following disclaimer. 3922a25490SDoug Rabson * 4022a25490SDoug Rabson * 2. Redistributions in binary form must reproduce the above copyright 4122a25490SDoug Rabson * notice, this list of conditions and the following disclaimer in the 4222a25490SDoug Rabson * documentation and/or other materials provided with the distribution. 4322a25490SDoug Rabson * 4422a25490SDoug Rabson * 3. Neither the name of the Institute nor the names of its contributors 4522a25490SDoug Rabson * may be used to endorse or promote products derived from this software 4622a25490SDoug Rabson * without specific prior written permission. 4722a25490SDoug Rabson * 4822a25490SDoug Rabson * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 4922a25490SDoug Rabson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 5022a25490SDoug Rabson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 5122a25490SDoug Rabson * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 5222a25490SDoug Rabson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 5322a25490SDoug Rabson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 5422a25490SDoug Rabson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 5522a25490SDoug Rabson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 5622a25490SDoug Rabson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5722a25490SDoug Rabson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5822a25490SDoug Rabson * SUCH DAMAGE. 5922a25490SDoug Rabson */ 6033f12199SDoug Rabson /* 61bf3f9db6SUlrich Spörlein * Copyright (c) 1998 - 2005 Kungliga Tekniska Högskolan 6233f12199SDoug Rabson * (Royal Institute of Technology, Stockholm, Sweden). 6333f12199SDoug Rabson * All rights reserved. 6433f12199SDoug Rabson * 6533f12199SDoug Rabson * Redistribution and use in source and binary forms, with or without 6633f12199SDoug Rabson * modification, are permitted provided that the following conditions 6733f12199SDoug Rabson * are met: 6833f12199SDoug Rabson * 6933f12199SDoug Rabson * 1. Redistributions of source code must retain the above copyright 7033f12199SDoug Rabson * notice, this list of conditions and the following disclaimer. 7133f12199SDoug Rabson * 7233f12199SDoug Rabson * 2. Redistributions in binary form must reproduce the above copyright 7333f12199SDoug Rabson * notice, this list of conditions and the following disclaimer in the 7433f12199SDoug Rabson * documentation and/or other materials provided with the distribution. 7533f12199SDoug Rabson * 7633f12199SDoug Rabson * 3. Neither the name of the Institute nor the names of its contributors 7733f12199SDoug Rabson * may be used to endorse or promote products derived from this software 7833f12199SDoug Rabson * without specific prior written permission. 7933f12199SDoug Rabson * 8033f12199SDoug Rabson * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 8133f12199SDoug Rabson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 8233f12199SDoug Rabson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 8333f12199SDoug Rabson * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 8433f12199SDoug Rabson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 8533f12199SDoug Rabson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 8633f12199SDoug Rabson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 8733f12199SDoug Rabson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 8833f12199SDoug Rabson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 8933f12199SDoug Rabson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 9033f12199SDoug Rabson * SUCH DAMAGE. 9133f12199SDoug Rabson */ 92c0b9f4feSDoug Rabson 93c0b9f4feSDoug Rabson #include <gssapi/gssapi.h> 9433f12199SDoug Rabson #include <stdio.h> 95c0b9f4feSDoug Rabson #include <string.h> 9633f12199SDoug Rabson #include <stdlib.h> 9722a25490SDoug Rabson #include <errno.h> 98c0b9f4feSDoug Rabson 99c0b9f4feSDoug Rabson #include "mech_switch.h" 10033f12199SDoug Rabson #include "utils.h" 101c0b9f4feSDoug Rabson 10222a25490SDoug Rabson static const char * 10322a25490SDoug Rabson calling_error(OM_uint32 v) 10422a25490SDoug Rabson { 10522a25490SDoug Rabson static const char *msgs[] = { 10622a25490SDoug Rabson NULL, /* 0 */ 10722a25490SDoug Rabson "A required input parameter could not be read.", /* */ 10822a25490SDoug Rabson "A required output parameter could not be written.", /* */ 10922a25490SDoug Rabson "A parameter was malformed" 110c0b9f4feSDoug Rabson }; 111c0b9f4feSDoug Rabson 11222a25490SDoug Rabson v >>= GSS_C_CALLING_ERROR_OFFSET; 113c0b9f4feSDoug Rabson 11422a25490SDoug Rabson if (v == 0) 11522a25490SDoug Rabson return ""; 11622a25490SDoug Rabson else if (v >= sizeof(msgs)/sizeof(*msgs)) 11722a25490SDoug Rabson return "unknown calling error"; 11822a25490SDoug Rabson else 11922a25490SDoug Rabson return msgs[v]; 12022a25490SDoug Rabson } 12122a25490SDoug Rabson 12222a25490SDoug Rabson static const char * 12322a25490SDoug Rabson routine_error(OM_uint32 v) 12422a25490SDoug Rabson { 12522a25490SDoug Rabson static const char *msgs[] = { 12633f12199SDoug Rabson "Function completed successfully", /* 0 */ 12722a25490SDoug Rabson "An unsupported mechanism was requested", 12822a25490SDoug Rabson "An invalid name was supplied", 12922a25490SDoug Rabson "A supplied name was of an unsupported type", 13022a25490SDoug Rabson "Incorrect channel bindings were supplied", 13122a25490SDoug Rabson "An invalid status code was supplied", 13222a25490SDoug Rabson "A token had an invalid MIC", 13322a25490SDoug Rabson "No credentials were supplied, " 13422a25490SDoug Rabson "or the credentials were unavailable or inaccessible.", 13522a25490SDoug Rabson "No context has been established", 13622a25490SDoug Rabson "A token was invalid", 13722a25490SDoug Rabson "A credential was invalid", 13822a25490SDoug Rabson "The referenced credentials have expired", 13922a25490SDoug Rabson "The context has expired", 14022a25490SDoug Rabson "Miscellaneous failure (see text)", 14122a25490SDoug Rabson "The quality-of-protection requested could not be provide", 14222a25490SDoug Rabson "The operation is forbidden by local security policy", 14322a25490SDoug Rabson "The operation or option is not available", 14422a25490SDoug Rabson "The requested credential element already exists", 14522a25490SDoug Rabson "The provided name was not a mechanism name.", 14622a25490SDoug Rabson }; 14722a25490SDoug Rabson 14822a25490SDoug Rabson v >>= GSS_C_ROUTINE_ERROR_OFFSET; 14922a25490SDoug Rabson 15033f12199SDoug Rabson if (v >= sizeof(msgs)/sizeof(*msgs)) 15122a25490SDoug Rabson return "unknown routine error"; 15222a25490SDoug Rabson else 15322a25490SDoug Rabson return msgs[v]; 15422a25490SDoug Rabson } 15522a25490SDoug Rabson 15622a25490SDoug Rabson static const char * 15722a25490SDoug Rabson supplementary_error(OM_uint32 v) 15822a25490SDoug Rabson { 15922a25490SDoug Rabson static const char *msgs[] = { 16022a25490SDoug Rabson "normal completion", 16122a25490SDoug Rabson "continuation call to routine required", 16222a25490SDoug Rabson "duplicate per-message token detected", 16322a25490SDoug Rabson "timed-out per-message token detected", 16422a25490SDoug Rabson "reordered (early) per-message token detected", 16522a25490SDoug Rabson "skipped predecessor token(s) detected" 16622a25490SDoug Rabson }; 16722a25490SDoug Rabson 16822a25490SDoug Rabson v >>= GSS_C_SUPPLEMENTARY_OFFSET; 16922a25490SDoug Rabson 17022a25490SDoug Rabson if (v >= sizeof(msgs)/sizeof(*msgs)) 17122a25490SDoug Rabson return "unknown routine error"; 17222a25490SDoug Rabson else 17322a25490SDoug Rabson return msgs[v]; 17422a25490SDoug Rabson } 175c0b9f4feSDoug Rabson 17633f12199SDoug Rabson #if defined(__sparc64__) || defined(__arm__) || defined(__mips__) 17733f12199SDoug Rabson 17833f12199SDoug Rabson /* 17933f12199SDoug Rabson * These platforms don't support TLS on FreeBSD - threads will just 18033f12199SDoug Rabson * have to step on each other's error values for now. 18133f12199SDoug Rabson */ 18233f12199SDoug Rabson #define __thread 18333f12199SDoug Rabson 18433f12199SDoug Rabson #endif 18533f12199SDoug Rabson 18633f12199SDoug Rabson struct mg_thread_ctx { 18733f12199SDoug Rabson gss_OID mech; 18833f12199SDoug Rabson OM_uint32 maj_stat; 18933f12199SDoug Rabson OM_uint32 min_stat; 19033f12199SDoug Rabson gss_buffer_desc maj_error; 19133f12199SDoug Rabson gss_buffer_desc min_error; 19233f12199SDoug Rabson }; 19333f12199SDoug Rabson static __thread struct mg_thread_ctx last_error_context; 19433f12199SDoug Rabson 19533f12199SDoug Rabson static OM_uint32 19633f12199SDoug Rabson _gss_mg_get_error(const gss_OID mech, OM_uint32 type, 19733f12199SDoug Rabson OM_uint32 value, gss_buffer_t string) 19833f12199SDoug Rabson { 19933f12199SDoug Rabson struct mg_thread_ctx *mg; 20033f12199SDoug Rabson 20133f12199SDoug Rabson mg = &last_error_context; 20233f12199SDoug Rabson 20333f12199SDoug Rabson if (mech != NULL && gss_oid_equal(mg->mech, mech) == 0) 20433f12199SDoug Rabson return (GSS_S_BAD_STATUS); 20533f12199SDoug Rabson 20633f12199SDoug Rabson switch (type) { 20733f12199SDoug Rabson case GSS_C_GSS_CODE: { 20833f12199SDoug Rabson if (value != mg->maj_stat || mg->maj_error.length == 0) 20933f12199SDoug Rabson break; 21033f12199SDoug Rabson string->value = malloc(mg->maj_error.length); 21133f12199SDoug Rabson string->length = mg->maj_error.length; 21233f12199SDoug Rabson memcpy(string->value, mg->maj_error.value, 21333f12199SDoug Rabson mg->maj_error.length); 21433f12199SDoug Rabson return (GSS_S_COMPLETE); 21533f12199SDoug Rabson } 21633f12199SDoug Rabson case GSS_C_MECH_CODE: { 21733f12199SDoug Rabson if (value != mg->min_stat || mg->min_error.length == 0) 21833f12199SDoug Rabson break; 21933f12199SDoug Rabson string->value = malloc(mg->min_error.length); 22033f12199SDoug Rabson string->length = mg->min_error.length; 22133f12199SDoug Rabson memcpy(string->value, mg->min_error.value, 22233f12199SDoug Rabson mg->min_error.length); 22333f12199SDoug Rabson return (GSS_S_COMPLETE); 22433f12199SDoug Rabson } 22533f12199SDoug Rabson } 22633f12199SDoug Rabson string->value = NULL; 22733f12199SDoug Rabson string->length = 0; 22833f12199SDoug Rabson return (GSS_S_BAD_STATUS); 22933f12199SDoug Rabson } 23033f12199SDoug Rabson 23133f12199SDoug Rabson void 23233f12199SDoug Rabson _gss_mg_error(struct _gss_mech_switch *m, OM_uint32 maj, OM_uint32 min) 23333f12199SDoug Rabson { 23433f12199SDoug Rabson OM_uint32 major_status, minor_status; 23533f12199SDoug Rabson OM_uint32 message_content; 23633f12199SDoug Rabson struct mg_thread_ctx *mg; 23733f12199SDoug Rabson 23833f12199SDoug Rabson mg = &last_error_context; 23933f12199SDoug Rabson 24033f12199SDoug Rabson gss_release_buffer(&minor_status, &mg->maj_error); 24133f12199SDoug Rabson gss_release_buffer(&minor_status, &mg->min_error); 24233f12199SDoug Rabson 24333f12199SDoug Rabson mg->mech = &m->gm_mech_oid; 24433f12199SDoug Rabson mg->maj_stat = maj; 24533f12199SDoug Rabson mg->min_stat = min; 24633f12199SDoug Rabson 24733f12199SDoug Rabson major_status = m->gm_display_status(&minor_status, 24833f12199SDoug Rabson maj, 24933f12199SDoug Rabson GSS_C_GSS_CODE, 25033f12199SDoug Rabson &m->gm_mech_oid, 25133f12199SDoug Rabson &message_content, 25233f12199SDoug Rabson &mg->maj_error); 25333f12199SDoug Rabson if (GSS_ERROR(major_status)) { 25433f12199SDoug Rabson mg->maj_error.value = NULL; 25533f12199SDoug Rabson mg->maj_error.length = 0; 25633f12199SDoug Rabson } 25733f12199SDoug Rabson major_status = m->gm_display_status(&minor_status, 25833f12199SDoug Rabson min, 25933f12199SDoug Rabson GSS_C_MECH_CODE, 26033f12199SDoug Rabson &m->gm_mech_oid, 26133f12199SDoug Rabson &message_content, 26233f12199SDoug Rabson &mg->min_error); 26333f12199SDoug Rabson if (GSS_ERROR(major_status)) { 26433f12199SDoug Rabson mg->min_error.value = NULL; 26533f12199SDoug Rabson mg->min_error.length = 0; 26633f12199SDoug Rabson } 26733f12199SDoug Rabson } 26833f12199SDoug Rabson 269c0b9f4feSDoug Rabson OM_uint32 270c0b9f4feSDoug Rabson gss_display_status(OM_uint32 *minor_status, 271c0b9f4feSDoug Rabson OM_uint32 status_value, 272c0b9f4feSDoug Rabson int status_type, 27333f12199SDoug Rabson const gss_OID mech_type, 274c0b9f4feSDoug Rabson OM_uint32 *message_content, 275c0b9f4feSDoug Rabson gss_buffer_t status_string) 276c0b9f4feSDoug Rabson { 277c0b9f4feSDoug Rabson OM_uint32 major_status; 27841ec3746SDoug Rabson 27933f12199SDoug Rabson _gss_buffer_zero(status_string); 28033f12199SDoug Rabson *message_content = 0; 28133f12199SDoug Rabson 28233f12199SDoug Rabson major_status = _gss_mg_get_error(mech_type, status_type, 28333f12199SDoug Rabson status_value, status_string); 28433f12199SDoug Rabson if (major_status == GSS_S_COMPLETE) { 28533f12199SDoug Rabson 28633f12199SDoug Rabson *message_content = 0; 28733f12199SDoug Rabson *minor_status = 0; 28833f12199SDoug Rabson return (GSS_S_COMPLETE); 28941ec3746SDoug Rabson } 290c0b9f4feSDoug Rabson 291c0b9f4feSDoug Rabson *minor_status = 0; 292c0b9f4feSDoug Rabson switch (status_type) { 29322a25490SDoug Rabson case GSS_C_GSS_CODE: { 29422a25490SDoug Rabson char *buf; 295c0b9f4feSDoug Rabson 29622a25490SDoug Rabson if (GSS_SUPPLEMENTARY_INFO(status_value)) 29722a25490SDoug Rabson asprintf(&buf, "%s", supplementary_error( 29822a25490SDoug Rabson GSS_SUPPLEMENTARY_INFO(status_value))); 29922a25490SDoug Rabson else 30022a25490SDoug Rabson asprintf (&buf, "%s %s", 30122a25490SDoug Rabson calling_error(GSS_CALLING_ERROR(status_value)), 30222a25490SDoug Rabson routine_error(GSS_ROUTINE_ERROR(status_value))); 30322a25490SDoug Rabson 30433f12199SDoug Rabson if (buf == NULL) 30533f12199SDoug Rabson break; 30633f12199SDoug Rabson 30722a25490SDoug Rabson status_string->length = strlen(buf); 30822a25490SDoug Rabson status_string->value = buf; 30922a25490SDoug Rabson 31033f12199SDoug Rabson return (GSS_S_COMPLETE); 31122a25490SDoug Rabson } 31222a25490SDoug Rabson case GSS_C_MECH_CODE: { 31333f12199SDoug Rabson OM_uint32 maj_junk, min_junk; 31433f12199SDoug Rabson gss_buffer_desc oid; 31533f12199SDoug Rabson char *buf; 31633f12199SDoug Rabson 31733f12199SDoug Rabson maj_junk = gss_oid_to_str(&min_junk, mech_type, &oid); 31833f12199SDoug Rabson if (maj_junk != GSS_S_COMPLETE) { 31933f12199SDoug Rabson oid.value = strdup("unknown"); 32033f12199SDoug Rabson oid.length = 7; 32133f12199SDoug Rabson } 32233f12199SDoug Rabson 32333f12199SDoug Rabson asprintf (&buf, "unknown mech-code %lu for mech %.*s", 32433f12199SDoug Rabson (unsigned long)status_value, 32533f12199SDoug Rabson (int)oid.length, (char *)oid.value); 32633f12199SDoug Rabson if (maj_junk == GSS_S_COMPLETE) 32733f12199SDoug Rabson gss_release_buffer(&min_junk, &oid); 32833f12199SDoug Rabson 32933f12199SDoug Rabson if (buf == NULL) 33033f12199SDoug Rabson break; 33133f12199SDoug Rabson 33233f12199SDoug Rabson status_string->length = strlen(buf); 33333f12199SDoug Rabson status_string->value = buf; 33433f12199SDoug Rabson 335c0b9f4feSDoug Rabson return (GSS_S_COMPLETE); 336c0b9f4feSDoug Rabson } 337c0b9f4feSDoug Rabson } 33833f12199SDoug Rabson _gss_buffer_zero(status_string); 339c0b9f4feSDoug Rabson return (GSS_S_BAD_STATUS); 340c0b9f4feSDoug Rabson } 341*ae771770SStanislav Sedov 342*ae771770SStanislav Sedov void 343*ae771770SStanislav Sedov _gss_mg_collect_error(gss_OID mech, OM_uint32 maj, OM_uint32 min) 344*ae771770SStanislav Sedov { 345*ae771770SStanislav Sedov struct _gss_mech_switch *m; 346*ae771770SStanislav Sedov 347*ae771770SStanislav Sedov m = _gss_find_mech_switch(mech); 348*ae771770SStanislav Sedov if (m != NULL) 349*ae771770SStanislav Sedov _gss_mg_error(m, maj, min); 350*ae771770SStanislav Sedov } 351