Initial import from FreeBSD RELENG_4:
[games.git] / crypto / heimdal / lib / gssapi / display_status.c
1 /*
2  * Copyright (c) 1998 - 2001 Kungliga Tekniska Högskolan
3  * (Royal Institute of Technology, Stockholm, Sweden). 
4  * All rights reserved. 
5  *
6  * Redistribution and use in source and binary forms, with or without 
7  * modification, are permitted provided that the following conditions 
8  * are met: 
9  *
10  * 1. Redistributions of source code must retain the above copyright 
11  *    notice, this list of conditions and the following disclaimer. 
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright 
14  *    notice, this list of conditions and the following disclaimer in the 
15  *    documentation and/or other materials provided with the distribution. 
16  *
17  * 3. Neither the name of the Institute nor the names of its contributors 
18  *    may be used to endorse or promote products derived from this software 
19  *    without specific prior written permission. 
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
31  * SUCH DAMAGE. 
32  */
33
34 #include "gssapi_locl.h"
35
36 RCSID("$Id: display_status.c,v 1.7 2001/08/23 04:34:41 assar Exp $");
37
38 static char *krb5_error_string;
39
40 static char *
41 calling_error(OM_uint32 v)
42 {
43     static char *msgs[] = {
44         NULL,                   /* 0 */
45         "A required input parameter could not be read.", /*  */
46         "A required output parameter could not be written.", /*  */
47         "A parameter was malformed"
48     };
49
50     v >>= GSS_C_CALLING_ERROR_OFFSET;
51
52     if (v == 0)
53         return "";
54     else if (v >= sizeof(msgs)/sizeof(*msgs))
55         return "unknown calling error";
56     else
57         return msgs[v];
58 }
59
60 static char *
61 routine_error(OM_uint32 v)
62 {
63     static char *msgs[] = {
64         NULL,                   /* 0 */
65         "An unsupported mechanism was requested",
66         "An invalid name was supplied",
67         "A supplied name was of an unsupported type",
68         "Incorrect channel bindings were supplied",
69         "An invalid status code was supplied",
70         "A token had an invalid MIC",
71         "No credentials were supplied, "
72         "or the credentials were unavailable or inaccessible.",
73         "No context has been established",
74         "A token was invalid",
75         "A credential was invalid",
76         "The referenced credentials have expired",
77         "The context has expired",
78         "Miscellaneous failure (see text)",
79         "The quality-of-protection requested could not be provide",
80         "The operation is forbidden by local security policy",
81         "The operation or option is not available",
82         "The requested credential element already exists",
83         "The provided name was not a mechanism name.",
84     };
85
86     v >>= GSS_C_ROUTINE_ERROR_OFFSET;
87
88     if (v == 0)
89         return "";
90     else if (v >= sizeof(msgs)/sizeof(*msgs))
91         return "unknown routine error";
92     else
93         return msgs[v];
94 }
95
96 void
97 gssapi_krb5_set_error_string (void)
98 {
99     krb5_error_string = krb5_get_error_string(gssapi_krb5_context);
100 }
101
102 char *
103 gssapi_krb5_get_error_string (void)
104 {
105     char *ret = krb5_error_string;
106     krb5_error_string = NULL;
107     return ret;
108 }
109
110 OM_uint32 gss_display_status
111            (OM_uint32           *minor_status,
112             OM_uint32            status_value,
113             int                  status_type,
114             const gss_OID        mech_type,
115             OM_uint32           *message_context,
116             gss_buffer_t         status_string)
117 {
118   char *buf;
119
120   gssapi_krb5_init ();
121
122   *minor_status = 0;
123
124   if (mech_type != GSS_C_NO_OID &&
125       mech_type != GSS_KRB5_MECHANISM)
126       return GSS_S_BAD_MECH;
127
128   if (status_type == GSS_C_GSS_CODE) {
129       asprintf (&buf, "%s %s",
130                 calling_error(GSS_CALLING_ERROR(status_value)),
131                 routine_error(GSS_ROUTINE_ERROR(status_value)));
132   } else if (status_type == GSS_C_MECH_CODE) {
133       buf = gssapi_krb5_get_error_string ();
134       if (buf == NULL) {
135           const char *tmp = krb5_get_err_text (gssapi_krb5_context,
136                                                status_value);
137           if (tmp == NULL)
138               asprintf(&buf, "unknown mech error-code %u",
139                        (unsigned)status_value);
140           else
141               buf = strdup(tmp);
142       }
143   } else
144       return GSS_S_BAD_STATUS;
145
146   if (buf == NULL) {
147       *minor_status = ENOMEM;
148       return GSS_S_FAILURE;
149   }
150
151   *message_context = 0;
152
153   status_string->length = strlen(buf);
154   status_string->value  = buf;
155   
156   return GSS_S_COMPLETE;
157 }