]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s4:libnet: Add support for samr_ChangePasswordUser4()
authorAndreas Schneider <asn@samba.org>
Tue, 26 Jul 2022 13:43:31 +0000 (15:43 +0200)
committerAndreas Schneider <asn@cryptomilk.org>
Thu, 28 Jul 2022 11:51:29 +0000 (11:51 +0000)
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
source4/libnet/libnet_passwd.c
source4/libnet/wscript_build

index 027b15b2bc94b835eadc4026f250b9ca1b62adc0..4f662110e55986ca5e2f386b943d271da19ba95e 100644 (file)
 #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 <gnutls/gnutls.h>
 #include <gnutls/crypto.h>
 
+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,
index e097fddc228668b7d6747b217659692f6762781b..0ec06f294967e4273cfe60b8200274ee83dd25da 100644 (file)
@@ -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,