2 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
7 * Copyright 1993 by OpenVision Technologies, Inc.
9 * Permission to use, copy, modify, distribute, and sell this software
10 * and its documentation for any purpose is hereby granted without fee,
11 * provided that the above copyright notice appears in all copies and
12 * that both that copyright notice and this permission notice appear in
13 * supporting documentation, and that the name of OpenVision not be used
14 * in advertising or publicity pertaining to distribution of the software
15 * without specific, written prior permission. OpenVision makes no
16 * representations about the suitability of this software for any
17 * purpose. It is provided "as is" without express or implied warranty.
19 * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
20 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
21 * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
22 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
23 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
24 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
25 * PERFORMANCE OF THIS SOFTWARE.
29 * Copyright (C) 1998 by the FundsXpress, INC.
31 * All rights reserved.
33 * Export of this software from the United States of America may require
34 * a specific license from the United States Government. It is the
35 * responsibility of any person or organization contemplating export to
36 * obtain such a license before exporting.
38 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
39 * distribute this software and its documentation for any purpose and
40 * without fee is hereby granted, provided that the above copyright
41 * notice appear in all copies and that both that copyright notice and
42 * this permission notice appear in supporting documentation, and that
43 * the name of FundsXpress. not be used in advertising or publicity pertaining
44 * to distribution of the software without specific, written prior
45 * permission. FundsXpress makes no representations about the suitability of
46 * this software for any purpose. It is provided "as is" without express
47 * or implied warranty.
49 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
50 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
51 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
55 * $Id: gssapi_krb5.c 18343 2006-07-19 18:14:01Z lxs $
59 /* For declaration of krb5_ser_context_init */
61 #include "gssapiP_krb5.h"
63 #include "gss_libinit.h"
68 * Kernel kgssd module debugging aid. The global variable "krb5_log" is a bit
69 * mask which allows various types of log messages to be printed out.
71 * The log levels are defined in:
72 * usr/src/uts/common/gssapi/mechs/krb5/include/k5-int.h
74 * Note, KRB5_LOG_LVL can be assigned via the make invocation.
75 * See KRB5_DEFS in the various Makefiles.
79 /* set the log level to that specified */
80 u_int krb5_log
= KRB5_LOG_LVL
;
82 /* default log level */
84 #endif /* KRB5_LOG_LVL */
86 /** exported constants defined in gssapi_krb5{,_nx}.h **/
88 /* these are bogus, but will compile */
91 * The OID of the draft krb5 mechanism, assigned by IETF, is:
92 * iso(1) org(3) dod(5) internet(1) security(5)
93 * kerberosv5(2) = 1.3.5.1.5.2
94 * The OID of the krb5_name type is:
95 * iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
96 * krb5(2) krb5_name(1) = 1.2.840.113554.1.2.2.1
97 * The OID of the krb5_principal type is:
98 * iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
99 * krb5(2) krb5_principal(2) = 1.2.840.113554.1.2.2.2
100 * The OID of the proposed standard krb5 mechanism is:
101 * iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
102 * krb5(2) = 1.2.840.113554.1.2.2
103 * The OID of the proposed standard krb5 v2 mechanism is:
104 * iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
105 * krb5v2(3) = 1.2.840.113554.1.2.3
110 * Encoding rules: The first two values are encoded in one byte as 40
111 * * value1 + value2. Subsequent values are encoded base 128, most
112 * significant digit first, with the high bit (\200) set on all octets
113 * except the last in each value's encoding.
116 const gss_OID_desc krb5_gss_oid_array
[] = {
117 /* this is the official, rfc-specified OID */
118 {GSS_MECH_KRB5_OID_LENGTH
, GSS_MECH_KRB5_OID
},
119 /* this pre-RFC mech OID */
120 {GSS_MECH_KRB5_OLD_OID_LENGTH
, GSS_MECH_KRB5_OLD_OID
},
121 /* this is the unofficial, incorrect mech OID emitted by MS */
122 {GSS_MECH_KRB5_WRONG_OID_LENGTH
, GSS_MECH_KRB5_WRONG_OID
},
123 /* this is the v2 assigned OID */
124 {9, "\052\206\110\206\367\022\001\002\003"},
125 /* these two are name type OID's */
127 /* 2.1.1. Kerberos Principal Name Form: (rfc 1964)
128 * This name form shall be represented by the Object Identifier {iso(1)
129 * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
130 * krb5(2) krb5_name(1)}. The recommended symbolic name for this type
131 * is "GSS_KRB5_NT_PRINCIPAL_NAME". */
132 {10, "\052\206\110\206\367\022\001\002\002\001"},
134 /* gss_nt_krb5_principal. Object identifier for a krb5_principal. Do not use. */
135 {10, "\052\206\110\206\367\022\001\002\002\002"},
139 const gss_OID_desc
* const gss_mech_krb5
= krb5_gss_oid_array
+0;
140 const gss_OID_desc
* const gss_mech_krb5_old
= krb5_gss_oid_array
+1;
141 const gss_OID_desc
* const gss_mech_krb5_wrong
= krb5_gss_oid_array
+2;
142 const gss_OID_desc
* const gss_nt_krb5_name
= krb5_gss_oid_array
+4;
143 const gss_OID_desc
* const gss_nt_krb5_principal
= krb5_gss_oid_array
+5;
144 const gss_OID_desc
* const GSS_KRB5_NT_PRINCIPAL_NAME
= krb5_gss_oid_array
+4;
146 static const gss_OID_set_desc oidsets
[] = {
147 {1, (gss_OID
) krb5_gss_oid_array
+0},
148 {1, (gss_OID
) krb5_gss_oid_array
+1},
149 {3, (gss_OID
) krb5_gss_oid_array
+0},
150 {1, (gss_OID
) krb5_gss_oid_array
+2},
151 {3, (gss_OID
) krb5_gss_oid_array
+0},
154 const gss_OID_set_desc
* const gss_mech_set_krb5
= oidsets
+0;
155 const gss_OID_set_desc
* const gss_mech_set_krb5_old
= oidsets
+1;
156 const gss_OID_set_desc
* const gss_mech_set_krb5_both
= oidsets
+2;
158 g_set kg_vdb
= G_SET_INIT
;
160 /** default credential support */
165 * init_sec_context() will explicitly re-acquire default credentials,
166 * so handling the expiration/invalidation condition here isn't needed.
169 kg_get_defcred(minor_status
, cred
)
170 OM_uint32
*minor_status
;
175 if ((major
= krb5_gss_acquire_cred(minor_status
,
176 (gss_name_t
) NULL
, GSS_C_INDEFINITE
,
177 GSS_C_NULL_OID_SET
, GSS_C_INITIATE
,
178 cred
, NULL
, NULL
)) && GSS_ERROR(major
)) {
182 return(GSS_S_COMPLETE
);
186 kg_sync_ccache_name (krb5_context context
, OM_uint32
*minor_status
)
191 * Sync up the context ccache name with the GSSAPI ccache name.
192 * If kg_ccache_name is NULL -- normal unless someone has called
193 * gss_krb5_ccache_name() -- then the system default ccache will
194 * be picked up and used by resetting the context default ccache.
195 * This is needed for platforms which support multiple ccaches.
199 /* if NULL, resets the context default ccache */
200 err
= krb5_cc_set_default_name(context
,
201 (char *) k5_getspecific(K5_KEY_GSS_KRB5_CCACHE_NAME
));
205 return (*minor_status
== 0) ? GSS_S_COMPLETE
: GSS_S_FAILURE
;
208 /* This function returns whether or not the caller set a cccache name. Used by
209 * gss_acquire_cred to figure out if the caller wants to only look at this
210 * ccache or search the cache collection for the desired name */
212 kg_caller_provided_ccache_name (OM_uint32
*minor_status
,
213 int *out_caller_provided_name
)
215 if (out_caller_provided_name
) {
216 *out_caller_provided_name
=
217 (k5_getspecific(K5_KEY_GSS_KRB5_CCACHE_NAME
) != NULL
);
221 return GSS_S_COMPLETE
;
225 kg_get_ccache_name (OM_uint32
*minor_status
, const char **out_name
)
227 const char *name
= NULL
;
229 char *kg_ccache_name
;
231 kg_ccache_name
= k5_getspecific(K5_KEY_GSS_KRB5_CCACHE_NAME
);
233 if (kg_ccache_name
!= NULL
) {
234 name
= strdup(kg_ccache_name
);
238 krb5_context context
= NULL
;
240 /* Reset the context default ccache (see text above), and then
242 err
= krb5_gss_init_context(&context
);
244 err
= krb5_cc_set_default_name (context
, NULL
);
246 name
= krb5_cc_default_name(context
);
254 save_error_info(err
, context
);
256 krb5_free_context(context
);
266 return (*minor_status
== 0) ? GSS_S_COMPLETE
: GSS_S_FAILURE
;
270 kg_set_ccache_name (OM_uint32
*minor_status
, const char *name
)
272 char *new_name
= NULL
;
274 char *kg_ccache_name
;
275 krb5_error_code kerr
;
278 new_name
= malloc(strlen(name
) + 1);
279 if (new_name
== NULL
) {
280 *minor_status
= ENOMEM
;
281 return GSS_S_FAILURE
;
283 strcpy(new_name
, name
);
286 kg_ccache_name
= k5_getspecific(K5_KEY_GSS_KRB5_CCACHE_NAME
);
287 swap
= kg_ccache_name
;
288 kg_ccache_name
= new_name
;
290 kerr
= k5_setspecific(K5_KEY_GSS_KRB5_CCACHE_NAME
, kg_ccache_name
);
292 /* Can't store, so free up the storage. */
293 free(kg_ccache_name
);
294 /* ??? free(new_name); */
295 *minor_status
= kerr
;
296 return GSS_S_FAILURE
;
301 return GSS_S_COMPLETE
;
304 #define g_OID_prefix_equal(o1, o2) \
305 (((o1)->length >= (o2)->length) && \
306 (memcmp((o1)->elements, (o2)->elements, (o2)->length) == 0))
309 * gss_inquire_sec_context_by_oid() methods
313 OM_uint32 (*func
)(OM_uint32
*, const gss_ctx_id_t
, const gss_OID
, gss_buffer_set_t
*);
314 } krb5_gss_inquire_sec_context_by_oid_ops
[] = {
316 {GSS_KRB5_GET_TKT_FLAGS_OID_LENGTH
, GSS_KRB5_GET_TKT_FLAGS_OID
},
317 gss_krb5int_get_tkt_flags
320 {GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID_LENGTH
, GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID
},
321 gss_krb5int_extract_authz_data_from_sec_context
324 {GSS_KRB5_INQ_SSPI_SESSION_KEY_OID_LENGTH
, GSS_KRB5_INQ_SSPI_SESSION_KEY_OID
},
325 gss_krb5int_inq_session_key
328 {GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID_LENGTH
, GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID
},
329 gss_krb5int_export_lucid_sec_context
332 {GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID_LENGTH
, GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID
},
333 gss_krb5int_extract_authtime_from_sec_context
338 krb5_gss_inquire_sec_context_by_oid (OM_uint32
*minor_status
,
339 const gss_ctx_id_t context_handle
,
340 const gss_OID desired_object
,
341 gss_buffer_set_t
*data_set
)
343 krb5_gss_ctx_id_rec
*ctx
;
346 if (minor_status
== NULL
)
347 return GSS_S_CALL_INACCESSIBLE_WRITE
;
351 if (desired_object
== GSS_C_NO_OID
)
352 return GSS_S_CALL_INACCESSIBLE_READ
;
354 if (data_set
== NULL
)
355 return GSS_S_CALL_INACCESSIBLE_WRITE
;
357 *data_set
= GSS_C_NO_BUFFER_SET
;
359 if (!kg_validate_ctx_id(context_handle
))
360 return GSS_S_NO_CONTEXT
;
362 ctx
= (krb5_gss_ctx_id_rec
*) context_handle
;
364 if (!ctx
->established
)
365 return GSS_S_NO_CONTEXT
;
367 for (i
= 0; i
< sizeof(krb5_gss_inquire_sec_context_by_oid_ops
)/
368 sizeof(krb5_gss_inquire_sec_context_by_oid_ops
[0]); i
++) {
369 if (g_OID_prefix_equal(desired_object
, &krb5_gss_inquire_sec_context_by_oid_ops
[i
].oid
)) {
370 return (*krb5_gss_inquire_sec_context_by_oid_ops
[i
].func
)(minor_status
,
377 *minor_status
= EINVAL
;
379 return GSS_S_UNAVAILABLE
;
383 #if 0 /* Solaris Kerberos - revisit for full 1.7/next resync */
384 MAKE_INIT_FUNCTION(gss_krb5int_lib_init
);
385 MAKE_FINI_FUNCTION(gss_krb5int_lib_fini
);
388 OM_uint32
gss_krb5int_initialize_library (void)
390 #if 0 /* Solaris Kerberos - revisit for full 1.7/next resync */
391 #ifdef _GSS_STATIC_LINK
392 return gssint_mechglue_initialize_library();
394 return CALL_INIT_FUNCTION(gss_krb5int_lib_init
);
397 return gssint_initialize_library();