s4-auth: Always pass down the salt principal
authorAndreas Schneider <asn@samba.org>
Thu, 23 Apr 2015 17:18:32 +0000 (19:18 +0200)
committerJeremy Allison <jra@samba.org>
Thu, 16 Jul 2015 23:38:15 +0000 (01:38 +0200)
We should always pass down the saltPrincipal to smb_krb5_update_keytab()
function.

Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
auth/credentials/credentials_krb5.c
source4/auth/kerberos/srv_keytab.c

index 286bede..6d0ef6f 100644 (file)
@@ -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;
index 3220085..ed7b1a3 100644 (file)
@@ -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) {