1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate /* 30*0Sstevel@tonic-gate * glue routine gss_display_status 31*0Sstevel@tonic-gate * 32*0Sstevel@tonic-gate */ 33*0Sstevel@tonic-gate 34*0Sstevel@tonic-gate #include <mechglueP.h> 35*0Sstevel@tonic-gate #include <stdio.h> 36*0Sstevel@tonic-gate #ifdef HAVE_STDLIB_H 37*0Sstevel@tonic-gate #include <stdlib.h> 38*0Sstevel@tonic-gate #endif 39*0Sstevel@tonic-gate #include <string.h> 40*0Sstevel@tonic-gate #include <libintl.h> 41*0Sstevel@tonic-gate #include <errno.h> 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gate #ifndef TEXT_DOMAIN 44*0Sstevel@tonic-gate #error TEXT_DOMAIN not defined 45*0Sstevel@tonic-gate #endif 46*0Sstevel@tonic-gate 47*0Sstevel@tonic-gate /* local function */ 48*0Sstevel@tonic-gate static OM_uint32 displayMajor(OM_uint32, OM_uint32 *, gss_buffer_t); 49*0Sstevel@tonic-gate 50*0Sstevel@tonic-gate 51*0Sstevel@tonic-gate OM_uint32 52*0Sstevel@tonic-gate gss_display_status(minor_status, 53*0Sstevel@tonic-gate status_value, 54*0Sstevel@tonic-gate status_type, 55*0Sstevel@tonic-gate req_mech_type, 56*0Sstevel@tonic-gate message_context, 57*0Sstevel@tonic-gate status_string) 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate OM_uint32 *minor_status; 60*0Sstevel@tonic-gate OM_uint32 status_value; 61*0Sstevel@tonic-gate int status_type; 62*0Sstevel@tonic-gate const gss_OID req_mech_type; 63*0Sstevel@tonic-gate OM_uint32 *message_context; 64*0Sstevel@tonic-gate gss_buffer_t status_string; 65*0Sstevel@tonic-gate { 66*0Sstevel@tonic-gate gss_OID mech_type = (gss_OID) req_mech_type; 67*0Sstevel@tonic-gate gss_mechanism mech; 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate /* check the input parameters */ 70*0Sstevel@tonic-gate if (!minor_status) 71*0Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE); 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate *minor_status = 0; 74*0Sstevel@tonic-gate 75*0Sstevel@tonic-gate if (!message_context || status_string == NULL) 76*0Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE); 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gate status_string->length = 0; 79*0Sstevel@tonic-gate status_string->value = NULL; 80*0Sstevel@tonic-gate 81*0Sstevel@tonic-gate /* we handle major status codes, and the mechs do the minor */ 82*0Sstevel@tonic-gate if (status_type == GSS_C_GSS_CODE) 83*0Sstevel@tonic-gate return (displayMajor(status_value, message_context, 84*0Sstevel@tonic-gate status_string)); 85*0Sstevel@tonic-gate 86*0Sstevel@tonic-gate /* 87*0Sstevel@tonic-gate * must be the minor status - let mechs do the work 88*0Sstevel@tonic-gate * select the appropriate underlying mechanism routine and 89*0Sstevel@tonic-gate * call it. 90*0Sstevel@tonic-gate */ 91*0Sstevel@tonic-gate mech = __gss_get_mechanism(mech_type); 92*0Sstevel@tonic-gate 93*0Sstevel@tonic-gate if (mech && mech->gss_display_status) { 94*0Sstevel@tonic-gate if (mech_type == GSS_C_NULL_OID) 95*0Sstevel@tonic-gate mech_type = &mech->mech_type; 96*0Sstevel@tonic-gate 97*0Sstevel@tonic-gate return (mech->gss_display_status(mech->context, minor_status, 98*0Sstevel@tonic-gate status_value, status_type, mech_type, 99*0Sstevel@tonic-gate message_context, status_string)); 100*0Sstevel@tonic-gate } 101*0Sstevel@tonic-gate 102*0Sstevel@tonic-gate if (!mech) 103*0Sstevel@tonic-gate return (GSS_S_BAD_MECH); 104*0Sstevel@tonic-gate 105*0Sstevel@tonic-gate return (GSS_S_UNAVAILABLE); 106*0Sstevel@tonic-gate } /* gss_display_status */ 107*0Sstevel@tonic-gate 108*0Sstevel@tonic-gate 109*0Sstevel@tonic-gate /* 110*0Sstevel@tonic-gate * function to map the major error codes 111*0Sstevel@tonic-gate * it uses case statements so that the strings could be wrapped by gettext 112*0Sstevel@tonic-gate * msgCtxt is interpreted as: 113*0Sstevel@tonic-gate * 0 - first call 114*0Sstevel@tonic-gate * 1 - routine error 115*0Sstevel@tonic-gate * >= 2 - the supplementary error code bit shifted by 1 116*0Sstevel@tonic-gate */ 117*0Sstevel@tonic-gate static OM_uint32 118*0Sstevel@tonic-gate displayMajor(status, msgCtxt, outStr) 119*0Sstevel@tonic-gate OM_uint32 status; 120*0Sstevel@tonic-gate OM_uint32 *msgCtxt; 121*0Sstevel@tonic-gate gss_buffer_t outStr; 122*0Sstevel@tonic-gate { 123*0Sstevel@tonic-gate OM_uint32 oneVal, mask = 0x1, currErr; 124*0Sstevel@tonic-gate char *errStr = NULL; 125*0Sstevel@tonic-gate int i, haveErr = 0; 126*0Sstevel@tonic-gate 127*0Sstevel@tonic-gate /* take care of the success value first */ 128*0Sstevel@tonic-gate if (status == GSS_S_COMPLETE) 129*0Sstevel@tonic-gate errStr = dgettext(TEXT_DOMAIN, 130*0Sstevel@tonic-gate "The routine completed successfully"); 131*0Sstevel@tonic-gate else if (*msgCtxt == 0 && (oneVal = GSS_CALLING_ERROR(status))) { 132*0Sstevel@tonic-gate switch (oneVal) { 133*0Sstevel@tonic-gate case GSS_S_CALL_INACCESSIBLE_READ: 134*0Sstevel@tonic-gate errStr = dgettext(TEXT_DOMAIN, 135*0Sstevel@tonic-gate "A required input parameter" 136*0Sstevel@tonic-gate " could not be read"); 137*0Sstevel@tonic-gate break; 138*0Sstevel@tonic-gate 139*0Sstevel@tonic-gate case GSS_S_CALL_INACCESSIBLE_WRITE: 140*0Sstevel@tonic-gate errStr = dgettext(TEXT_DOMAIN, 141*0Sstevel@tonic-gate "A required output parameter" 142*0Sstevel@tonic-gate " could not be written"); 143*0Sstevel@tonic-gate break; 144*0Sstevel@tonic-gate 145*0Sstevel@tonic-gate case GSS_S_CALL_BAD_STRUCTURE: 146*0Sstevel@tonic-gate errStr = dgettext(TEXT_DOMAIN, 147*0Sstevel@tonic-gate "A parameter was malformed"); 148*0Sstevel@tonic-gate break; 149*0Sstevel@tonic-gate 150*0Sstevel@tonic-gate default: 151*0Sstevel@tonic-gate errStr = dgettext(TEXT_DOMAIN, 152*0Sstevel@tonic-gate "An invalid status code was supplied"); 153*0Sstevel@tonic-gate break; 154*0Sstevel@tonic-gate } 155*0Sstevel@tonic-gate 156*0Sstevel@tonic-gate /* we now need to determine new value of msgCtxt */ 157*0Sstevel@tonic-gate if (GSS_ROUTINE_ERROR(status)) 158*0Sstevel@tonic-gate *msgCtxt = 1; 159*0Sstevel@tonic-gate else if ((oneVal = GSS_SUPPLEMENTARY_INFO(status)) != 0) 160*0Sstevel@tonic-gate *msgCtxt = (OM_uint32)(oneVal << 1); 161*0Sstevel@tonic-gate else 162*0Sstevel@tonic-gate *msgCtxt = 0; 163*0Sstevel@tonic-gate 164*0Sstevel@tonic-gate } else if ((*msgCtxt == 0 || *msgCtxt == 1) && 165*0Sstevel@tonic-gate (oneVal = GSS_ROUTINE_ERROR(status))) { 166*0Sstevel@tonic-gate switch (oneVal) { 167*0Sstevel@tonic-gate case GSS_S_BAD_MECH: 168*0Sstevel@tonic-gate errStr = dgettext(TEXT_DOMAIN, 169*0Sstevel@tonic-gate "An unsupported mechanism" 170*0Sstevel@tonic-gate " was requested"); 171*0Sstevel@tonic-gate break; 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gate case GSS_S_BAD_NAME: 174*0Sstevel@tonic-gate errStr = dgettext(TEXT_DOMAIN, 175*0Sstevel@tonic-gate "An invalid name was supplied"); 176*0Sstevel@tonic-gate break; 177*0Sstevel@tonic-gate 178*0Sstevel@tonic-gate case GSS_S_BAD_NAMETYPE: 179*0Sstevel@tonic-gate errStr = dgettext(TEXT_DOMAIN, 180*0Sstevel@tonic-gate "A supplied name was of an" 181*0Sstevel@tonic-gate " unsupported type"); 182*0Sstevel@tonic-gate break; 183*0Sstevel@tonic-gate 184*0Sstevel@tonic-gate case GSS_S_BAD_BINDINGS: 185*0Sstevel@tonic-gate errStr = dgettext(TEXT_DOMAIN, 186*0Sstevel@tonic-gate "Incorrect channel bindings" 187*0Sstevel@tonic-gate " were supplied"); 188*0Sstevel@tonic-gate break; 189*0Sstevel@tonic-gate 190*0Sstevel@tonic-gate case GSS_S_BAD_SIG: /* same as GSS_S_BAD_MIC: */ 191*0Sstevel@tonic-gate errStr = dgettext(TEXT_DOMAIN, 192*0Sstevel@tonic-gate "A token had an invalid Message" 193*0Sstevel@tonic-gate " Integrity Check (MIC)"); 194*0Sstevel@tonic-gate break; 195*0Sstevel@tonic-gate 196*0Sstevel@tonic-gate case GSS_S_NO_CRED: 197*0Sstevel@tonic-gate errStr = dgettext(TEXT_DOMAIN, 198*0Sstevel@tonic-gate "No credentials were supplied, or the" 199*0Sstevel@tonic-gate " credentials were unavailable or" 200*0Sstevel@tonic-gate " inaccessible"); 201*0Sstevel@tonic-gate break; 202*0Sstevel@tonic-gate 203*0Sstevel@tonic-gate case GSS_S_NO_CONTEXT: 204*0Sstevel@tonic-gate errStr = dgettext(TEXT_DOMAIN, 205*0Sstevel@tonic-gate "No context has been established"); 206*0Sstevel@tonic-gate break; 207*0Sstevel@tonic-gate 208*0Sstevel@tonic-gate case GSS_S_DEFECTIVE_TOKEN: 209*0Sstevel@tonic-gate errStr = dgettext(TEXT_DOMAIN, 210*0Sstevel@tonic-gate "Invalid token was supplied"); 211*0Sstevel@tonic-gate break; 212*0Sstevel@tonic-gate 213*0Sstevel@tonic-gate case GSS_S_DEFECTIVE_CREDENTIAL: 214*0Sstevel@tonic-gate errStr = dgettext(TEXT_DOMAIN, 215*0Sstevel@tonic-gate "Invalid credential was supplied"); 216*0Sstevel@tonic-gate break; 217*0Sstevel@tonic-gate 218*0Sstevel@tonic-gate case GSS_S_CREDENTIALS_EXPIRED: 219*0Sstevel@tonic-gate errStr = dgettext(TEXT_DOMAIN, 220*0Sstevel@tonic-gate "The referenced credential has" 221*0Sstevel@tonic-gate " expired"); 222*0Sstevel@tonic-gate break; 223*0Sstevel@tonic-gate 224*0Sstevel@tonic-gate case GSS_S_CONTEXT_EXPIRED: 225*0Sstevel@tonic-gate errStr = dgettext(TEXT_DOMAIN, 226*0Sstevel@tonic-gate "The referenced context has expired"); 227*0Sstevel@tonic-gate break; 228*0Sstevel@tonic-gate 229*0Sstevel@tonic-gate case GSS_S_FAILURE: 230*0Sstevel@tonic-gate errStr = dgettext(TEXT_DOMAIN, 231*0Sstevel@tonic-gate "Unspecified GSS failure. Minor code" 232*0Sstevel@tonic-gate " may provide more information"); 233*0Sstevel@tonic-gate break; 234*0Sstevel@tonic-gate 235*0Sstevel@tonic-gate case GSS_S_BAD_QOP: 236*0Sstevel@tonic-gate errStr = dgettext(TEXT_DOMAIN, 237*0Sstevel@tonic-gate "The quality-of-protection (QOP) " 238*0Sstevel@tonic-gate "requested could not be provided"); 239*0Sstevel@tonic-gate break; 240*0Sstevel@tonic-gate 241*0Sstevel@tonic-gate case GSS_S_UNAUTHORIZED: 242*0Sstevel@tonic-gate errStr = dgettext(TEXT_DOMAIN, 243*0Sstevel@tonic-gate "The operation is forbidden by local" 244*0Sstevel@tonic-gate " security policy"); 245*0Sstevel@tonic-gate break; 246*0Sstevel@tonic-gate 247*0Sstevel@tonic-gate case GSS_S_UNAVAILABLE: 248*0Sstevel@tonic-gate errStr = dgettext(TEXT_DOMAIN, 249*0Sstevel@tonic-gate "The operation or option is not" 250*0Sstevel@tonic-gate " available or unsupported"); 251*0Sstevel@tonic-gate break; 252*0Sstevel@tonic-gate 253*0Sstevel@tonic-gate case GSS_S_DUPLICATE_ELEMENT: 254*0Sstevel@tonic-gate errStr = dgettext(TEXT_DOMAIN, 255*0Sstevel@tonic-gate "The requested credential element" 256*0Sstevel@tonic-gate " already exists"); 257*0Sstevel@tonic-gate break; 258*0Sstevel@tonic-gate 259*0Sstevel@tonic-gate case GSS_S_NAME_NOT_MN: 260*0Sstevel@tonic-gate errStr = dgettext(TEXT_DOMAIN, 261*0Sstevel@tonic-gate "The provided name was not mechanism" 262*0Sstevel@tonic-gate " specific (MN)"); 263*0Sstevel@tonic-gate break; 264*0Sstevel@tonic-gate 265*0Sstevel@tonic-gate case GSS_S_BAD_STATUS: 266*0Sstevel@tonic-gate default: 267*0Sstevel@tonic-gate errStr = dgettext(TEXT_DOMAIN, 268*0Sstevel@tonic-gate "An invalid status code was supplied"); 269*0Sstevel@tonic-gate } 270*0Sstevel@tonic-gate 271*0Sstevel@tonic-gate /* we must determine if the caller should call us again */ 272*0Sstevel@tonic-gate if ((oneVal = GSS_SUPPLEMENTARY_INFO(status)) != 0) 273*0Sstevel@tonic-gate *msgCtxt = (OM_uint32)(oneVal << 1); 274*0Sstevel@tonic-gate else 275*0Sstevel@tonic-gate *msgCtxt = 0; 276*0Sstevel@tonic-gate 277*0Sstevel@tonic-gate } else if ((*msgCtxt == 0 || *msgCtxt >= 2) && 278*0Sstevel@tonic-gate (oneVal = GSS_SUPPLEMENTARY_INFO(status))) { 279*0Sstevel@tonic-gate /* 280*0Sstevel@tonic-gate * if msgCtxt is not 0, then it should encode 281*0Sstevel@tonic-gate * the supplementary error code we should be printing 282*0Sstevel@tonic-gate */ 283*0Sstevel@tonic-gate if (*msgCtxt >= 2) 284*0Sstevel@tonic-gate oneVal = (OM_uint32) (*msgCtxt) >> 1; 285*0Sstevel@tonic-gate else 286*0Sstevel@tonic-gate oneVal = GSS_SUPPLEMENTARY_INFO(status); 287*0Sstevel@tonic-gate 288*0Sstevel@tonic-gate /* we display the errors LSB first */ 289*0Sstevel@tonic-gate for (i = 0; i < 16; i++) { 290*0Sstevel@tonic-gate if (oneVal & mask) { 291*0Sstevel@tonic-gate haveErr = 1; 292*0Sstevel@tonic-gate break; 293*0Sstevel@tonic-gate } 294*0Sstevel@tonic-gate mask <<= 1; 295*0Sstevel@tonic-gate } 296*0Sstevel@tonic-gate 297*0Sstevel@tonic-gate /* isolate the bit or if not found set to illegal value */ 298*0Sstevel@tonic-gate if (haveErr) 299*0Sstevel@tonic-gate currErr = oneVal & mask; 300*0Sstevel@tonic-gate else 301*0Sstevel@tonic-gate currErr = 1 << 17; /* illegal value */ 302*0Sstevel@tonic-gate 303*0Sstevel@tonic-gate switch (currErr) { 304*0Sstevel@tonic-gate case GSS_S_CONTINUE_NEEDED: 305*0Sstevel@tonic-gate errStr = dgettext(TEXT_DOMAIN, 306*0Sstevel@tonic-gate "The routine must be called again to" 307*0Sstevel@tonic-gate " complete its function"); 308*0Sstevel@tonic-gate break; 309*0Sstevel@tonic-gate 310*0Sstevel@tonic-gate case GSS_S_DUPLICATE_TOKEN: 311*0Sstevel@tonic-gate errStr = dgettext(TEXT_DOMAIN, 312*0Sstevel@tonic-gate "The token was a duplicate of an" 313*0Sstevel@tonic-gate " earlier token"); 314*0Sstevel@tonic-gate break; 315*0Sstevel@tonic-gate 316*0Sstevel@tonic-gate case GSS_S_OLD_TOKEN: 317*0Sstevel@tonic-gate errStr = dgettext(TEXT_DOMAIN, 318*0Sstevel@tonic-gate "The token's validity period" 319*0Sstevel@tonic-gate " has expired"); 320*0Sstevel@tonic-gate break; 321*0Sstevel@tonic-gate 322*0Sstevel@tonic-gate case GSS_S_UNSEQ_TOKEN: 323*0Sstevel@tonic-gate errStr = dgettext(TEXT_DOMAIN, 324*0Sstevel@tonic-gate "A later token has already been" 325*0Sstevel@tonic-gate " processed"); 326*0Sstevel@tonic-gate break; 327*0Sstevel@tonic-gate 328*0Sstevel@tonic-gate case GSS_S_GAP_TOKEN: 329*0Sstevel@tonic-gate errStr = dgettext(TEXT_DOMAIN, 330*0Sstevel@tonic-gate "An expected per-message token was" 331*0Sstevel@tonic-gate " not received"); 332*0Sstevel@tonic-gate break; 333*0Sstevel@tonic-gate 334*0Sstevel@tonic-gate default: 335*0Sstevel@tonic-gate errStr = dgettext(TEXT_DOMAIN, 336*0Sstevel@tonic-gate "An invalid status code was supplied"); 337*0Sstevel@tonic-gate } 338*0Sstevel@tonic-gate 339*0Sstevel@tonic-gate /* 340*0Sstevel@tonic-gate * we must check if there is any other supplementary errors 341*0Sstevel@tonic-gate * if found, then turn off current bit, and store next value 342*0Sstevel@tonic-gate * in msgCtxt shifted by 1 bit 343*0Sstevel@tonic-gate */ 344*0Sstevel@tonic-gate if (!haveErr) 345*0Sstevel@tonic-gate *msgCtxt = 0; 346*0Sstevel@tonic-gate else if (GSS_SUPPLEMENTARY_INFO(oneVal) ^ mask) 347*0Sstevel@tonic-gate *msgCtxt = (OM_uint32) 348*0Sstevel@tonic-gate ((GSS_SUPPLEMENTARY_INFO(oneVal) ^ mask) << 1); 349*0Sstevel@tonic-gate else 350*0Sstevel@tonic-gate *msgCtxt = 0; 351*0Sstevel@tonic-gate } 352*0Sstevel@tonic-gate 353*0Sstevel@tonic-gate if (errStr == NULL) 354*0Sstevel@tonic-gate errStr = dgettext(TEXT_DOMAIN, 355*0Sstevel@tonic-gate "An invalid status code was supplied"); 356*0Sstevel@tonic-gate 357*0Sstevel@tonic-gate /* now copy the status code and return to caller */ 358*0Sstevel@tonic-gate outStr->length = strlen(errStr); 359*0Sstevel@tonic-gate outStr->value = malloc((size_t)outStr->length+1); 360*0Sstevel@tonic-gate if (outStr->value == NULL) { 361*0Sstevel@tonic-gate outStr->length = 0; 362*0Sstevel@tonic-gate return (GSS_S_FAILURE); 363*0Sstevel@tonic-gate } 364*0Sstevel@tonic-gate 365*0Sstevel@tonic-gate (void) strcpy((char *)outStr->value, errStr); 366*0Sstevel@tonic-gate return (GSS_S_COMPLETE); 367*0Sstevel@tonic-gate } /* displayMajor */ 368