diff options
-rw-r--r-- | source4/torture/rpc/samr.c | 289 |
1 files changed, 181 insertions, 108 deletions
diff --git a/source4/torture/rpc/samr.c b/source4/torture/rpc/samr.c index 2e59a06f98..b9fa778fa7 100644 --- a/source4/torture/rpc/samr.c +++ b/source4/torture/rpc/samr.c @@ -1041,9 +1041,11 @@ static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p, uint16_t level, uint32_t fields_present, char **password, uint8_t password_expired, - bool use_setinfo2, NTSTATUS expected_error) + bool use_setinfo2, + bool *matched_expected_error) { NTSTATUS status; + NTSTATUS expected_error = NT_STATUS_OK; struct samr_SetUserInfo s; struct samr_SetUserInfo2 s2; union samr_UserInfo u; @@ -1157,6 +1159,15 @@ static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p, status = dcerpc_samr_SetUserInfo(p, tctx, &s); } + if (!NT_STATUS_IS_OK(status)) { + if (fields_present == 0) { + expected_error = NT_STATUS_INVALID_PARAMETER; + } + if (fields_present & SAMR_FIELD_LAST_PWD_CHANGE) { + expected_error = NT_STATUS_ACCESS_DENIED; + } + } + if (!NT_STATUS_IS_OK(expected_error)) { if (use_setinfo2) { torture_assert_ntstatus_equal(tctx, @@ -1167,6 +1178,7 @@ static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p, s.out.result, expected_error, "SetUserInfo failed"); } + *matched_expected_error = true; return true; } @@ -2550,7 +2562,7 @@ static bool test_SetPassword_level(struct dcerpc_pipe *p, uint16_t level, uint32_t fields_present, uint8_t password_expired, - NTSTATUS expected_error, + bool *matched_expected_error, bool use_setinfo2, char **password, bool use_queryinfo2, @@ -2586,7 +2598,7 @@ static bool test_SetPassword_level(struct dcerpc_pipe *p, password, password_expired, use_setinfo2, - expected_error)) { + matched_expected_error)) { ret = false; } break; @@ -2609,143 +2621,73 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p, struct policy_handle *handle, char **password) { - int i, s = 0, q = 0; + int i, s = 0, q = 0, f = 0; bool ret = true; int delay = 500000; bool set_levels[] = { false, true }; bool query_levels[] = { false, true }; + uint32_t fields_present[] = { + 0, + SAMR_FIELD_EXPIRED_FLAG, + SAMR_FIELD_LAST_PWD_CHANGE, + SAMR_FIELD_EXPIRED_FLAG | SAMR_FIELD_LAST_PWD_CHANGE, + SAMR_FIELD_COMMENT, + SAMR_FIELD_NT_PASSWORD_PRESENT, + SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE, + SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT, + SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE, + SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG, + SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG, + SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE | SAMR_FIELD_EXPIRED_FLAG + }; struct { uint16_t level; uint8_t password_expired_nonzero; - uint32_t fields_present; - bool query_info2; - bool set_info2; - NTSTATUS set_error; } pwd_tests[] = { /* level 21 */ { .level = 21, .password_expired_nonzero = 1, - .fields_present = SAMR_FIELD_EXPIRED_FLAG - },{ - .level = 21, - .password_expired_nonzero = 1, - .fields_present = SAMR_FIELD_LAST_PWD_CHANGE, - .set_error = NT_STATUS_ACCESS_DENIED - },{ - .level = 21, - .password_expired_nonzero = 1, - .fields_present = 0, - .set_error = NT_STATUS_INVALID_PARAMETER - },{ - .level = 21, - .password_expired_nonzero = 1, - .fields_present = SAMR_FIELD_COMMENT, - -#if 0 - /* FIXME */ },{ .level = 21, - .password_expired_nonzero = 1, - .fields_present = SAMR_FIELD_NT_PASSWORD_PRESENT | - SAMR_FIELD_LM_PASSWORD_PRESENT | - SAMR_FIELD_LAST_PWD_CHANGE, - .query_info2 = false, - .set_error = NT_STATUS_ACCESS_DENIED -#endif + .password_expired_nonzero = 24, /* level 23 */ },{ .level = 23, .password_expired_nonzero = 1, - .fields_present = SAMR_FIELD_EXPIRED_FLAG - },{ - .level = 23, - .password_expired_nonzero = 1, - .fields_present = SAMR_FIELD_LAST_PWD_CHANGE, - .set_error = NT_STATUS_ACCESS_DENIED - },{ - .level = 23, - .password_expired_nonzero = 1, - .fields_present = SAMR_FIELD_LAST_PWD_CHANGE | - SAMR_FIELD_NT_PASSWORD_PRESENT | - SAMR_FIELD_LM_PASSWORD_PRESENT, - .set_error = NT_STATUS_ACCESS_DENIED - },{ - .level = 23, - .password_expired_nonzero = 1, - .fields_present = SAMR_FIELD_LAST_PWD_CHANGE | - SAMR_FIELD_NT_PASSWORD_PRESENT | - SAMR_FIELD_LM_PASSWORD_PRESENT | - SAMR_FIELD_EXPIRED_FLAG, - .set_error = NT_STATUS_ACCESS_DENIED },{ .level = 23, - .password_expired_nonzero = 1, - .fields_present = SAMR_FIELD_NT_PASSWORD_PRESENT | - SAMR_FIELD_LM_PASSWORD_PRESENT | - SAMR_FIELD_EXPIRED_FLAG - },{ - .level = 23, - .password_expired_nonzero = 1, - .fields_present = SAMR_FIELD_NT_PASSWORD_PRESENT | - SAMR_FIELD_LM_PASSWORD_PRESENT, - },{ - .level = 23, - .password_expired_nonzero = 1, - .fields_present = SAMR_FIELD_COMMENT, - },{ - .level = 23, - .password_expired_nonzero = 1, - .fields_present = 0, - .set_error = NT_STATUS_INVALID_PARAMETER + .password_expired_nonzero = 24, },{ /* level 24 */ .level = 24, - .password_expired_nonzero = 1 + .password_expired_nonzero = 1, },{ .level = 24, - .password_expired_nonzero = 24 + .password_expired_nonzero = 24, },{ /* level 25 */ .level = 25, .password_expired_nonzero = 1, - .fields_present = SAMR_FIELD_LAST_PWD_CHANGE, - .set_error = NT_STATUS_ACCESS_DENIED - },{ - .level = 25, - .password_expired_nonzero = 1, - .fields_present = SAMR_FIELD_EXPIRED_FLAG, - },{ - .level = 25, - .password_expired_nonzero = 1, - .fields_present = SAMR_FIELD_NT_PASSWORD_PRESENT | - SAMR_FIELD_LM_PASSWORD_PRESENT | - SAMR_FIELD_EXPIRED_FLAG - },{ - .level = 25, - .password_expired_nonzero = 1, - .fields_present = SAMR_FIELD_NT_PASSWORD_PRESENT | - SAMR_FIELD_LM_PASSWORD_PRESENT, },{ .level = 25, - .password_expired_nonzero = 1, - .fields_present = SAMR_FIELD_COMMENT, + .password_expired_nonzero = 24 },{ /* level 26 */ .level = 26, - .password_expired_nonzero = 1 + .password_expired_nonzero = 1, },{ .level = 26, - .password_expired_nonzero = 24 + .password_expired_nonzero = 24, } }; @@ -2763,6 +2705,7 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p, #define TEST_QUERY_LEVELS 1 #endif for (i=0; i<ARRAY_SIZE(pwd_tests); i++) { + for (f=0; f<ARRAY_SIZE(fields_present); f++) { #ifdef TEST_SET_LEVELS for (s=0; s<ARRAY_SIZE(set_levels); s++) { #endif @@ -2771,6 +2714,7 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p, #endif NTTIME pwdlastset_old = 0; NTTIME pwdlastset_new = 0; + bool matched_expected_error = false; torture_comment(tctx, "------------------------------\n" "Testing pwdLastSet attribute for flags: 0x%08x " @@ -2784,9 +2728,9 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p, if (!test_SetPassword_level(p, tctx, handle, pwd_tests[i].level, - pwd_tests[i].fields_present, + fields_present[f], pwd_tests[i].password_expired_nonzero, - pwd_tests[i].set_error, + &matched_expected_error, set_levels[s], password, query_levels[q], @@ -2794,7 +2738,7 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p, ret = false; } - if (!NT_STATUS_IS_OK(pwd_tests[i].set_error)) { + if (matched_expected_error == true) { /* skipping on expected failure */ continue; } @@ -2807,7 +2751,7 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p, case 23: case 25: if ((pwdlastset_new != 0) && - !(pwd_tests[i].fields_present & SAMR_FIELD_EXPIRED_FLAG)) { + !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) { torture_comment(tctx, "not considering a non-0 " "pwdLastSet as a an error as the " "SAMR_FIELD_EXPIRED_FLAG has not " @@ -2824,6 +2768,27 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p, break; } + switch (pwd_tests[i].level) { + case 21: + case 23: + case 25: + if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) || + (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) && + (pwdlastset_old > 0) && (pwdlastset_new > 0) && + (pwdlastset_old >= pwdlastset_new)) { + torture_warning(tctx, "pwdlastset not increasing\n"); + ret = false; + } + break; + default: + if ((pwdlastset_old > 0) && (pwdlastset_new > 0) && + (pwdlastset_old >= pwdlastset_new)) { + torture_warning(tctx, "pwdlastset not increasing\n"); + ret = false; + } + break; + } + usleep(delay); /* set #2 */ @@ -2831,15 +2796,15 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p, /* set a password, pwdlastset needs to get updated (increased * value), password_expired value used here is 0 */ - if (!test_SetPassword_level(p, tctx, handle, pwd_tests[i].level, - pwd_tests[i].fields_present, + if (!test_SetPassword_level(p, tctx, handle, + pwd_tests[i].level, + fields_present[f], 0, - pwd_tests[i].set_error, + &matched_expected_error, set_levels[s], password, query_levels[q], &pwdlastset_new)) { - ret = false; } @@ -2878,19 +2843,91 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p, } } + switch (pwd_tests[i].level) { + case 21: + case 23: + case 25: + if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) || + (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) && + (pwdlastset_old > 0) && (pwdlastset_new > 0) && + (pwdlastset_old >= pwdlastset_new)) { + torture_warning(tctx, "pwdlastset not increasing\n"); + ret = false; + } + break; + default: + if ((pwdlastset_old > 0) && (pwdlastset_new > 0) && + (pwdlastset_old >= pwdlastset_new)) { + torture_warning(tctx, "pwdlastset not increasing\n"); + ret = false; + } + break; + } + pwdlastset_old = pwdlastset_new; usleep(delay); + /* set #2b */ + + /* set a password, pwdlastset needs to get updated (increased + * value), password_expired value used here is 0 */ + + if (!test_SetPassword_level(p, tctx, handle, + pwd_tests[i].level, + fields_present[f], + 0, + &matched_expected_error, + set_levels[s], + password, + query_levels[q], + &pwdlastset_new)) { + ret = false; + } + + /* when a password has been changed, pwdlastset must not be 0 afterwards + * and must be larger then the old value */ + + switch (pwd_tests[i].level) { + case 21: + case 23: + case 25: + + /* if no password has been changed, old and new pwdlastset + * need to be the same value */ + + if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) || + (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT))) + { + torture_assert_int_equal(tctx, pwdlastset_old, + pwdlastset_new, "pwdlastset must be equal"); + break; + } + default: + if (pwdlastset_old >= pwdlastset_new) { + torture_warning(tctx, "pwdLastSet test failed: " + "expected last pwdlastset (%lld) < new pwdlastset (%lld)\n", + pwdlastset_old, pwdlastset_new); + ret = false; + } + if (pwdlastset_new == 0) { + torture_warning(tctx, "pwdLastSet test failed: " + "expected non-0 pwdlastset, got: %lld\n", + pwdlastset_new); + ret = false; + } + } + /* set #3 */ /* set a password and force password change (pwdlastset 0) by * setting the password expired flag to a non-0 value */ - if (!test_SetPassword_level(p, tctx, handle, pwd_tests[i].level, - pwd_tests[i].fields_present, + if (!test_SetPassword_level(p, tctx, handle, + pwd_tests[i].level, + fields_present[f], pwd_tests[i].password_expired_nonzero, - pwd_tests[i].set_error, + &matched_expected_error, set_levels[s], password, query_levels[q], @@ -2906,7 +2943,7 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p, case 23: case 25: if ((pwdlastset_new != 0) && - !(pwd_tests[i].fields_present & SAMR_FIELD_EXPIRED_FLAG)) { + !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) { torture_comment(tctx, "not considering a non-0 " "pwdLastSet as a an error as the " "SAMR_FIELD_EXPIRED_FLAG has not " @@ -2943,6 +2980,35 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p, } break; } + + switch (pwd_tests[i].level) { + case 21: + case 23: + case 25: + if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) || + (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) && + (pwdlastset_old > 0) && (pwdlastset_new > 0) && + (pwdlastset_old >= pwdlastset_new)) { + torture_warning(tctx, "pwdlastset not increasing\n"); + ret = false; + } + break; + default: + if ((pwdlastset_old > 0) && (pwdlastset_new > 0) && + (pwdlastset_old >= pwdlastset_new)) { + torture_warning(tctx, "pwdlastset not increasing\n"); + ret = false; + } + break; + } + + switch (pwd_tests[i].level) { + case 24: + case 26: + f = ARRAY_SIZE(fields_present); + break; + } + #ifdef TEST_QUERY_LEVELS } #endif @@ -2950,6 +3016,7 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p, } #endif } + } #undef TEST_SET_LEVELS #undef TEST_QUERY_LEVELS @@ -5370,7 +5437,6 @@ static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx, switch (which_ops) { case TORTURE_SAMR_USER_ATTRIBUTES: case TORTURE_SAMR_PASSWORDS: - case TORTURE_SAMR_PASSWORDS_PWDLASTSET: ret &= test_CreateUser2(p, tctx, &domain_handle, sid, which_ops); ret &= test_CreateUser(p, tctx, &domain_handle, &user_handle, sid, which_ops); /* This test needs 'complex' users to validate */ @@ -5379,6 +5445,13 @@ static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx, printf("Testing PASSWORDS or ATTRIBUTES on domain %s failed!\n", dom_sid_string(tctx, sid)); } break; + case TORTURE_SAMR_PASSWORDS_PWDLASTSET: + ret &= test_CreateUser2(p, tctx, &domain_handle, sid, which_ops); + ret &= test_CreateUser(p, tctx, &domain_handle, &user_handle, sid, which_ops); + if (!ret) { + printf("Testing PASSWORDS PWDLASTSET on domain %s failed!\n", dom_sid_string(tctx, sid)); + } + break; case TORTURE_SAMR_OTHER: ret &= test_CreateUser(p, tctx, &domain_handle, &user_handle, sid, which_ops); if (!ret) { |