4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
26 * glue routine gss_display_status
30 #include <mechglueP.h>
31 #include "gssapiP_generic.h"
41 #error TEXT_DOMAIN not defined
45 static OM_uint32
displayMajor(OM_uint32
, OM_uint32
*, gss_buffer_t
);
49 gss_display_status(minor_status
,
56 OM_uint32
*minor_status
;
57 OM_uint32 status_value
;
59 const gss_OID req_mech_type
;
60 OM_uint32
*message_context
;
61 gss_buffer_t status_string
;
63 gss_OID mech_type
= (gss_OID
) req_mech_type
;
65 gss_OID_desc m_oid
= { 0, 0 };
67 if (minor_status
!= NULL
)
70 if (status_string
!= GSS_C_NO_BUFFER
) {
71 status_string
->length
= 0;
72 status_string
->value
= NULL
;
75 if (minor_status
== NULL
||
76 message_context
== NULL
||
77 status_string
== GSS_C_NO_BUFFER
)
78 return (GSS_S_CALL_INACCESSIBLE_WRITE
);
80 /* we handle major status codes, and the mechs do the minor */
81 if (status_type
== GSS_C_GSS_CODE
)
82 return (displayMajor(status_value
, message_context
,
86 * must be the minor status - let mechs do the work
87 * select the appropriate underlying mechanism routine and
91 /* In this version, we only handle status codes that have been
92 mapped to a flat numbering space. Look up the value we got
93 passed. If it's not found, complain. */
94 if (status_value
== 0) {
95 status_string
->value
= strdup("Unknown error");
96 if (status_string
->value
== NULL
) {
97 *minor_status
= ENOMEM
;
98 map_errcode(minor_status
);
101 status_string
->length
= strlen(status_string
->value
);
102 *message_context
= 0;
104 return GSS_S_COMPLETE
;
108 OM_uint32 m_status
= 0, status
;
110 err
= gssint_mecherrmap_get(status_value
, &m_oid
, &m_status
);
113 map_errcode(minor_status
);
114 return GSS_S_BAD_STATUS
;
117 if (m_oid
.length
== 0) {
118 /* Magic flag for com_err values. */
119 status
= gssint_g_display_com_err_status(minor_status
,
122 if (status
!= GSS_S_COMPLETE
)
123 map_errcode(minor_status
);
127 status_value
= m_status
;
130 mech
= __gss_get_mechanism(mech_type
);
132 if (mech
&& mech
->gss_display_status
) {
135 if (mech_type
== GSS_C_NULL_OID
)
136 mech_type
= &mech
->mech_type
;
138 r
= mech
->gss_display_status(mech
->context
, minor_status
,
139 status_value
, status_type
, mech_type
,
140 message_context
, status_string
);
141 /* How's this for weird? If we get an error returning the
142 mechanism-specific error code, we save away the
143 mechanism-specific error code describing the error. */
144 if (r
!= GSS_S_COMPLETE
)
145 map_error(minor_status
, mech
);
150 return (GSS_S_BAD_MECH
);
152 return (GSS_S_UNAVAILABLE
);
153 } /* gss_display_status */
157 * function to map the major error codes
158 * it uses case statements so that the strings could be wrapped by gettext
159 * msgCtxt is interpreted as:
162 * >= 2 - the supplementary error code bit shifted by 1
165 displayMajor(status
, msgCtxt
, outStr
)
170 OM_uint32 oneVal
, mask
= 0x1, currErr
;
174 /* take care of the success value first */
175 if (status
== GSS_S_COMPLETE
)
176 errStr
= dgettext(TEXT_DOMAIN
,
177 "The routine completed successfully");
178 else if (*msgCtxt
== 0 && (oneVal
= GSS_CALLING_ERROR(status
))) {
180 case GSS_S_CALL_INACCESSIBLE_READ
:
181 errStr
= dgettext(TEXT_DOMAIN
,
182 "A required input parameter"
183 " could not be read");
186 case GSS_S_CALL_INACCESSIBLE_WRITE
:
187 errStr
= dgettext(TEXT_DOMAIN
,
188 "A required output parameter"
189 " could not be written");
192 case GSS_S_CALL_BAD_STRUCTURE
:
193 errStr
= dgettext(TEXT_DOMAIN
,
194 "A parameter was malformed");
198 errStr
= dgettext(TEXT_DOMAIN
,
199 "An invalid status code was supplied");
203 /* we now need to determine new value of msgCtxt */
204 if (GSS_ROUTINE_ERROR(status
))
206 else if ((oneVal
= GSS_SUPPLEMENTARY_INFO(status
)) != 0)
207 *msgCtxt
= (OM_uint32
)(oneVal
<< 1);
211 } else if ((*msgCtxt
== 0 || *msgCtxt
== 1) &&
212 (oneVal
= GSS_ROUTINE_ERROR(status
))) {
215 errStr
= dgettext(TEXT_DOMAIN
,
216 "An unsupported mechanism"
221 errStr
= dgettext(TEXT_DOMAIN
,
222 "An invalid name was supplied");
225 case GSS_S_BAD_NAMETYPE
:
226 errStr
= dgettext(TEXT_DOMAIN
,
227 "A supplied name was of an"
228 " unsupported type");
231 case GSS_S_BAD_BINDINGS
:
232 errStr
= dgettext(TEXT_DOMAIN
,
233 "Incorrect channel bindings"
237 case GSS_S_BAD_SIG
: /* same as GSS_S_BAD_MIC: */
238 errStr
= dgettext(TEXT_DOMAIN
,
239 "A token had an invalid Message"
240 " Integrity Check (MIC)");
244 errStr
= dgettext(TEXT_DOMAIN
,
245 "No credentials were supplied, or the"
246 " credentials were unavailable or"
250 case GSS_S_NO_CONTEXT
:
251 errStr
= dgettext(TEXT_DOMAIN
,
252 "No context has been established");
255 case GSS_S_DEFECTIVE_TOKEN
:
256 errStr
= dgettext(TEXT_DOMAIN
,
257 "Invalid token was supplied");
260 case GSS_S_DEFECTIVE_CREDENTIAL
:
261 errStr
= dgettext(TEXT_DOMAIN
,
262 "Invalid credential was supplied");
265 case GSS_S_CREDENTIALS_EXPIRED
:
266 errStr
= dgettext(TEXT_DOMAIN
,
267 "The referenced credential has"
271 case GSS_S_CONTEXT_EXPIRED
:
272 errStr
= dgettext(TEXT_DOMAIN
,
273 "The referenced context has expired");
277 errStr
= dgettext(TEXT_DOMAIN
,
278 "Unspecified GSS failure. Minor code"
279 " may provide more information");
283 errStr
= dgettext(TEXT_DOMAIN
,
284 "The quality-of-protection (QOP) "
285 "requested could not be provided");
288 case GSS_S_UNAUTHORIZED
:
289 errStr
= dgettext(TEXT_DOMAIN
,
290 "The operation is forbidden by local"
294 case GSS_S_UNAVAILABLE
:
295 errStr
= dgettext(TEXT_DOMAIN
,
296 "The operation or option is not"
297 " available or unsupported");
300 case GSS_S_DUPLICATE_ELEMENT
:
301 errStr
= dgettext(TEXT_DOMAIN
,
302 "The requested credential element"
306 case GSS_S_NAME_NOT_MN
:
307 errStr
= dgettext(TEXT_DOMAIN
,
308 "The provided name was not mechanism"
312 case GSS_S_BAD_STATUS
:
314 errStr
= dgettext(TEXT_DOMAIN
,
315 "An invalid status code was supplied");
318 /* we must determine if the caller should call us again */
319 if ((oneVal
= GSS_SUPPLEMENTARY_INFO(status
)) != 0)
320 *msgCtxt
= (OM_uint32
)(oneVal
<< 1);
324 } else if ((*msgCtxt
== 0 || *msgCtxt
>= 2) &&
325 (oneVal
= GSS_SUPPLEMENTARY_INFO(status
))) {
327 * if msgCtxt is not 0, then it should encode
328 * the supplementary error code we should be printing
331 oneVal
= (OM_uint32
) (*msgCtxt
) >> 1;
333 oneVal
= GSS_SUPPLEMENTARY_INFO(status
);
335 /* we display the errors LSB first */
336 for (i
= 0; i
< 16; i
++) {
344 /* isolate the bit or if not found set to illegal value */
346 currErr
= oneVal
& mask
;
348 currErr
= 1 << 17; /* illegal value */
351 case GSS_S_CONTINUE_NEEDED
:
352 errStr
= dgettext(TEXT_DOMAIN
,
353 "The routine must be called again to"
354 " complete its function");
357 case GSS_S_DUPLICATE_TOKEN
:
358 errStr
= dgettext(TEXT_DOMAIN
,
359 "The token was a duplicate of an"
363 case GSS_S_OLD_TOKEN
:
364 errStr
= dgettext(TEXT_DOMAIN
,
365 "The token's validity period"
369 case GSS_S_UNSEQ_TOKEN
:
370 errStr
= dgettext(TEXT_DOMAIN
,
371 "A later token has already been"
375 case GSS_S_GAP_TOKEN
:
376 errStr
= dgettext(TEXT_DOMAIN
,
377 "An expected per-message token was"
382 errStr
= dgettext(TEXT_DOMAIN
,
383 "An invalid status code was supplied");
387 * we must check if there is any other supplementary errors
388 * if found, then turn off current bit, and store next value
389 * in msgCtxt shifted by 1 bit
393 else if (GSS_SUPPLEMENTARY_INFO(oneVal
) ^ mask
)
394 *msgCtxt
= (OM_uint32
)
395 ((GSS_SUPPLEMENTARY_INFO(oneVal
) ^ mask
) << 1);
401 errStr
= dgettext(TEXT_DOMAIN
,
402 "An invalid status code was supplied");
404 /* now copy the status code and return to caller */
405 outStr
->length
= strlen(errStr
);
406 outStr
->value
= strdup(errStr
);
407 if (outStr
->value
== NULL
) {
409 return (GSS_S_FAILURE
);
412 return (GSS_S_COMPLETE
);