1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-25 17:57:42 +03:00

CVE-2022-37966 s4:libnet: add support LIBNET_SET_PASSWORD_SAMR_HANDLE_18 to set nthash only

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15237

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Joseph Sutton <josephsutton@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
This commit is contained in:
Stefan Metzmacher 2022-03-24 14:09:50 +01:00
parent 9e69289b09
commit 271cd82cd6
2 changed files with 80 additions and 0 deletions

View File

@ -752,6 +752,66 @@ out:
return status;
}
static NTSTATUS libnet_SetPassword_samr_handle_18(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r)
{
NTSTATUS status;
struct samr_SetUserInfo2 sui;
union samr_UserInfo u_info;
struct samr_Password ntpwd;
DATA_BLOB ntpwd_in;
DATA_BLOB ntpwd_out;
DATA_BLOB session_key;
int rc;
if (r->samr_handle.in.info21) {
return NT_STATUS_INVALID_PARAMETER_MIX;
}
/* prepare samr_SetUserInfo2 level 18 (nt_hash) */
ZERO_STRUCT(u_info);
E_md4hash(r->samr_handle.in.newpassword, ntpwd.hash);
ntpwd_in = data_blob_const(ntpwd.hash, sizeof(ntpwd.hash));
ntpwd_out = data_blob_const(u_info.info18.nt_pwd.hash,
sizeof(u_info.info18.nt_pwd.hash));
u_info.info18.nt_pwd_active = 1;
u_info.info18.password_expired = 0;
status = dcerpc_fetch_session_key(r->samr_handle.in.dcerpc_pipe, &session_key);
if (!NT_STATUS_IS_OK(status)) {
r->samr_handle.out.error_string = talloc_asprintf(mem_ctx,
"dcerpc_fetch_session_key failed: %s",
nt_errstr(status));
return status;
}
rc = sess_crypt_blob(&ntpwd_out, &ntpwd_in,
&session_key, SAMBA_GNUTLS_ENCRYPT);
if (rc < 0) {
status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
goto out;
}
sui.in.user_handle = r->samr_handle.in.user_handle;
sui.in.info = &u_info;
sui.in.level = 18;
/* 9. try samr_SetUserInfo2 level 18 to set the password */
status = dcerpc_samr_SetUserInfo2_r(r->samr_handle.in.dcerpc_pipe->binding_handle, mem_ctx, &sui);
if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(sui.out.result)) {
status = sui.out.result;
}
if (!NT_STATUS_IS_OK(status)) {
r->samr_handle.out.error_string
= talloc_asprintf(mem_ctx,
"SetUserInfo2 level 18 for [%s] failed: %s",
r->samr_handle.in.account_name, nt_errstr(status));
}
out:
data_blob_clear(&session_key);
return status;
}
/*
* 1. try samr_SetUserInfo2 level 26 to set the password
* 2. try samr_SetUserInfo2 level 25 to set the password
@ -770,6 +830,11 @@ static NTSTATUS libnet_SetPassword_samr_handle(struct libnet_context *ctx, TALLO
};
unsigned int i;
if (r->samr_handle.samr_level != 0) {
r->generic.level = r->samr_handle.samr_level;
return libnet_SetPassword(ctx, mem_ctx, r);
}
for (i=0; i < ARRAY_SIZE(levels); i++) {
r->generic.level = levels[i];
status = libnet_SetPassword(ctx, mem_ctx, r);
@ -944,6 +1009,7 @@ static NTSTATUS libnet_SetPassword_samr(struct libnet_context *ctx, TALLOC_CTX *
ZERO_STRUCT(r2);
r2.samr_handle.level = LIBNET_SET_PASSWORD_SAMR_HANDLE;
r2.samr_handle.samr_level = r->samr.samr_level;
r2.samr_handle.in.account_name = r->samr.in.account_name;
r2.samr_handle.in.newpassword = r->samr.in.newpassword;
r2.samr_handle.in.user_handle = &u_handle;
@ -968,6 +1034,7 @@ static NTSTATUS libnet_SetPassword_generic(struct libnet_context *ctx, TALLOC_CT
ZERO_STRUCT(r2);
r2.samr.level = LIBNET_SET_PASSWORD_SAMR;
r2.samr.samr_level = r->generic.samr_level;
r2.samr.in.account_name = r->generic.in.account_name;
r2.samr.in.domain_name = r->generic.in.domain_name;
r2.samr.in.newpassword = r->generic.in.newpassword;
@ -1020,6 +1087,12 @@ NTSTATUS libnet_SetPassword(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, uni
}
status = libnet_SetPassword_samr_handle_23(ctx, mem_ctx, r);
break;
case LIBNET_SET_PASSWORD_SAMR_HANDLE_18:
if (encryption_state == SMB_ENCRYPTION_REQUIRED) {
GNUTLS_FIPS140_SET_LAX_MODE();
}
status = libnet_SetPassword_samr_handle_18(ctx, mem_ctx, r);
break;
case LIBNET_SET_PASSWORD_KRB5:
status = NT_STATUS_NOT_IMPLEMENTED;
break;

View File

@ -76,6 +76,7 @@ enum libnet_SetPassword_level {
LIBNET_SET_PASSWORD_SAMR_HANDLE_25,
LIBNET_SET_PASSWORD_SAMR_HANDLE_24,
LIBNET_SET_PASSWORD_SAMR_HANDLE_23,
LIBNET_SET_PASSWORD_SAMR_HANDLE_18,
LIBNET_SET_PASSWORD_KRB5,
LIBNET_SET_PASSWORD_LDAP,
LIBNET_SET_PASSWORD_RAP
@ -84,6 +85,7 @@ enum libnet_SetPassword_level {
union libnet_SetPassword {
struct {
enum libnet_SetPassword_level level;
enum libnet_SetPassword_level samr_level;
struct _libnet_SetPassword_in {
const char *account_name;
@ -98,6 +100,7 @@ union libnet_SetPassword {
struct {
enum libnet_SetPassword_level level;
enum libnet_SetPassword_level samr_level;
struct _libnet_SetPassword_samr_handle_in {
const char *account_name; /* for debug only */
struct policy_handle *user_handle;
@ -113,24 +116,28 @@ union libnet_SetPassword {
struct {
enum libnet_SetPassword_level level;
enum libnet_SetPassword_level samr_level;
struct _libnet_SetPassword_in in;
struct _libnet_SetPassword_out out;
} samr;
struct {
enum libnet_SetPassword_level level;
enum libnet_SetPassword_level samr_level;
struct _libnet_SetPassword_in in;
struct _libnet_SetPassword_out out;
} krb5;
struct {
enum libnet_SetPassword_level level;
enum libnet_SetPassword_level samr_level;
struct _libnet_SetPassword_in in;
struct _libnet_SetPassword_out out;
} ldap;
struct {
enum libnet_ChangePassword_level level;
enum libnet_SetPassword_level samr_level;
struct _libnet_SetPassword_in in;
struct _libnet_SetPassword_out out;
} rap;