1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
3 * Copyright 1993 by OpenVision Technologies, Inc.
5 * Permission to use, copy, modify, distribute, and sell this software
6 * and its documentation for any purpose is hereby granted without fee,
7 * provided that the above copyright notice appears in all copies and
8 * that both that copyright notice and this permission notice appear in
9 * supporting documentation, and that the name of OpenVision not be used
10 * in advertising or publicity pertaining to distribution of the software
11 * without specific, written prior permission. OpenVision makes no
12 * representations about the suitability of this software for any
13 * purpose. It is provided "as is" without express or implied warranty.
15 * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17 * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
19 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
20 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21 * PERFORMANCE OF THIS SOFTWARE.
24 #include "gssapiP_generic.h"
32 /* This code has knowledge of the min and max errors of each type
33 within the gssapi major status */
35 #define GSS_ERROR_STR(value, array, select, min, max, num) \
36 (((select(value) < (min)) || (select(value) > (max))) ? NULL : \
37 _((array)[num(value)]))
41 static const char * const calling_error_string[] = {
43 N_("A required input parameter could not be read"),
44 N_("A required input parameter could not be written"),
45 N_("A parameter was malformed"),
48 static const char * const calling_error = N_("calling error");
50 #define GSS_CALLING_ERROR_STR(x) \
51 GSS_ERROR_STR((x), calling_error_string, GSS_CALLING_ERROR, \
52 GSS_S_CALL_INACCESSIBLE_READ, GSS_S_CALL_BAD_STRUCTURE, \
53 GSS_CALLING_ERROR_FIELD)
57 static const char * const routine_error_string[] = {
59 N_("An unsupported mechanism was requested"),
60 N_("An invalid name was supplied"),
61 N_("A supplied name was of an unsupported type"),
62 N_("Incorrect channel bindings were supplied"),
63 N_("An invalid status code was supplied"),
64 N_("A token had an invalid signature"),
65 N_("No credentials were supplied"),
66 N_("No context has been established"),
67 N_("A token was invalid"),
68 N_("A credential was invalid"),
69 N_("The referenced credentials have expired"),
70 N_("The context has expired"),
71 N_("Miscellaneous failure"),
72 N_("The quality-of-protection requested could not be provided"),
73 N_("The operation is forbidden by the local security policy"),
74 N_("The operation or option is not available"),
77 static const char * const routine_error = N_("routine error");
79 #define GSS_ROUTINE_ERROR_STR(x) \
80 GSS_ERROR_STR((x), routine_error_string, GSS_ROUTINE_ERROR, \
81 GSS_S_BAD_MECH, GSS_S_FAILURE, \
82 GSS_ROUTINE_ERROR_FIELD)
86 /* this becomes overly gross after about 4 strings */
88 static const char * const sinfo_string[] = {
89 N_("The routine must be called again to complete its function"),
90 N_("The token was a duplicate of an earlier token"),
91 N_("The token's validity period has expired"),
92 N_("A later token has already been processed"),
95 static const char * const sinfo_code = N_("supplementary info code");
97 #define LSBGET(x) ((((x)^((x)-1))+1)>>1)
98 #define LSBMASK(n) ((1<<(n))^((1<<(n))-1))
100 #define GSS_SINFO_STR(x) \
101 ((((1<<(x)) < GSS_S_CONTINUE_NEEDED) || ((1<<(x)) > GSS_S_UNSEQ_TOKEN)) ? \
102 /**/NULL:sinfo_string[(x)])
106 static const char * const no_error = N_("No error");
107 static const char * const unknown_error = N_("Unknown %s (field = %d)");
112 display_unknown(const char *kind, OM_uint32 value, gss_buffer_t buffer)
116 if (asprintf(&str, _(unknown_error), kind, value) < 0)
119 buffer->length = strlen(str);
125 /* code should be set to the calling error field */
128 display_calling(OM_uint32 *minor_status, OM_uint32 code,
129 gss_buffer_t status_string)
133 if ((str = GSS_CALLING_ERROR_STR(code))) {
134 if (! g_make_string_buffer(str, status_string)) {
135 *minor_status = ENOMEM;
136 return(GSS_S_FAILURE);
139 if (! display_unknown(_(calling_error), GSS_CALLING_ERROR_FIELD(code),
141 *minor_status = ENOMEM;
142 return(GSS_S_FAILURE);
146 return(GSS_S_COMPLETE);
149 /* code should be set to the routine error field */
152 display_routine(OM_uint32 *minor_status, OM_uint32 code,
153 gss_buffer_t status_string)
157 if ((str = GSS_ROUTINE_ERROR_STR(code))) {
158 if (! g_make_string_buffer(str, status_string)) {
159 *minor_status = ENOMEM;
160 return(GSS_S_FAILURE);
163 if (! display_unknown(_(routine_error), GSS_ROUTINE_ERROR_FIELD(code),
165 *minor_status = ENOMEM;
166 return(GSS_S_FAILURE);
170 return(GSS_S_COMPLETE);
173 /* code should be set to the bit offset (log_2) of a supplementary info bit */
176 display_bit(OM_uint32 *minor_status, OM_uint32 code,
177 gss_buffer_t status_string)
181 if ((str = GSS_SINFO_STR(code))) {
182 if (! g_make_string_buffer(str, status_string)) {
183 *minor_status = ENOMEM;
184 return(GSS_S_FAILURE);
187 if (! display_unknown(_(sinfo_code), 1<<code, status_string)) {
188 *minor_status = ENOMEM;
189 return(GSS_S_FAILURE);
193 return(GSS_S_COMPLETE);
198 /* return error messages, for routine errors, call error, and status,
200 message_context == 0 : print the routine error
201 message_context == 1 : print the calling error
202 message_context > 2 : print supplementary info bit (message_context-2)
206 g_display_major_status(OM_uint32 *minor_status, OM_uint32 status_value,
207 OM_uint32 *message_context, gss_buffer_t status_string)
212 /*** deal with no error at all specially */
214 if (status_value == 0) {
215 if (! g_make_string_buffer(no_error, status_string)) {
216 *minor_status = ENOMEM;
217 return(GSS_S_FAILURE);
219 *message_context = 0;
221 return(GSS_S_COMPLETE);
224 /*** do routine error */
226 if (*message_context == 0) {
227 if ((tmp = GSS_ROUTINE_ERROR(status_value))) {
229 if ((ret = display_routine(minor_status, tmp, status_string)))
233 (*message_context)++;
234 return(GSS_S_COMPLETE);
236 *message_context = 0;
237 return(GSS_S_COMPLETE);
240 (*message_context)++;
243 status_value -= GSS_ROUTINE_ERROR(status_value);
246 /*** do calling error */
248 if (*message_context == 1) {
249 if ((tmp = GSS_CALLING_ERROR(status_value))) {
251 if ((ret = display_calling(minor_status, tmp, status_string)))
255 (*message_context)++;
256 return(GSS_S_COMPLETE);
258 *message_context = 0;
259 return(GSS_S_COMPLETE);
262 (*message_context)++;
265 status_value -= GSS_CALLING_ERROR(status_value);
268 /*** do sinfo bits (*message_context == 2 + number of bits done) */
270 tmp = GSS_SUPPLEMENTARY_INFO_FIELD(status_value);
271 /* mask off the bits which have been done */
272 if (*message_context > 2) {
273 tmp &= ~LSBMASK(*message_context-3);
274 status_value &= ~LSBMASK(*message_context-3);
278 /* bogon input - there should be something left */
279 *minor_status = (OM_uint32) G_BAD_MSG_CTX;
280 return(GSS_S_FAILURE);
283 /* compute the bit offset */
285 for (bit=0; (((OM_uint32) 1)<<bit) != LSBGET(tmp); bit++) ;
288 if ((ret = display_bit(minor_status, bit, status_string)))
291 /* compute the new status_value/message_context */
292 status_value -= ((OM_uint32) 1)<<bit;
295 *message_context = bit+3;
296 return(GSS_S_COMPLETE);
298 *message_context = 0;
299 return(GSS_S_COMPLETE);