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