1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
3 * Copyright 1993 by OpenVision Technologies, Inc.
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.
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.
25 * Copyright (C) 1998 by the FundsXpress, INC.
27 * All rights reserved.
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.
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.
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.
50 * Copyright (c) 2006-2008, Novell, Inc.
51 * All rights reserved.
53 * Redistribution and use in source and binary forms, with or without
54 * modification, are permitted provided that the following conditions are met:
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.
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.
82 /* For declaration of krb5_ser_context_init */
84 #include "gssapiP_krb5.h"
91 /** exported constants defined in gssapi_krb5{,_nx}.h **/
93 /* these are bogus, but will compile */
96 * The OID of the draft krb5 mechanism, assigned by IETF, is:
97 * iso(1) org(3) dod(5) internet(1) security(5)
98 * kerberosv5(2) = 1.3.5.1.5.2
99 * The OID of the krb5_name type is:
100 * iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
101 * krb5(2) krb5_name(1) = 1.2.840.113554.1.2.2.1
102 * The OID of the krb5_principal type is:
103 * iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
104 * krb5(2) krb5_principal(2) = 1.2.840.113554.1.2.2.2
105 * The OID of the proposed standard krb5 mechanism is:
106 * iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
107 * krb5(2) = 1.2.840.113554.1.2.2
108 * The OID of the proposed standard krb5 v2 mechanism is:
109 * iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
110 * krb5v2(3) = 1.2.840.113554.1.2.3
111 * Provisionally reserved for Kerberos session key algorithm
113 * iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
114 * krb5(2) krb5_enctype(4) = 1.2.840.113554.1.2.2.4
115 * Provisionally reserved for Kerberos mechanism-specific APIs:
116 * iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
117 * krb5(2) krb5_gssapi_ext(5) = 1.2.840.113554.1.2.2.5
121 * Encoding rules: The first two values are encoded in one byte as 40
122 * * value1 + value2. Subsequent values are encoded base 128, most
123 * significant digit first, with the high bit (\200) set on all octets
124 * except the last in each value's encoding.
127 const gss_OID_desc krb5_gss_oid_array[] = {
128 /* this is the official, rfc-specified OID */
129 {GSS_MECH_KRB5_OID_LENGTH, GSS_MECH_KRB5_OID},
130 /* this pre-RFC mech OID */
131 {GSS_MECH_KRB5_OLD_OID_LENGTH, GSS_MECH_KRB5_OLD_OID},
132 /* this is the unofficial, incorrect mech OID emitted by MS */
133 {GSS_MECH_KRB5_WRONG_OID_LENGTH, GSS_MECH_KRB5_WRONG_OID},
135 {GSS_MECH_IAKERB_OID_LENGTH, GSS_MECH_IAKERB_OID},
136 /* this is the v2 assigned OID */
137 {9, "\052\206\110\206\367\022\001\002\003"},
138 /* these two are name type OID's */
139 /* 2.1.1. Kerberos Principal Name Form: (rfc 1964)
140 * This name form shall be represented by the Object Identifier {iso(1)
141 * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
142 * krb5(2) krb5_name(1)}. The recommended symbolic name for this type
143 * is "GSS_KRB5_NT_PRINCIPAL_NAME". */
144 {10, "\052\206\110\206\367\022\001\002\002\001"},
145 /* gss_nt_krb5_principal. Object identifier for a krb5_principal. Do not use. */
146 {10, "\052\206\110\206\367\022\001\002\002\002"},
150 const gss_OID_desc * const gss_mech_krb5 = krb5_gss_oid_array+0;
151 const gss_OID_desc * const gss_mech_krb5_old = krb5_gss_oid_array+1;
152 const gss_OID_desc * const gss_mech_krb5_wrong = krb5_gss_oid_array+2;
153 const gss_OID_desc * const gss_mech_iakerb = krb5_gss_oid_array+3;
156 const gss_OID_desc * const gss_nt_krb5_name = krb5_gss_oid_array+5;
157 const gss_OID_desc * const gss_nt_krb5_principal = krb5_gss_oid_array+6;
158 const gss_OID_desc * const GSS_KRB5_NT_PRINCIPAL_NAME = krb5_gss_oid_array+5;
160 static const gss_OID_set_desc oidsets[] = {
161 {1, (gss_OID) krb5_gss_oid_array+0}, /* RFC OID */
162 {1, (gss_OID) krb5_gss_oid_array+1}, /* pre-RFC OID */
163 {4, (gss_OID) krb5_gss_oid_array+0}, /* includes wrong OID & IAKERB */
164 {1, (gss_OID) krb5_gss_oid_array+2},
165 {3, (gss_OID) krb5_gss_oid_array+0},
168 const gss_OID_set_desc * const gss_mech_set_krb5 = oidsets+0;
169 const gss_OID_set_desc * const gss_mech_set_krb5_old = oidsets+1;
170 const gss_OID_set_desc * const gss_mech_set_krb5_both = oidsets+2;
172 g_set kg_vdb = G_SET_INIT;
174 /** default credential support */
177 * init_sec_context() will explicitly re-acquire default credentials,
178 * so handling the expiration/invalidation condition here isn't needed.
181 kg_get_defcred(minor_status, cred)
182 OM_uint32 *minor_status;
187 if ((major = krb5_gss_acquire_cred(minor_status,
188 (gss_name_t) NULL, GSS_C_INDEFINITE,
189 GSS_C_NULL_OID_SET, GSS_C_INITIATE,
190 cred, NULL, NULL)) && GSS_ERROR(major)) {
194 return(GSS_S_COMPLETE);
198 kg_sync_ccache_name (krb5_context context, OM_uint32 *minor_status)
203 * Sync up the context ccache name with the GSSAPI ccache name.
204 * If kg_ccache_name is NULL -- normal unless someone has called
205 * gss_krb5_ccache_name() -- then the system default ccache will
206 * be picked up and used by resetting the context default ccache.
207 * This is needed for platforms which support multiple ccaches.
211 /* if NULL, resets the context default ccache */
212 err = krb5_cc_set_default_name(context,
213 (char *) k5_getspecific(K5_KEY_GSS_KRB5_CCACHE_NAME));
217 return (*minor_status == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE;
220 /* This function returns whether or not the caller set a cccache name. Used by
221 * gss_acquire_cred to figure out if the caller wants to only look at this
222 * ccache or search the cache collection for the desired name */
224 kg_caller_provided_ccache_name (OM_uint32 *minor_status,
225 int *out_caller_provided_name)
227 if (out_caller_provided_name) {
228 *out_caller_provided_name =
229 (k5_getspecific(K5_KEY_GSS_KRB5_CCACHE_NAME) != NULL);
233 return GSS_S_COMPLETE;
237 kg_get_ccache_name (OM_uint32 *minor_status, const char **out_name)
239 const char *name = NULL;
241 char *kg_ccache_name;
243 kg_ccache_name = k5_getspecific(K5_KEY_GSS_KRB5_CCACHE_NAME);
245 if (kg_ccache_name != NULL) {
246 name = strdup(kg_ccache_name);
250 krb5_context context = NULL;
252 /* Reset the context default ccache (see text above), and then
254 err = krb5_gss_init_context(&context);
256 err = krb5_cc_set_default_name (context, NULL);
258 name = krb5_cc_default_name(context);
266 save_error_info(err, context);
268 krb5_free_context(context);
278 return (*minor_status == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE;
282 kg_set_ccache_name (OM_uint32 *minor_status, const char *name)
284 char *new_name = NULL;
286 char *kg_ccache_name;
287 krb5_error_code kerr;
290 new_name = strdup(name);
291 if (new_name == NULL) {
292 *minor_status = ENOMEM;
293 return GSS_S_FAILURE;
297 kg_ccache_name = k5_getspecific(K5_KEY_GSS_KRB5_CCACHE_NAME);
298 swap = kg_ccache_name;
299 kg_ccache_name = new_name;
301 kerr = k5_setspecific(K5_KEY_GSS_KRB5_CCACHE_NAME, kg_ccache_name);
303 /* Can't store, so free up the storage. */
304 free(kg_ccache_name);
305 /* ??? free(new_name); */
306 *minor_status = kerr;
307 return GSS_S_FAILURE;
312 return GSS_S_COMPLETE;
315 #define g_OID_prefix_equal(o1, o2) \
316 (((o1)->length >= (o2)->length) && \
317 (memcmp((o1)->elements, (o2)->elements, (o2)->length) == 0))
320 * gss_inquire_sec_context_by_oid() methods
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[] = {
327 {GSS_KRB5_GET_TKT_FLAGS_OID_LENGTH, GSS_KRB5_GET_TKT_FLAGS_OID},
328 gss_krb5int_get_tkt_flags
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
335 {GSS_KRB5_INQ_SSPI_SESSION_KEY_OID_LENGTH, GSS_KRB5_INQ_SSPI_SESSION_KEY_OID},
336 gss_krb5int_inq_session_key
339 {GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID_LENGTH, GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID},
340 gss_krb5int_export_lucid_sec_context
343 {GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID_LENGTH, GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID},
344 gss_krb5int_extract_authtime_from_sec_context
348 static OM_uint32 KRB5_CALLCONV
349 krb5_gss_inquire_sec_context_by_oid (OM_uint32 *minor_status,
350 const gss_ctx_id_t context_handle,
351 const gss_OID desired_object,
352 gss_buffer_set_t *data_set)
354 krb5_gss_ctx_id_rec *ctx;
357 if (minor_status == NULL)
358 return GSS_S_CALL_INACCESSIBLE_WRITE;
362 if (desired_object == GSS_C_NO_OID)
363 return GSS_S_CALL_INACCESSIBLE_READ;
365 if (data_set == NULL)
366 return GSS_S_CALL_INACCESSIBLE_WRITE;
368 *data_set = GSS_C_NO_BUFFER_SET;
370 ctx = (krb5_gss_ctx_id_rec *) context_handle;
372 if (!ctx->established)
373 return GSS_S_NO_CONTEXT;
375 for (i = 0; i < sizeof(krb5_gss_inquire_sec_context_by_oid_ops)/
376 sizeof(krb5_gss_inquire_sec_context_by_oid_ops[0]); i++) {
377 if (g_OID_prefix_equal(desired_object, &krb5_gss_inquire_sec_context_by_oid_ops[i].oid)) {
378 return (*krb5_gss_inquire_sec_context_by_oid_ops[i].func)(minor_status,
385 *minor_status = EINVAL;
387 return GSS_S_UNAVAILABLE;
391 * gss_inquire_cred_by_oid() methods
396 OM_uint32 (*func)(OM_uint32 *, const gss_cred_id_t, const gss_OID, gss_buffer_set_t *);
397 } krb5_gss_inquire_cred_by_oid_ops[] = {
401 static OM_uint32 KRB5_CALLCONV
402 krb5_gss_inquire_cred_by_oid(OM_uint32 *minor_status,
403 const gss_cred_id_t cred_handle,
404 const gss_OID desired_object,
405 gss_buffer_set_t *data_set)
407 OM_uint32 major_status = GSS_S_FAILURE;
408 krb5_gss_cred_id_t cred;
413 if (minor_status == NULL)
414 return GSS_S_CALL_INACCESSIBLE_WRITE;
418 if (desired_object == GSS_C_NO_OID)
419 return GSS_S_CALL_INACCESSIBLE_READ;
421 if (data_set == NULL)
422 return GSS_S_CALL_INACCESSIBLE_WRITE;
424 *data_set = GSS_C_NO_BUFFER_SET;
425 if (cred_handle == GSS_C_NO_CREDENTIAL) {
426 *minor_status = (OM_uint32)KRB5_NOCREDS_SUPPLIED;
427 return GSS_S_NO_CRED;
430 major_status = krb5_gss_validate_cred(minor_status, cred_handle);
431 if (GSS_ERROR(major_status))
434 cred = (krb5_gss_cred_id_t) cred_handle;
437 for (i = 0; i < sizeof(krb5_gss_inquire_cred_by_oid_ops)/
438 sizeof(krb5_gss_inquire_cred_by_oid_ops[0]); i++) {
439 if (g_OID_prefix_equal(desired_object, &krb5_gss_inquire_cred_by_oid_ops[i].oid)) {
440 return (*krb5_gss_inquire_cred_by_oid_ops[i].func)(minor_status,
448 *minor_status = EINVAL;
450 return GSS_S_UNAVAILABLE;
454 * gss_set_sec_context_option() methods
455 * (Disabled until we have something to populate the array.)
460 OM_uint32 (*func)(OM_uint32 *, gss_ctx_id_t *, const gss_OID, const gss_buffer_t);
461 } krb5_gss_set_sec_context_option_ops[] = {
465 static OM_uint32 KRB5_CALLCONV
466 krb5_gss_set_sec_context_option (OM_uint32 *minor_status,
467 gss_ctx_id_t *context_handle,
468 const gss_OID desired_object,
469 const gss_buffer_t value)
475 if (minor_status == NULL)
476 return GSS_S_CALL_INACCESSIBLE_WRITE;
480 if (context_handle == NULL)
481 return GSS_S_CALL_INACCESSIBLE_READ;
483 if (desired_object == GSS_C_NO_OID)
484 return GSS_S_CALL_INACCESSIBLE_READ;
487 for (i = 0; i < sizeof(krb5_gss_set_sec_context_option_ops)/
488 sizeof(krb5_gss_set_sec_context_option_ops[0]); i++) {
489 if (g_OID_prefix_equal(desired_object, &krb5_gss_set_sec_context_option_ops[i].oid)) {
490 return (*krb5_gss_set_sec_context_option_ops[i].func)(minor_status,
498 *minor_status = EINVAL;
500 return GSS_S_UNAVAILABLE;
504 * gssspi_set_cred_option() methods
508 OM_uint32 (*func)(OM_uint32 *, gss_cred_id_t *, const gss_OID, const gss_buffer_t);
509 } krb5_gssspi_set_cred_option_ops[] = {
511 {GSS_KRB5_COPY_CCACHE_OID_LENGTH, GSS_KRB5_COPY_CCACHE_OID},
512 gss_krb5int_copy_ccache
515 {GSS_KRB5_SET_ALLOWABLE_ENCTYPES_OID_LENGTH, GSS_KRB5_SET_ALLOWABLE_ENCTYPES_OID},
516 gss_krb5int_set_allowable_enctypes
519 {GSS_KRB5_SET_CRED_RCACHE_OID_LENGTH, GSS_KRB5_SET_CRED_RCACHE_OID},
520 gss_krb5int_set_cred_rcache
523 {GSS_KRB5_IMPORT_CRED_OID_LENGTH, GSS_KRB5_IMPORT_CRED_OID},
524 gss_krb5int_import_cred
528 static OM_uint32 KRB5_CALLCONV
529 krb5_gssspi_set_cred_option(OM_uint32 *minor_status,
530 gss_cred_id_t *cred_handle,
531 const gss_OID desired_object,
532 const gss_buffer_t value)
534 OM_uint32 major_status = GSS_S_FAILURE;
537 if (minor_status == NULL)
538 return GSS_S_CALL_INACCESSIBLE_WRITE;
540 if (cred_handle == NULL)
541 return GSS_S_CALL_INACCESSIBLE_WRITE;
545 if (desired_object == GSS_C_NO_OID)
546 return GSS_S_CALL_INACCESSIBLE_READ;
548 if (*cred_handle != GSS_C_NO_CREDENTIAL) {
549 major_status = krb5_gss_validate_cred(minor_status, *cred_handle);
550 if (GSS_ERROR(major_status))
554 for (i = 0; i < sizeof(krb5_gssspi_set_cred_option_ops)/
555 sizeof(krb5_gssspi_set_cred_option_ops[0]); i++) {
556 if (g_OID_prefix_equal(desired_object, &krb5_gssspi_set_cred_option_ops[i].oid)) {
557 return (*krb5_gssspi_set_cred_option_ops[i].func)(minor_status,
564 *minor_status = EINVAL;
566 return GSS_S_UNAVAILABLE;
570 * gssspi_mech_invoke() methods
574 OM_uint32 (*func)(OM_uint32 *, const gss_OID, const gss_OID, gss_buffer_t);
575 } krb5_gssspi_mech_invoke_ops[] = {
577 {GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_OID_LENGTH, GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_OID},
578 gss_krb5int_register_acceptor_identity
581 {GSS_KRB5_CCACHE_NAME_OID_LENGTH, GSS_KRB5_CCACHE_NAME_OID},
582 gss_krb5int_ccache_name
585 {GSS_KRB5_FREE_LUCID_SEC_CONTEXT_OID_LENGTH, GSS_KRB5_FREE_LUCID_SEC_CONTEXT_OID},
586 gss_krb5int_free_lucid_sec_context
590 {GSS_KRB5_USE_KDC_CONTEXT_OID_LENGTH, GSS_KRB5_USE_KDC_CONTEXT_OID},
591 krb5int_gss_use_kdc_context
596 static OM_uint32 KRB5_CALLCONV
597 krb5_gssspi_mech_invoke (OM_uint32 *minor_status,
598 const gss_OID desired_mech,
599 const gss_OID desired_object,
604 if (minor_status == NULL)
605 return GSS_S_CALL_INACCESSIBLE_WRITE;
609 if (desired_mech == GSS_C_NO_OID)
610 return GSS_S_BAD_MECH;
612 if (desired_object == GSS_C_NO_OID)
613 return GSS_S_CALL_INACCESSIBLE_READ;
615 for (i = 0; i < sizeof(krb5_gssspi_mech_invoke_ops)/
616 sizeof(krb5_gssspi_mech_invoke_ops[0]); i++) {
617 if (g_OID_prefix_equal(desired_object, &krb5_gssspi_mech_invoke_ops[i].oid)) {
618 return (*krb5_gssspi_mech_invoke_ops[i].func)(minor_status,
625 *minor_status = EINVAL;
627 return GSS_S_UNAVAILABLE;
630 #define GS2_KRB5_SASL_NAME "GS2-KRB5"
631 #define GS2_KRB5_SASL_NAME_LEN (sizeof(GS2_KRB5_SASL_NAME) - 1)
633 #define GS2_IAKERB_SASL_NAME "GS2-IAKERB"
634 #define GS2_IAKERB_SASL_NAME_LEN (sizeof(GS2_IAKERB_SASL_NAME) - 1)
636 static OM_uint32 KRB5_CALLCONV
637 krb5_gss_inquire_mech_for_saslname(OM_uint32 *minor_status,
638 const gss_buffer_t sasl_mech_name,
643 if (sasl_mech_name->length == GS2_KRB5_SASL_NAME_LEN &&
644 memcmp(sasl_mech_name->value,
645 GS2_KRB5_SASL_NAME, GS2_KRB5_SASL_NAME_LEN) == 0) {
646 if (mech_type != NULL)
647 *mech_type = (gss_OID)gss_mech_krb5;
648 return GSS_S_COMPLETE;
649 } else if (sasl_mech_name->length == GS2_IAKERB_SASL_NAME_LEN &&
650 memcmp(sasl_mech_name->value,
651 GS2_IAKERB_SASL_NAME, GS2_IAKERB_SASL_NAME_LEN) == 0) {
652 if (mech_type != NULL)
653 *mech_type = (gss_OID)gss_mech_iakerb;
654 return GSS_S_COMPLETE;
657 return GSS_S_BAD_MECH;
660 static OM_uint32 KRB5_CALLCONV
661 krb5_gss_inquire_saslname_for_mech(OM_uint32 *minor_status,
662 const gss_OID desired_mech,
663 gss_buffer_t sasl_mech_name,
664 gss_buffer_t mech_name,
665 gss_buffer_t mech_description)
667 if (g_OID_equal(desired_mech, gss_mech_iakerb)) {
668 if (!g_make_string_buffer(GS2_IAKERB_SASL_NAME, sasl_mech_name) ||
669 !g_make_string_buffer("iakerb", mech_name) ||
670 !g_make_string_buffer("Initial and Pass Through Authentication "
671 "Kerberos Mechanism (IAKERB)",
675 if (!g_make_string_buffer(GS2_KRB5_SASL_NAME, sasl_mech_name) ||
676 !g_make_string_buffer("krb5", mech_name) ||
677 !g_make_string_buffer("Kerberos 5 GSS-API Mechanism",
683 return GSS_S_COMPLETE;
686 *minor_status = ENOMEM;
687 return GSS_S_FAILURE;
690 static OM_uint32 KRB5_CALLCONV
691 krb5_gss_inquire_attrs_for_mech(OM_uint32 *minor_status,
693 gss_OID_set *mech_attrs,
694 gss_OID_set *known_mech_attrs)
696 OM_uint32 major, tmpMinor;
698 if (mech_attrs == NULL) {
700 return GSS_S_COMPLETE;
703 major = gss_create_empty_oid_set(minor_status, mech_attrs);
704 if (GSS_ERROR(major))
707 #define MA_SUPPORTED(ma) do { \
708 major = gss_add_oid_set_member(minor_status, (gss_OID)ma, \
710 if (GSS_ERROR(major)) \
714 MA_SUPPORTED(GSS_C_MA_MECH_CONCRETE);
715 MA_SUPPORTED(GSS_C_MA_ITOK_FRAMED);
716 MA_SUPPORTED(GSS_C_MA_AUTH_INIT);
717 MA_SUPPORTED(GSS_C_MA_AUTH_TARG);
718 MA_SUPPORTED(GSS_C_MA_DELEG_CRED);
719 MA_SUPPORTED(GSS_C_MA_INTEG_PROT);
720 MA_SUPPORTED(GSS_C_MA_CONF_PROT);
721 MA_SUPPORTED(GSS_C_MA_MIC);
722 MA_SUPPORTED(GSS_C_MA_WRAP);
723 MA_SUPPORTED(GSS_C_MA_PROT_READY);
724 MA_SUPPORTED(GSS_C_MA_REPLAY_DET);
725 MA_SUPPORTED(GSS_C_MA_OOS_DET);
726 MA_SUPPORTED(GSS_C_MA_CBINDINGS);
727 MA_SUPPORTED(GSS_C_MA_CTX_TRANS);
729 if (g_OID_equal(mech, gss_mech_iakerb)) {
730 MA_SUPPORTED(GSS_C_MA_AUTH_INIT_INIT);
731 } else if (!g_OID_equal(mech, gss_mech_krb5)) {
732 MA_SUPPORTED(GSS_C_MA_DEPRECATED);
736 if (GSS_ERROR(major))
737 gss_release_oid_set(&tmpMinor, mech_attrs);
742 static OM_uint32 KRB5_CALLCONV
743 krb5_gss_localname(OM_uint32 *minor,
744 const gss_name_t pname,
745 const gss_const_OID mech_type,
746 gss_buffer_t localname)
748 krb5_context context;
749 krb5_error_code code;
750 krb5_gss_name_t kname;
753 code = krb5_gss_init_context(&context);
756 return GSS_S_FAILURE;
759 kname = (krb5_gss_name_t)pname;
761 code = krb5_aname_to_localname(context, kname->princ,
762 sizeof(lname), lname);
764 *minor = KRB5_NO_LOCALNAME;
765 krb5_free_context(context);
766 return GSS_S_FAILURE;
770 krb5_free_context(context);
771 localname->value = gssalloc_strdup(lname);
772 localname->length = strlen(lname);
774 return (code == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE;
778 static OM_uint32 KRB5_CALLCONV
779 krb5_gss_authorize_localname(OM_uint32 *minor,
780 const gss_name_t pname,
781 gss_const_buffer_t local_user,
782 gss_const_OID name_type)
784 krb5_context context;
785 krb5_error_code code;
786 krb5_gss_name_t kname;
790 if (name_type != GSS_C_NO_OID &&
791 !g_OID_equal(name_type, GSS_C_NT_USER_NAME)) {
792 return GSS_S_BAD_NAMETYPE;
795 kname = (krb5_gss_name_t)pname;
797 code = krb5_gss_init_context(&context);
800 return GSS_S_FAILURE;
803 user = k5alloc(local_user->length + 1, &code);
806 krb5_free_context(context);
807 return GSS_S_FAILURE;
810 memcpy(user, local_user->value, local_user->length);
811 user[local_user->length] = '\0';
813 user_ok = krb5_kuserok(context, kname->princ, user);
816 krb5_free_context(context);
819 return user_ok ? GSS_S_COMPLETE : GSS_S_UNAUTHORIZED;
822 static struct gss_config krb5_mechanism = {
823 { GSS_MECH_KRB5_OID_LENGTH, GSS_MECH_KRB5_OID },
825 krb5_gss_acquire_cred,
826 krb5_gss_release_cred,
827 krb5_gss_init_sec_context,
831 krb5_gss_accept_sec_context,
833 krb5_gss_process_context_token,
834 krb5_gss_delete_sec_context,
835 krb5_gss_context_time,
838 #if defined(IOV_SHIM_EXERCISE_WRAP) || defined(IOV_SHIM_EXERCISE)
843 #if defined(IOV_SHIM_EXERCISE_UNWRAP) || defined(IOV_SHIM_EXERCISE)
848 krb5_gss_display_status,
849 krb5_gss_indicate_mechs,
850 krb5_gss_compare_name,
851 krb5_gss_display_name,
852 krb5_gss_import_name,
853 krb5_gss_release_name,
854 krb5_gss_inquire_cred,
860 krb5_gss_export_sec_context,
861 krb5_gss_import_sec_context,
863 krb5_gss_inquire_cred_by_mech,
864 krb5_gss_inquire_names_for_mech,
865 krb5_gss_inquire_context,
866 krb5_gss_internal_release_oid,
867 krb5_gss_wrap_size_limit,
870 krb5_gss_authorize_localname,
871 krb5_gss_export_name,
872 krb5_gss_duplicate_name,
874 krb5_gss_inquire_sec_context_by_oid,
875 krb5_gss_inquire_cred_by_oid,
876 krb5_gss_set_sec_context_option,
877 krb5_gssspi_set_cred_option,
878 krb5_gssspi_mech_invoke,
879 NULL, /* wrap_aead */
880 NULL, /* unwrap_aead */
883 krb5_gss_wrap_iov_length,
884 NULL, /* complete_auth_token */
885 krb5_gss_acquire_cred_impersonate_name,
886 NULL, /* krb5_gss_add_cred_impersonate_name */
887 NULL, /* display_name_ext */
888 krb5_gss_inquire_name,
889 krb5_gss_get_name_attribute,
890 krb5_gss_set_name_attribute,
891 krb5_gss_delete_name_attribute,
892 krb5_gss_export_name_composite,
893 krb5_gss_map_name_to_any,
894 krb5_gss_release_any_name_mapping,
895 krb5_gss_pseudo_random,
896 NULL, /* set_neg_mechs */
897 krb5_gss_inquire_saslname_for_mech,
898 krb5_gss_inquire_mech_for_saslname,
899 krb5_gss_inquire_attrs_for_mech,
902 static struct gss_config_ext krb5_mechanism_ext = {
903 krb5_gss_acquire_cred_with_password,
906 static struct gss_config_ext iakerb_mechanism_ext = {
907 iakerb_gss_acquire_cred_with_password,
910 #ifdef _GSS_STATIC_LINK
912 static int gss_iakerbmechglue_init(void)
914 struct gss_mech_config mech_iakerb;
915 struct gss_config iakerb_mechanism = krb5_mechanism;
917 /* IAKERB mechanism mirrors krb5, but with different context SPIs */
918 iakerb_mechanism.gss_accept_sec_context = iakerb_gss_accept_sec_context;
919 iakerb_mechanism.gss_init_sec_context = iakerb_gss_init_sec_context;
920 iakerb_mechanism.gss_delete_sec_context = iakerb_gss_delete_sec_context;
921 iakerb_mechanism.gss_acquire_cred = iakerb_gss_acquire_cred;
923 memset(&mech_iakerb, 0, sizeof(mech_iakerb));
924 mech_iakerb.mech = &iakerb_mechanism;
925 mech_iakerb.mech_ext = &iakerb_mechanism_ext;
927 mech_iakerb.mechNameStr = "iakerb";
928 mech_iakerb.mech_type = (gss_OID)gss_mech_iakerb;
929 gssint_register_mechinfo(&mech_iakerb);
934 static int gss_krb5mechglue_init(void)
936 struct gss_mech_config mech_krb5;
938 memset(&mech_krb5, 0, sizeof(mech_krb5));
939 mech_krb5.mech = &krb5_mechanism;
940 mech_krb5.mech_ext = &krb5_mechanism_ext;
942 mech_krb5.mechNameStr = "kerberos_v5";
943 mech_krb5.mech_type = (gss_OID)gss_mech_krb5;
944 gssint_register_mechinfo(&mech_krb5);
946 mech_krb5.mechNameStr = "kerberos_v5_old";
947 mech_krb5.mech_type = (gss_OID)gss_mech_krb5_old;
948 gssint_register_mechinfo(&mech_krb5);
950 mech_krb5.mechNameStr = "mskrb";
951 mech_krb5.mech_type = (gss_OID)gss_mech_krb5_wrong;
952 gssint_register_mechinfo(&mech_krb5);
957 MAKE_INIT_FUNCTION(gss_krb5int_lib_init);
958 MAKE_FINI_FUNCTION(gss_krb5int_lib_fini);
960 gss_mechanism KRB5_CALLCONV
961 gss_mech_initialize(void)
963 return &krb5_mechanism;
965 #endif /* _GSS_STATIC_LINK */
967 int gss_krb5int_lib_init(void)
971 #ifdef SHOW_INITFINI_FUNCS
972 printf("gss_krb5int_lib_init\n");
975 add_error_table(&et_k5g_error_table);
978 err = k5_mutex_finish_init(&gssint_krb5_keytab_lock);
981 #endif /* LEAN_CLIENT */
982 err = k5_key_register(K5_KEY_GSS_KRB5_SET_CCACHE_OLD_NAME, free);
985 err = k5_key_register(K5_KEY_GSS_KRB5_CCACHE_NAME, free);
988 err = k5_key_register(K5_KEY_GSS_KRB5_ERROR_MESSAGE,
989 krb5_gss_delete_error_info);
993 err = k5_mutex_finish_init(&kg_kdc_flag_mutex);
996 err = k5_mutex_finish_init(&kg_vdb.mutex);
1000 #ifdef _GSS_STATIC_LINK
1001 err = gss_krb5mechglue_init();
1004 err = gss_iakerbmechglue_init();
1012 void gss_krb5int_lib_fini(void)
1014 #ifndef _GSS_STATIC_LINK
1015 if (!INITIALIZER_RAN(gss_krb5int_lib_init) || PROGRAM_EXITING()) {
1016 # ifdef SHOW_INITFINI_FUNCS
1017 printf("gss_krb5int_lib_fini: skipping\n");
1022 #ifdef SHOW_INITFINI_FUNCS
1023 printf("gss_krb5int_lib_fini\n");
1025 remove_error_table(&et_k5g_error_table);
1027 k5_key_delete(K5_KEY_GSS_KRB5_SET_CCACHE_OLD_NAME);
1028 k5_key_delete(K5_KEY_GSS_KRB5_CCACHE_NAME);
1029 k5_mutex_destroy(&kg_vdb.mutex);
1031 k5_mutex_destroy(&kg_kdc_flag_mutex);
1034 k5_mutex_destroy(&gssint_krb5_keytab_lock);
1035 #endif /* LEAN_CLIENT */
1038 #ifdef _GSS_STATIC_LINK
1039 extern OM_uint32 gssint_lib_init(void);
1042 OM_uint32 gss_krb5int_initialize_library (void)
1044 #ifdef _GSS_STATIC_LINK
1045 return gssint_mechglue_initialize_library();
1047 return CALL_INIT_FUNCTION(gss_krb5int_lib_init);