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