Coverage Report

Created: 2025-11-03 06:53

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/krb5/src/lib/gssapi/krb5/gssapi_krb5.c
Line
Count
Source
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
/*
25
 * Copyright (C) 1998 by the FundsXpress, INC.
26
 *
27
 * All rights reserved.
28
 *
29
 * Export of this software from the United States of America may require
30
 * a specific license from the United States Government.  It is the
31
 * responsibility of any person or organization contemplating export to
32
 * obtain such a license before exporting.
33
 *
34
 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
35
 * distribute this software and its documentation for any purpose and
36
 * without fee is hereby granted, provided that the above copyright
37
 * notice appear in all copies and that both that copyright notice and
38
 * this permission notice appear in supporting documentation, and that
39
 * the name of FundsXpress. not be used in advertising or publicity pertaining
40
 * to distribution of the software without specific, written prior
41
 * permission.  FundsXpress makes no representations about the suitability of
42
 * this software for any purpose.  It is provided "as is" without express
43
 * or implied warranty.
44
 *
45
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
46
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
47
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
48
 */
49
/*
50
 * Copyright (c) 2006-2008, Novell, Inc.
51
 * All rights reserved.
52
 *
53
 * Redistribution and use in source and binary forms, with or without
54
 * modification, are permitted provided that the following conditions are met:
55
 *
56
 *   * Redistributions of source code must retain the above copyright notice,
57
 *       this list of conditions and the following disclaimer.
58
 *   * Redistributions in binary form must reproduce the above copyright
59
 *       notice, this list of conditions and the following disclaimer in the
60
 *       documentation and/or other materials provided with the distribution.
61
 *   * The copyright holder's name is not used to endorse or promote products
62
 *       derived from this software without specific prior written permission.
63
 *
64
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
65
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
66
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
67
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
68
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
69
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
70
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
71
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
72
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
73
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
74
 * POSSIBILITY OF SUCH DAMAGE.
75
 */
76
77
/*
78
 * $Id$
79
 */
80
81
82
#include "gssapiP_krb5.h"
83
#include "mglueP.h"
84
85
#ifndef NO_PASSWORD
86
#include <pwd.h>
87
#endif
88
89
/** exported constants defined in gssapi_krb5{,_nx}.h **/
90
91
/* these are bogus, but will compile */
92
93
/*
94
 * The OID of the draft krb5 mechanism, assigned by IETF, is:
95
 *      iso(1) org(3) dod(5) internet(1) security(5)
96
 *      kerberosv5(2) = 1.3.5.1.5.2
97
 * The OID of the krb5_name type is:
98
 *      iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
99
 *      krb5(2) krb5_name(1) = 1.2.840.113554.1.2.2.1
100
 * The OID of the krb5_principal type is:
101
 *      iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
102
 *      krb5(2) krb5_principal(2) = 1.2.840.113554.1.2.2.2
103
 * The OID of the proposed standard krb5 mechanism is:
104
 *      iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
105
 *      krb5(2) = 1.2.840.113554.1.2.2
106
 * The OID of the proposed standard krb5 v2 mechanism is:
107
 *      iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
108
 *      krb5v2(3) = 1.2.840.113554.1.2.3
109
 * Provisionally reserved for Kerberos session key algorithm
110
 * identifiers is:
111
 *      iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
112
 *      krb5(2) krb5_enctype(4) = 1.2.840.113554.1.2.2.4
113
 * Provisionally reserved for Kerberos mechanism-specific APIs:
114
 *      iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
115
 *      krb5(2) krb5_gssapi_ext(5) = 1.2.840.113554.1.2.2.5
116
 */
117
118
/*
119
 * Encoding rules: The first two values are encoded in one byte as 40
120
 * * value1 + value2.  Subsequent values are encoded base 128, most
121
 * significant digit first, with the high bit (\200) set on all octets
122
 * except the last in each value's encoding.
123
 */
124
125
#define NO_CI_FLAGS_X_OID_LENGTH 6
126
#define NO_CI_FLAGS_X_OID "\x2a\x85\x70\x2b\x0d\x1d"
127
#define GET_CRED_IMPERSONATOR_OID_LENGTH 11
128
#define GET_CRED_IMPERSONATOR_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0e"
129
130
const gss_OID_desc krb5_gss_oid_array[] = {
131
    /* this is the official, rfc-specified OID */
132
    {GSS_MECH_KRB5_OID_LENGTH, GSS_MECH_KRB5_OID},
133
    /* this pre-RFC mech OID */
134
    {GSS_MECH_KRB5_OLD_OID_LENGTH, GSS_MECH_KRB5_OLD_OID},
135
    /* this is the unofficial, incorrect mech OID emitted by MS */
136
    {GSS_MECH_KRB5_WRONG_OID_LENGTH, GSS_MECH_KRB5_WRONG_OID},
137
    /* IAKERB OID */
138
    {GSS_MECH_IAKERB_OID_LENGTH, GSS_MECH_IAKERB_OID},
139
    /* this is the v2 assigned OID */
140
    {9, "\052\206\110\206\367\022\001\002\003"},
141
    /* these two are name type OID's */
142
    /* 2.1.1. Kerberos Principal Name Form:  (rfc 1964)
143
     * This name form shall be represented by the Object Identifier {iso(1)
144
     * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
145
     * krb5(2) krb5_name(1)}.  The recommended symbolic name for this type
146
     * is "GSS_KRB5_NT_PRINCIPAL_NAME". */
147
    {10, "\052\206\110\206\367\022\001\002\002\001"},
148
    /* gss_nt_krb5_principal.  Object identifier for a krb5_principal. Do not use. */
149
    {10, "\052\206\110\206\367\022\001\002\002\002"},
150
    {NO_CI_FLAGS_X_OID_LENGTH, NO_CI_FLAGS_X_OID},
151
    /* this is an inquire cred OID */
152
    {GET_CRED_IMPERSONATOR_OID_LENGTH, GET_CRED_IMPERSONATOR_OID},
153
    /* GSS_KRB5_NT_ENTERPRISE_NAME */
154
    {10, "\052\206\110\206\367\022\001\002\002\006"},
155
    /* GSS_KRB5_NT_X509_CERT */
156
    {10, "\052\206\110\206\367\022\001\002\002\007"},
157
    { 0, 0 }
158
};
159
160
#define kg_oids ((gss_OID)krb5_gss_oid_array)
161
162
const gss_OID gss_mech_krb5             = &kg_oids[0];
163
const gss_OID gss_mech_krb5_old         = &kg_oids[1];
164
const gss_OID gss_mech_krb5_wrong       = &kg_oids[2];
165
const gss_OID gss_mech_iakerb           = &kg_oids[3];
166
167
168
const gss_OID gss_nt_krb5_name                  = &kg_oids[5];
169
const gss_OID gss_nt_krb5_principal             = &kg_oids[6];
170
const gss_OID GSS_KRB5_NT_PRINCIPAL_NAME        = &kg_oids[5];
171
172
const gss_OID GSS_KRB5_CRED_NO_CI_FLAGS_X       = &kg_oids[7];
173
const gss_OID GSS_KRB5_GET_CRED_IMPERSONATOR    = &kg_oids[8];
174
const gss_OID GSS_KRB5_NT_ENTERPRISE_NAME       = &kg_oids[9];
175
const gss_OID GSS_KRB5_NT_X509_CERT             = &kg_oids[10];
176
177
static const gss_OID_set_desc oidsets[] = {
178
    {1, &kg_oids[0]}, /* RFC OID */
179
    {1, &kg_oids[1]}, /* pre-RFC OID */
180
    {3, &kg_oids[0]}, /* all names for krb5 mech */
181
    {4, &kg_oids[0]}, /* all krb5 names and IAKERB */
182
};
183
184
#define kg_oidsets ((gss_OID_set)oidsets)
185
186
const gss_OID_set gss_mech_set_krb5             = &kg_oidsets[0];
187
const gss_OID_set gss_mech_set_krb5_old         = &kg_oidsets[1];
188
const gss_OID_set gss_mech_set_krb5_both        = &kg_oidsets[2];
189
const gss_OID_set kg_all_mechs                  = &kg_oidsets[3];
190
191
/** default credential support */
192
193
/*
194
 * init_sec_context() will explicitly re-acquire default credentials,
195
 * so handling the expiration/invalidation condition here isn't needed.
196
 */
197
OM_uint32
198
kg_get_defcred(OM_uint32 *minor_status, gss_cred_id_t *cred)
199
0
{
200
0
    OM_uint32 major;
201
202
0
    if ((major = krb5_gss_acquire_cred(minor_status,
203
0
                                       (gss_name_t) NULL, GSS_C_INDEFINITE,
204
0
                                       GSS_C_NULL_OID_SET, GSS_C_INITIATE,
205
0
                                       cred, NULL, NULL)) && GSS_ERROR(major)) {
206
0
        return(major);
207
0
    }
208
0
    *minor_status = 0;
209
0
    return(GSS_S_COMPLETE);
210
0
}
211
212
OM_uint32
213
kg_sync_ccache_name (krb5_context context, OM_uint32 *minor_status)
214
0
{
215
0
    OM_uint32 err = 0;
216
217
    /*
218
     * Sync up the context ccache name with the GSSAPI ccache name.
219
     * If kg_ccache_name is NULL -- normal unless someone has called
220
     * gss_krb5_ccache_name() -- then the system default ccache will
221
     * be picked up and used by resetting the context default ccache.
222
     * This is needed for platforms which support multiple ccaches.
223
     */
224
225
0
    if (!err) {
226
        /* if NULL, resets the context default ccache */
227
0
        err = krb5_cc_set_default_name(context,
228
0
                                       (char *) k5_getspecific(K5_KEY_GSS_KRB5_CCACHE_NAME));
229
0
    }
230
231
0
    *minor_status = err;
232
0
    return (*minor_status == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE;
233
0
}
234
235
/* This function returns whether or not the caller set a cccache name.  Used by
236
 * gss_acquire_cred to figure out if the caller wants to only look at this
237
 * ccache or search the cache collection for the desired name */
238
OM_uint32
239
kg_caller_provided_ccache_name (OM_uint32 *minor_status,
240
                                int *out_caller_provided_name)
241
0
{
242
0
    if (out_caller_provided_name) {
243
0
        *out_caller_provided_name =
244
0
            (k5_getspecific(K5_KEY_GSS_KRB5_CCACHE_NAME) != NULL);
245
0
    }
246
247
0
    *minor_status = 0;
248
0
    return GSS_S_COMPLETE;
249
0
}
250
251
OM_uint32
252
kg_get_ccache_name(OM_uint32 *minor_status, char **out_name)
253
0
{
254
0
    char *kg_ccache_name;
255
0
    const char *def_name;
256
0
    OM_uint32 err;
257
0
    krb5_context context;
258
259
0
    *out_name = NULL;
260
261
0
    kg_ccache_name = k5_getspecific(K5_KEY_GSS_KRB5_CCACHE_NAME);
262
0
    if (kg_ccache_name != NULL) {
263
0
        *out_name = strdup(kg_ccache_name);
264
0
        err = (*out_name == NULL) ? ENOMEM : 0;
265
0
    } else {
266
        /* Use the default ccache name. */
267
0
        err = krb5_gss_init_context(&context);
268
0
        if (err)
269
0
            goto cleanup;
270
0
        def_name = krb5_cc_default_name(context);
271
0
        *out_name = (def_name != NULL) ? strdup(def_name) : NULL;
272
0
        err = (*out_name == NULL) ? ENOMEM : 0;
273
0
        krb5_free_context(context);
274
0
    }
275
276
0
cleanup:
277
0
    *minor_status = err;
278
0
    return (*minor_status == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE;
279
0
}
280
281
OM_uint32
282
kg_set_ccache_name (OM_uint32 *minor_status, const char *name)
283
0
{
284
0
    char *new_name = NULL;
285
0
    char *swap = NULL;
286
0
    char *kg_ccache_name;
287
0
    krb5_error_code kerr;
288
289
0
    if (name) {
290
0
        new_name = strdup(name);
291
0
        if (new_name == NULL) {
292
0
            *minor_status = ENOMEM;
293
0
            return GSS_S_FAILURE;
294
0
        }
295
0
    }
296
297
0
    kg_ccache_name = k5_getspecific(K5_KEY_GSS_KRB5_CCACHE_NAME);
298
0
    swap = kg_ccache_name;
299
0
    kg_ccache_name = new_name;
300
0
    new_name = swap;
301
0
    kerr = k5_setspecific(K5_KEY_GSS_KRB5_CCACHE_NAME, kg_ccache_name);
302
0
    if (kerr != 0) {
303
        /* Can't store, so free up the storage.  */
304
0
        free(kg_ccache_name);
305
        /* ??? free(new_name); */
306
0
        *minor_status = kerr;
307
0
        return GSS_S_FAILURE;
308
0
    }
309
310
0
    free (new_name);
311
0
    *minor_status = 0;
312
0
    return GSS_S_COMPLETE;
313
0
}
314
315
#define g_OID_prefix_equal(o1, o2)                                      \
316
0
    (((o1)->length >= (o2)->length) &&                                  \
317
0
     (memcmp((o1)->elements, (o2)->elements, (o2)->length) == 0))
318
319
/*
320
 * gss_inquire_sec_context_by_oid() methods
321
 */
322
static struct {
323
    gss_OID_desc oid;
324
    OM_uint32 (*func)(OM_uint32 *, const gss_ctx_id_t, const gss_OID, gss_buffer_set_t *);
325
} krb5_gss_inquire_sec_context_by_oid_ops[] = {
326
    {
327
        {GSS_KRB5_GET_TKT_FLAGS_OID_LENGTH, GSS_KRB5_GET_TKT_FLAGS_OID},
328
        gss_krb5int_get_tkt_flags
329
    },
330
    {
331
        {GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID_LENGTH, GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID},
332
        gss_krb5int_extract_authz_data_from_sec_context
333
    },
334
    {
335
        {GSS_KRB5_INQ_SSPI_SESSION_KEY_OID_LENGTH, GSS_KRB5_INQ_SSPI_SESSION_KEY_OID},
336
        gss_krb5int_inq_sspi_session_key
337
    },
338
    {
339
        {GSS_KRB5_INQ_ODBC_SESSION_KEY_OID_LENGTH, GSS_KRB5_INQ_ODBC_SESSION_KEY_OID},
340
        gss_krb5int_inq_odbc_session_key
341
    },
342
    {
343
        {GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID_LENGTH, GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID},
344
        gss_krb5int_export_lucid_sec_context
345
    },
346
    {
347
        {GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID_LENGTH, GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID},
348
        gss_krb5int_extract_authtime_from_sec_context
349
    },
350
    {
351
        {GET_SEC_CONTEXT_SASL_SSF_OID_LENGTH, GET_SEC_CONTEXT_SASL_SSF_OID},
352
        gss_krb5int_sec_context_sasl_ssf
353
    }
354
};
355
356
OM_uint32 KRB5_CALLCONV
357
krb5_gss_inquire_sec_context_by_oid (OM_uint32 *minor_status,
358
                                     const gss_ctx_id_t context_handle,
359
                                     const gss_OID desired_object,
360
                                     gss_buffer_set_t *data_set)
361
0
{
362
0
    krb5_gss_ctx_id_rec *ctx;
363
0
    size_t i;
364
365
0
    if (minor_status == NULL)
366
0
        return GSS_S_CALL_INACCESSIBLE_WRITE;
367
368
0
    *minor_status = 0;
369
370
0
    if (desired_object == GSS_C_NO_OID)
371
0
        return GSS_S_CALL_INACCESSIBLE_READ;
372
373
0
    if (data_set == NULL)
374
0
        return GSS_S_CALL_INACCESSIBLE_WRITE;
375
376
0
    *data_set = GSS_C_NO_BUFFER_SET;
377
378
0
    ctx = (krb5_gss_ctx_id_rec *) context_handle;
379
380
0
    if (ctx->terminated || !ctx->established)
381
0
        return GSS_S_NO_CONTEXT;
382
383
0
    for (i = 0; i < sizeof(krb5_gss_inquire_sec_context_by_oid_ops)/
384
0
             sizeof(krb5_gss_inquire_sec_context_by_oid_ops[0]); i++) {
385
0
        if (g_OID_prefix_equal(desired_object, &krb5_gss_inquire_sec_context_by_oid_ops[i].oid)) {
386
0
            return (*krb5_gss_inquire_sec_context_by_oid_ops[i].func)(minor_status,
387
0
                                                                      context_handle,
388
0
                                                                      desired_object,
389
0
                                                                      data_set);
390
0
        }
391
0
    }
392
393
0
    *minor_status = EINVAL;
394
395
0
    return GSS_S_UNAVAILABLE;
396
0
}
397
398
/*
399
 * gss_inquire_cred_by_oid() methods
400
 */
401
402
static struct {
403
    gss_OID_desc oid;
404
    OM_uint32 (*func)(OM_uint32 *, const gss_cred_id_t, const gss_OID, gss_buffer_set_t *);
405
} krb5_gss_inquire_cred_by_oid_ops[] = {
406
    {
407
        {GET_CRED_IMPERSONATOR_OID_LENGTH, GET_CRED_IMPERSONATOR_OID},
408
        gss_krb5int_get_cred_impersonator
409
    }
410
};
411
412
static OM_uint32 KRB5_CALLCONV
413
krb5_gss_inquire_cred_by_oid(OM_uint32 *minor_status,
414
                             const gss_cred_id_t cred_handle,
415
                             const gss_OID desired_object,
416
                             gss_buffer_set_t *data_set)
417
0
{
418
0
    OM_uint32 major_status = GSS_S_FAILURE;
419
0
    size_t i;
420
421
0
    if (minor_status == NULL)
422
0
        return GSS_S_CALL_INACCESSIBLE_WRITE;
423
424
0
    *minor_status = 0;
425
426
0
    if (desired_object == GSS_C_NO_OID)
427
0
        return GSS_S_CALL_INACCESSIBLE_READ;
428
429
0
    if (data_set == NULL)
430
0
        return GSS_S_CALL_INACCESSIBLE_WRITE;
431
432
0
    *data_set = GSS_C_NO_BUFFER_SET;
433
0
    if (cred_handle == GSS_C_NO_CREDENTIAL) {
434
0
        *minor_status = (OM_uint32)KRB5_NOCREDS_SUPPLIED;
435
0
        return GSS_S_NO_CRED;
436
0
    }
437
438
0
    major_status = krb5_gss_validate_cred(minor_status, cred_handle);
439
0
    if (GSS_ERROR(major_status))
440
0
        return major_status;
441
442
0
    for (i = 0; i < sizeof(krb5_gss_inquire_cred_by_oid_ops)/
443
0
             sizeof(krb5_gss_inquire_cred_by_oid_ops[0]); i++) {
444
0
        if (g_OID_prefix_equal(desired_object, &krb5_gss_inquire_cred_by_oid_ops[i].oid)) {
445
0
            return (*krb5_gss_inquire_cred_by_oid_ops[i].func)(minor_status,
446
0
                                                               cred_handle,
447
0
                                                               desired_object,
448
0
                                                               data_set);
449
0
        }
450
0
    }
451
452
0
    *minor_status = EINVAL;
453
454
0
    return GSS_S_UNAVAILABLE;
455
0
}
456
457
OM_uint32 KRB5_CALLCONV
458
krb5_gss_set_sec_context_option (OM_uint32 *minor_status,
459
                                 gss_ctx_id_t *context_handle,
460
                                 const gss_OID desired_object,
461
                                 const gss_buffer_t value)
462
0
{
463
0
    if (minor_status == NULL)
464
0
        return GSS_S_CALL_INACCESSIBLE_WRITE;
465
466
0
    *minor_status = 0;
467
468
0
    if (context_handle == NULL)
469
0
        return GSS_S_CALL_INACCESSIBLE_READ;
470
471
0
    if (desired_object == GSS_C_NO_OID)
472
0
        return GSS_S_CALL_INACCESSIBLE_READ;
473
474
0
    *minor_status = EINVAL;
475
476
0
    return GSS_S_UNAVAILABLE;
477
0
}
478
479
static OM_uint32
480
no_ci_flags(OM_uint32 *minor_status,
481
            gss_cred_id_t *cred_handle,
482
            const gss_OID desired_oid,
483
            const gss_buffer_t value)
484
0
{
485
0
    krb5_gss_cred_id_t cred;
486
487
0
    cred = (krb5_gss_cred_id_t) *cred_handle;
488
0
    cred->suppress_ci_flags = 1;
489
490
0
    *minor_status = 0;
491
0
    return GSS_S_COMPLETE;
492
0
}
493
/*
494
 * gssspi_set_cred_option() methods
495
 */
496
static struct {
497
    gss_OID_desc oid;
498
    OM_uint32 (*func)(OM_uint32 *, gss_cred_id_t *, const gss_OID, const gss_buffer_t);
499
} krb5_gssspi_set_cred_option_ops[] = {
500
    {
501
        {GSS_KRB5_COPY_CCACHE_OID_LENGTH, GSS_KRB5_COPY_CCACHE_OID},
502
        gss_krb5int_copy_ccache
503
    },
504
    {
505
        {GSS_KRB5_SET_ALLOWABLE_ENCTYPES_OID_LENGTH, GSS_KRB5_SET_ALLOWABLE_ENCTYPES_OID},
506
        gss_krb5int_set_allowable_enctypes
507
    },
508
    {
509
        {GSS_KRB5_SET_CRED_RCACHE_OID_LENGTH, GSS_KRB5_SET_CRED_RCACHE_OID},
510
        gss_krb5int_set_cred_rcache
511
    },
512
    {
513
        {GSS_KRB5_IMPORT_CRED_OID_LENGTH, GSS_KRB5_IMPORT_CRED_OID},
514
        gss_krb5int_import_cred
515
    },
516
    {
517
        {NO_CI_FLAGS_X_OID_LENGTH, NO_CI_FLAGS_X_OID},
518
        no_ci_flags
519
    },
520
};
521
522
static OM_uint32 KRB5_CALLCONV
523
krb5_gssspi_set_cred_option(OM_uint32 *minor_status,
524
                            gss_cred_id_t *cred_handle,
525
                            const gss_OID desired_object,
526
                            const gss_buffer_t value)
527
0
{
528
0
    OM_uint32 major_status = GSS_S_FAILURE;
529
0
    size_t i;
530
531
0
    if (minor_status == NULL)
532
0
        return GSS_S_CALL_INACCESSIBLE_WRITE;
533
534
0
    if (cred_handle == NULL)
535
0
        return GSS_S_CALL_INACCESSIBLE_WRITE;
536
537
0
    *minor_status = 0;
538
539
0
    if (desired_object == GSS_C_NO_OID)
540
0
        return GSS_S_CALL_INACCESSIBLE_READ;
541
542
0
    if (*cred_handle != GSS_C_NO_CREDENTIAL) {
543
0
        major_status = krb5_gss_validate_cred(minor_status, *cred_handle);
544
0
        if (GSS_ERROR(major_status))
545
0
            return major_status;
546
0
    }
547
548
0
    for (i = 0; i < sizeof(krb5_gssspi_set_cred_option_ops)/
549
0
             sizeof(krb5_gssspi_set_cred_option_ops[0]); i++) {
550
0
        if (g_OID_prefix_equal(desired_object, &krb5_gssspi_set_cred_option_ops[i].oid)) {
551
0
            return (*krb5_gssspi_set_cred_option_ops[i].func)(minor_status,
552
0
                                                              cred_handle,
553
0
                                                              desired_object,
554
0
                                                              value);
555
0
        }
556
0
    }
557
558
0
    *minor_status = EINVAL;
559
560
0
    return GSS_S_UNAVAILABLE;
561
0
}
562
563
/*
564
 * gssspi_mech_invoke() methods
565
 */
566
static struct {
567
    gss_OID_desc oid;
568
    OM_uint32 (*func)(OM_uint32 *, const gss_OID, const gss_OID, gss_buffer_t);
569
} krb5_gssspi_mech_invoke_ops[] = {
570
    {
571
        {GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_OID_LENGTH, GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_OID},
572
        gss_krb5int_register_acceptor_identity
573
    },
574
    {
575
        {GSS_KRB5_CCACHE_NAME_OID_LENGTH, GSS_KRB5_CCACHE_NAME_OID},
576
        gss_krb5int_ccache_name
577
    },
578
    {
579
        {GSS_KRB5_FREE_LUCID_SEC_CONTEXT_OID_LENGTH, GSS_KRB5_FREE_LUCID_SEC_CONTEXT_OID},
580
        gss_krb5int_free_lucid_sec_context
581
    },
582
#ifndef _WIN32
583
    {
584
        {GSS_KRB5_USE_KDC_CONTEXT_OID_LENGTH, GSS_KRB5_USE_KDC_CONTEXT_OID},
585
        krb5int_gss_use_kdc_context
586
    },
587
#endif
588
};
589
590
static OM_uint32 KRB5_CALLCONV
591
krb5_gssspi_mech_invoke (OM_uint32 *minor_status,
592
                         const gss_OID desired_mech,
593
                         const gss_OID desired_object,
594
                         gss_buffer_t value)
595
0
{
596
0
    size_t i;
597
598
0
    if (minor_status == NULL)
599
0
        return GSS_S_CALL_INACCESSIBLE_WRITE;
600
601
0
    *minor_status = 0;
602
603
0
    if (desired_mech == GSS_C_NO_OID)
604
0
        return GSS_S_BAD_MECH;
605
606
0
    if (desired_object == GSS_C_NO_OID)
607
0
        return GSS_S_CALL_INACCESSIBLE_READ;
608
609
0
    for (i = 0; i < sizeof(krb5_gssspi_mech_invoke_ops)/
610
0
             sizeof(krb5_gssspi_mech_invoke_ops[0]); i++) {
611
0
        if (g_OID_prefix_equal(desired_object, &krb5_gssspi_mech_invoke_ops[i].oid)) {
612
0
            return (*krb5_gssspi_mech_invoke_ops[i].func)(minor_status,
613
0
                                                          desired_mech,
614
0
                                                          desired_object,
615
0
                                                          value);
616
0
        }
617
0
    }
618
619
0
    *minor_status = EINVAL;
620
621
0
    return GSS_S_UNAVAILABLE;
622
0
}
623
624
0
#define GS2_KRB5_SASL_NAME        "GS2-KRB5"
625
0
#define GS2_KRB5_SASL_NAME_LEN    (sizeof(GS2_KRB5_SASL_NAME) - 1)
626
627
0
#define GS2_IAKERB_SASL_NAME      "GS2-IAKERB"
628
0
#define GS2_IAKERB_SASL_NAME_LEN  (sizeof(GS2_IAKERB_SASL_NAME) - 1)
629
630
static OM_uint32 KRB5_CALLCONV
631
krb5_gss_inquire_mech_for_saslname(OM_uint32 *minor_status,
632
                                   const gss_buffer_t sasl_mech_name,
633
                                   gss_OID *mech_type)
634
0
{
635
0
    *minor_status = 0;
636
637
0
    if (sasl_mech_name->length == GS2_KRB5_SASL_NAME_LEN &&
638
0
        memcmp(sasl_mech_name->value,
639
0
               GS2_KRB5_SASL_NAME, GS2_KRB5_SASL_NAME_LEN) == 0) {
640
0
        if (mech_type != NULL)
641
0
            *mech_type = (gss_OID)gss_mech_krb5;
642
0
        return GSS_S_COMPLETE;
643
0
    } else if (sasl_mech_name->length == GS2_IAKERB_SASL_NAME_LEN &&
644
0
               memcmp(sasl_mech_name->value,
645
0
                      GS2_IAKERB_SASL_NAME, GS2_IAKERB_SASL_NAME_LEN) == 0) {
646
0
        if (mech_type != NULL)
647
0
            *mech_type = (gss_OID)gss_mech_iakerb;
648
0
        return GSS_S_COMPLETE;
649
0
    }
650
651
0
    return GSS_S_BAD_MECH;
652
0
}
653
654
static OM_uint32 KRB5_CALLCONV
655
krb5_gss_inquire_saslname_for_mech(OM_uint32 *minor_status,
656
                                   const gss_OID desired_mech,
657
                                   gss_buffer_t sasl_mech_name,
658
                                   gss_buffer_t mech_name,
659
                                   gss_buffer_t mech_description)
660
0
{
661
0
    if (g_OID_equal(desired_mech, gss_mech_iakerb)) {
662
0
        if (!g_make_string_buffer(GS2_IAKERB_SASL_NAME, sasl_mech_name) ||
663
0
            !g_make_string_buffer("iakerb", mech_name) ||
664
0
            !g_make_string_buffer("Initial and Pass Through Authentication "
665
0
                                  "Kerberos Mechanism (IAKERB)",
666
0
                                  mech_description))
667
0
            goto fail;
668
0
    } else {
669
0
        if (!g_make_string_buffer(GS2_KRB5_SASL_NAME, sasl_mech_name) ||
670
0
            !g_make_string_buffer("krb5", mech_name) ||
671
0
            !g_make_string_buffer("Kerberos 5 GSS-API Mechanism",
672
0
                                  mech_description))
673
0
            goto fail;
674
0
    }
675
676
0
    *minor_status = 0;
677
0
    return GSS_S_COMPLETE;
678
679
0
fail:
680
0
    *minor_status = ENOMEM;
681
0
    return GSS_S_FAILURE;
682
0
}
683
684
static OM_uint32 KRB5_CALLCONV
685
krb5_gss_inquire_attrs_for_mech(OM_uint32 *minor_status,
686
                                gss_const_OID mech,
687
                                gss_OID_set *mech_attrs,
688
                                gss_OID_set *known_mech_attrs)
689
234
{
690
234
    OM_uint32 major, tmpMinor;
691
692
234
    if (mech_attrs == NULL) {
693
0
        *minor_status = 0;
694
0
        return GSS_S_COMPLETE;
695
0
    }
696
697
234
    major = gss_create_empty_oid_set(minor_status, mech_attrs);
698
234
    if (GSS_ERROR(major))
699
0
        goto cleanup;
700
701
3.50k
#define MA_SUPPORTED(ma)    do {                                        \
702
3.50k
        major = gss_add_oid_set_member(minor_status, (gss_OID)ma,       \
703
3.50k
                                       mech_attrs);                     \
704
3.50k
        if (GSS_ERROR(major))                                           \
705
3.50k
            goto cleanup;                                               \
706
3.50k
    } while (0)
707
708
234
    MA_SUPPORTED(GSS_C_MA_MECH_CONCRETE);
709
234
    MA_SUPPORTED(GSS_C_MA_ITOK_FRAMED);
710
234
    MA_SUPPORTED(GSS_C_MA_AUTH_INIT);
711
234
    MA_SUPPORTED(GSS_C_MA_AUTH_TARG);
712
234
    MA_SUPPORTED(GSS_C_MA_DELEG_CRED);
713
234
    MA_SUPPORTED(GSS_C_MA_INTEG_PROT);
714
234
    MA_SUPPORTED(GSS_C_MA_CONF_PROT);
715
234
    MA_SUPPORTED(GSS_C_MA_MIC);
716
234
    MA_SUPPORTED(GSS_C_MA_WRAP);
717
234
    MA_SUPPORTED(GSS_C_MA_PROT_READY);
718
234
    MA_SUPPORTED(GSS_C_MA_REPLAY_DET);
719
234
    MA_SUPPORTED(GSS_C_MA_OOS_DET);
720
234
    MA_SUPPORTED(GSS_C_MA_CBINDINGS);
721
234
    MA_SUPPORTED(GSS_C_MA_CTX_TRANS);
722
723
234
    if (g_OID_equal(mech, gss_mech_iakerb)) {
724
77
        MA_SUPPORTED(GSS_C_MA_AUTH_INIT_INIT);
725
77
        MA_SUPPORTED(GSS_C_MA_NOT_DFLT_MECH);
726
157
    } else if (!g_OID_equal(mech, gss_mech_krb5)) {
727
78
        MA_SUPPORTED(GSS_C_MA_DEPRECATED);
728
78
    }
729
730
234
cleanup:
731
234
    if (GSS_ERROR(major))
732
0
        gss_release_oid_set(&tmpMinor, mech_attrs);
733
734
234
    return major;
735
234
}
736
737
static OM_uint32 KRB5_CALLCONV
738
krb5_gss_localname(OM_uint32 *minor,
739
                   const gss_name_t pname,
740
                   const gss_const_OID mech_type,
741
                   gss_buffer_t localname)
742
0
{
743
0
    krb5_context context;
744
0
    krb5_error_code code;
745
0
    krb5_gss_name_t kname;
746
0
    char lname[BUFSIZ];
747
748
0
    code = krb5_gss_init_context(&context);
749
0
    if (code != 0) {
750
0
        *minor = code;
751
0
        return GSS_S_FAILURE;
752
0
    }
753
754
0
    kname = (krb5_gss_name_t)pname;
755
756
0
    code = krb5_aname_to_localname(context, kname->princ,
757
0
                                   sizeof(lname), lname);
758
0
    if (code != 0) {
759
0
        *minor = KRB5_NO_LOCALNAME;
760
0
        krb5_free_context(context);
761
0
        return GSS_S_FAILURE;
762
0
    }
763
764
765
0
    krb5_free_context(context);
766
0
    localname->value = gssalloc_strdup(lname);
767
0
    localname->length = strlen(lname);
768
769
0
    return GSS_S_COMPLETE;
770
0
}
771
772
773
static OM_uint32 KRB5_CALLCONV
774
krb5_gss_authorize_localname(OM_uint32 *minor,
775
                             const gss_name_t pname,
776
                             gss_const_buffer_t local_user,
777
                             gss_const_OID name_type)
778
0
{
779
0
    krb5_context context;
780
0
    krb5_error_code code;
781
0
    krb5_gss_name_t kname;
782
0
    char *user;
783
0
    int user_ok;
784
785
0
    if (name_type != GSS_C_NO_OID &&
786
0
        !g_OID_equal(name_type, GSS_C_NT_USER_NAME)) {
787
0
        return GSS_S_BAD_NAMETYPE;
788
0
    }
789
790
0
    kname = (krb5_gss_name_t)pname;
791
792
0
    code = krb5_gss_init_context(&context);
793
0
    if (code != 0) {
794
0
        *minor = code;
795
0
        return GSS_S_FAILURE;
796
0
    }
797
798
0
    user = k5memdup0(local_user->value, local_user->length, &code);
799
0
    if (user == NULL) {
800
0
        *minor = code;
801
0
        krb5_free_context(context);
802
0
        return GSS_S_FAILURE;
803
0
    }
804
805
0
    user_ok = krb5_kuserok(context, kname->princ, user);
806
807
0
    free(user);
808
0
    krb5_free_context(context);
809
810
0
    *minor = 0;
811
0
    return user_ok ? GSS_S_COMPLETE : GSS_S_UNAUTHORIZED;
812
0
}
813
814
static struct gss_config krb5_mechanism = {
815
    { GSS_MECH_KRB5_OID_LENGTH, GSS_MECH_KRB5_OID },
816
    NULL,
817
    krb5_gss_acquire_cred,
818
    krb5_gss_release_cred,
819
    krb5_gss_init_sec_context,
820
#ifdef LEAN_CLIENT
821
    NULL,
822
#else
823
    krb5_gss_accept_sec_context,
824
#endif
825
    krb5_gss_process_context_token,
826
    krb5_gss_delete_sec_context,
827
    krb5_gss_context_time,
828
    krb5_gss_get_mic,
829
    krb5_gss_verify_mic,
830
#if defined(IOV_SHIM_EXERCISE_WRAP) || defined(IOV_SHIM_EXERCISE)
831
    NULL,
832
#else
833
    krb5_gss_wrap,
834
#endif
835
#if defined(IOV_SHIM_EXERCISE_UNWRAP) || defined(IOV_SHIM_EXERCISE)
836
    NULL,
837
#else
838
    krb5_gss_unwrap,
839
#endif
840
    krb5_gss_display_status,
841
    krb5_gss_indicate_mechs,
842
    krb5_gss_compare_name,
843
    krb5_gss_display_name,
844
    krb5_gss_import_name,
845
    krb5_gss_release_name,
846
    krb5_gss_inquire_cred,
847
    NULL,                /* add_cred */
848
#ifdef LEAN_CLIENT
849
    NULL,
850
    NULL,
851
#else
852
    krb5_gss_export_sec_context,
853
    krb5_gss_import_sec_context,
854
#endif
855
    krb5_gss_inquire_cred_by_mech,
856
    krb5_gss_inquire_names_for_mech,
857
    krb5_gss_inquire_context,
858
    krb5_gss_internal_release_oid,
859
    krb5_gss_wrap_size_limit,
860
    krb5_gss_localname,
861
862
    krb5_gss_authorize_localname,
863
    krb5_gss_export_name,
864
    krb5_gss_duplicate_name,
865
    krb5_gss_store_cred,
866
    krb5_gss_inquire_sec_context_by_oid,
867
    krb5_gss_inquire_cred_by_oid,
868
    krb5_gss_set_sec_context_option,
869
    krb5_gssspi_set_cred_option,
870
    krb5_gssspi_mech_invoke,
871
    NULL,                /* wrap_aead */
872
    NULL,                /* unwrap_aead */
873
    krb5_gss_wrap_iov,
874
    krb5_gss_unwrap_iov,
875
    krb5_gss_wrap_iov_length,
876
    NULL,               /* complete_auth_token */
877
    krb5_gss_acquire_cred_impersonate_name,
878
    NULL,               /* krb5_gss_add_cred_impersonate_name */
879
    NULL,               /* display_name_ext */
880
    krb5_gss_inquire_name,
881
    krb5_gss_get_name_attribute,
882
    krb5_gss_set_name_attribute,
883
    krb5_gss_delete_name_attribute,
884
    krb5_gss_export_name_composite,
885
    krb5_gss_map_name_to_any,
886
    krb5_gss_release_any_name_mapping,
887
    krb5_gss_pseudo_random,
888
    NULL,               /* set_neg_mechs */
889
    krb5_gss_inquire_saslname_for_mech,
890
    krb5_gss_inquire_mech_for_saslname,
891
    krb5_gss_inquire_attrs_for_mech,
892
    krb5_gss_acquire_cred_from,
893
    krb5_gss_store_cred_into,
894
    krb5_gss_acquire_cred_with_password,
895
    krb5_gss_export_cred,
896
    krb5_gss_import_cred,
897
    NULL,               /* import_sec_context_by_mech */
898
    NULL,               /* import_name_by_mech */
899
    NULL,               /* import_cred_by_mech */
900
    krb5_gss_get_mic_iov,
901
    krb5_gss_verify_mic_iov,
902
    krb5_gss_get_mic_iov_length,
903
};
904
905
/* Functions which use security contexts or acquire creds are IAKERB-specific;
906
 * other functions can borrow from the krb5 mech. */
907
static struct gss_config iakerb_mechanism = {
908
    { GSS_MECH_KRB5_OID_LENGTH, GSS_MECH_KRB5_OID },
909
    NULL,
910
    iakerb_gss_acquire_cred,
911
    krb5_gss_release_cred,
912
    iakerb_gss_init_sec_context,
913
#ifdef LEAN_CLIENT
914
    NULL,
915
#else
916
    iakerb_gss_accept_sec_context,
917
#endif
918
    iakerb_gss_process_context_token,
919
    iakerb_gss_delete_sec_context,
920
    iakerb_gss_context_time,
921
    iakerb_gss_get_mic,
922
    iakerb_gss_verify_mic,
923
#if defined(IOV_SHIM_EXERCISE_WRAP) || defined(IOV_SHIM_EXERCISE)
924
    NULL,
925
#else
926
    iakerb_gss_wrap,
927
#endif
928
#if defined(IOV_SHIM_EXERCISE_UNWRAP) || defined(IOV_SHIM_EXERCISE)
929
    NULL,
930
#else
931
    iakerb_gss_unwrap,
932
#endif
933
    krb5_gss_display_status,
934
    krb5_gss_indicate_mechs,
935
    krb5_gss_compare_name,
936
    krb5_gss_display_name,
937
    iakerb_gss_import_name,
938
    krb5_gss_release_name,
939
    krb5_gss_inquire_cred,
940
    NULL,                /* add_cred */
941
#ifdef LEAN_CLIENT
942
    NULL,
943
    NULL,
944
#else
945
    iakerb_gss_export_sec_context,
946
    iakerb_gss_import_sec_context,
947
#endif
948
    krb5_gss_inquire_cred_by_mech,
949
    krb5_gss_inquire_names_for_mech,
950
    iakerb_gss_inquire_context,
951
    krb5_gss_internal_release_oid,
952
    iakerb_gss_wrap_size_limit,
953
    krb5_gss_localname,
954
    krb5_gss_authorize_localname,
955
    krb5_gss_export_name,
956
    krb5_gss_duplicate_name,
957
    krb5_gss_store_cred,
958
    iakerb_gss_inquire_sec_context_by_oid,
959
    krb5_gss_inquire_cred_by_oid,
960
    iakerb_gss_set_sec_context_option,
961
    krb5_gssspi_set_cred_option,
962
    krb5_gssspi_mech_invoke,
963
    NULL,                /* wrap_aead */
964
    NULL,                /* unwrap_aead */
965
    iakerb_gss_wrap_iov,
966
    iakerb_gss_unwrap_iov,
967
    iakerb_gss_wrap_iov_length,
968
    NULL,               /* complete_auth_token */
969
    NULL,               /* acquire_cred_impersonate_name */
970
    NULL,               /* add_cred_impersonate_name */
971
    NULL,               /* display_name_ext */
972
    krb5_gss_inquire_name,
973
    krb5_gss_get_name_attribute,
974
    krb5_gss_set_name_attribute,
975
    krb5_gss_delete_name_attribute,
976
    krb5_gss_export_name_composite,
977
    krb5_gss_map_name_to_any,
978
    krb5_gss_release_any_name_mapping,
979
    iakerb_gss_pseudo_random,
980
    NULL,               /* set_neg_mechs */
981
    krb5_gss_inquire_saslname_for_mech,
982
    krb5_gss_inquire_mech_for_saslname,
983
    krb5_gss_inquire_attrs_for_mech,
984
    iakerb_gss_acquire_cred_from,
985
    krb5_gss_store_cred_into,
986
    iakerb_gss_acquire_cred_with_password,
987
    krb5_gss_export_cred,
988
    krb5_gss_import_cred,
989
    NULL,               /* import_sec_context_by_mech */
990
    NULL,               /* import_name_by_mech */
991
    NULL,               /* import_cred_by_mech */
992
    iakerb_gss_get_mic_iov,
993
    iakerb_gss_verify_mic_iov,
994
    iakerb_gss_get_mic_iov_length,
995
};
996
997
#ifdef _GSS_STATIC_LINK
998
#include "mglueP.h"
999
static int gss_iakerbmechglue_init(void)
1000
2
{
1001
2
    struct gss_mech_config mech_iakerb;
1002
1003
2
    memset(&mech_iakerb, 0, sizeof(mech_iakerb));
1004
2
    mech_iakerb.mech = &iakerb_mechanism;
1005
1006
2
    mech_iakerb.mechNameStr = "iakerb";
1007
2
    mech_iakerb.mech_type = (gss_OID)gss_mech_iakerb;
1008
2
    gssint_register_mechinfo(&mech_iakerb);
1009
1010
2
    return 0;
1011
2
}
1012
1013
static int gss_krb5mechglue_init(void)
1014
2
{
1015
2
    struct gss_mech_config mech_krb5;
1016
1017
2
    memset(&mech_krb5, 0, sizeof(mech_krb5));
1018
2
    mech_krb5.mech = &krb5_mechanism;
1019
1020
2
    mech_krb5.mechNameStr = "kerberos_v5";
1021
2
    mech_krb5.mech_type = (gss_OID)gss_mech_krb5;
1022
2
    gssint_register_mechinfo(&mech_krb5);
1023
1024
2
    mech_krb5.mechNameStr = "kerberos_v5_old";
1025
2
    mech_krb5.mech_type = (gss_OID)gss_mech_krb5_old;
1026
2
    gssint_register_mechinfo(&mech_krb5);
1027
1028
2
    mech_krb5.mechNameStr = "mskrb";
1029
2
    mech_krb5.mech_type = (gss_OID)gss_mech_krb5_wrong;
1030
2
    gssint_register_mechinfo(&mech_krb5);
1031
1032
2
    return 0;
1033
2
}
1034
#else
1035
MAKE_INIT_FUNCTION(gss_krb5int_lib_init);
1036
MAKE_FINI_FUNCTION(gss_krb5int_lib_fini);
1037
1038
gss_mechanism KRB5_CALLCONV
1039
gss_mech_initialize(void)
1040
{
1041
    return &krb5_mechanism;
1042
}
1043
#endif /* _GSS_STATIC_LINK */
1044
1045
int gss_krb5int_lib_init(void)
1046
2
{
1047
2
    int err;
1048
1049
#ifdef SHOW_INITFINI_FUNCS
1050
    printf("gss_krb5int_lib_init\n");
1051
#endif
1052
1053
2
    add_error_table(&et_k5g_error_table);
1054
1055
2
#ifndef LEAN_CLIENT
1056
2
    err = k5_mutex_finish_init(&gssint_krb5_keytab_lock);
1057
2
    if (err)
1058
0
        return err;
1059
2
#endif /* LEAN_CLIENT */
1060
2
    err = k5_key_register(K5_KEY_GSS_KRB5_SET_CCACHE_OLD_NAME, free);
1061
2
    if (err)
1062
0
        return err;
1063
2
    err = k5_key_register(K5_KEY_GSS_KRB5_CCACHE_NAME, free);
1064
2
    if (err)
1065
0
        return err;
1066
2
    err = k5_key_register(K5_KEY_GSS_KRB5_ERROR_MESSAGE,
1067
2
                          krb5_gss_delete_error_info);
1068
2
    if (err)
1069
0
        return err;
1070
2
#ifndef _WIN32
1071
2
    err = k5_mutex_finish_init(&kg_kdc_flag_mutex);
1072
2
    if (err)
1073
0
        return err;
1074
2
#endif
1075
2
#ifdef _GSS_STATIC_LINK
1076
2
    err = gss_krb5mechglue_init();
1077
2
    if (err)
1078
0
        return err;
1079
2
    err = gss_iakerbmechglue_init();
1080
2
    if (err)
1081
0
        return err;
1082
2
#endif
1083
1084
2
    return 0;
1085
2
}
1086
1087
void gss_krb5int_lib_fini(void)
1088
0
{
1089
#ifndef _GSS_STATIC_LINK
1090
    if (!INITIALIZER_RAN(gss_krb5int_lib_init) || PROGRAM_EXITING()) {
1091
# ifdef SHOW_INITFINI_FUNCS
1092
        printf("gss_krb5int_lib_fini: skipping\n");
1093
# endif
1094
        return;
1095
    }
1096
#endif
1097
#ifdef SHOW_INITFINI_FUNCS
1098
    printf("gss_krb5int_lib_fini\n");
1099
#endif
1100
0
    remove_error_table(&et_k5g_error_table);
1101
1102
0
    k5_key_delete(K5_KEY_GSS_KRB5_SET_CCACHE_OLD_NAME);
1103
0
    k5_key_delete(K5_KEY_GSS_KRB5_CCACHE_NAME);
1104
0
    k5_key_delete(K5_KEY_GSS_KRB5_ERROR_MESSAGE);
1105
0
#ifndef _WIN32
1106
0
    k5_mutex_destroy(&kg_kdc_flag_mutex);
1107
0
#endif
1108
0
#ifndef LEAN_CLIENT
1109
0
    k5_mutex_destroy(&gssint_krb5_keytab_lock);
1110
0
#endif /* LEAN_CLIENT */
1111
0
}
1112
1113
#ifdef _GSS_STATIC_LINK
1114
extern OM_uint32 gssint_lib_init(void);
1115
#endif
1116
1117
OM_uint32 gss_krb5int_initialize_library (void)
1118
85
{
1119
85
#ifdef _GSS_STATIC_LINK
1120
85
    return gssint_mechglue_initialize_library();
1121
#else
1122
    return CALL_INIT_FUNCTION(gss_krb5int_lib_init);
1123
#endif
1124
85
}