2 Unix SMB/CIFS implementation.
4 Handle user credentials (as regards krb5)
6 Copyright (C) Jelmer Vernooij 2005
7 Copyright (C) Tim Potter 2001
8 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include "system/kerberos.h"
27 #include "auth/kerberos/kerberos.h"
29 int cli_credentials_get_krb5_context(struct cli_credentials *cred,
30 struct smb_krb5_context **smb_krb5_context)
33 if (cred->smb_krb5_context) {
34 *smb_krb5_context = cred->smb_krb5_context;
38 ret = smb_krb5_init_context(cred, &cred->smb_krb5_context);
42 *smb_krb5_context = cred->smb_krb5_context;
46 int cli_credentials_set_from_ccache(struct cli_credentials *cred,
47 enum credentials_obtained obtained)
55 ret = krb5_cc_get_principal(cred->ccache->smb_krb5_context->krb5_context,
56 cred->ccache->ccache, &princ);
59 char *err_mess = smb_get_krb5_error_message(cred->ccache->smb_krb5_context->krb5_context, ret, cred);
60 DEBUG(1,("failed to get principal from ccache: %s\n",
62 talloc_free(err_mess);
66 ret = krb5_unparse_name(cred->ccache->smb_krb5_context->krb5_context, princ, &name);
68 char *err_mess = smb_get_krb5_error_message(cred->ccache->smb_krb5_context->krb5_context, ret, cred);
69 DEBUG(1,("failed to unparse principal from ccache: %s\n",
71 talloc_free(err_mess);
75 realm = krb5_princ_realm(cred->ccache->smb_krb5_context->krb5_context, princ);
77 cli_credentials_set_principal(cred, name, obtained);
81 krb5_free_principal(cred->ccache->smb_krb5_context->krb5_context, princ);
83 cred->ccache_obtained = obtained;
88 /* Free a memory ccache */
89 static int free_mccache(void *ptr) {
90 struct ccache_container *ccc = ptr;
91 krb5_cc_destroy(ccc->smb_krb5_context->krb5_context, ccc->ccache);
96 /* Free a disk-based ccache */
97 static int free_dccache(void *ptr) {
98 struct ccache_container *ccc = ptr;
99 krb5_cc_close(ccc->smb_krb5_context->krb5_context, ccc->ccache);
104 int cli_credentials_set_ccache(struct cli_credentials *cred,
106 enum credentials_obtained obtained)
109 krb5_principal princ;
110 struct ccache_container *ccc = talloc(cred, struct ccache_container);
115 ret = cli_credentials_get_krb5_context(cred, &ccc->smb_krb5_context);
120 talloc_reference(ccc, ccc->smb_krb5_context);
123 ret = krb5_cc_resolve(ccc->smb_krb5_context->krb5_context, name, &ccc->ccache);
125 DEBUG(1,("failed to read krb5 ccache: %s: %s\n",
127 smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc)));
132 ret = krb5_cc_default(ccc->smb_krb5_context->krb5_context, &ccc->ccache);
134 DEBUG(3,("failed to read default krb5 ccache: %s\n",
135 smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc)));
141 talloc_set_destructor(ccc, free_dccache);
143 ret = krb5_cc_get_principal(ccc->smb_krb5_context->krb5_context, ccc->ccache, &princ);
146 DEBUG(3,("failed to get principal from default ccache: %s\n",
147 smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc)));
152 krb5_free_principal(ccc->smb_krb5_context->krb5_context, princ);
155 talloc_steal(cred, ccc);
157 ret = cli_credentials_set_from_ccache(cred, obtained);
167 int cli_credentials_new_ccache(struct cli_credentials *cred, struct ccache_container **_ccc)
171 struct ccache_container *ccc = talloc(cred, struct ccache_container);
177 rand_string = generate_random_str(NULL, 16);
183 ccache_name = talloc_asprintf(ccc, "MEMORY:%s",
185 talloc_free(rand_string);
192 ret = cli_credentials_get_krb5_context(cred, &ccc->smb_krb5_context);
197 talloc_reference(ccc, ccc->smb_krb5_context);
199 ret = krb5_cc_resolve(ccc->smb_krb5_context->krb5_context, ccache_name, &ccc->ccache);
201 DEBUG(1,("failed to generate a new krb5 ccache (%s): %s\n",
203 smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc)));
204 talloc_free(ccache_name);
209 talloc_set_destructor(ccc, free_mccache);
212 talloc_steal(cred, ccc);
213 talloc_free(ccache_name);
222 int cli_credentials_get_ccache(struct cli_credentials *cred,
223 struct ccache_container **ccc)
227 if (cred->ccache_obtained >= (MAX(cred->principal_obtained,
228 cred->username_obtained))) {
232 if (cli_credentials_is_anonymous(cred)) {
236 ret = cli_credentials_new_ccache(cred, NULL);
240 ret = kinit_to_ccache(cred, cred, cred->ccache->smb_krb5_context, cred->ccache->ccache);
244 ret = cli_credentials_set_from_ccache(cred, cred->principal_obtained);
253 static int free_gssapi_creds(void *ptr) {
254 OM_uint32 min_stat, maj_stat;
255 struct gssapi_creds_container *gcc = ptr;
256 maj_stat = gss_release_cred(&min_stat,
261 int cli_credentials_get_client_gss_creds(struct cli_credentials *cred,
262 struct gssapi_creds_container **_gcc)
265 OM_uint32 maj_stat, min_stat;
266 struct gssapi_creds_container *gcc;
267 struct ccache_container *ccache;
268 if (cred->gss_creds_obtained >= (MAX(cred->ccache_obtained,
269 MAX(cred->principal_obtained,
270 cred->username_obtained)))) {
271 *_gcc = cred->gssapi_creds;
274 ret = cli_credentials_get_ccache(cred,
277 DEBUG(1, ("Failed to get CCACHE for GSSAPI client: %s\n", error_message(ret)));
281 gcc = talloc(cred, struct gssapi_creds_container);
286 maj_stat = gss_krb5_import_ccache(&min_stat, ccache->ccache,
296 cred->gss_creds_obtained = cred->ccache_obtained;
297 talloc_set_destructor(gcc, free_gssapi_creds);
298 cred->gssapi_creds = gcc;
305 Set a gssapi cred_id_t into the credentails system.
307 This grabs the credentials both 'intact' and getting the krb5
308 ccache out of it. This routine can be generalised in future for
309 the case where we deal with GSSAPI mechs other than krb5.
311 On sucess, the caller must not free gssapi_cred, as it now belongs
312 to the credentials system.
315 int cli_credentials_set_client_gss_creds(struct cli_credentials *cred,
316 gss_cred_id_t gssapi_cred,
317 enum credentials_obtained obtained)
320 OM_uint32 maj_stat, min_stat;
321 struct ccache_container *ccc;
322 struct gssapi_creds_container *gcc = talloc(cred, struct gssapi_creds_container);
327 ret = cli_credentials_new_ccache(cred, &ccc);
332 maj_stat = gss_krb5_copy_ccache(&min_stat,
333 gssapi_cred, ccc->ccache);
343 ret = cli_credentials_set_from_ccache(cred, obtained);
346 gcc->creds = gssapi_cred;
347 talloc_set_destructor(gcc, free_gssapi_creds);
349 cred->gss_creds_obtained = obtained;
350 cred->gssapi_creds = gcc;
355 int cli_credentials_get_keytab(struct cli_credentials *cred,
356 struct keytab_container **_ktc)
359 struct keytab_container *ktc;
360 struct smb_krb5_context *smb_krb5_context;
362 if (cred->keytab_obtained >= (MAX(cred->principal_obtained,
363 cred->username_obtained))) {
364 *_ktc = cred->keytab;
368 if (cli_credentials_is_anonymous(cred)) {
372 ret = cli_credentials_get_krb5_context(cred, &smb_krb5_context);
377 ret = create_memory_keytab(cred, cred, smb_krb5_context, &ktc);
382 cred->keytab_obtained = (MAX(cred->principal_obtained,
383 cred->username_obtained));
386 *_ktc = cred->keytab;
394 void cli_credentials_set_kvno(struct cli_credentials *cred,
401 * Return Kerberos KVNO
404 int cli_credentials_get_kvno(struct cli_credentials *cred)
409 const char *cli_credentials_get_salt_principal(struct cli_credentials *cred)
411 return cred->salt_principal;
414 void cli_credentials_set_salt_principal(struct cli_credentials *cred, const char *principal)
416 cred->salt_principal = talloc_strdup(cred, principal);