diff options
-rw-r--r-- | source4/libcli/util/smbdes.c | 30 | ||||
-rw-r--r-- | source4/libcli/util/smbencrypt.c | 21 | ||||
-rw-r--r-- | source4/librpc/idl/samr.idl | 20 | ||||
-rw-r--r-- | source4/torture/rpc/autoidl.c | 2 | ||||
-rw-r--r-- | source4/torture/rpc/samr.c | 120 |
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; |