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