summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/libcli/util/smbdes.c30
-rw-r--r--source4/libcli/util/smbencrypt.c21
-rw-r--r--source4/librpc/idl/samr.idl20
-rw-r--r--source4/torture/rpc/autoidl.c2
-rw-r--r--source4/torture/rpc/samr.c120
5 files changed, 157 insertions, 36 deletions
diff --git a/source4/libcli/util/smbdes.c b/source4/libcli/util/smbdes.c
index d282b0135a..80b938b460 100644
--- a/source4/libcli/util/smbdes.c
+++ b/source4/libcli/util/smbdes.c
@@ -357,7 +357,8 @@ void cred_hash3(unsigned char *out, unsigned char *in, const unsigned char *key,
smbhash(out + 8, in + 8, key2, forw);
}
-void SamOEMhash( unsigned char *data, const unsigned char *key, int val)
+
+void SamOEMhashBlob(unsigned char *data, int len, const DATA_BLOB *key)
{
unsigned char s_box[256];
unsigned char index_i = 0;
@@ -369,23 +370,22 @@ void SamOEMhash( unsigned char *data, const unsigned char *key, int val)
s_box[ind] = (unsigned char)ind;
}
- for( ind = 0; ind < 256; ind++) {
+ for (ind = 0; ind < 256; ind++) {
unsigned char tc;
-
- j += (s_box[ind] + key[ind%16]);
-
+
+ j += (s_box[ind] + key->data[ind%key->length]);
+
tc = s_box[ind];
s_box[ind] = s_box[j];
s_box[j] = tc;
}
-
- for (ind = 0; ind < val; ind++){
+ for (ind = 0; ind < len; ind++) {
unsigned char tc;
unsigned char t;
index_i++;
index_j += s_box[index_i];
-
+
tc = s_box[index_i];
s_box[index_i] = s_box[index_j];
s_box[index_j] = tc;
@@ -395,6 +395,20 @@ void SamOEMhash( unsigned char *data, const unsigned char *key, int val)
}
}
+/*
+ a varient that assumes a 16 byte key. This should be removed
+ when the last user is gone
+*/
+void SamOEMhash(unsigned char *data, const unsigned char keystr[16], int len)
+{
+ DATA_BLOB key;
+
+ key.length = 16;
+ key.data = keystr;
+
+ SamOEMhashBlob(data, len, &key);
+}
+
/* Decode a sam password hash into a password. The password hash is the
same method used to store passwords in the NT registry. The DES key
diff --git a/source4/libcli/util/smbencrypt.c b/source4/libcli/util/smbencrypt.c
index 13d56e1e78..a1c026a27d 100644
--- a/source4/libcli/util/smbencrypt.c
+++ b/source4/libcli/util/smbencrypt.c
@@ -460,21 +460,28 @@ BOOL SMBNTLMv2encrypt(const char *user, const char *domain, const char *password
}
/***********************************************************
- encode a password buffer. The caller gets to figure out
- what to put in it.
+ encode a password buffer with a unicode password. The buffer
+ is filled with random data to make it harder to attack.
************************************************************/
-BOOL encode_pw_buffer(char buffer[516], char *new_pw, int new_pw_length)
+BOOL encode_pw_buffer(char buffer[516], const char *password, int string_flags)
{
- generate_random_buffer((unsigned char *)buffer, 516, True);
+ uchar new_pw[512];
+ size_t new_pw_len;
- memcpy(&buffer[512 - new_pw_length], new_pw, new_pw_length);
+ new_pw_len = push_string(NULL, new_pw,
+ password,
+ sizeof(new_pw), string_flags);
+
+ memcpy(&buffer[512 - new_pw_len], new_pw, new_pw_len);
+
+ generate_random_buffer((unsigned char *)buffer, 512 - new_pw_len, True);
/*
* The length of the new password is in the last 4 bytes of
* the data buffer.
*/
- SIVAL(buffer, 512, new_pw_length);
-
+ SIVAL(buffer, 512, new_pw_len);
+ ZERO_STRUCT(new_pw);
return True;
}
diff --git a/source4/librpc/idl/samr.idl b/source4/librpc/idl/samr.idl
index 3639c21cd3..b76541bb26 100644
--- a/source4/librpc/idl/samr.idl
+++ b/source4/librpc/idl/samr.idl
@@ -641,6 +641,15 @@
uint8 unknown4;
} samr_UserInfo21;
+ typedef [flag(NDR_PAHEX)] struct {
+ uint8 data[516];
+ } samr_CryptPassword;
+
+ typedef struct {
+ samr_CryptPassword password;
+ uint16 pw_len;
+ } samr_UserInfo24;
+
typedef union {
[case(1)] samr_UserInfo1 info1;
[case(2)] samr_UserInfo2 info2;
@@ -660,6 +669,7 @@
[case(17)] samr_UserInfo17 info17;
[case(20)] samr_UserInfo20 info20;
[case(21)] samr_UserInfo21 info21;
+ [case(24)] samr_UserInfo24 info24;
} samr_UserInfo;
NTSTATUS samr_QueryUserInfo(
@@ -962,10 +972,6 @@
/************************/
/* Function 0x36 */
- typedef [flag(NDR_PAHEX)] struct {
- uint8 data[516];
- } samr_CryptPassword;
-
NTSTATUS samr_OemChangePasswordUser2(
[in] samr_AsciiName *server,
[in,ref] samr_AsciiName *account,
@@ -1044,7 +1050,11 @@
/************************/
/* Function 0x41 */
- NTSTATUS samr_RID_TO_SID();
+ NTSTATUS samr_RidToSid(
+ [in,ref] policy_handle *handle,
+ [in] uint32 rid,
+ [out] dom_sid2 *sid
+ );
/************************/
/* Function 0x42 */
diff --git a/source4/torture/rpc/autoidl.c b/source4/torture/rpc/autoidl.c
index 31359b4baf..ae4126688f 100644
--- a/source4/torture/rpc/autoidl.c
+++ b/source4/torture/rpc/autoidl.c
@@ -222,7 +222,7 @@ static void test_scan_call(TALLOC_CTX *mem_ctx, const struct dcerpc_interface_ta
static void test_auto_scan(TALLOC_CTX *mem_ctx, const struct dcerpc_interface_table *iface)
{
- test_scan_call(mem_ctx, iface, 0x37);
+ test_scan_call(mem_ctx, iface, 0x41);
}
BOOL torture_rpc_autoidl(int dummy)
diff --git a/source4/torture/rpc/samr.c b/source4/torture/rpc/samr.c
index 2a48a6c584..6f90d68f75 100644
--- a/source4/torture/rpc/samr.c
+++ b/source4/torture/rpc/samr.c
@@ -27,6 +27,9 @@
#define TEST_GROUPNAME "samrtorturetestgroup"
#define TEST_MACHINENAME "samrtorturetestmach$"
#define TEST_DOMAINNAME "samrtorturetestdom$"
+#define TEST_PASSWORD "Caamei2n"
+#define TEST_PASSWORD2 "ipei8Thi"
+#define TEST_PASSWORD3 "Vohxoim1"
static BOOL test_QueryUserInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
@@ -241,6 +244,44 @@ static BOOL test_SetUserInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
return ret;
}
+
+static BOOL test_SetUserPass(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+ struct policy_handle *handle)
+{
+ NTSTATUS status;
+ struct samr_SetUserInfo s;
+ union samr_UserInfo u;
+ BOOL ret = True;
+ uint8 session_key[16];
+
+ s.in.handle = handle;
+ s.in.info = &u;
+ s.in.level = 24;
+
+ encode_pw_buffer(u.info24.password.data, TEST_PASSWORD, STR_UNICODE);
+ u.info24.pw_len = 24;
+
+ status = dcerpc_fetch_session_key(p, session_key);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("SetUserInfo level %u - no session key - %s\n",
+ s.in.level, nt_errstr(status));
+ return False;
+ }
+
+ SamOEMhash(u.info24.password.data, session_key, 516);
+
+ printf("Testing SetUserInfo level 24 (set password)\n");
+
+ status = dcerpc_samr_SetUserInfo(p, mem_ctx, &s);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("SetUserInfo level %u failed - %s\n",
+ s.in.level, nt_errstr(status));
+ ret = False;
+ }
+
+ return ret;
+}
+
static BOOL test_SetAliasInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
struct policy_handle *handle)
{
@@ -427,22 +468,29 @@ static BOOL test_OemChangePasswordUser2(struct dcerpc_pipe *p, TALLOC_CTX *mem_c
NTSTATUS status;
struct samr_OemChangePasswordUser2 r;
BOOL ret = True;
- struct samr_Hash hash;
- struct samr_CryptPassword pass;
+ struct samr_Hash lm_verifier;
+ struct samr_CryptPassword lm_pass;
struct samr_AsciiName server, account;
+ const char *oldpass = TEST_PASSWORD2;
+ const char *newpass = TEST_PASSWORD3;
+ uint8 old_lm_hash[16], new_lm_hash[16];
printf("Testing OemChangePasswordUser2\n");
- ZERO_STRUCT(hash);
- ZERO_STRUCT(pass);
-
server.name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
account.name = TEST_USERNAME;
+ E_deshash(oldpass, old_lm_hash);
+ E_deshash(newpass, new_lm_hash);
+
+ encode_pw_buffer(lm_pass.data, newpass, 516);
+ SamOEMhash(lm_pass.data, old_lm_hash, 516);
+ E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
+
r.in.server = &server;
r.in.account = &account;
- r.in.password = &pass;
- r.in.hash = &hash;
+ r.in.password = &lm_pass;
+ r.in.hash = &lm_verifier;
status = dcerpc_samr_OemChangePasswordUser2(p, mem_ctx, &r);
if (!NT_STATUS_IS_OK(status)) {
@@ -462,17 +510,30 @@ static BOOL test_ChangePasswordUser2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
struct samr_Name server, account;
struct samr_CryptPassword nt_pass, lm_pass;
struct samr_Hash nt_verifier, lm_verifier;
+ const char *oldpass = TEST_PASSWORD;
+ const char *newpass = TEST_PASSWORD2;
+ uint8 old_nt_hash[16], new_nt_hash[16];
+ uint8 old_lm_hash[16], new_lm_hash[16];
printf("Testing ChangePasswordUser2\n");
server.name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
init_samr_Name(&account, TEST_USERNAME);
- ZERO_STRUCT(nt_pass);
- ZERO_STRUCT(lm_pass);
- ZERO_STRUCT(nt_verifier);
- ZERO_STRUCT(lm_verifier);
-
+ E_md4hash(oldpass, old_nt_hash);
+ E_md4hash(newpass, new_nt_hash);
+
+ E_deshash(oldpass, old_lm_hash);
+ E_deshash(newpass, new_lm_hash);
+
+ encode_pw_buffer(lm_pass.data, newpass, 516);
+ SamOEMhash(lm_pass.data, old_lm_hash, 516);
+ E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
+
+ encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
+ SamOEMhash(nt_pass.data, old_nt_hash, 516);
+ E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
+
r.in.server = &server;
r.in.account = &account;
r.in.nt_password = &nt_pass;
@@ -647,6 +708,10 @@ static BOOL test_user_ops(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
ret = False;
}
+ if (!test_SetUserPass(p, mem_ctx, handle)) {
+ ret = False;
+ }
+
if (!test_GetUserPwInfo(p, mem_ctx, handle)) {
ret = False;
}
@@ -926,11 +991,11 @@ static BOOL test_CreateUser(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
}
}
- if (!test_ChangePasswordUser(p, mem_ctx, domain_handle)) {
+ if (!test_user_ops(p, mem_ctx, user_handle)) {
ret = False;
}
- if (!test_OemChangePasswordUser2(p, mem_ctx, domain_handle)) {
+ if (!test_ChangePasswordUser(p, mem_ctx, domain_handle)) {
ret = False;
}
@@ -938,7 +1003,7 @@ static BOOL test_CreateUser(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
ret = False;
}
- if (!test_user_ops(p, mem_ctx, user_handle)) {
+ if (!test_OemChangePasswordUser2(p, mem_ctx, domain_handle)) {
ret = False;
}
@@ -1876,6 +1941,27 @@ static BOOL test_TestPrivateFunctionsDomain(struct dcerpc_pipe *p, TALLOC_CTX *m
return ret;
}
+static BOOL test_RidToSid(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+ struct policy_handle *domain_handle)
+{
+ struct samr_RidToSid r;
+ NTSTATUS status;
+ BOOL ret = True;
+
+ printf("Testing RidToSid\n");
+
+ r.in.handle = domain_handle;
+ r.in.rid = 512;
+
+ status = dcerpc_samr_RidToSid(p, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("RidToSid failed - %s\n", nt_errstr(status));
+ ret = False;
+ }
+
+ return ret;
+}
+
static BOOL test_AddGroupMember(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
struct policy_handle *domain_handle,
struct policy_handle *group_handle)
@@ -2107,6 +2193,10 @@ static BOOL test_OpenDomain(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
ret = False;
}
+ if (!test_RidToSid(p, mem_ctx, &domain_handle)) {
+ ret = False;
+ }
+
if (!policy_handle_empty(&user_handle) &&
!test_DeleteUser(p, mem_ctx, &user_handle)) {
ret = False;