Path: blob/main/crypto/krb5/src/lib/gssapi/mechglue/g_dsp_status.c
39586 views
/* #pragma ident "@(#)g_dsp_status.c 1.17 04/02/23 SMI" */12/*3* Copyright 1996 by Sun Microsystems, Inc.4*5* Permission to use, copy, modify, distribute, and sell this software6* and its documentation for any purpose is hereby granted without fee,7* provided that the above copyright notice appears in all copies and8* that both that copyright notice and this permission notice appear in9* supporting documentation, and that the name of Sun Microsystems not be used10* in advertising or publicity pertaining to distribution of the software11* without specific, written prior permission. Sun Microsystems makes no12* representations about the suitability of this software for any13* purpose. It is provided "as is" without express or implied warranty.14*15* SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,16* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO17* EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR18* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF19* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR20* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR21* PERFORMANCE OF THIS SOFTWARE.22*/2324/*25* glue routine gss_display_status26*27*/2829#include "mglueP.h"30#include <stdio.h>31#include <stdlib.h>32#include <string.h>3334/* local function */35static OM_uint32 displayMajor(OM_uint32, OM_uint32 *, gss_buffer_t);3637OM_uint32 KRB5_CALLCONV38gss_display_status(OM_uint32 *minor_status, OM_uint32 status_value,39int status_type, gss_OID req_mech_type,40OM_uint32 *message_context, gss_buffer_t status_string)41{42gss_OID mech_type = (gss_OID) req_mech_type;43gss_mechanism mech;44gss_OID_desc m_oid = { 0, 0 };4546if (minor_status != NULL)47*minor_status = 0;4849if (status_string != GSS_C_NO_BUFFER) {50status_string->length = 0;51status_string->value = NULL;52}5354if (minor_status == NULL ||55message_context == NULL ||56status_string == GSS_C_NO_BUFFER)5758return (GSS_S_CALL_INACCESSIBLE_WRITE);5960/* we handle major status codes, and the mechs do the minor */61if (status_type == GSS_C_GSS_CODE)62return (displayMajor(status_value, message_context,63status_string));6465/*66* must be the minor status - let mechs do the work67* select the appropriate underlying mechanism routine and68* call it.69*/7071/* In this version, we only handle status codes that have been72mapped to a flat numbering space. Look up the value we got73passed. If it's not found, complain. */74if (status_value == 0) {75status_string->value = gssalloc_strdup("Unknown error");76if (status_string->value == NULL) {77*minor_status = ENOMEM;78map_errcode(minor_status);79return GSS_S_FAILURE;80}81status_string->length = strlen(status_string->value);82*message_context = 0;83*minor_status = 0;84return GSS_S_COMPLETE;85}86{87int err;88OM_uint32 m_status = 0, status;8990err = gssint_mecherrmap_get(status_value, &m_oid, &m_status);91if (err) {92*minor_status = err;93map_errcode(minor_status);94return GSS_S_BAD_STATUS;95}96if (m_oid.length == 0) {97/* Magic flag for com_err values. */98status = g_display_com_err_status(minor_status, m_status, status_string);99if (status != GSS_S_COMPLETE)100map_errcode(minor_status);101return status;102}103mech_type = &m_oid;104status_value = m_status;105}106107mech = gssint_get_mechanism (mech_type);108109if (mech && mech->gss_display_status) {110OM_uint32 r;111112r = mech->gss_display_status(minor_status,113status_value, status_type, mech_type,114message_context, status_string);115/* How's this for weird? If we get an error returning the116mechanism-specific error code, we save away the117mechanism-specific error code describing the error. */118if (r != GSS_S_COMPLETE)119map_error(minor_status, mech);120return r;121}122123if (!mech)124return (GSS_S_BAD_MECH);125126return (GSS_S_UNAVAILABLE);127}128129/*130* function to map the major error codes131* it uses case statements so that the strings could be wrapped by gettext132* msgCtxt is interpreted as:133* 0 - first call134* 1 - routine error135* >= 2 - the supplementary error code bit shifted by 1136*/137static OM_uint32138displayMajor(OM_uint32 status, OM_uint32 *msgCtxt, gss_buffer_t outStr)139{140OM_uint32 oneVal, mask = 0x1, currErr;141char *errStr = NULL;142int i, haveErr = 0;143144/* take care of the success value first */145if (status == GSS_S_COMPLETE)146errStr = _("The routine completed successfully");147else if (*msgCtxt == 0 && (oneVal = GSS_CALLING_ERROR(status))) {148switch (oneVal) {149case GSS_S_CALL_INACCESSIBLE_READ:150errStr = _("A required input parameter could not be "151"read");152break;153154case GSS_S_CALL_INACCESSIBLE_WRITE:155errStr = _("A required output parameter could not be "156"written");157break;158159case GSS_S_CALL_BAD_STRUCTURE:160errStr = _("A parameter was malformed");161break;162163default:164errStr = _("An invalid status code was supplied");165break;166}167168/* we now need to determine new value of msgCtxt */169if (GSS_ROUTINE_ERROR(status))170*msgCtxt = 1;171else if ((oneVal = GSS_SUPPLEMENTARY_INFO(status)) != 0)172*msgCtxt = (OM_uint32)(oneVal << 1);173else174*msgCtxt = 0;175176} else if ((*msgCtxt == 0 || *msgCtxt == 1) &&177(oneVal = GSS_ROUTINE_ERROR(status))) {178switch (oneVal) {179case GSS_S_BAD_MECH:180errStr = _("An unsupported mechanism was requested");181break;182183case GSS_S_BAD_NAME:184errStr = _("An invalid name was supplied");185break;186187case GSS_S_BAD_NAMETYPE:188errStr = _("A supplied name was of an unsupported "189"type");190break;191192case GSS_S_BAD_BINDINGS:193errStr = _("Incorrect channel bindings were supplied");194break;195196case GSS_S_BAD_SIG: /* same as GSS_S_BAD_MIC: */197errStr = _("A token had an invalid Message Integrity "198"Check (MIC)");199break;200201case GSS_S_NO_CRED:202errStr = _("No credentials were supplied, or the "203"credentials were unavailable or "204"inaccessible");205break;206207case GSS_S_NO_CONTEXT:208errStr = _("No context has been established");209break;210211case GSS_S_DEFECTIVE_TOKEN:212errStr = _("Invalid token was supplied");213break;214215case GSS_S_DEFECTIVE_CREDENTIAL:216errStr = _("Invalid credential was supplied");217break;218219case GSS_S_CREDENTIALS_EXPIRED:220errStr = _("The referenced credential has expired");221break;222223case GSS_S_CONTEXT_EXPIRED:224errStr = _("The referenced context has expired");225break;226227case GSS_S_FAILURE:228errStr = _("Unspecified GSS failure. Minor code "229"may provide more information");230break;231232case GSS_S_BAD_QOP:233errStr = _("The quality-of-protection (QOP) "234"requested could not be provided");235break;236237case GSS_S_UNAUTHORIZED:238errStr = _("The operation is forbidden by local "239"security policy");240break;241242case GSS_S_UNAVAILABLE:243errStr = _("The operation or option is not "244"available or unsupported");245break;246247case GSS_S_DUPLICATE_ELEMENT:248errStr = _("The requested credential element "249"already exists");250break;251252case GSS_S_NAME_NOT_MN:253errStr = _("The provided name was not mechanism "254"specific (MN)");255break;256257case GSS_S_BAD_STATUS:258default:259errStr = _("An invalid status code was supplied");260}261262/* we must determine if the caller should call us again */263if ((oneVal = GSS_SUPPLEMENTARY_INFO(status)) != 0)264*msgCtxt = (OM_uint32)(oneVal << 1);265else266*msgCtxt = 0;267268} else if ((*msgCtxt == 0 || *msgCtxt >= 2) &&269(oneVal = GSS_SUPPLEMENTARY_INFO(status))) {270/*271* if msgCtxt is not 0, then it should encode272* the supplementary error code we should be printing273*/274if (*msgCtxt >= 2)275oneVal = (OM_uint32) (*msgCtxt) >> 1;276else277oneVal = GSS_SUPPLEMENTARY_INFO(status);278279/* we display the errors LSB first */280for (i = 0; i < 16; i++) {281if (oneVal & mask) {282haveErr = 1;283break;284}285mask <<= 1;286}287288/* isolate the bit or if not found set to illegal value */289if (haveErr)290currErr = oneVal & mask;291else292currErr = 1 << 17; /* illegal value */293294switch (currErr) {295case GSS_S_CONTINUE_NEEDED:296errStr = _("The routine must be called again to "297"complete its function");298break;299300case GSS_S_DUPLICATE_TOKEN:301errStr = _("The token was a duplicate of an earlier "302"token");303break;304305case GSS_S_OLD_TOKEN:306errStr = _("The token's validity period has expired");307break;308309case GSS_S_UNSEQ_TOKEN:310errStr = _("A later token has already been processed");311break;312313case GSS_S_GAP_TOKEN:314errStr = _("An expected per-message token was not "315"received");316break;317318default:319errStr = _("An invalid status code was supplied");320}321322/*323* we must check if there is any other supplementary errors324* if found, then turn off current bit, and store next value325* in msgCtxt shifted by 1 bit326*/327if (!haveErr)328*msgCtxt = 0;329else if (GSS_SUPPLEMENTARY_INFO(oneVal) ^ mask)330*msgCtxt = (OM_uint32)331((GSS_SUPPLEMENTARY_INFO(oneVal) ^ mask) << 1);332else333*msgCtxt = 0;334}335336if (errStr == NULL)337errStr = "An invalid status code was supplied";338339/* now copy the status code and return to caller */340outStr->length = strlen(errStr);341outStr->value = gssalloc_strdup(errStr);342if (outStr->value == NULL) {343outStr->length = 0;344return (GSS_S_FAILURE);345}346347return (GSS_S_COMPLETE);348} /* displayMajor */349350351