]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libgssapi/gss_display_status.c
amd64: allow gdb(4) to write to most registers
[FreeBSD/FreeBSD.git] / lib / libgssapi / gss_display_status.c
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 2005 Doug Rabson
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  *      $FreeBSD$
29  */
30 /*
31  * Copyright (c) 1998 - 2005 Kungliga Tekniska Högskolan
32  * (Royal Institute of Technology, Stockholm, Sweden). 
33  * All rights reserved. 
34  *
35  * Redistribution and use in source and binary forms, with or without 
36  * modification, are permitted provided that the following conditions 
37  * are met: 
38  *
39  * 1. Redistributions of source code must retain the above copyright 
40  *    notice, this list of conditions and the following disclaimer. 
41  *
42  * 2. Redistributions in binary form must reproduce the above copyright 
43  *    notice, this list of conditions and the following disclaimer in the 
44  *    documentation and/or other materials provided with the distribution. 
45  *
46  * 3. Neither the name of the Institute nor the names of its contributors 
47  *    may be used to endorse or promote products derived from this software 
48  *    without specific prior written permission. 
49  *
50  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
51  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
52  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
53  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
54  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
55  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
56  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
57  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
58  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
59  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
60  * SUCH DAMAGE. 
61  */
62 /*
63  * Copyright (c) 1998 - 2005 Kungliga Tekniska Högskolan
64  * (Royal Institute of Technology, Stockholm, Sweden). 
65  * All rights reserved. 
66  *
67  * Redistribution and use in source and binary forms, with or without 
68  * modification, are permitted provided that the following conditions 
69  * are met: 
70  *
71  * 1. Redistributions of source code must retain the above copyright 
72  *    notice, this list of conditions and the following disclaimer. 
73  *
74  * 2. Redistributions in binary form must reproduce the above copyright 
75  *    notice, this list of conditions and the following disclaimer in the 
76  *    documentation and/or other materials provided with the distribution. 
77  *
78  * 3. Neither the name of the Institute nor the names of its contributors 
79  *    may be used to endorse or promote products derived from this software 
80  *    without specific prior written permission. 
81  *
82  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
83  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
84  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
85  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
86  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
87  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
88  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
89  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
90  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
91  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
92  * SUCH DAMAGE. 
93  */
94
95 #include <sys/param.h>
96 #include <gssapi/gssapi.h>
97 #include <stdio.h>
98 #include <string.h>
99 #include <stdlib.h>
100 #include <errno.h>
101
102 #include "mech_switch.h"
103 #include "utils.h"
104
105 static const char *
106 calling_error(OM_uint32 v)
107 {
108     static const char *msgs[] = {
109         [0] = "",
110         [1] = "A required input parameter could not be read.",
111         [2] = "A required output parameter could not be written.",
112         [3] = "A parameter was malformed",
113     };
114
115     v >>= GSS_C_CALLING_ERROR_OFFSET;
116
117     if (v >= nitems(msgs))
118         return "unknown calling error";
119     else
120         return msgs[v];
121 }
122
123 static const char *
124 routine_error(OM_uint32 v)
125 {
126     static const char *msgs[] = {
127         [0] = "Function completed successfully",
128         [1] = "An unsupported mechanism was requested",
129         [2] = "An invalid name was supplied",
130         [3] = "A supplied name was of an unsupported type",
131         [4] = "Incorrect channel bindings were supplied",
132         [5] = "An invalid status code was supplied",
133         [6] = "A token had an invalid MIC",
134         [7] = ("No credentials were supplied, "
135             "or the credentials were unavailable or inaccessible."),
136         [8] = "No context has been established",
137         [9] = "A token was invalid",
138         [10] = "A credential was invalid",
139         [11] =  "The referenced credentials have expired",
140         [12] = "The context has expired",
141         [13] = "Miscellaneous failure (see text)",
142         [14] = "The quality-of-protection requested could not be provide",
143         [15] = "The operation is forbidden by local security policy",
144         [16] = "The operation or option is not available",
145         [17] = "The requested credential element already exists",
146         [18] = "The provided name was not a mechanism name.",
147     };
148
149     v >>= GSS_C_ROUTINE_ERROR_OFFSET;
150
151     if (v >= nitems(msgs))
152         return "unknown routine error";
153     else
154         return msgs[v];
155 }
156
157 static const char *
158 supplementary_error(OM_uint32 v)
159 {
160     static const char *msgs[] = {
161         [0] = "normal completion",
162         [1] = "continuation call to routine required",
163         [2] = "duplicate per-message token detected",
164         [3] = "timed-out per-message token detected",
165         [4] = "reordered (early) per-message token detected",
166         [5] = "skipped predecessor token(s) detected",
167     };
168
169     v >>= GSS_C_SUPPLEMENTARY_OFFSET;
170
171     if (v >= nitems(msgs))
172         return "unknown routine error";
173     else
174         return msgs[v];
175 }
176
177 #if defined(__NO_TLS)
178
179 /*
180  * These platforms don't support TLS on FreeBSD - threads will just
181  * have to step on each other's error values for now.
182  */
183 #define __thread
184
185 #endif
186
187 struct mg_thread_ctx {
188     gss_OID mech;
189     OM_uint32 maj_stat;
190     OM_uint32 min_stat;
191     gss_buffer_desc maj_error;
192     gss_buffer_desc min_error;
193 };
194 static __thread struct mg_thread_ctx last_error_context;
195
196 static OM_uint32
197 _gss_mg_get_error(const gss_OID mech, OM_uint32 type,
198                   OM_uint32 value, gss_buffer_t string)
199 {
200         struct mg_thread_ctx *mg;
201
202         mg = &last_error_context;
203
204         if (mech != NULL && gss_oid_equal(mg->mech, mech) == 0)
205                 return (GSS_S_BAD_STATUS);
206
207         switch (type) {
208         case GSS_C_GSS_CODE: {
209                 if (value != mg->maj_stat || mg->maj_error.length == 0)
210                         break;
211                 string->value = malloc(mg->maj_error.length);
212                 string->length = mg->maj_error.length;
213                 memcpy(string->value, mg->maj_error.value,
214                     mg->maj_error.length);
215                 return (GSS_S_COMPLETE);
216         }
217         case GSS_C_MECH_CODE: {
218                 if (value != mg->min_stat || mg->min_error.length == 0)
219                         break;
220                 string->value = malloc(mg->min_error.length);
221                 string->length = mg->min_error.length;
222                 memcpy(string->value, mg->min_error.value,
223                     mg->min_error.length);
224                 return (GSS_S_COMPLETE);
225         }
226         }
227         string->value = NULL;
228         string->length = 0;
229         return (GSS_S_BAD_STATUS);
230 }
231
232 void
233 _gss_mg_error(struct _gss_mech_switch *m, OM_uint32 maj, OM_uint32 min)
234 {
235         OM_uint32 major_status, minor_status;
236         OM_uint32 message_content;
237         struct mg_thread_ctx *mg;
238
239         mg = &last_error_context;
240
241         gss_release_buffer(&minor_status, &mg->maj_error);
242         gss_release_buffer(&minor_status, &mg->min_error);
243
244         mg->mech = &m->gm_mech_oid;
245         mg->maj_stat = maj;
246         mg->min_stat = min;
247
248         major_status = m->gm_display_status(&minor_status,
249             maj, 
250             GSS_C_GSS_CODE,
251             &m->gm_mech_oid,
252             &message_content,
253             &mg->maj_error);
254         if (GSS_ERROR(major_status)) {
255                 mg->maj_error.value = NULL;
256                 mg->maj_error.length = 0;
257         }
258         major_status = m->gm_display_status(&minor_status,
259             min, 
260             GSS_C_MECH_CODE,
261             &m->gm_mech_oid,
262             &message_content,
263             &mg->min_error);
264         if (GSS_ERROR(major_status)) {
265                 mg->min_error.value = NULL;
266                 mg->min_error.length = 0;
267         }
268 }
269
270 OM_uint32
271 gss_display_status(OM_uint32 *minor_status,
272     OM_uint32 status_value,
273     int status_type,
274     const gss_OID mech_type,
275     OM_uint32 *message_content,
276     gss_buffer_t status_string)
277 {
278         OM_uint32 major_status;
279
280         _gss_buffer_zero(status_string);
281         *message_content = 0;
282
283         major_status = _gss_mg_get_error(mech_type, status_type,
284                                          status_value, status_string);
285         if (major_status == GSS_S_COMPLETE) {
286
287                 *message_content = 0;
288                 *minor_status = 0;
289                 return (GSS_S_COMPLETE);
290         }
291
292         *minor_status = 0;
293         switch (status_type) {
294         case GSS_C_GSS_CODE: {
295                 char *buf;
296
297                 if (GSS_SUPPLEMENTARY_INFO(status_value))
298                     asprintf(&buf, "%s", supplementary_error(
299                         GSS_SUPPLEMENTARY_INFO(status_value)));
300                 else
301                     asprintf (&buf, "%s %s",
302                         calling_error(GSS_CALLING_ERROR(status_value)),
303                         routine_error(GSS_ROUTINE_ERROR(status_value)));
304
305                 if (buf == NULL)
306                         break;
307
308                 status_string->length = strlen(buf);
309                 status_string->value  = buf;
310
311                 return (GSS_S_COMPLETE);
312         }
313         case GSS_C_MECH_CODE: {
314                 OM_uint32 maj_junk, min_junk;
315                 gss_buffer_desc oid;
316                 char *buf;
317
318                 maj_junk = gss_oid_to_str(&min_junk, mech_type, &oid);
319                 if (maj_junk != GSS_S_COMPLETE) {
320                         oid.value = strdup("unknown");
321                         oid.length = 7;
322                 }
323
324                 asprintf (&buf, "unknown mech-code %lu for mech %.*s",
325                           (unsigned long)status_value,
326                           (int)oid.length, (char *)oid.value);
327                 if (maj_junk == GSS_S_COMPLETE)
328                         gss_release_buffer(&min_junk, &oid);
329
330                 if (buf == NULL)
331                     break;
332
333                 status_string->length = strlen(buf);
334                 status_string->value  = buf;
335
336                 return (GSS_S_COMPLETE);
337         }
338         }
339         _gss_buffer_zero(status_string);
340         return (GSS_S_BAD_STATUS);
341 }
342
343 void
344 _gss_mg_collect_error(gss_OID mech, OM_uint32 maj, OM_uint32 min)
345 {
346         struct _gss_mech_switch *m;
347
348         m = _gss_find_mech_switch(mech);
349         if (m != NULL)
350                 _gss_mg_error(m, maj, min);
351 }