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