2 * Unix SMB/CIFS implementation.
4 * Simple GSSAPI wrappers
6 * Copyright (c) 2012 Andreas Schneider <asn@samba.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
23 #include "gss_samba.h"
27 #if !defined(HAVE_GSS_OID_EQUAL)
28 int smb_gss_oid_equal(const gss_OID first_oid
, const gss_OID second_oid
)
30 if (first_oid
== GSS_C_NO_OID
|| second_oid
== GSS_C_NO_OID
) {
34 if (first_oid
== second_oid
) {
38 if ((first_oid
)->length
!= (second_oid
)->length
) {
42 if (memcmp((first_oid
)->elements
, (second_oid
)->elements
,
43 (first_oid
)->length
) == 0) {
49 #endif /* !HAVE_GSS_OID_EQUAL */
51 /* wrapper around gss_krb5_import_cred() that prefers to use gss_acquire_cred_from()
52 * if this GSSAPI extension is available. gss_acquire_cred_from() is properly
53 * interposed by GSSPROXY while gss_krb5_import_cred() is not.
55 * This wrapper requires a proper krb5_context to resolve ccache name.
56 * All gss_krb5_import_cred() callers in Samba already have krb5_context available. */
57 uint32_t smb_gss_krb5_import_cred(uint32_t *minor_status
,
60 krb5_principal keytab_principal
,
64 return smb_gss_mech_import_cred(minor_status
,
73 uint32_t smb_gss_mech_import_cred(OM_uint32
*minor_status
,
76 krb5_principal keytab_principal
,
78 const struct gss_OID_desc_struct
*mech
,
81 uint32_t major_status
= 0;
83 #ifdef HAVE_GSS_ACQUIRE_CRED_FROM
85 gss_key_value_element_desc ccache_element
= {
90 gss_key_value_element_desc keytab_element
= {
95 gss_key_value_element_desc elements
[2];
97 gss_key_value_set_desc cred_store
= {
98 .elements
= &ccache_element
,
102 /* we are interested exclusively in krb5 credentials,
103 * indicate to GSSAPI that we are not interested in any other
105 gss_OID_set_desc mech_set
= {
107 .elements
= discard_const_p(struct gss_OID_desc_struct
,
111 gss_cred_usage_t cred_usage
= GSS_C_INITIATE
;
112 gss_name_t name
= NULL
;
113 gss_buffer_desc pr_name
= {
119 major_status
= krb5_cc_get_full_name(ctx
,
121 discard_const(&ccache_element
.value
));
122 if (major_status
!= 0) {
127 if (keytab
!= NULL
) {
128 keytab_element
.value
= malloc(4096);
129 if (!keytab_element
.value
) {
132 major_status
= krb5_kt_get_name(ctx
,
134 discard_const(keytab_element
.value
), 4096);
135 if (major_status
!= 0) {
136 free(discard_const(keytab_element
.value
));
139 cred_usage
= GSS_C_ACCEPT
;
140 cred_store
.elements
= &keytab_element
;
142 if (keytab_principal
!= NULL
) {
143 major_status
= krb5_unparse_name(ctx
, keytab_principal
, (char**)&pr_name
.value
);
144 if (major_status
!= 0) {
145 free(discard_const(keytab_element
.value
));
148 pr_name
.length
= strlen(pr_name
.value
);
150 major_status
= gss_import_name(minor_status
,
152 discard_const(GSS_KRB5_NT_PRINCIPAL_NAME
),
154 if (major_status
!= 0) {
155 krb5_free_unparsed_name(ctx
, pr_name
.value
);
156 free(discard_const(keytab_element
.value
));
162 if (id
!= NULL
&& keytab
!= NULL
) {
163 elements
[0] = ccache_element
;
164 elements
[1] = keytab_element
;
166 cred_store
.elements
= elements
;
167 cred_store
.count
= 2;
168 cred_usage
= GSS_C_BOTH
;
171 major_status
= gss_acquire_cred_from(minor_status
,
181 if (pr_name
.value
!= NULL
) {
182 (void)gss_release_name(&minor
, &name
);
183 krb5_free_unparsed_name(ctx
, pr_name
.value
);
185 if (keytab_element
.value
!= NULL
) {
186 free(discard_const(keytab_element
.value
));
188 krb5_free_string(ctx
, discard_const(ccache_element
.value
));
190 major_status
= gss_krb5_import_cred(minor_status
,
195 if (major_status
== (GSS_S_CALL_BAD_STRUCTURE
|GSS_S_BAD_NAME
)) {
196 if ((keytab_principal
== NULL
) && (keytab
!= NULL
)) {
197 /* No principal was specified and MIT krb5 1.9 version failed.
198 * We have to fall back to set global acceptor identity */
199 gss_OID_set_desc mech_set
;
200 char *kt_name
= NULL
;
202 kt_name
= malloc(4096);
207 major_status
= krb5_kt_get_name(ctx
,
210 if (major_status
!= 0) {
215 major_status
= gsskrb5_register_acceptor_identity(kt_name
);
221 /* We are dealing with krb5 GSSAPI mech in this fallback */
224 discard_const_p(struct gss_OID_desc_struct
,
226 major_status
= gss_acquire_cred(minor_status
,
241 #endif /* HAVE_GSSAPI */