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 */