1*13132SGlenn.Barry@oracle.com /* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */
2*13132SGlenn.Barry@oracle.com /* -*- mode: c; indent-tabs-mode: nil -*- */
3*13132SGlenn.Barry@oracle.com /*
4*13132SGlenn.Barry@oracle.com * Copyright 2007, 2008 by the Massachusetts Institute of Technology.
5*13132SGlenn.Barry@oracle.com * All Rights Reserved.
6*13132SGlenn.Barry@oracle.com *
7*13132SGlenn.Barry@oracle.com * Export of this software from the United States of America may
8*13132SGlenn.Barry@oracle.com * require a specific license from the United States Government.
9*13132SGlenn.Barry@oracle.com * It is the responsibility of any person or organization contemplating
10*13132SGlenn.Barry@oracle.com * export to obtain such a license before exporting.
11*13132SGlenn.Barry@oracle.com *
12*13132SGlenn.Barry@oracle.com * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13*13132SGlenn.Barry@oracle.com * distribute this software and its documentation for any purpose and
14*13132SGlenn.Barry@oracle.com * without fee is hereby granted, provided that the above copyright
15*13132SGlenn.Barry@oracle.com * notice appear in all copies and that both that copyright notice and
16*13132SGlenn.Barry@oracle.com * this permission notice appear in supporting documentation, and that
17*13132SGlenn.Barry@oracle.com * the name of M.I.T. not be used in advertising or publicity pertaining
18*13132SGlenn.Barry@oracle.com * to distribution of the software without specific, written prior
19*13132SGlenn.Barry@oracle.com * permission. Furthermore if you modify this software you must label
20*13132SGlenn.Barry@oracle.com * your software as modified software and not distribute it in such a
21*13132SGlenn.Barry@oracle.com * fashion that it might be confused with the original M.I.T. software.
22*13132SGlenn.Barry@oracle.com * M.I.T. makes no representations about the suitability of
23*13132SGlenn.Barry@oracle.com * this software for any purpose. It is provided "as is" without express
24*13132SGlenn.Barry@oracle.com * or implied warranty.
25*13132SGlenn.Barry@oracle.com *
26*13132SGlenn.Barry@oracle.com */
27*13132SGlenn.Barry@oracle.com
28*13132SGlenn.Barry@oracle.com #include "gssapiP_generic.h"
29*13132SGlenn.Barry@oracle.com #include "mechglueP.h"
30*13132SGlenn.Barry@oracle.com #include <string.h>
31*13132SGlenn.Barry@oracle.com #include <stdio.h>
32*13132SGlenn.Barry@oracle.com #ifndef _WIN32
33*13132SGlenn.Barry@oracle.com #include <unistd.h>
34*13132SGlenn.Barry@oracle.com #endif
35*13132SGlenn.Barry@oracle.com
36*13132SGlenn.Barry@oracle.com /* Solaris Kerberos */
37*13132SGlenn.Barry@oracle.com #define inline
38*13132SGlenn.Barry@oracle.com #ifdef DEBUG
39*13132SGlenn.Barry@oracle.com #undef DEBUG
40*13132SGlenn.Barry@oracle.com #endif
41*13132SGlenn.Barry@oracle.com
42*13132SGlenn.Barry@oracle.com /* The mapping table is 0-based, but let's export codes that are
43*13132SGlenn.Barry@oracle.com 1-based, keeping 0 for errors or unknown errors.
44*13132SGlenn.Barry@oracle.com
45*13132SGlenn.Barry@oracle.com The elements in the mapping table currently have separate copies of
46*13132SGlenn.Barry@oracle.com each OID stored. This is a bit wasteful, but we are assuming the
47*13132SGlenn.Barry@oracle.com table isn't likely to grow very large. */
48*13132SGlenn.Barry@oracle.com
49*13132SGlenn.Barry@oracle.com struct mecherror {
50*13132SGlenn.Barry@oracle.com gss_OID_desc mech;
51*13132SGlenn.Barry@oracle.com OM_uint32 code;
52*13132SGlenn.Barry@oracle.com };
53*13132SGlenn.Barry@oracle.com
54*13132SGlenn.Barry@oracle.com static inline int
cmp_OM_uint32(OM_uint32 m1,OM_uint32 m2)55*13132SGlenn.Barry@oracle.com cmp_OM_uint32(OM_uint32 m1, OM_uint32 m2)
56*13132SGlenn.Barry@oracle.com {
57*13132SGlenn.Barry@oracle.com if (m1 < m2)
58*13132SGlenn.Barry@oracle.com return -1;
59*13132SGlenn.Barry@oracle.com else if (m1 > m2)
60*13132SGlenn.Barry@oracle.com return 1;
61*13132SGlenn.Barry@oracle.com else
62*13132SGlenn.Barry@oracle.com return 0;
63*13132SGlenn.Barry@oracle.com }
64*13132SGlenn.Barry@oracle.com
65*13132SGlenn.Barry@oracle.com static inline int
mecherror_cmp(struct mecherror m1,struct mecherror m2)66*13132SGlenn.Barry@oracle.com mecherror_cmp(struct mecherror m1, struct mecherror m2)
67*13132SGlenn.Barry@oracle.com {
68*13132SGlenn.Barry@oracle.com if (m1.code < m2.code)
69*13132SGlenn.Barry@oracle.com return -1;
70*13132SGlenn.Barry@oracle.com if (m1.code > m2.code)
71*13132SGlenn.Barry@oracle.com return 1;
72*13132SGlenn.Barry@oracle.com if (m1.mech.length < m2.mech.length)
73*13132SGlenn.Barry@oracle.com return -1;
74*13132SGlenn.Barry@oracle.com if (m1.mech.length > m2.mech.length)
75*13132SGlenn.Barry@oracle.com return 1;
76*13132SGlenn.Barry@oracle.com if (m1.mech.length == 0)
77*13132SGlenn.Barry@oracle.com return 0;
78*13132SGlenn.Barry@oracle.com return memcmp(m1.mech.elements, m2.mech.elements, m1.mech.length);
79*13132SGlenn.Barry@oracle.com }
80*13132SGlenn.Barry@oracle.com
81*13132SGlenn.Barry@oracle.com static void
print_OM_uint32(OM_uint32 value,FILE * f)82*13132SGlenn.Barry@oracle.com print_OM_uint32 (OM_uint32 value, FILE *f)
83*13132SGlenn.Barry@oracle.com {
84*13132SGlenn.Barry@oracle.com fprintf(f, "%lu", (unsigned long) value);
85*13132SGlenn.Barry@oracle.com }
86*13132SGlenn.Barry@oracle.com
87*13132SGlenn.Barry@oracle.com static inline int
mecherror_copy(struct mecherror * dest,struct mecherror src)88*13132SGlenn.Barry@oracle.com mecherror_copy(struct mecherror *dest, struct mecherror src)
89*13132SGlenn.Barry@oracle.com {
90*13132SGlenn.Barry@oracle.com *dest = src;
91*13132SGlenn.Barry@oracle.com dest->mech.elements = malloc(src.mech.length);
92*13132SGlenn.Barry@oracle.com if (dest->mech.elements == NULL) {
93*13132SGlenn.Barry@oracle.com if (src.mech.length)
94*13132SGlenn.Barry@oracle.com return ENOMEM;
95*13132SGlenn.Barry@oracle.com else
96*13132SGlenn.Barry@oracle.com return 0;
97*13132SGlenn.Barry@oracle.com }
98*13132SGlenn.Barry@oracle.com memcpy(dest->mech.elements, src.mech.elements, src.mech.length);
99*13132SGlenn.Barry@oracle.com return 0;
100*13132SGlenn.Barry@oracle.com }
101*13132SGlenn.Barry@oracle.com
102*13132SGlenn.Barry@oracle.com static void
mecherror_print(struct mecherror value,FILE * f)103*13132SGlenn.Barry@oracle.com mecherror_print(struct mecherror value, FILE *f)
104*13132SGlenn.Barry@oracle.com {
105*13132SGlenn.Barry@oracle.com OM_uint32 minor;
106*13132SGlenn.Barry@oracle.com gss_buffer_desc str;
107*13132SGlenn.Barry@oracle.com static const struct {
108*13132SGlenn.Barry@oracle.com const char *oidstr, *name;
109*13132SGlenn.Barry@oracle.com } mechnames[] = {
110*13132SGlenn.Barry@oracle.com { "{ 1 2 840 113554 1 2 2 }", "krb5-new" },
111*13132SGlenn.Barry@oracle.com { "{ 1 3 5 1 5 2 }", "krb5-old" },
112*13132SGlenn.Barry@oracle.com { "{ 1 2 840 48018 1 2 2 }", "krb5-microsoft" },
113*13132SGlenn.Barry@oracle.com { "{ 1 3 6 1 5 5 2 }", "spnego" },
114*13132SGlenn.Barry@oracle.com };
115*13132SGlenn.Barry@oracle.com unsigned int i;
116*13132SGlenn.Barry@oracle.com
117*13132SGlenn.Barry@oracle.com fprintf(f, "%lu@", (unsigned long) value.code);
118*13132SGlenn.Barry@oracle.com
119*13132SGlenn.Barry@oracle.com if (value.mech.length == 0) {
120*13132SGlenn.Barry@oracle.com fprintf(f, "(com_err)");
121*13132SGlenn.Barry@oracle.com return;
122*13132SGlenn.Barry@oracle.com }
123*13132SGlenn.Barry@oracle.com fprintf(f, "%p=", value.mech.elements);
124*13132SGlenn.Barry@oracle.com if (generic_gss_oid_to_str(&minor, &value.mech, &str)) {
125*13132SGlenn.Barry@oracle.com fprintf(f, "(error in conversion)");
126*13132SGlenn.Barry@oracle.com return;
127*13132SGlenn.Barry@oracle.com }
128*13132SGlenn.Barry@oracle.com /* Note: generic_gss_oid_to_str returns a null-terminated string. */
129*13132SGlenn.Barry@oracle.com for (i = 0; i < sizeof(mechnames)/sizeof(mechnames[0]); i++) {
130*13132SGlenn.Barry@oracle.com if (!strcmp(str.value, mechnames[i].oidstr) && mechnames[i].name != 0) {
131*13132SGlenn.Barry@oracle.com fprintf(f, "%s", mechnames[i].name);
132*13132SGlenn.Barry@oracle.com break;
133*13132SGlenn.Barry@oracle.com }
134*13132SGlenn.Barry@oracle.com }
135*13132SGlenn.Barry@oracle.com if (i == sizeof(mechnames)/sizeof(mechnames[0]))
136*13132SGlenn.Barry@oracle.com fprintf(f, "%s", (char *) str.value);
137*13132SGlenn.Barry@oracle.com generic_gss_release_buffer(&minor, &str);
138*13132SGlenn.Barry@oracle.com }
139*13132SGlenn.Barry@oracle.com
140*13132SGlenn.Barry@oracle.com #include "errmap.h"
141*13132SGlenn.Barry@oracle.com #include "krb5.h" /* for KRB5KRB_AP_WRONG_PRINC */
142*13132SGlenn.Barry@oracle.com
143*13132SGlenn.Barry@oracle.com static mecherrmap m;
144*13132SGlenn.Barry@oracle.com static k5_mutex_t mutex = K5_MUTEX_PARTIAL_INITIALIZER;
145*13132SGlenn.Barry@oracle.com static OM_uint32 next_fake = 100000;
146*13132SGlenn.Barry@oracle.com
gssint_mecherrmap_init(void)147*13132SGlenn.Barry@oracle.com int gssint_mecherrmap_init(void)
148*13132SGlenn.Barry@oracle.com {
149*13132SGlenn.Barry@oracle.com int err;
150*13132SGlenn.Barry@oracle.com
151*13132SGlenn.Barry@oracle.com err = mecherrmap_init(&m);
152*13132SGlenn.Barry@oracle.com if (err)
153*13132SGlenn.Barry@oracle.com return err;
154*13132SGlenn.Barry@oracle.com err = k5_mutex_finish_init(&mutex);
155*13132SGlenn.Barry@oracle.com if (err) {
156*13132SGlenn.Barry@oracle.com mecherrmap_destroy(&m);
157*13132SGlenn.Barry@oracle.com return err;
158*13132SGlenn.Barry@oracle.com }
159*13132SGlenn.Barry@oracle.com
160*13132SGlenn.Barry@oracle.com return 0;
161*13132SGlenn.Barry@oracle.com }
162*13132SGlenn.Barry@oracle.com
163*13132SGlenn.Barry@oracle.com /* Currently the enumeration template doesn't handle freeing
164*13132SGlenn.Barry@oracle.com element storage when destroying the collection. */
free_one(OM_uint32 i,struct mecherror value,void * p)165*13132SGlenn.Barry@oracle.com static int free_one(OM_uint32 i, struct mecherror value, void *p)
166*13132SGlenn.Barry@oracle.com {
167*13132SGlenn.Barry@oracle.com if (value.mech.length && value.mech.elements)
168*13132SGlenn.Barry@oracle.com free(value.mech.elements);
169*13132SGlenn.Barry@oracle.com return 0;
170*13132SGlenn.Barry@oracle.com }
171*13132SGlenn.Barry@oracle.com
gssint_mecherrmap_destroy(void)172*13132SGlenn.Barry@oracle.com void gssint_mecherrmap_destroy(void)
173*13132SGlenn.Barry@oracle.com {
174*13132SGlenn.Barry@oracle.com mecherrmap_foreach(&m, free_one, NULL);
175*13132SGlenn.Barry@oracle.com mecherrmap_destroy(&m);
176*13132SGlenn.Barry@oracle.com k5_mutex_destroy(&mutex);
177*13132SGlenn.Barry@oracle.com }
178*13132SGlenn.Barry@oracle.com
gssint_mecherrmap_map(OM_uint32 minor,const gss_OID_desc * oid)179*13132SGlenn.Barry@oracle.com OM_uint32 gssint_mecherrmap_map(OM_uint32 minor, const gss_OID_desc * oid)
180*13132SGlenn.Barry@oracle.com {
181*13132SGlenn.Barry@oracle.com const struct mecherror *mep;
182*13132SGlenn.Barry@oracle.com struct mecherror me, me_copy;
183*13132SGlenn.Barry@oracle.com const OM_uint32 *p;
184*13132SGlenn.Barry@oracle.com int err;
185*13132SGlenn.Barry@oracle.com OM_uint32 new_status;
186*13132SGlenn.Barry@oracle.com
187*13132SGlenn.Barry@oracle.com #ifdef DEBUG
188*13132SGlenn.Barry@oracle.com FILE *f;
189*13132SGlenn.Barry@oracle.com f = fopen("/dev/pts/9", "w+");
190*13132SGlenn.Barry@oracle.com if (f == NULL)
191*13132SGlenn.Barry@oracle.com f = stderr;
192*13132SGlenn.Barry@oracle.com #endif
193*13132SGlenn.Barry@oracle.com
194*13132SGlenn.Barry@oracle.com me.code = minor;
195*13132SGlenn.Barry@oracle.com me.mech = *oid;
196*13132SGlenn.Barry@oracle.com err = k5_mutex_lock(&mutex);
197*13132SGlenn.Barry@oracle.com if (err) {
198*13132SGlenn.Barry@oracle.com #ifdef DEBUG
199*13132SGlenn.Barry@oracle.com if (f != stderr) fclose(f);
200*13132SGlenn.Barry@oracle.com #endif
201*13132SGlenn.Barry@oracle.com return 0;
202*13132SGlenn.Barry@oracle.com }
203*13132SGlenn.Barry@oracle.com
204*13132SGlenn.Barry@oracle.com /* Is this status+oid already mapped? */
205*13132SGlenn.Barry@oracle.com p = mecherrmap_findright(&m, me);
206*13132SGlenn.Barry@oracle.com if (p != NULL) {
207*13132SGlenn.Barry@oracle.com k5_mutex_unlock(&mutex);
208*13132SGlenn.Barry@oracle.com #ifdef DEBUG
209*13132SGlenn.Barry@oracle.com fprintf(f, "%s: found ", __func__);
210*13132SGlenn.Barry@oracle.com mecherror_print(me, f);
211*13132SGlenn.Barry@oracle.com fprintf(f, " in map as %lu\n", (unsigned long) *p);
212*13132SGlenn.Barry@oracle.com if (f != stderr) fclose(f);
213*13132SGlenn.Barry@oracle.com #endif
214*13132SGlenn.Barry@oracle.com return *p;
215*13132SGlenn.Barry@oracle.com }
216*13132SGlenn.Barry@oracle.com /* Is this status code already mapped to something else
217*13132SGlenn.Barry@oracle.com mech-specific? */
218*13132SGlenn.Barry@oracle.com mep = mecherrmap_findleft(&m, minor);
219*13132SGlenn.Barry@oracle.com if (mep == NULL) {
220*13132SGlenn.Barry@oracle.com /* Map it to itself plus this mech-oid. */
221*13132SGlenn.Barry@oracle.com new_status = minor;
222*13132SGlenn.Barry@oracle.com } else {
223*13132SGlenn.Barry@oracle.com /* Already assigned. Pick a fake new value and map it. */
224*13132SGlenn.Barry@oracle.com /* There's a theoretical infinite loop risk here, if we fill
225*13132SGlenn.Barry@oracle.com in 2**32 values. Also, returning 0 has a special
226*13132SGlenn.Barry@oracle.com meaning. */
227*13132SGlenn.Barry@oracle.com do {
228*13132SGlenn.Barry@oracle.com next_fake++;
229*13132SGlenn.Barry@oracle.com new_status = next_fake;
230*13132SGlenn.Barry@oracle.com if (new_status == 0)
231*13132SGlenn.Barry@oracle.com /* ??? */;
232*13132SGlenn.Barry@oracle.com } while (mecherrmap_findleft(&m, new_status) != NULL);
233*13132SGlenn.Barry@oracle.com }
234*13132SGlenn.Barry@oracle.com err = mecherror_copy(&me_copy, me);
235*13132SGlenn.Barry@oracle.com if (err) {
236*13132SGlenn.Barry@oracle.com k5_mutex_unlock(&mutex);
237*13132SGlenn.Barry@oracle.com return err;
238*13132SGlenn.Barry@oracle.com }
239*13132SGlenn.Barry@oracle.com err = mecherrmap_add(&m, new_status, me_copy);
240*13132SGlenn.Barry@oracle.com k5_mutex_unlock(&mutex);
241*13132SGlenn.Barry@oracle.com if (err) {
242*13132SGlenn.Barry@oracle.com if (me_copy.mech.length)
243*13132SGlenn.Barry@oracle.com free(me_copy.mech.elements);
244*13132SGlenn.Barry@oracle.com }
245*13132SGlenn.Barry@oracle.com #ifdef DEBUG
246*13132SGlenn.Barry@oracle.com fprintf(f, "%s: mapping ", __func__);
247*13132SGlenn.Barry@oracle.com mecherror_print(me, f);
248*13132SGlenn.Barry@oracle.com fprintf(f, " to %lu: err=%d\nnew map: ", (unsigned long) new_status, err);
249*13132SGlenn.Barry@oracle.com mecherrmap_printmap(&m, f);
250*13132SGlenn.Barry@oracle.com fprintf(f, "\n");
251*13132SGlenn.Barry@oracle.com if (f != stderr) fclose(f);
252*13132SGlenn.Barry@oracle.com #endif
253*13132SGlenn.Barry@oracle.com
254*13132SGlenn.Barry@oracle.com if (err)
255*13132SGlenn.Barry@oracle.com return 0;
256*13132SGlenn.Barry@oracle.com else
257*13132SGlenn.Barry@oracle.com return new_status;
258*13132SGlenn.Barry@oracle.com }
259*13132SGlenn.Barry@oracle.com
260*13132SGlenn.Barry@oracle.com static gss_OID_desc no_oid = { 0, 0 };
gssint_mecherrmap_map_errcode(OM_uint32 errcode)261*13132SGlenn.Barry@oracle.com OM_uint32 gssint_mecherrmap_map_errcode(OM_uint32 errcode)
262*13132SGlenn.Barry@oracle.com {
263*13132SGlenn.Barry@oracle.com return gssint_mecherrmap_map(errcode, &no_oid);
264*13132SGlenn.Barry@oracle.com }
265*13132SGlenn.Barry@oracle.com
gssint_mecherrmap_get(OM_uint32 minor,gss_OID mech_oid,OM_uint32 * mech_minor)266*13132SGlenn.Barry@oracle.com int gssint_mecherrmap_get(OM_uint32 minor, gss_OID mech_oid,
267*13132SGlenn.Barry@oracle.com OM_uint32 *mech_minor)
268*13132SGlenn.Barry@oracle.com {
269*13132SGlenn.Barry@oracle.com const struct mecherror *p;
270*13132SGlenn.Barry@oracle.com int err;
271*13132SGlenn.Barry@oracle.com
272*13132SGlenn.Barry@oracle.com if (minor == 0) {
273*13132SGlenn.Barry@oracle.com return EINVAL;
274*13132SGlenn.Barry@oracle.com }
275*13132SGlenn.Barry@oracle.com err = k5_mutex_lock(&mutex);
276*13132SGlenn.Barry@oracle.com if (err)
277*13132SGlenn.Barry@oracle.com return err;
278*13132SGlenn.Barry@oracle.com p = mecherrmap_findleft(&m, minor);
279*13132SGlenn.Barry@oracle.com k5_mutex_unlock(&mutex);
280*13132SGlenn.Barry@oracle.com if (!p) {
281*13132SGlenn.Barry@oracle.com return EINVAL;
282*13132SGlenn.Barry@oracle.com }
283*13132SGlenn.Barry@oracle.com *mech_oid = p->mech;
284*13132SGlenn.Barry@oracle.com *mech_minor = p->code;
285*13132SGlenn.Barry@oracle.com return 0;
286*13132SGlenn.Barry@oracle.com }
287