r21719: Try to cover more of the server-side password processing.
authorAndrew Bartlett <abartlet@samba.org>
Tue, 6 Mar 2007 05:30:25 +0000 (05:30 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 19:49:17 +0000 (14:49 -0500)
Don't just exit the test with 'return True', actually process the result.

Turn off password complexity checking for the password length test.

Andrew Bartlett

source/torture/rpc/samr.c

index e76599b3e4331e12e8cf20b607701cff694832ff..0367cc4dc81c3be6247a28aebb50822004e7f112 100644 (file)
@@ -1034,6 +1034,7 @@ static BOOL test_ChangePasswordUser(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        char *oldpass;
        uint8_t old_nt_hash[16], new_nt_hash[16];
        uint8_t old_lm_hash[16], new_lm_hash[16];
+       BOOL changed = True;
 
        char *newpass;
        struct samr_GetUserPwInfo pwp;
@@ -1072,6 +1073,43 @@ static BOOL test_ChangePasswordUser(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
        E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
 
+       r.in.user_handle = &user_handle;
+       r.in.lm_present = 1;
+       r.in.old_lm_crypted = &hash1;
+       r.in.new_lm_crypted = &hash2;
+       r.in.nt_present = 1;
+       r.in.old_nt_crypted = &hash3;
+       r.in.new_nt_crypted = &hash4;
+       r.in.cross1_present = 1;
+       r.in.nt_cross = &hash5;
+       r.in.cross2_present = 0;
+       r.in.lm_cross = NULL;
+
+       status = dcerpc_samr_ChangePasswordUser(p, mem_ctx, &r);
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED)) {
+               printf("ChangePasswordUser failed: expected NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED, got %s\n", nt_errstr(status));
+               ret = False;
+       }
+
+       
+       r.in.user_handle = &user_handle;
+       r.in.lm_present = 1;
+       r.in.old_lm_crypted = &hash1;
+       r.in.new_lm_crypted = &hash2;
+       r.in.nt_present = 1;
+       r.in.old_nt_crypted = &hash3;
+       r.in.new_nt_crypted = &hash4;
+       r.in.cross1_present = 0;
+       r.in.nt_cross = NULL;
+       r.in.cross2_present = 1;
+       r.in.lm_cross = &hash6;
+
+       status = dcerpc_samr_ChangePasswordUser(p, mem_ctx, &r);
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED)) {
+               printf("ChangePasswordUser failed: expected NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED, got %s\n", nt_errstr(status));
+               ret = False;
+       }
+
        r.in.user_handle = &user_handle;
        r.in.lm_present = 1;
        r.in.old_lm_crypted = &hash1;
@@ -1091,9 +1129,30 @@ static BOOL test_ChangePasswordUser(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                printf("ChangePasswordUser failed - %s\n", nt_errstr(status));
                ret = False;
        } else {
+               changed = True;
                *password = newpass;
        }
 
+       r.in.user_handle = &user_handle;
+       r.in.lm_present = 1;
+       r.in.old_lm_crypted = &hash1;
+       r.in.new_lm_crypted = &hash2;
+       r.in.nt_present = 1;
+       r.in.old_nt_crypted = &hash3;
+       r.in.new_nt_crypted = &hash4;
+       r.in.cross1_present = 1;
+       r.in.nt_cross = &hash5;
+       r.in.cross2_present = 1;
+       r.in.lm_cross = &hash6;
+
+       if (changed) {
+               status = dcerpc_samr_ChangePasswordUser(p, mem_ctx, &r);
+               if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
+                       printf("ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we already changed the password, got %s\n", nt_errstr(status));
+                       ret = False;
+               }
+       }
+
        if (!test_samr_handle_Close(p, mem_ctx, &user_handle)) {
                ret = False;
        }
@@ -1167,6 +1226,45 @@ static BOOL test_OemChangePasswordUser2(struct dcerpc_pipe *p, TALLOC_CTX *mem_c
                ret = False;
        }
 
+       encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
+       /* Break the old password */
+       old_lm_hash[0]++;
+       arcfour_crypt(lm_pass.data, old_lm_hash, 516);
+       /* unbreak it for the next operation */
+       old_lm_hash[0]--;
+       E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
+
+       r.in.server = &server;
+       r.in.account = &account;
+       r.in.password = &lm_pass;
+       r.in.hash = &lm_verifier;
+
+       status = dcerpc_samr_OemChangePasswordUser2(p, mem_ctx, &r);
+
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
+           && !NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
+               printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
+                       nt_errstr(status));
+               ret = False;
+       }
+
+       encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
+       arcfour_crypt(lm_pass.data, old_lm_hash, 516);
+
+       r.in.server = &server;
+       r.in.account = &account;
+       r.in.password = &lm_pass;
+       r.in.hash = NULL;
+
+       status = dcerpc_samr_OemChangePasswordUser2(p, mem_ctx, &r);
+
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
+           && !NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
+               printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for no supplied validation hash - %s\n",
+                       nt_errstr(status));
+               ret = False;
+       }
+
        /* This shouldn't be a valid name */
        account_bad.string = TEST_ACCOUNT_NAME "XX";
        r.in.account = &account_bad;
@@ -1305,11 +1403,13 @@ BOOL test_ChangePasswordUser3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        printf("Testing ChangePasswordUser3\n");
 
        if (newpass == NULL) {
-               if (policy_min_pw_len == 0) {
-                       newpass = samr_rand_pass(mem_ctx, policy_min_pw_len);
-               } else {
-                       newpass = samr_rand_pass_fixed_len(mem_ctx, policy_min_pw_len);
-               }
+               do {
+                       if (policy_min_pw_len == 0) {
+                               newpass = samr_rand_pass(mem_ctx, policy_min_pw_len);
+                       } else {
+                               newpass = samr_rand_pass_fixed_len(mem_ctx, policy_min_pw_len);
+                       }
+               } while (check_password_quality(newpass) == False);
        } else {
                printf("Using password '%s'\n", newpass);
        }
@@ -1357,6 +1457,35 @@ BOOL test_ChangePasswordUser3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                ret = False;
        }
        
+       encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
+       arcfour_crypt(lm_pass.data, old_nt_hash, 516);
+       E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
+
+       encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
+       /* Break the NT hash */
+       old_nt_hash[0]++;
+       arcfour_crypt(nt_pass.data, old_nt_hash, 516);
+       /* Unbreak it again */
+       old_nt_hash[0]--;
+       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;
+       r.in.nt_verifier = &nt_verifier;
+       r.in.lm_change = 1;
+       r.in.lm_password = &lm_pass;
+       r.in.lm_verifier = &lm_verifier;
+       r.in.password3 = NULL;
+
+       status = dcerpc_samr_ChangePasswordUser3(p, mem_ctx, &r);
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) &&
+           (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD))) {
+               printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
+                       nt_errstr(status));
+               ret = False;
+       }
+       
        /* This shouldn't be a valid name */
        init_lsa_String(&account_bad, talloc_asprintf(mem_ctx, "%sXX", account_string));
 
@@ -1434,14 +1563,6 @@ BOOL test_ChangePasswordUser3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                                return False;
                        }
 
-               } else if (r.out.dominfo->password_properties & DOMAIN_PASSWORD_COMPLEX) {
-
-                       if (r.out.reject->reason != SAMR_REJECT_COMPLEXITY) {
-                               printf("expected SAMR_REJECT_COMPLEXITY (%d), got %d\n", 
-                                       SAMR_REJECT_COMPLEXITY, r.out.reject->reason);
-                               return False;
-                       }
-
                } else if ((r.out.dominfo->password_history_length > 0) && 
                            strequal(oldpass, newpass)) {
 
@@ -1450,6 +1571,14 @@ BOOL test_ChangePasswordUser3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                                        SAMR_REJECT_IN_HISTORY, r.out.reject->reason);
                                return False;
                        }
+               } else if (r.out.dominfo->password_properties & DOMAIN_PASSWORD_COMPLEX) {
+
+                       if (r.out.reject->reason != SAMR_REJECT_COMPLEXITY) {
+                               printf("expected SAMR_REJECT_COMPLEXITY (%d), got %d\n", 
+                                       SAMR_REJECT_COMPLEXITY, r.out.reject->reason);
+                               return False;
+                       }
+
                }
 
                if (r.out.reject->reason == SAMR_REJECT_TOO_SHORT) {
@@ -1970,9 +2099,10 @@ static BOOL test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                struct samr_QueryDomainInfo r;
                struct samr_SetDomainInfo s;
                uint16_t len_old, len;
+               uint32_t pwd_prop_old;
                NTSTATUS status;
 
-               len = 3;
+               len = 5;
 
                r.in.domain_handle = domain_handle;
                r.in.level = 1;
@@ -1987,8 +2117,12 @@ static BOOL test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                s.in.level = 1;
                s.in.info = r.out.info;
 
+               /* remember the old min length, so we can reset it */
                len_old = s.in.info->info1.min_password_length;
                s.in.info->info1.min_password_length = len;
+               pwd_prop_old = s.in.info->info1.password_properties;
+               /* turn off password complexity checks for this test */
+               s.in.info->info1.password_properties &= ~DOMAIN_PASSWORD_COMPLEX;
 
                printf("testing samr_SetDomainInfo level 1\n");
                status = dcerpc_samr_SetDomainInfo(p, mem_ctx, &s);
@@ -2003,6 +2137,7 @@ static BOOL test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                }
 
                s.in.info->info1.min_password_length = len_old;
+               s.in.info->info1.password_properties = pwd_prop_old;
                
                printf("testing samr_SetDomainInfo level 1\n");
                status = dcerpc_samr_SetDomainInfo(p, mem_ctx, &s);
@@ -2058,8 +2193,6 @@ static BOOL test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                }
        }
 
-       return True;
-
        /* we change passwords twice - this has the effect of verifying
           they were changed correctly for the final call */
        if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, NULL, 0, True)) {