lib/krb5_wrap: use krb5_const_principal in smb_krb5_create_key_from_string.
[kai/samba-autobuild/.git] / source4 / auth / kerberos / srv_keytab.c
index 475f09d9342807de2300204ae706721efe381f2c..754f2c2c2c9c0cd97fb7627a2bc577e333cf2690 100644 (file)
@@ -22,7 +22,6 @@
 
 
 #include "includes.h"
-#include "auth/credentials/credentials.h"
 #include "system/kerberos.h"
 #include "auth/kerberos/kerberos.h"
 #include "auth/kerberos/kerberos_srv_keytab.h"
@@ -55,8 +54,7 @@ static krb5_error_code principals_from_list(TALLOC_CTX *parent_ctx,
        }
 
        if (!realm) {
-               *error_string = "Cannot have a kerberos secret in "
-                               "secrets.ldb without a realm";
+               *error_string = "Cannot make principal without a realm";
                ret = EINVAL;
                goto done;
        }
@@ -82,7 +80,7 @@ static krb5_error_code principals_from_list(TALLOC_CTX *parent_ctx,
        }
 
        if (samAccountName) {
-               ret = krb5_make_principal(context, &principals[i],
+               ret = smb_krb5_make_principal(context, &principals[i],
                                          upper_realm, samAccountName,
                                          NULL);
                if (ret) {
@@ -135,8 +133,7 @@ static krb5_error_code salt_principal(TALLOC_CTX *parent_ctx,
        }
 
        if (!realm) {
-               *error_string = "Cannot have a kerberos secret in "
-                               "secrets.ldb without a realm";
+               *error_string = "Cannot make principal without a realm";
                return EINVAL;
        }
 
@@ -146,7 +143,7 @@ static krb5_error_code salt_principal(TALLOC_CTX *parent_ctx,
                return ENOMEM;
        }
 
-       machine_username = talloc_strdup(tmp_ctx, samAccountName);
+       machine_username = strlower_talloc(tmp_ctx, samAccountName);
        if (!machine_username) {
                *error_string = "Cannot duplicate samAccountName";
                talloc_free(tmp_ctx);
@@ -179,7 +176,7 @@ static krb5_error_code salt_principal(TALLOC_CTX *parent_ctx,
                return ENOMEM;
        }
 
-       ret = krb5_make_principal(context, salt_princ, upper_realm,
+       ret = smb_krb5_make_principal(context, salt_princ, upper_realm,
                                                "host", salt_body, NULL);
        if (ret) {
                *error_string = smb_get_krb5_error_message(context,
@@ -190,51 +187,6 @@ static krb5_error_code salt_principal(TALLOC_CTX *parent_ctx,
        return ret;
 }
 
-/* Translate between the Microsoft msDS-SupportedEncryptionTypes values
- * and the IETF encryption type values */
-static krb5_enctype ms_suptype_to_ietf_enctype(uint32_t enctype_bitmap)
-{
-       switch (enctype_bitmap) {
-       case ENC_CRC32:
-               return ENCTYPE_DES_CBC_CRC;
-       case ENC_RSA_MD5:
-               return ENCTYPE_DES_CBC_MD5;
-       case ENC_RC4_HMAC_MD5:
-               return ENCTYPE_ARCFOUR_HMAC_MD5;
-       case ENC_HMAC_SHA1_96_AES128:
-               return ENCTYPE_AES128_CTS_HMAC_SHA1_96;
-       case ENC_HMAC_SHA1_96_AES256:
-               return ENCTYPE_AES256_CTS_HMAC_SHA1_96;
-       default:
-               return 0;
-       }
-}
-
-/* Return an array of krb5_enctype values */
-static krb5_error_code ms_suptypes_to_ietf_enctypes(TALLOC_CTX *mem_ctx,
-                                               uint32_t enctype_bitmap,
-                                               krb5_enctype **enctypes)
-{
-       unsigned int i, j = 0;
-       *enctypes = talloc_zero_array(mem_ctx, krb5_enctype,
-                                       (8 * sizeof(enctype_bitmap)) + 1);
-       if (!*enctypes) {
-               return ENOMEM;
-       }
-       for (i = 0; i < (8 * sizeof(enctype_bitmap)); i++) {
-               uint32_t bit_value = (1 << i) & enctype_bitmap;
-               if (bit_value & enctype_bitmap) {
-                       (*enctypes)[j] = ms_suptype_to_ietf_enctype(bit_value);
-                       if (!(*enctypes)[j]) {
-                               continue;
-                       }
-                       j++;
-               }
-       }
-       (*enctypes)[j] = 0;
-       return 0;
-}
-
 static krb5_error_code keytab_add_keys(TALLOC_CTX *parent_ctx,
                                       krb5_principal *principals,
                                       krb5_principal salt_princ,
@@ -250,7 +202,7 @@ static krb5_error_code keytab_add_keys(TALLOC_CTX *parent_ctx,
        krb5_data password;
        char *unparsed;
 
-       password.data = discard_const_p(char *, password_s);
+       password.data = discard_const_p(char, password_s);
        password.length = strlen(password_s);
 
        for (i = 0; enctypes[i]; i++) {
@@ -258,9 +210,12 @@ static krb5_error_code keytab_add_keys(TALLOC_CTX *parent_ctx,
 
                ZERO_STRUCT(entry);
 
-               ret = create_kerberos_key_from_string_direct(context,
-                                               salt_princ, &password,
-                                               &entry.keyblock, enctypes[i]);
+               ret = smb_krb5_create_key_from_string(context,
+                                                     salt_princ,
+                                                     NULL,
+                                                     &password,
+                                                     enctypes[i],
+                                                     KRB5_KT_KEY(&entry));
                if (ret != 0) {
                        return ret;
                }
@@ -286,14 +241,14 @@ static krb5_error_code keytab_add_keys(TALLOC_CTX *parent_ctx,
                                free(unparsed);
                                talloc_free(k5_error_string);
                                krb5_free_keyblock_contents(context,
-                                                           &entry.keyblock);
+                                                           KRB5_KT_KEY(&entry));
                                return ret;
                        }
 
                        DEBUG(5, ("Added key (kvno %d) to keytab (enctype %d)\n",
                                  kvno, (int)enctypes[i]));
                }
-               krb5_free_keyblock_contents(context, &entry.keyblock);
+               krb5_free_keyblock_contents(context, KRB5_KT_KEY(&entry));
        }
        return 0;
 }
@@ -324,7 +279,8 @@ static krb5_error_code create_keytab(TALLOC_CTX *parent_ctx,
 
        mem_ctx = talloc_new(parent_ctx);
        if (!mem_ctx) {
-               *error_string = "unable to allocate tmp_ctx for create_keytab";
+               *error_string = talloc_strdup(parent_ctx,
+                       "unable to allocate tmp_ctx for create_keytab");
                return ENOMEM;
        }
 
@@ -351,6 +307,7 @@ static krb5_error_code create_keytab(TALLOC_CTX *parent_ctx,
                              salt_princ, kvno, new_secret,
                              context, enctypes, keytab, error_string);
        if (ret) {
+               talloc_steal(parent_ctx, *error_string);
                goto done;
        }
 
@@ -358,6 +315,9 @@ static krb5_error_code create_keytab(TALLOC_CTX *parent_ctx,
                ret = keytab_add_keys(mem_ctx, principals,
                                      salt_princ, kvno - 1, old_secret,
                                      context, enctypes, keytab, error_string);
+               if (ret) {
+                       talloc_steal(parent_ctx, *error_string);
+               }
        }
 
 done:
@@ -400,7 +360,9 @@ static krb5_error_code remove_old_entries(TALLOC_CTX *parent_ctx,
        switch (ret) {
        case 0:
                break;
+#ifdef HEIM_ERR_OPNOTSUPP
        case HEIM_ERR_OPNOTSUPP:
+#endif
        case ENOENT:
        case KRB5_KT_END:
                /* no point enumerating if there isn't anything here */
@@ -418,14 +380,15 @@ static krb5_error_code remove_old_entries(TALLOC_CTX *parent_ctx,
                unsigned int i;
                bool matched = false;
                krb5_keytab_entry entry;
+
                ret = krb5_kt_next_entry(context, keytab, &entry, &cursor);
                if (ret) {
                        break;
                }
                for (i = 0; principals[i]; i++) {
                        /* if it matches our principal */
-                       if (krb5_kt_compare(context, &entry,
-                                           principals[i], 0, 0)) {
+                       if (smb_krb5_kt_compare(context, &entry,
+                                               principals[i], 0, 0)) {
                                matched = true;
                                break;
                        }
@@ -435,6 +398,8 @@ static krb5_error_code remove_old_entries(TALLOC_CTX *parent_ctx,
                        /* Free the entry,
                         * it wasn't the one we were looking for anyway */
                        krb5_kt_free_entry(context, &entry);
+                       /* Make sure we do not double free */
+                       ZERO_STRUCT(entry);
                        continue;
                }
 
@@ -452,11 +417,15 @@ static krb5_error_code remove_old_entries(TALLOC_CTX *parent_ctx,
 
                        ret = krb5_kt_remove_entry(context, keytab, &entry);
                        krb5_kt_free_entry(context, &entry);
+                       /* Make sure we do not double free */
+                       ZERO_STRUCT(entry);
 
                        /* Deleted: Restart from the top */
                        ret2 = krb5_kt_start_seq_get(context, keytab, &cursor);
                        if (ret2) {
                                krb5_kt_free_entry(context, &entry);
+                               /* Make sure we do not double free */
+                               ZERO_STRUCT(entry);
                                DEBUG(1, ("failed to restart enumeration of keytab: %s\n",
                                          smb_get_krb5_error_message(context,
                                                                ret, mem_ctx)));
@@ -475,6 +444,8 @@ static krb5_error_code remove_old_entries(TALLOC_CTX *parent_ctx,
 
                /* Free the entry, we don't need it any more */
                krb5_kt_free_entry(context, &entry);
+               /* Make sure we do not double free */
+               ZERO_STRUCT(entry);
        }
        krb5_kt_end_seq_get(context, keytab, &cursor);
 
@@ -495,7 +466,7 @@ static krb5_error_code remove_old_entries(TALLOC_CTX *parent_ctx,
 }
 
 krb5_error_code smb_krb5_update_keytab(TALLOC_CTX *parent_ctx,
-                               struct smb_krb5_context *smb_krb5_context,
+                               krb5_context context,
                                const char *keytab_name,
                                const char *samAccountName,
                                const char *realm,
@@ -520,12 +491,10 @@ krb5_error_code smb_krb5_update_keytab(TALLOC_CTX *parent_ctx,
                return ENOENT;
        }
 
-       ret = krb5_kt_resolve(smb_krb5_context->krb5_context,
-                                       keytab_name, &keytab);
+       ret = krb5_kt_resolve(context, keytab_name, &keytab);
        if (ret) {
-               *error_string = smb_get_krb5_error_message(
-                                       smb_krb5_context->krb5_context,
-                                       ret, parent_ctx);
+               *error_string = smb_get_krb5_error_message(context,
+                                                          ret, parent_ctx);
                return ret;
        }
 
@@ -539,8 +508,7 @@ krb5_error_code smb_krb5_update_keytab(TALLOC_CTX *parent_ctx,
        /* Get the principal we will store the new keytab entries under */
        ret = principals_from_list(tmp_ctx,
                                  samAccountName, realm, SPNs, num_SPNs,
-                                 smb_krb5_context->krb5_context,
-                                 &principals, error_string);
+                                 context, &principals, error_string);
 
        if (ret != 0) {
                *error_string = talloc_asprintf(parent_ctx,
@@ -550,8 +518,7 @@ krb5_error_code smb_krb5_update_keytab(TALLOC_CTX *parent_ctx,
        }
 
        ret = remove_old_entries(tmp_ctx, kvno, principals, delete_all_kvno,
-                                smb_krb5_context->krb5_context,
-                                keytab, &found_previous, error_string);
+                                context, keytab, &found_previous, error_string);
        if (ret != 0) {
                *error_string = talloc_asprintf(parent_ctx,
                        "Failed to remove old principals from keytab: %s\n",
@@ -568,8 +535,7 @@ krb5_error_code smb_krb5_update_keytab(TALLOC_CTX *parent_ctx,
                                    samAccountName, realm, saltPrincipal,
                                    kvno, new_secret, old_secret,
                                    supp_enctypes, principals,
-                                   smb_krb5_context->krb5_context,
-                                   keytab,
+                                   context, keytab,
                                    found_previous ? false : true,
                                    error_string);
                if (ret) {
@@ -583,27 +549,26 @@ krb5_error_code smb_krb5_update_keytab(TALLOC_CTX *parent_ctx,
        }
 
 done:
-       keytab_principals_free(smb_krb5_context->krb5_context, principals);
+       keytab_principals_free(context, principals);
        if (ret != 0 || _keytab == NULL) {
-               krb5_kt_close(smb_krb5_context->krb5_context, keytab);
+               krb5_kt_close(context, keytab);
        }
        talloc_free(tmp_ctx);
        return ret;
 }
 
 krb5_error_code smb_krb5_create_memory_keytab(TALLOC_CTX *parent_ctx,
-                               struct cli_credentials *machine_account,
-                               struct smb_krb5_context *smb_krb5_context,
+                               krb5_context context,
+                               const char *new_secret,
+                               const char *samAccountName,
+                               const char *realm,
+                               int kvno,
                                krb5_keytab *keytab,
                                const char **keytab_name)
 {
        krb5_error_code ret;
        TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
        const char *rand_string;
-       const char *new_secret;
-       const char *samAccountName;
-       const char *realm;
-       int kvno;
        const char *error_string;
        if (!mem_ctx) {
                return ENOMEM;
@@ -621,12 +586,8 @@ krb5_error_code smb_krb5_create_memory_keytab(TALLOC_CTX *parent_ctx,
                return ENOMEM;
        }
 
-       new_secret = cli_credentials_get_password(machine_account);
-       samAccountName = cli_credentials_get_username(machine_account);
-       realm = cli_credentials_get_realm(machine_account);
-       kvno = cli_credentials_get_kvno(machine_account);
 
-       ret = smb_krb5_update_keytab(mem_ctx, smb_krb5_context,
+       ret = smb_krb5_update_keytab(mem_ctx, context,
                                     *keytab_name, samAccountName, realm,
                                     NULL, 0, NULL, new_secret, NULL,
                                     kvno, ENC_ALL_TYPES,