From 369c53ccf418cf50c9b94b639b809a3553b4e7ea Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 10 May 2005 14:24:23 +0000 Subject: r6711: Clarify that we are dealing with a salting principal in the kerberos code, which is certainly not in the form of machine$. Rework the default salt to match what I just added to the heimdal server (Samba4 is back on speaking terms with lorikeet heimdal now), from Luke Howard's post to samba-technical in Nov 2004. Now to test compatability with MS... Andrew Bartlett (This used to be commit d719a0093bfe37fc62f28c7c02f17f93eec16abf) --- source4/auth/kerberos/kerberos_verify.c | 100 +++++++++++++++++++------------- 1 file changed, 60 insertions(+), 40 deletions(-) diff --git a/source4/auth/kerberos/kerberos_verify.c b/source4/auth/kerberos/kerberos_verify.c index 4cd48ed63b..927b12d454 100644 --- a/source4/auth/kerberos/kerberos_verify.c +++ b/source4/auth/kerberos/kerberos_verify.c @@ -222,7 +222,7 @@ static krb5_error_code ads_secrets_verify_ticket(TALLOC_CTX *mem_ctx, struct cli_credentials *machine_account, krb5_context context, krb5_auth_context auth_context, - krb5_principal host_princ, + krb5_principal salt_princ, const DATA_BLOB *ticket, krb5_data *p_packet, krb5_ticket **pp_tkt, krb5_keyblock *keyblock) @@ -237,7 +237,7 @@ static krb5_error_code ads_secrets_verify_ticket(TALLOC_CTX *mem_ctx, DEBUG(1, ("ads_secrets_verify_ticket: Could not obtain password for our local machine account!\n")); return ENOENT; } - + ZERO_STRUCTP(keyblock); password.data = password_s; @@ -248,6 +248,8 @@ static krb5_error_code ads_secrets_verify_ticket(TALLOC_CTX *mem_ctx, if ((ret = get_kerberos_allowed_etypes(context, &enctypes))) { DEBUG(1,("ads_secrets_verify_ticket: krb5_get_permitted_enctypes failed (%s)\n", error_message(ret))); + + krb5_free_principal(context, salt_princ); return ret; } @@ -264,7 +266,7 @@ static krb5_error_code ads_secrets_verify_ticket(TALLOC_CTX *mem_ctx, break; } - if (create_kerberos_key_from_string(context, host_princ, &password, key, enctypes[i])) { + if (create_kerberos_key_from_string(context, salt_princ, &password, key, enctypes[i])) { SAFE_FREE(key); continue; } @@ -318,16 +320,62 @@ static krb5_error_code ads_secrets_verify_ticket(TALLOC_CTX *mem_ctx, krb5_rcache rcache = NULL; int ret; - krb5_principal host_princ = NULL; - char *host_princ_s = NULL; BOOL got_replay_mutex = False; char *malloc_principal; + char *machine_username; + krb5_principal salt_princ = NULL; + + NTSTATUS creds_nt_status; + struct cli_credentials *machine_account; ZERO_STRUCT(packet); ZERO_STRUCTP(auth_data); ZERO_STRUCTP(ap_rep); + machine_account = cli_credentials_init(mem_ctx); + cli_credentials_set_conf(machine_account); + creds_nt_status = cli_credentials_set_machine_account(machine_account); + + if (!NT_STATUS_IS_OK(creds_nt_status)) { + DEBUG(3, ("Could not obtain machine account credentials from the local database\n")); + + /* This just becomes a locking key, if we don't have creds, we must be using the keytab */ + ret = krb5_make_principal(context, &salt_princ, lp_realm(), + "host", lp_netbios_name(), NULL); + } else { + + machine_username = talloc_strdup(mem_ctx, cli_credentials_get_username(machine_account)); + + if (!machine_username) { + ret = ENOMEM; + } else { + char *salt_body; + char *lower_realm = strlower_talloc(mem_ctx, cli_credentials_get_realm(machine_account));; + if (machine_username[strlen(machine_username)-1] == '$') { + machine_username[strlen(machine_username)-1] = '\0'; + } + if (!lower_realm) { + ret = ENOMEM; + } else { + salt_body = talloc_asprintf(mem_ctx, "%s.%s", machine_username, + lower_realm); + if (!salt_body) { + ret = ENOMEM; + } else { + ret = krb5_make_principal(context, &salt_princ, cli_credentials_get_realm(machine_account), + "host", salt_body, NULL); + } + } + } + } + + if (ret) { + DEBUG(1,("ads_verify_ticket: maksing salt principal failed (%s)\n", + error_message(ret))); + return NT_STATUS_INTERNAL_ERROR; + } + /* This whole process is far more complex than I would like. We have to go through all this to allow us to store the secret internally, instead of using /etc/krb5.keytab */ @@ -346,7 +394,7 @@ static krb5_error_code ads_secrets_verify_ticket(TALLOC_CTX *mem_ctx, * JRA. We must set the rcache here. This will prevent replay attacks. */ - ret = krb5_get_server_rcache(context, krb5_princ_component(context, host_princ, 0), &rcache); + ret = krb5_get_server_rcache(context, krb5_princ_component(context, salt_princ, 0), &rcache); if (ret) { DEBUG(1,("ads_verify_ticket: krb5_get_server_rcache failed (%s)\n", error_message(ret))); goto out; @@ -361,35 +409,9 @@ static krb5_error_code ads_secrets_verify_ticket(TALLOC_CTX *mem_ctx, ret = ads_keytab_verify_ticket(mem_ctx, context, auth_context, service, ticket, &packet, &tkt, keyblock); if (ret) { - NTSTATUS creds_nt_status; - struct cli_credentials *credentials; - credentials = cli_credentials_init(mem_ctx); - cli_credentials_set_conf(credentials); - creds_nt_status = cli_credentials_set_machine_account(credentials); - - if (!NT_STATUS_IS_OK(creds_nt_status)) { - DEBUG(3, ("Could not obtain machine account credentials from the local database\n")); - } else { - - host_princ_s = talloc_asprintf(mem_ctx, "%s$", lp_netbios_name()); - host_princ_s = strlower_talloc(mem_ctx, host_princ_s); - if (!host_princ_s) { - ret = ENOMEM; - } else { - ret = krb5_parse_name(context, host_princ_s, &host_princ); - } - - if (ret) { - DEBUG(1,("ads_verify_ticket: krb5_parse_name(%s) failed (%s)\n", - host_princ_s, error_message(ret))); - } else { - - DEBUG(10, ("ads_secrets_verify_ticket: using host principal: [%s]\n", host_princ_s)); - ret = ads_secrets_verify_ticket(mem_ctx, credentials, context, auth_context, - host_princ, ticket, - &packet, &tkt, keyblock); - } - } + ret = ads_secrets_verify_ticket(mem_ctx, machine_account, context, auth_context, + salt_princ, ticket, + &packet, &tkt, keyblock); } release_server_mutex(); @@ -458,15 +480,13 @@ static krb5_error_code ads_secrets_verify_ticket(TALLOC_CTX *mem_ctx, data_blob_free(ap_rep); } - if (host_princ) { - krb5_free_principal(context, host_princ); - } - if (tkt != NULL) { krb5_free_ticket(context, tkt); } - SAFE_FREE(host_princ_s); + if (salt_princ != NULL) { + krb5_free_principal(context, salt_princ); + } return sret; } -- cgit