17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * Copyright 1993 by OpenVision Technologies, Inc.
3*1da57d55SToomas Soome *
47c478bd9Sstevel@tonic-gate * Permission to use, copy, modify, distribute, and sell this software
57c478bd9Sstevel@tonic-gate * and its documentation for any purpose is hereby granted without fee,
67c478bd9Sstevel@tonic-gate * provided that the above copyright notice appears in all copies and
77c478bd9Sstevel@tonic-gate * that both that copyright notice and this permission notice appear in
87c478bd9Sstevel@tonic-gate * supporting documentation, and that the name of OpenVision not be used
97c478bd9Sstevel@tonic-gate * in advertising or publicity pertaining to distribution of the software
107c478bd9Sstevel@tonic-gate * without specific, written prior permission. OpenVision makes no
117c478bd9Sstevel@tonic-gate * representations about the suitability of this software for any
127c478bd9Sstevel@tonic-gate * purpose. It is provided "as is" without express or implied warranty.
13*1da57d55SToomas Soome *
147c478bd9Sstevel@tonic-gate * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
157c478bd9Sstevel@tonic-gate * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
167c478bd9Sstevel@tonic-gate * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
177c478bd9Sstevel@tonic-gate * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
187c478bd9Sstevel@tonic-gate * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
197c478bd9Sstevel@tonic-gate * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
207c478bd9Sstevel@tonic-gate * PERFORMANCE OF THIS SOFTWARE.
217c478bd9Sstevel@tonic-gate */
227c478bd9Sstevel@tonic-gate
23ab9b2e15Sgtb #include "gssapiP_generic.h"
247c478bd9Sstevel@tonic-gate #include <string.h>
257c478bd9Sstevel@tonic-gate #include <stdio.h>
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate /*
28ab9b2e15Sgtb * $Id: disp_major_status.c 13236 2001-05-08 17:10:18Z epeisach $
297c478bd9Sstevel@tonic-gate */
307c478bd9Sstevel@tonic-gate
31ab9b2e15Sgtb /* XXXX these are not part of the GSSAPI C bindings! (but should be) */
32ab9b2e15Sgtb /* SUNW15resync - MIT 1.5 has these in gssapi.h */
33ab9b2e15Sgtb
34ab9b2e15Sgtb #define GSS_CALLING_ERROR_FIELD(x) \
35ab9b2e15Sgtb (((x) >> GSS_C_CALLING_ERROR_OFFSET) & GSS_C_CALLING_ERROR_MASK)
36ab9b2e15Sgtb #define GSS_ROUTINE_ERROR_FIELD(x) \
37ab9b2e15Sgtb (((x) >> GSS_C_ROUTINE_ERROR_OFFSET) & GSS_C_ROUTINE_ERROR_MASK)
38ab9b2e15Sgtb #define GSS_SUPPLEMENTARY_INFO_FIELD(x) \
39ab9b2e15Sgtb (((x) >> GSS_C_SUPPLEMENTARY_OFFSET) & GSS_C_SUPPLEMENTARY_MASK)
407c478bd9Sstevel@tonic-gate
417c478bd9Sstevel@tonic-gate
427c478bd9Sstevel@tonic-gate /* This code has knowledge of the min and max errors of each type
437c478bd9Sstevel@tonic-gate within the gssapi major status */
447c478bd9Sstevel@tonic-gate
457c478bd9Sstevel@tonic-gate #define GSS_ERROR_STR(value, array, select, min, max, num) \
467c478bd9Sstevel@tonic-gate (((select(value) < (min)) || (select(value) > (max))) ? NULL : \
477c478bd9Sstevel@tonic-gate (array)[num(value)])
487c478bd9Sstevel@tonic-gate
497c478bd9Sstevel@tonic-gate /**/
507c478bd9Sstevel@tonic-gate
517c478bd9Sstevel@tonic-gate static const char * const calling_error_string[] = {
527c478bd9Sstevel@tonic-gate NULL,
537c478bd9Sstevel@tonic-gate "A required input parameter could not be read",
547c478bd9Sstevel@tonic-gate "A required input parameter could not be written",
557c478bd9Sstevel@tonic-gate "A parameter was malformed",
567c478bd9Sstevel@tonic-gate };
57*1da57d55SToomas Soome
587c478bd9Sstevel@tonic-gate static const char * const calling_error = "calling error";
597c478bd9Sstevel@tonic-gate
607c478bd9Sstevel@tonic-gate #define GSS_CALLING_ERROR_STR(x) \
617c478bd9Sstevel@tonic-gate GSS_ERROR_STR((x), calling_error_string, GSS_CALLING_ERROR, \
627c478bd9Sstevel@tonic-gate GSS_S_CALL_INACCESSIBLE_READ, GSS_S_CALL_BAD_STRUCTURE, \
637c478bd9Sstevel@tonic-gate GSS_CALLING_ERROR_FIELD)
647c478bd9Sstevel@tonic-gate
657c478bd9Sstevel@tonic-gate /**/
667c478bd9Sstevel@tonic-gate
677c478bd9Sstevel@tonic-gate static const char * const routine_error_string[] = {
687c478bd9Sstevel@tonic-gate NULL,
697c478bd9Sstevel@tonic-gate "An unsupported mechanism was requested",
707c478bd9Sstevel@tonic-gate "An invalid name was supplied",
717c478bd9Sstevel@tonic-gate "A supplied name was of an unsupported type",
727c478bd9Sstevel@tonic-gate "Incorrect channel bindings were supplied",
737c478bd9Sstevel@tonic-gate "An invalid status code was supplied",
747c478bd9Sstevel@tonic-gate "A token had an invalid signature",
757c478bd9Sstevel@tonic-gate "No credentials were supplied",
767c478bd9Sstevel@tonic-gate "No context has been established",
777c478bd9Sstevel@tonic-gate "A token was invalid",
787c478bd9Sstevel@tonic-gate "A credential was invalid",
797c478bd9Sstevel@tonic-gate "The referenced credentials have expired",
807c478bd9Sstevel@tonic-gate "The context has expired",
817c478bd9Sstevel@tonic-gate "Miscellaneous failure",
827c478bd9Sstevel@tonic-gate "The quality-of-protection requested could not be provided",
837c478bd9Sstevel@tonic-gate "The operation is forbidden by the local security policy",
847c478bd9Sstevel@tonic-gate "The operation or option is not available",
85*1da57d55SToomas Soome };
867c478bd9Sstevel@tonic-gate
877c478bd9Sstevel@tonic-gate static const char * const routine_error = "routine error";
887c478bd9Sstevel@tonic-gate
897c478bd9Sstevel@tonic-gate #define GSS_ROUTINE_ERROR_STR(x) \
907c478bd9Sstevel@tonic-gate GSS_ERROR_STR((x), routine_error_string, GSS_ROUTINE_ERROR, \
917c478bd9Sstevel@tonic-gate GSS_S_BAD_MECH, GSS_S_FAILURE, \
927c478bd9Sstevel@tonic-gate GSS_ROUTINE_ERROR_FIELD)
937c478bd9Sstevel@tonic-gate
947c478bd9Sstevel@tonic-gate /**/
957c478bd9Sstevel@tonic-gate
967c478bd9Sstevel@tonic-gate /* this becomes overly gross after about 4 strings */
977c478bd9Sstevel@tonic-gate
987c478bd9Sstevel@tonic-gate static const char * const sinfo_string[] = {
997c478bd9Sstevel@tonic-gate "The routine must be called again to complete its function",
1007c478bd9Sstevel@tonic-gate "The token was a duplicate of an earlier token",
1017c478bd9Sstevel@tonic-gate "The token's validity period has expired",
1027c478bd9Sstevel@tonic-gate "A later token has already been processed",
1037c478bd9Sstevel@tonic-gate };
1047c478bd9Sstevel@tonic-gate
1057c478bd9Sstevel@tonic-gate static const char * const sinfo_code = "supplementary info code";
1067c478bd9Sstevel@tonic-gate
1077c478bd9Sstevel@tonic-gate #define LSBGET(x) ((((x)^((x)-1))+1)>>1)
1087c478bd9Sstevel@tonic-gate #define LSBMASK(n) ((1<<(n))^((1<<(n))-1))
1097c478bd9Sstevel@tonic-gate
1107c478bd9Sstevel@tonic-gate #define GSS_SINFO_STR(x) \
1117c478bd9Sstevel@tonic-gate ((((1<<(x)) < GSS_S_CONTINUE_NEEDED) || ((1<<(x)) > GSS_S_UNSEQ_TOKEN)) ? \
1127c478bd9Sstevel@tonic-gate /**/NULL:sinfo_string[(x)])
1137c478bd9Sstevel@tonic-gate
1147c478bd9Sstevel@tonic-gate /**/
1157c478bd9Sstevel@tonic-gate
1167c478bd9Sstevel@tonic-gate static const char * const no_error = "No error";
1177c478bd9Sstevel@tonic-gate static const char * const unknown_error = "Unknown %s (field = %d)";
1187c478bd9Sstevel@tonic-gate
1197c478bd9Sstevel@tonic-gate /**/
1207c478bd9Sstevel@tonic-gate
121*1da57d55SToomas Soome static int
display_unknown(kind,value,buffer)122ab9b2e15Sgtb display_unknown(kind, value, buffer)
1237c478bd9Sstevel@tonic-gate const char *kind;
1247c478bd9Sstevel@tonic-gate OM_uint32 value;
1257c478bd9Sstevel@tonic-gate gss_buffer_t buffer;
1267c478bd9Sstevel@tonic-gate {
1277c478bd9Sstevel@tonic-gate char *str;
1287c478bd9Sstevel@tonic-gate
129ab9b2e15Sgtb if ((str =
130ab9b2e15Sgtb (char *) xmalloc(strlen(unknown_error)+strlen(kind)+7)) == NULL)
1317c478bd9Sstevel@tonic-gate return(0);
1327c478bd9Sstevel@tonic-gate
1337c478bd9Sstevel@tonic-gate sprintf(str, unknown_error, kind, value);
1347c478bd9Sstevel@tonic-gate
1357c478bd9Sstevel@tonic-gate buffer->length = strlen(str);
1367c478bd9Sstevel@tonic-gate buffer->value = str;
1377c478bd9Sstevel@tonic-gate
1387c478bd9Sstevel@tonic-gate return(1);
1397c478bd9Sstevel@tonic-gate }
1407c478bd9Sstevel@tonic-gate
1417c478bd9Sstevel@tonic-gate /* code should be set to the calling error field */
1427c478bd9Sstevel@tonic-gate
display_calling(minor_status,code,status_string)1437c478bd9Sstevel@tonic-gate static OM_uint32 display_calling(minor_status, code, status_string)
1447c478bd9Sstevel@tonic-gate OM_uint32 *minor_status;
1457c478bd9Sstevel@tonic-gate OM_uint32 code;
1467c478bd9Sstevel@tonic-gate gss_buffer_t status_string;
1477c478bd9Sstevel@tonic-gate {
1487c478bd9Sstevel@tonic-gate const char *str;
1497c478bd9Sstevel@tonic-gate
150ab9b2e15Sgtb if ((str = GSS_CALLING_ERROR_STR(code))) {
1517c478bd9Sstevel@tonic-gate if (! g_make_string_buffer(str, status_string)) {
1527c478bd9Sstevel@tonic-gate *minor_status = ENOMEM;
1537c478bd9Sstevel@tonic-gate return(GSS_S_FAILURE);
1547c478bd9Sstevel@tonic-gate }
1557c478bd9Sstevel@tonic-gate } else {
1567c478bd9Sstevel@tonic-gate if (! display_unknown(calling_error, GSS_CALLING_ERROR_FIELD(code),
1577c478bd9Sstevel@tonic-gate status_string)) {
1587c478bd9Sstevel@tonic-gate *minor_status = ENOMEM;
1597c478bd9Sstevel@tonic-gate return(GSS_S_FAILURE);
1607c478bd9Sstevel@tonic-gate }
1617c478bd9Sstevel@tonic-gate }
1627c478bd9Sstevel@tonic-gate *minor_status = 0;
1637c478bd9Sstevel@tonic-gate return(GSS_S_COMPLETE);
1647c478bd9Sstevel@tonic-gate }
1657c478bd9Sstevel@tonic-gate
1667c478bd9Sstevel@tonic-gate /* code should be set to the routine error field */
1677c478bd9Sstevel@tonic-gate
display_routine(minor_status,code,status_string)1687c478bd9Sstevel@tonic-gate static OM_uint32 display_routine(minor_status, code, status_string)
1697c478bd9Sstevel@tonic-gate OM_uint32 *minor_status;
1707c478bd9Sstevel@tonic-gate OM_uint32 code;
1717c478bd9Sstevel@tonic-gate gss_buffer_t status_string;
1727c478bd9Sstevel@tonic-gate {
1737c478bd9Sstevel@tonic-gate const char *str;
1747c478bd9Sstevel@tonic-gate
175ab9b2e15Sgtb if ((str = GSS_ROUTINE_ERROR_STR(code))) {
1767c478bd9Sstevel@tonic-gate if (! g_make_string_buffer(str, status_string)) {
1777c478bd9Sstevel@tonic-gate *minor_status = ENOMEM;
1787c478bd9Sstevel@tonic-gate return(GSS_S_FAILURE);
1797c478bd9Sstevel@tonic-gate }
1807c478bd9Sstevel@tonic-gate } else {
1817c478bd9Sstevel@tonic-gate if (! display_unknown(routine_error, GSS_ROUTINE_ERROR_FIELD(code),
1827c478bd9Sstevel@tonic-gate status_string)) {
1837c478bd9Sstevel@tonic-gate *minor_status = ENOMEM;
1847c478bd9Sstevel@tonic-gate return(GSS_S_FAILURE);
1857c478bd9Sstevel@tonic-gate }
1867c478bd9Sstevel@tonic-gate }
1877c478bd9Sstevel@tonic-gate *minor_status = 0;
1887c478bd9Sstevel@tonic-gate return(GSS_S_COMPLETE);
1897c478bd9Sstevel@tonic-gate }
1907c478bd9Sstevel@tonic-gate
1917c478bd9Sstevel@tonic-gate /* code should be set to the bit offset (log_2) of a supplementary info bit */
1927c478bd9Sstevel@tonic-gate
display_bit(minor_status,code,status_string)1937c478bd9Sstevel@tonic-gate static OM_uint32 display_bit(minor_status, code, status_string)
1947c478bd9Sstevel@tonic-gate OM_uint32 *minor_status;
1957c478bd9Sstevel@tonic-gate OM_uint32 code;
1967c478bd9Sstevel@tonic-gate gss_buffer_t status_string;
1977c478bd9Sstevel@tonic-gate {
1987c478bd9Sstevel@tonic-gate const char *str;
1997c478bd9Sstevel@tonic-gate
200ab9b2e15Sgtb if ((str = GSS_SINFO_STR(code))) {
2017c478bd9Sstevel@tonic-gate if (! g_make_string_buffer(str, status_string)) {
2027c478bd9Sstevel@tonic-gate *minor_status = ENOMEM;
2037c478bd9Sstevel@tonic-gate return(GSS_S_FAILURE);
2047c478bd9Sstevel@tonic-gate }
2057c478bd9Sstevel@tonic-gate } else {
2067c478bd9Sstevel@tonic-gate if (! display_unknown(sinfo_code, 1<<code, status_string)) {
2077c478bd9Sstevel@tonic-gate *minor_status = ENOMEM;
2087c478bd9Sstevel@tonic-gate return(GSS_S_FAILURE);
2097c478bd9Sstevel@tonic-gate }
2107c478bd9Sstevel@tonic-gate }
2117c478bd9Sstevel@tonic-gate *minor_status = 0;
2127c478bd9Sstevel@tonic-gate return(GSS_S_COMPLETE);
2137c478bd9Sstevel@tonic-gate }
2147c478bd9Sstevel@tonic-gate
2157c478bd9Sstevel@tonic-gate /**/
2167c478bd9Sstevel@tonic-gate
2177c478bd9Sstevel@tonic-gate /* return error messages, for routine errors, call error, and status,
2187c478bd9Sstevel@tonic-gate in that order.
2197c478bd9Sstevel@tonic-gate message_context == 0 : print the routine error
2207c478bd9Sstevel@tonic-gate message_context == 1 : print the calling error
2217c478bd9Sstevel@tonic-gate message_context > 2 : print supplementary info bit (message_context-2)
2227c478bd9Sstevel@tonic-gate */
2237c478bd9Sstevel@tonic-gate
g_display_major_status(minor_status,status_value,message_context,status_string)224*1da57d55SToomas Soome OM_uint32 g_display_major_status(minor_status, status_value,
2257c478bd9Sstevel@tonic-gate message_context, status_string)
2267c478bd9Sstevel@tonic-gate OM_uint32 *minor_status;
2277c478bd9Sstevel@tonic-gate OM_uint32 status_value;
2287c478bd9Sstevel@tonic-gate OM_uint32 *message_context;
2297c478bd9Sstevel@tonic-gate gss_buffer_t status_string;
2307c478bd9Sstevel@tonic-gate {
2317c478bd9Sstevel@tonic-gate OM_uint32 ret, tmp;
2327c478bd9Sstevel@tonic-gate int bit;
2337c478bd9Sstevel@tonic-gate
2347c478bd9Sstevel@tonic-gate /*** deal with no error at all specially */
2357c478bd9Sstevel@tonic-gate
2367c478bd9Sstevel@tonic-gate if (status_value == 0) {
2377c478bd9Sstevel@tonic-gate if (! g_make_string_buffer(no_error, status_string)) {
2387c478bd9Sstevel@tonic-gate *minor_status = ENOMEM;
2397c478bd9Sstevel@tonic-gate return(GSS_S_FAILURE);
2407c478bd9Sstevel@tonic-gate }
2417c478bd9Sstevel@tonic-gate *message_context = 0;
2427c478bd9Sstevel@tonic-gate *minor_status = 0;
2437c478bd9Sstevel@tonic-gate return(GSS_S_COMPLETE);
2447c478bd9Sstevel@tonic-gate }
2457c478bd9Sstevel@tonic-gate
2467c478bd9Sstevel@tonic-gate /*** do routine error */
2477c478bd9Sstevel@tonic-gate
2487c478bd9Sstevel@tonic-gate if (*message_context == 0) {
249ab9b2e15Sgtb if ((tmp = GSS_ROUTINE_ERROR(status_value))) {
2507c478bd9Sstevel@tonic-gate status_value -= tmp;
2517c478bd9Sstevel@tonic-gate if ((ret = display_routine(minor_status, tmp, status_string)))
2527c478bd9Sstevel@tonic-gate return(ret);
2537c478bd9Sstevel@tonic-gate *minor_status = 0;
2547c478bd9Sstevel@tonic-gate if (status_value) {
2557c478bd9Sstevel@tonic-gate (*message_context)++;
2567c478bd9Sstevel@tonic-gate return(GSS_S_COMPLETE);
2577c478bd9Sstevel@tonic-gate } else {
2587c478bd9Sstevel@tonic-gate *message_context = 0;
2597c478bd9Sstevel@tonic-gate return(GSS_S_COMPLETE);
2607c478bd9Sstevel@tonic-gate }
2617c478bd9Sstevel@tonic-gate } else {
2627c478bd9Sstevel@tonic-gate (*message_context)++;
2637c478bd9Sstevel@tonic-gate }
2647c478bd9Sstevel@tonic-gate } else {
2657c478bd9Sstevel@tonic-gate status_value -= GSS_ROUTINE_ERROR(status_value);
2667c478bd9Sstevel@tonic-gate }
2677c478bd9Sstevel@tonic-gate
2687c478bd9Sstevel@tonic-gate /*** do calling error */
2697c478bd9Sstevel@tonic-gate
2707c478bd9Sstevel@tonic-gate if (*message_context == 1) {
271ab9b2e15Sgtb if ((tmp = GSS_CALLING_ERROR(status_value))) {
2727c478bd9Sstevel@tonic-gate status_value -= tmp;
2737c478bd9Sstevel@tonic-gate if ((ret = display_calling(minor_status, tmp, status_string)))
2747c478bd9Sstevel@tonic-gate return(ret);
2757c478bd9Sstevel@tonic-gate *minor_status = 0;
2767c478bd9Sstevel@tonic-gate if (status_value) {
2777c478bd9Sstevel@tonic-gate (*message_context)++;
2787c478bd9Sstevel@tonic-gate return(GSS_S_COMPLETE);
2797c478bd9Sstevel@tonic-gate } else {
2807c478bd9Sstevel@tonic-gate *message_context = 0;
2817c478bd9Sstevel@tonic-gate return(GSS_S_COMPLETE);
2827c478bd9Sstevel@tonic-gate }
2837c478bd9Sstevel@tonic-gate } else {
2847c478bd9Sstevel@tonic-gate (*message_context)++;
2857c478bd9Sstevel@tonic-gate }
2867c478bd9Sstevel@tonic-gate } else {
2877c478bd9Sstevel@tonic-gate status_value -= GSS_CALLING_ERROR(status_value);
2887c478bd9Sstevel@tonic-gate }
2897c478bd9Sstevel@tonic-gate
2907c478bd9Sstevel@tonic-gate /*** do sinfo bits (*message_context == 2 + number of bits done) */
2917c478bd9Sstevel@tonic-gate
292ab9b2e15Sgtb tmp = GSS_SUPPLEMENTARY_INFO_FIELD(status_value);
2937c478bd9Sstevel@tonic-gate /* mask off the bits which have been done */
2947c478bd9Sstevel@tonic-gate if (*message_context > 2) {
2957c478bd9Sstevel@tonic-gate tmp &= ~LSBMASK(*message_context-3);
2967c478bd9Sstevel@tonic-gate status_value &= ~LSBMASK(*message_context-3);
2977c478bd9Sstevel@tonic-gate }
2987c478bd9Sstevel@tonic-gate
2997c478bd9Sstevel@tonic-gate if (!tmp) {
3007c478bd9Sstevel@tonic-gate /* bogon input - there should be something left */
3017c478bd9Sstevel@tonic-gate *minor_status = (OM_uint32) G_BAD_MSG_CTX;
3027c478bd9Sstevel@tonic-gate return(GSS_S_FAILURE);
3037c478bd9Sstevel@tonic-gate }
3047c478bd9Sstevel@tonic-gate
3057c478bd9Sstevel@tonic-gate /* compute the bit offset */
3067c478bd9Sstevel@tonic-gate /*SUPPRESS 570*/
3077c478bd9Sstevel@tonic-gate for (bit=0; (((OM_uint32) 1)<<bit) != LSBGET(tmp); bit++) ;
3087c478bd9Sstevel@tonic-gate
3097c478bd9Sstevel@tonic-gate /* print it */
3107c478bd9Sstevel@tonic-gate if ((ret = display_bit(minor_status, bit, status_string)))
3117c478bd9Sstevel@tonic-gate return(ret);
3127c478bd9Sstevel@tonic-gate
3137c478bd9Sstevel@tonic-gate /* compute the new status_value/message_context */
3147c478bd9Sstevel@tonic-gate status_value -= ((OM_uint32) 1)<<bit;
3157c478bd9Sstevel@tonic-gate
3167c478bd9Sstevel@tonic-gate if (status_value) {
3177c478bd9Sstevel@tonic-gate *message_context = bit+3;
3187c478bd9Sstevel@tonic-gate return(GSS_S_COMPLETE);
3197c478bd9Sstevel@tonic-gate } else {
3207c478bd9Sstevel@tonic-gate *message_context = 0;
3217c478bd9Sstevel@tonic-gate return(GSS_S_COMPLETE);
3227c478bd9Sstevel@tonic-gate }
3237c478bd9Sstevel@tonic-gate }
324