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 3 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, see <http://www.gnu.org/licenses/>.
25 #include "system/kerberos.h"
26 #include "auth/kerberos/kerberos.h"
27 #include "auth/credentials/credentials.h"
28 #include "auth/credentials/credentials_proto.h"
29 #include "auth/credentials/credentials_krb5.h"
30 #include "auth/kerberos/kerberos_credentials.h"
31 #include "auth/kerberos/kerberos_srv_keytab.h"
32 #include "auth/kerberos/kerberos_util.h"
33 #include "param/param.h"
35 static void cli_credentials_invalidate_client_gss_creds(
36 struct cli_credentials
*cred
,
37 enum credentials_obtained obtained
);
39 _PUBLIC_
int cli_credentials_get_krb5_context(struct cli_credentials
*cred
,
40 struct loadparm_context
*lp_ctx
,
41 struct smb_krb5_context
**smb_krb5_context
)
44 if (cred
->smb_krb5_context
) {
45 *smb_krb5_context
= cred
->smb_krb5_context
;
49 ret
= smb_krb5_init_context(cred
, NULL
, lp_ctx
,
50 &cred
->smb_krb5_context
);
52 cred
->smb_krb5_context
= NULL
;
55 *smb_krb5_context
= cred
->smb_krb5_context
;
59 /* For most predictable behaviour, this needs to be called directly after the cli_credentials_init(),
60 * otherwise we may still have references to the old smb_krb5_context in a credential cache etc
62 _PUBLIC_ NTSTATUS
cli_credentials_set_krb5_context(struct cli_credentials
*cred
,
63 struct smb_krb5_context
*smb_krb5_context
)
65 if (smb_krb5_context
== NULL
) {
66 talloc_unlink(cred
, cred
->smb_krb5_context
);
67 cred
->smb_krb5_context
= NULL
;
71 if (!talloc_reference(cred
, smb_krb5_context
)) {
72 return NT_STATUS_NO_MEMORY
;
74 cred
->smb_krb5_context
= smb_krb5_context
;
78 static int cli_credentials_set_from_ccache(struct cli_credentials
*cred
,
79 struct ccache_container
*ccache
,
80 enum credentials_obtained obtained
,
81 const char **error_string
)
88 if (cred
->ccache_obtained
> obtained
) {
92 ret
= krb5_cc_get_principal(ccache
->smb_krb5_context
->krb5_context
,
93 ccache
->ccache
, &princ
);
96 (*error_string
) = talloc_asprintf(cred
, "failed to get principal from ccache: %s\n",
97 smb_get_krb5_error_message(ccache
->smb_krb5_context
->krb5_context
,
102 ret
= krb5_unparse_name(ccache
->smb_krb5_context
->krb5_context
, princ
, &name
);
104 (*error_string
) = talloc_asprintf(cred
, "failed to unparse principal from ccache: %s\n",
105 smb_get_krb5_error_message(ccache
->smb_krb5_context
->krb5_context
,
110 cli_credentials_set_principal(cred
, name
, obtained
);
114 krb5_free_principal(ccache
->smb_krb5_context
->krb5_context
, princ
);
116 /* set the ccache_obtained here, as it just got set to UNINITIALISED by the calls above */
117 cred
->ccache_obtained
= obtained
;
122 /* Free a memory ccache */
123 static int free_mccache(struct ccache_container
*ccc
)
125 krb5_cc_destroy(ccc
->smb_krb5_context
->krb5_context
, ccc
->ccache
);
130 /* Free a disk-based ccache */
131 static int free_dccache(struct ccache_container
*ccc
) {
132 krb5_cc_close(ccc
->smb_krb5_context
->krb5_context
, ccc
->ccache
);
137 _PUBLIC_
int cli_credentials_set_ccache(struct cli_credentials
*cred
,
138 struct loadparm_context
*lp_ctx
,
140 enum credentials_obtained obtained
,
141 const char **error_string
)
144 krb5_principal princ
;
145 struct ccache_container
*ccc
;
146 if (cred
->ccache_obtained
> obtained
) {
150 ccc
= talloc(cred
, struct ccache_container
);
152 (*error_string
) = error_message(ENOMEM
);
156 ret
= cli_credentials_get_krb5_context(cred
, lp_ctx
,
157 &ccc
->smb_krb5_context
);
159 (*error_string
) = error_message(ret
);
163 if (!talloc_reference(ccc
, ccc
->smb_krb5_context
)) {
165 (*error_string
) = error_message(ENOMEM
);
170 ret
= krb5_cc_resolve(ccc
->smb_krb5_context
->krb5_context
, name
, &ccc
->ccache
);
172 (*error_string
) = talloc_asprintf(cred
, "failed to read krb5 ccache: %s: %s\n",
174 smb_get_krb5_error_message(ccc
->smb_krb5_context
->krb5_context
,
180 ret
= krb5_cc_default(ccc
->smb_krb5_context
->krb5_context
, &ccc
->ccache
);
182 (*error_string
) = talloc_asprintf(cred
, "failed to read default krb5 ccache: %s\n",
183 smb_get_krb5_error_message(ccc
->smb_krb5_context
->krb5_context
,
190 talloc_set_destructor(ccc
, free_dccache
);
192 ret
= krb5_cc_get_principal(ccc
->smb_krb5_context
->krb5_context
, ccc
->ccache
, &princ
);
195 krb5_free_principal(ccc
->smb_krb5_context
->krb5_context
, princ
);
196 ret
= cli_credentials_set_from_ccache(cred
, ccc
, obtained
, error_string
);
199 (*error_string
) = error_message(ret
);
204 cred
->ccache_obtained
= obtained
;
205 talloc_steal(cred
, ccc
);
207 cli_credentials_invalidate_client_gss_creds(cred
, cred
->ccache_obtained
);
214 static int cli_credentials_new_ccache(struct cli_credentials
*cred
,
215 struct loadparm_context
*lp_ctx
,
217 struct ccache_container
**_ccc
,
218 const char **error_string
)
220 bool must_free_cc_name
= false;
222 struct ccache_container
*ccc
= talloc(cred
, struct ccache_container
);
227 ret
= cli_credentials_get_krb5_context(cred
, lp_ctx
,
228 &ccc
->smb_krb5_context
);
231 (*error_string
) = talloc_asprintf(cred
, "Failed to get krb5_context: %s",
235 if (!talloc_reference(ccc
, ccc
->smb_krb5_context
)) {
237 (*error_string
) = strerror(ENOMEM
);
242 must_free_cc_name
= true;
244 if (lpcfg_parm_bool(lp_ctx
, NULL
, "credentials", "krb5_cc_file", false)) {
245 ccache_name
= talloc_asprintf(ccc
, "FILE:/tmp/krb5_cc_samba_%u_%p",
246 (unsigned int)getpid(), ccc
);
248 ccache_name
= talloc_asprintf(ccc
, "MEMORY:%p",
254 (*error_string
) = strerror(ENOMEM
);
259 ret
= krb5_cc_resolve(ccc
->smb_krb5_context
->krb5_context
, ccache_name
,
262 (*error_string
) = talloc_asprintf(cred
, "failed to resolve a krb5 ccache (%s): %s\n",
264 smb_get_krb5_error_message(ccc
->smb_krb5_context
->krb5_context
,
266 talloc_free(ccache_name
);
271 if (strncasecmp(ccache_name
, "MEMORY:", 7) == 0) {
272 talloc_set_destructor(ccc
, free_mccache
);
274 talloc_set_destructor(ccc
, free_dccache
);
277 if (must_free_cc_name
) {
278 talloc_free(ccache_name
);
286 _PUBLIC_
int cli_credentials_get_named_ccache(struct cli_credentials
*cred
,
287 struct tevent_context
*event_ctx
,
288 struct loadparm_context
*lp_ctx
,
290 struct ccache_container
**ccc
,
291 const char **error_string
)
294 enum credentials_obtained obtained
;
296 if (cred
->machine_account_pending
) {
297 cli_credentials_set_machine_account(cred
, lp_ctx
);
300 if (cred
->ccache_obtained
>= cred
->ccache_threshold
&&
301 cred
->ccache_obtained
> CRED_UNINITIALISED
) {
303 bool expired
= false;
304 ret
= krb5_cc_get_lifetime(cred
->ccache
->smb_krb5_context
->krb5_context
,
305 cred
->ccache
->ccache
, &lifetime
);
306 if (ret
== KRB5_CC_END
) {
307 /* If we have a particular ccache set, without
308 * an initial ticket, then assume there is a
310 } else if (ret
== 0) {
312 DEBUG(3, ("Ticket in credentials cache for %s expired, will refresh\n",
313 cli_credentials_get_principal(cred
, cred
)));
315 } else if (lifetime
< 300) {
316 DEBUG(3, ("Ticket in credentials cache for %s will shortly expire (%u secs), will refresh\n",
317 cli_credentials_get_principal(cred
, cred
), (unsigned int)lifetime
));
321 (*error_string
) = talloc_asprintf(cred
, "failed to get ccache lifetime: %s\n",
322 smb_get_krb5_error_message(cred
->ccache
->smb_krb5_context
->krb5_context
,
327 DEBUG(5, ("Ticket in credentials cache for %s will expire in %u secs\n",
328 cli_credentials_get_principal(cred
, cred
), (unsigned int)lifetime
));
335 if (cli_credentials_is_anonymous(cred
)) {
336 (*error_string
) = "Cannot get anonymous kerberos credentials";
340 ret
= cli_credentials_new_ccache(cred
, lp_ctx
, ccache_name
, ccc
, error_string
);
345 ret
= kinit_to_ccache(cred
, cred
, (*ccc
)->smb_krb5_context
, event_ctx
, (*ccc
)->ccache
, &obtained
, error_string
);
350 ret
= cli_credentials_set_from_ccache(cred
, *ccc
,
351 obtained
, error_string
);
354 cred
->ccache_obtained
= cred
->principal_obtained
;
358 cli_credentials_invalidate_client_gss_creds(cred
, cred
->ccache_obtained
);
362 _PUBLIC_
int cli_credentials_get_ccache(struct cli_credentials
*cred
,
363 struct tevent_context
*event_ctx
,
364 struct loadparm_context
*lp_ctx
,
365 struct ccache_container
**ccc
,
366 const char **error_string
)
368 return cli_credentials_get_named_ccache(cred
, event_ctx
, lp_ctx
, NULL
, ccc
, error_string
);
371 /* We have good reason to think the ccache in these credentials is invalid - blow it away */
372 static void cli_credentials_unconditionally_invalidate_client_gss_creds(struct cli_credentials
*cred
)
374 if (cred
->client_gss_creds_obtained
> CRED_UNINITIALISED
) {
375 talloc_unlink(cred
, cred
->client_gss_creds
);
376 cred
->client_gss_creds
= NULL
;
378 cred
->client_gss_creds_obtained
= CRED_UNINITIALISED
;
381 void cli_credentials_invalidate_client_gss_creds(struct cli_credentials
*cred
,
382 enum credentials_obtained obtained
)
384 /* If the caller just changed the username/password etc, then
385 * any cached credentials are now invalid */
386 if (obtained
>= cred
->client_gss_creds_obtained
) {
387 if (cred
->client_gss_creds_obtained
> CRED_UNINITIALISED
) {
388 talloc_unlink(cred
, cred
->client_gss_creds
);
389 cred
->client_gss_creds
= NULL
;
391 cred
->client_gss_creds_obtained
= CRED_UNINITIALISED
;
393 /* Now that we know that the data is 'this specified', then
394 * don't allow something less 'known' to be returned as a
395 * ccache. Ie, if the username is on the command line, we
396 * don't want to later guess to use a file-based ccache */
397 if (obtained
> cred
->client_gss_creds_threshold
) {
398 cred
->client_gss_creds_threshold
= obtained
;
402 /* We have good reason to think this CCACHE is invalid. Blow it away */
403 static void cli_credentials_unconditionally_invalidate_ccache(struct cli_credentials
*cred
)
405 if (cred
->ccache_obtained
> CRED_UNINITIALISED
) {
406 talloc_unlink(cred
, cred
->ccache
);
409 cred
->ccache_obtained
= CRED_UNINITIALISED
;
411 cli_credentials_unconditionally_invalidate_client_gss_creds(cred
);
414 _PUBLIC_
void cli_credentials_invalidate_ccache(struct cli_credentials
*cred
,
415 enum credentials_obtained obtained
)
417 /* If the caller just changed the username/password etc, then
418 * any cached credentials are now invalid */
419 if (obtained
>= cred
->ccache_obtained
) {
420 if (cred
->ccache_obtained
> CRED_UNINITIALISED
) {
421 talloc_unlink(cred
, cred
->ccache
);
424 cred
->ccache_obtained
= CRED_UNINITIALISED
;
426 /* Now that we know that the data is 'this specified', then
427 * don't allow something less 'known' to be returned as a
428 * ccache. i.e, if the username is on the command line, we
429 * don't want to later guess to use a file-based ccache */
430 if (obtained
> cred
->ccache_threshold
) {
431 cred
->ccache_threshold
= obtained
;
434 cli_credentials_invalidate_client_gss_creds(cred
,
438 static int free_gssapi_creds(struct gssapi_creds_container
*gcc
)
441 (void)gss_release_cred(&min_stat
, &gcc
->creds
);
445 _PUBLIC_
int cli_credentials_get_client_gss_creds(struct cli_credentials
*cred
,
446 struct tevent_context
*event_ctx
,
447 struct loadparm_context
*lp_ctx
,
448 struct gssapi_creds_container
**_gcc
,
449 const char **error_string
)
452 OM_uint32 maj_stat
, min_stat
;
453 struct gssapi_creds_container
*gcc
;
454 struct ccache_container
*ccache
;
455 gss_buffer_desc empty_buffer
= GSS_C_EMPTY_BUFFER
;
456 krb5_enctype
*etypes
= NULL
;
458 if (cred
->client_gss_creds_obtained
>= cred
->client_gss_creds_threshold
&&
459 cred
->client_gss_creds_obtained
> CRED_UNINITIALISED
) {
460 bool expired
= false;
461 OM_uint32 lifetime
= 0;
462 gss_cred_usage_t usage
= 0;
463 maj_stat
= gss_inquire_cred(&min_stat
, cred
->client_gss_creds
->creds
,
464 NULL
, &lifetime
, &usage
, NULL
);
465 if (maj_stat
== GSS_S_CREDENTIALS_EXPIRED
) {
466 DEBUG(3, ("Credentials for %s expired, must refresh credentials cache\n", cli_credentials_get_principal(cred
, cred
)));
468 } else if (maj_stat
== GSS_S_COMPLETE
&& lifetime
< 300) {
469 DEBUG(3, ("Credentials for %s will expire shortly (%u sec), must refresh credentials cache\n", cli_credentials_get_principal(cred
, cred
), lifetime
));
471 } else if (maj_stat
!= GSS_S_COMPLETE
) {
472 *error_string
= talloc_asprintf(cred
, "inquiry of credential lifefime via GSSAPI gss_inquire_cred failed: %s\n",
473 gssapi_error_string(cred
, maj_stat
, min_stat
, NULL
));
477 cli_credentials_unconditionally_invalidate_client_gss_creds(cred
);
479 DEBUG(5, ("GSSAPI credentials for %s will expire in %u secs\n",
480 cli_credentials_get_principal(cred
, cred
), (unsigned int)lifetime
));
482 *_gcc
= cred
->client_gss_creds
;
487 ret
= cli_credentials_get_ccache(cred
, event_ctx
, lp_ctx
,
488 &ccache
, error_string
);
490 if (cli_credentials_get_kerberos_state(cred
) == CRED_MUST_USE_KERBEROS
) {
491 DEBUG(1, ("Failed to get kerberos credentials (kerberos required): %s\n", *error_string
));
493 DEBUG(4, ("Failed to get kerberos credentials: %s\n", *error_string
));
498 gcc
= talloc(cred
, struct gssapi_creds_container
);
500 (*error_string
) = error_message(ENOMEM
);
504 maj_stat
= gss_krb5_import_cred(&min_stat
, ccache
->ccache
, NULL
, NULL
,
506 if ((maj_stat
== GSS_S_FAILURE
) && (min_stat
== (OM_uint32
)KRB5_CC_END
|| min_stat
== (OM_uint32
) KRB5_CC_NOTFOUND
)) {
507 /* This CCACHE is no good. Ensure we don't use it again */
508 cli_credentials_unconditionally_invalidate_ccache(cred
);
510 /* Now try again to get a ccache */
511 ret
= cli_credentials_get_ccache(cred
, event_ctx
, lp_ctx
,
512 &ccache
, error_string
);
514 DEBUG(1, ("Failed to re-get CCACHE for GSSAPI client: %s\n", error_message(ret
)));
518 maj_stat
= gss_krb5_import_cred(&min_stat
, ccache
->ccache
, NULL
, NULL
,
530 (*error_string
) = talloc_asprintf(cred
, "gss_krb5_import_cred failed: %s", error_message(ret
));
535 * transfer the enctypes from the smb_krb5_context to the gssapi layer
537 * We use 'our' smb_krb5_context to do the AS-REQ and it is possible
538 * to configure the enctypes via the krb5.conf.
540 * And the gss_init_sec_context() creates it's own krb5_context and
541 * the TGS-REQ had all enctypes in it and only the ones configured
542 * and used for the AS-REQ, so it wasn't possible to disable the usage
545 min_stat
= krb5_get_default_in_tkt_etypes(ccache
->smb_krb5_context
->krb5_context
,
549 OM_uint32 num_ktypes
;
551 for (num_ktypes
= 0; etypes
[num_ktypes
]; num_ktypes
++);
553 maj_stat
= gss_krb5_set_allowable_enctypes(&min_stat
, gcc
->creds
,
564 (*error_string
) = talloc_asprintf(cred
, "gss_krb5_set_allowable_enctypes failed: %s", error_message(ret
));
569 /* don't force GSS_C_CONF_FLAG and GSS_C_INTEG_FLAG */
570 maj_stat
= gss_set_cred_option(&min_stat
, &gcc
->creds
,
571 GSS_KRB5_CRED_NO_CI_FLAGS_X
,
580 (*error_string
) = talloc_asprintf(cred
, "gss_set_cred_option failed: %s", error_message(ret
));
584 cred
->client_gss_creds_obtained
= cred
->ccache_obtained
;
585 talloc_set_destructor(gcc
, free_gssapi_creds
);
586 cred
->client_gss_creds
= gcc
;
592 Set a gssapi cred_id_t into the credentials system. (Client case)
594 This grabs the credentials both 'intact' and getting the krb5
595 ccache out of it. This routine can be generalised in future for
596 the case where we deal with GSSAPI mechs other than krb5.
598 On sucess, the caller must not free gssapi_cred, as it now belongs
599 to the credentials system.
602 int cli_credentials_set_client_gss_creds(struct cli_credentials
*cred
,
603 struct loadparm_context
*lp_ctx
,
604 gss_cred_id_t gssapi_cred
,
605 enum credentials_obtained obtained
,
606 const char **error_string
)
609 OM_uint32 maj_stat
, min_stat
;
610 struct ccache_container
*ccc
;
611 struct gssapi_creds_container
*gcc
;
612 if (cred
->client_gss_creds_obtained
> obtained
) {
616 gcc
= talloc(cred
, struct gssapi_creds_container
);
618 (*error_string
) = error_message(ENOMEM
);
622 ret
= cli_credentials_new_ccache(cred
, lp_ctx
, NULL
, &ccc
, error_string
);
627 maj_stat
= gss_krb5_copy_ccache(&min_stat
,
628 gssapi_cred
, ccc
->ccache
);
636 (*error_string
) = error_message(ENOMEM
);
641 ret
= cli_credentials_set_from_ccache(cred
, ccc
, obtained
, error_string
);
644 cred
->ccache_obtained
= obtained
;
646 gcc
->creds
= gssapi_cred
;
647 talloc_set_destructor(gcc
, free_gssapi_creds
);
649 /* set the clinet_gss_creds_obtained here, as it just
650 got set to UNINITIALISED by the calls above */
651 cred
->client_gss_creds_obtained
= obtained
;
652 cred
->client_gss_creds
= gcc
;
657 /* Get the keytab (actually, a container containing the krb5_keytab)
658 * attached to this context. If this hasn't been done or set before,
659 * it will be generated from the password.
661 _PUBLIC_
int cli_credentials_get_keytab(struct cli_credentials
*cred
,
662 struct loadparm_context
*lp_ctx
,
663 struct keytab_container
**_ktc
)
666 struct keytab_container
*ktc
;
667 struct smb_krb5_context
*smb_krb5_context
;
668 const char *keytab_name
;
672 if (cred
->keytab_obtained
>= (MAX(cred
->principal_obtained
,
673 cred
->username_obtained
))) {
674 *_ktc
= cred
->keytab
;
678 if (cli_credentials_is_anonymous(cred
)) {
682 ret
= cli_credentials_get_krb5_context(cred
, lp_ctx
,
688 mem_ctx
= talloc_new(cred
);
693 ret
= smb_krb5_create_memory_keytab(mem_ctx
,
694 smb_krb5_context
->krb5_context
,
695 cli_credentials_get_password(cred
),
696 cli_credentials_get_username(cred
),
697 cli_credentials_get_realm(cred
),
698 cli_credentials_get_kvno(cred
),
699 &keytab
, &keytab_name
);
701 talloc_free(mem_ctx
);
705 ret
= smb_krb5_get_keytab_container(mem_ctx
, smb_krb5_context
,
706 keytab
, keytab_name
, &ktc
);
708 talloc_free(mem_ctx
);
712 cred
->keytab_obtained
= (MAX(cred
->principal_obtained
,
713 cred
->username_obtained
));
715 talloc_steal(cred
, ktc
);
717 *_ktc
= cred
->keytab
;
718 talloc_free(mem_ctx
);
722 /* Given the name of a keytab (presumably in the format
723 * FILE:/etc/krb5.keytab), open it and attach it */
725 _PUBLIC_
int cli_credentials_set_keytab_name(struct cli_credentials
*cred
,
726 struct loadparm_context
*lp_ctx
,
727 const char *keytab_name
,
728 enum credentials_obtained obtained
)
731 struct keytab_container
*ktc
;
732 struct smb_krb5_context
*smb_krb5_context
;
735 if (cred
->keytab_obtained
>= obtained
) {
739 ret
= cli_credentials_get_krb5_context(cred
, lp_ctx
, &smb_krb5_context
);
744 mem_ctx
= talloc_new(cred
);
749 ret
= smb_krb5_get_keytab_container(mem_ctx
, smb_krb5_context
,
750 NULL
, keytab_name
, &ktc
);
755 cred
->keytab_obtained
= obtained
;
757 talloc_steal(cred
, ktc
);
759 talloc_free(mem_ctx
);
764 /* Get server gss credentials (in gsskrb5, this means the keytab) */
766 _PUBLIC_
int cli_credentials_get_server_gss_creds(struct cli_credentials
*cred
,
767 struct loadparm_context
*lp_ctx
,
768 struct gssapi_creds_container
**_gcc
)
771 OM_uint32 maj_stat
, min_stat
;
772 struct gssapi_creds_container
*gcc
;
773 struct keytab_container
*ktc
;
774 struct smb_krb5_context
*smb_krb5_context
;
776 krb5_principal princ
;
777 const char *error_string
;
778 enum credentials_obtained obtained
;
780 mem_ctx
= talloc_new(cred
);
785 ret
= cli_credentials_get_krb5_context(cred
, lp_ctx
, &smb_krb5_context
);
790 ret
= principal_from_credentials(mem_ctx
, cred
, smb_krb5_context
, &princ
, &obtained
, &error_string
);
792 DEBUG(1,("cli_credentials_get_server_gss_creds: making krb5 principal failed (%s)\n",
794 talloc_free(mem_ctx
);
798 if (cred
->server_gss_creds_obtained
>= (MAX(cred
->keytab_obtained
, obtained
))) {
799 talloc_free(mem_ctx
);
800 *_gcc
= cred
->server_gss_creds
;
804 ret
= cli_credentials_get_keytab(cred
, lp_ctx
, &ktc
);
806 DEBUG(1, ("Failed to get keytab for GSSAPI server: %s\n", error_message(ret
)));
810 gcc
= talloc(cred
, struct gssapi_creds_container
);
812 talloc_free(mem_ctx
);
816 if (obtained
< CRED_SPECIFIED
) {
817 /* This creates a GSSAPI cred_id_t with the principal and keytab set */
818 maj_stat
= gss_krb5_import_cred(&min_stat
, NULL
, NULL
, ktc
->keytab
,
821 /* This creates a GSSAPI cred_id_t with the principal and keytab set */
822 maj_stat
= gss_krb5_import_cred(&min_stat
, NULL
, princ
, ktc
->keytab
,
833 cred
->server_gss_creds_obtained
= cred
->keytab_obtained
;
834 talloc_set_destructor(gcc
, free_gssapi_creds
);
835 cred
->server_gss_creds
= gcc
;
838 talloc_free(mem_ctx
);
846 _PUBLIC_
void cli_credentials_set_kvno(struct cli_credentials
*cred
,
853 * Return Kerberos KVNO
856 _PUBLIC_
int cli_credentials_get_kvno(struct cli_credentials
*cred
)
862 const char *cli_credentials_get_salt_principal(struct cli_credentials
*cred
)
864 return cred
->salt_principal
;
867 _PUBLIC_
void cli_credentials_set_salt_principal(struct cli_credentials
*cred
, const char *principal
)
869 talloc_free(cred
->salt_principal
);
870 cred
->salt_principal
= talloc_strdup(cred
, principal
);
873 /* The 'impersonate_principal' is used to allow one Kerberos principal
874 * (and it's associated keytab etc) to impersonate another. The
875 * ability to do this is controlled by the KDC, but it is generally
876 * permitted to impersonate anyone to yourself. This allows any
877 * member of the domain to get the groups of a user. This is also
878 * known as S4U2Self */
880 _PUBLIC_
const char *cli_credentials_get_impersonate_principal(struct cli_credentials
*cred
)
882 return cred
->impersonate_principal
;
886 * The 'self_service' is the service principal that
887 * represents the same object (by its objectSid)
888 * as the client principal (typically our machine account).
889 * When trying to impersonate 'impersonate_principal' with
892 _PUBLIC_
const char *cli_credentials_get_self_service(struct cli_credentials
*cred
)
894 return cred
->self_service
;
897 _PUBLIC_
void cli_credentials_set_impersonate_principal(struct cli_credentials
*cred
,
898 const char *principal
,
899 const char *self_service
)
901 talloc_free(cred
->impersonate_principal
);
902 cred
->impersonate_principal
= talloc_strdup(cred
, principal
);
903 talloc_free(cred
->self_service
);
904 cred
->self_service
= talloc_strdup(cred
, self_service
);
905 cli_credentials_set_kerberos_state(cred
, CRED_MUST_USE_KERBEROS
);
909 * when impersonating for S4U2proxy we need to set the target principal.
910 * Similarly, we may only be authorized to do general impersonation to
911 * some particular services.
913 * Likewise, password changes typically require a ticket to kpasswd/realm directly, not via a TGT
915 * NULL means that tickets will be obtained for the krbtgt service.
918 const char *cli_credentials_get_target_service(struct cli_credentials
*cred
)
920 return cred
->target_service
;
923 _PUBLIC_
void cli_credentials_set_target_service(struct cli_credentials
*cred
, const char *target_service
)
925 talloc_free(cred
->target_service
);
926 cred
->target_service
= talloc_strdup(cred
, target_service
);