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