diff options
author | Andrew Tridgell <tridge@samba.org> | 2004-04-21 05:01:31 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 12:51:19 -0500 |
commit | 5f545543f0bfb9d97d6401576906c0ba9e596cd1 (patch) | |
tree | 048b807b3904f10f949c72df0d4338769c2f06ec | |
parent | 6428ffb89a350d70cb62b4b1574dd671d840e62c (diff) | |
download | samba-5f545543f0bfb9d97d6401576906c0ba9e596cd1.tar.gz samba-5f545543f0bfb9d97d6401576906c0ba9e596cd1.tar.bz2 samba-5f545543f0bfb9d97d6401576906c0ba9e596cd1.zip |
r305: - added IDL and test code for samr_RidToSid()
- completed the IDL and test code for the various set user password
mechanisms in samr. Three password mechanisms are now working, the
UserInfo24 method, the OemChangePasswordUser2() method (which only
sets the LM password) and the ChangePasswordUser2() method which sets
both the LM and NT passwords.
- updated some crypto routines to support the password change tests
(This used to be commit 051efa2abf9d1fbbf783df411c02f2714027f813)
-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; |