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