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_util.h"
32 #include "param/param.h"
34 _PUBLIC_
int cli_credentials_get_krb5_context(struct cli_credentials
*cred
,
35 struct loadparm_context
*lp_ctx
,
36 struct smb_krb5_context
**smb_krb5_context
)
39 if (cred
->smb_krb5_context
) {
40 *smb_krb5_context
= cred
->smb_krb5_context
;
44 ret
= smb_krb5_init_context(cred
, NULL
, lp_ctx
,
45 &cred
->smb_krb5_context
);
47 cred
->smb_krb5_context
= NULL
;
50 *smb_krb5_context
= cred
->smb_krb5_context
;
54 /* For most predictable behaviour, this needs to be called directly after the cli_credentials_init(),
55 * otherwise we may still have references to the old smb_krb5_context in a credential cache etc
57 _PUBLIC_ NTSTATUS
cli_credentials_set_krb5_context(struct cli_credentials
*cred
,
58 struct smb_krb5_context
*smb_krb5_context
)
60 if (smb_krb5_context
== NULL
) {
61 talloc_unlink(cred
, cred
->smb_krb5_context
);
62 cred
->smb_krb5_context
= NULL
;
66 if (!talloc_reference(cred
, smb_krb5_context
)) {
67 return NT_STATUS_NO_MEMORY
;
69 cred
->smb_krb5_context
= smb_krb5_context
;
73 static int cli_credentials_set_from_ccache(struct cli_credentials
*cred
,
74 struct ccache_container
*ccache
,
75 enum credentials_obtained obtained
,
76 const char **error_string
)
83 if (cred
->ccache_obtained
> obtained
) {
87 ret
= krb5_cc_get_principal(ccache
->smb_krb5_context
->krb5_context
,
88 ccache
->ccache
, &princ
);
91 (*error_string
) = talloc_asprintf(cred
, "failed to get principal from ccache: %s\n",
92 smb_get_krb5_error_message(ccache
->smb_krb5_context
->krb5_context
,
97 ret
= krb5_unparse_name(ccache
->smb_krb5_context
->krb5_context
, princ
, &name
);
99 (*error_string
) = talloc_asprintf(cred
, "failed to unparse principal from ccache: %s\n",
100 smb_get_krb5_error_message(ccache
->smb_krb5_context
->krb5_context
,
105 cli_credentials_set_principal(cred
, name
, obtained
);
109 krb5_free_principal(ccache
->smb_krb5_context
->krb5_context
, princ
);
111 /* set the ccache_obtained here, as it just got set to UNINITIALISED by the calls above */
112 cred
->ccache_obtained
= obtained
;
117 /* Free a memory ccache */
118 static int free_mccache(struct ccache_container
*ccc
)
120 krb5_cc_destroy(ccc
->smb_krb5_context
->krb5_context
, ccc
->ccache
);
125 /* Free a disk-based ccache */
126 static int free_dccache(struct ccache_container
*ccc
) {
127 krb5_cc_close(ccc
->smb_krb5_context
->krb5_context
, ccc
->ccache
);
132 _PUBLIC_
int cli_credentials_set_ccache(struct cli_credentials
*cred
,
133 struct loadparm_context
*lp_ctx
,
135 enum credentials_obtained obtained
,
136 const char **error_string
)
139 krb5_principal princ
;
140 struct ccache_container
*ccc
;
141 if (cred
->ccache_obtained
> obtained
) {
145 ccc
= talloc(cred
, struct ccache_container
);
147 (*error_string
) = error_message(ENOMEM
);
151 ret
= cli_credentials_get_krb5_context(cred
, lp_ctx
,
152 &ccc
->smb_krb5_context
);
154 (*error_string
) = error_message(ret
);
158 if (!talloc_reference(ccc
, ccc
->smb_krb5_context
)) {
160 (*error_string
) = error_message(ENOMEM
);
165 ret
= krb5_cc_resolve(ccc
->smb_krb5_context
->krb5_context
, name
, &ccc
->ccache
);
167 (*error_string
) = talloc_asprintf(cred
, "failed to read krb5 ccache: %s: %s\n",
169 smb_get_krb5_error_message(ccc
->smb_krb5_context
->krb5_context
,
175 ret
= krb5_cc_default(ccc
->smb_krb5_context
->krb5_context
, &ccc
->ccache
);
177 (*error_string
) = talloc_asprintf(cred
, "failed to read default krb5 ccache: %s\n",
178 smb_get_krb5_error_message(ccc
->smb_krb5_context
->krb5_context
,
185 talloc_set_destructor(ccc
, free_dccache
);
187 ret
= krb5_cc_get_principal(ccc
->smb_krb5_context
->krb5_context
, ccc
->ccache
, &princ
);
190 krb5_free_principal(ccc
->smb_krb5_context
->krb5_context
, princ
);
191 ret
= cli_credentials_set_from_ccache(cred
, ccc
, obtained
, error_string
);
194 (*error_string
) = error_message(ret
);
199 cred
->ccache_obtained
= obtained
;
200 talloc_steal(cred
, ccc
);
202 cli_credentials_invalidate_client_gss_creds(cred
, cred
->ccache_obtained
);
209 static int cli_credentials_new_ccache(struct cli_credentials
*cred
,
210 struct loadparm_context
*lp_ctx
,
212 struct ccache_container
**_ccc
,
213 const char **error_string
)
215 bool must_free_cc_name
= false;
217 struct ccache_container
*ccc
= talloc(cred
, struct ccache_container
);
222 ret
= cli_credentials_get_krb5_context(cred
, lp_ctx
,
223 &ccc
->smb_krb5_context
);
226 (*error_string
) = talloc_asprintf(cred
, "Failed to get krb5_context: %s",
230 if (!talloc_reference(ccc
, ccc
->smb_krb5_context
)) {
232 (*error_string
) = strerror(ENOMEM
);
237 must_free_cc_name
= true;
239 if (lpcfg_parm_bool(lp_ctx
, NULL
, "credentials", "krb5_cc_file", false)) {
240 ccache_name
= talloc_asprintf(ccc
, "FILE:/tmp/krb5_cc_samba_%u_%p",
241 (unsigned int)getpid(), ccc
);
243 ccache_name
= talloc_asprintf(ccc
, "MEMORY:%p",
249 (*error_string
) = strerror(ENOMEM
);
254 ret
= krb5_cc_resolve(ccc
->smb_krb5_context
->krb5_context
, ccache_name
,
257 (*error_string
) = talloc_asprintf(cred
, "failed to resolve a krb5 ccache (%s): %s\n",
259 smb_get_krb5_error_message(ccc
->smb_krb5_context
->krb5_context
,
261 talloc_free(ccache_name
);
266 if (strncasecmp(ccache_name
, "MEMORY:", 7) == 0) {
267 talloc_set_destructor(ccc
, free_mccache
);
269 talloc_set_destructor(ccc
, free_dccache
);
272 if (must_free_cc_name
) {
273 talloc_free(ccache_name
);
281 _PUBLIC_
int cli_credentials_get_named_ccache(struct cli_credentials
*cred
,
282 struct tevent_context
*event_ctx
,
283 struct loadparm_context
*lp_ctx
,
285 struct ccache_container
**ccc
,
286 const char **error_string
)
289 enum credentials_obtained obtained
;
291 if (cred
->machine_account_pending
) {
292 cli_credentials_set_machine_account(cred
, lp_ctx
);
295 if (cred
->ccache_obtained
>= cred
->ccache_threshold
&&
296 cred
->ccache_obtained
> CRED_UNINITIALISED
) {
298 bool expired
= false;
299 ret
= krb5_cc_get_lifetime(cred
->ccache
->smb_krb5_context
->krb5_context
,
300 cred
->ccache
->ccache
, &lifetime
);
301 if (ret
== KRB5_CC_END
) {
302 /* If we have a particular ccache set, without
303 * an initial ticket, then assume there is a
305 } else if (ret
== 0) {
307 DEBUG(3, ("Ticket in credentials cache for %s expired, will refresh\n",
308 cli_credentials_get_principal(cred
, cred
)));
310 } else if (lifetime
< 300) {
311 DEBUG(3, ("Ticket in credentials cache for %s will shortly expire (%u secs), will refresh\n",
312 cli_credentials_get_principal(cred
, cred
), (unsigned int)lifetime
));
316 (*error_string
) = talloc_asprintf(cred
, "failed to get ccache lifetime: %s\n",
317 smb_get_krb5_error_message(cred
->ccache
->smb_krb5_context
->krb5_context
,
322 DEBUG(5, ("Ticket in credentials cache for %s will expire in %u secs\n",
323 cli_credentials_get_principal(cred
, cred
), (unsigned int)lifetime
));
330 if (cli_credentials_is_anonymous(cred
)) {
331 (*error_string
) = "Cannot get anonymous kerberos credentials";
335 ret
= cli_credentials_new_ccache(cred
, lp_ctx
, ccache_name
, ccc
, error_string
);
340 ret
= kinit_to_ccache(cred
, cred
, (*ccc
)->smb_krb5_context
, event_ctx
, (*ccc
)->ccache
, &obtained
, error_string
);
345 ret
= cli_credentials_set_from_ccache(cred
, *ccc
,
346 obtained
, error_string
);
349 cred
->ccache_obtained
= cred
->principal_obtained
;
353 cli_credentials_invalidate_client_gss_creds(cred
, cred
->ccache_obtained
);
357 _PUBLIC_
int cli_credentials_get_ccache(struct cli_credentials
*cred
,
358 struct tevent_context
*event_ctx
,
359 struct loadparm_context
*lp_ctx
,
360 struct ccache_container
**ccc
,
361 const char **error_string
)
363 return cli_credentials_get_named_ccache(cred
, event_ctx
, lp_ctx
, NULL
, ccc
, error_string
);
366 /* We have good reason to think the ccache in these credentials is invalid - blow it away */
367 static void cli_credentials_unconditionally_invalidate_client_gss_creds(struct cli_credentials
*cred
)
369 if (cred
->client_gss_creds_obtained
> CRED_UNINITIALISED
) {
370 talloc_unlink(cred
, cred
->client_gss_creds
);
371 cred
->client_gss_creds
= NULL
;
373 cred
->client_gss_creds_obtained
= CRED_UNINITIALISED
;
376 void cli_credentials_invalidate_client_gss_creds(struct cli_credentials
*cred
,
377 enum credentials_obtained obtained
)
379 /* If the caller just changed the username/password etc, then
380 * any cached credentials are now invalid */
381 if (obtained
>= cred
->client_gss_creds_obtained
) {
382 if (cred
->client_gss_creds_obtained
> CRED_UNINITIALISED
) {
383 talloc_unlink(cred
, cred
->client_gss_creds
);
384 cred
->client_gss_creds
= NULL
;
386 cred
->client_gss_creds_obtained
= CRED_UNINITIALISED
;
388 /* Now that we know that the data is 'this specified', then
389 * don't allow something less 'known' to be returned as a
390 * ccache. Ie, if the username is on the command line, we
391 * don't want to later guess to use a file-based ccache */
392 if (obtained
> cred
->client_gss_creds_threshold
) {
393 cred
->client_gss_creds_threshold
= obtained
;
397 /* We have good reason to think this CCACHE is invalid. Blow it away */
398 static void cli_credentials_unconditionally_invalidate_ccache(struct cli_credentials
*cred
)
400 if (cred
->ccache_obtained
> CRED_UNINITIALISED
) {
401 talloc_unlink(cred
, cred
->ccache
);
404 cred
->ccache_obtained
= CRED_UNINITIALISED
;
406 cli_credentials_unconditionally_invalidate_client_gss_creds(cred
);
409 _PUBLIC_
void cli_credentials_invalidate_ccache(struct cli_credentials
*cred
,
410 enum credentials_obtained obtained
)
412 /* If the caller just changed the username/password etc, then
413 * any cached credentials are now invalid */
414 if (obtained
>= cred
->ccache_obtained
) {
415 if (cred
->ccache_obtained
> CRED_UNINITIALISED
) {
416 talloc_unlink(cred
, cred
->ccache
);
419 cred
->ccache_obtained
= CRED_UNINITIALISED
;
421 /* Now that we know that the data is 'this specified', then
422 * don't allow something less 'known' to be returned as a
423 * ccache. i.e, if the username is on the command line, we
424 * don't want to later guess to use a file-based ccache */
425 if (obtained
> cred
->ccache_threshold
) {
426 cred
->ccache_threshold
= obtained
;
429 cli_credentials_invalidate_client_gss_creds(cred
,
433 static int free_gssapi_creds(struct gssapi_creds_container
*gcc
)
436 (void)gss_release_cred(&min_stat
, &gcc
->creds
);
440 _PUBLIC_
int cli_credentials_get_client_gss_creds(struct cli_credentials
*cred
,
441 struct tevent_context
*event_ctx
,
442 struct loadparm_context
*lp_ctx
,
443 struct gssapi_creds_container
**_gcc
,
444 const char **error_string
)
447 OM_uint32 maj_stat
, min_stat
;
448 struct gssapi_creds_container
*gcc
;
449 struct ccache_container
*ccache
;
450 gss_buffer_desc empty_buffer
= GSS_C_EMPTY_BUFFER
;
451 krb5_enctype
*etypes
= NULL
;
453 if (cred
->client_gss_creds_obtained
>= cred
->client_gss_creds_threshold
&&
454 cred
->client_gss_creds_obtained
> CRED_UNINITIALISED
) {
455 bool expired
= false;
456 OM_uint32 lifetime
= 0;
457 gss_cred_usage_t usage
= 0;
458 maj_stat
= gss_inquire_cred(&min_stat
, cred
->client_gss_creds
->creds
,
459 NULL
, &lifetime
, &usage
, NULL
);
460 if (maj_stat
== GSS_S_CREDENTIALS_EXPIRED
) {
461 DEBUG(3, ("Credentials for %s expired, must refresh credentials cache\n", cli_credentials_get_principal(cred
, cred
)));
463 } else if (maj_stat
== GSS_S_COMPLETE
&& lifetime
< 300) {
464 DEBUG(3, ("Credentials for %s will expire shortly (%u sec), must refresh credentials cache\n", cli_credentials_get_principal(cred
, cred
), lifetime
));
466 } else if (maj_stat
!= GSS_S_COMPLETE
) {
467 *error_string
= talloc_asprintf(cred
, "inquiry of credential lifefime via GSSAPI gss_inquire_cred failed: %s\n",
468 gssapi_error_string(cred
, maj_stat
, min_stat
, NULL
));
472 cli_credentials_unconditionally_invalidate_client_gss_creds(cred
);
474 DEBUG(5, ("GSSAPI credentials for %s will expire in %u secs\n",
475 cli_credentials_get_principal(cred
, cred
), (unsigned int)lifetime
));
477 *_gcc
= cred
->client_gss_creds
;
482 ret
= cli_credentials_get_ccache(cred
, event_ctx
, lp_ctx
,
483 &ccache
, error_string
);
485 if (cli_credentials_get_kerberos_state(cred
) == CRED_MUST_USE_KERBEROS
) {
486 DEBUG(1, ("Failed to get kerberos credentials (kerberos required): %s\n", error_message(ret
)));
488 DEBUG(4, ("Failed to get kerberos credentials: %s\n", error_message(ret
)));
493 gcc
= talloc(cred
, struct gssapi_creds_container
);
495 (*error_string
) = error_message(ENOMEM
);
499 maj_stat
= gss_krb5_import_cred(&min_stat
, ccache
->ccache
, NULL
, NULL
,
501 if ((maj_stat
== GSS_S_FAILURE
) && (min_stat
== (OM_uint32
)KRB5_CC_END
|| min_stat
== (OM_uint32
) KRB5_CC_NOTFOUND
)) {
502 /* This CCACHE is no good. Ensure we don't use it again */
503 cli_credentials_unconditionally_invalidate_ccache(cred
);
505 /* Now try again to get a ccache */
506 ret
= cli_credentials_get_ccache(cred
, event_ctx
, lp_ctx
,
507 &ccache
, error_string
);
509 DEBUG(1, ("Failed to re-get CCACHE for GSSAPI client: %s\n", error_message(ret
)));
513 maj_stat
= gss_krb5_import_cred(&min_stat
, ccache
->ccache
, NULL
, NULL
,
525 (*error_string
) = talloc_asprintf(cred
, "gss_krb5_import_cred failed: %s", error_message(ret
));
530 * transfer the enctypes from the smb_krb5_context to the gssapi layer
532 * We use 'our' smb_krb5_context to do the AS-REQ and it is possible
533 * to configure the enctypes via the krb5.conf.
535 * And the gss_init_sec_context() creates it's own krb5_context and
536 * the TGS-REQ had all enctypes in it and only the ones configured
537 * and used for the AS-REQ, so it wasn't possible to disable the usage
540 min_stat
= krb5_get_default_in_tkt_etypes(ccache
->smb_krb5_context
->krb5_context
,
544 OM_uint32 num_ktypes
;
546 for (num_ktypes
= 0; etypes
[num_ktypes
]; num_ktypes
++);
548 maj_stat
= gss_krb5_set_allowable_enctypes(&min_stat
, gcc
->creds
,
559 (*error_string
) = talloc_asprintf(cred
, "gss_krb5_set_allowable_enctypes failed: %s", error_message(ret
));
564 /* don't force GSS_C_CONF_FLAG and GSS_C_INTEG_FLAG */
565 maj_stat
= gss_set_cred_option(&min_stat
, &gcc
->creds
,
566 GSS_KRB5_CRED_NO_CI_FLAGS_X
,
575 (*error_string
) = talloc_asprintf(cred
, "gss_set_cred_option failed: %s", error_message(ret
));
579 cred
->client_gss_creds_obtained
= cred
->ccache_obtained
;
580 talloc_set_destructor(gcc
, free_gssapi_creds
);
581 cred
->client_gss_creds
= gcc
;
587 Set a gssapi cred_id_t into the credentials system. (Client case)
589 This grabs the credentials both 'intact' and getting the krb5
590 ccache out of it. This routine can be generalised in future for
591 the case where we deal with GSSAPI mechs other than krb5.
593 On sucess, the caller must not free gssapi_cred, as it now belongs
594 to the credentials system.
597 int cli_credentials_set_client_gss_creds(struct cli_credentials
*cred
,
598 struct loadparm_context
*lp_ctx
,
599 gss_cred_id_t gssapi_cred
,
600 enum credentials_obtained obtained
,
601 const char **error_string
)
604 OM_uint32 maj_stat
, min_stat
;
605 struct ccache_container
*ccc
;
606 struct gssapi_creds_container
*gcc
;
607 if (cred
->client_gss_creds_obtained
> obtained
) {
611 gcc
= talloc(cred
, struct gssapi_creds_container
);
613 (*error_string
) = error_message(ENOMEM
);
617 ret
= cli_credentials_new_ccache(cred
, lp_ctx
, NULL
, &ccc
, error_string
);
622 maj_stat
= gss_krb5_copy_ccache(&min_stat
,
623 gssapi_cred
, ccc
->ccache
);
631 (*error_string
) = error_message(ENOMEM
);
636 ret
= cli_credentials_set_from_ccache(cred
, ccc
, obtained
, error_string
);
639 cred
->ccache_obtained
= obtained
;
641 gcc
->creds
= gssapi_cred
;
642 talloc_set_destructor(gcc
, free_gssapi_creds
);
644 /* set the clinet_gss_creds_obtained here, as it just
645 got set to UNINITIALISED by the calls above */
646 cred
->client_gss_creds_obtained
= obtained
;
647 cred
->client_gss_creds
= gcc
;
652 /* Get the keytab (actually, a container containing the krb5_keytab)
653 * attached to this context. If this hasn't been done or set before,
654 * it will be generated from the password.
656 _PUBLIC_
int cli_credentials_get_keytab(struct cli_credentials
*cred
,
657 struct loadparm_context
*lp_ctx
,
658 struct keytab_container
**_ktc
)
661 struct keytab_container
*ktc
;
662 struct smb_krb5_context
*smb_krb5_context
;
665 if (cred
->keytab_obtained
>= (MAX(cred
->principal_obtained
,
666 cred
->username_obtained
))) {
667 *_ktc
= cred
->keytab
;
671 if (cli_credentials_is_anonymous(cred
)) {
675 ret
= cli_credentials_get_krb5_context(cred
, lp_ctx
,
681 mem_ctx
= talloc_new(cred
);
686 ret
= smb_krb5_create_memory_keytab(mem_ctx
, cred
,
687 smb_krb5_context
, &ktc
);
689 talloc_free(mem_ctx
);
693 cred
->keytab_obtained
= (MAX(cred
->principal_obtained
,
694 cred
->username_obtained
));
696 talloc_steal(cred
, ktc
);
698 *_ktc
= cred
->keytab
;
699 talloc_free(mem_ctx
);
703 /* Given the name of a keytab (presumably in the format
704 * FILE:/etc/krb5.keytab), open it and attach it */
706 _PUBLIC_
int cli_credentials_set_keytab_name(struct cli_credentials
*cred
,
707 struct loadparm_context
*lp_ctx
,
708 const char *keytab_name
,
709 enum credentials_obtained obtained
)
712 struct keytab_container
*ktc
;
713 struct smb_krb5_context
*smb_krb5_context
;
716 if (cred
->keytab_obtained
>= obtained
) {
720 ret
= cli_credentials_get_krb5_context(cred
, lp_ctx
, &smb_krb5_context
);
725 mem_ctx
= talloc_new(cred
);
730 ret
= smb_krb5_get_keytab_container(mem_ctx
, smb_krb5_context
,
736 cred
->keytab_obtained
= obtained
;
738 talloc_steal(cred
, ktc
);
740 talloc_free(mem_ctx
);
745 /* Get server gss credentials (in gsskrb5, this means the keytab) */
747 _PUBLIC_
int cli_credentials_get_server_gss_creds(struct cli_credentials
*cred
,
748 struct loadparm_context
*lp_ctx
,
749 struct gssapi_creds_container
**_gcc
)
752 OM_uint32 maj_stat
, min_stat
;
753 struct gssapi_creds_container
*gcc
;
754 struct keytab_container
*ktc
;
755 struct smb_krb5_context
*smb_krb5_context
;
757 krb5_principal princ
;
758 const char *error_string
;
759 enum credentials_obtained obtained
;
761 mem_ctx
= talloc_new(cred
);
766 ret
= cli_credentials_get_krb5_context(cred
, lp_ctx
, &smb_krb5_context
);
771 ret
= principal_from_credentials(mem_ctx
, cred
, smb_krb5_context
, &princ
, &obtained
, &error_string
);
773 DEBUG(1,("cli_credentials_get_server_gss_creds: making krb5 principal failed (%s)\n",
775 talloc_free(mem_ctx
);
779 if (cred
->server_gss_creds_obtained
>= (MAX(cred
->keytab_obtained
, obtained
))) {
780 talloc_free(mem_ctx
);
781 *_gcc
= cred
->server_gss_creds
;
785 ret
= cli_credentials_get_keytab(cred
, lp_ctx
, &ktc
);
787 DEBUG(1, ("Failed to get keytab for GSSAPI server: %s\n", error_message(ret
)));
791 gcc
= talloc(cred
, struct gssapi_creds_container
);
793 talloc_free(mem_ctx
);
797 if (obtained
< CRED_SPECIFIED
) {
798 /* This creates a GSSAPI cred_id_t with the principal and keytab set */
799 maj_stat
= gss_krb5_import_cred(&min_stat
, NULL
, NULL
, ktc
->keytab
,
802 /* This creates a GSSAPI cred_id_t with the principal and keytab set */
803 maj_stat
= gss_krb5_import_cred(&min_stat
, NULL
, princ
, ktc
->keytab
,
814 cred
->server_gss_creds_obtained
= cred
->keytab_obtained
;
815 talloc_set_destructor(gcc
, free_gssapi_creds
);
816 cred
->server_gss_creds
= gcc
;
819 talloc_free(mem_ctx
);
827 _PUBLIC_
void cli_credentials_set_kvno(struct cli_credentials
*cred
,
834 * Return Kerberos KVNO
837 _PUBLIC_
int cli_credentials_get_kvno(struct cli_credentials
*cred
)
843 const char *cli_credentials_get_salt_principal(struct cli_credentials
*cred
)
845 return cred
->salt_principal
;
848 _PUBLIC_
void cli_credentials_set_salt_principal(struct cli_credentials
*cred
, const char *principal
)
850 talloc_free(cred
->salt_principal
);
851 cred
->salt_principal
= talloc_strdup(cred
, principal
);
854 /* The 'impersonate_principal' is used to allow one Kerberos principal
855 * (and it's associated keytab etc) to impersonate another. The
856 * ability to do this is controlled by the KDC, but it is generally
857 * permitted to impersonate anyone to yourself. This allows any
858 * member of the domain to get the groups of a user. This is also
859 * known as S4U2Self */
861 _PUBLIC_
const char *cli_credentials_get_impersonate_principal(struct cli_credentials
*cred
)
863 return cred
->impersonate_principal
;
867 * The 'self_service' is the service principal that
868 * represents the same object (by its objectSid)
869 * as the client principal (typically our machine account).
870 * When trying to impersonate 'impersonate_principal' with
873 _PUBLIC_
const char *cli_credentials_get_self_service(struct cli_credentials
*cred
)
875 return cred
->self_service
;
878 _PUBLIC_
void cli_credentials_set_impersonate_principal(struct cli_credentials
*cred
,
879 const char *principal
,
880 const char *self_service
)
882 talloc_free(cred
->impersonate_principal
);
883 cred
->impersonate_principal
= talloc_strdup(cred
, principal
);
884 talloc_free(cred
->self_service
);
885 cred
->self_service
= talloc_strdup(cred
, self_service
);
886 cli_credentials_set_kerberos_state(cred
, CRED_MUST_USE_KERBEROS
);
890 * when impersonating for S4U2proxy we need to set the target principal.
891 * Similarly, we may only be authorized to do general impersonation to
892 * some particular services.
894 * Likewise, password changes typically require a ticket to kpasswd/realm directly, not via a TGT
896 * NULL means that tickets will be obtained for the krbtgt service.
899 const char *cli_credentials_get_target_service(struct cli_credentials
*cred
)
901 return cred
->target_service
;
904 _PUBLIC_
void cli_credentials_set_target_service(struct cli_credentials
*cred
, const char *target_service
)
906 talloc_free(cred
->target_service
);
907 cred
->target_service
= talloc_strdup(cred
, target_service
);