xref: /freebsd/crypto/heimdal/lib/gssapi/krb5/display_status.c (revision c19800e8cd5640693f36f2040db4ab5e8d738146)
1c19800e8SDoug Rabson /*
2c19800e8SDoug Rabson  * 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 
34c19800e8SDoug Rabson #include "krb5/gsskrb5_locl.h"
35c19800e8SDoug Rabson 
36c19800e8SDoug Rabson RCSID("$Id: display_status.c 19031 2006-11-13 18:02:57Z lha $");
37c19800e8SDoug Rabson 
38c19800e8SDoug Rabson static const char *
39c19800e8SDoug Rabson calling_error(OM_uint32 v)
40c19800e8SDoug Rabson {
41c19800e8SDoug Rabson     static const char *msgs[] = {
42c19800e8SDoug Rabson 	NULL,			/* 0 */
43c19800e8SDoug Rabson 	"A required input parameter could not be read.", /*  */
44c19800e8SDoug Rabson 	"A required output parameter could not be written.", /*  */
45c19800e8SDoug Rabson 	"A parameter was malformed"
46c19800e8SDoug Rabson     };
47c19800e8SDoug Rabson 
48c19800e8SDoug Rabson     v >>= GSS_C_CALLING_ERROR_OFFSET;
49c19800e8SDoug Rabson 
50c19800e8SDoug Rabson     if (v == 0)
51c19800e8SDoug Rabson 	return "";
52c19800e8SDoug Rabson     else if (v >= sizeof(msgs)/sizeof(*msgs))
53c19800e8SDoug Rabson 	return "unknown calling error";
54c19800e8SDoug Rabson     else
55c19800e8SDoug Rabson 	return msgs[v];
56c19800e8SDoug Rabson }
57c19800e8SDoug Rabson 
58c19800e8SDoug Rabson static const char *
59c19800e8SDoug Rabson routine_error(OM_uint32 v)
60c19800e8SDoug Rabson {
61c19800e8SDoug Rabson     static const char *msgs[] = {
62c19800e8SDoug Rabson 	NULL,			/* 0 */
63c19800e8SDoug Rabson 	"An unsupported mechanism was requested",
64c19800e8SDoug Rabson 	"An invalid name was supplied",
65c19800e8SDoug Rabson 	"A supplied name was of an unsupported type",
66c19800e8SDoug Rabson 	"Incorrect channel bindings were supplied",
67c19800e8SDoug Rabson 	"An invalid status code was supplied",
68c19800e8SDoug Rabson 	"A token had an invalid MIC",
69c19800e8SDoug Rabson 	"No credentials were supplied, "
70c19800e8SDoug Rabson 	"or the credentials were unavailable or inaccessible.",
71c19800e8SDoug Rabson 	"No context has been established",
72c19800e8SDoug Rabson 	"A token was invalid",
73c19800e8SDoug Rabson 	"A credential was invalid",
74c19800e8SDoug Rabson 	"The referenced credentials have expired",
75c19800e8SDoug Rabson 	"The context has expired",
76c19800e8SDoug Rabson 	"Miscellaneous failure (see text)",
77c19800e8SDoug Rabson 	"The quality-of-protection requested could not be provide",
78c19800e8SDoug Rabson 	"The operation is forbidden by local security policy",
79c19800e8SDoug Rabson 	"The operation or option is not available",
80c19800e8SDoug Rabson 	"The requested credential element already exists",
81c19800e8SDoug Rabson 	"The provided name was not a mechanism name.",
82c19800e8SDoug Rabson     };
83c19800e8SDoug Rabson 
84c19800e8SDoug Rabson     v >>= GSS_C_ROUTINE_ERROR_OFFSET;
85c19800e8SDoug Rabson 
86c19800e8SDoug Rabson     if (v == 0)
87c19800e8SDoug Rabson 	return "";
88c19800e8SDoug Rabson     else if (v >= sizeof(msgs)/sizeof(*msgs))
89c19800e8SDoug Rabson 	return "unknown routine error";
90c19800e8SDoug Rabson     else
91c19800e8SDoug Rabson 	return msgs[v];
92c19800e8SDoug Rabson }
93c19800e8SDoug Rabson 
94c19800e8SDoug Rabson static const char *
95c19800e8SDoug Rabson supplementary_error(OM_uint32 v)
96c19800e8SDoug Rabson {
97c19800e8SDoug Rabson     static const char *msgs[] = {
98c19800e8SDoug Rabson 	"normal completion",
99c19800e8SDoug Rabson 	"continuation call to routine required",
100c19800e8SDoug Rabson 	"duplicate per-message token detected",
101c19800e8SDoug Rabson 	"timed-out per-message token detected",
102c19800e8SDoug Rabson 	"reordered (early) per-message token detected",
103c19800e8SDoug Rabson 	"skipped predecessor token(s) detected"
104c19800e8SDoug Rabson     };
105c19800e8SDoug Rabson 
106c19800e8SDoug Rabson     v >>= GSS_C_SUPPLEMENTARY_OFFSET;
107c19800e8SDoug Rabson 
108c19800e8SDoug Rabson     if (v >= sizeof(msgs)/sizeof(*msgs))
109c19800e8SDoug Rabson 	return "unknown routine error";
110c19800e8SDoug Rabson     else
111c19800e8SDoug Rabson 	return msgs[v];
112c19800e8SDoug Rabson }
113c19800e8SDoug Rabson 
114c19800e8SDoug Rabson void
115c19800e8SDoug Rabson _gsskrb5_clear_status (void)
116c19800e8SDoug Rabson {
117c19800e8SDoug Rabson     krb5_context context;
118c19800e8SDoug Rabson 
119c19800e8SDoug Rabson     if (_gsskrb5_init (&context) != 0)
120c19800e8SDoug Rabson 	return;
121c19800e8SDoug Rabson     krb5_clear_error_string(context);
122c19800e8SDoug Rabson }
123c19800e8SDoug Rabson 
124c19800e8SDoug Rabson void
125c19800e8SDoug Rabson _gsskrb5_set_status (const char *fmt, ...)
126c19800e8SDoug Rabson {
127c19800e8SDoug Rabson     krb5_context context;
128c19800e8SDoug Rabson     va_list args;
129c19800e8SDoug Rabson     char *str;
130c19800e8SDoug Rabson 
131c19800e8SDoug Rabson     if (_gsskrb5_init (&context) != 0)
132c19800e8SDoug Rabson 	return;
133c19800e8SDoug Rabson 
134c19800e8SDoug Rabson     va_start(args, fmt);
135c19800e8SDoug Rabson     vasprintf(&str, fmt, args);
136c19800e8SDoug Rabson     va_end(args);
137c19800e8SDoug Rabson     if (str) {
138c19800e8SDoug Rabson 	krb5_set_error_string(context, str);
139c19800e8SDoug Rabson 	free(str);
140c19800e8SDoug Rabson     }
141c19800e8SDoug Rabson }
142c19800e8SDoug Rabson 
143c19800e8SDoug Rabson OM_uint32 _gsskrb5_display_status
144c19800e8SDoug Rabson (OM_uint32		*minor_status,
145c19800e8SDoug Rabson  OM_uint32		 status_value,
146c19800e8SDoug Rabson  int			 status_type,
147c19800e8SDoug Rabson  const gss_OID	 mech_type,
148c19800e8SDoug Rabson  OM_uint32		*message_context,
149c19800e8SDoug Rabson  gss_buffer_t	 status_string)
150c19800e8SDoug Rabson {
151c19800e8SDoug Rabson     krb5_context context;
152c19800e8SDoug Rabson     char *buf;
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))
167c19800e8SDoug Rabson 	    asprintf(&buf, "%s",
168c19800e8SDoug Rabson 		     supplementary_error(GSS_SUPPLEMENTARY_INFO(status_value)));
169c19800e8SDoug Rabson 	else
170c19800e8SDoug Rabson 	    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) {
174c19800e8SDoug Rabson 	buf = krb5_get_error_string(context);
175c19800e8SDoug Rabson 	if (buf == NULL) {
176c19800e8SDoug Rabson 	    const char *tmp = krb5_get_err_text (context, status_value);
177c19800e8SDoug Rabson 	    if (tmp == NULL)
178c19800e8SDoug Rabson 		asprintf(&buf, "unknown mech error-code %u",
179c19800e8SDoug Rabson 			 (unsigned)status_value);
180c19800e8SDoug Rabson 	    else
181c19800e8SDoug Rabson 		buf = strdup(tmp);
182c19800e8SDoug Rabson 	}
183c19800e8SDoug Rabson     } else {
184c19800e8SDoug Rabson 	*minor_status = EINVAL;
185c19800e8SDoug Rabson 	return GSS_S_BAD_STATUS;
186c19800e8SDoug Rabson     }
187c19800e8SDoug Rabson 
188c19800e8SDoug Rabson     if (buf == NULL) {
189c19800e8SDoug Rabson 	*minor_status = ENOMEM;
190c19800e8SDoug Rabson 	return GSS_S_FAILURE;
191c19800e8SDoug Rabson     }
192c19800e8SDoug Rabson 
193c19800e8SDoug Rabson     *message_context = 0;
194c19800e8SDoug Rabson     *minor_status = 0;
195c19800e8SDoug Rabson 
196c19800e8SDoug Rabson     status_string->length = strlen(buf);
197c19800e8SDoug Rabson     status_string->value  = buf;
198c19800e8SDoug Rabson 
199c19800e8SDoug Rabson     return GSS_S_COMPLETE;
200c19800e8SDoug Rabson }
201