1153838Sdfr/*- 2153838Sdfr * Copyright (c) 2005 Doug Rabson 3153838Sdfr * All rights reserved. 4153838Sdfr * 5153838Sdfr * Redistribution and use in source and binary forms, with or without 6153838Sdfr * modification, are permitted provided that the following conditions 7153838Sdfr * are met: 8153838Sdfr * 1. Redistributions of source code must retain the above copyright 9153838Sdfr * notice, this list of conditions and the following disclaimer. 10153838Sdfr * 2. Redistributions in binary form must reproduce the above copyright 11153838Sdfr * notice, this list of conditions and the following disclaimer in the 12153838Sdfr * documentation and/or other materials provided with the distribution. 13153838Sdfr * 14153838Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15153838Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16153838Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17153838Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18153838Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19153838Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20153838Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21153838Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22153838Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23153838Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24153838Sdfr * SUCH DAMAGE. 25153838Sdfr * 26153838Sdfr * $FreeBSD$ 27153838Sdfr */ 28171112Sdfr/* 29229784Suqs * Copyright (c) 1998 - 2005 Kungliga Tekniska H��gskolan 30171112Sdfr * (Royal Institute of Technology, Stockholm, Sweden). 31171112Sdfr * All rights reserved. 32171112Sdfr * 33171112Sdfr * Redistribution and use in source and binary forms, with or without 34171112Sdfr * modification, are permitted provided that the following conditions 35171112Sdfr * are met: 36171112Sdfr * 37171112Sdfr * 1. Redistributions of source code must retain the above copyright 38171112Sdfr * notice, this list of conditions and the following disclaimer. 39171112Sdfr * 40171112Sdfr * 2. Redistributions in binary form must reproduce the above copyright 41171112Sdfr * notice, this list of conditions and the following disclaimer in the 42171112Sdfr * documentation and/or other materials provided with the distribution. 43171112Sdfr * 44171112Sdfr * 3. Neither the name of the Institute nor the names of its contributors 45171112Sdfr * may be used to endorse or promote products derived from this software 46171112Sdfr * without specific prior written permission. 47171112Sdfr * 48171112Sdfr * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 49171112Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50171112Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51171112Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 52171112Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53171112Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54171112Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55171112Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56171112Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57171112Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58171112Sdfr * SUCH DAMAGE. 59171112Sdfr */ 60178828Sdfr/* 61229784Suqs * Copyright (c) 1998 - 2005 Kungliga Tekniska H��gskolan 62178828Sdfr * (Royal Institute of Technology, Stockholm, Sweden). 63178828Sdfr * All rights reserved. 64178828Sdfr * 65178828Sdfr * Redistribution and use in source and binary forms, with or without 66178828Sdfr * modification, are permitted provided that the following conditions 67178828Sdfr * are met: 68178828Sdfr * 69178828Sdfr * 1. Redistributions of source code must retain the above copyright 70178828Sdfr * notice, this list of conditions and the following disclaimer. 71178828Sdfr * 72178828Sdfr * 2. Redistributions in binary form must reproduce the above copyright 73178828Sdfr * notice, this list of conditions and the following disclaimer in the 74178828Sdfr * documentation and/or other materials provided with the distribution. 75178828Sdfr * 76178828Sdfr * 3. Neither the name of the Institute nor the names of its contributors 77178828Sdfr * may be used to endorse or promote products derived from this software 78178828Sdfr * without specific prior written permission. 79178828Sdfr * 80178828Sdfr * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 81178828Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 82178828Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 83178828Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 84178828Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 85178828Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 86178828Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 87178828Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 88178828Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 89178828Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 90178828Sdfr * SUCH DAMAGE. 91178828Sdfr */ 92153838Sdfr 93153838Sdfr#include <gssapi/gssapi.h> 94178828Sdfr#include <stdio.h> 95153838Sdfr#include <string.h> 96178828Sdfr#include <stdlib.h> 97171112Sdfr#include <errno.h> 98153838Sdfr 99153838Sdfr#include "mech_switch.h" 100178828Sdfr#include "utils.h" 101153838Sdfr 102171112Sdfrstatic const char * 103171112Sdfrcalling_error(OM_uint32 v) 104171112Sdfr{ 105171112Sdfr static const char *msgs[] = { 106171112Sdfr NULL, /* 0 */ 107171112Sdfr "A required input parameter could not be read.", /* */ 108171112Sdfr "A required output parameter could not be written.", /* */ 109171112Sdfr "A parameter was malformed" 110171112Sdfr }; 111153838Sdfr 112171112Sdfr v >>= GSS_C_CALLING_ERROR_OFFSET; 113153838Sdfr 114171112Sdfr if (v == 0) 115171112Sdfr return ""; 116171112Sdfr else if (v >= sizeof(msgs)/sizeof(*msgs)) 117171112Sdfr return "unknown calling error"; 118171112Sdfr else 119171112Sdfr return msgs[v]; 120171112Sdfr} 121153838Sdfr 122171112Sdfrstatic const char * 123171112Sdfrroutine_error(OM_uint32 v) 124171112Sdfr{ 125171112Sdfr static const char *msgs[] = { 126178828Sdfr "Function completed successfully", /* 0 */ 127171112Sdfr "An unsupported mechanism was requested", 128171112Sdfr "An invalid name was supplied", 129171112Sdfr "A supplied name was of an unsupported type", 130171112Sdfr "Incorrect channel bindings were supplied", 131171112Sdfr "An invalid status code was supplied", 132171112Sdfr "A token had an invalid MIC", 133171112Sdfr "No credentials were supplied, " 134171112Sdfr "or the credentials were unavailable or inaccessible.", 135171112Sdfr "No context has been established", 136171112Sdfr "A token was invalid", 137171112Sdfr "A credential was invalid", 138171112Sdfr "The referenced credentials have expired", 139171112Sdfr "The context has expired", 140171112Sdfr "Miscellaneous failure (see text)", 141171112Sdfr "The quality-of-protection requested could not be provide", 142171112Sdfr "The operation is forbidden by local security policy", 143171112Sdfr "The operation or option is not available", 144171112Sdfr "The requested credential element already exists", 145171112Sdfr "The provided name was not a mechanism name.", 146171112Sdfr }; 147171112Sdfr 148171112Sdfr v >>= GSS_C_ROUTINE_ERROR_OFFSET; 149171112Sdfr 150178828Sdfr if (v >= sizeof(msgs)/sizeof(*msgs)) 151171112Sdfr return "unknown routine error"; 152171112Sdfr else 153171112Sdfr return msgs[v]; 154171112Sdfr} 155171112Sdfr 156171112Sdfrstatic const char * 157171112Sdfrsupplementary_error(OM_uint32 v) 158171112Sdfr{ 159171112Sdfr static const char *msgs[] = { 160171112Sdfr "normal completion", 161171112Sdfr "continuation call to routine required", 162171112Sdfr "duplicate per-message token detected", 163171112Sdfr "timed-out per-message token detected", 164171112Sdfr "reordered (early) per-message token detected", 165171112Sdfr "skipped predecessor token(s) detected" 166171112Sdfr }; 167171112Sdfr 168171112Sdfr v >>= GSS_C_SUPPLEMENTARY_OFFSET; 169171112Sdfr 170171112Sdfr if (v >= sizeof(msgs)/sizeof(*msgs)) 171171112Sdfr return "unknown routine error"; 172171112Sdfr else 173171112Sdfr return msgs[v]; 174171112Sdfr} 175171112Sdfr 176234011Sstas#if defined(__NO_TLS) 177178828Sdfr 178178828Sdfr/* 179178828Sdfr * These platforms don't support TLS on FreeBSD - threads will just 180178828Sdfr * have to step on each other's error values for now. 181178828Sdfr */ 182178828Sdfr#define __thread 183178828Sdfr 184178828Sdfr#endif 185178828Sdfr 186178828Sdfrstruct mg_thread_ctx { 187178828Sdfr gss_OID mech; 188178828Sdfr OM_uint32 maj_stat; 189178828Sdfr OM_uint32 min_stat; 190178828Sdfr gss_buffer_desc maj_error; 191178828Sdfr gss_buffer_desc min_error; 192178828Sdfr}; 193178828Sdfrstatic __thread struct mg_thread_ctx last_error_context; 194178828Sdfr 195178828Sdfrstatic OM_uint32 196178828Sdfr_gss_mg_get_error(const gss_OID mech, OM_uint32 type, 197178828Sdfr OM_uint32 value, gss_buffer_t string) 198178828Sdfr{ 199178828Sdfr struct mg_thread_ctx *mg; 200178828Sdfr 201178828Sdfr mg = &last_error_context; 202178828Sdfr 203178828Sdfr if (mech != NULL && gss_oid_equal(mg->mech, mech) == 0) 204178828Sdfr return (GSS_S_BAD_STATUS); 205178828Sdfr 206178828Sdfr switch (type) { 207178828Sdfr case GSS_C_GSS_CODE: { 208178828Sdfr if (value != mg->maj_stat || mg->maj_error.length == 0) 209178828Sdfr break; 210178828Sdfr string->value = malloc(mg->maj_error.length); 211178828Sdfr string->length = mg->maj_error.length; 212178828Sdfr memcpy(string->value, mg->maj_error.value, 213178828Sdfr mg->maj_error.length); 214178828Sdfr return (GSS_S_COMPLETE); 215178828Sdfr } 216178828Sdfr case GSS_C_MECH_CODE: { 217178828Sdfr if (value != mg->min_stat || mg->min_error.length == 0) 218178828Sdfr break; 219178828Sdfr string->value = malloc(mg->min_error.length); 220178828Sdfr string->length = mg->min_error.length; 221178828Sdfr memcpy(string->value, mg->min_error.value, 222178828Sdfr mg->min_error.length); 223178828Sdfr return (GSS_S_COMPLETE); 224178828Sdfr } 225178828Sdfr } 226178828Sdfr string->value = NULL; 227178828Sdfr string->length = 0; 228178828Sdfr return (GSS_S_BAD_STATUS); 229178828Sdfr} 230178828Sdfr 231178828Sdfrvoid 232178828Sdfr_gss_mg_error(struct _gss_mech_switch *m, OM_uint32 maj, OM_uint32 min) 233178828Sdfr{ 234178828Sdfr OM_uint32 major_status, minor_status; 235178828Sdfr OM_uint32 message_content; 236178828Sdfr struct mg_thread_ctx *mg; 237178828Sdfr 238178828Sdfr mg = &last_error_context; 239178828Sdfr 240178828Sdfr gss_release_buffer(&minor_status, &mg->maj_error); 241178828Sdfr gss_release_buffer(&minor_status, &mg->min_error); 242178828Sdfr 243178828Sdfr mg->mech = &m->gm_mech_oid; 244178828Sdfr mg->maj_stat = maj; 245178828Sdfr mg->min_stat = min; 246178828Sdfr 247178828Sdfr major_status = m->gm_display_status(&minor_status, 248178828Sdfr maj, 249178828Sdfr GSS_C_GSS_CODE, 250178828Sdfr &m->gm_mech_oid, 251178828Sdfr &message_content, 252178828Sdfr &mg->maj_error); 253178828Sdfr if (GSS_ERROR(major_status)) { 254178828Sdfr mg->maj_error.value = NULL; 255178828Sdfr mg->maj_error.length = 0; 256178828Sdfr } 257178828Sdfr major_status = m->gm_display_status(&minor_status, 258178828Sdfr min, 259178828Sdfr GSS_C_MECH_CODE, 260178828Sdfr &m->gm_mech_oid, 261178828Sdfr &message_content, 262178828Sdfr &mg->min_error); 263178828Sdfr if (GSS_ERROR(major_status)) { 264178828Sdfr mg->min_error.value = NULL; 265178828Sdfr mg->min_error.length = 0; 266178828Sdfr } 267178828Sdfr} 268178828Sdfr 269153838SdfrOM_uint32 270153838Sdfrgss_display_status(OM_uint32 *minor_status, 271153838Sdfr OM_uint32 status_value, 272153838Sdfr int status_type, 273178828Sdfr const gss_OID mech_type, 274153838Sdfr OM_uint32 *message_content, 275153838Sdfr gss_buffer_t status_string) 276153838Sdfr{ 277153838Sdfr OM_uint32 major_status; 278153838Sdfr 279178828Sdfr _gss_buffer_zero(status_string); 280178828Sdfr *message_content = 0; 281178828Sdfr 282178828Sdfr major_status = _gss_mg_get_error(mech_type, status_type, 283178828Sdfr status_value, status_string); 284178828Sdfr if (major_status == GSS_S_COMPLETE) { 285178828Sdfr 286178828Sdfr *message_content = 0; 287178828Sdfr *minor_status = 0; 288178828Sdfr return (GSS_S_COMPLETE); 289171254Sdfr } 290171254Sdfr 291153838Sdfr *minor_status = 0; 292153838Sdfr switch (status_type) { 293171112Sdfr case GSS_C_GSS_CODE: { 294171112Sdfr char *buf; 295153838Sdfr 296171112Sdfr if (GSS_SUPPLEMENTARY_INFO(status_value)) 297171112Sdfr asprintf(&buf, "%s", supplementary_error( 298171112Sdfr GSS_SUPPLEMENTARY_INFO(status_value))); 299171112Sdfr else 300171112Sdfr asprintf (&buf, "%s %s", 301171112Sdfr calling_error(GSS_CALLING_ERROR(status_value)), 302171112Sdfr routine_error(GSS_ROUTINE_ERROR(status_value))); 303171112Sdfr 304178828Sdfr if (buf == NULL) 305178828Sdfr break; 306178828Sdfr 307171112Sdfr status_string->length = strlen(buf); 308171112Sdfr status_string->value = buf; 309171112Sdfr 310178828Sdfr return (GSS_S_COMPLETE); 311171112Sdfr } 312171112Sdfr case GSS_C_MECH_CODE: { 313178828Sdfr OM_uint32 maj_junk, min_junk; 314178828Sdfr gss_buffer_desc oid; 315178828Sdfr char *buf; 316178828Sdfr 317178828Sdfr maj_junk = gss_oid_to_str(&min_junk, mech_type, &oid); 318178828Sdfr if (maj_junk != GSS_S_COMPLETE) { 319178828Sdfr oid.value = strdup("unknown"); 320178828Sdfr oid.length = 7; 321153838Sdfr } 322178828Sdfr 323178828Sdfr asprintf (&buf, "unknown mech-code %lu for mech %.*s", 324178828Sdfr (unsigned long)status_value, 325178828Sdfr (int)oid.length, (char *)oid.value); 326178828Sdfr if (maj_junk == GSS_S_COMPLETE) 327178828Sdfr gss_release_buffer(&min_junk, &oid); 328178828Sdfr 329178828Sdfr if (buf == NULL) 330178828Sdfr break; 331178828Sdfr 332178828Sdfr status_string->length = strlen(buf); 333178828Sdfr status_string->value = buf; 334178828Sdfr 335178828Sdfr return (GSS_S_COMPLETE); 336153838Sdfr } 337171112Sdfr } 338178828Sdfr _gss_buffer_zero(status_string); 339153838Sdfr return (GSS_S_BAD_STATUS); 340153838Sdfr} 341233294Sstas 342233294Sstasvoid 343233294Sstas_gss_mg_collect_error(gss_OID mech, OM_uint32 maj, OM_uint32 min) 344233294Sstas{ 345233294Sstas struct _gss_mech_switch *m; 346233294Sstas 347233294Sstas m = _gss_find_mech_switch(mech); 348233294Sstas if (m != NULL) 349233294Sstas _gss_mg_error(m, maj, min); 350233294Sstas} 351