~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/heimdal/lib/gssapi/mech/gss_mech_switch.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-
 
2
 * Copyright (c) 2005 Doug Rabson
 
3
 * All rights reserved.
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without
 
6
 * modification, are permitted provided that the following conditions
 
7
 * are met:
 
8
 * 1. Redistributions of source code must retain the above copyright
 
9
 *    notice, this list of conditions and the following disclaimer.
 
10
 * 2. Redistributions in binary form must reproduce the above copyright
 
11
 *    notice, this list of conditions and the following disclaimer in the
 
12
 *    documentation and/or other materials provided with the distribution.
 
13
 *
 
14
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 
15
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
16
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
17
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 
18
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
19
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
20
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
21
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
22
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
23
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
24
 * SUCH DAMAGE.
 
25
 *
 
26
 *      $FreeBSD: src/lib/libgssapi/gss_mech_switch.c,v 1.2 2006/02/04 09:40:21 dfr Exp $
 
27
 */
 
28
 
 
29
#include "mech_locl.h"
 
30
#include <heim_threads.h>
 
31
RCSID("$Id$");
 
32
 
 
33
#ifndef _PATH_GSS_MECH
 
34
#define _PATH_GSS_MECH  "/etc/gss/mech"
 
35
#endif
 
36
 
 
37
struct _gss_mech_switch_list _gss_mechs = { NULL } ;
 
38
gss_OID_set _gss_mech_oids;
 
39
static HEIMDAL_MUTEX _gss_mech_mutex = HEIMDAL_MUTEX_INITIALIZER;
 
40
 
 
41
/*
 
42
 * Convert a string containing an OID in 'dot' form
 
43
 * (e.g. 1.2.840.113554.1.2.2) to a gss_OID.
 
44
 */
 
45
static int
 
46
_gss_string_to_oid(const char* s, gss_OID oid)
 
47
{
 
48
        int                     number_count, i, j;
 
49
        size_t                  byte_count;
 
50
        const char              *p, *q;
 
51
        char                    *res;
 
52
 
 
53
        oid->length = 0;
 
54
        oid->elements = NULL;
 
55
 
 
56
        /*
 
57
         * First figure out how many numbers in the oid, then
 
58
         * calculate the compiled oid size.
 
59
         */
 
60
        number_count = 0;
 
61
        for (p = s; p; p = q) {
 
62
                q = strchr(p, '.');
 
63
                if (q) q = q + 1;
 
64
                number_count++;
 
65
        }
 
66
        
 
67
        /*
 
68
         * The first two numbers are in the first byte and each
 
69
         * subsequent number is encoded in a variable byte sequence.
 
70
         */
 
71
        if (number_count < 2)
 
72
                return (EINVAL);
 
73
 
 
74
        /*
 
75
         * We do this in two passes. The first pass, we just figure
 
76
         * out the size. Second time around, we actually encode the
 
77
         * number.
 
78
         */
 
79
        res = 0;
 
80
        for (i = 0; i < 2; i++) {
 
81
                byte_count = 0;
 
82
                for (p = s, j = 0; p; p = q, j++) {
 
83
                        unsigned int number = 0;
 
84
 
 
85
                        /*
 
86
                         * Find the end of this number.
 
87
                         */
 
88
                        q = strchr(p, '.');
 
89
                        if (q) q = q + 1;
 
90
 
 
91
                        /*
 
92
                         * Read the number of of the string. Don't
 
93
                         * bother with anything except base ten.
 
94
                         */
 
95
                        while (*p && *p != '.') {
 
96
                                number = 10 * number + (*p - '0');
 
97
                                p++;
 
98
                        }
 
99
 
 
100
                        /*
 
101
                         * Encode the number. The first two numbers
 
102
                         * are packed into the first byte. Subsequent
 
103
                         * numbers are encoded in bytes seven bits at
 
104
                         * a time with the last byte having the high
 
105
                         * bit set.
 
106
                         */
 
107
                        if (j == 0) {
 
108
                                if (res)
 
109
                                        *res = number * 40;
 
110
                        } else if (j == 1) {
 
111
                                if (res) {
 
112
                                        *res += number;
 
113
                                        res++;
 
114
                                }
 
115
                                byte_count++;
 
116
                        } else if (j >= 2) {
 
117
                                /*
 
118
                                 * The number is encoded in seven bit chunks.
 
119
                                 */
 
120
                                unsigned int t;
 
121
                                unsigned int bytes;
 
122
 
 
123
                                bytes = 0;
 
124
                                for (t = number; t; t >>= 7)
 
125
                                        bytes++;
 
126
                                if (bytes == 0) bytes = 1;
 
127
                                while (bytes) {
 
128
                                        if (res) {
 
129
                                                int bit = 7*(bytes-1);
 
130
                                                
 
131
                                                *res = (number >> bit) & 0x7f;
 
132
                                                if (bytes != 1)
 
133
                                                        *res |= 0x80;
 
134
                                                res++;
 
135
                                        }
 
136
                                        byte_count++;
 
137
                                        bytes--;
 
138
                                }
 
139
                        }
 
140
                }
 
141
                if (!res) {
 
142
                        res = malloc(byte_count);
 
143
                        if (!res)
 
144
                                return (ENOMEM);
 
145
                        oid->length = byte_count;
 
146
                        oid->elements = res;
 
147
                }
 
148
        }
 
149
 
 
150
        return (0);
 
151
}
 
152
 
 
153
#define SYM(name)                                                       \
 
154
do {                                                                    \
 
155
        m->gm_mech.gm_ ## name = dlsym(so, "gss_" #name);               \
 
156
        if (!m->gm_mech.gm_ ## name) {                                  \
 
157
                fprintf(stderr, "can't find symbol gss_" #name "\n");   \
 
158
                goto bad;                                               \
 
159
        }                                                               \
 
160
} while (0)
 
161
 
 
162
#define OPTSYM(name)                                                    \
 
163
do {                                                                    \
 
164
        m->gm_mech.gm_ ## name = dlsym(so, "gss_" #name);                       \
 
165
} while (0)
 
166
 
 
167
/*
 
168
 *
 
169
 */
 
170
static int
 
171
add_builtin(gssapi_mech_interface mech)
 
172
{
 
173
    struct _gss_mech_switch *m;
 
174
    OM_uint32 minor_status;
 
175
 
 
176
    /* not registering any mech is ok */
 
177
    if (mech == NULL)
 
178
        return 0;
 
179
 
 
180
    m = malloc(sizeof(*m));
 
181
    if (m == NULL)
 
182
        return 1;
 
183
    m->gm_so = NULL;
 
184
    m->gm_mech = *mech;
 
185
    m->gm_mech_oid = mech->gm_mech_oid; /* XXX */
 
186
    gss_add_oid_set_member(&minor_status,
 
187
                           &m->gm_mech.gm_mech_oid, &_gss_mech_oids);
 
188
 
 
189
    SLIST_INSERT_HEAD(&_gss_mechs, m, gm_link);
 
190
    return 0;
 
191
}
 
192
 
 
193
/*
 
194
 * Load the mechanisms file (/etc/gss/mech).
 
195
 */
 
196
void
 
197
_gss_load_mech(void)
 
198
{
 
199
        OM_uint32       major_status, minor_status;
 
200
        FILE            *fp;
 
201
        char            buf[256];
 
202
        char            *p;
 
203
        char            *name, *oid, *lib, *kobj;
 
204
        struct _gss_mech_switch *m;
 
205
        void            *so;
 
206
 
 
207
 
 
208
        HEIMDAL_MUTEX_lock(&_gss_mech_mutex);
 
209
 
 
210
        if (SLIST_FIRST(&_gss_mechs)) {
 
211
                HEIMDAL_MUTEX_unlock(&_gss_mech_mutex);
 
212
                return;
 
213
        }
 
214
 
 
215
        major_status = gss_create_empty_oid_set(&minor_status,
 
216
            &_gss_mech_oids);
 
217
        if (major_status) {
 
218
                HEIMDAL_MUTEX_unlock(&_gss_mech_mutex);
 
219
                return;
 
220
        }
 
221
 
 
222
        add_builtin(__gss_krb5_initialize());
 
223
        add_builtin(__gss_spnego_initialize());
 
224
#ifndef HEIMDAL_SMALLER
 
225
        add_builtin(__gss_ntlm_initialize());
 
226
#endif
 
227
 
 
228
#ifdef HAVE_DLOPEN
 
229
        fp = fopen(_PATH_GSS_MECH, "r");
 
230
        if (!fp) {
 
231
                HEIMDAL_MUTEX_unlock(&_gss_mech_mutex);
 
232
                return;
 
233
        }
 
234
        rk_cloexec_file(fp);
 
235
 
 
236
        while (fgets(buf, sizeof(buf), fp)) {
 
237
                if (*buf == '#')
 
238
                        continue;
 
239
                p = buf;
 
240
                name = strsep(&p, "\t\n ");
 
241
                if (p) while (isspace((unsigned char)*p)) p++;
 
242
                oid = strsep(&p, "\t\n ");
 
243
                if (p) while (isspace((unsigned char)*p)) p++;
 
244
                lib = strsep(&p, "\t\n ");
 
245
                if (p) while (isspace((unsigned char)*p)) p++;
 
246
                kobj = strsep(&p, "\t\n ");
 
247
                if (!name || !oid || !lib || !kobj)
 
248
                        continue;
 
249
 
 
250
#ifndef RTLD_LOCAL
 
251
#define RTLD_LOCAL 0
 
252
#endif
 
253
 
 
254
                so = dlopen(lib, RTLD_LAZY | RTLD_LOCAL);
 
255
                if (!so) {
 
256
/*                      fprintf(stderr, "dlopen: %s\n", dlerror()); */
 
257
                        continue;
 
258
                }
 
259
 
 
260
                m = malloc(sizeof(*m));
 
261
                if (!m)
 
262
                        break;
 
263
                m->gm_so = so;
 
264
                if (_gss_string_to_oid(oid, &m->gm_mech.gm_mech_oid)) {
 
265
                        free(m);
 
266
                        continue;
 
267
                }
 
268
                
 
269
                major_status = gss_add_oid_set_member(&minor_status,
 
270
                    &m->gm_mech.gm_mech_oid, &_gss_mech_oids);
 
271
                if (major_status) {
 
272
                        free(m->gm_mech.gm_mech_oid.elements);
 
273
                        free(m);
 
274
                        continue;
 
275
                }
 
276
 
 
277
                SYM(acquire_cred);
 
278
                SYM(release_cred);
 
279
                SYM(init_sec_context);
 
280
                SYM(accept_sec_context);
 
281
                SYM(process_context_token);
 
282
                SYM(delete_sec_context);
 
283
                SYM(context_time);
 
284
                SYM(get_mic);
 
285
                SYM(verify_mic);
 
286
                SYM(wrap);
 
287
                SYM(unwrap);
 
288
                SYM(display_status);
 
289
                SYM(indicate_mechs);
 
290
                SYM(compare_name);
 
291
                SYM(display_name);
 
292
                SYM(import_name);
 
293
                SYM(export_name);
 
294
                SYM(release_name);
 
295
                SYM(inquire_cred);
 
296
                SYM(inquire_context);
 
297
                SYM(wrap_size_limit);
 
298
                SYM(add_cred);
 
299
                SYM(inquire_cred_by_mech);
 
300
                SYM(export_sec_context);
 
301
                SYM(import_sec_context);
 
302
                SYM(inquire_names_for_mech);
 
303
                SYM(inquire_mechs_for_name);
 
304
                SYM(canonicalize_name);
 
305
                SYM(duplicate_name);
 
306
                OPTSYM(inquire_cred_by_oid);
 
307
                OPTSYM(inquire_sec_context_by_oid);
 
308
                OPTSYM(set_sec_context_option);
 
309
                OPTSYM(set_cred_option);
 
310
                OPTSYM(pseudo_random);
 
311
 
 
312
                SLIST_INSERT_HEAD(&_gss_mechs, m, gm_link);
 
313
                continue;
 
314
 
 
315
        bad:
 
316
                free(m->gm_mech.gm_mech_oid.elements);
 
317
                free(m);
 
318
                dlclose(so);
 
319
                continue;
 
320
        }
 
321
        fclose(fp);
 
322
#endif
 
323
        HEIMDAL_MUTEX_unlock(&_gss_mech_mutex);
 
324
}
 
325
 
 
326
gssapi_mech_interface
 
327
__gss_get_mechanism(gss_OID mech)
 
328
{
 
329
        struct _gss_mech_switch *m;
 
330
 
 
331
        _gss_load_mech();
 
332
        SLIST_FOREACH(m, &_gss_mechs, gm_link) {
 
333
                if (gss_oid_equal(&m->gm_mech.gm_mech_oid, mech))
 
334
                        return &m->gm_mech;
 
335
        }
 
336
        return NULL;
 
337
}