1*5e01956fSGlenn Barry /* -*- mode: c; indent-tabs-mode: nil -*- */
2*5e01956fSGlenn Barry /*
3*5e01956fSGlenn Barry  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
4*5e01956fSGlenn Barry  */
57c478bd9Sstevel@tonic-gate /*
67c478bd9Sstevel@tonic-gate  * Copyright 1993 by OpenVision Technologies, Inc.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * Permission to use, copy, modify, distribute, and sell this software
97c478bd9Sstevel@tonic-gate  * and its documentation for any purpose is hereby granted without fee,
107c478bd9Sstevel@tonic-gate  * provided that the above copyright notice appears in all copies and
117c478bd9Sstevel@tonic-gate  * that both that copyright notice and this permission notice appear in
127c478bd9Sstevel@tonic-gate  * supporting documentation, and that the name of OpenVision not be used
137c478bd9Sstevel@tonic-gate  * in advertising or publicity pertaining to distribution of the software
147c478bd9Sstevel@tonic-gate  * without specific, written prior permission. OpenVision makes no
157c478bd9Sstevel@tonic-gate  * representations about the suitability of this software for any
167c478bd9Sstevel@tonic-gate  * purpose.  It is provided "as is" without express or implied warranty.
177c478bd9Sstevel@tonic-gate  *
187c478bd9Sstevel@tonic-gate  * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
197c478bd9Sstevel@tonic-gate  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
207c478bd9Sstevel@tonic-gate  * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
217c478bd9Sstevel@tonic-gate  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
227c478bd9Sstevel@tonic-gate  * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
237c478bd9Sstevel@tonic-gate  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
247c478bd9Sstevel@tonic-gate  * PERFORMANCE OF THIS SOFTWARE.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
27ab9b2e15Sgtb #include "gssapiP_krb5.h"
28ab9b2e15Sgtb #include "com_err.h"
29*5e01956fSGlenn Barry #include <syslog.h>
307c478bd9Sstevel@tonic-gate /* XXXX internationalization!! */
317c478bd9Sstevel@tonic-gate 
32*5e01956fSGlenn Barry static inline int
compare_OM_uint32(OM_uint32 a,OM_uint32 b)33*5e01956fSGlenn Barry compare_OM_uint32 (OM_uint32 a, OM_uint32 b)
34*5e01956fSGlenn Barry {
35*5e01956fSGlenn Barry     if (a < b)
36*5e01956fSGlenn Barry         return -1;
37*5e01956fSGlenn Barry     else if (a == b)
38*5e01956fSGlenn Barry         return 0;
39*5e01956fSGlenn Barry     else
40*5e01956fSGlenn Barry         return 1;
41*5e01956fSGlenn Barry }
42*5e01956fSGlenn Barry static inline void
free_string(char * s)43*5e01956fSGlenn Barry free_string (char *s)
44*5e01956fSGlenn Barry {
45*5e01956fSGlenn Barry     free(s);
46*5e01956fSGlenn Barry }
47*5e01956fSGlenn Barry #include "error_map.h"
48*5e01956fSGlenn Barry #include <stdio.h>
49*5e01956fSGlenn Barry /*
50*5e01956fSGlenn Barry  * AKA krb5_gss_get_error_message.  See #define in gssapiP_krb5.h.
51*5e01956fSGlenn Barry  */
get_error_message(OM_uint32 minor_code)52*5e01956fSGlenn Barry char *get_error_message(OM_uint32 minor_code)
53*5e01956fSGlenn Barry {
54*5e01956fSGlenn Barry     gsserrmap *p = k5_getspecific(K5_KEY_GSS_KRB5_ERROR_MESSAGE);
55*5e01956fSGlenn Barry     char *msg = NULL;
56*5e01956fSGlenn Barry 
57*5e01956fSGlenn Barry #ifdef DEBUG
58*5e01956fSGlenn Barry     fprintf(stderr, "%s(%lu, p=%p)", __func__, (unsigned long) minor_code,
59*5e01956fSGlenn Barry             (void *) p);
60*5e01956fSGlenn Barry #endif
61*5e01956fSGlenn Barry     if (p) {
62*5e01956fSGlenn Barry         char **v = gsserrmap_find(p, minor_code);
63*5e01956fSGlenn Barry         if (v) {
64*5e01956fSGlenn Barry             msg = *v;
65*5e01956fSGlenn Barry #ifdef DEBUG
66*5e01956fSGlenn Barry             fprintf(stderr, " FOUND!");
67*5e01956fSGlenn Barry #endif
68*5e01956fSGlenn Barry         }
69*5e01956fSGlenn Barry     }
70*5e01956fSGlenn Barry     if (msg == NULL)
71*5e01956fSGlenn Barry         msg = (char *)error_message((krb5_error_code)minor_code);
72*5e01956fSGlenn Barry #ifdef DEBUG
73*5e01956fSGlenn Barry     fprintf(stderr, " -> %p/%s\n", (void *) msg, msg);
74*5e01956fSGlenn Barry #endif
75*5e01956fSGlenn Barry 
76*5e01956fSGlenn Barry     return msg;
77*5e01956fSGlenn Barry }
78*5e01956fSGlenn Barry #define save_error_string_nocopy gss_krb5_save_error_string_nocopy
save_error_string_nocopy(OM_uint32 minor_code,char * msg)79*5e01956fSGlenn Barry static int save_error_string_nocopy(OM_uint32 minor_code, char *msg)
80*5e01956fSGlenn Barry {
81*5e01956fSGlenn Barry     gsserrmap *p;
82*5e01956fSGlenn Barry     int ret;
83*5e01956fSGlenn Barry 
84*5e01956fSGlenn Barry #ifdef DEBUG
85*5e01956fSGlenn Barry     fprintf(stderr, "%s(%lu, %s)", __func__, (unsigned long) minor_code, msg);
86*5e01956fSGlenn Barry #endif
87*5e01956fSGlenn Barry     p = k5_getspecific(K5_KEY_GSS_KRB5_ERROR_MESSAGE);
88*5e01956fSGlenn Barry     if (!p) {
89*5e01956fSGlenn Barry         p = malloc(sizeof(*p));
90*5e01956fSGlenn Barry         if (p == NULL) {
91*5e01956fSGlenn Barry             ret = 1;
92*5e01956fSGlenn Barry             goto fail;
93*5e01956fSGlenn Barry         }
94*5e01956fSGlenn Barry         if (gsserrmap_init(p) != 0) {
95*5e01956fSGlenn Barry             free(p);
96*5e01956fSGlenn Barry             p = NULL;
97*5e01956fSGlenn Barry             ret = 1;
98*5e01956fSGlenn Barry             goto fail;
99*5e01956fSGlenn Barry         }
100*5e01956fSGlenn Barry         if (k5_setspecific(K5_KEY_GSS_KRB5_ERROR_MESSAGE, p) != 0) {
101*5e01956fSGlenn Barry             gsserrmap_destroy(p);
102*5e01956fSGlenn Barry             free(p);
103*5e01956fSGlenn Barry             p = NULL;
104*5e01956fSGlenn Barry             ret = 1;
105*5e01956fSGlenn Barry             goto fail;
106*5e01956fSGlenn Barry         }
107*5e01956fSGlenn Barry     }
108*5e01956fSGlenn Barry     ret = gsserrmap_replace_or_insert(p, minor_code, msg);
109*5e01956fSGlenn Barry     /* Solaris Kerberos */
110*5e01956fSGlenn Barry     if (ret) {
111*5e01956fSGlenn Barry             gsserrmap_destroy(p);
112*5e01956fSGlenn Barry             free(p);
113*5e01956fSGlenn Barry             p = NULL;
114*5e01956fSGlenn Barry     }
115*5e01956fSGlenn Barry 
116*5e01956fSGlenn Barry fail:
117*5e01956fSGlenn Barry #ifdef DEBUG
118*5e01956fSGlenn Barry     fprintf(stderr, " p=%p %s\n", (void *)p, ret ? "FAIL" : "SUCCESS");
119*5e01956fSGlenn Barry #endif
120*5e01956fSGlenn Barry     return ret;
121*5e01956fSGlenn Barry }
save_error_string(OM_uint32 minor_code,char * msg)122*5e01956fSGlenn Barry void save_error_string(OM_uint32 minor_code, char *msg)
123*5e01956fSGlenn Barry {
124*5e01956fSGlenn Barry     char *s = strdup(msg);
125*5e01956fSGlenn Barry     if (s) {
126*5e01956fSGlenn Barry         if (save_error_string_nocopy(minor_code, s) != 0)
127*5e01956fSGlenn Barry             free(s);
128*5e01956fSGlenn Barry     }
129*5e01956fSGlenn Barry }
save_error_message(OM_uint32 minor_code,const char * format,...)130*5e01956fSGlenn Barry void save_error_message(OM_uint32 minor_code, const char *format, ...)
131*5e01956fSGlenn Barry {
132*5e01956fSGlenn Barry     char *s;
133*5e01956fSGlenn Barry     int n;
134*5e01956fSGlenn Barry     va_list ap;
135*5e01956fSGlenn Barry 
136*5e01956fSGlenn Barry     va_start(ap, format);
137*5e01956fSGlenn Barry     n = vasprintf(&s, format, ap);
138*5e01956fSGlenn Barry     va_end(ap);
139*5e01956fSGlenn Barry     if (n >= 0) {
140*5e01956fSGlenn Barry         if (save_error_string_nocopy(minor_code, s) != 0)
141*5e01956fSGlenn Barry             free(s);
142*5e01956fSGlenn Barry     }
143*5e01956fSGlenn Barry }
krb5_gss_save_error_info(OM_uint32 minor_code,krb5_context ctx)144*5e01956fSGlenn Barry void krb5_gss_save_error_info(OM_uint32 minor_code, krb5_context ctx)
145*5e01956fSGlenn Barry {
146*5e01956fSGlenn Barry     char *s;
147*5e01956fSGlenn Barry 
148*5e01956fSGlenn Barry #ifdef DEBUG
149*5e01956fSGlenn Barry     fprintf(stderr, "%s(%lu, ctx=%p)\n", __func__,
150*5e01956fSGlenn Barry             (unsigned long) minor_code, (void *)ctx);
151*5e01956fSGlenn Barry #endif
152*5e01956fSGlenn Barry     s = (char *)krb5_get_error_message(ctx, (krb5_error_code)minor_code);
153*5e01956fSGlenn Barry #ifdef DEBUG
154*5e01956fSGlenn Barry     fprintf(stderr, "%s(%lu, ctx=%p) saving: %s\n", __func__,
155*5e01956fSGlenn Barry             (unsigned long) minor_code, (void *)ctx, s);
156*5e01956fSGlenn Barry #endif
157*5e01956fSGlenn Barry     save_error_string(minor_code, s);
158*5e01956fSGlenn Barry     /* The get_error_message call above resets the error message in
159*5e01956fSGlenn Barry        ctx.  Put it back, in case we make this call again *sigh*.  */
160*5e01956fSGlenn Barry     krb5_set_error_message(ctx, (krb5_error_code)minor_code, "%s", s);
161*5e01956fSGlenn Barry     krb5_free_error_message(ctx, s);
162*5e01956fSGlenn Barry }
krb5_gss_delete_error_info(void * p)163*5e01956fSGlenn Barry void krb5_gss_delete_error_info(void *p)
164*5e01956fSGlenn Barry {
165*5e01956fSGlenn Barry     gsserrmap_destroy(p);
166*5e01956fSGlenn Barry }
167*5e01956fSGlenn Barry 
168ab9b2e15Sgtb /**/
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate OM_uint32
krb5_gss_display_status(minor_status,status_value,status_type,mech_type,message_context,status_string)171ab9b2e15Sgtb krb5_gss_display_status(minor_status, status_value, status_type,
1727c478bd9Sstevel@tonic-gate                         mech_type, message_context, status_string)
1737c478bd9Sstevel@tonic-gate     OM_uint32 *minor_status;
1747c478bd9Sstevel@tonic-gate     OM_uint32 status_value;
1757c478bd9Sstevel@tonic-gate     int status_type;
1767c478bd9Sstevel@tonic-gate     gss_OID mech_type;
1777c478bd9Sstevel@tonic-gate     OM_uint32 *message_context;
1787c478bd9Sstevel@tonic-gate     gss_buffer_t status_string;
1797c478bd9Sstevel@tonic-gate {
1807c478bd9Sstevel@tonic-gate     status_string->length = 0;
1817c478bd9Sstevel@tonic-gate     status_string->value = NULL;
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate     if ((mech_type != GSS_C_NULL_OID) &&
1847c478bd9Sstevel@tonic-gate         !g_OID_equal(gss_mech_krb5, mech_type) &&
1857c478bd9Sstevel@tonic-gate         !g_OID_equal(gss_mech_krb5_old, mech_type)) {
1867c478bd9Sstevel@tonic-gate         *minor_status = 0;
1877c478bd9Sstevel@tonic-gate         return(GSS_S_BAD_MECH);
1887c478bd9Sstevel@tonic-gate     }
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate     if (status_type == GSS_C_GSS_CODE) {
191ab9b2e15Sgtb         return(g_display_major_status(minor_status, status_value,
192ab9b2e15Sgtb                                       message_context, status_string));
1937c478bd9Sstevel@tonic-gate     } else if (status_type == GSS_C_MECH_CODE) {
194*5e01956fSGlenn Barry         (void) gss_krb5int_initialize_library();
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate         if (*message_context) {
1977c478bd9Sstevel@tonic-gate             *minor_status = (OM_uint32) G_BAD_MSG_CTX;
1987c478bd9Sstevel@tonic-gate             return(GSS_S_FAILURE);
1997c478bd9Sstevel@tonic-gate         }
2007c478bd9Sstevel@tonic-gate 
201*5e01956fSGlenn Barry         /* If this fails, there's not much we can do...  */
202*5e01956fSGlenn Barry         /* Solaris Kerberos - cleaned-up/fixed the return checks/values here */
203*5e01956fSGlenn Barry         if (!g_make_string_buffer(krb5_gss_get_error_message(status_value),
204*5e01956fSGlenn Barry                                  status_string)) {
205*5e01956fSGlenn Barry             *minor_status = ENOMEM;
206*5e01956fSGlenn Barry             return(GSS_S_FAILURE);
207*5e01956fSGlenn Barry         }
208*5e01956fSGlenn Barry         *minor_status = 0;
209*5e01956fSGlenn Barry         return(GSS_S_COMPLETE);
2107c478bd9Sstevel@tonic-gate     } else {
2117c478bd9Sstevel@tonic-gate         *minor_status = 0;
2127c478bd9Sstevel@tonic-gate         return(GSS_S_BAD_STATUS);
2137c478bd9Sstevel@tonic-gate     }
2147c478bd9Sstevel@tonic-gate }
215*5e01956fSGlenn Barry 
216*5e01956fSGlenn Barry /*
217*5e01956fSGlenn Barry  * Solaris Kerberos
218*5e01956fSGlenn Barry  * Hack alert: workaround obfusicated func name issues for mech_spnego.so.
219*5e01956fSGlenn Barry  */
220*5e01956fSGlenn Barry OM_uint32
krb5_gss_display_status2(minor_status,status_value,status_type,mech_type,message_context,status_string)221*5e01956fSGlenn Barry krb5_gss_display_status2(minor_status, status_value, status_type,
222*5e01956fSGlenn Barry                         mech_type, message_context, status_string)
223*5e01956fSGlenn Barry     OM_uint32 *minor_status;
224*5e01956fSGlenn Barry     OM_uint32 status_value;
225*5e01956fSGlenn Barry     int status_type;
226*5e01956fSGlenn Barry     gss_OID mech_type;
227*5e01956fSGlenn Barry     OM_uint32 *message_context;
228*5e01956fSGlenn Barry     gss_buffer_t status_string;
229*5e01956fSGlenn Barry {
230*5e01956fSGlenn Barry         return(krb5_gss_display_status(minor_status, status_value,
231*5e01956fSGlenn Barry  				  status_type, mech_type, message_context,
232*5e01956fSGlenn Barry  				  status_string));
233*5e01956fSGlenn Barry }
234