static krb5_error_code create_keytab(TALLOC_CTX *parent_ctx, const char *samAccountName, const char *realm, const char *saltPrincipal, int kvno, const char *new_secret, const char *old_secret, uint32_t supp_enctypes, krb5_principal *principals, krb5_context context, krb5_keytab keytab, bool add_old, const char **error_string) { krb5_error_code ret; krb5_principal salt_princ = NULL; krb5_enctype *enctypes; TALLOC_CTX *mem_ctx; if (!new_secret) { /* There is no password here, so nothing to do */ return 0; } mem_ctx = talloc_new(parent_ctx); if (!mem_ctx) { *error_string = talloc_strdup(parent_ctx, "unable to allocate tmp_ctx for create_keytab"); return ENOMEM; } /* 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); if (ret) { talloc_free(mem_ctx); return ret; } ret = ms_suptypes_to_ietf_enctypes(mem_ctx, supp_enctypes, &enctypes); if (ret) { *error_string = talloc_asprintf(parent_ctx, "create_keytab: generating list of " "encryption types failed (%s)\n", smb_get_krb5_error_message(context, ret, mem_ctx)); goto done; } ret = keytab_add_keys(mem_ctx, principals, salt_princ, kvno, new_secret, context, enctypes, keytab, error_string); if (ret) { talloc_steal(parent_ctx, *error_string); goto done; } if (old_secret && add_old && kvno != 0) { 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: krb5_free_principal(context, salt_princ); talloc_free(mem_ctx); return ret; }
static int create_keytab(TALLOC_CTX *parent_ctx, struct cli_credentials *machine_account, struct smb_krb5_context *smb_krb5_context, const char **enctype_strings, krb5_keytab keytab, BOOL add_old) { krb5_error_code ret; const char *password_s; const char *old_secret; int kvno; krb5_principal salt_princ; krb5_principal princ; const char *princ_string; TALLOC_CTX *mem_ctx = talloc_new(parent_ctx); if (!mem_ctx) { return ENOMEM; } princ_string = cli_credentials_get_principal(machine_account, mem_ctx); /* Get the principal we will store the new keytab entries under */ ret = principal_from_credentials(mem_ctx, machine_account, smb_krb5_context, &princ); if (ret) { DEBUG(1,("create_keytab: makeing krb5 principal failed (%s)\n", smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx))); talloc_free(mem_ctx); return ret; } /* The salt used to generate these entries may be different however, fetch that */ ret = salt_principal_from_credentials(mem_ctx, machine_account, smb_krb5_context, &salt_princ); if (ret) { DEBUG(1,("create_keytab: makeing salt principal failed (%s)\n", smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx))); talloc_free(mem_ctx); return ret; } /* Finally, do the dance to get the password to put in the entry */ password_s = cli_credentials_get_password(machine_account); if (!password_s) { krb5_keytab_entry entry; const struct samr_Password *mach_pwd; if (!str_list_check(enctype_strings, "arcfour-hmac-md5")) { DEBUG(1, ("Asked to create keytab, but with only an NT hash supplied, " "but not listing arcfour-hmac-md5 as an enc type to include in the keytab!\n")); talloc_free(mem_ctx); return EINVAL; } /* If we don't have the plaintext password, try for * the MD4 password hash */ mach_pwd = cli_credentials_get_nt_hash(machine_account, mem_ctx); if (!mach_pwd) { /* OK, nothing to do here */ talloc_free(mem_ctx); return 0; } ret = krb5_keyblock_init(smb_krb5_context->krb5_context, ETYPE_ARCFOUR_HMAC_MD5, mach_pwd->hash, sizeof(mach_pwd->hash), &entry.keyblock); if (ret) { DEBUG(1, ("create_keytab: krb5_keyblock_init failed: %s\n", smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx))); talloc_free(mem_ctx); return ret; } 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) { DEBUG(1, ("Failed to add ARCFOUR_HMAC (only) entry for %s to keytab: %s", cli_credentials_get_principal(machine_account, mem_ctx), smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx))); talloc_free(mem_ctx); krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &entry.keyblock); return ret; } DEBUG(5, ("Added %s(kvno %d) to keytab (arcfour-hmac-md5)\n", cli_credentials_get_principal(machine_account, mem_ctx), cli_credentials_get_kvno(machine_account))); krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &entry.keyblock); /* Can't go any further, we only have this one key */ talloc_free(mem_ctx); return 0; } kvno = cli_credentials_get_kvno(machine_account); /* good, we actually have the real plaintext */ ret = keytab_add_keys(mem_ctx, princ_string, princ, salt_princ, kvno, password_s, smb_krb5_context, enctype_strings, keytab); if (!ret) { talloc_free(mem_ctx); return ret; } if (!add_old || kvno == 0) { talloc_free(mem_ctx); return 0; } old_secret = cli_credentials_get_old_password(machine_account); if (!old_secret) { talloc_free(mem_ctx); return 0; } ret = keytab_add_keys(mem_ctx, princ_string, princ, salt_princ, kvno - 1, old_secret, smb_krb5_context, enctype_strings, keytab); if (!ret) { talloc_free(mem_ctx); return ret; } talloc_free(mem_ctx); return 0; }