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 "system/gssapi.h"
27 #include "auth/kerberos/kerberos.h"
28 #include "auth/credentials/credentials.h"
29 #include "auth/credentials/credentials_proto.h"
30 #include "auth/credentials/credentials_krb5.h"
31 #include "auth/kerberos/kerberos_credentials.h"
32 #include "auth/kerberos/kerberos_srv_keytab.h"
33 #include "auth/kerberos/kerberos_util.h"
34 #include "auth/kerberos/pac_utils.h"
35 #include "param/param.h"
37 static void cli_credentials_invalidate_client_gss_creds(
38 struct cli_credentials
*cred
,
39 enum credentials_obtained obtained
);
41 _PUBLIC_
int cli_credentials_get_krb5_context(struct cli_credentials
*cred
,
42 struct loadparm_context
*lp_ctx
,
43 struct smb_krb5_context
**smb_krb5_context
)
46 if (cred
->smb_krb5_context
) {
47 *smb_krb5_context
= cred
->smb_krb5_context
;
51 ret
= smb_krb5_init_context(cred
, NULL
, lp_ctx
,
52 &cred
->smb_krb5_context
);
54 cred
->smb_krb5_context
= NULL
;
57 *smb_krb5_context
= cred
->smb_krb5_context
;
61 /* For most predictable behaviour, this needs to be called directly after the cli_credentials_init(),
62 * otherwise we may still have references to the old smb_krb5_context in a credential cache etc
64 _PUBLIC_ NTSTATUS
cli_credentials_set_krb5_context(struct cli_credentials
*cred
,
65 struct smb_krb5_context
*smb_krb5_context
)
67 if (smb_krb5_context
== NULL
) {
68 talloc_unlink(cred
, cred
->smb_krb5_context
);
69 cred
->smb_krb5_context
= NULL
;
73 if (!talloc_reference(cred
, smb_krb5_context
)) {
74 return NT_STATUS_NO_MEMORY
;
76 cred
->smb_krb5_context
= smb_krb5_context
;
80 static int cli_credentials_set_from_ccache(struct cli_credentials
*cred
,
81 struct ccache_container
*ccache
,
82 enum credentials_obtained obtained
,
83 const char **error_string
)
90 if (cred
->ccache_obtained
> obtained
) {
94 ret
= krb5_cc_get_principal(ccache
->smb_krb5_context
->krb5_context
,
95 ccache
->ccache
, &princ
);
98 (*error_string
) = talloc_asprintf(cred
, "failed to get principal from ccache: %s\n",
99 smb_get_krb5_error_message(ccache
->smb_krb5_context
->krb5_context
,
104 ret
= krb5_unparse_name(ccache
->smb_krb5_context
->krb5_context
, princ
, &name
);
106 (*error_string
) = talloc_asprintf(cred
, "failed to unparse principal from ccache: %s\n",
107 smb_get_krb5_error_message(ccache
->smb_krb5_context
->krb5_context
,
112 cli_credentials_set_principal(cred
, name
, obtained
);
116 krb5_free_principal(ccache
->smb_krb5_context
->krb5_context
, princ
);
118 /* set the ccache_obtained here, as it just got set to UNINITIALISED by the calls above */
119 cred
->ccache_obtained
= obtained
;
124 /* Free a memory ccache */
125 static int free_mccache(struct ccache_container
*ccc
)
127 krb5_cc_destroy(ccc
->smb_krb5_context
->krb5_context
, ccc
->ccache
);
132 /* Free a disk-based ccache */
133 static int free_dccache(struct ccache_container
*ccc
) {
134 krb5_cc_close(ccc
->smb_krb5_context
->krb5_context
, ccc
->ccache
);
139 _PUBLIC_
int cli_credentials_set_ccache(struct cli_credentials
*cred
,
140 struct loadparm_context
*lp_ctx
,
142 enum credentials_obtained obtained
,
143 const char **error_string
)
146 krb5_principal princ
;
147 struct ccache_container
*ccc
;
148 if (cred
->ccache_obtained
> obtained
) {
152 ccc
= talloc(cred
, struct ccache_container
);
154 (*error_string
) = error_message(ENOMEM
);
158 ret
= cli_credentials_get_krb5_context(cred
, lp_ctx
,
159 &ccc
->smb_krb5_context
);
161 (*error_string
) = error_message(ret
);
165 if (!talloc_reference(ccc
, ccc
->smb_krb5_context
)) {
167 (*error_string
) = error_message(ENOMEM
);
172 ret
= krb5_cc_resolve(ccc
->smb_krb5_context
->krb5_context
, name
, &ccc
->ccache
);
174 (*error_string
) = talloc_asprintf(cred
, "failed to read krb5 ccache: %s: %s\n",
176 smb_get_krb5_error_message(ccc
->smb_krb5_context
->krb5_context
,
182 ret
= krb5_cc_default(ccc
->smb_krb5_context
->krb5_context
, &ccc
->ccache
);
184 (*error_string
) = talloc_asprintf(cred
, "failed to read default krb5 ccache: %s\n",
185 smb_get_krb5_error_message(ccc
->smb_krb5_context
->krb5_context
,
192 talloc_set_destructor(ccc
, free_dccache
);
194 ret
= krb5_cc_get_principal(ccc
->smb_krb5_context
->krb5_context
, ccc
->ccache
, &princ
);
197 krb5_free_principal(ccc
->smb_krb5_context
->krb5_context
, princ
);
198 ret
= cli_credentials_set_from_ccache(cred
, ccc
, obtained
, error_string
);
201 (*error_string
) = error_message(ret
);
206 cred
->ccache_obtained
= obtained
;
207 talloc_steal(cred
, ccc
);
209 cli_credentials_invalidate_client_gss_creds(cred
, cred
->ccache_obtained
);
216 static int cli_credentials_new_ccache(struct cli_credentials
*cred
,
217 struct loadparm_context
*lp_ctx
,
219 struct ccache_container
**_ccc
,
220 const char **error_string
)
222 bool must_free_cc_name
= false;
224 struct ccache_container
*ccc
= talloc(cred
, struct ccache_container
);
229 ret
= cli_credentials_get_krb5_context(cred
, lp_ctx
,
230 &ccc
->smb_krb5_context
);
233 (*error_string
) = talloc_asprintf(cred
, "Failed to get krb5_context: %s",
237 if (!talloc_reference(ccc
, ccc
->smb_krb5_context
)) {
239 (*error_string
) = strerror(ENOMEM
);
244 must_free_cc_name
= true;
246 if (lpcfg_parm_bool(lp_ctx
, NULL
, "credentials", "krb5_cc_file", false)) {
247 ccache_name
= talloc_asprintf(ccc
, "FILE:/tmp/krb5_cc_samba_%u_%p",
248 (unsigned int)getpid(), ccc
);
250 ccache_name
= talloc_asprintf(ccc
, "MEMORY:%p",
256 (*error_string
) = strerror(ENOMEM
);
261 ret
= krb5_cc_resolve(ccc
->smb_krb5_context
->krb5_context
, ccache_name
,
264 (*error_string
) = talloc_asprintf(cred
, "failed to resolve a krb5 ccache (%s): %s\n",
266 smb_get_krb5_error_message(ccc
->smb_krb5_context
->krb5_context
,
268 talloc_free(ccache_name
);
273 if (strncasecmp(ccache_name
, "MEMORY:", 7) == 0) {
274 talloc_set_destructor(ccc
, free_mccache
);
276 talloc_set_destructor(ccc
, free_dccache
);
279 if (must_free_cc_name
) {
280 talloc_free(ccache_name
);
288 _PUBLIC_
int cli_credentials_get_named_ccache(struct cli_credentials
*cred
,
289 struct tevent_context
*event_ctx
,
290 struct loadparm_context
*lp_ctx
,
292 struct ccache_container
**ccc
,
293 const char **error_string
)
296 enum credentials_obtained obtained
;
298 if (cred
->machine_account_pending
) {
299 cli_credentials_set_machine_account(cred
, lp_ctx
);
302 if (cred
->ccache_obtained
>= cred
->ccache_threshold
&&
303 cred
->ccache_obtained
> CRED_UNINITIALISED
) {
305 bool expired
= false;
306 ret
= krb5_cc_get_lifetime(cred
->ccache
->smb_krb5_context
->krb5_context
,
307 cred
->ccache
->ccache
, &lifetime
);
308 if (ret
== KRB5_CC_END
) {
309 /* If we have a particular ccache set, without
310 * an initial ticket, then assume there is a
312 } else if (ret
== 0) {
314 DEBUG(3, ("Ticket in credentials cache for %s expired, will refresh\n",
315 cli_credentials_get_principal(cred
, cred
)));
317 } else if (lifetime
< 300) {
318 DEBUG(3, ("Ticket in credentials cache for %s will shortly expire (%u secs), will refresh\n",
319 cli_credentials_get_principal(cred
, cred
), (unsigned int)lifetime
));
323 (*error_string
) = talloc_asprintf(cred
, "failed to get ccache lifetime: %s\n",
324 smb_get_krb5_error_message(cred
->ccache
->smb_krb5_context
->krb5_context
,
329 DEBUG(5, ("Ticket in credentials cache for %s will expire in %u secs\n",
330 cli_credentials_get_principal(cred
, cred
), (unsigned int)lifetime
));
337 if (cli_credentials_is_anonymous(cred
)) {
338 (*error_string
) = "Cannot get anonymous kerberos credentials";
342 ret
= cli_credentials_new_ccache(cred
, lp_ctx
, ccache_name
, ccc
, error_string
);
347 ret
= kinit_to_ccache(cred
, cred
, (*ccc
)->smb_krb5_context
, event_ctx
, (*ccc
)->ccache
, &obtained
, error_string
);
352 ret
= cli_credentials_set_from_ccache(cred
, *ccc
,
353 obtained
, error_string
);
356 cred
->ccache_obtained
= cred
->principal_obtained
;
360 cli_credentials_invalidate_client_gss_creds(cred
, cred
->ccache_obtained
);
364 _PUBLIC_
int cli_credentials_get_ccache(struct cli_credentials
*cred
,
365 struct tevent_context
*event_ctx
,
366 struct loadparm_context
*lp_ctx
,
367 struct ccache_container
**ccc
,
368 const char **error_string
)
370 return cli_credentials_get_named_ccache(cred
, event_ctx
, lp_ctx
, NULL
, ccc
, error_string
);
373 /* We have good reason to think the ccache in these credentials is invalid - blow it away */
374 static void cli_credentials_unconditionally_invalidate_client_gss_creds(struct cli_credentials
*cred
)
376 if (cred
->client_gss_creds_obtained
> CRED_UNINITIALISED
) {
377 talloc_unlink(cred
, cred
->client_gss_creds
);
378 cred
->client_gss_creds
= NULL
;
380 cred
->client_gss_creds_obtained
= CRED_UNINITIALISED
;
383 void cli_credentials_invalidate_client_gss_creds(struct cli_credentials
*cred
,
384 enum credentials_obtained obtained
)
386 /* If the caller just changed the username/password etc, then
387 * any cached credentials are now invalid */
388 if (obtained
>= cred
->client_gss_creds_obtained
) {
389 if (cred
->client_gss_creds_obtained
> CRED_UNINITIALISED
) {
390 talloc_unlink(cred
, cred
->client_gss_creds
);
391 cred
->client_gss_creds
= NULL
;
393 cred
->client_gss_creds_obtained
= CRED_UNINITIALISED
;
395 /* Now that we know that the data is 'this specified', then
396 * don't allow something less 'known' to be returned as a
397 * ccache. Ie, if the username is on the command line, we
398 * don't want to later guess to use a file-based ccache */
399 if (obtained
> cred
->client_gss_creds_threshold
) {
400 cred
->client_gss_creds_threshold
= obtained
;
404 /* We have good reason to think this CCACHE is invalid. Blow it away */
405 static void cli_credentials_unconditionally_invalidate_ccache(struct cli_credentials
*cred
)
407 if (cred
->ccache_obtained
> CRED_UNINITIALISED
) {
408 talloc_unlink(cred
, cred
->ccache
);
411 cred
->ccache_obtained
= CRED_UNINITIALISED
;
413 cli_credentials_unconditionally_invalidate_client_gss_creds(cred
);
416 _PUBLIC_
void cli_credentials_invalidate_ccache(struct cli_credentials
*cred
,
417 enum credentials_obtained obtained
)
419 /* If the caller just changed the username/password etc, then
420 * any cached credentials are now invalid */
421 if (obtained
>= cred
->ccache_obtained
) {
422 if (cred
->ccache_obtained
> CRED_UNINITIALISED
) {
423 talloc_unlink(cred
, cred
->ccache
);
426 cred
->ccache_obtained
= CRED_UNINITIALISED
;
428 /* Now that we know that the data is 'this specified', then
429 * don't allow something less 'known' to be returned as a
430 * ccache. i.e, if the username is on the command line, we
431 * don't want to later guess to use a file-based ccache */
432 if (obtained
> cred
->ccache_threshold
) {
433 cred
->ccache_threshold
= obtained
;
436 cli_credentials_invalidate_client_gss_creds(cred
,
440 static int free_gssapi_creds(struct gssapi_creds_container
*gcc
)
443 (void)gss_release_cred(&min_stat
, &gcc
->creds
);
447 _PUBLIC_
int cli_credentials_get_client_gss_creds(struct cli_credentials
*cred
,
448 struct tevent_context
*event_ctx
,
449 struct loadparm_context
*lp_ctx
,
450 struct gssapi_creds_container
**_gcc
,
451 const char **error_string
)
454 OM_uint32 maj_stat
, min_stat
;
455 struct gssapi_creds_container
*gcc
;
456 struct ccache_container
*ccache
;
457 gss_buffer_desc empty_buffer
= GSS_C_EMPTY_BUFFER
;
458 krb5_enctype
*etypes
= NULL
;
460 if (cred
->client_gss_creds_obtained
>= cred
->client_gss_creds_threshold
&&
461 cred
->client_gss_creds_obtained
> CRED_UNINITIALISED
) {
462 bool expired
= false;
463 OM_uint32 lifetime
= 0;
464 gss_cred_usage_t usage
= 0;
465 maj_stat
= gss_inquire_cred(&min_stat
, cred
->client_gss_creds
->creds
,
466 NULL
, &lifetime
, &usage
, NULL
);
467 if (maj_stat
== GSS_S_CREDENTIALS_EXPIRED
) {
468 DEBUG(3, ("Credentials for %s expired, must refresh credentials cache\n", cli_credentials_get_principal(cred
, cred
)));
470 } else if (maj_stat
== GSS_S_COMPLETE
&& lifetime
< 300) {
471 DEBUG(3, ("Credentials for %s will expire shortly (%u sec), must refresh credentials cache\n", cli_credentials_get_principal(cred
, cred
), lifetime
));
473 } else if (maj_stat
!= GSS_S_COMPLETE
) {
474 *error_string
= talloc_asprintf(cred
, "inquiry of credential lifefime via GSSAPI gss_inquire_cred failed: %s\n",
475 gssapi_error_string(cred
, maj_stat
, min_stat
, NULL
));
479 cli_credentials_unconditionally_invalidate_client_gss_creds(cred
);
481 DEBUG(5, ("GSSAPI credentials for %s will expire in %u secs\n",
482 cli_credentials_get_principal(cred
, cred
), (unsigned int)lifetime
));
484 *_gcc
= cred
->client_gss_creds
;
489 ret
= cli_credentials_get_ccache(cred
, event_ctx
, lp_ctx
,
490 &ccache
, error_string
);
492 if (cli_credentials_get_kerberos_state(cred
) == CRED_MUST_USE_KERBEROS
) {
493 DEBUG(1, ("Failed to get kerberos credentials (kerberos required): %s\n", *error_string
));
495 DEBUG(4, ("Failed to get kerberos credentials: %s\n", *error_string
));
500 gcc
= talloc(cred
, struct gssapi_creds_container
);
502 (*error_string
) = error_message(ENOMEM
);
506 maj_stat
= gss_krb5_import_cred(&min_stat
, ccache
->ccache
, NULL
, NULL
,
508 if ((maj_stat
== GSS_S_FAILURE
) && (min_stat
== (OM_uint32
)KRB5_CC_END
|| min_stat
== (OM_uint32
) KRB5_CC_NOTFOUND
)) {
509 /* This CCACHE is no good. Ensure we don't use it again */
510 cli_credentials_unconditionally_invalidate_ccache(cred
);
512 /* Now try again to get a ccache */
513 ret
= cli_credentials_get_ccache(cred
, event_ctx
, lp_ctx
,
514 &ccache
, error_string
);
516 DEBUG(1, ("Failed to re-get CCACHE for GSSAPI client: %s\n", error_message(ret
)));
520 maj_stat
= gss_krb5_import_cred(&min_stat
, ccache
->ccache
, NULL
, NULL
,
532 (*error_string
) = talloc_asprintf(cred
, "gss_krb5_import_cred failed: %s", error_message(ret
));
537 * transfer the enctypes from the smb_krb5_context to the gssapi layer
539 * We use 'our' smb_krb5_context to do the AS-REQ and it is possible
540 * to configure the enctypes via the krb5.conf.
542 * And the gss_init_sec_context() creates it's own krb5_context and
543 * the TGS-REQ had all enctypes in it and only the ones configured
544 * and used for the AS-REQ, so it wasn't possible to disable the usage
547 min_stat
= krb5_get_default_in_tkt_etypes(ccache
->smb_krb5_context
->krb5_context
,
551 OM_uint32 num_ktypes
;
553 for (num_ktypes
= 0; etypes
[num_ktypes
]; num_ktypes
++);
555 maj_stat
= gss_krb5_set_allowable_enctypes(&min_stat
, gcc
->creds
,
566 (*error_string
) = talloc_asprintf(cred
, "gss_krb5_set_allowable_enctypes failed: %s", error_message(ret
));
571 /* don't force GSS_C_CONF_FLAG and GSS_C_INTEG_FLAG */
572 maj_stat
= gss_set_cred_option(&min_stat
, &gcc
->creds
,
573 GSS_KRB5_CRED_NO_CI_FLAGS_X
,
582 (*error_string
) = talloc_asprintf(cred
, "gss_set_cred_option failed: %s", error_message(ret
));
586 cred
->client_gss_creds_obtained
= cred
->ccache_obtained
;
587 talloc_set_destructor(gcc
, free_gssapi_creds
);
588 cred
->client_gss_creds
= gcc
;
594 Set a gssapi cred_id_t into the credentials system. (Client case)
596 This grabs the credentials both 'intact' and getting the krb5
597 ccache out of it. This routine can be generalised in future for
598 the case where we deal with GSSAPI mechs other than krb5.
600 On sucess, the caller must not free gssapi_cred, as it now belongs
601 to the credentials system.
604 int cli_credentials_set_client_gss_creds(struct cli_credentials
*cred
,
605 struct loadparm_context
*lp_ctx
,
606 gss_cred_id_t gssapi_cred
,
607 enum credentials_obtained obtained
,
608 const char **error_string
)
611 OM_uint32 maj_stat
, min_stat
;
612 struct ccache_container
*ccc
;
613 struct gssapi_creds_container
*gcc
;
614 if (cred
->client_gss_creds_obtained
> obtained
) {
618 gcc
= talloc(cred
, struct gssapi_creds_container
);
620 (*error_string
) = error_message(ENOMEM
);
624 ret
= cli_credentials_new_ccache(cred
, lp_ctx
, NULL
, &ccc
, error_string
);
629 maj_stat
= gss_krb5_copy_ccache(&min_stat
,
630 gssapi_cred
, ccc
->ccache
);
638 (*error_string
) = error_message(ENOMEM
);
643 ret
= cli_credentials_set_from_ccache(cred
, ccc
, obtained
, error_string
);
646 cred
->ccache_obtained
= obtained
;
648 gcc
->creds
= gssapi_cred
;
649 talloc_set_destructor(gcc
, free_gssapi_creds
);
651 /* set the clinet_gss_creds_obtained here, as it just
652 got set to UNINITIALISED by the calls above */
653 cred
->client_gss_creds_obtained
= obtained
;
654 cred
->client_gss_creds
= gcc
;
659 /* Get the keytab (actually, a container containing the krb5_keytab)
660 * attached to this context. If this hasn't been done or set before,
661 * it will be generated from the password.
663 _PUBLIC_
int cli_credentials_get_keytab(struct cli_credentials
*cred
,
664 struct loadparm_context
*lp_ctx
,
665 struct keytab_container
**_ktc
)
668 struct keytab_container
*ktc
;
669 struct smb_krb5_context
*smb_krb5_context
;
670 const char *keytab_name
;
674 if (cred
->keytab_obtained
>= (MAX(cred
->principal_obtained
,
675 cred
->username_obtained
))) {
676 *_ktc
= cred
->keytab
;
680 if (cli_credentials_is_anonymous(cred
)) {
684 ret
= cli_credentials_get_krb5_context(cred
, lp_ctx
,
690 mem_ctx
= talloc_new(cred
);
695 ret
= smb_krb5_create_memory_keytab(mem_ctx
,
696 smb_krb5_context
->krb5_context
,
697 cli_credentials_get_password(cred
),
698 cli_credentials_get_username(cred
),
699 cli_credentials_get_realm(cred
),
700 cli_credentials_get_kvno(cred
),
701 &keytab
, &keytab_name
);
703 talloc_free(mem_ctx
);
707 ret
= smb_krb5_get_keytab_container(mem_ctx
, smb_krb5_context
,
708 keytab
, keytab_name
, &ktc
);
710 talloc_free(mem_ctx
);
714 cred
->keytab_obtained
= (MAX(cred
->principal_obtained
,
715 cred
->username_obtained
));
717 talloc_steal(cred
, ktc
);
719 *_ktc
= cred
->keytab
;
720 talloc_free(mem_ctx
);
724 /* Given the name of a keytab (presumably in the format
725 * FILE:/etc/krb5.keytab), open it and attach it */
727 _PUBLIC_
int cli_credentials_set_keytab_name(struct cli_credentials
*cred
,
728 struct loadparm_context
*lp_ctx
,
729 const char *keytab_name
,
730 enum credentials_obtained obtained
)
733 struct keytab_container
*ktc
;
734 struct smb_krb5_context
*smb_krb5_context
;
737 if (cred
->keytab_obtained
>= obtained
) {
741 ret
= cli_credentials_get_krb5_context(cred
, lp_ctx
, &smb_krb5_context
);
746 mem_ctx
= talloc_new(cred
);
751 ret
= smb_krb5_get_keytab_container(mem_ctx
, smb_krb5_context
,
752 NULL
, keytab_name
, &ktc
);
757 cred
->keytab_obtained
= obtained
;
759 talloc_steal(cred
, ktc
);
761 talloc_free(mem_ctx
);
766 /* Get server gss credentials (in gsskrb5, this means the keytab) */
768 _PUBLIC_
int cli_credentials_get_server_gss_creds(struct cli_credentials
*cred
,
769 struct loadparm_context
*lp_ctx
,
770 struct gssapi_creds_container
**_gcc
)
773 OM_uint32 maj_stat
, min_stat
;
774 struct gssapi_creds_container
*gcc
;
775 struct keytab_container
*ktc
;
776 struct smb_krb5_context
*smb_krb5_context
;
778 krb5_principal princ
;
779 const char *error_string
;
780 enum credentials_obtained obtained
;
782 mem_ctx
= talloc_new(cred
);
787 ret
= cli_credentials_get_krb5_context(cred
, lp_ctx
, &smb_krb5_context
);
792 ret
= principal_from_credentials(mem_ctx
, cred
, smb_krb5_context
, &princ
, &obtained
, &error_string
);
794 DEBUG(1,("cli_credentials_get_server_gss_creds: making krb5 principal failed (%s)\n",
796 talloc_free(mem_ctx
);
800 if (cred
->server_gss_creds_obtained
>= (MAX(cred
->keytab_obtained
, obtained
))) {
801 talloc_free(mem_ctx
);
802 *_gcc
= cred
->server_gss_creds
;
806 ret
= cli_credentials_get_keytab(cred
, lp_ctx
, &ktc
);
808 DEBUG(1, ("Failed to get keytab for GSSAPI server: %s\n", error_message(ret
)));
812 gcc
= talloc(cred
, struct gssapi_creds_container
);
814 talloc_free(mem_ctx
);
818 if (obtained
< CRED_SPECIFIED
) {
819 /* This creates a GSSAPI cred_id_t with the principal and keytab set */
820 maj_stat
= gss_krb5_import_cred(&min_stat
, NULL
, NULL
, ktc
->keytab
,
823 /* This creates a GSSAPI cred_id_t with the principal and keytab set */
824 maj_stat
= gss_krb5_import_cred(&min_stat
, NULL
, princ
, ktc
->keytab
,
835 cred
->server_gss_creds_obtained
= cred
->keytab_obtained
;
836 talloc_set_destructor(gcc
, free_gssapi_creds
);
837 cred
->server_gss_creds
= gcc
;
840 talloc_free(mem_ctx
);
848 _PUBLIC_
void cli_credentials_set_kvno(struct cli_credentials
*cred
,
855 * Return Kerberos KVNO
858 _PUBLIC_
int cli_credentials_get_kvno(struct cli_credentials
*cred
)
864 const char *cli_credentials_get_salt_principal(struct cli_credentials
*cred
)
866 return cred
->salt_principal
;
869 _PUBLIC_
void cli_credentials_set_salt_principal(struct cli_credentials
*cred
, const char *principal
)
871 talloc_free(cred
->salt_principal
);
872 cred
->salt_principal
= talloc_strdup(cred
, principal
);
875 /* The 'impersonate_principal' is used to allow one Kerberos principal
876 * (and it's associated keytab etc) to impersonate another. The
877 * ability to do this is controlled by the KDC, but it is generally
878 * permitted to impersonate anyone to yourself. This allows any
879 * member of the domain to get the groups of a user. This is also
880 * known as S4U2Self */
882 _PUBLIC_
const char *cli_credentials_get_impersonate_principal(struct cli_credentials
*cred
)
884 return cred
->impersonate_principal
;
888 * The 'self_service' is the service principal that
889 * represents the same object (by its objectSid)
890 * as the client principal (typically our machine account).
891 * When trying to impersonate 'impersonate_principal' with
894 _PUBLIC_
const char *cli_credentials_get_self_service(struct cli_credentials
*cred
)
896 return cred
->self_service
;
899 _PUBLIC_
void cli_credentials_set_impersonate_principal(struct cli_credentials
*cred
,
900 const char *principal
,
901 const char *self_service
)
903 talloc_free(cred
->impersonate_principal
);
904 cred
->impersonate_principal
= talloc_strdup(cred
, principal
);
905 talloc_free(cred
->self_service
);
906 cred
->self_service
= talloc_strdup(cred
, self_service
);
907 cli_credentials_set_kerberos_state(cred
, CRED_MUST_USE_KERBEROS
);
911 * when impersonating for S4U2proxy we need to set the target principal.
912 * Similarly, we may only be authorized to do general impersonation to
913 * some particular services.
915 * Likewise, password changes typically require a ticket to kpasswd/realm directly, not via a TGT
917 * NULL means that tickets will be obtained for the krbtgt service.
920 const char *cli_credentials_get_target_service(struct cli_credentials
*cred
)
922 return cred
->target_service
;
925 _PUBLIC_
void cli_credentials_set_target_service(struct cli_credentials
*cred
, const char *target_service
)
927 talloc_free(cred
->target_service
);
928 cred
->target_service
= talloc_strdup(cred
, target_service
);