Home | History | Annotate | Download | only in libgss
      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