Udiff g_dsp_status.c
--- /net/etna.eng/build7/semery/mit2/webrev/usr/src/lib/libgss/g_dsp_status.c-  Wed Sep  8 17:00:21 2004
+++ g_dsp_status.c      Wed Sep  8 13:42:02 2004
@@ -1,11 +1,11 @@
 /*
  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident  "@(#)g_dsp_status.c     1.18    04/09/08 SMI"
+#pragma ident  "@(#)g_dsp_status.c     1.17    04/02/23 SMI"
 
 /*
  *  glue routine gss_display_status
  *
  */
@@ -40,30 +40,307 @@
 int status_type;
 const gss_OID req_mech_type;
 OM_uint32 *message_context;
 gss_buffer_t status_string;
 {
-       OM_uint32 status;
        gss_OID mech_type = (gss_OID) req_mech_type;
        gss_mechanism mech;
 
-       gss_initialize();
+       /* check the input parameters */
+       if (!minor_status)
+               return (GSS_S_CALL_INACCESSIBLE_WRITE);
 
+       *minor_status = 0;
+
+       if (!message_context || status_string == NULL)
+               return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+       status_string->length = 0;
+       status_string->value = NULL;
+
+       /* we handle major status codes, and the mechs do the minor */
+       if (status_type == GSS_C_GSS_CODE)
+               return (displayMajor(status_value, message_context,
+                               status_string));
+
        /*
-        * select the approprate underlying mechanism routine and
+        * must be the minor status - let mechs do the work
+        * select the appropriate underlying mechanism routine and
         * call it.
         */
        mech = __gss_get_mechanism(mech_type);
 
+       if (mech && mech->gss_display_status) {
        if (mech_type == GSS_C_NULL_OID)
                mech_type = &mech->mech_type;
 
-       if (mech->gss_display_status)
-               status = mech->gss_display_status(mech->context, minor_status,
+               return (mech->gss_display_status(mech->context, minor_status,
                                status_value, status_type, mech_type,
                                message_context, status_string));
-       else
-               status = GSS_S_BAD_BINDINGS;
+       }
 
-       return (status);
+       if (!mech)
+               return (GSS_S_BAD_MECH);
+
+       return (GSS_S_UNAVAILABLE);
 } /* gss_display_status */
 
+
+/*
+ * function to map the major error codes
+ * it uses case statements so that the strings could be wrapped by gettext
+ * msgCtxt is interpreted as:
+ *     0 - first call
+ *     1 - routine error
+ *     >= 2 - the supplementary error code bit shifted by 1
+ */
+static OM_uint32
+displayMajor(status, msgCtxt, outStr)
+OM_uint32 status;
+OM_uint32 *msgCtxt;
+gss_buffer_t outStr;
+{
+       OM_uint32 oneVal, mask = 0x1, currErr;
+       char *errStr = NULL;
+       int i, haveErr = 0;
+
+       /* take care of the success value first */
+       if (status == GSS_S_COMPLETE)
+               errStr = dgettext(TEXT_DOMAIN,
+                               "The routine completed successfully");
+       else if (*msgCtxt == 0 && (oneVal = GSS_CALLING_ERROR(status))) {
+               switch (oneVal) {
+               case GSS_S_CALL_INACCESSIBLE_READ:
+                       errStr = dgettext(TEXT_DOMAIN,
+                                       "A required input parameter"
+                                       " could not be read");
+                       break;
+
+               case GSS_S_CALL_INACCESSIBLE_WRITE:
+                       errStr = dgettext(TEXT_DOMAIN,
+                                       "A required output parameter"
+                                       " could not be written");
+                       break;
+
+               case GSS_S_CALL_BAD_STRUCTURE:
+                       errStr = dgettext(TEXT_DOMAIN,
+                                       "A parameter was malformed");
+                       break;
+
+               default:
+                       errStr = dgettext(TEXT_DOMAIN,
+                                       "An invalid status code was supplied");
+                       break;
+               }
+
+               /* we now need to determine new value of msgCtxt */
+               if (GSS_ROUTINE_ERROR(status))
+                       *msgCtxt = 1;
+               else if ((oneVal = GSS_SUPPLEMENTARY_INFO(status)) != 0)
+                       *msgCtxt = (OM_uint32)(oneVal << 1);
+               else
+                       *msgCtxt = 0;
+
+       } else if ((*msgCtxt == 0 || *msgCtxt == 1) &&
+               (oneVal = GSS_ROUTINE_ERROR(status))) {
+               switch (oneVal) {
+               case GSS_S_BAD_MECH:
+                       errStr = dgettext(TEXT_DOMAIN,
+                                       "An unsupported mechanism"
+                                       " was requested");
+                       break;
+
+               case GSS_S_BAD_NAME:
+                       errStr = dgettext(TEXT_DOMAIN,
+                                       "An invalid name was supplied");
+                       break;
+
+               case GSS_S_BAD_NAMETYPE:
+                       errStr = dgettext(TEXT_DOMAIN,
+                                       "A supplied name was of an"
+                                       " unsupported type");
+                       break;
+
+               case GSS_S_BAD_BINDINGS:
+                       errStr = dgettext(TEXT_DOMAIN,
+                                       "Incorrect channel bindings"
+                                       " were supplied");
+                       break;
+
+               case GSS_S_BAD_SIG: /* same as GSS_S_BAD_MIC: */
+                       errStr = dgettext(TEXT_DOMAIN,
+                                       "A token had an invalid Message"
+                                       " Integrity Check (MIC)");
+                       break;
+
+               case GSS_S_NO_CRED:
+                       errStr = dgettext(TEXT_DOMAIN,
+                                       "No credentials were supplied, or the"
+                                       " credentials were unavailable or"
+                                       " inaccessible");
+                       break;
+
+               case GSS_S_NO_CONTEXT:
+                       errStr = dgettext(TEXT_DOMAIN,
+                                       "No context has been established");
+                       break;
+
+               case GSS_S_DEFECTIVE_TOKEN:
+                       errStr = dgettext(TEXT_DOMAIN,
+                                       "Invalid token was supplied");
+                       break;
+
+               case GSS_S_DEFECTIVE_CREDENTIAL:
+                       errStr = dgettext(TEXT_DOMAIN,
+                                       "Invalid credential was supplied");
+                       break;
+
+               case GSS_S_CREDENTIALS_EXPIRED:
+                       errStr = dgettext(TEXT_DOMAIN,
+                                       "The referenced credential has"
+                                       " expired");
+                       break;
+
+               case GSS_S_CONTEXT_EXPIRED:
+                       errStr = dgettext(TEXT_DOMAIN,
+                                       "The referenced context has expired");
+                       break;
+
+               case GSS_S_FAILURE:
+                       errStr = dgettext(TEXT_DOMAIN,
+                                       "Unspecified GSS failure.  Minor code"
+                                       " may provide more information");
+                       break;
+
+               case GSS_S_BAD_QOP:
+                       errStr = dgettext(TEXT_DOMAIN,
+                                       "The quality-of-protection (QOP) "
+                                       "requested could not be provided");
+                       break;
+
+               case GSS_S_UNAUTHORIZED:
+                       errStr = dgettext(TEXT_DOMAIN,
+                                       "The operation is forbidden by local"
+                                       " security policy");
+                       break;
+
+               case GSS_S_UNAVAILABLE:
+                       errStr = dgettext(TEXT_DOMAIN,
+                                       "The operation or option is not"
+                                       " available or unsupported");
+                       break;
+
+               case GSS_S_DUPLICATE_ELEMENT:
+                       errStr = dgettext(TEXT_DOMAIN,
+                                       "The requested credential element"
+                                       " already exists");
+                       break;
+
+               case GSS_S_NAME_NOT_MN:
+                       errStr = dgettext(TEXT_DOMAIN,
+                                       "The provided name was not mechanism"
+                                       " specific (MN)");
+                       break;
+
+               case GSS_S_BAD_STATUS:
+               default:
+                       errStr = dgettext(TEXT_DOMAIN,
+                                       "An invalid status code was supplied");
+               }
+
+               /* we must determine if the caller should call us again */
+               if ((oneVal = GSS_SUPPLEMENTARY_INFO(status)) != 0)
+                       *msgCtxt = (OM_uint32)(oneVal << 1);
+               else
+                       *msgCtxt = 0;
+
+       } else if ((*msgCtxt == 0 || *msgCtxt >= 2) &&
+               (oneVal = GSS_SUPPLEMENTARY_INFO(status))) {
+               /*
+                * if msgCtxt is not 0, then it should encode
+                * the supplementary error code we should be printing
+                */
+               if (*msgCtxt >= 2)
+                       oneVal = (OM_uint32) (*msgCtxt) >> 1;
+               else
+                       oneVal = GSS_SUPPLEMENTARY_INFO(status);
+
+               /* we display the errors LSB first */
+               for (i = 0; i < 16; i++) {
+                       if (oneVal & mask) {
+                               haveErr = 1;
+                               break;
+                       }
+                       mask <<= 1;
+               }
+
+               /* isolate the bit or if not found set to illegal value */
+               if (haveErr)
+                       currErr = oneVal & mask;
+               else
+                       currErr = 1 << 17; /* illegal value */
+
+               switch (currErr) {
+               case GSS_S_CONTINUE_NEEDED:
+                       errStr = dgettext(TEXT_DOMAIN,
+                                       "The routine must be called again to"
+                                       " complete its function");
+                       break;
+
+               case GSS_S_DUPLICATE_TOKEN:
+                       errStr = dgettext(TEXT_DOMAIN,
+                                       "The token was a duplicate of an"
+                                       " earlier token");
+                       break;
+
+               case GSS_S_OLD_TOKEN:
+                       errStr = dgettext(TEXT_DOMAIN,
+                                       "The token's validity period"
+                                       " has expired");
+                       break;
+
+               case GSS_S_UNSEQ_TOKEN:
+                       errStr = dgettext(TEXT_DOMAIN,
+                                       "A later token has already been"
+                                       " processed");
+                       break;
+
+               case GSS_S_GAP_TOKEN:
+                       errStr = dgettext(TEXT_DOMAIN,
+                                       "An expected per-message token was"
+                                       " not received");
+                       break;
+
+               default:
+                       errStr = dgettext(TEXT_DOMAIN,
+                                       "An invalid status code was supplied");
+               }
+
+               /*
+                * we must check if there is any other supplementary errors
+                * if found, then turn off current bit, and store next value
+                * in msgCtxt shifted by 1 bit
+                */
+               if (!haveErr)
+                       *msgCtxt = 0;
+               else if (GSS_SUPPLEMENTARY_INFO(oneVal) ^ mask)
+                       *msgCtxt = (OM_uint32)
+                               ((GSS_SUPPLEMENTARY_INFO(oneVal) ^ mask) << 1);
+               else
+                       *msgCtxt = 0;
+       }
+
+       if (errStr == NULL)
+               errStr = dgettext(TEXT_DOMAIN,
+                               "An invalid status code was supplied");
+
+       /* now copy the status code and return to caller */
+       outStr->length = strlen(errStr);
+       outStr->value = malloc((size_t)outStr->length+1);
+       if (outStr->value == NULL) {
+               outStr->length = 0;
+               return (GSS_S_FAILURE);
+       }
+
+       (void) strcpy((char *)outStr->value, errStr);
+       return (GSS_S_COMPLETE);
+} /* displayMajor */