r10035: This patch removes the need for the special case hack
authorAndrew Bartlett <abartlet@samba.org>
Mon, 5 Sep 2005 10:53:14 +0000 (10:53 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:36:31 +0000 (13:36 -0500)
'MEMORY_WILDCARD' keytab type. (part of this checking is in effect a
merge from lorikeet-heimdal, where I removed this)

This is achieved by correctly using the GSSAPI gsskrb5_acquire_cred()
function, as this allows us to specify the target principal, regardless
of which alias the client may use.

This patch also tries to simplify some principal handling and fixes some
error cases.

Posted to samba-technical, reviewed by metze, and looked over by lha on IRC.

Andrew Bartlett

source/auth/gensec/gensec_gssapi.c
source/auth/kerberos/kerberos.c
source/auth/kerberos/kerberos.h
source/auth/kerberos/kerberos_util.c
source/heimdal/lib/krb5/context.c
source/heimdal/lib/krb5/keytab_memory.c
source/heimdal/lib/krb5/krb5.h

index 26494f022284d3fc047719281145f966411e3573..6316b52bad764e56a74c961b7990f17684e23514 100644 (file)
@@ -154,6 +154,7 @@ static NTSTATUS gensec_gssapi_server_start(struct gensec_security *gensec_securi
 {
        NTSTATUS nt_status;
        OM_uint32 maj_stat, min_stat;
+       gss_buffer_desc name_token;
        struct gensec_gssapi_state *gensec_gssapi_state;
        struct cli_credentials *machine_account;
 
@@ -177,7 +178,6 @@ static NTSTATUS gensec_gssapi_server_start(struct gensec_security *gensec_securi
                                                 machine_account, 
                                                 gensec_gssapi_state->smb_krb5_context,
                                                 &gensec_gssapi_state->keytab);
-               talloc_free(machine_account);
                if (!NT_STATUS_IS_OK(nt_status)) {
                        DEBUG(3, ("Could not create memory keytab!\n"));
                        talloc_free(machine_account);
@@ -185,9 +185,26 @@ static NTSTATUS gensec_gssapi_server_start(struct gensec_security *gensec_securi
                }
        }
 
+       name_token.value = cli_credentials_get_principal(machine_account, 
+                                                        machine_account);
+       name_token.length = strlen(name_token.value);
+
+       maj_stat = gss_import_name (&min_stat,
+                                   &name_token,
+                                   GSS_C_NT_USER_NAME,
+                                   &gensec_gssapi_state->server_name);
+       talloc_free(machine_account);
+
+       if (maj_stat) {
+               DEBUG(2, ("GSS Import name of %s failed: %s\n",
+                         (char *)name_token.value,
+                         gssapi_error_string(gensec_gssapi_state, maj_stat, min_stat)));
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
        maj_stat = gsskrb5_acquire_cred(&min_stat, 
                                        gensec_gssapi_state->keytab, NULL,
-                                       NULL,
+                                       gensec_gssapi_state->server_name,
                                        GSS_C_INDEFINITE,
                                        GSS_C_NULL_OID_SET,
                                        GSS_C_ACCEPT,
index 31e0c71c55072ec81444541388c724590d082d79..3935bfaf92af04bd130f2ca090d4ca17cf546718 100644 (file)
@@ -69,35 +69,27 @@ kerb_prompter(krb5_context ctx, void *data,
   original password.
 */
  int kerberos_kinit_keyblock_cc(krb5_context ctx, krb5_ccache cc, 
-                               const char *principal, krb5_keyblock *keyblock,
+                               krb5_principal principal, krb5_keyblock *keyblock,
                                time_t *expire_time, time_t *kdc_time)
 {
        krb5_error_code code = 0;
-       krb5_principal me;
        krb5_creds my_creds;
        krb5_get_init_creds_opt options;
 
-       if ((code = krb5_parse_name(ctx, principal, &me))) {
-               return code;
-       }
-
        krb5_get_init_creds_opt_init(&options);
 
-       if ((code = krb5_get_init_creds_keyblock(ctx, &my_creds, me, keyblock,
+       if ((code = krb5_get_init_creds_keyblock(ctx, &my_creds, principal, keyblock,
                                                 0, NULL, &options))) {
-               krb5_free_principal(ctx, me);
                return code;
        }
        
-       if ((code = krb5_cc_initialize(ctx, cc, me))) {
+       if ((code = krb5_cc_initialize(ctx, cc, principal))) {
                krb5_free_cred_contents(ctx, &my_creds);
-               krb5_free_principal(ctx, me);
                return code;
        }
        
        if ((code = krb5_cc_store_cred(ctx, cc, &my_creds))) {
                krb5_free_cred_contents(ctx, &my_creds);
-               krb5_free_principal(ctx, me);
                return code;
        }
        
@@ -110,7 +102,6 @@ kerb_prompter(krb5_context ctx, void *data,
        }
 
        krb5_free_cred_contents(ctx, &my_creds);
-       krb5_free_principal(ctx, me);
        
        return 0;
 }
@@ -120,36 +111,28 @@ kerb_prompter(krb5_context ctx, void *data,
   Orignally by remus@snapserver.com
 */
  int kerberos_kinit_password_cc(krb5_context ctx, krb5_ccache cc, 
-                              const char *principal, const char *password, 
-                              time_t *expire_time, time_t *kdc_time)
+                               krb5_principal principal, const char *password, 
+                               time_t *expire_time, time_t *kdc_time)
 {
        krb5_error_code code = 0;
-       krb5_principal me;
        krb5_creds my_creds;
        krb5_get_init_creds_opt options;
 
-       if ((code = krb5_parse_name(ctx, principal, &me))) {
-               return code;
-       }
-
        krb5_get_init_creds_opt_init(&options);
 
-       if ((code = krb5_get_init_creds_password(ctx, &my_creds, me, password, 
+       if ((code = krb5_get_init_creds_password(ctx, &my_creds, principal, password, 
                                                 kerb_prompter, 
                                                 NULL, 0, NULL, &options))) {
-               krb5_free_principal(ctx, me);
                return code;
        }
        
-       if ((code = krb5_cc_initialize(ctx, cc, me))) {
+       if ((code = krb5_cc_initialize(ctx, cc, principal))) {
                krb5_free_cred_contents(ctx, &my_creds);
-               krb5_free_principal(ctx, me);
                return code;
        }
        
        if ((code = krb5_cc_store_cred(ctx, cc, &my_creds))) {
                krb5_free_cred_contents(ctx, &my_creds);
-               krb5_free_principal(ctx, me);
                return code;
        }
        
@@ -162,7 +145,6 @@ kerb_prompter(krb5_context ctx, void *data,
        }
 
        krb5_free_cred_contents(ctx, &my_creds);
-       krb5_free_principal(ctx, me);
        
        return 0;
 }
index 8cc8e561accf5aebbdc331116622eb2570161cc5..39bba5f46f94ddfdbb9085c1208baf82e91289db 100644 (file)
@@ -102,10 +102,10 @@ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
                           DATA_BLOB *ap_rep,
                           krb5_keyblock **keyblock);
 int kerberos_kinit_password_cc(krb5_context ctx, krb5_ccache cc, 
-                              const char *principal, const char *password, 
+                              krb5_principal principal, const char *password, 
                               time_t *expire_time, time_t *kdc_time);
 int kerberos_kinit_keyblock_cc(krb5_context ctx, krb5_ccache cc, 
-                              const char *principal, krb5_keyblock *keyblock,
+                              krb5_principal principal, krb5_keyblock *keyblock,
                               time_t *expire_time, time_t *kdc_time);
 krb5_principal kerberos_fetch_salt_princ_for_host_princ(krb5_context context,
                                                        krb5_principal host_princ,
index 9dc8621b0ea52ed133b00cfc6bd3f9cacd8b0c73..922869af5c4e2087b0ecc8d492ea75431b78c209 100644 (file)
@@ -87,7 +87,7 @@ krb5_error_code salt_principal_from_credentials(TALLOC_CTX *parent_ctx,
                                  cli_credentials_get_realm(machine_account), 
                                  "host", salt_body, NULL);
 
-       if (ret != 0) {
+       if (ret == 0) {
                mem_ctx->smb_krb5_context = talloc_reference(mem_ctx, smb_krb5_context);
                mem_ctx->principal = *salt_princ;
                talloc_set_destructor(mem_ctx, free_principal);
@@ -95,6 +95,36 @@ krb5_error_code salt_principal_from_credentials(TALLOC_CTX *parent_ctx,
        return ret;
 }
 
+krb5_error_code principal_from_credentials(TALLOC_CTX *parent_ctx, 
+                                          struct cli_credentials *credentials, 
+                                          struct smb_krb5_context *smb_krb5_context,
+                                          krb5_principal *princ)
+{
+       krb5_error_code ret;
+       const char *princ_string;
+       struct principal_container *mem_ctx = talloc(parent_ctx, struct principal_container);
+       if (!mem_ctx) {
+               return ENOMEM;
+       }
+       
+       princ_string = cli_credentials_get_principal(credentials, mem_ctx);
+
+       if (!princ_string) {
+               talloc_free(mem_ctx);
+               return ENOMEM;
+       }
+
+       ret = krb5_parse_name(smb_krb5_context->krb5_context,
+                             princ_string, princ);
+
+       if (ret == 0) {
+               mem_ctx->smb_krb5_context = talloc_reference(mem_ctx, smb_krb5_context);
+               mem_ctx->principal = *princ;
+               talloc_set_destructor(mem_ctx, free_principal);
+       }
+       return ret;
+}
+
 /**
  * Return a freshly allocated ccache (destroyed by destructor on child
  * of parent_ctx), for a given set of client credentials 
@@ -108,6 +138,7 @@ krb5_error_code salt_principal_from_credentials(TALLOC_CTX *parent_ctx,
        krb5_error_code ret;
        const char *password;
        time_t kdc_time = 0;
+       krb5_principal princ;
 
        TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
 
@@ -115,11 +146,17 @@ krb5_error_code salt_principal_from_credentials(TALLOC_CTX *parent_ctx,
                return ENOMEM;
        }
 
+       ret = principal_from_credentials(mem_ctx, credentials, smb_krb5_context, &princ);
+       if (ret) {
+               talloc_free(mem_ctx);
+               return ret;
+       }
+
        password = cli_credentials_get_password(credentials);
        
        if (password) {
                ret = kerberos_kinit_password_cc(smb_krb5_context->krb5_context, ccache, 
-                                                cli_credentials_get_principal(credentials, mem_ctx)
+                                                princ
                                                 password, NULL, &kdc_time);
        } else {
                /* No password available, try to use a keyblock instead */
@@ -139,7 +176,7 @@ 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, 
-                                                        cli_credentials_get_principal(credentials, mem_ctx), 
+                                                        princ,
                                                         &keyblock, NULL, &kdc_time);
                        krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &keyblock);
                }
@@ -191,12 +228,13 @@ static int free_keytab(void *ptr) {
        struct keytab_container *mem_ctx = talloc(parent_ctx, struct keytab_container);
        krb5_enctype *enctypes;
        krb5_principal salt_princ;
+       krb5_principal princ;
        
        if (!mem_ctx) {
                return NT_STATUS_NO_MEMORY;
        }
 
-       ret = krb5_kt_resolve(smb_krb5_context->krb5_context, "MEMORY_WILDCARD:", keytab);
+       ret = krb5_kt_resolve(smb_krb5_context->krb5_context, "MEMORY:", keytab);
        if (ret) {
                DEBUG(1,("failed to generate a new krb5 keytab: %s\n", 
                         error_message(ret)));
@@ -214,7 +252,18 @@ static int free_keytab(void *ptr) {
                                              &salt_princ);
        if (ret) {
                DEBUG(1,("create_memory_keytab: maksing salt principal failed (%s)\n",
-                        error_message(ret)));
+                        smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
+                                                   ret, mem_ctx)));
+               talloc_free(mem_ctx);
+               return NT_STATUS_INTERNAL_ERROR;
+       }
+
+       ret = principal_from_credentials(mem_ctx, machine_account, smb_krb5_context, &princ);
+       if (ret) {
+               DEBUG(1,("create_memory_keytab: maksing krb5 principal failed (%s)\n",
+                        smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
+                                                   ret, mem_ctx)));
+               talloc_free(mem_ctx);
                return NT_STATUS_INTERNAL_ERROR;
        }
 
@@ -243,7 +292,7 @@ static int free_keytab(void *ptr) {
                        return NT_STATUS_INTERNAL_ERROR;
                }
 
-               entry.principal = salt_princ;
+               entry.principal = princ;
                entry.vno       = cli_credentials_get_kvno(machine_account);
                ret = krb5_kt_add_entry(smb_krb5_context->krb5_context, *keytab, &entry);
                if (ret) {
@@ -283,7 +332,7 @@ static int free_keytab(void *ptr) {
                        return NT_STATUS_INTERNAL_ERROR;
                }
 
-                entry.principal = salt_princ;
+                entry.principal = princ;
                 entry.vno       = cli_credentials_get_kvno(machine_account);
                ret = krb5_kt_add_entry(smb_krb5_context->krb5_context, *keytab, &entry);
                if (ret) {
index 62fb92d66646cf4bfbb3b0c8dcd1f8728a37cf08..4d6eae2b24b9862295122e30cc6b493efa9aa108 100644 (file)
@@ -231,7 +231,6 @@ krb5_init_context(krb5_context *context)
     krb5_kt_register (p, &krb5_wrfkt_ops);
     krb5_kt_register (p, &krb5_javakt_ops);
     krb5_kt_register (p, &krb5_mkt_ops);
-    krb5_kt_register (p, &krb5_mktw_ops);
     krb5_kt_register (p, &krb5_akf_ops);
     krb5_kt_register (p, &krb4_fkt_ops);
     krb5_kt_register (p, &krb5_srvtab_fkt_ops);
index 3dca5154e30bc904a4c32c2fcb662c920d517787..1d866fa11e08e73092ea30b0e2f6efbb247e958b 100644 (file)
@@ -174,56 +174,3 @@ const krb5_kt_ops krb5_mkt_ops = {
     mkt_add_entry,
     mkt_remove_entry
 };
-
-static krb5_error_code 
-mktw_get_entry(krb5_context context,
-              krb5_keytab id,
-              krb5_const_principal principal,
-              krb5_kvno kvno,
-              krb5_enctype enctype,
-              krb5_keytab_entry *entry)
-{
-    krb5_keytab_entry tmp;
-    krb5_error_code ret;
-    krb5_kt_cursor cursor;
-
-    ret = krb5_kt_start_seq_get (context, id, &cursor);
-    if (ret)
-       return KRB5_KT_NOTFOUND; /* XXX i.e. file not found */
-
-    entry->vno = 0;
-    while (krb5_kt_next_entry(context, id, &tmp, &cursor) == 0) {
-       if (krb5_kt_compare(context, &tmp, NULL, 0, enctype)) {
-           if (kvno == tmp.vno) {
-               krb5_kt_copy_entry_contents (context, &tmp, entry);
-               krb5_kt_free_entry (context, &tmp);
-               krb5_kt_end_seq_get(context, id, &cursor);
-               return 0;
-           } else if (kvno == 0 && tmp.vno > entry->vno) {
-               if (entry->vno)
-                   krb5_kt_free_entry (context, entry);
-               krb5_kt_copy_entry_contents (context, &tmp, entry);
-           }
-       }
-       krb5_kt_free_entry(context, &tmp);
-    }
-    krb5_kt_end_seq_get (context, id, &cursor);
-    if (entry->vno) {
-       return 0;
-    } else {
-           return KRB5_KT_NOTFOUND;
-    }
-};
-
-const krb5_kt_ops krb5_mktw_ops = {
-    "MEMORY_WILDCARD",
-    mkt_resolve,
-    mkt_get_name,
-    mkt_close,
-    mktw_get_entry, /* get */
-    mkt_start_seq_get,
-    mkt_next_entry,
-    mkt_end_seq_get,
-    mkt_add_entry,
-    mkt_remove_entry
-};
index 5789bff2050980cd2a092003ab92758bead32e2e..c47c4450f15a37b3cd6b06acb95dc3709dfa6728 100644 (file)
@@ -698,7 +698,6 @@ extern const krb5_kt_ops krb5_fkt_ops;
 extern const krb5_kt_ops krb5_wrfkt_ops;
 extern const krb5_kt_ops krb5_javakt_ops;
 extern const krb5_kt_ops krb5_mkt_ops;
-extern const krb5_kt_ops krb5_mktw_ops;
 extern const krb5_kt_ops krb5_akf_ops;
 extern const krb5_kt_ops krb4_fkt_ops;
 extern const krb5_kt_ops krb5_srvtab_fkt_ops;