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