From 89827af5250a0e65e19ee3752cfe407a6e01856f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 16 Sep 2010 14:13:29 +1000 Subject: s4-kerberos: obey the credentials setting for forwardable tickets Pair-Programmed-With: Andrew Bartlett --- source4/auth/kerberos/kerberos.c | 27 ++++----------------------- source4/auth/kerberos/kerberos.h | 8 +++++--- source4/auth/kerberos/kerberos_util.c | 32 +++++++++++++++++++++++++++++++- 3 files changed, 40 insertions(+), 27 deletions(-) (limited to 'source4') diff --git a/source4/auth/kerberos/kerberos.c b/source4/auth/kerberos/kerberos.c index 42757640f2..0db0dd3ced 100644 --- a/source4/auth/kerberos/kerberos.c +++ b/source4/auth/kerberos/kerberos.c @@ -41,31 +41,23 @@ krb5_error_code kerberos_kinit_keyblock_cc(krb5_context ctx, krb5_ccache cc, krb5_principal principal, krb5_keyblock *keyblock, const char *target_service, + krb5_get_init_creds_opt *krb_options, time_t *expire_time, time_t *kdc_time) { krb5_error_code code = 0; krb5_creds my_creds; - krb5_get_init_creds_opt *options; - - if ((code = krb5_get_init_creds_opt_alloc(ctx, &options))) { - return code; - } - - krb5_get_init_creds_opt_set_default_flags(ctx, NULL, NULL, options); if ((code = krb5_get_init_creds_keyblock(ctx, &my_creds, principal, keyblock, - 0, target_service, options))) { + 0, target_service, krb_options))) { return code; } if ((code = krb5_cc_initialize(ctx, cc, principal))) { - krb5_get_init_creds_opt_free(ctx, options); krb5_free_cred_contents(ctx, &my_creds); return code; } if ((code = krb5_cc_store_cred(ctx, cc, &my_creds))) { - krb5_get_init_creds_opt_free(ctx, options); krb5_free_cred_contents(ctx, &my_creds); return code; } @@ -78,7 +70,6 @@ *kdc_time = (time_t) my_creds.times.starttime; } - krb5_get_init_creds_opt_free(ctx, options); krb5_free_cred_contents(ctx, &my_creds); return 0; @@ -96,20 +87,14 @@ krb5_error_code kerberos_kinit_password_cc(krb5_context ctx, krb5_ccache cc, krb5_principal principal, const char *password, krb5_principal impersonate_principal, const char *target_service, + krb5_get_init_creds_opt *krb_options, time_t *expire_time, time_t *kdc_time) { krb5_error_code code = 0; krb5_creds my_creds; krb5_creds *impersonate_creds; - krb5_get_init_creds_opt *init_options; krb5_get_creds_opt options; - if ((code = krb5_get_init_creds_opt_alloc(ctx, &init_options))) { - return code; - } - - krb5_get_init_creds_opt_set_default_flags(ctx, NULL, NULL, init_options); - /* If we are not impersonating, then get this ticket for the * target service, otherwise a krbtgt, and get the next ticket * for the target */ @@ -117,19 +102,16 @@ NULL, NULL, 0, impersonate_principal ? NULL : target_service, - init_options))) { - krb5_get_init_creds_opt_free(ctx, init_options); + krb_options))) { return code; } if ((code = krb5_cc_initialize(ctx, cc, principal))) { - krb5_get_init_creds_opt_free(ctx, init_options); krb5_free_cred_contents(ctx, &my_creds); return code; } if ((code = krb5_cc_store_cred(ctx, cc, &my_creds))) { - krb5_get_init_creds_opt_free(ctx, init_options); krb5_free_cred_contents(ctx, &my_creds); return code; } @@ -142,7 +124,6 @@ *kdc_time = (time_t) my_creds.times.starttime; } - krb5_get_init_creds_opt_free(ctx, init_options); krb5_free_cred_contents(ctx, &my_creds); if (code == 0 && impersonate_principal) { diff --git a/source4/auth/kerberos/kerberos.h b/source4/auth/kerberos/kerberos.h index b4422b5b16..b58014f493 100644 --- a/source4/auth/kerberos/kerberos.h +++ b/source4/auth/kerberos/kerberos.h @@ -94,11 +94,13 @@ bool get_auth_data_from_tkt(TALLOC_CTX *mem_ctx, DATA_BLOB *auth_data, krb5_tick krb5_error_code kerberos_kinit_password_cc(krb5_context ctx, krb5_ccache cc, krb5_principal principal, const char *password, krb5_principal impersonate_principal, const char *target_service, + krb5_get_init_creds_opt *krb_options, time_t *expire_time, time_t *kdc_time); krb5_error_code kerberos_kinit_keyblock_cc(krb5_context ctx, krb5_ccache cc, - krb5_principal principal, krb5_keyblock *keyblock, - const char *target_service, - time_t *expire_time, time_t *kdc_time); + krb5_principal principal, krb5_keyblock *keyblock, + const char *target_service, + krb5_get_init_creds_opt *krb_options, + time_t *expire_time, time_t *kdc_time); krb5_principal kerberos_fetch_salt_princ_for_host_princ(krb5_context context, krb5_principal host_princ, int enctype); diff --git a/source4/auth/kerberos/kerberos_util.c b/source4/auth/kerberos/kerberos_util.c index 30e43f0795..8b533f6c21 100644 --- a/source4/auth/kerberos/kerberos_util.c +++ b/source4/auth/kerberos/kerberos_util.c @@ -200,6 +200,7 @@ static krb5_error_code salt_principal_from_credentials(TALLOC_CTX *parent_ctx, krb5_principal impersonate_principal; int tries; TALLOC_CTX *mem_ctx = talloc_new(parent_ctx); + krb5_get_init_creds_opt *krb_options; if (!mem_ctx) { (*error_string) = strerror(ENOMEM); @@ -222,12 +223,37 @@ static krb5_error_code salt_principal_from_credentials(TALLOC_CTX *parent_ctx, password = cli_credentials_get_password(credentials); + /* setup the krb5 options we want */ + if ((ret = krb5_get_init_creds_opt_alloc(smb_krb5_context->krb5_context, &krb_options))) { + (*error_string) = talloc_asprintf(credentials, "krb5_get_init_creds_opt_alloc failed (%s)\n", + smb_get_krb5_error_message(smb_krb5_context->krb5_context, + ret, mem_ctx)); + talloc_free(mem_ctx); + return ret; + } + + /* get the defaults */ + krb5_get_init_creds_opt_set_default_flags(smb_krb5_context->krb5_context, NULL, NULL, krb_options); + + /* set if we want a forwardable ticket */ + switch (cli_credentials_get_krb_forwardable(credentials)) { + case CRED_AUTO_KRB_FORWARDABLE: + break; + case CRED_NO_KRB_FORWARDABLE: + krb5_get_init_creds_opt_set_forwardable(krb_options, FALSE); + break; + case CRED_FORCE_KRB_FORWARDABLE: + krb5_get_init_creds_opt_set_forwardable(krb_options, TRUE); + break; + } + tries = 2; while (tries--) { if (password) { ret = kerberos_kinit_password_cc(smb_krb5_context->krb5_context, ccache, princ, password, impersonate_principal, target_service, + krb_options, NULL, &kdc_time); } else if (impersonate_principal) { (*error_string) = "INTERNAL error: Cannot impersonate principal with just a keyblock. A password must be specified in the credentials"; @@ -241,6 +267,7 @@ static krb5_error_code salt_principal_from_credentials(TALLOC_CTX *parent_ctx, if (!mach_pwd) { talloc_free(mem_ctx); (*error_string) = "kinit_to_ccache: No password available for kinit\n"; + krb5_get_init_creds_opt_free(smb_krb5_context->krb5_context, krb_options); return EINVAL; } ret = krb5_keyblock_init(smb_krb5_context->krb5_context, @@ -251,7 +278,7 @@ static krb5_error_code salt_principal_from_credentials(TALLOC_CTX *parent_ctx, if (ret == 0) { ret = kerberos_kinit_keyblock_cc(smb_krb5_context->krb5_context, ccache, princ, &keyblock, - target_service, + target_service, krb_options, NULL, &kdc_time); krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &keyblock); } @@ -267,6 +294,8 @@ static krb5_error_code salt_principal_from_credentials(TALLOC_CTX *parent_ctx, } } + krb5_get_init_creds_opt_free(smb_krb5_context->krb5_context, krb_options); + if (ret == KRB5KRB_AP_ERR_SKEW || ret == KRB5_KDCREP_SKEW) { (*error_string) = talloc_asprintf(credentials, "kinit for %s failed (%s)\n", cli_credentials_get_principal(credentials, mem_ctx), @@ -291,6 +320,7 @@ static krb5_error_code salt_principal_from_credentials(TALLOC_CTX *parent_ctx, ccache, obtained, error_string); } + if (ret) { (*error_string) = talloc_asprintf(credentials, "kinit for %s failed (%s)\n", cli_credentials_get_principal(credentials, mem_ctx), -- cgit