xref: /freebsd/crypto/krb5/src/lib/gssapi/krb5/disp_status.c (revision f1c4c3daccbaf3820f0e2224de53df12fc952fcc)
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3  * Copyright 1993 by OpenVision Technologies, Inc.
4  *
5  * Permission to use, copy, modify, distribute, and sell this software
6  * and its documentation for any purpose is hereby granted without fee,
7  * provided that the above copyright notice appears in all copies and
8  * that both that copyright notice and this permission notice appear in
9  * supporting documentation, and that the name of OpenVision not be used
10  * in advertising or publicity pertaining to distribution of the software
11  * without specific, written prior permission. OpenVision makes no
12  * representations about the suitability of this software for any
13  * purpose.  It is provided "as is" without express or implied warranty.
14  *
15  * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17  * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
19  * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
20  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21  * PERFORMANCE OF THIS SOFTWARE.
22  */
23 
24 #include "gssapiP_krb5.h"
25 #include "com_err.h"
26 
27 /* XXXX internationalization!! */
28 
29 static inline int
compare_OM_uint32(OM_uint32 a,OM_uint32 b)30 compare_OM_uint32 (OM_uint32 a, OM_uint32 b)
31 {
32     if (a < b)
33         return -1;
34     else if (a == b)
35         return 0;
36     else
37         return 1;
38 }
39 static inline void
free_string(char * s)40 free_string (char *s)
41 {
42     free(s);
43 }
44 #include "error_map.h"
45 #include <stdio.h>
get_error_message(OM_uint32 minor_code)46 char *get_error_message(OM_uint32 minor_code)
47 {
48     gsserrmap *p = k5_getspecific(K5_KEY_GSS_KRB5_ERROR_MESSAGE);
49     char *msg = NULL;
50 #ifdef DEBUG
51     fprintf(stderr, "%s(%lu, p=%p)", __FUNCTION__, (unsigned long) minor_code,
52             (void *) p);
53 #endif
54     if (p) {
55         char **v = gsserrmap_find(p, minor_code);
56         if (v) {
57             msg = *v;
58 #ifdef DEBUG
59             fprintf(stderr, " FOUND!");
60 #endif
61         }
62     }
63     if (msg == 0)
64         msg = (char *)error_message((krb5_error_code)minor_code);
65 #ifdef DEBUG
66     fprintf(stderr, " -> %p/%s\n", (void *) msg, msg);
67 #endif
68     return msg;
69 }
70 #define save_error_string_nocopy gss_krb5_save_error_string_nocopy
save_error_string_nocopy(OM_uint32 minor_code,char * msg)71 static int save_error_string_nocopy(OM_uint32 minor_code, char *msg)
72 {
73     gsserrmap *p;
74     int ret;
75 
76 #ifdef DEBUG
77     fprintf(stderr, "%s(%lu, %s)", __FUNCTION__, (unsigned long) minor_code, msg);
78 #endif
79     p = k5_getspecific(K5_KEY_GSS_KRB5_ERROR_MESSAGE);
80     if (!p) {
81         p = malloc(sizeof(*p));
82         if (p == NULL) {
83             ret = 1;
84             goto fail;
85         }
86         if (gsserrmap_init(p) != 0) {
87             free(p);
88             p = NULL;
89             ret = 1;
90             goto fail;
91         }
92         if (k5_setspecific(K5_KEY_GSS_KRB5_ERROR_MESSAGE, p) != 0) {
93             gsserrmap_destroy(p);
94             free(p);
95             p = NULL;
96             ret = 1;
97             goto fail;
98         }
99     }
100     ret = gsserrmap_replace_or_insert(p, minor_code, msg);
101 fail:
102 #ifdef DEBUG
103     fprintf(stderr, " p=%p %s\n", (void *)p, ret ? "FAIL" : "SUCCESS");
104 #endif
105     return ret;
106 }
save_error_string(OM_uint32 minor_code,char * msg)107 void save_error_string(OM_uint32 minor_code, char *msg)
108 {
109     char *s = strdup(msg);
110     if (s) {
111         if (save_error_string_nocopy(minor_code, s) != 0)
112             free(s);
113     }
114 }
save_error_message(OM_uint32 minor_code,const char * format,...)115 void save_error_message(OM_uint32 minor_code, const char *format, ...)
116 {
117     char *s;
118     int n;
119     va_list ap;
120 
121     va_start(ap, format);
122     n = vasprintf(&s, format, ap);
123     va_end(ap);
124     if (n >= 0) {
125         if (save_error_string_nocopy(minor_code, s) != 0)
126             free(s);
127     }
128 }
krb5_gss_save_error_info(OM_uint32 minor_code,krb5_context ctx)129 void krb5_gss_save_error_info(OM_uint32 minor_code, krb5_context ctx)
130 {
131     char *s;
132 
133 #ifdef DEBUG
134     fprintf(stderr, "%s(%lu, ctx=%p)\n", __FUNCTION__,
135             (unsigned long) minor_code, (void *)ctx);
136 #endif
137     s = (char *)krb5_get_error_message(ctx, (krb5_error_code)minor_code);
138 #ifdef DEBUG
139     fprintf(stderr, "%s(%lu, ctx=%p) saving: %s\n", __FUNCTION__,
140             (unsigned long) minor_code, (void *)ctx, s);
141 #endif
142     save_error_string(minor_code, s);
143     /* The get_error_message call above resets the error message in
144        ctx.  Put it back, in case we make this call again *sigh*.  */
145     k5_setmsg(ctx, (krb5_error_code)minor_code, "%s", s);
146     krb5_free_error_message(ctx, s);
147 }
krb5_gss_delete_error_info(void * p)148 void krb5_gss_delete_error_info(void *p)
149 {
150     gsserrmap_destroy(p);
151     free(p);
152 }
153 
154 /**/
155 
156 OM_uint32 KRB5_CALLCONV
krb5_gss_display_status(OM_uint32 * minor_status,OM_uint32 status_value,int status_type,gss_OID mech_type,OM_uint32 * message_context,gss_buffer_t status_string)157 krb5_gss_display_status(OM_uint32 *minor_status, OM_uint32 status_value,
158                         int status_type, gss_OID mech_type,
159                         OM_uint32 *message_context, gss_buffer_t status_string)
160 {
161     status_string->length = 0;
162     status_string->value = NULL;
163 
164     if ((mech_type != GSS_C_NULL_OID) &&
165         !g_OID_equal(gss_mech_krb5, mech_type) &&
166         !g_OID_equal(gss_mech_krb5_old, mech_type) &&
167         !g_OID_equal(gss_mech_iakerb, mech_type)) {
168         *minor_status = 0;
169         return(GSS_S_BAD_MECH);
170     }
171 
172     if (status_type == GSS_C_GSS_CODE) {
173         return(g_display_major_status(minor_status, status_value,
174                                       message_context, status_string));
175     } else if (status_type == GSS_C_MECH_CODE) {
176         (void) gss_krb5int_initialize_library();
177 
178         if (*message_context) {
179             *minor_status = (OM_uint32) G_BAD_MSG_CTX;
180             return(GSS_S_FAILURE);
181         }
182 
183         /* If this fails, there's not much we can do...  */
184         if (!g_make_string_buffer(krb5_gss_get_error_message(status_value),
185                                   status_string)) {
186             *minor_status = ENOMEM;
187             return(GSS_S_FAILURE);
188         }
189         *minor_status = 0;
190         return(GSS_S_COMPLETE);
191     } else {
192         *minor_status = 0;
193         return(GSS_S_BAD_STATUS);
194     }
195 }
196