mirror of
https://github.com/samba-team/samba.git
synced 2025-03-09 08:58:35 +03:00
s3:rpc_server: Implement dcesrv_samr_ChangePasswordUser4()
Signed-off-by: Andreas Schneider <asn@samba.org> Reviewed-by: Stefan Metzmacher <metze@samba.org>
This commit is contained in:
parent
68b7863f19
commit
1ca42e12ef
@ -54,6 +54,7 @@
|
||||
#include "passdb.h"
|
||||
#include "auth.h"
|
||||
#include "lib/util/sys_rw.h"
|
||||
#include "librpc/rpc/dcerpc_samr.h"
|
||||
|
||||
#include "lib/crypto/gnutls_helpers.h"
|
||||
#include <gnutls/gnutls.h>
|
||||
@ -1297,3 +1298,63 @@ NTSTATUS pass_oem_change(char *user, const char *rhost,
|
||||
|
||||
return nt_status;
|
||||
}
|
||||
|
||||
NTSTATUS samr_set_password_aes(TALLOC_CTX *mem_ctx,
|
||||
struct samu *sampass,
|
||||
const char *rhost,
|
||||
const DATA_BLOB *cdk,
|
||||
struct samr_EncryptedPasswordAES *pwbuf,
|
||||
enum samPwdChangeReason *reject_reason)
|
||||
{
|
||||
DATA_BLOB pw_data = data_blob_null;
|
||||
DATA_BLOB new_password = data_blob_null;
|
||||
const DATA_BLOB ciphertext =
|
||||
data_blob_const(pwbuf->cipher, pwbuf->cipher_len);
|
||||
DATA_BLOB iv = data_blob_const(pwbuf->salt, sizeof(pwbuf->salt));
|
||||
char *new_password_str = NULL;
|
||||
NTSTATUS status;
|
||||
bool ok;
|
||||
|
||||
status = samba_gnutls_aead_aes_256_cbc_hmac_sha512_decrypt(
|
||||
mem_ctx,
|
||||
&ciphertext,
|
||||
cdk,
|
||||
&samr_aes256_enc_key_salt,
|
||||
&samr_aes256_mac_key_salt,
|
||||
&iv,
|
||||
pwbuf->auth_data,
|
||||
&pw_data);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return NT_STATUS_WRONG_PASSWORD;
|
||||
}
|
||||
|
||||
ok = decode_pwd_string_from_buffer514(mem_ctx,
|
||||
pw_data.data,
|
||||
CH_UTF16,
|
||||
&new_password);
|
||||
TALLOC_FREE(pw_data.data);
|
||||
if (!ok) {
|
||||
DBG_NOTICE("samr: failed to decode password buffer\n");
|
||||
return NT_STATUS_WRONG_PASSWORD;
|
||||
}
|
||||
|
||||
new_password_str = talloc_strndup(mem_ctx,
|
||||
(char *)new_password.data,
|
||||
new_password.length);
|
||||
TALLOC_FREE(new_password.data);
|
||||
if (new_password_str == NULL) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
become_root();
|
||||
status = change_oem_password(sampass,
|
||||
rhost,
|
||||
NULL,
|
||||
new_password_str,
|
||||
true,
|
||||
reject_reason);
|
||||
unbecome_root();
|
||||
TALLOC_FREE(new_password_str);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -7677,8 +7677,115 @@ void _samr_Opnum72NotUsedOnWire(struct pipes_struct *p,
|
||||
NTSTATUS _samr_ChangePasswordUser4(struct pipes_struct *p,
|
||||
struct samr_ChangePasswordUser4 *r)
|
||||
{
|
||||
#ifdef HAVE_GNUTLS_PBKDF2
|
||||
TALLOC_CTX *frame = talloc_stackframe();
|
||||
struct dcesrv_call_state *dce_call = p->dce_call;
|
||||
struct dcesrv_connection *dcesrv_conn = dce_call->conn;
|
||||
const struct tsocket_address *remote_address =
|
||||
dcesrv_connection_get_remote_address(dcesrv_conn);
|
||||
enum samPwdChangeReason reject_reason;
|
||||
char *rhost = NULL;
|
||||
struct samu *sampass = NULL;
|
||||
char *username = NULL;
|
||||
uint32_t acct_ctrl = 0;
|
||||
const uint8_t *nt_pw = NULL;
|
||||
gnutls_datum_t nt_key;
|
||||
gnutls_datum_t salt = {
|
||||
.data = r->in.password->salt,
|
||||
.size = sizeof(r->in.password->salt),
|
||||
};
|
||||
uint8_t cdk_data[16] = {0};
|
||||
DATA_BLOB cdk = {
|
||||
.data = cdk_data,
|
||||
.length = sizeof(cdk_data),
|
||||
};
|
||||
NTSTATUS status = NT_STATUS_WRONG_PASSWORD;
|
||||
bool ok;
|
||||
int rc;
|
||||
|
||||
r->out.result = NT_STATUS_WRONG_PASSWORD;
|
||||
|
||||
DBG_NOTICE("_samr_ChangePasswordUser4\n");
|
||||
|
||||
if (r->in.account->string == NULL) {
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
if (r->in.password == NULL) {
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (r->in.password->PBKDF2Iterations < 5000 ||
|
||||
r->in.password->PBKDF2Iterations > 1000000) {
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
(void)map_username(frame, r->in.account->string, &username);
|
||||
if (username == NULL) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
rhost = tsocket_address_inet_addr_string(remote_address, frame);
|
||||
if (rhost == NULL) {
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto done;
|
||||
}
|
||||
sampass = samu_new(frame);
|
||||
if (sampass == NULL) {
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
become_root();
|
||||
ok = pdb_getsampwnam(sampass, username);
|
||||
unbecome_root();
|
||||
if (!ok) {
|
||||
status = NT_STATUS_NO_SUCH_USER;
|
||||
goto done;
|
||||
}
|
||||
|
||||
acct_ctrl = pdb_get_acct_ctrl(sampass);
|
||||
if (acct_ctrl & ACB_AUTOLOCK) {
|
||||
status = NT_STATUS_ACCOUNT_LOCKED_OUT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
nt_pw = pdb_get_nt_passwd(sampass);
|
||||
nt_key = (gnutls_datum_t){
|
||||
.data = discard_const_p(uint8_t, nt_pw),
|
||||
.size = NT_HASH_LEN,
|
||||
};
|
||||
|
||||
rc = gnutls_pbkdf2(GNUTLS_MAC_SHA512,
|
||||
&nt_key,
|
||||
&salt,
|
||||
r->in.password->PBKDF2Iterations,
|
||||
cdk.data,
|
||||
cdk.length);
|
||||
if (rc < 0) {
|
||||
BURN_DATA(cdk_data);
|
||||
status = NT_STATUS_WRONG_PASSWORD;
|
||||
goto done;
|
||||
}
|
||||
|
||||
status = samr_set_password_aes(frame,
|
||||
sampass,
|
||||
rhost,
|
||||
&cdk,
|
||||
r->in.password,
|
||||
&reject_reason);
|
||||
BURN_DATA(cdk_data);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
|
||||
return NT_STATUS_WRONG_PASSWORD;
|
||||
}
|
||||
|
||||
done:
|
||||
TALLOC_FREE(frame);
|
||||
|
||||
return status;
|
||||
#else /* HAVE_GNUTLS_PBKDF2 */
|
||||
p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
|
||||
return NT_STATUS_NOT_IMPLEMENTED;
|
||||
#endif /* HAVE_GNUTLS_PBKDF2 */
|
||||
}
|
||||
|
||||
/* include the generated boilerplate */
|
||||
|
@ -79,3 +79,9 @@ NTSTATUS check_password_complexity(const char *username,
|
||||
const char *fullname,
|
||||
const char *password,
|
||||
enum samPwdChangeReason *samr_reject_reason);
|
||||
NTSTATUS samr_set_password_aes(TALLOC_CTX *mem_ctx,
|
||||
struct samu *sampass,
|
||||
const char *rhost,
|
||||
const DATA_BLOB *cdk,
|
||||
struct samr_EncryptedPasswordAES *pwbuf,
|
||||
enum samPwdChangeReason *reject_reason);
|
||||
|
Loading…
x
Reference in New Issue
Block a user