From: Andreas Schneider Date: Thu, 23 Apr 2015 17:18:32 +0000 (+0200) Subject: s4-auth: Always pass down the salt principal X-Git-Tag: talloc-2.1.3~51 X-Git-Url: http://git.samba.org/samba.git/?p=sfrench%2Fsamba-autobuild%2F.git;a=commitdiff_plain;h=c9a8fff52519bb57040bf34b730263f191a6a88f s4-auth: Always pass down the salt principal We should always pass down the saltPrincipal to smb_krb5_update_keytab() function. Signed-off-by: Andreas Schneider Reviewed-by: Jeremy Allison --- diff --git a/auth/credentials/credentials_krb5.c b/auth/credentials/credentials_krb5.c index 286bede2a80..6d0ef6f953e 100644 --- a/auth/credentials/credentials_krb5.c +++ b/auth/credentials/credentials_krb5.c @@ -731,6 +731,83 @@ _PUBLIC_ int cli_credentials_get_client_gss_creds(struct cli_credentials *cred, return ret; } +static int smb_krb5_create_salt_principal(TALLOC_CTX *mem_ctx, + const char *samAccountName, + const char *realm, + const char **salt_principal, + const char **error_string) +{ + char *machine_username; + bool is_machine_account = false; + char *upper_realm; + TALLOC_CTX *tmp_ctx; + int rc = -1; + + if (samAccountName == NULL) { + *error_string = "Cannot determine salt principal, no " + "saltPrincipal or samAccountName specified"; + return rc; + } + + if (realm == NULL) { + *error_string = "Cannot make principal without a realm"; + return rc; + } + + tmp_ctx = talloc_new(mem_ctx); + if (tmp_ctx == NULL) { + *error_string = "Cannot allocate talloc context"; + return rc; + } + + upper_realm = strupper_talloc(tmp_ctx, realm); + if (upper_realm == NULL) { + *error_string = "Cannot allocate to upper case realm"; + goto out; + } + + machine_username = strlower_talloc(tmp_ctx, samAccountName); + if (!machine_username) { + *error_string = "Cannot duplicate samAccountName"; + goto out; + } + + if (machine_username[strlen(machine_username) - 1] == '$') { + machine_username[strlen(machine_username) - 1] = '\0'; + is_machine_account = true; + } + + if (is_machine_account) { + char *lower_realm; + + lower_realm = strlower_talloc(tmp_ctx, realm); + if (lower_realm == NULL) { + *error_string = "Cannot allocate to lower case realm"; + goto out; + } + + *salt_principal = talloc_asprintf(mem_ctx, + "host/%s.%s@%s", + machine_username, + lower_realm, + upper_realm); + } else { + *salt_principal = talloc_asprintf(mem_ctx, + "%s@%s", + machine_username, + upper_realm); + } + if (*salt_principal == NULL) { + *error_string = "Cannot create salt principal"; + goto out; + } + + rc = 0; +out: + talloc_free(tmp_ctx); + return rc; +} + /* Get the keytab (actually, a container containing the krb5_keytab) * attached to this context. If this hasn't been done or set before, * it will be generated from the password. @@ -745,6 +822,10 @@ _PUBLIC_ int cli_credentials_get_keytab(struct cli_credentials *cred, const char *keytab_name; krb5_keytab keytab; TALLOC_CTX *mem_ctx; + const char *username = cli_credentials_get_username(cred); + const char *realm = cli_credentials_get_realm(cred); + const char *error_string; + const char *salt_principal; if (cred->keytab_obtained >= (MAX(cred->principal_obtained, cred->username_obtained))) { @@ -767,13 +848,30 @@ _PUBLIC_ int cli_credentials_get_keytab(struct cli_credentials *cred, return ENOMEM; } + /* + * FIXME: Currently there is no better way than to create the correct + * salt principal by checking if the username ends with a '$'. It would + * be better if it is part of the credentials. + */ + ret = smb_krb5_create_salt_principal(mem_ctx, + username, + realm, + &salt_principal, + &error_string); + if (ret) { + talloc_free(mem_ctx); + return ret; + } + ret = smb_krb5_create_memory_keytab(mem_ctx, - smb_krb5_context->krb5_context, - cli_credentials_get_password(cred), - cli_credentials_get_username(cred), - cli_credentials_get_realm(cred), - cli_credentials_get_kvno(cred), - &keytab, &keytab_name); + smb_krb5_context->krb5_context, + cli_credentials_get_password(cred), + username, + realm, + salt_principal, + cli_credentials_get_kvno(cred), + &keytab, + &keytab_name); if (ret) { talloc_free(mem_ctx); return ret; diff --git a/source4/auth/kerberos/srv_keytab.c b/source4/auth/kerberos/srv_keytab.c index 32200850c11..ed7b1a39183 100644 --- a/source4/auth/kerberos/srv_keytab.c +++ b/source4/auth/kerberos/srv_keytab.c @@ -39,93 +39,6 @@ static void keytab_principals_free(krb5_context context, } } -static krb5_error_code salt_principal(TALLOC_CTX *parent_ctx, - const char *samAccountName, - const char *realm, - const char *saltPrincipal, - krb5_context context, - krb5_principal *salt_princ, - const char **error_string) -{ - - krb5_error_code ret; - char *machine_username; - char *salt_body; - char *lower_realm; - char *upper_realm; - - TALLOC_CTX *tmp_ctx; - - if (saltPrincipal) { - ret = krb5_parse_name(context, saltPrincipal, salt_princ); - if (ret) { - *error_string = smb_get_krb5_error_message( - context, ret, parent_ctx); - } - return ret; - } - - if (!samAccountName) { - (*error_string) = "Cannot determine salt principal, no " - "saltPrincipal or samAccountName specified"; - return EINVAL; - } - - if (!realm) { - *error_string = "Cannot make principal without a realm"; - return EINVAL; - } - - tmp_ctx = talloc_new(parent_ctx); - if (!tmp_ctx) { - *error_string = "Cannot allocate tmp_ctx"; - return ENOMEM; - } - - machine_username = strlower_talloc(tmp_ctx, samAccountName); - if (!machine_username) { - *error_string = "Cannot duplicate samAccountName"; - talloc_free(tmp_ctx); - return ENOMEM; - } - - if (machine_username[strlen(machine_username)-1] == '$') { - machine_username[strlen(machine_username)-1] = '\0'; - } - - lower_realm = strlower_talloc(tmp_ctx, realm); - if (!lower_realm) { - *error_string = "Cannot allocate to lower case realm"; - talloc_free(tmp_ctx); - return ENOMEM; - } - - upper_realm = strupper_talloc(tmp_ctx, realm); - if (!upper_realm) { - *error_string = "Cannot allocate to upper case realm"; - talloc_free(tmp_ctx); - return ENOMEM; - } - - salt_body = talloc_asprintf(tmp_ctx, "%s.%s", - machine_username, lower_realm); - if (!salt_body) { - *error_string = "Cannot form salt principal body"; - talloc_free(tmp_ctx); - return ENOMEM; - } - - ret = smb_krb5_make_principal(context, salt_princ, upper_realm, - "host", salt_body, NULL); - if (ret) { - *error_string = smb_get_krb5_error_message(context, - ret, parent_ctx); - } - - talloc_free(tmp_ctx); - return ret; -} - static krb5_error_code keytab_add_keys(TALLOC_CTX *parent_ctx, uint32_t num_principals, krb5_principal *principals, @@ -227,9 +140,11 @@ static krb5_error_code create_keytab(TALLOC_CTX *parent_ctx, /* The salt used to generate these entries may be different however, * fetch that */ - ret = salt_principal(mem_ctx, samAccountName, realm, saltPrincipal, - context, &salt_princ, error_string); + ret = krb5_parse_name(context, saltPrincipal, &salt_princ); if (ret) { + *error_string = smb_get_krb5_error_message(context, + ret, + parent_ctx); talloc_free(mem_ctx); return ret; } @@ -299,6 +214,11 @@ krb5_error_code smb_krb5_update_keytab(TALLOC_CTX *parent_ctx, return ENOENT; } + if (saltPrincipal == NULL) { + *error_string = "No saltPrincipal provided"; + return EINVAL; + } + ret = krb5_kt_resolve(context, keytab_name, &keytab); if (ret) { *error_string = smb_get_krb5_error_message(context, @@ -389,6 +309,7 @@ krb5_error_code smb_krb5_create_memory_keytab(TALLOC_CTX *parent_ctx, const char *new_secret, const char *samAccountName, const char *realm, + const char *salt_principal, int kvno, krb5_keytab *keytab, const char **keytab_name) @@ -415,7 +336,7 @@ krb5_error_code smb_krb5_create_memory_keytab(TALLOC_CTX *parent_ctx, ret = smb_krb5_update_keytab(mem_ctx, context, *keytab_name, samAccountName, realm, - NULL, 0, NULL, new_secret, NULL, + NULL, 0, salt_principal, new_secret, NULL, kvno, ENC_ALL_TYPES, false, keytab, &error_string); if (ret == 0) {