summaryrefslogtreecommitdiff
path: root/source4/torture/rpc/samr.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/torture/rpc/samr.c')
-rw-r--r--source4/torture/rpc/samr.c1214
1 files changed, 1043 insertions, 171 deletions
diff --git a/source4/torture/rpc/samr.c b/source4/torture/rpc/samr.c
index 23c288bfcc..01ff01674c 100644
--- a/source4/torture/rpc/samr.c
+++ b/source4/torture/rpc/samr.c
@@ -29,6 +29,8 @@
#include "libcli/security/security.h"
#include "torture/rpc/rpc.h"
+#include <unistd.h>
+
#define TEST_ACCOUNT_NAME "samrtorturetest"
#define TEST_ALIASNAME "samrtorturetestalias"
#define TEST_GROUPNAME "samrtorturetestgroup"
@@ -37,6 +39,7 @@
enum torture_samr_choice {
TORTURE_SAMR_PASSWORDS,
+ TORTURE_SAMR_PASSWORDS_PWDLASTSET,
TORTURE_SAMR_USER_ATTRIBUTES,
TORTURE_SAMR_OTHER
};
@@ -59,6 +62,13 @@ static void init_lsa_String(struct lsa_String *string, const char *s)
string->string = s;
}
+static void init_lsa_BinaryString(struct lsa_BinaryString *string, const char *s, uint32_t length)
+{
+ string->length = length;
+ string->size = length;
+ string->array = (uint16_t *)discard_const(s);
+}
+
bool test_samr_handle_Close(struct dcerpc_pipe *p, struct torture_context *tctx,
struct policy_handle *handle)
{
@@ -131,18 +141,20 @@ static bool test_QuerySecurity(struct dcerpc_pipe *p,
NTSTATUS status;
struct samr_QuerySecurity r;
struct samr_SetSecurity s;
+ struct sec_desc_buf *sdbuf = NULL;
r.in.handle = handle;
r.in.sec_info = 7;
+ r.out.sdbuf = &sdbuf;
status = dcerpc_samr_QuerySecurity(p, tctx, &r);
torture_assert_ntstatus_ok(tctx, status, "QuerySecurity");
- torture_assert(tctx, r.out.sdbuf != NULL, "sdbuf is NULL");
+ torture_assert(tctx, sdbuf != NULL, "sdbuf is NULL");
s.in.handle = handle;
s.in.sec_info = 7;
- s.in.sdbuf = r.out.sdbuf;
+ s.in.sdbuf = sdbuf;
if (torture_setting_bool(tctx, "samba4", false)) {
torture_skip(tctx, "skipping SetSecurity test against Samba4\n");
@@ -168,6 +180,7 @@ static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx
struct samr_QueryUserInfo q;
struct samr_QueryUserInfo q0;
union samr_UserInfo u;
+ union samr_UserInfo *info;
bool ret = true;
const char *test_account_name;
@@ -184,7 +197,7 @@ static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx
s2.in.info = &u;
q.in.user_handle = handle;
- q.out.info = &u;
+ q.out.info = &info;
q0 = q;
#define TESTCALL(call, r) \
@@ -204,6 +217,14 @@ static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx
break; \
}
+#define MEM_EQUAL(s1, s2, length, field) \
+ if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
+ torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
+ #field, (const char *)s2, __location__); \
+ ret = false; \
+ break; \
+ }
+
#define INT_EQUAL(i1, i2, field) \
if (i1 != i2) { \
torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
@@ -218,7 +239,7 @@ static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx
TESTCALL(QueryUserInfo, q) \
s.in.level = lvl1; \
s2.in.level = lvl1; \
- u = *q.out.info; \
+ u = *info; \
if (lvl1 == 21) { \
ZERO_STRUCT(u.info21); \
u.info21.fields_present = fpval; \
@@ -228,21 +249,45 @@ static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx
TESTCALL(SetUserInfo2, s2) \
init_lsa_String(&u.info ## lvl1.field1, ""); \
TESTCALL(QueryUserInfo, q); \
- u = *q.out.info; \
+ u = *info; \
STRING_EQUAL(u.info ## lvl1.field1.string, value, field1); \
q.in.level = lvl2; \
TESTCALL(QueryUserInfo, q) \
- u = *q.out.info; \
+ u = *info; \
STRING_EQUAL(u.info ## lvl2.field2.string, value, field2); \
} while (0)
+#define TEST_USERINFO_BINARYSTRING(lvl1, field1, lvl2, field2, value, fpval) do { \
+ torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
+ q.in.level = lvl1; \
+ TESTCALL(QueryUserInfo, q) \
+ s.in.level = lvl1; \
+ s2.in.level = lvl1; \
+ u = *info; \
+ if (lvl1 == 21) { \
+ ZERO_STRUCT(u.info21); \
+ u.info21.fields_present = fpval; \
+ } \
+ init_lsa_BinaryString(&u.info ## lvl1.field1, value, strlen(value)); \
+ TESTCALL(SetUserInfo, s) \
+ TESTCALL(SetUserInfo2, s2) \
+ init_lsa_BinaryString(&u.info ## lvl1.field1, "", 1); \
+ TESTCALL(QueryUserInfo, q); \
+ u = *info; \
+ MEM_EQUAL(u.info ## lvl1.field1.array, value, strlen(value), field1); \
+ q.in.level = lvl2; \
+ TESTCALL(QueryUserInfo, q) \
+ u = *info; \
+ MEM_EQUAL(u.info ## lvl2.field2.array, value, strlen(value), field2); \
+ } while (0)
+
#define TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value, fpval) do { \
torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
q.in.level = lvl1; \
TESTCALL(QueryUserInfo, q) \
s.in.level = lvl1; \
s2.in.level = lvl1; \
- u = *q.out.info; \
+ u = *info; \
if (lvl1 == 21) { \
uint8_t *bits = u.info21.logon_hours.bits; \
ZERO_STRUCT(u.info21); \
@@ -257,11 +302,11 @@ static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx
TESTCALL(SetUserInfo2, s2) \
u.info ## lvl1.field1 = 0; \
TESTCALL(QueryUserInfo, q); \
- u = *q.out.info; \
+ u = *info; \
INT_EQUAL(u.info ## lvl1.field1, exp_value, field1); \
q.in.level = lvl2; \
TESTCALL(QueryUserInfo, q) \
- u = *q.out.info; \
+ u = *info; \
INT_EQUAL(u.info ## lvl2.field2, exp_value, field1); \
} while (0)
@@ -359,10 +404,10 @@ static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx
TEST_USERINFO_STRING(21, workstations, 14, workstations, "21workstation14",
SAMR_FIELD_WORKSTATIONS);
- TEST_USERINFO_STRING(20, parameters, 21, parameters, "xx20-21 parameters", 0);
- TEST_USERINFO_STRING(21, parameters, 21, parameters, "xx21-21 parameters",
+ TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "xx20-21 parameters", 0);
+ TEST_USERINFO_BINARYSTRING(21, parameters, 21, parameters, "xx21-21 parameters",
SAMR_FIELD_PARAMETERS);
- TEST_USERINFO_STRING(21, parameters, 20, parameters, "xx21-20 parameters",
+ TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "xx21-20 parameters",
SAMR_FIELD_PARAMETERS);
TEST_USERINFO_INT(2, country_code, 2, country_code, __LINE__, 0);
@@ -466,12 +511,19 @@ static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx
/*
generate a random password for password change tests
*/
-static char *samr_rand_pass(TALLOC_CTX *mem_ctx, int min_len)
+static char *samr_rand_pass_silent(TALLOC_CTX *mem_ctx, int min_len)
{
size_t len = MAX(8, min_len) + (random() % 6);
char *s = generate_random_str(mem_ctx, len);
+ return s;
+}
+
+static char *samr_rand_pass(TALLOC_CTX *mem_ctx, int min_len)
+{
+ char *s = samr_rand_pass_silent(mem_ctx, min_len);
printf("Generated password '%s'\n", s);
return s;
+
}
/*
@@ -512,12 +564,14 @@ static bool test_SetUserPass(struct dcerpc_pipe *p, struct torture_context *tctx
DATA_BLOB session_key;
char *newpass;
struct samr_GetUserPwInfo pwp;
+ struct samr_PwInfo info;
int policy_min_pw_len = 0;
pwp.in.user_handle = handle;
+ pwp.out.info = &info;
status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
if (NT_STATUS_IS_OK(status)) {
- policy_min_pw_len = pwp.out.info.min_password_length;
+ policy_min_pw_len = pwp.out.info->min_password_length;
}
newpass = samr_rand_pass(tctx, policy_min_pw_len);
@@ -526,8 +580,7 @@ static bool test_SetUserPass(struct dcerpc_pipe *p, struct torture_context *tctx
s.in.level = 24;
encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
- /* w2k3 ignores this length */
- u.info24.pw_len = strlen_m(newpass) * 2;
+ u.info24.password_expired = 0;
status = dcerpc_fetch_session_key(p, &session_key);
if (!NT_STATUS_IS_OK(status)) {
@@ -564,12 +617,14 @@ static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *t
DATA_BLOB session_key;
char *newpass;
struct samr_GetUserPwInfo pwp;
+ struct samr_PwInfo info;
int policy_min_pw_len = 0;
pwp.in.user_handle = handle;
+ pwp.out.info = &info;
status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
if (NT_STATUS_IS_OK(status)) {
- policy_min_pw_len = pwp.out.info.min_password_length;
+ policy_min_pw_len = pwp.out.info->min_password_length;
}
newpass = samr_rand_pass(tctx, policy_min_pw_len);
@@ -643,12 +698,14 @@ static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tc
char *newpass;
struct MD5Context ctx;
struct samr_GetUserPwInfo pwp;
+ struct samr_PwInfo info;
int policy_min_pw_len = 0;
pwp.in.user_handle = handle;
+ pwp.out.info = &info;
status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
if (NT_STATUS_IS_OK(status)) {
- policy_min_pw_len = pwp.out.info.min_password_length;
+ policy_min_pw_len = pwp.out.info->min_password_length;
}
if (makeshort && policy_min_pw_len) {
newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len - 1);
@@ -661,7 +718,7 @@ static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tc
s.in.level = 26;
encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
- u.info26.pw_len = strlen(newpass);
+ u.info26.password_expired = 0;
status = dcerpc_fetch_session_key(p, &session_key);
if (!NT_STATUS_IS_OK(status)) {
@@ -725,12 +782,14 @@ static bool test_SetUserPass_25(struct dcerpc_pipe *p, struct torture_context *t
uint8_t confounder[16];
char *newpass;
struct samr_GetUserPwInfo pwp;
+ struct samr_PwInfo info;
int policy_min_pw_len = 0;
pwp.in.user_handle = handle;
+ pwp.out.info = &info;
status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
if (NT_STATUS_IS_OK(status)) {
- policy_min_pw_len = pwp.out.info.min_password_length;
+ policy_min_pw_len = pwp.out.info->min_password_length;
}
newpass = samr_rand_pass(tctx, policy_min_pw_len);
@@ -790,12 +849,161 @@ static bool test_SetUserPass_25(struct dcerpc_pipe *p, struct torture_context *t
return ret;
}
+static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
+ struct policy_handle *handle,
+ uint16_t level,
+ uint32_t fields_present,
+ char **password, uint8_t password_expired,
+ bool use_setinfo2, NTSTATUS expected_error)
+{
+ NTSTATUS status;
+ struct samr_SetUserInfo s;
+ struct samr_SetUserInfo2 s2;
+ union samr_UserInfo u;
+ bool ret = true;
+ DATA_BLOB session_key;
+ DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
+ struct MD5Context ctx;
+ uint8_t confounder[16];
+ char *newpass;
+ struct samr_GetUserPwInfo pwp;
+ struct samr_PwInfo info;
+ int policy_min_pw_len = 0;
+ const char *comment = NULL;
+
+ pwp.in.user_handle = handle;
+ pwp.out.info = &info;
+
+ status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
+ if (NT_STATUS_IS_OK(status)) {
+ policy_min_pw_len = pwp.out.info->min_password_length;
+ }
+ newpass = samr_rand_pass_silent(tctx, policy_min_pw_len);
+
+ if (use_setinfo2) {
+ s2.in.user_handle = handle;
+ s2.in.info = &u;
+ s2.in.level = level;
+ } else {
+ s.in.user_handle = handle;
+ s.in.info = &u;
+ s.in.level = level;
+ }
+
+ if (fields_present & SAMR_FIELD_COMMENT) {
+ comment = talloc_asprintf(tctx, "comment: %d\n", time(NULL));
+ }
+
+ ZERO_STRUCT(u);
+
+ switch (level) {
+ case 21:
+ u.info21.fields_present = fields_present;
+ u.info21.password_expired = password_expired;
+ u.info21.comment.string = comment;
+
+ break;
+ case 23:
+ u.info23.info.fields_present = fields_present;
+ u.info23.info.password_expired = password_expired;
+ u.info23.info.comment.string = comment;
+
+ encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
+
+ break;
+ case 24:
+ u.info24.password_expired = password_expired;
+
+ encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
+
+ break;
+ case 25:
+ u.info25.info.fields_present = fields_present;
+ u.info25.info.password_expired = password_expired;
+ u.info25.info.comment.string = comment;
+
+ encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
+
+ break;
+ case 26:
+ u.info26.password_expired = password_expired;
+
+ encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
+
+ break;
+ }
+
+ 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;
+ }
+
+ generate_random_buffer((uint8_t *)confounder, 16);
+
+ MD5Init(&ctx);
+ MD5Update(&ctx, confounder, 16);
+ MD5Update(&ctx, session_key.data, session_key.length);
+ MD5Final(confounded_session_key.data, &ctx);
+
+ switch (level) {
+ case 23:
+ arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
+ break;
+ case 24:
+ arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
+ break;
+ case 25:
+ arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
+ memcpy(&u.info25.password.data[516], confounder, 16);
+ break;
+ case 26:
+ arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
+ memcpy(&u.info26.password.data[516], confounder, 16);
+ break;
+ }
+
+ if (use_setinfo2) {
+ status = dcerpc_samr_SetUserInfo2(p, tctx, &s2);
+ } else {
+ status = dcerpc_samr_SetUserInfo(p, tctx, &s);
+ }
+
+ if (!NT_STATUS_IS_OK(expected_error)) {
+ if (use_setinfo2) {
+ torture_assert_ntstatus_equal(tctx,
+ s2.out.result,
+ expected_error, "SetUserInfo2 failed");
+ } else {
+ torture_assert_ntstatus_equal(tctx,
+ s.out.result,
+ expected_error, "SetUserInfo failed");
+ }
+ return true;
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("SetUserInfo%s level %u failed - %s\n",
+ use_setinfo2 ? "2":"", level, nt_errstr(status));
+ ret = false;
+ } else {
+ if (level != 21) {
+ *password = newpass;
+ }
+ }
+
+ return ret;
+}
+
static bool test_SetAliasInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
struct policy_handle *handle)
{
NTSTATUS status;
struct samr_SetAliasInfo r;
struct samr_QueryAliasInfo q;
+ union samr_AliasInfo *info;
uint16_t levels[] = {2, 3};
int i;
bool ret = true;
@@ -826,6 +1034,7 @@ static bool test_SetAliasInfo(struct dcerpc_pipe *p, struct torture_context *tct
q.in.alias_handle = handle;
q.in.level = levels[i];
+ q.out.info = &info;
status = dcerpc_samr_QueryAliasInfo(p, tctx, &q);
if (!NT_STATUS_IS_OK(status)) {
@@ -842,11 +1051,13 @@ static bool test_GetGroupsForUser(struct dcerpc_pipe *p, struct torture_context
struct policy_handle *user_handle)
{
struct samr_GetGroupsForUser r;
+ struct samr_RidWithAttributeArray *rids = NULL;
NTSTATUS status;
torture_comment(tctx, "testing GetGroupsForUser\n");
r.in.user_handle = user_handle;
+ r.out.rids = &rids;
status = dcerpc_samr_GetGroupsForUser(p, tctx, &r);
torture_assert_ntstatus_ok(tctx, status, "GetGroupsForUser");
@@ -860,8 +1071,11 @@ static bool test_GetDomPwInfo(struct dcerpc_pipe *p, struct torture_context *tct
{
NTSTATUS status;
struct samr_GetDomPwInfo r;
+ struct samr_PwInfo info;
r.in.domain_name = domain_name;
+ r.out.info = &info;
+
torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
@@ -893,10 +1107,12 @@ static bool test_GetUserPwInfo(struct dcerpc_pipe *p, struct torture_context *tc
{
NTSTATUS status;
struct samr_GetUserPwInfo r;
+ struct samr_PwInfo info;
torture_comment(tctx, "Testing GetUserPwInfo\n");
r.in.user_handle = handle;
+ r.out.info = &info;
status = dcerpc_samr_GetUserPwInfo(p, tctx, &r);
torture_assert_ntstatus_ok(tctx, status, "GetUserPwInfo");
@@ -911,15 +1127,18 @@ static NTSTATUS test_LookupName(struct dcerpc_pipe *p, struct torture_context *t
NTSTATUS status;
struct samr_LookupNames n;
struct lsa_String sname[2];
+ struct samr_Ids rids, types;
init_lsa_String(&sname[0], name);
n.in.domain_handle = domain_handle;
n.in.num_names = 1;
n.in.names = sname;
+ n.out.rids = &rids;
+ n.out.types = &types;
status = dcerpc_samr_LookupNames(p, tctx, &n);
if (NT_STATUS_IS_OK(status)) {
- *rid = n.out.rids.ids[0];
+ *rid = n.out.rids->ids[0];
} else {
return status;
}
@@ -1071,6 +1290,7 @@ static bool test_ChangePasswordUser(struct dcerpc_pipe *p, struct torture_contex
char *newpass;
struct samr_GetUserPwInfo pwp;
+ struct samr_PwInfo info;
int policy_min_pw_len = 0;
status = test_OpenUser_byname(p, tctx, handle, acct_name, &user_handle);
@@ -1078,10 +1298,11 @@ static bool test_ChangePasswordUser(struct dcerpc_pipe *p, struct torture_contex
return false;
}
pwp.in.user_handle = &user_handle;
+ pwp.out.info = &info;
status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
if (NT_STATUS_IS_OK(status)) {
- policy_min_pw_len = pwp.out.info.min_password_length;
+ policy_min_pw_len = pwp.out.info->min_password_length;
}
newpass = samr_rand_pass(tctx, policy_min_pw_len);
@@ -1346,12 +1567,14 @@ static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p, struct torture_co
uint8_t old_lm_hash[16], new_lm_hash[16];
struct samr_GetDomPwInfo dom_pw_info;
+ struct samr_PwInfo info;
int policy_min_pw_len = 0;
struct lsa_String domain_name;
domain_name.string = "";
dom_pw_info.in.domain_name = &domain_name;
+ dom_pw_info.out.info = &info;
torture_comment(tctx, "Testing OemChangePasswordUser2\n");
@@ -1362,7 +1585,7 @@ static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p, struct torture_co
status = dcerpc_samr_GetDomPwInfo(p, tctx, &dom_pw_info);
if (NT_STATUS_IS_OK(status)) {
- policy_min_pw_len = dom_pw_info.out.info.min_password_length;
+ policy_min_pw_len = dom_pw_info.out.info->min_password_length;
}
newpass = samr_rand_pass(tctx, policy_min_pw_len);
@@ -1515,11 +1738,13 @@ static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_conte
uint8_t old_lm_hash[16], new_lm_hash[16];
struct samr_GetDomPwInfo dom_pw_info;
+ struct samr_PwInfo info;
struct lsa_String domain_name;
domain_name.string = "";
dom_pw_info.in.domain_name = &domain_name;
+ dom_pw_info.out.info = &info;
torture_comment(tctx, "Testing ChangePasswordUser2 on %s\n", acct_name);
@@ -1531,7 +1756,7 @@ static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_conte
int policy_min_pw_len = 0;
status = dcerpc_samr_GetDomPwInfo(p, tctx, &dom_pw_info);
if (NT_STATUS_IS_OK(status)) {
- policy_min_pw_len = dom_pw_info.out.info.min_password_length;
+ policy_min_pw_len = dom_pw_info.out.info->min_password_length;
}
newpass = samr_rand_pass(tctx, policy_min_pw_len);
@@ -1594,6 +1819,8 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct
uint8_t old_nt_hash[16], new_nt_hash[16];
uint8_t old_lm_hash[16], new_lm_hash[16];
NTTIME t;
+ struct samr_DomInfo1 *dominfo = NULL;
+ struct samr_ChangeReject *reject = NULL;
torture_comment(tctx, "Testing ChangePasswordUser3\n");
@@ -1641,6 +1868,8 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct
r.in.lm_password = &lm_pass;
r.in.lm_verifier = &lm_verifier;
r.in.password3 = NULL;
+ r.out.dominfo = &dominfo;
+ r.out.reject = &reject;
status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) &&
@@ -1670,6 +1899,8 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct
r.in.lm_password = &lm_pass;
r.in.lm_verifier = &lm_verifier;
r.in.password3 = NULL;
+ r.out.dominfo = &dominfo;
+ r.out.reject = &reject;
status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) &&
@@ -1712,21 +1943,23 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct
r.in.lm_password = &lm_pass;
r.in.lm_verifier = &lm_verifier;
r.in.password3 = NULL;
+ r.out.dominfo = &dominfo;
+ r.out.reject = &reject;
unix_to_nt_time(&t, time(NULL));
status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
- && r.out.dominfo
- && r.out.reject
+ && dominfo
+ && reject
&& handle_reject_reason
- && (!null_nttime(last_password_change) || !r.out.dominfo->min_password_age)) {
- if (r.out.dominfo->password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE ) {
+ && (!null_nttime(last_password_change) || !dominfo->min_password_age)) {
+ if (dominfo->password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE ) {
- if (r.out.reject && (r.out.reject->reason != SAMR_REJECT_OTHER)) {
+ if (reject && (reject->reason != SAMR_REJECT_OTHER)) {
printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
- SAMR_REJECT_OTHER, r.out.reject->reason);
+ SAMR_REJECT_OTHER, reject->reason);
return false;
}
}
@@ -1740,54 +1973,54 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct
Guenther */
- if ((r.out.dominfo->min_password_age > 0) && !null_nttime(last_password_change) &&
- (last_password_change + r.out.dominfo->min_password_age > t)) {
+ if ((dominfo->min_password_age > 0) && !null_nttime(last_password_change) &&
+ (last_password_change + dominfo->min_password_age > t)) {
- if (r.out.reject->reason != SAMR_REJECT_OTHER) {
+ if (reject->reason != SAMR_REJECT_OTHER) {
printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
- SAMR_REJECT_OTHER, r.out.reject->reason);
+ SAMR_REJECT_OTHER, reject->reason);
return false;
}
- } else if ((r.out.dominfo->min_password_length > 0) &&
- (strlen(newpass) < r.out.dominfo->min_password_length)) {
+ } else if ((dominfo->min_password_length > 0) &&
+ (strlen(newpass) < dominfo->min_password_length)) {
- if (r.out.reject->reason != SAMR_REJECT_TOO_SHORT) {
+ if (reject->reason != SAMR_REJECT_TOO_SHORT) {
printf("expected SAMR_REJECT_TOO_SHORT (%d), got %d\n",
- SAMR_REJECT_TOO_SHORT, r.out.reject->reason);
+ SAMR_REJECT_TOO_SHORT, reject->reason);
return false;
}
- } else if ((r.out.dominfo->password_history_length > 0) &&
+ } else if ((dominfo->password_history_length > 0) &&
strequal(oldpass, newpass)) {
- if (r.out.reject->reason != SAMR_REJECT_IN_HISTORY) {
+ if (reject->reason != SAMR_REJECT_IN_HISTORY) {
printf("expected SAMR_REJECT_IN_HISTORY (%d), got %d\n",
- SAMR_REJECT_IN_HISTORY, r.out.reject->reason);
+ SAMR_REJECT_IN_HISTORY, reject->reason);
return false;
}
- } else if (r.out.dominfo->password_properties & DOMAIN_PASSWORD_COMPLEX) {
+ } else if (dominfo->password_properties & DOMAIN_PASSWORD_COMPLEX) {
- if (r.out.reject->reason != SAMR_REJECT_COMPLEXITY) {
+ if (reject->reason != SAMR_REJECT_COMPLEXITY) {
printf("expected SAMR_REJECT_COMPLEXITY (%d), got %d\n",
- SAMR_REJECT_COMPLEXITY, r.out.reject->reason);
+ SAMR_REJECT_COMPLEXITY, reject->reason);
return false;
}
}
- if (r.out.reject->reason == SAMR_REJECT_TOO_SHORT) {
+ if (reject->reason == SAMR_REJECT_TOO_SHORT) {
/* retry with adjusted size */
return test_ChangePasswordUser3(p, tctx, account_string,
- r.out.dominfo->min_password_length,
+ dominfo->min_password_length,
password, NULL, 0, false);
}
} else if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
- if (r.out.reject && r.out.reject->reason != SAMR_REJECT_OTHER) {
+ if (reject && reject->reason != SAMR_REJECT_OTHER) {
printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
- SAMR_REJECT_OTHER, r.out.reject->reason);
+ SAMR_REJECT_OTHER, reject->reason);
return false;
}
/* Perhaps the server has a 'min password age' set? */
@@ -1823,6 +2056,8 @@ bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_contex
char *oldpass;
uint8_t old_nt_hash[16], new_nt_hash[16];
NTTIME t;
+ struct samr_DomInfo1 *dominfo = NULL;
+ struct samr_ChangeReject *reject = NULL;
new_random_pass = samr_very_rand_pass(tctx, 128);
@@ -1889,15 +2124,17 @@ bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_contex
r.in.lm_password = NULL;
r.in.lm_verifier = NULL;
r.in.password3 = NULL;
+ r.out.dominfo = &dominfo;
+ r.out.reject = &reject;
unix_to_nt_time(&t, time(NULL));
status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
- if (r.out.reject && r.out.reject->reason != SAMR_REJECT_OTHER) {
+ if (reject && reject->reason != SAMR_REJECT_OTHER) {
printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
- SAMR_REJECT_OTHER, r.out.reject->reason);
+ SAMR_REJECT_OTHER, reject->reason);
return false;
}
/* Perhaps the server has a 'min password age' set? */
@@ -1925,15 +2162,17 @@ bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_contex
r.in.lm_password = NULL;
r.in.lm_verifier = NULL;
r.in.password3 = NULL;
+ r.out.dominfo = &dominfo;
+ r.out.reject = &reject;
unix_to_nt_time(&t, time(NULL));
status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
- if (r.out.reject && r.out.reject->reason != SAMR_REJECT_OTHER) {
+ if (reject && reject->reason != SAMR_REJECT_OTHER) {
printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
- SAMR_REJECT_OTHER, r.out.reject->reason);
+ SAMR_REJECT_OTHER, reject->reason);
return false;
}
/* Perhaps the server has a 'min password age' set? */
@@ -2051,6 +2290,486 @@ static bool test_TestPrivateFunctionsUser(struct dcerpc_pipe *p, struct torture_
return true;
}
+static bool test_QueryUserInfo_pwdlastset(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
+ struct policy_handle *handle,
+ bool use_info2,
+ NTTIME *pwdlastset)
+{
+ NTSTATUS status;
+ uint16_t levels[] = { /* 3, */ 5, 21 };
+ int i;
+ NTTIME pwdlastset3 = 0;
+ NTTIME pwdlastset5 = 0;
+ NTTIME pwdlastset21 = 0;
+
+ torture_comment(tctx, "Testing QueryUserInfo%s level 5 and 21 call ",
+ use_info2 ? "2":"");
+
+ for (i=0; i<ARRAY_SIZE(levels); i++) {
+
+ struct samr_QueryUserInfo r;
+ struct samr_QueryUserInfo2 r2;
+ union samr_UserInfo *info;
+
+ if (use_info2) {
+ r2.in.user_handle = handle;
+ r2.in.level = levels[i];
+ r2.out.info = &info;
+ status = dcerpc_samr_QueryUserInfo2(p, tctx, &r2);
+
+ } else {
+ r.in.user_handle = handle;
+ r.in.level = levels[i];
+ r.out.info = &info;
+ status = dcerpc_samr_QueryUserInfo(p, tctx, &r);
+ }
+
+ if (!NT_STATUS_IS_OK(status) &&
+ !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
+ printf("QueryUserInfo%s level %u failed - %s\n",
+ use_info2 ? "2":"", levels[i], nt_errstr(status));
+ return false;
+ }
+
+ switch (levels[i]) {
+ case 3:
+ pwdlastset3 = info->info3.last_password_change;
+ break;
+ case 5:
+ pwdlastset5 = info->info5.last_password_change;
+ break;
+ case 21:
+ pwdlastset21 = info->info21.last_password_change;
+ break;
+ default:
+ return false;
+ }
+ }
+ /* torture_assert_int_equal(tctx, pwdlastset3, pwdlastset5,
+ "pwdlastset mixup"); */
+ torture_assert_int_equal(tctx, pwdlastset5, pwdlastset21,
+ "pwdlastset mixup");
+
+ *pwdlastset = pwdlastset21;
+
+ torture_comment(tctx, "(pwdlastset: %lld)\n", *pwdlastset);
+
+ return true;
+}
+
+static bool test_SetPassword_level(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
+ struct policy_handle *handle,
+ uint16_t level,
+ uint32_t fields_present,
+ uint8_t password_expired,
+ NTSTATUS expected_error,
+ bool use_setinfo2,
+ char **password,
+ bool use_queryinfo2,
+ NTTIME *pwdlastset)
+{
+ const char *fields = NULL;
+ bool ret = true;
+
+ switch (level) {
+ case 21:
+ case 23:
+ case 25:
+ fields = talloc_asprintf(tctx, "(fields_present: 0x%08x)",
+ fields_present);
+ break;
+ default:
+ break;
+ }
+
+ torture_comment(tctx, "Testing SetUserInfo%s level %d call "
+ "(password_expired: %d) %s\n",
+ use_setinfo2 ? "2":"", level, password_expired,
+ fields ? fields : "");
+
+ switch (level) {
+ case 21:
+ case 23:
+ case 24:
+ case 25:
+ case 26:
+ if (!test_SetUserPass_level_ex(p, tctx, handle, level,
+ fields_present,
+ password,
+ password_expired,
+ use_setinfo2,
+ expected_error)) {
+ ret = false;
+ }
+ break;
+ default:
+ return false;
+ }
+
+ if (!test_QueryUserInfo_pwdlastset(p, tctx, handle,
+ use_queryinfo2,
+ pwdlastset)) {
+ ret = false;
+ }
+
+ return ret;
+}
+
+static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
+ uint32_t acct_flags,
+ struct policy_handle *handle,
+ char **password)
+{
+ int i, s = 0, q = 0;
+ bool ret = true;
+ int delay = 500000;
+ bool set_levels[] = { false, true };
+ bool query_levels[] = { false, true };
+
+ 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_PASSWORD |
+ SAMR_FIELD_PASSWORD2 |
+ SAMR_FIELD_LAST_PWD_CHANGE,
+ .query_info2 = false,
+ .set_error = NT_STATUS_ACCESS_DENIED
+#endif
+
+ /* 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_PASSWORD |
+ SAMR_FIELD_PASSWORD2,
+ .set_error = NT_STATUS_ACCESS_DENIED
+ },{
+ .level = 23,
+ .password_expired_nonzero = 1,
+ .fields_present = SAMR_FIELD_LAST_PWD_CHANGE |
+ SAMR_FIELD_PASSWORD |
+ SAMR_FIELD_PASSWORD2 |
+ SAMR_FIELD_EXPIRED_FLAG,
+ .set_error = NT_STATUS_ACCESS_DENIED
+ },{
+ .level = 23,
+ .password_expired_nonzero = 1,
+ .fields_present = SAMR_FIELD_PASSWORD |
+ SAMR_FIELD_PASSWORD2 |
+ SAMR_FIELD_EXPIRED_FLAG
+ },{
+ .level = 23,
+ .password_expired_nonzero = 1,
+ .fields_present = SAMR_FIELD_PASSWORD |
+ SAMR_FIELD_PASSWORD2,
+ },{
+ .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
+ },{
+
+ /* level 24 */
+
+ .level = 24,
+ .password_expired_nonzero = 1
+ },{
+ .level = 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_PASSWORD |
+ SAMR_FIELD_PASSWORD2 |
+ SAMR_FIELD_EXPIRED_FLAG
+ },{
+ .level = 25,
+ .password_expired_nonzero = 1,
+ .fields_present = SAMR_FIELD_PASSWORD |
+ SAMR_FIELD_PASSWORD2,
+ },{
+ .level = 25,
+ .password_expired_nonzero = 1,
+ .fields_present = SAMR_FIELD_COMMENT,
+ },{
+
+ /* level 26 */
+
+ .level = 26,
+ .password_expired_nonzero = 1
+ },{
+ .level = 26,
+ .password_expired_nonzero = 24
+ }
+ };
+
+ if (torture_setting_bool(tctx, "samba3", false)) {
+ delay = 1000000;
+ printf("Samba3 has second granularity, setting delay to: %d\n",
+ delay);
+ }
+
+ /* set to 1 to enable testing for all possible opcode
+ (SetUserInfo, SetUserInfo2, QueryUserInfo, QueryUserInfo2)
+ combinations */
+#if 0
+#define TEST_SET_LEVELS 1
+#define TEST_QUERY_LEVELS 1
+#endif
+ for (i=0; i<ARRAY_SIZE(pwd_tests); i++) {
+#ifdef TEST_SET_LEVELS
+ for (s=0; s<ARRAY_SIZE(set_levels); s++) {
+#endif
+#ifdef TEST_QUERY_LEVELS
+ for (q=0; q<ARRAY_SIZE(query_levels); q++) {
+#endif
+ NTTIME pwdlastset_old = 0;
+ NTTIME pwdlastset_new = 0;
+
+ torture_comment(tctx, "------------------------------\n"
+ "Testing pwdLastSet attribute for flags: 0x%08x "
+ "(s: %d (l: %d), q: %d)\n",
+ acct_flags, s, pwd_tests[i].level, q);
+
+ /* set #1 */
+
+ /* 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,
+ pwd_tests[i].password_expired_nonzero,
+ pwd_tests[i].set_error,
+ set_levels[s],
+ password,
+ query_levels[q],
+ &pwdlastset_old)) {
+ ret = false;
+ }
+
+ if (!NT_STATUS_IS_OK(pwd_tests[i].set_error)) {
+ /* skipping on expected failure */
+ continue;
+ }
+
+ /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
+ * set without the SAMR_FIELD_EXPIRED_FLAG */
+
+ switch (pwd_tests[i].level) {
+ case 21:
+ case 23:
+ case 25:
+ if ((pwdlastset_new != 0) &&
+ !(pwd_tests[i].fields_present & 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 "
+ "been set\n");
+ break;
+ }
+ default:
+ if (pwdlastset_new != 0) {
+ torture_warning(tctx, "pwdLastSet test failed: "
+ "expected pwdLastSet 0 but got %lld\n",
+ pwdlastset_old);
+ ret = false;
+ }
+ break;
+ }
+
+ usleep(delay);
+
+ /* set #2 */
+
+ /* 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,
+ 0,
+ pwd_tests[i].set_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:
+
+ /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
+ * password has been changed, old and new pwdlastset
+ * need to be the same value */
+
+ if (!(pwd_tests[i].fields_present & SAMR_FIELD_EXPIRED_FLAG) &&
+ !((pwd_tests[i].fields_present & SAMR_FIELD_PASSWORD) ||
+ (pwd_tests[i].fields_present & SAMR_FIELD_PASSWORD2)))
+ {
+ 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;
+ }
+ }
+
+ pwdlastset_old = pwdlastset_new;
+
+ usleep(delay);
+
+ /* 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,
+ pwd_tests[i].password_expired_nonzero,
+ pwd_tests[i].set_error,
+ set_levels[s],
+ password,
+ query_levels[q],
+ &pwdlastset_new)) {
+ ret = false;
+ }
+
+ /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
+ * set without the SAMR_FIELD_EXPIRED_FLAG */
+
+ switch (pwd_tests[i].level) {
+ case 21:
+ case 23:
+ case 25:
+ if ((pwdlastset_new != 0) &&
+ !(pwd_tests[i].fields_present & 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 "
+ "been set\n");
+ break;
+ }
+
+ /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
+ * password has been changed, old and new pwdlastset
+ * need to be the same value */
+
+ if (!(pwd_tests[i].fields_present & SAMR_FIELD_EXPIRED_FLAG) &&
+ !((pwd_tests[i].fields_present & SAMR_FIELD_PASSWORD) ||
+ (pwd_tests[i].fields_present & SAMR_FIELD_PASSWORD2)))
+ {
+ 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 pwdLastSet 0, got %lld\n",
+ pwdlastset_old);
+ ret = false;
+ }
+ break;
+ }
+#ifdef TEST_QUERY_LEVELS
+ }
+#endif
+#ifdef TEST_SET_LEVELS
+ }
+#endif
+ }
+
+#undef TEST_SET_LEVELS
+#undef TEST_QUERY_LEVELS
+
+ return ret;
+}
static bool test_user_ops(struct dcerpc_pipe *p,
struct torture_context *tctx,
@@ -2061,6 +2780,7 @@ static bool test_user_ops(struct dcerpc_pipe *p,
{
char *password = NULL;
struct samr_QueryUserInfo q;
+ union samr_UserInfo *info;
NTSTATUS status;
bool ret = true;
@@ -2143,7 +2863,7 @@ static bool test_user_ops(struct dcerpc_pipe *p,
ret = false;
}
}
-
+
for (i = 0; password_fields[i]; i++) {
if (!test_SetUserPass_23(p, tctx, user_handle, password_fields[i], &password)) {
ret = false;
@@ -2176,6 +2896,7 @@ static bool test_user_ops(struct dcerpc_pipe *p,
q.in.user_handle = user_handle;
q.in.level = 5;
+ q.out.info = &info;
status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
if (!NT_STATUS_IS_OK(status)) {
@@ -2184,20 +2905,37 @@ static bool test_user_ops(struct dcerpc_pipe *p,
ret = false;
} else {
uint32_t expected_flags = (base_acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
- if ((q.out.info->info5.acct_flags) != expected_flags) {
+ if ((info->info5.acct_flags) != expected_flags) {
printf("QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
- q.out.info->info5.acct_flags,
+ info->info5.acct_flags,
expected_flags);
ret = false;
}
- if (q.out.info->info5.rid != rid) {
+ if (info->info5.rid != rid) {
printf("QuerUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
- q.out.info->info5.rid, rid);
+ info->info5.rid, rid);
}
}
break;
+
+ case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
+
+ /* test last password change timestamp behaviour */
+ if (!test_SetPassword_pwdlastset(p, tctx, base_acct_flags,
+ user_handle, &password)) {
+ ret = false;
+ }
+
+ if (ret == true) {
+ torture_comment(tctx, "pwdLastSet test succeeded\n");
+ } else {
+ torture_warning(tctx, "pwdLastSet test failed\n");
+ }
+
+ break;
+
case TORTURE_SAMR_OTHER:
/* We just need the account to exist */
break;
@@ -2481,6 +3219,7 @@ static bool test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
/* set samr_SetDomainInfo level 1 with min_length 5 */
{
struct samr_QueryDomainInfo r;
+ union samr_DomainInfo *info = NULL;
struct samr_SetDomainInfo s;
uint16_t len_old, len;
uint32_t pwd_prop_old;
@@ -2491,6 +3230,7 @@ static bool test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
r.in.domain_handle = domain_handle;
r.in.level = 1;
+ r.out.info = &info;
printf("testing samr_QueryDomainInfo level 1\n");
status = dcerpc_samr_QueryDomainInfo(p, mem_ctx, &r);
@@ -2500,7 +3240,7 @@ static bool test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
s.in.domain_handle = domain_handle;
s.in.level = 1;
- s.in.info = r.out.info;
+ s.in.info = info;
/* remember the old min length, so we can reset it */
len_old = s.in.info->info1.min_password_length;
@@ -2540,13 +3280,17 @@ static bool test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
NTSTATUS status;
struct samr_OpenUser r;
struct samr_QueryUserInfo q;
+ union samr_UserInfo *info;
struct samr_LookupNames n;
struct policy_handle user_handle;
+ struct samr_Ids rids, types;
n.in.domain_handle = domain_handle;
n.in.num_names = 1;
n.in.names = talloc_array(mem_ctx, struct lsa_String, 1);
n.in.names[0].string = acct_name;
+ n.out.rids = &rids;
+ n.out.types = &types;
status = dcerpc_samr_LookupNames(p, mem_ctx, &n);
if (!NT_STATUS_IS_OK(status)) {
@@ -2556,17 +3300,18 @@ static bool test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
r.in.domain_handle = domain_handle;
r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
- r.in.rid = n.out.rids.ids[0];
+ r.in.rid = n.out.rids->ids[0];
r.out.user_handle = &user_handle;
status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
if (!NT_STATUS_IS_OK(status)) {
- printf("OpenUser(%u) failed - %s\n", n.out.rids.ids[0], nt_errstr(status));
+ printf("OpenUser(%u) failed - %s\n", n.out.rids->ids[0], nt_errstr(status));
return false;
}
q.in.user_handle = &user_handle;
q.in.level = 5;
+ q.out.info = &info;
status = dcerpc_samr_QueryUserInfo(p, mem_ctx, &q);
if (!NT_STATUS_IS_OK(status)) {
@@ -2577,7 +3322,7 @@ static bool test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
printf("calling test_ChangePasswordUser3 with too early password change\n");
if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, NULL,
- q.out.info->info5.last_password_change, true)) {
+ info->info5.last_password_change, true)) {
ret = false;
}
}
@@ -2607,6 +3352,7 @@ static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
NTSTATUS status;
struct samr_CreateUser r;
struct samr_QueryUserInfo q;
+ union samr_UserInfo *info;
struct samr_DeleteUser d;
uint32_t rid;
@@ -2654,6 +3400,7 @@ static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
} else {
q.in.user_handle = &user_handle;
q.in.level = 16;
+ q.out.info = &info;
status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q);
if (!NT_STATUS_IS_OK(status)) {
@@ -2661,9 +3408,9 @@ static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
q.in.level, nt_errstr(status));
ret = false;
} else {
- if ((q.out.info->info16.acct_flags & acct_flags) != acct_flags) {
+ if ((info->info16.acct_flags & acct_flags) != acct_flags) {
printf("QuerUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
- q.out.info->info16.acct_flags,
+ info->info16.acct_flags,
acct_flags);
ret = false;
}
@@ -2705,6 +3452,7 @@ static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx
NTSTATUS status;
struct samr_CreateUser2 r;
struct samr_QueryUserInfo q;
+ union samr_UserInfo *info;
struct samr_DeleteUser d;
struct policy_handle user_handle;
uint32_t rid;
@@ -2783,6 +3531,7 @@ static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx
if (NT_STATUS_IS_OK(status)) {
q.in.user_handle = &user_handle;
q.in.level = 5;
+ q.out.info = &info;
status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q);
if (!NT_STATUS_IS_OK(status)) {
@@ -2794,31 +3543,31 @@ static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx
if (acct_flags == ACB_NORMAL) {
expected_flags |= ACB_PW_EXPIRED;
}
- if ((q.out.info->info5.acct_flags) != expected_flags) {
+ if ((info->info5.acct_flags) != expected_flags) {
printf("QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
- q.out.info->info5.acct_flags,
+ info->info5.acct_flags,
expected_flags);
ret = false;
}
switch (acct_flags) {
case ACB_SVRTRUST:
- if (q.out.info->info5.primary_gid != DOMAIN_RID_DCS) {
+ if (info->info5.primary_gid != DOMAIN_RID_DCS) {
printf("QuerUserInfo level 5: DC should have had Primary Group %d, got %d\n",
- DOMAIN_RID_DCS, q.out.info->info5.primary_gid);
+ DOMAIN_RID_DCS, info->info5.primary_gid);
ret = false;
}
break;
case ACB_WSTRUST:
- if (q.out.info->info5.primary_gid != DOMAIN_RID_DOMAIN_MEMBERS) {
+ if (info->info5.primary_gid != DOMAIN_RID_DOMAIN_MEMBERS) {
printf("QuerUserInfo level 5: Domain Member should have had Primary Group %d, got %d\n",
- DOMAIN_RID_DOMAIN_MEMBERS, q.out.info->info5.primary_gid);
+ DOMAIN_RID_DOMAIN_MEMBERS, info->info5.primary_gid);
ret = false;
}
break;
case ACB_NORMAL:
- if (q.out.info->info5.primary_gid != DOMAIN_RID_USERS) {
+ if (info->info5.primary_gid != DOMAIN_RID_USERS) {
printf("QuerUserInfo level 5: Users should have had Primary Group %d, got %d\n",
- DOMAIN_RID_USERS, q.out.info->info5.primary_gid);
+ DOMAIN_RID_USERS, info->info5.primary_gid);
ret = false;
}
break;
@@ -2852,6 +3601,7 @@ static bool test_QueryAliasInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
{
NTSTATUS status;
struct samr_QueryAliasInfo r;
+ union samr_AliasInfo *info;
uint16_t levels[] = {1, 2, 3};
int i;
bool ret = true;
@@ -2861,6 +3611,7 @@ static bool test_QueryAliasInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
r.in.alias_handle = handle;
r.in.level = levels[i];
+ r.out.info = &info;
status = dcerpc_samr_QueryAliasInfo(p, mem_ctx, &r);
if (!NT_STATUS_IS_OK(status)) {
@@ -2878,6 +3629,7 @@ static bool test_QueryGroupInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
{
NTSTATUS status;
struct samr_QueryGroupInfo r;
+ union samr_GroupInfo *info;
uint16_t levels[] = {1, 2, 3, 4, 5};
int i;
bool ret = true;
@@ -2887,6 +3639,7 @@ static bool test_QueryGroupInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
r.in.group_handle = handle;
r.in.level = levels[i];
+ r.out.info = &info;
status = dcerpc_samr_QueryGroupInfo(p, mem_ctx, &r);
if (!NT_STATUS_IS_OK(status)) {
@@ -2904,11 +3657,13 @@ static bool test_QueryGroupMember(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
{
NTSTATUS status;
struct samr_QueryGroupMember r;
+ struct samr_RidTypeArray *rids = NULL;
bool ret = true;
printf("Testing QueryGroupMember\n");
r.in.group_handle = handle;
+ r.out.rids = &rids;
status = dcerpc_samr_QueryGroupMember(p, mem_ctx, &r);
if (!NT_STATUS_IS_OK(status)) {
@@ -2925,6 +3680,7 @@ static bool test_SetGroupInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
{
NTSTATUS status;
struct samr_QueryGroupInfo r;
+ union samr_GroupInfo *info;
struct samr_SetGroupInfo s;
uint16_t levels[] = {1, 2, 3, 4};
uint16_t set_ok[] = {0, 1, 1, 1};
@@ -2936,6 +3692,7 @@ static bool test_SetGroupInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
r.in.group_handle = handle;
r.in.level = levels[i];
+ r.out.info = &info;
status = dcerpc_samr_QueryGroupInfo(p, mem_ctx, &r);
if (!NT_STATUS_IS_OK(status)) {
@@ -2948,7 +3705,7 @@ static bool test_SetGroupInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
s.in.group_handle = handle;
s.in.level = levels[i];
- s.in.info = r.out.info;
+ s.in.info = *r.out.info;
#if 0
/* disabled this, as it changes the name only from the point of view of samr,
@@ -2990,6 +3747,7 @@ static bool test_QueryUserInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
{
NTSTATUS status;
struct samr_QueryUserInfo r;
+ union samr_UserInfo *info;
uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 16, 17, 20, 21};
int i;
@@ -3000,6 +3758,7 @@ static bool test_QueryUserInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
r.in.user_handle = handle;
r.in.level = levels[i];
+ r.out.info = &info;
status = dcerpc_samr_QueryUserInfo(p, mem_ctx, &r);
if (!NT_STATUS_IS_OK(status)) {
@@ -3017,6 +3776,7 @@ static bool test_QueryUserInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
{
NTSTATUS status;
struct samr_QueryUserInfo2 r;
+ union samr_UserInfo *info;
uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 16, 17, 20, 21};
int i;
@@ -3027,6 +3787,7 @@ static bool test_QueryUserInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
r.in.user_handle = handle;
r.in.level = levels[i];
+ r.out.info = &info;
status = dcerpc_samr_QueryUserInfo2(p, mem_ctx, &r);
if (!NT_STATUS_IS_OK(status)) {
@@ -3174,6 +3935,7 @@ static bool check_mask(struct dcerpc_pipe *p, struct torture_context *tctx,
NTSTATUS status;
struct samr_OpenUser r;
struct samr_QueryUserInfo q;
+ union samr_UserInfo *info;
struct policy_handle user_handle;
bool ret = true;
@@ -3192,6 +3954,7 @@ static bool check_mask(struct dcerpc_pipe *p, struct torture_context *tctx,
q.in.user_handle = &user_handle;
q.in.level = 16;
+ q.out.info = &info;
status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
if (!NT_STATUS_IS_OK(status)) {
@@ -3199,9 +3962,9 @@ static bool check_mask(struct dcerpc_pipe *p, struct torture_context *tctx,
nt_errstr(status));
ret = false;
} else {
- if ((acct_flag_mask & q.out.info->info16.acct_flags) == 0) {
+ if ((acct_flag_mask & info->info16.acct_flags) == 0) {
printf("Server failed to filter for 0x%x, allowed 0x%x (%d) on EnumDomainUsers\n",
- acct_flag_mask, q.out.info->info16.acct_flags, rid);
+ acct_flag_mask, info->info16.acct_flags, rid);
ret = false;
}
}
@@ -3223,6 +3986,11 @@ static bool test_EnumDomainUsers(struct dcerpc_pipe *p, struct torture_context *
bool ret = true;
struct samr_LookupNames n;
struct samr_LookupRids lr ;
+ struct lsa_Strings names;
+ struct samr_Ids rids, types;
+ struct samr_SamArray *sam = NULL;
+ uint32_t num_entries = 0;
+
uint32_t masks[] = {ACB_NORMAL, ACB_DOMTRUST, ACB_WSTRUST,
ACB_DISABLED, ACB_NORMAL | ACB_DISABLED,
ACB_SVRTRUST | ACB_DOMTRUST | ACB_WSTRUST,
@@ -3236,6 +4004,8 @@ static bool test_EnumDomainUsers(struct dcerpc_pipe *p, struct torture_context *
r.in.acct_flags = mask = masks[mask_idx];
r.in.max_size = (uint32_t)-1;
r.out.resume_handle = &resume_handle;
+ r.out.num_entries = &num_entries;
+ r.out.sam = &sam;
status = dcerpc_samr_EnumDomainUsers(p, tctx, &r);
if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
@@ -3244,18 +4014,18 @@ static bool test_EnumDomainUsers(struct dcerpc_pipe *p, struct torture_context *
return false;
}
- torture_assert(tctx, r.out.sam, "EnumDomainUsers failed: r.out.sam unexpectedly NULL");
+ torture_assert(tctx, sam, "EnumDomainUsers failed: r.out.sam unexpectedly NULL");
- if (r.out.sam->count == 0) {
+ if (sam->count == 0) {
continue;
}
- for (i=0;i<r.out.sam->count;i++) {
+ for (i=0;i<sam->count;i++) {
if (mask) {
- if (!check_mask(p, tctx, handle, r.out.sam->entries[i].idx, mask)) {
+ if (!check_mask(p, tctx, handle, sam->entries[i].idx, mask)) {
ret = false;
}
- } else if (!test_OpenUser(p, tctx, handle, r.out.sam->entries[i].idx)) {
+ } else if (!test_OpenUser(p, tctx, handle, sam->entries[i].idx)) {
ret = false;
}
}
@@ -3263,10 +4033,12 @@ static bool test_EnumDomainUsers(struct dcerpc_pipe *p, struct torture_context *
printf("Testing LookupNames\n");
n.in.domain_handle = handle;
- n.in.num_names = r.out.sam->count;
- n.in.names = talloc_array(tctx, struct lsa_String, r.out.sam->count);
- for (i=0;i<r.out.sam->count;i++) {
- n.in.names[i].string = r.out.sam->entries[i].name.string;
+ n.in.num_names = sam->count;
+ n.in.names = talloc_array(tctx, struct lsa_String, sam->count);
+ n.out.rids = &rids;
+ n.out.types = &types;
+ for (i=0;i<sam->count;i++) {
+ n.in.names[i].string = sam->entries[i].name.string;
}
status = dcerpc_samr_LookupNames(p, tctx, &n);
if (!NT_STATUS_IS_OK(status)) {
@@ -3277,10 +4049,12 @@ static bool test_EnumDomainUsers(struct dcerpc_pipe *p, struct torture_context *
printf("Testing LookupRids\n");
lr.in.domain_handle = handle;
- lr.in.num_rids = r.out.sam->count;
- lr.in.rids = talloc_array(tctx, uint32_t, r.out.sam->count);
- for (i=0;i<r.out.sam->count;i++) {
- lr.in.rids[i] = r.out.sam->entries[i].idx;
+ lr.in.num_rids = sam->count;
+ lr.in.rids = talloc_array(tctx, uint32_t, sam->count);
+ lr.out.names = &names;
+ lr.out.types = &types;
+ for (i=0;i<sam->count;i++) {
+ lr.in.rids[i] = sam->entries[i].idx;
}
status = dcerpc_samr_LookupRids(p, tctx, &lr);
torture_assert_ntstatus_ok(tctx, status, "LookupRids");
@@ -3337,6 +4111,8 @@ static bool test_EnumDomainGroups(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
NTSTATUS status;
struct samr_EnumDomainGroups r;
uint32_t resume_handle=0;
+ struct samr_SamArray *sam = NULL;
+ uint32_t num_entries = 0;
int i;
bool ret = true;
@@ -3346,6 +4122,8 @@ static bool test_EnumDomainGroups(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
r.in.resume_handle = &resume_handle;
r.in.max_size = (uint32_t)-1;
r.out.resume_handle = &resume_handle;
+ r.out.num_entries = &num_entries;
+ r.out.sam = &sam;
status = dcerpc_samr_EnumDomainGroups(p, mem_ctx, &r);
if (!NT_STATUS_IS_OK(status)) {
@@ -3353,12 +4131,12 @@ static bool test_EnumDomainGroups(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
return false;
}
- if (!r.out.sam) {
+ if (!sam) {
return false;
}
- for (i=0;i<r.out.sam->count;i++) {
- if (!test_OpenGroup(p, mem_ctx, handle, r.out.sam->entries[i].idx)) {
+ for (i=0;i<sam->count;i++) {
+ if (!test_OpenGroup(p, mem_ctx, handle, sam->entries[i].idx)) {
ret = false;
}
}
@@ -3372,6 +4150,8 @@ static bool test_EnumDomainAliases(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
NTSTATUS status;
struct samr_EnumDomainAliases r;
uint32_t resume_handle=0;
+ struct samr_SamArray *sam = NULL;
+ uint32_t num_entries = 0;
int i;
bool ret = true;
@@ -3379,7 +4159,9 @@ static bool test_EnumDomainAliases(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
r.in.domain_handle = handle;
r.in.resume_handle = &resume_handle;
- r.in.acct_flags = (uint32_t)-1;
+ r.in.max_size = (uint32_t)-1;
+ r.out.sam = &sam;
+ r.out.num_entries = &num_entries;
r.out.resume_handle = &resume_handle;
status = dcerpc_samr_EnumDomainAliases(p, mem_ctx, &r);
@@ -3388,12 +4170,12 @@ static bool test_EnumDomainAliases(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
return false;
}
- if (!r.out.sam) {
+ if (!sam) {
return false;
}
- for (i=0;i<r.out.sam->count;i++) {
- if (!test_OpenAlias(p, mem_ctx, handle, r.out.sam->entries[i].idx)) {
+ for (i=0;i<sam->count;i++) {
+ if (!test_OpenAlias(p, mem_ctx, handle, sam->entries[i].idx)) {
ret = false;
}
}
@@ -3409,14 +4191,19 @@ static bool test_GetDisplayEnumerationIndex(struct dcerpc_pipe *p, TALLOC_CTX *m
bool ret = true;
uint16_t levels[] = {1, 2, 3, 4, 5};
uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
+ struct lsa_String name;
+ uint32_t idx = 0;
int i;
for (i=0;i<ARRAY_SIZE(levels);i++) {
printf("Testing GetDisplayEnumerationIndex level %u\n", levels[i]);
+ init_lsa_String(&name, TEST_ACCOUNT_NAME);
+
r.in.domain_handle = handle;
r.in.level = levels[i];
- init_lsa_String(&r.in.name, TEST_ACCOUNT_NAME);
+ r.in.name = &name;
+ r.out.idx = &idx;
status = dcerpc_samr_GetDisplayEnumerationIndex(p, mem_ctx, &r);
@@ -3428,7 +4215,7 @@ static bool test_GetDisplayEnumerationIndex(struct dcerpc_pipe *p, TALLOC_CTX *m
ret = false;
}
- init_lsa_String(&r.in.name, "zzzzzzzz");
+ init_lsa_String(&name, "zzzzzzzz");
status = dcerpc_samr_GetDisplayEnumerationIndex(p, mem_ctx, &r);
@@ -3450,14 +4237,19 @@ static bool test_GetDisplayEnumerationIndex2(struct dcerpc_pipe *p, TALLOC_CTX *
bool ret = true;
uint16_t levels[] = {1, 2, 3, 4, 5};
uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
+ struct lsa_String name;
+ uint32_t idx = 0;
int i;
for (i=0;i<ARRAY_SIZE(levels);i++) {
printf("Testing GetDisplayEnumerationIndex2 level %u\n", levels[i]);
+ init_lsa_String(&name, TEST_ACCOUNT_NAME);
+
r.in.domain_handle = handle;
r.in.level = levels[i];
- init_lsa_String(&r.in.name, TEST_ACCOUNT_NAME);
+ r.in.name = &name;
+ r.out.idx = &idx;
status = dcerpc_samr_GetDisplayEnumerationIndex2(p, mem_ctx, &r);
if (ok_lvl[i] &&
@@ -3468,7 +4260,7 @@ static bool test_GetDisplayEnumerationIndex2(struct dcerpc_pipe *p, TALLOC_CTX *
ret = false;
}
- init_lsa_String(&r.in.name, "zzzzzzzz");
+ init_lsa_String(&name, "zzzzzzzz");
status = dcerpc_samr_GetDisplayEnumerationIndex2(p, mem_ctx, &r);
if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
@@ -3502,6 +4294,7 @@ static bool test_each_DisplayInfo_user(struct dcerpc_pipe *p, TALLOC_CTX *mem_ct
{
struct samr_OpenUser r;
struct samr_QueryUserInfo q;
+ union samr_UserInfo *info;
struct policy_handle user_handle;
int i, ret = true;
NTSTATUS status;
@@ -3510,16 +4303,16 @@ static bool test_each_DisplayInfo_user(struct dcerpc_pipe *p, TALLOC_CTX *mem_ct
for (i = 0; ; i++) {
switch (querydisplayinfo->in.level) {
case 1:
- if (i >= querydisplayinfo->out.info.info1.count) {
+ if (i >= querydisplayinfo->out.info->info1.count) {
return ret;
}
- r.in.rid = querydisplayinfo->out.info.info1.entries[i].rid;
+ r.in.rid = querydisplayinfo->out.info->info1.entries[i].rid;
break;
case 2:
- if (i >= querydisplayinfo->out.info.info2.count) {
+ if (i >= querydisplayinfo->out.info->info2.count) {
return ret;
}
- r.in.rid = querydisplayinfo->out.info.info2.entries[i].rid;
+ r.in.rid = querydisplayinfo->out.info->info2.entries[i].rid;
break;
case 3:
/* Groups */
@@ -3543,6 +4336,7 @@ static bool test_each_DisplayInfo_user(struct dcerpc_pipe *p, TALLOC_CTX *mem_ct
q.in.user_handle = &user_handle;
q.in.level = 21;
+ q.out.info = &info;
status = dcerpc_samr_QueryUserInfo(p, mem_ctx, &q);
if (!NT_STATUS_IS_OK(status)) {
printf("QueryUserInfo(%u) failed - %s\n", r.in.rid, nt_errstr(status));
@@ -3551,41 +4345,41 @@ static bool test_each_DisplayInfo_user(struct dcerpc_pipe *p, TALLOC_CTX *mem_ct
switch (querydisplayinfo->in.level) {
case 1:
- if (seen_testuser && strcmp(q.out.info->info21.account_name.string, TEST_ACCOUNT_NAME) == 0) {
+ if (seen_testuser && strcmp(info->info21.account_name.string, TEST_ACCOUNT_NAME) == 0) {
*seen_testuser = true;
}
- STRING_EQUAL_QUERY(querydisplayinfo->out.info.info1.entries[i].full_name,
- q.out.info->info21.full_name, q.out.info->info21.account_name);
- STRING_EQUAL_QUERY(querydisplayinfo->out.info.info1.entries[i].account_name,
- q.out.info->info21.account_name, q.out.info->info21.account_name);
- STRING_EQUAL_QUERY(querydisplayinfo->out.info.info1.entries[i].description,
- q.out.info->info21.description, q.out.info->info21.account_name);
- INT_EQUAL_QUERY(querydisplayinfo->out.info.info1.entries[i].rid,
- q.out.info->info21.rid, q.out.info->info21.account_name);
- INT_EQUAL_QUERY(querydisplayinfo->out.info.info1.entries[i].acct_flags,
- q.out.info->info21.acct_flags, q.out.info->info21.account_name);
+ STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].full_name,
+ info->info21.full_name, info->info21.account_name);
+ STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].account_name,
+ info->info21.account_name, info->info21.account_name);
+ STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].description,
+ info->info21.description, info->info21.account_name);
+ INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].rid,
+ info->info21.rid, info->info21.account_name);
+ INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].acct_flags,
+ info->info21.acct_flags, info->info21.account_name);
break;
case 2:
- STRING_EQUAL_QUERY(querydisplayinfo->out.info.info2.entries[i].account_name,
- q.out.info->info21.account_name, q.out.info->info21.account_name);
- STRING_EQUAL_QUERY(querydisplayinfo->out.info.info2.entries[i].description,
- q.out.info->info21.description, q.out.info->info21.account_name);
- INT_EQUAL_QUERY(querydisplayinfo->out.info.info2.entries[i].rid,
- q.out.info->info21.rid, q.out.info->info21.account_name);
- INT_EQUAL_QUERY((querydisplayinfo->out.info.info2.entries[i].acct_flags & ~ACB_NORMAL),
- q.out.info->info21.acct_flags, q.out.info->info21.account_name);
+ STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].account_name,
+ info->info21.account_name, info->info21.account_name);
+ STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].description,
+ info->info21.description, info->info21.account_name);
+ INT_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].rid,
+ info->info21.rid, info->info21.account_name);
+ INT_EQUAL_QUERY((querydisplayinfo->out.info->info2.entries[i].acct_flags & ~ACB_NORMAL),
+ info->info21.acct_flags, info->info21.account_name);
- if (!(querydisplayinfo->out.info.info2.entries[i].acct_flags & ACB_NORMAL)) {
+ if (!(querydisplayinfo->out.info->info2.entries[i].acct_flags & ACB_NORMAL)) {
printf("Missing ACB_NORMAL in querydisplayinfo->out.info.info2.entries[i].acct_flags on %s\n",
- q.out.info->info21.account_name.string);
+ info->info21.account_name.string);
}
- if (!(q.out.info->info21.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST))) {
+ if (!(info->info21.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST))) {
printf("Found non-trust account %s in trust account listing: 0x%x 0x%x\n",
- q.out.info->info21.account_name.string,
- querydisplayinfo->out.info.info2.entries[i].acct_flags,
- q.out.info->info21.acct_flags);
+ info->info21.account_name.string,
+ querydisplayinfo->out.info->info2.entries[i].acct_flags,
+ info->info21.acct_flags);
return false;
}
@@ -3605,10 +4399,15 @@ static bool test_QueryDisplayInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
NTSTATUS status;
struct samr_QueryDisplayInfo r;
struct samr_QueryDomainInfo dom_info;
+ union samr_DomainInfo *info = NULL;
bool ret = true;
uint16_t levels[] = {1, 2, 3, 4, 5};
int i;
bool seen_testuser = false;
+ uint32_t total_size;
+ uint32_t returned_size;
+ union samr_DispInfo disp_info;
+
for (i=0;i<ARRAY_SIZE(levels);i++) {
printf("Testing QueryDisplayInfo level %u\n", levels[i]);
@@ -3620,6 +4419,9 @@ static bool test_QueryDisplayInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
r.in.level = levels[i];
r.in.max_entries = 2;
r.in.buf_size = (uint32_t)-1;
+ r.out.total_size = &total_size;
+ r.out.returned_size = &returned_size;
+ r.out.info = &disp_info;
status = dcerpc_samr_QueryDisplayInfo(p, mem_ctx, &r);
if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) && !NT_STATUS_IS_OK(status)) {
@@ -3632,27 +4434,29 @@ static bool test_QueryDisplayInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
if (!test_each_DisplayInfo_user(p, mem_ctx, &r, &seen_testuser)) {
ret = false;
}
- r.in.start_idx += r.out.info.info1.count;
+ r.in.start_idx += r.out.info->info1.count;
break;
case 2:
if (!test_each_DisplayInfo_user(p, mem_ctx, &r, NULL)) {
ret = false;
}
- r.in.start_idx += r.out.info.info2.count;
+ r.in.start_idx += r.out.info->info2.count;
break;
case 3:
- r.in.start_idx += r.out.info.info3.count;
+ r.in.start_idx += r.out.info->info3.count;
break;
case 4:
- r.in.start_idx += r.out.info.info4.count;
+ r.in.start_idx += r.out.info->info4.count;
break;
case 5:
- r.in.start_idx += r.out.info.info5.count;
+ r.in.start_idx += r.out.info->info5.count;
break;
}
}
dom_info.in.domain_handle = handle;
dom_info.in.level = 2;
+ dom_info.out.info = &info;
+
/* Check number of users returned is correct */
status = dcerpc_samr_QueryDomainInfo(p, mem_ctx, &dom_info);
if (!NT_STATUS_IS_OK(status)) {
@@ -3664,17 +4468,17 @@ static bool test_QueryDisplayInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
switch (r.in.level) {
case 1:
case 4:
- if (dom_info.out.info->general.num_users < r.in.start_idx) {
+ if (info->general.num_users < r.in.start_idx) {
printf("QueryDomainInfo indicates that QueryDisplayInfo returned more users (%d/%d) than the domain %s is said to contain!\n",
- r.in.start_idx, dom_info.out.info->general.num_groups,
- dom_info.out.info->general.domain_name.string);
+ r.in.start_idx, info->general.num_groups,
+ info->general.domain_name.string);
ret = false;
}
if (!seen_testuser) {
struct policy_handle user_handle;
if (NT_STATUS_IS_OK(test_OpenUser_byname(p, mem_ctx, handle, TEST_ACCOUNT_NAME, &user_handle))) {
printf("Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n",
- dom_info.out.info->general.domain_name.string);
+ info->general.domain_name.string);
ret = false;
test_samr_handle_Close(p, mem_ctx, &user_handle);
}
@@ -3682,10 +4486,10 @@ static bool test_QueryDisplayInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
break;
case 3:
case 5:
- if (dom_info.out.info->general.num_groups != r.in.start_idx) {
+ if (info->general.num_groups != r.in.start_idx) {
printf("QueryDomainInfo indicates that QueryDisplayInfo didn't return all (%d/%d) the groups in %s\n",
- r.in.start_idx, dom_info.out.info->general.num_groups,
- dom_info.out.info->general.domain_name.string);
+ r.in.start_idx, info->general.num_groups,
+ info->general.domain_name.string);
ret = false;
}
@@ -3705,6 +4509,9 @@ static bool test_QueryDisplayInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
bool ret = true;
uint16_t levels[] = {1, 2, 3, 4, 5};
int i;
+ uint32_t total_size;
+ uint32_t returned_size;
+ union samr_DispInfo info;
for (i=0;i<ARRAY_SIZE(levels);i++) {
printf("Testing QueryDisplayInfo2 level %u\n", levels[i]);
@@ -3714,6 +4521,9 @@ static bool test_QueryDisplayInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
r.in.start_idx = 0;
r.in.max_entries = 1000;
r.in.buf_size = (uint32_t)-1;
+ r.out.total_size = &total_size;
+ r.out.returned_size = &returned_size;
+ r.out.info = &info;
status = dcerpc_samr_QueryDisplayInfo2(p, mem_ctx, &r);
if (!NT_STATUS_IS_OK(status)) {
@@ -3734,6 +4544,9 @@ static bool test_QueryDisplayInfo3(struct dcerpc_pipe *p, struct torture_context
bool ret = true;
uint16_t levels[] = {1, 2, 3, 4, 5};
int i;
+ uint32_t total_size;
+ uint32_t returned_size;
+ union samr_DispInfo info;
for (i=0;i<ARRAY_SIZE(levels);i++) {
torture_comment(tctx, "Testing QueryDisplayInfo3 level %u\n", levels[i]);
@@ -3743,6 +4556,9 @@ static bool test_QueryDisplayInfo3(struct dcerpc_pipe *p, struct torture_context
r.in.start_idx = 0;
r.in.max_entries = 1000;
r.in.buf_size = (uint32_t)-1;
+ r.out.total_size = &total_size;
+ r.out.returned_size = &returned_size;
+ r.out.info = &info;
status = dcerpc_samr_QueryDisplayInfo3(p, tctx, &r);
if (!NT_STATUS_IS_OK(status)) {
@@ -3762,6 +4578,9 @@ static bool test_QueryDisplayInfo_continue(struct dcerpc_pipe *p, TALLOC_CTX *me
NTSTATUS status;
struct samr_QueryDisplayInfo r;
bool ret = true;
+ uint32_t total_size;
+ uint32_t returned_size;
+ union samr_DispInfo info;
printf("Testing QueryDisplayInfo continuation\n");
@@ -3770,14 +4589,17 @@ static bool test_QueryDisplayInfo_continue(struct dcerpc_pipe *p, TALLOC_CTX *me
r.in.start_idx = 0;
r.in.max_entries = 1;
r.in.buf_size = (uint32_t)-1;
+ r.out.total_size = &total_size;
+ r.out.returned_size = &returned_size;
+ r.out.info = &info;
do {
status = dcerpc_samr_QueryDisplayInfo(p, mem_ctx, &r);
- if (NT_STATUS_IS_OK(status) && r.out.returned_size != 0) {
- if (r.out.info.info1.entries[0].idx != r.in.start_idx + 1) {
+ if (NT_STATUS_IS_OK(status) && *r.out.returned_size != 0) {
+ if (r.out.info->info1.entries[0].idx != r.in.start_idx + 1) {
printf("expected idx %d but got %d\n",
r.in.start_idx + 1,
- r.out.info.info1.entries[0].idx);
+ r.out.info->info1.entries[0].idx);
break;
}
}
@@ -3791,7 +4613,7 @@ static bool test_QueryDisplayInfo_continue(struct dcerpc_pipe *p, TALLOC_CTX *me
r.in.start_idx++;
} while ((NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) ||
NT_STATUS_IS_OK(status)) &&
- r.out.returned_size != 0);
+ *r.out.returned_size != 0);
return ret;
}
@@ -3801,6 +4623,7 @@ static bool test_QueryDomainInfo(struct dcerpc_pipe *p, struct torture_context *
{
NTSTATUS status;
struct samr_QueryDomainInfo r;
+ union samr_DomainInfo *info = NULL;
struct samr_SetDomainInfo s;
uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
uint16_t set_ok[] = {1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0};
@@ -3827,6 +4650,7 @@ static bool test_QueryDomainInfo(struct dcerpc_pipe *p, struct torture_context *
r.in.domain_handle = handle;
r.in.level = levels[i];
+ r.out.info = &info;
status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
if (!NT_STATUS_IS_OK(status)) {
@@ -3838,40 +4662,40 @@ static bool test_QueryDomainInfo(struct dcerpc_pipe *p, struct torture_context *
switch (levels[i]) {
case 2:
- if (strcmp(r.out.info->general.oem_information.string, domain_comment) != 0) {
+ if (strcmp(info->general.oem_information.string, domain_comment) != 0) {
printf("QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
- levels[i], r.out.info->general.oem_information.string, domain_comment);
+ levels[i], info->general.oem_information.string, domain_comment);
ret = false;
}
- if (!r.out.info->general.primary.string) {
+ if (!info->general.primary.string) {
printf("QueryDomainInfo level %u returned no PDC name\n",
levels[i]);
ret = false;
- } else if (r.out.info->general.role == SAMR_ROLE_DOMAIN_PDC) {
- if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), r.out.info->general.primary.string) != 0) {
+ } else if (info->general.role == SAMR_ROLE_DOMAIN_PDC) {
+ if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), info->general.primary.string) != 0) {
printf("QueryDomainInfo level %u returned different PDC name (%s) compared to server name (%s), despite claiming to be the PDC\n",
- levels[i], r.out.info->general.primary.string, dcerpc_server_name(p));
+ levels[i], info->general.primary.string, dcerpc_server_name(p));
}
}
break;
case 4:
- if (strcmp(r.out.info->oem.oem_information.string, domain_comment) != 0) {
+ if (strcmp(info->oem.oem_information.string, domain_comment) != 0) {
printf("QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
- levels[i], r.out.info->oem.oem_information.string, domain_comment);
+ levels[i], info->oem.oem_information.string, domain_comment);
ret = false;
}
break;
case 6:
- if (!r.out.info->info6.primary.string) {
+ if (!info->info6.primary.string) {
printf("QueryDomainInfo level %u returned no PDC name\n",
levels[i]);
ret = false;
}
break;
case 11:
- if (strcmp(r.out.info->general2.general.oem_information.string, domain_comment) != 0) {
+ if (strcmp(info->general2.general.oem_information.string, domain_comment) != 0) {
printf("QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
- levels[i], r.out.info->general2.general.oem_information.string, domain_comment);
+ levels[i], info->general2.general.oem_information.string, domain_comment);
ret = false;
}
break;
@@ -3881,7 +4705,7 @@ static bool test_QueryDomainInfo(struct dcerpc_pipe *p, struct torture_context *
s.in.domain_handle = handle;
s.in.level = levels[i];
- s.in.info = r.out.info;
+ s.in.info = info;
status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
if (set_ok[i]) {
@@ -3918,6 +4742,7 @@ static bool test_QueryDomainInfo2(struct dcerpc_pipe *p, struct torture_context
{
NTSTATUS status;
struct samr_QueryDomainInfo2 r;
+ union samr_DomainInfo *info = NULL;
uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
int i;
bool ret = true;
@@ -3927,6 +4752,7 @@ static bool test_QueryDomainInfo2(struct dcerpc_pipe *p, struct torture_context
r.in.domain_handle = handle;
r.in.level = levels[i];
+ r.out.info = &info;
status = dcerpc_samr_QueryDomainInfo2(p, tctx, &r);
if (!NT_STATUS_IS_OK(status)) {
@@ -3949,8 +4775,13 @@ static bool test_GroupList(struct dcerpc_pipe *p, struct torture_context *tctx,
struct samr_QueryDisplayInfo q2;
NTSTATUS status;
uint32_t resume_handle=0;
+ struct samr_SamArray *sam = NULL;
+ uint32_t num_entries = 0;
int i;
bool ret = true;
+ uint32_t total_size;
+ uint32_t returned_size;
+ union samr_DispInfo info;
int num_names = 0;
const char **names = NULL;
@@ -3961,6 +4792,8 @@ static bool test_GroupList(struct dcerpc_pipe *p, struct torture_context *tctx,
q1.in.resume_handle = &resume_handle;
q1.in.max_size = 5;
q1.out.resume_handle = &resume_handle;
+ q1.out.num_entries = &num_entries;
+ q1.out.sam = &sam;
status = STATUS_MORE_ENTRIES;
while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
@@ -3970,22 +4803,25 @@ static bool test_GroupList(struct dcerpc_pipe *p, struct torture_context *tctx,
!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
break;
- for (i=0; i<q1.out.num_entries; i++) {
+ for (i=0; i<*q1.out.num_entries; i++) {
add_string_to_array(tctx,
- q1.out.sam->entries[i].name.string,
+ sam->entries[i].name.string,
&names, &num_names);
}
}
torture_assert_ntstatus_ok(tctx, status, "EnumDomainGroups");
- torture_assert(tctx, q1.out.sam, "EnumDomainGroups failed to return q1.out.sam");
+ torture_assert(tctx, sam, "EnumDomainGroups failed to return sam");
q2.in.domain_handle = handle;
q2.in.level = 5;
q2.in.start_idx = 0;
q2.in.max_entries = 5;
q2.in.buf_size = (uint32_t)-1;
+ q2.out.total_size = &total_size;
+ q2.out.returned_size = &returned_size;
+ q2.out.info = &info;
status = STATUS_MORE_ENTRIES;
while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
@@ -3995,9 +4831,9 @@ static bool test_GroupList(struct dcerpc_pipe *p, struct torture_context *tctx,
!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
break;
- for (i=0; i<q2.out.info.info5.count; i++) {
+ for (i=0; i<q2.out.info->info5.count; i++) {
int j;
- const char *name = q2.out.info.info5.entries[i].account_name.string;
+ const char *name = q2.out.info->info5.entries[i].account_name.string;
bool found = false;
for (j=0; j<num_names; j++) {
if (names[j] == NULL)
@@ -4015,7 +4851,7 @@ static bool test_GroupList(struct dcerpc_pipe *p, struct torture_context *tctx,
ret = false;
}
}
- q2.in.start_idx += q2.out.info.info5.count;
+ q2.in.start_idx += q2.out.info->info5.count;
}
if (!NT_STATUS_IS_OK(status)) {
@@ -4076,7 +4912,7 @@ static bool test_RidToSid(struct dcerpc_pipe *p, struct torture_context *tctx,
struct samr_RidToSid r;
NTSTATUS status;
bool ret = true;
- struct dom_sid *calc_sid;
+ struct dom_sid *calc_sid, *out_sid;
int rids[] = { 0, 42, 512, 10200 };
int i;
@@ -4086,6 +4922,7 @@ static bool test_RidToSid(struct dcerpc_pipe *p, struct torture_context *tctx,
calc_sid = dom_sid_dup(tctx, domain_sid);
r.in.domain_handle = domain_handle;
r.in.rid = rids[i];
+ r.out.sid = &out_sid;
status = dcerpc_samr_RidToSid(p, tctx, &r);
if (!NT_STATUS_IS_OK(status)) {
@@ -4094,9 +4931,9 @@ static bool test_RidToSid(struct dcerpc_pipe *p, struct torture_context *tctx,
} else {
calc_sid = dom_sid_add_rid(calc_sid, calc_sid, rids[i]);
- if (!dom_sid_equal(calc_sid, r.out.sid)) {
+ if (!dom_sid_equal(calc_sid, out_sid)) {
printf("RidToSid for %d failed - got %s, expected %s\n", rids[i],
- dom_sid_string(tctx, r.out.sid),
+ dom_sid_string(tctx, out_sid),
dom_sid_string(tctx, calc_sid));
ret = false;
}
@@ -4112,10 +4949,12 @@ static bool test_GetBootKeyInformation(struct dcerpc_pipe *p, struct torture_con
struct samr_GetBootKeyInformation r;
NTSTATUS status;
bool ret = true;
+ uint32_t unknown = 0;
torture_comment(tctx, "Testing GetBootKeyInformation\n");
r.in.domain_handle = domain_handle;
+ r.out.unknown = &unknown;
status = dcerpc_samr_GetBootKeyInformation(p, tctx, &r);
if (!NT_STATUS_IS_OK(status)) {
@@ -4134,6 +4973,7 @@ static bool test_AddGroupMember(struct dcerpc_pipe *p, struct torture_context *t
struct samr_AddGroupMember r;
struct samr_DeleteGroupMember d;
struct samr_QueryGroupMember q;
+ struct samr_RidTypeArray *rids = NULL;
struct samr_SetMemberAttributesOfGroup s;
uint32_t rid;
@@ -4173,6 +5013,7 @@ static bool test_AddGroupMember(struct dcerpc_pipe *p, struct torture_context *t
}
q.in.group_handle = group_handle;
+ q.out.rids = &rids;
status = dcerpc_samr_QueryGroupMember(p, tctx, &q);
torture_assert_ntstatus_ok(tctx, status, "QueryGroupMember");
@@ -4312,6 +5153,7 @@ 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 */
@@ -4388,6 +5230,7 @@ static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tct
{
NTSTATUS status;
struct samr_LookupDomain r;
+ struct dom_sid2 *sid = NULL;
struct lsa_String n1;
struct lsa_String n2;
bool ret = true;
@@ -4397,6 +5240,7 @@ static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tct
/* check for correct error codes */
r.in.connect_handle = handle;
r.in.domain_name = &n2;
+ r.out.sid = &sid;
n2.string = NULL;
status = dcerpc_samr_LookupDomain(p, tctx, &r);
@@ -4419,7 +5263,7 @@ static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tct
ret = false;
}
- if (!test_OpenDomain(p, tctx, handle, r.out.sid, which_ops)) {
+ if (!test_OpenDomain(p, tctx, handle, *r.out.sid, which_ops)) {
ret = false;
}
@@ -4433,6 +5277,8 @@ static bool test_EnumDomains(struct dcerpc_pipe *p, struct torture_context *tctx
NTSTATUS status;
struct samr_EnumDomains r;
uint32_t resume_handle = 0;
+ uint32_t num_entries = 0;
+ struct samr_SamArray *sam = NULL;
int i;
bool ret = true;
@@ -4440,17 +5286,19 @@ static bool test_EnumDomains(struct dcerpc_pipe *p, struct torture_context *tctx
r.in.resume_handle = &resume_handle;
r.in.buf_size = (uint32_t)-1;
r.out.resume_handle = &resume_handle;
+ r.out.num_entries = &num_entries;
+ r.out.sam = &sam;
status = dcerpc_samr_EnumDomains(p, tctx, &r);
torture_assert_ntstatus_ok(tctx, status, "EnumDomains");
- if (!r.out.sam) {
+ if (!*r.out.sam) {
return false;
}
- for (i=0;i<r.out.sam->count;i++) {
+ for (i=0;i<sam->count;i++) {
if (!test_LookupDomain(p, tctx, handle,
- r.out.sam->entries[i].name.string, which_ops)) {
+ sam->entries[i].name.string, which_ops)) {
ret = false;
}
}
@@ -4473,6 +5321,7 @@ static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx,
struct samr_Connect5 r5;
union samr_ConnectInfo info;
struct policy_handle h;
+ uint32_t level_out = 0;
bool ret = true, got_handle = false;
torture_comment(tctx, "testing samr_Connect\n");
@@ -4553,9 +5402,10 @@ static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx,
r5.in.system_name = "";
r5.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
- r5.in.level = 1;
- r5.in.info = &info;
- r5.out.info = &info;
+ r5.in.level_in = 1;
+ r5.out.level_out = &level_out;
+ r5.in.info_in = &info;
+ r5.out.info_out = &info;
r5.out.connect_handle = &h;
status = dcerpc_samr_Connect5(p, tctx, &r5);
@@ -4651,3 +5501,25 @@ bool torture_rpc_samr_passwords(struct torture_context *torture)
return ret;
}
+bool torture_rpc_samr_passwords_pwdlastset(struct torture_context *torture)
+{
+ NTSTATUS status;
+ struct dcerpc_pipe *p;
+ bool ret = true;
+ struct policy_handle handle;
+
+ status = torture_rpc_connection(torture, &p, &ndr_table_samr);
+ if (!NT_STATUS_IS_OK(status)) {
+ return false;
+ }
+
+ ret &= test_Connect(p, torture, &handle);
+
+ ret &= test_EnumDomains(p, torture, &handle,
+ TORTURE_SAMR_PASSWORDS_PWDLASTSET);
+
+ ret &= test_samr_handle_Close(p, torture, &handle);
+
+ return ret;
+}
+