xref: /netbsd-src/crypto/external/bsd/heimdal/dist/lib/gssapi/krb5/display_status.c (revision afab4e300d3a9fb07dd8c80daf53d0feb3345706)
1*afab4e30Schristos /*	$NetBSD: display_status.c,v 1.3 2023/06/19 21:41:43 christos Exp $	*/
2ca1c9b0cSelric 
3ca1c9b0cSelric /*
4ca1c9b0cSelric  * Copyright (c) 1998 - 2006 Kungliga Tekniska Högskolan
5ca1c9b0cSelric  * (Royal Institute of Technology, Stockholm, Sweden).
6ca1c9b0cSelric  * All rights reserved.
7ca1c9b0cSelric  *
8ca1c9b0cSelric  * Redistribution and use in source and binary forms, with or without
9ca1c9b0cSelric  * modification, are permitted provided that the following conditions
10ca1c9b0cSelric  * are met:
11ca1c9b0cSelric  *
12ca1c9b0cSelric  * 1. Redistributions of source code must retain the above copyright
13ca1c9b0cSelric  *    notice, this list of conditions and the following disclaimer.
14ca1c9b0cSelric  *
15ca1c9b0cSelric  * 2. Redistributions in binary form must reproduce the above copyright
16ca1c9b0cSelric  *    notice, this list of conditions and the following disclaimer in the
17ca1c9b0cSelric  *    documentation and/or other materials provided with the distribution.
18ca1c9b0cSelric  *
19ca1c9b0cSelric  * 3. Neither the name of the Institute nor the names of its contributors
20ca1c9b0cSelric  *    may be used to endorse or promote products derived from this software
21ca1c9b0cSelric  *    without specific prior written permission.
22ca1c9b0cSelric  *
23ca1c9b0cSelric  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24ca1c9b0cSelric  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25ca1c9b0cSelric  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ca1c9b0cSelric  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27ca1c9b0cSelric  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28ca1c9b0cSelric  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29ca1c9b0cSelric  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30ca1c9b0cSelric  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31ca1c9b0cSelric  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32ca1c9b0cSelric  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33ca1c9b0cSelric  * SUCH DAMAGE.
34ca1c9b0cSelric  */
35ca1c9b0cSelric 
36ca1c9b0cSelric #include "gsskrb5_locl.h"
37ca1c9b0cSelric 
38ca1c9b0cSelric static const char *
calling_error(OM_uint32 v)39ca1c9b0cSelric calling_error(OM_uint32 v)
40ca1c9b0cSelric {
41ca1c9b0cSelric     static const char *msgs[] = {
42ca1c9b0cSelric 	NULL,			/* 0 */
43ca1c9b0cSelric 	"A required input parameter could not be read.", /*  */
44ca1c9b0cSelric 	"A required output parameter could not be written.", /*  */
45ca1c9b0cSelric 	"A parameter was malformed"
46ca1c9b0cSelric     };
47ca1c9b0cSelric 
48ca1c9b0cSelric     v >>= GSS_C_CALLING_ERROR_OFFSET;
49ca1c9b0cSelric 
50ca1c9b0cSelric     if (v == 0)
51ca1c9b0cSelric 	return "";
52ca1c9b0cSelric     else if (v >= sizeof(msgs)/sizeof(*msgs))
53ca1c9b0cSelric 	return "unknown calling error";
54ca1c9b0cSelric     else
55ca1c9b0cSelric 	return msgs[v];
56ca1c9b0cSelric }
57ca1c9b0cSelric 
58ca1c9b0cSelric static const char *
routine_error(OM_uint32 v)59ca1c9b0cSelric routine_error(OM_uint32 v)
60ca1c9b0cSelric {
61ca1c9b0cSelric     static const char *msgs[] = {
62ca1c9b0cSelric 	NULL,			/* 0 */
63ca1c9b0cSelric 	"An unsupported mechanism was requested",
64ca1c9b0cSelric 	"An invalid name was supplied",
65ca1c9b0cSelric 	"A supplied name was of an unsupported type",
66ca1c9b0cSelric 	"Incorrect channel bindings were supplied",
67ca1c9b0cSelric 	"An invalid status code was supplied",
68ca1c9b0cSelric 	"A token had an invalid MIC",
69*afab4e30Schristos 	"No credentials were supplied, or the credentials were unavailable or inaccessible.",
70ca1c9b0cSelric 	"No context has been established",
71ca1c9b0cSelric 	"A token was invalid",
72ca1c9b0cSelric 	"A credential was invalid",
73ca1c9b0cSelric 	"The referenced credentials have expired",
74ca1c9b0cSelric 	"The context has expired",
75ca1c9b0cSelric 	"Miscellaneous failure (see text)",
76ca1c9b0cSelric 	"The quality-of-protection requested could not be provide",
77ca1c9b0cSelric 	"The operation is forbidden by local security policy",
78ca1c9b0cSelric 	"The operation or option is not available",
79ca1c9b0cSelric 	"The requested credential element already exists",
80ca1c9b0cSelric 	"The provided name was not a mechanism name.",
81ca1c9b0cSelric     };
82ca1c9b0cSelric 
83ca1c9b0cSelric     v >>= GSS_C_ROUTINE_ERROR_OFFSET;
84ca1c9b0cSelric 
85ca1c9b0cSelric     if (v == 0)
86ca1c9b0cSelric 	return "";
87ca1c9b0cSelric     else if (v >= sizeof(msgs)/sizeof(*msgs))
88ca1c9b0cSelric 	return "unknown routine error";
89ca1c9b0cSelric     else
90ca1c9b0cSelric 	return msgs[v];
91ca1c9b0cSelric }
92ca1c9b0cSelric 
93ca1c9b0cSelric static const char *
supplementary_error(OM_uint32 v)94ca1c9b0cSelric supplementary_error(OM_uint32 v)
95ca1c9b0cSelric {
96ca1c9b0cSelric     static const char *msgs[] = {
97ca1c9b0cSelric 	"normal completion",
98ca1c9b0cSelric 	"continuation call to routine required",
99ca1c9b0cSelric 	"duplicate per-message token detected",
100ca1c9b0cSelric 	"timed-out per-message token detected",
101ca1c9b0cSelric 	"reordered (early) per-message token detected",
102ca1c9b0cSelric 	"skipped predecessor token(s) detected"
103ca1c9b0cSelric     };
104ca1c9b0cSelric 
105ca1c9b0cSelric     v >>= GSS_C_SUPPLEMENTARY_OFFSET;
106ca1c9b0cSelric 
107ca1c9b0cSelric     if (v >= sizeof(msgs)/sizeof(*msgs))
108ca1c9b0cSelric 	return "unknown routine error";
109ca1c9b0cSelric     else
110ca1c9b0cSelric 	return msgs[v];
111ca1c9b0cSelric }
112ca1c9b0cSelric 
113ca1c9b0cSelric void
_gsskrb5_clear_status(void)114ca1c9b0cSelric _gsskrb5_clear_status (void)
115ca1c9b0cSelric {
116ca1c9b0cSelric     krb5_context context;
117ca1c9b0cSelric 
118ca1c9b0cSelric     if (_gsskrb5_init (&context) != 0)
119ca1c9b0cSelric 	return;
120ca1c9b0cSelric     krb5_clear_error_message(context);
121ca1c9b0cSelric }
122ca1c9b0cSelric 
123ca1c9b0cSelric void
_gsskrb5_set_status(int ret,const char * fmt,...)124ca1c9b0cSelric _gsskrb5_set_status (int ret, const char *fmt, ...)
125ca1c9b0cSelric {
126ca1c9b0cSelric     krb5_context context;
127ca1c9b0cSelric     va_list args;
128ca1c9b0cSelric     char *str;
129ca1c9b0cSelric     int e;
130ca1c9b0cSelric 
131ca1c9b0cSelric     if (_gsskrb5_init (&context) != 0)
132ca1c9b0cSelric 	return;
133ca1c9b0cSelric 
134ca1c9b0cSelric     va_start(args, fmt);
135ca1c9b0cSelric     e = vasprintf(&str, fmt, args);
136ca1c9b0cSelric     va_end(args);
137ca1c9b0cSelric     if (e >= 0 && str) {
138ca1c9b0cSelric 	krb5_set_error_message(context, ret, "%s", str);
139ca1c9b0cSelric 	free(str);
140ca1c9b0cSelric     }
141ca1c9b0cSelric }
142ca1c9b0cSelric 
_gsskrb5_display_status(OM_uint32 * minor_status,OM_uint32 status_value,int status_type,const gss_OID mech_type,OM_uint32 * message_context,gss_buffer_t status_string)143ca1c9b0cSelric OM_uint32 GSSAPI_CALLCONV _gsskrb5_display_status
144ca1c9b0cSelric (OM_uint32		*minor_status,
145ca1c9b0cSelric  OM_uint32		 status_value,
146ca1c9b0cSelric  int			 status_type,
147ca1c9b0cSelric  const gss_OID	 mech_type,
148ca1c9b0cSelric  OM_uint32		*message_context,
149ca1c9b0cSelric  gss_buffer_t	 status_string)
150ca1c9b0cSelric {
151ca1c9b0cSelric     krb5_context context;
152ca1c9b0cSelric     char *buf = NULL;
153ca1c9b0cSelric     int e = 0;
154ca1c9b0cSelric 
155ca1c9b0cSelric     GSSAPI_KRB5_INIT (&context);
156ca1c9b0cSelric 
157ca1c9b0cSelric     status_string->length = 0;
158ca1c9b0cSelric     status_string->value = NULL;
159ca1c9b0cSelric 
160ca1c9b0cSelric     if (gss_oid_equal(mech_type, GSS_C_NO_OID) == 0 &&
161ca1c9b0cSelric 	gss_oid_equal(mech_type, GSS_KRB5_MECHANISM) == 0) {
162ca1c9b0cSelric 	*minor_status = 0;
163ca1c9b0cSelric 	return GSS_C_GSS_CODE;
164ca1c9b0cSelric     }
165ca1c9b0cSelric 
166ca1c9b0cSelric     if (status_type == GSS_C_GSS_CODE) {
167ca1c9b0cSelric 	if (GSS_SUPPLEMENTARY_INFO(status_value))
168ca1c9b0cSelric 	    e = asprintf(&buf, "%s",
169ca1c9b0cSelric 			 supplementary_error(GSS_SUPPLEMENTARY_INFO(status_value)));
170ca1c9b0cSelric 	else
171ca1c9b0cSelric 	    e = asprintf (&buf, "%s %s",
172ca1c9b0cSelric 			  calling_error(GSS_CALLING_ERROR(status_value)),
173ca1c9b0cSelric 			  routine_error(GSS_ROUTINE_ERROR(status_value)));
174ca1c9b0cSelric     } else if (status_type == GSS_C_MECH_CODE) {
175ca1c9b0cSelric 	const char *buf2 = krb5_get_error_message(context, status_value);
176ca1c9b0cSelric 	if (buf2) {
177ca1c9b0cSelric 	    buf = strdup(buf2);
178ca1c9b0cSelric 	    krb5_free_error_message(context, buf2);
179ca1c9b0cSelric 	} else {
180ca1c9b0cSelric 	    e = asprintf(&buf, "unknown mech error-code %u",
181ca1c9b0cSelric 			 (unsigned)status_value);
182ca1c9b0cSelric 	}
183ca1c9b0cSelric     } else {
184ca1c9b0cSelric 	*minor_status = EINVAL;
185ca1c9b0cSelric 	return GSS_S_BAD_STATUS;
186ca1c9b0cSelric     }
187ca1c9b0cSelric 
188ca1c9b0cSelric     if (e < 0 || buf == NULL) {
189ca1c9b0cSelric 	*minor_status = ENOMEM;
190ca1c9b0cSelric 	return GSS_S_FAILURE;
191ca1c9b0cSelric     }
192ca1c9b0cSelric 
193ca1c9b0cSelric     *message_context = 0;
194ca1c9b0cSelric     *minor_status = 0;
195ca1c9b0cSelric 
196ca1c9b0cSelric     status_string->length = strlen(buf);
197ca1c9b0cSelric     status_string->value  = buf;
198ca1c9b0cSelric 
199ca1c9b0cSelric     return GSS_S_COMPLETE;
200ca1c9b0cSelric }
201