summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
authorAndreas Schneider <asn@samba.org>2022-07-26 15:13:08 +0200
committerAndreas Schneider <asn@cryptomilk.org>2022-07-28 11:51:29 +0000
commit0c961b16f1913fd4b16ad7b7a4b2da2f83fe349c (patch)
tree4d39bc96666233b69348084d7181a082d33fdc26 /source4
parentda0e0c8aeb2426ff017e890593a0f7e65cba6b03 (diff)
downloadsamba-0c961b16f1913fd4b16ad7b7a4b2da2f83fe349c.tar.gz
s4:libnet: Move code using RC4 into its own function
Signed-off-by: Andreas Schneider <asn@samba.org> Reviewed-by: Stefan Metzmacher <metze@samba.org>
Diffstat (limited to 'source4')
-rw-r--r--source4/libnet/libnet_passwd.c209
1 files changed, 123 insertions, 86 deletions
diff --git a/source4/libnet/libnet_passwd.c b/source4/libnet/libnet_passwd.c
index 4990f69bc49..027b15b2bc9 100644
--- a/source4/libnet/libnet_passwd.c
+++ b/source4/libnet/libnet_passwd.c
@@ -30,28 +30,22 @@
#include <gnutls/gnutls.h>
#include <gnutls/crypto.h>
-/*
- * do a password change using DCERPC/SAMR calls
- * 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation)
- * 2. try samr_ChangePasswordUser3
- * 3. try samr_ChangePasswordUser2
- * 4. try samr_OemChangePasswordUser2
- */
-static NTSTATUS libnet_ChangePassword_samr(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_ChangePassword *r)
+static NTSTATUS libnet_ChangePassword_samr_rc4(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)
{
- NTSTATUS status;
- struct libnet_RpcConnect c;
struct samr_OemChangePasswordUser2 oe2;
struct samr_ChangePasswordUser2 pw2;
struct samr_ChangePasswordUser3 pw3;
- struct lsa_String server, account;
- struct lsa_AsciiString a_server, a_account;
struct samr_CryptPassword nt_pass, lm_pass;
- struct samr_Password nt_verifier, lm_verifier;
uint8_t old_nt_hash[16], new_nt_hash[16];
uint8_t old_lm_hash[16], new_lm_hash[16];
- struct samr_DomInfo1 *dominfo = NULL;
- struct userPwdChangeFailureInformation *reject = NULL;
+ struct samr_Password nt_verifier, lm_verifier;
+ struct lsa_AsciiString a_server, a_account;
gnutls_cipher_hd_t cipher_hnd = NULL;
gnutls_datum_t nt_session_key = {
.data = old_nt_hash,
@@ -61,37 +55,19 @@ static NTSTATUS libnet_ChangePassword_samr(struct libnet_context *ctx, TALLOC_CT
.data = old_lm_hash,
.size = sizeof(old_lm_hash),
};
+ struct samr_DomInfo1 *dominfo = NULL;
+ struct userPwdChangeFailureInformation *reject = NULL;
+ NTSTATUS status;
int rc;
- ZERO_STRUCT(c);
+ E_md4hash(old_password, old_nt_hash);
+ E_md4hash(new_password, new_nt_hash);
- /* prepare connect to the SAMR pipe of the users domain PDC */
- c.level = LIBNET_RPC_CONNECT_PDC;
- c.in.name = r->samr.in.domain_name;
- c.in.dcerpc_iface = &ndr_table_samr;
- c.in.dcerpc_flags = DCERPC_ANON_FALLBACK;
-
- /* 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation) */
- status = libnet_RpcConnect(ctx, mem_ctx, &c);
- if (!NT_STATUS_IS_OK(status)) {
- r->samr.out.error_string = talloc_asprintf(mem_ctx,
- "Connection to SAMR pipe of PDC of domain '%s' failed: %s",
- r->samr.in.domain_name, nt_errstr(status));
- return status;
- }
-
- /* prepare password change for account */
- server.string = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(c.out.dcerpc_pipe));
- account.string = r->samr.in.account_name;
-
- E_md4hash(r->samr.in.oldpassword, old_nt_hash);
- E_md4hash(r->samr.in.newpassword, new_nt_hash);
-
- E_deshash(r->samr.in.oldpassword, old_lm_hash);
- E_deshash(r->samr.in.newpassword, new_lm_hash);
+ E_deshash(old_password, old_lm_hash);
+ E_deshash(new_password, new_lm_hash);
/* prepare samr_ChangePasswordUser3 */
- encode_pw_buffer(lm_pass.data, r->samr.in.newpassword, STR_UNICODE);
+ encode_pw_buffer(lm_pass.data, new_password, STR_UNICODE);
rc = gnutls_cipher_init(&cipher_hnd,
GNUTLS_CIPHER_ARCFOUR_128,
@@ -99,7 +75,7 @@ static NTSTATUS libnet_ChangePassword_samr(struct libnet_context *ctx, TALLOC_CT
NULL);
if (rc < 0) {
status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
- goto disconnect;
+ goto done;
}
rc = gnutls_cipher_encrypt(cipher_hnd,
@@ -108,16 +84,16 @@ static NTSTATUS libnet_ChangePassword_samr(struct libnet_context *ctx, TALLOC_CT
gnutls_cipher_deinit(cipher_hnd);
if (rc < 0) {
status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
- goto disconnect;
+ goto done;
}
rc = E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
if (rc != 0) {
status = gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
- goto disconnect;
+ goto done;
}
- encode_pw_buffer(nt_pass.data, r->samr.in.newpassword, STR_UNICODE);
+ encode_pw_buffer(nt_pass.data, new_password, STR_UNICODE);
rc = gnutls_cipher_init(&cipher_hnd,
GNUTLS_CIPHER_ARCFOUR_128,
@@ -125,7 +101,7 @@ static NTSTATUS libnet_ChangePassword_samr(struct libnet_context *ctx, TALLOC_CT
NULL);
if (rc < 0) {
status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
- goto disconnect;
+ goto done;
}
rc = gnutls_cipher_encrypt(cipher_hnd,
@@ -134,17 +110,17 @@ static NTSTATUS libnet_ChangePassword_samr(struct libnet_context *ctx, TALLOC_CT
gnutls_cipher_deinit(cipher_hnd);
if (rc < 0) {
status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
- goto disconnect;
+ goto done;
}
rc = E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
if (rc != 0) {
status = gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
- goto disconnect;
+ goto done;
}
- pw3.in.server = &server;
- pw3.in.account = &account;
+ pw3.in.server = server;
+ pw3.in.account = account;
pw3.in.nt_password = &nt_pass;
pw3.in.nt_verifier = &nt_verifier;
pw3.in.lm_change = 1;
@@ -155,25 +131,29 @@ static NTSTATUS libnet_ChangePassword_samr(struct libnet_context *ctx, TALLOC_CT
pw3.out.reject = &reject;
/* 2. try samr_ChangePasswordUser3 */
- status = dcerpc_samr_ChangePasswordUser3_r(c.out.dcerpc_pipe->binding_handle, mem_ctx, &pw3);
+ status = dcerpc_samr_ChangePasswordUser3_r(h, mem_ctx, &pw3);
if (!NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(pw3.out.result)) {
status = pw3.out.result;
}
if (!NT_STATUS_IS_OK(status)) {
- r->samr.out.error_string = talloc_asprintf(mem_ctx,
- "samr_ChangePasswordUser3 failed: %s",
- nt_errstr(status));
- r->samr.out.error_string = talloc_asprintf(mem_ctx,
- "samr_ChangePasswordUser3 for '%s\\%s' failed: %s",
- r->samr.in.domain_name, r->samr.in.account_name,
- nt_errstr(status));
+ *error_string = talloc_asprintf(
+ mem_ctx,
+ "samr_ChangePasswordUser3 failed: %s",
+ nt_errstr(status));
+ *error_string =
+ talloc_asprintf(mem_ctx,
+ "samr_ChangePasswordUser3 for "
+ "'%s\\%s' failed: %s",
+ server->string,
+ account->string,
+ nt_errstr(status));
}
- goto disconnect;
+ goto done;
}
/* prepare samr_ChangePasswordUser2 */
- encode_pw_buffer(lm_pass.data, r->samr.in.newpassword, STR_ASCII|STR_TERMINATE);
+ encode_pw_buffer(lm_pass.data, new_password, STR_ASCII | STR_TERMINATE);
rc = gnutls_cipher_init(&cipher_hnd,
GNUTLS_CIPHER_ARCFOUR_128,
@@ -181,7 +161,7 @@ static NTSTATUS libnet_ChangePassword_samr(struct libnet_context *ctx, TALLOC_CT
NULL);
if (rc < 0) {
status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
- goto disconnect;
+ goto done;
}
rc = gnutls_cipher_encrypt(cipher_hnd,
@@ -190,16 +170,16 @@ static NTSTATUS libnet_ChangePassword_samr(struct libnet_context *ctx, TALLOC_CT
gnutls_cipher_deinit(cipher_hnd);
if (rc < 0) {
status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
- goto disconnect;
+ goto done;
}
rc = E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
if (rc != 0) {
status = gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
- goto disconnect;
+ goto done;
}
- encode_pw_buffer(nt_pass.data, r->samr.in.newpassword, STR_UNICODE);
+ encode_pw_buffer(nt_pass.data, new_password, STR_UNICODE);
rc = gnutls_cipher_init(&cipher_hnd,
GNUTLS_CIPHER_ARCFOUR_128,
@@ -207,7 +187,7 @@ static NTSTATUS libnet_ChangePassword_samr(struct libnet_context *ctx, TALLOC_CT
NULL);
if (rc < 0) {
status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
- goto disconnect;
+ goto done;
}
rc = gnutls_cipher_encrypt(cipher_hnd,
nt_pass.data,
@@ -215,17 +195,17 @@ static NTSTATUS libnet_ChangePassword_samr(struct libnet_context *ctx, TALLOC_CT
gnutls_cipher_deinit(cipher_hnd);
if (rc < 0) {
status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
- goto disconnect;
+ goto done;
}
rc = E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
if (rc != 0) {
status = gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
- goto disconnect;
+ goto done;
}
- pw2.in.server = &server;
- pw2.in.account = &account;
+ pw2.in.server = server;
+ pw2.in.account = account;
pw2.in.nt_password = &nt_pass;
pw2.in.nt_verifier = &nt_verifier;
pw2.in.lm_change = 1;
@@ -233,26 +213,29 @@ static NTSTATUS libnet_ChangePassword_samr(struct libnet_context *ctx, TALLOC_CT
pw2.in.lm_verifier = &lm_verifier;
/* 3. try samr_ChangePasswordUser2 */
- status = dcerpc_samr_ChangePasswordUser2_r(c.out.dcerpc_pipe->binding_handle, mem_ctx, &pw2);
+ status = dcerpc_samr_ChangePasswordUser2_r(h, mem_ctx, &pw2);
if (!NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(pw2.out.result)) {
status = pw2.out.result;
}
if (!NT_STATUS_IS_OK(status)) {
- r->samr.out.error_string = talloc_asprintf(mem_ctx,
- "samr_ChangePasswordUser2 for '%s\\%s' failed: %s",
- r->samr.in.domain_name, r->samr.in.account_name,
- nt_errstr(status));
+ *error_string =
+ talloc_asprintf(mem_ctx,
+ "samr_ChangePasswordUser2 for "
+ "'%s\\%s' failed: %s",
+ server->string,
+ account->string,
+ nt_errstr(status));
}
- goto disconnect;
+ goto done;
}
/* prepare samr_OemChangePasswordUser2 */
- a_server.string = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(c.out.dcerpc_pipe));
- a_account.string = r->samr.in.account_name;
+ a_server.string = server->string;
+ a_account.string = account->string;
- encode_pw_buffer(lm_pass.data, r->samr.in.newpassword, STR_ASCII);
+ encode_pw_buffer(lm_pass.data, new_password, STR_ASCII);
rc = gnutls_cipher_init(&cipher_hnd,
GNUTLS_CIPHER_ARCFOUR_128,
@@ -260,7 +243,7 @@ static NTSTATUS libnet_ChangePassword_samr(struct libnet_context *ctx, TALLOC_CT
NULL);
if (rc < 0) {
status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
- goto disconnect;
+ goto done;
}
rc = gnutls_cipher_encrypt(cipher_hnd,
@@ -269,13 +252,13 @@ static NTSTATUS libnet_ChangePassword_samr(struct libnet_context *ctx, TALLOC_CT
gnutls_cipher_deinit(cipher_hnd);
if (rc < 0) {
status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
- goto disconnect;
+ goto done;
}
rc = E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
if (rc != 0) {
status = gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
- goto disconnect;
+ goto done;
}
oe2.in.server = &a_server;
@@ -284,17 +267,71 @@ static NTSTATUS libnet_ChangePassword_samr(struct libnet_context *ctx, TALLOC_CT
oe2.in.hash = &lm_verifier;
/* 4. try samr_OemChangePasswordUser2 */
- status = dcerpc_samr_OemChangePasswordUser2_r(c.out.dcerpc_pipe->binding_handle, mem_ctx, &oe2);
+ status = dcerpc_samr_OemChangePasswordUser2_r(h, mem_ctx, &oe2);
if (!NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(oe2.out.result)) {
status = oe2.out.result;
}
if (!NT_STATUS_IS_OK(oe2.out.result)) {
- r->samr.out.error_string = talloc_asprintf(mem_ctx,
- "samr_OemChangePasswordUser2 for '%s\\%s' failed: %s",
- r->samr.in.domain_name, r->samr.in.account_name,
- nt_errstr(status));
+ *error_string =
+ talloc_asprintf(mem_ctx,
+ "samr_OemChangePasswordUser2 "
+ "for '%s\\%s' failed: %s",
+ server->string,
+ account->string,
+ nt_errstr(status));
}
+ goto done;
+ }
+
+ status = NT_STATUS_OK;
+done:
+ return status;
+}
+
+/*
+ * do a password change using DCERPC/SAMR calls
+ * 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation)
+ * 2. try samr_ChangePasswordUser3
+ * 3. try samr_ChangePasswordUser2
+ * 4. try samr_OemChangePasswordUser2
+ */
+static NTSTATUS libnet_ChangePassword_samr(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_ChangePassword *r)
+{
+ NTSTATUS status;
+ struct libnet_RpcConnect c;
+ struct lsa_String server, account;
+
+ ZERO_STRUCT(c);
+
+ /* prepare connect to the SAMR pipe of the users domain PDC */
+ c.level = LIBNET_RPC_CONNECT_PDC;
+ c.in.name = r->samr.in.domain_name;
+ c.in.dcerpc_iface = &ndr_table_samr;
+ c.in.dcerpc_flags = DCERPC_ANON_FALLBACK;
+
+ /* 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation) */
+ status = libnet_RpcConnect(ctx, mem_ctx, &c);
+ if (!NT_STATUS_IS_OK(status)) {
+ r->samr.out.error_string = talloc_asprintf(mem_ctx,
+ "Connection to SAMR pipe of PDC of domain '%s' failed: %s",
+ r->samr.in.domain_name, nt_errstr(status));
+ return status;
+ }
+
+ /* prepare password change for account */
+ 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_rc4(
+ 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)) {
goto disconnect;
}