s4-kerberos: obey the credentials setting for forwardable tickets
authorAndrew Tridgell <tridge@samba.org>
Thu, 16 Sep 2010 04:13:29 +0000 (14:13 +1000)
committerAndrew Tridgell <tridge@samba.org>
Thu, 16 Sep 2010 06:08:46 +0000 (16:08 +1000)
Pair-Programmed-With: Andrew Bartlett <abartlet@samba.org>

source4/auth/kerberos/kerberos.c
source4/auth/kerberos/kerberos.h
source4/auth/kerberos/kerberos_util.c

index 42757640f24b0c73a949de2863c12755f71e4185..0db0dd3ced12c37f192ed4aec35c3494274b2c31 100644 (file)
  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;
  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 */
                                                 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;
        }
                *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) {
index b4422b5b16d2355eb272c90f0b7992a6a8e57f00..b58014f4930a6db309ebf4431f2f4725e3138393 100644 (file)
@@ -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);
index 30e43f0795a4f2fea44a61f1e1951b15e1c54180..8b533f6c21cf7c4eba651d40c02cec6e229f0f00 100644 (file)
@@ -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),