From 83dac5ce89f96704de1bbc4ae67dbba5298eca37 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Tue, 26 Jul 2022 15:43:31 +0200 Subject: [PATCH] s4:libnet: Add support for samr_ChangePasswordUser4() Signed-off-by: Andreas Schneider Reviewed-by: Stefan Metzmacher --- source4/libnet/libnet_passwd.c | 116 +++++++++++++++++++++++++++++++++ source4/libnet/wscript_build | 1 + 2 files changed, 117 insertions(+) diff --git a/source4/libnet/libnet_passwd.c b/source4/libnet/libnet_passwd.c index 027b15b2bc9..4f662110e55 100644 --- a/source4/libnet/libnet_passwd.c +++ b/source4/libnet/libnet_passwd.c @@ -25,11 +25,103 @@ #include "source4/librpc/rpc/dcerpc.h" #include "auth/credentials/credentials.h" #include "libcli/smb/smb_constants.h" +#include "librpc/rpc/dcerpc_samr.h" +#include "source3/rpc_client/init_samr.h" +#include "lib/param/loadparm.h" +#include "lib/param/param.h" #include "lib/crypto/gnutls_helpers.h" #include #include +static NTSTATUS libnet_ChangePassword_samr_aes(TALLOC_CTX *mem_ctx, + struct dcerpc_binding_handle *h, + struct lsa_String *server, + struct lsa_String *account, + const char *old_password, + const char *new_password, + const char **error_string) +{ +#ifdef HAVE_GNUTLS_PBKDF2 + struct samr_ChangePasswordUser4 r; + uint8_t old_nt_key_data[16] = {0}; + gnutls_datum_t old_nt_key = { + .data = old_nt_key_data, + .size = sizeof(old_nt_key_data), + }; + uint8_t cek_data[16] = {0}; + DATA_BLOB cek = { + .data = cek_data, + .length = sizeof(cek_data), + }; + struct samr_EncryptedPasswordAES pwd_buf = { + .cipher_len = 0 + }; + DATA_BLOB iv = { + .data = pwd_buf.salt, + .length = sizeof(pwd_buf.salt), + }; + gnutls_datum_t iv_datum = { + .data = iv.data, + .size = iv.length, + }; + uint64_t pbkdf2_iterations = generate_random_u64_range(5000, 1000000); + NTSTATUS status; + int rc; + + E_md4hash(old_password, old_nt_key_data); + + generate_nonce_buffer(iv.data, iv.length); + + rc = gnutls_pbkdf2(GNUTLS_MAC_SHA512, + &old_nt_key, + &iv_datum, + pbkdf2_iterations, + cek.data, + cek.length); + BURN_DATA(old_nt_key_data); + if (rc < 0) { + status = gnutls_error_to_ntstatus(rc, NT_STATUS_WRONG_PASSWORD); + } + + status = init_samr_CryptPasswordAES(mem_ctx, + new_password, + &cek, + &pwd_buf); + data_blob_clear(&cek); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + pwd_buf.PBKDF2Iterations = pbkdf2_iterations; + + r.in.server = server; + r.in.account = account; + r.in.password = &pwd_buf; + + status = dcerpc_samr_ChangePasswordUser4_r(h, mem_ctx, &r); + if (NT_STATUS_IS_OK(status)) { + goto done; + } + if (!NT_STATUS_IS_OK(r.out.result)) { + *error_string = talloc_asprintf(mem_ctx, + "samr_ChangePasswordUser4 for " + "'%s\\%s' failed: %s", + server->string, + account->string, + nt_errstr(status)); + status = r.out.result; + } + +done: + BURN_DATA(pwd_buf); + + return status; +#else /* HAVE_GNUTLS_PBKDF2 */ + return NT_STATUS_NOT_IMPLEMENTED; +#endif /* HAVE_GNUTLS_PBKDF2 */ +} + static NTSTATUS libnet_ChangePassword_samr_rc4(TALLOC_CTX *mem_ctx, struct dcerpc_binding_handle *h, struct lsa_String *server, @@ -323,6 +415,30 @@ static NTSTATUS libnet_ChangePassword_samr(struct libnet_context *ctx, TALLOC_CT server.string = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(c.out.dcerpc_pipe)); account.string = r->samr.in.account_name; + status = libnet_ChangePassword_samr_aes( + mem_ctx, + c.out.dcerpc_pipe->binding_handle, + &server, + &account, + r->samr.in.oldpassword, + r->samr.in.newpassword, + &(r->samr.out.error_string)); + if (!NT_STATUS_IS_OK(status)) { + if (NT_STATUS_EQUAL(status, + NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE) || + NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED) || + NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) { + /* + * Don't fallback to RC4 based SAMR if weak crypto is not + * allowed. + */ + if (lpcfg_weak_crypto(ctx->lp_ctx) == + SAMBA_WEAK_CRYPTO_DISALLOWED) { + goto disconnect; + } + } + } + status = libnet_ChangePassword_samr_rc4( mem_ctx, c.out.dcerpc_pipe->binding_handle, diff --git a/source4/libnet/wscript_build b/source4/libnet/wscript_build index e097fddc228..0ec06f29496 100644 --- a/source4/libnet/wscript_build +++ b/source4/libnet/wscript_build @@ -8,6 +8,7 @@ auto_proto='libnet_proto.h' bld.SAMBA_LIBRARY(name, source='libnet.c libnet_passwd.c libnet_time.c libnet_rpc.c libnet_join.c libnet_site.c libnet_become_dc.c libnet_unbecome_dc.c libnet_vampire.c libnet_user.c libnet_group.c libnet_share.c libnet_lookup.c libnet_domain.c userinfo.c groupinfo.c userman.c groupman.c prereq_domain.c', autoproto=auto_proto, + deps='INIT_SAMR', public_deps='samba-credentials dcerpc dcerpc-samr RPC_NDR_LSA RPC_NDR_SRVSVC RPC_NDR_DRSUAPI cli_composite LIBCLI_RESOLVE LIBCLI_FINDDCS cli_cldap LIBCLI_FINDDCS gensec_schannel LIBCLI_AUTH ndr smbpasswdparser %s LIBCLI_SAMSYNC LIBTSOCKET GNUTLS_HELPERS' % (provision), private_library=True, pyembed=True, -- 2.47.3