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