1524bc
From 23f422c0df67c0f9e701e0deb5f1708a930a98bd Mon Sep 17 00:00:00 2001
1524bc
From: Andreas Schneider <asn@samba.org>
1524bc
Date: Tue, 19 Feb 2019 17:40:29 +0100
1524bc
Subject: [PATCH 037/187] s4:rpc_server: Use GnuTLS RC4 for samr password
1524bc
1524bc
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14031
1524bc
1524bc
Signed-off-by: Andreas Schneider <asn@samba.org>
1524bc
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
1524bc
(cherry picked from commit 4326e7de6ba0ce02ab23af7297d2f7242988daa4)
1524bc
---
1524bc
 source4/rpc_server/samr/samr_password.c | 105 ++++++++++++++++++++----
1524bc
 1 file changed, 89 insertions(+), 16 deletions(-)
1524bc
1524bc
diff --git a/source4/rpc_server/samr/samr_password.c b/source4/rpc_server/samr/samr_password.c
1524bc
index fde0de2c3cc..b04e37f06f3 100644
1524bc
--- a/source4/rpc_server/samr/samr_password.c
1524bc
+++ b/source4/rpc_server/samr/samr_password.c
1524bc
@@ -24,7 +24,7 @@
1524bc
 #include "rpc_server/dcerpc_server.h"
1524bc
 #include "rpc_server/samr/dcesrv_samr.h"
1524bc
 #include "system/time.h"
1524bc
-#include "../lib/crypto/crypto.h"
1524bc
+#include "lib/crypto/md4.h"
1524bc
 #include "dsdb/samdb/samdb.h"
1524bc
 #include "auth/auth.h"
1524bc
 #include "libcli/auth/libcli_auth.h"
1524bc
@@ -119,13 +119,15 @@ NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call,
1524bc
 				       "samAccountName",
1524bc
 				       NULL };
1524bc
 	struct samr_Password *lm_pwd;
1524bc
-	DATA_BLOB lm_pwd_blob;
1524bc
 	uint8_t new_lm_hash[16];
1524bc
 	struct samr_Password lm_verifier;
1524bc
 	size_t unicode_pw_len;
1524bc
 	size_t converted_size = 0;
1524bc
 	const char *user_samAccountName = NULL;
1524bc
 	struct dom_sid *user_objectSid = NULL;
1524bc
+	gnutls_cipher_hd_t cipher_hnd = NULL;
1524bc
+	gnutls_datum_t lm_session_key;
1524bc
+	int rc;
1524bc
 
1524bc
 	if (pwbuf == NULL) {
1524bc
 		return NT_STATUS_INVALID_PARAMETER;
1524bc
@@ -179,9 +181,28 @@ NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call,
1524bc
 	}
1524bc
 
1524bc
 	/* decrypt the password we have been given */
1524bc
-	lm_pwd_blob = data_blob(lm_pwd->hash, sizeof(lm_pwd->hash));
1524bc
-	arcfour_crypt_blob(pwbuf->data, 516, &lm_pwd_blob);
1524bc
-	data_blob_free(&lm_pwd_blob);
1524bc
+	lm_session_key = (gnutls_datum_t) {
1524bc
+		.data = lm_pwd->hash,
1524bc
+		.size = sizeof(lm_pwd->hash),
1524bc
+	};
1524bc
+
1524bc
+	rc = gnutls_cipher_init(&cipher_hnd,
1524bc
+				GNUTLS_CIPHER_ARCFOUR_128,
1524bc
+				&lm_session_key,
1524bc
+				NULL);
1524bc
+	if (rc < 0) {
1524bc
+		status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
1524bc
+		goto failed;
1524bc
+	}
1524bc
+
1524bc
+	rc = gnutls_cipher_decrypt(cipher_hnd,
1524bc
+				   pwbuf->data,
1524bc
+				   516);
1524bc
+	gnutls_cipher_deinit(cipher_hnd);
1524bc
+	if (rc < 0) {
1524bc
+		status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
1524bc
+		goto failed;
1524bc
+	}
1524bc
 
1524bc
 	if (!extract_pw_from_buffer(mem_ctx, pwbuf->data, &new_password)) {
1524bc
 		DEBUG(3,("samr: failed to decode password buffer\n"));
1524bc
@@ -315,7 +336,6 @@ NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call,
1524bc
 				       "badPwdCount", "badPasswordTime",
1524bc
 				       "objectSid", NULL };
1524bc
 	struct samr_Password *nt_pwd, *lm_pwd;
1524bc
-	DATA_BLOB nt_pwd_blob;
1524bc
 	struct samr_DomInfo1 *dominfo = NULL;
1524bc
 	struct userPwdChangeFailureInformation *reject = NULL;
1524bc
 	enum samPwdChangeReason reason = SAM_PWD_CHANGE_NO_ERROR;
1524bc
@@ -325,6 +345,9 @@ NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call,
1524bc
 	struct dom_sid *user_objectSid = NULL;
1524bc
 	enum ntlm_auth_level ntlm_auth_level
1524bc
 		= lpcfg_ntlm_auth(dce_call->conn->dce_ctx->lp_ctx);
1524bc
+	gnutls_cipher_hd_t cipher_hnd = NULL;
1524bc
+	gnutls_datum_t nt_session_key;
1524bc
+	int rc;
1524bc
 
1524bc
 	*r->out.dominfo = NULL;
1524bc
 	*r->out.reject = NULL;
1524bc
@@ -381,9 +404,28 @@ NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call,
1524bc
 	}
1524bc
 
1524bc
 	/* decrypt the password we have been given */
1524bc
-	nt_pwd_blob = data_blob(nt_pwd->hash, sizeof(nt_pwd->hash));
1524bc
-	arcfour_crypt_blob(r->in.nt_password->data, 516, &nt_pwd_blob);
1524bc
-	data_blob_free(&nt_pwd_blob);
1524bc
+	nt_session_key = (gnutls_datum_t) {
1524bc
+		.data = nt_pwd->hash,
1524bc
+		.size = sizeof(nt_pwd->hash),
1524bc
+	};
1524bc
+
1524bc
+	rc = gnutls_cipher_init(&cipher_hnd,
1524bc
+				GNUTLS_CIPHER_ARCFOUR_128,
1524bc
+				&nt_session_key,
1524bc
+				NULL);
1524bc
+	if (rc < 0) {
1524bc
+		status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
1524bc
+		goto failed;
1524bc
+	}
1524bc
+
1524bc
+	rc = gnutls_cipher_decrypt(cipher_hnd,
1524bc
+				   r->in.nt_password->data,
1524bc
+				   516);
1524bc
+	gnutls_cipher_deinit(cipher_hnd);
1524bc
+	if (rc < 0) {
1524bc
+		status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
1524bc
+		goto failed;
1524bc
+	}
1524bc
 
1524bc
 	if (!extract_pw_from_buffer(mem_ctx, r->in.nt_password->data, &new_password)) {
1524bc
 		DEBUG(3,("samr: failed to decode password buffer\n"));
1524bc
@@ -547,6 +589,9 @@ NTSTATUS samr_set_password(struct dcesrv_call_state *dce_call,
1524bc
 	NTSTATUS nt_status;
1524bc
 	DATA_BLOB new_password;
1524bc
 	DATA_BLOB session_key = data_blob(NULL, 0);
1524bc
+	gnutls_cipher_hd_t cipher_hnd = NULL;
1524bc
+	gnutls_datum_t _session_key;
1524bc
+	int rc;
1524bc
 
1524bc
 	nt_status = dcesrv_transport_session_key(dce_call, &session_key);
1524bc
 	if (!NT_STATUS_IS_OK(nt_status)) {
1524bc
@@ -556,7 +601,28 @@ NTSTATUS samr_set_password(struct dcesrv_call_state *dce_call,
1524bc
 		return NT_STATUS_WRONG_PASSWORD;
1524bc
 	}
1524bc
 
1524bc
-	arcfour_crypt_blob(pwbuf->data, 516, &session_key);
1524bc
+	_session_key = (gnutls_datum_t) {
1524bc
+		.data = session_key.data,
1524bc
+		.size = session_key.length,
1524bc
+	};
1524bc
+
1524bc
+	rc = gnutls_cipher_init(&cipher_hnd,
1524bc
+				GNUTLS_CIPHER_ARCFOUR_128,
1524bc
+				&_session_key,
1524bc
+				NULL);
1524bc
+	if (rc < 0) {
1524bc
+		nt_status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
1524bc
+		goto out;
1524bc
+	}
1524bc
+
1524bc
+	rc = gnutls_cipher_decrypt(cipher_hnd,
1524bc
+				   pwbuf->data,
1524bc
+				   516);
1524bc
+	gnutls_cipher_deinit(cipher_hnd);
1524bc
+	if (rc < 0) {
1524bc
+		nt_status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
1524bc
+		goto out;
1524bc
+	}
1524bc
 
1524bc
 	if (!extract_pw_from_buffer(mem_ctx, pwbuf->data, &new_password)) {
1524bc
 		DEBUG(3,("samr: failed to decode password buffer\n"));
1524bc
@@ -565,12 +631,19 @@ NTSTATUS samr_set_password(struct dcesrv_call_state *dce_call,
1524bc
 
1524bc
 	/* set the password - samdb needs to know both the domain and user DNs,
1524bc
 	   so the domain password policy can be used */
1524bc
-	return samdb_set_password(sam_ctx, mem_ctx,
1524bc
-				  account_dn, domain_dn,
1524bc
-				  &new_password,
1524bc
-				  NULL, NULL,
1524bc
-				  NULL, NULL, /* This is a password set, not change */
1524bc
-				  NULL, NULL);
1524bc
+	nt_status = samdb_set_password(sam_ctx,
1524bc
+				       mem_ctx,
1524bc
+				       account_dn,
1524bc
+				       domain_dn,
1524bc
+				       &new_password,
1524bc
+				       NULL,
1524bc
+				       NULL,
1524bc
+				       NULL,
1524bc
+				       NULL, /* This is a password set, not change */
1524bc
+				       NULL,
1524bc
+				       NULL);
1524bc
+out:
1524bc
+	return nt_status;
1524bc
 }
1524bc
 
1524bc
 
1524bc
-- 
1524bc
2.23.0
1524bc