1/*- 2 * Copyright (c) 2005 Doug Rabson 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: stable/11/lib/libgssapi/gss_display_status.c 366940 2020-10-22 16:41:13Z brooks $ 27 */ 28/* 29 * Copyright (c) 1998 - 2005 Kungliga Tekniska H��gskolan 30 * (Royal Institute of Technology, Stockholm, Sweden). 31 * All rights reserved. 32 * 33 * Redistribution and use in source and binary forms, with or without 34 * modification, are permitted provided that the following conditions 35 * are met: 36 * 37 * 1. Redistributions of source code must retain the above copyright 38 * notice, this list of conditions and the following disclaimer. 39 * 40 * 2. Redistributions in binary form must reproduce the above copyright 41 * notice, this list of conditions and the following disclaimer in the 42 * documentation and/or other materials provided with the distribution. 43 * 44 * 3. Neither the name of the Institute nor the names of its contributors 45 * may be used to endorse or promote products derived from this software 46 * without specific prior written permission. 47 * 48 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 * SUCH DAMAGE. 59 */ 60/* 61 * Copyright (c) 1998 - 2005 Kungliga Tekniska H��gskolan 62 * (Royal Institute of Technology, Stockholm, Sweden). 63 * All rights reserved. 64 * 65 * Redistribution and use in source and binary forms, with or without 66 * modification, are permitted provided that the following conditions 67 * are met: 68 * 69 * 1. Redistributions of source code must retain the above copyright 70 * notice, this list of conditions and the following disclaimer. 71 * 72 * 2. Redistributions in binary form must reproduce the above copyright 73 * notice, this list of conditions and the following disclaimer in the 74 * documentation and/or other materials provided with the distribution. 75 * 76 * 3. Neither the name of the Institute nor the names of its contributors 77 * may be used to endorse or promote products derived from this software 78 * without specific prior written permission. 79 * 80 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 81 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 82 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 83 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 84 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 85 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 86 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 87 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 88 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 89 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 90 * SUCH DAMAGE. 91 */ 92 93#include <sys/param.h> 94#include <gssapi/gssapi.h> 95#include <stdio.h> 96#include <string.h> 97#include <stdlib.h> 98#include <errno.h> 99 100#include "mech_switch.h" 101#include "utils.h" 102 103static const char * 104calling_error(OM_uint32 v) 105{ 106 static const char *msgs[] = { 107 [0] = "", 108 [1] = "A required input parameter could not be read.", 109 [2] = "A required output parameter could not be written.", 110 [3] = "A parameter was malformed", 111 }; 112 113 v >>= GSS_C_CALLING_ERROR_OFFSET; 114 115 if (v >= nitems(msgs)) 116 return "unknown calling error"; 117 else 118 return msgs[v]; 119} 120 121static const char * 122routine_error(OM_uint32 v) 123{ 124 static const char *msgs[] = { 125 [0] = "Function completed successfully", 126 [1] = "An unsupported mechanism was requested", 127 [2] = "An invalid name was supplied", 128 [3] = "A supplied name was of an unsupported type", 129 [4] = "Incorrect channel bindings were supplied", 130 [5] = "An invalid status code was supplied", 131 [6] = "A token had an invalid MIC", 132 [7] = ("No credentials were supplied, " 133 "or the credentials were unavailable or inaccessible."), 134 [8] = "No context has been established", 135 [9] = "A token was invalid", 136 [10] = "A credential was invalid", 137 [11] = "The referenced credentials have expired", 138 [12] = "The context has expired", 139 [13] = "Miscellaneous failure (see text)", 140 [14] = "The quality-of-protection requested could not be provide", 141 [15] = "The operation is forbidden by local security policy", 142 [16] = "The operation or option is not available", 143 [17] = "The requested credential element already exists", 144 [18] = "The provided name was not a mechanism name.", 145 }; 146 147 v >>= GSS_C_ROUTINE_ERROR_OFFSET; 148 149 if (v >= nitems(msgs)) 150 return "unknown routine error"; 151 else 152 return msgs[v]; 153} 154 155static const char * 156supplementary_error(OM_uint32 v) 157{ 158 static const char *msgs[] = { 159 [0] = "normal completion", 160 [1] = "continuation call to routine required", 161 [2] = "duplicate per-message token detected", 162 [3] = "timed-out per-message token detected", 163 [4] = "reordered (early) per-message token detected", 164 [5] = "skipped predecessor token(s) detected", 165 }; 166 167 v >>= GSS_C_SUPPLEMENTARY_OFFSET; 168 169 if (v >= nitems(msgs)) 170 return "unknown routine error"; 171 else 172 return msgs[v]; 173} 174 175#if defined(__NO_TLS) 176 177/* 178 * These platforms don't support TLS on FreeBSD - threads will just 179 * have to step on each other's error values for now. 180 */ 181#define __thread 182 183#endif 184 185struct mg_thread_ctx { 186 gss_OID mech; 187 OM_uint32 maj_stat; 188 OM_uint32 min_stat; 189 gss_buffer_desc maj_error; 190 gss_buffer_desc min_error; 191}; 192static __thread struct mg_thread_ctx last_error_context; 193 194static OM_uint32 195_gss_mg_get_error(const gss_OID mech, OM_uint32 type, 196 OM_uint32 value, gss_buffer_t string) 197{ 198 struct mg_thread_ctx *mg; 199 200 mg = &last_error_context; 201 202 if (mech != NULL && gss_oid_equal(mg->mech, mech) == 0) 203 return (GSS_S_BAD_STATUS); 204 205 switch (type) { 206 case GSS_C_GSS_CODE: { 207 if (value != mg->maj_stat || mg->maj_error.length == 0) 208 break; 209 string->value = malloc(mg->maj_error.length); 210 string->length = mg->maj_error.length; 211 memcpy(string->value, mg->maj_error.value, 212 mg->maj_error.length); 213 return (GSS_S_COMPLETE); 214 } 215 case GSS_C_MECH_CODE: { 216 if (value != mg->min_stat || mg->min_error.length == 0) 217 break; 218 string->value = malloc(mg->min_error.length); 219 string->length = mg->min_error.length; 220 memcpy(string->value, mg->min_error.value, 221 mg->min_error.length); 222 return (GSS_S_COMPLETE); 223 } 224 } 225 string->value = NULL; 226 string->length = 0; 227 return (GSS_S_BAD_STATUS); 228} 229 230void 231_gss_mg_error(struct _gss_mech_switch *m, OM_uint32 maj, OM_uint32 min) 232{ 233 OM_uint32 major_status, minor_status; 234 OM_uint32 message_content; 235 struct mg_thread_ctx *mg; 236 237 mg = &last_error_context; 238 239 gss_release_buffer(&minor_status, &mg->maj_error); 240 gss_release_buffer(&minor_status, &mg->min_error); 241 242 mg->mech = &m->gm_mech_oid; 243 mg->maj_stat = maj; 244 mg->min_stat = min; 245 246 major_status = m->gm_display_status(&minor_status, 247 maj, 248 GSS_C_GSS_CODE, 249 &m->gm_mech_oid, 250 &message_content, 251 &mg->maj_error); 252 if (GSS_ERROR(major_status)) { 253 mg->maj_error.value = NULL; 254 mg->maj_error.length = 0; 255 } 256 major_status = m->gm_display_status(&minor_status, 257 min, 258 GSS_C_MECH_CODE, 259 &m->gm_mech_oid, 260 &message_content, 261 &mg->min_error); 262 if (GSS_ERROR(major_status)) { 263 mg->min_error.value = NULL; 264 mg->min_error.length = 0; 265 } 266} 267 268OM_uint32 269gss_display_status(OM_uint32 *minor_status, 270 OM_uint32 status_value, 271 int status_type, 272 const gss_OID mech_type, 273 OM_uint32 *message_content, 274 gss_buffer_t status_string) 275{ 276 OM_uint32 major_status; 277 278 _gss_buffer_zero(status_string); 279 *message_content = 0; 280 281 major_status = _gss_mg_get_error(mech_type, status_type, 282 status_value, status_string); 283 if (major_status == GSS_S_COMPLETE) { 284 285 *message_content = 0; 286 *minor_status = 0; 287 return (GSS_S_COMPLETE); 288 } 289 290 *minor_status = 0; 291 switch (status_type) { 292 case GSS_C_GSS_CODE: { 293 char *buf; 294 295 if (GSS_SUPPLEMENTARY_INFO(status_value)) 296 asprintf(&buf, "%s", supplementary_error( 297 GSS_SUPPLEMENTARY_INFO(status_value))); 298 else 299 asprintf (&buf, "%s %s", 300 calling_error(GSS_CALLING_ERROR(status_value)), 301 routine_error(GSS_ROUTINE_ERROR(status_value))); 302 303 if (buf == NULL) 304 break; 305 306 status_string->length = strlen(buf); 307 status_string->value = buf; 308 309 return (GSS_S_COMPLETE); 310 } 311 case GSS_C_MECH_CODE: { 312 OM_uint32 maj_junk, min_junk; 313 gss_buffer_desc oid; 314 char *buf; 315 316 maj_junk = gss_oid_to_str(&min_junk, mech_type, &oid); 317 if (maj_junk != GSS_S_COMPLETE) { 318 oid.value = strdup("unknown"); 319 oid.length = 7; 320 } 321 322 asprintf (&buf, "unknown mech-code %lu for mech %.*s", 323 (unsigned long)status_value, 324 (int)oid.length, (char *)oid.value); 325 if (maj_junk == GSS_S_COMPLETE) 326 gss_release_buffer(&min_junk, &oid); 327 328 if (buf == NULL) 329 break; 330 331 status_string->length = strlen(buf); 332 status_string->value = buf; 333 334 return (GSS_S_COMPLETE); 335 } 336 } 337 _gss_buffer_zero(status_string); 338 return (GSS_S_BAD_STATUS); 339} 340 341void 342_gss_mg_collect_error(gss_OID mech, OM_uint32 maj, OM_uint32 min) 343{ 344 struct _gss_mech_switch *m; 345 346 m = _gss_find_mech_switch(mech); 347 if (m != NULL) 348 _gss_mg_error(m, maj, min); 349} 350