- add 'print' to the DCERPC binding strings
[samba.git] / source4 / torture / rpc / samr.c
index e8771f2e5a24b7e87658215d37bcd4fb03f1f668..fccae8412c4d74242ccf0c94f771509051cc6444 100644 (file)
@@ -3,6 +3,7 @@
    test suite for samr rpc operations
 
    Copyright (C) Andrew Tridgell 2003
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 
 #include "includes.h"
 
+#define TEST_USERNAME "samrtorturetest"
+#define TEST_ALIASNAME "samrtorturetestalias"
+#define TEST_MACHINENAME "samrtorturetestmach$"
+#define TEST_DOMAINNAME "samrtorturetestdom$"
+
+
+static BOOL test_QueryUserInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+                              struct policy_handle *handle);
+
+static BOOL test_QueryAliasInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+                              struct policy_handle *handle);
+
+static void init_samr_Name(struct samr_Name *name, const char *s)
+{
+       name->name = s;
+}
+
+static BOOL test_Close(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+                      struct policy_handle *handle)
+{
+       NTSTATUS status;
+       struct samr_Close r;
+
+       r.in.handle = handle;
+       r.out.handle = handle;
+
+       status = dcerpc_samr_Close(p, mem_ctx, &r);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("Close handle failed - %s\n", nt_errstr(status));
+               return False;
+       }
+
+       return True;
+}
+
+
+static BOOL test_QuerySecurity(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+                              struct policy_handle *handle)
+{
+       NTSTATUS status;
+       struct samr_QuerySecurity r;
+       struct samr_SetSecurity s;
+
+       r.in.handle = handle;
+       r.in.sec_info = 7;
+
+       status = dcerpc_samr_QuerySecurity(p, mem_ctx, &r);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("QuerySecurity failed - %s\n", nt_errstr(status));
+               return False;
+       }
+
+       s.in.handle = handle;
+       s.in.sec_info = 7;
+       s.in.sdbuf = r.out.sdbuf;
+
+       status = dcerpc_samr_SetSecurity(p, mem_ctx, &s);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("SetSecurity failed - %s\n", nt_errstr(status));
+               return False;
+       }
+
+       status = dcerpc_samr_QuerySecurity(p, mem_ctx, &r);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("QuerySecurity failed - %s\n", nt_errstr(status));
+               return False;
+       }
+
+       return True;
+}
+
+
+static BOOL test_SetUserInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+                            struct policy_handle *handle)
+{
+       NTSTATUS status;
+       struct samr_SetUserInfo s;
+       struct samr_QueryUserInfo q;
+       struct samr_QueryUserInfo q0;
+       union samr_UserInfo u;
+       BOOL ret = True;
+
+       s.in.handle = handle;
+       s.in.info = &u;
+       q.in.handle = handle;
+       q.out.info = &u;
+       q0 = q;
+
+#define TESTCALL(call, r) \
+               status = dcerpc_samr_ ##call(p, mem_ctx, &r); \
+               if (!NT_STATUS_IS_OK(status)) { \
+                       printf(#call " level %u failed - %s (line %d)\n", \
+                              r.in.level, nt_errstr(status), __LINE__); \
+                       ret = False; \
+                       break; \
+               }
+
+#define STRING_EQUAL(s1, s2, field) \
+               if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
+                       printf("Failed to set %s to '%s' (line %d)\n", \
+                              #field, s2, __LINE__); \
+                       ret = False; \
+                       break; \
+               }
+
+#define INT_EQUAL(i1, i2, field) \
+               if (i1 != i2) { \
+                       printf("Failed to set %s to %u (line %d)\n", \
+                              #field, i2, __LINE__); \
+                       ret = False; \
+                       break; \
+               }
+
+#define TEST_USERINFO_NAME(lvl1, field1, lvl2, field2, value, fpval) do { \
+               printf("field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
+               q.in.level = lvl1; \
+               TESTCALL(QueryUserInfo, q) \
+               s.in.level = lvl1; \
+               u = *q.out.info; \
+               init_samr_Name(&u.info ## lvl1.field1, value); \
+               if (lvl1 == 21) { \
+                       u.info21.fields_present = fpval; \
+               } \
+               TESTCALL(SetUserInfo, s) \
+               init_samr_Name(&u.info ## lvl1.field1, ""); \
+               TESTCALL(QueryUserInfo, q); \
+               u = *q.out.info; \
+               STRING_EQUAL(u.info ## lvl1.field1.name, value, field1); \
+               q.in.level = lvl2; \
+               TESTCALL(QueryUserInfo, q) \
+               u = *q.out.info; \
+               STRING_EQUAL(u.info ## lvl2.field2.name, value, field2); \
+       } while (0)
+
+#define TEST_USERINFO_INT(lvl1, field1, lvl2, field2, value, fpval) do { \
+               printf("field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
+               q.in.level = lvl1; \
+               TESTCALL(QueryUserInfo, q) \
+               s.in.level = lvl1; \
+               u = *q.out.info; \
+               u.info ## lvl1.field1 = value; \
+               if (lvl1 == 21) { \
+                       u.info21.fields_present = fpval; \
+               } \
+               TESTCALL(SetUserInfo, s) \
+               u.info ## lvl1.field1 = 0; \
+               TESTCALL(QueryUserInfo, q); \
+               u = *q.out.info; \
+               INT_EQUAL(u.info ## lvl1.field1, value, field1); \
+               q.in.level = lvl2; \
+               TESTCALL(QueryUserInfo, q) \
+               u = *q.out.info; \
+               INT_EQUAL(u.info ## lvl2.field2, value, field1); \
+       } while (0)
+
+       q0.in.level = 12;
+       do { TESTCALL(QueryUserInfo, q0) } while (0);
+
+       TEST_USERINFO_NAME(2, comment,  1, comment, "xx2-1 comment", 0);
+       TEST_USERINFO_NAME(2, comment, 21, comment, "xx2-21 comment", 0);
+       TEST_USERINFO_NAME(21, comment, 21, comment, "xx21-21 comment", 0x00000020);
+
+       TEST_USERINFO_NAME(6, full_name,  1, full_name, "xx6-1 full_name", 0);
+       TEST_USERINFO_NAME(6, full_name,  3, full_name, "xx6-3 full_name", 0);
+       TEST_USERINFO_NAME(6, full_name,  5, full_name, "xx6-5 full_name", 0);
+       TEST_USERINFO_NAME(6, full_name,  6, full_name, "xx6-6 full_name", 0);
+       TEST_USERINFO_NAME(6, full_name,  8, full_name, "xx6-8 full_name", 0);
+       TEST_USERINFO_NAME(6, full_name, 21, full_name, "xx6-21 full_name", 0);
+       TEST_USERINFO_NAME(8, full_name, 21, full_name, "xx8-21 full_name", 0);
+       TEST_USERINFO_NAME(21, full_name, 21, full_name, "xx21-21 full_name", 0x00000002);
+
+       TEST_USERINFO_NAME(11, logon_script, 3, logon_script, "xx11-3 logon_script", 0);
+       TEST_USERINFO_NAME(11, logon_script, 5, logon_script, "xx11-5 logon_script", 0);
+       TEST_USERINFO_NAME(11, logon_script, 21, logon_script, "xx11-21 logon_script", 0);
+       TEST_USERINFO_NAME(21, logon_script, 21, logon_script, "xx21-21 logon_script", 0x00000100);
+
+       TEST_USERINFO_NAME(12, profile,  3, profile, "xx12-3 profile", 0);
+       TEST_USERINFO_NAME(12, profile,  5, profile, "xx12-5 profile", 0);
+       TEST_USERINFO_NAME(12, profile, 21, profile, "xx12-21 profile", 0);
+       TEST_USERINFO_NAME(21, profile, 21, profile, "xx21-21 profile", 0x00000200);
+
+       TEST_USERINFO_NAME(13, description,  1, description, "xx13-1 description", 0);
+       TEST_USERINFO_NAME(13, description,  5, description, "xx13-5 description", 0);
+       TEST_USERINFO_NAME(13, description, 21, description, "xx13-21 description", 0);
+       TEST_USERINFO_NAME(21, description, 21, description, "xx21-21 description", 0x00000010);
+
+       TEST_USERINFO_NAME(14, workstations,  3, workstations, "14workstation3", 0);
+       TEST_USERINFO_NAME(14, workstations,  5, workstations, "14workstation4", 0);
+       TEST_USERINFO_NAME(14, workstations, 21, workstations, "14workstation21", 0);
+       TEST_USERINFO_NAME(21, workstations, 21, workstations, "21workstation21", 0x00000400);
+
+       TEST_USERINFO_NAME(20, callback, 21, callback, "xx20-21 callback", 0);
+       TEST_USERINFO_NAME(21, callback, 21, callback, "xx21-21 callback", 0x00200000);
+
+       TEST_USERINFO_INT(2, country_code, 21, country_code, __LINE__, 0);
+       TEST_USERINFO_INT(21, country_code, 21, country_code, __LINE__, 0x00400000);
+       TEST_USERINFO_INT(2, code_page, 21, code_page, __LINE__, 0);
+       TEST_USERINFO_INT(21, code_page, 21, code_page, __LINE__, 0x00800000);
+
+       TEST_USERINFO_INT(4, logon_hours.bitmap[3],  3, logon_hours.bitmap[3], __LINE__, 0);
+       TEST_USERINFO_INT(4, logon_hours.bitmap[3],  5, logon_hours.bitmap[3], __LINE__, 0);
+       TEST_USERINFO_INT(4, logon_hours.bitmap[3], 21, logon_hours.bitmap[3], __LINE__, 0);
+       TEST_USERINFO_INT(21, logon_hours.bitmap[3], 21, logon_hours.bitmap[3], __LINE__, 0x00002000);
+
+#if 0
+       /* these fail with win2003 - it appears you can't set the primary gid?
+          the set succeeds, but the gid isn't changed. Very weird! */
+       TEST_USERINFO_INT(9, primary_gid,  1, primary_gid, 513);
+       TEST_USERINFO_INT(9, primary_gid,  3, primary_gid, 513);
+       TEST_USERINFO_INT(9, primary_gid,  5, primary_gid, 513);
+       TEST_USERINFO_INT(9, primary_gid, 21, primary_gid, 513);
+#endif
+       return ret;
+}
+
+static BOOL test_SetAliasInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+                              struct policy_handle *handle)
+{
+       NTSTATUS status;
+       struct samr_SetAliasInfo r;
+       struct samr_QueryAliasInfo q;
+       uint16 levels[] = {2, 3};
+       int i;
+       BOOL ret = True;
+
+       /* Ignoring switch level 1, as that includes the number of members for the alias
+        * and setting this to a wrong value might have negative consequences
+        */
+
+       for (i=0;i<ARRAY_SIZE(levels);i++) {
+               printf("Testing SetAliasInfo level %u\n", levels[i]);
+
+               r.in.handle = handle;
+               r.in.level = levels[i];
+               switch (r.in.level) {
+                   case 2 : init_samr_Name(&r.in.info.name,TEST_ALIASNAME); break;
+                   case 3 : init_samr_Name(&r.in.info.description,
+                               "Test Description, should test I18N as well"); break;
+               }
+
+               status = dcerpc_samr_SetAliasInfo(p, mem_ctx, &r);
+               if (!NT_STATUS_IS_OK(status)) {
+                       printf("SetAliasInfo level %u failed - %s\n",
+                              levels[i], nt_errstr(status));
+                       ret = False;
+               }
+
+               q.in.handle = handle;
+               q.in.level = levels[i];
+
+               status = dcerpc_samr_QueryAliasInfo(p, mem_ctx, &q);
+               if (!NT_STATUS_IS_OK(status)) {
+                       printf("QueryAliasInfo level %u failed - %s\n",
+                              levels[i], nt_errstr(status));
+                       ret = False;
+               }
+       }
+
+       return ret;
+}
+
+static BOOL test_GetGroupsForUser(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+                                 struct policy_handle *user_handle)
+{
+       struct samr_GetGroupsForUser r;
+       NTSTATUS status;
+       BOOL ret = True;
+
+       printf("testing GetGroupsForUser\n");
+
+       r.in.handle = user_handle;
+
+       status = dcerpc_samr_GetGroupsForUser(p, mem_ctx, &r);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("GetGroupsForUser failed - %s\n",nt_errstr(status));
+               ret = False;
+       }
+
+       return ret;
+
+}
+static BOOL test_GetUserPwInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+                              struct policy_handle *handle)
+{
+       NTSTATUS status;
+       struct samr_GetUserPwInfo r;
+       BOOL ret = True;
+
+       printf("Testing GetUserPwInfo\n");
+
+       r.in.handle = handle;
+
+       status = dcerpc_samr_GetUserPwInfo(p, mem_ctx, &r);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("GetUserPwInfo failed - %s\n", nt_errstr(status));
+               ret = False;
+       }
+
+       return ret;
+}
+
+static BOOL test_GetMembersInAlias(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+                                 struct policy_handle *alias_handle)
+{
+       struct samr_GetMembersInAlias r;
+       struct lsa_SidArray sids;
+       NTSTATUS status;
+       BOOL     ret = True;
+
+       printf("Testing GetMembersInAlias\n");
+
+       r.in.handle = alias_handle;
+       r.out.sids = &sids;
+
+       status = dcerpc_samr_GetMembersInAlias(p, mem_ctx, &r);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("GetMembersInAlias failed - %s\n",
+                      nt_errstr(status));
+               ret = False;
+       }
+
+       return ret;
+}
+
+static BOOL test_AddMemberToAlias(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+                                 struct policy_handle *alias_handle,
+                                 struct policy_handle *domain_handle,
+                                 const struct dom_sid *domain_sid)
+{
+       struct samr_AddAliasMem r;
+       struct samr_DelAliasMem d;
+       NTSTATUS status;
+       BOOL ret = True;
+       struct dom_sid *sid;
+
+       sid = dom_sid_add_rid(mem_ctx, domain_sid, 512);
+
+       printf("testing AddAliasMem\n");
+       r.in.handle = alias_handle;
+       r.in.sid = sid;
+
+       status = dcerpc_samr_AddAliasMem(p, mem_ctx, &r);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("AddAliasMem failed - %s\n", nt_errstr(status));
+               ret = False;
+       }
+
+       d.in.handle = alias_handle;
+       d.in.sid = sid;
+
+       status = dcerpc_samr_DelAliasMem(p, mem_ctx, &d);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("DelAliasMem failed - %s\n", nt_errstr(status));
+               ret = False;
+       }
+
+       return ret;
+}
+
+static BOOL test_user_ops(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+                         struct policy_handle *handle)
+{
+       BOOL ret = True;
+
+       if (!test_QuerySecurity(p, mem_ctx, handle)) {
+               ret = False;
+       }
+
+       if (!test_QueryUserInfo(p, mem_ctx, handle)) {
+               ret = False;
+       }
+
+       if (!test_SetUserInfo(p, mem_ctx, handle)) {
+               ret = False;
+       }       
+
+       if (!test_GetUserPwInfo(p, mem_ctx, handle)) {
+               ret = False;
+       }
+
+       return ret;
+}
+
+static BOOL test_alias_ops(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+                          struct policy_handle *alias_handle,
+                          struct policy_handle *domain_handle,
+                          const struct dom_sid *domain_sid)
+{
+       BOOL ret = True;
+
+       if (!test_QuerySecurity(p, mem_ctx, alias_handle)) {
+               ret = False;
+       }
+
+       if (!test_QueryAliasInfo(p, mem_ctx, alias_handle)) {
+               ret = False;
+       }
+
+       if (!test_SetAliasInfo(p, mem_ctx, alias_handle)) {
+               ret = False;
+       }
+
+       if (!test_AddMemberToAlias(p, mem_ctx, alias_handle, 
+                                  domain_handle, domain_sid)) {
+               ret = False;
+       }
+
+       return ret;
+}
+
+static BOOL test_DeleteUser_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+                                  struct policy_handle *handle, const char *name)
+{
+       NTSTATUS status;
+       struct samr_LookupNames n;
+       struct samr_OpenUser r;
+       struct samr_DeleteUser d;
+       struct policy_handle acct_handle;
+       struct samr_Name sname;
+
+       init_samr_Name(&sname, name);
+
+       n.in.handle = handle;
+       n.in.num_names = 1;
+       n.in.names = &sname;
+       status = dcerpc_samr_LookupNames(p, mem_ctx, &n);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto failed;
+       }
+
+       r.in.handle = handle;
+       r.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
+       r.in.rid = n.out.rids.ids[0];
+       r.out.acct_handle = &acct_handle;
+       status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto failed;
+       }
+
+       d.in.handle = &acct_handle;
+       d.out.handle = &acct_handle;
+       status = dcerpc_samr_DeleteUser(p, mem_ctx, &d);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto failed;
+       }
+
+       return True;
+
+failed:
+       printf("DeleteUser_byname(%s) failed - %s\n", name, nt_errstr(status));
+       return False;
+}
+
+static BOOL test_DeleteAlias_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+                                  struct policy_handle *domain_handle, const char *name)
+{
+       NTSTATUS status;
+       struct samr_LookupNames n;
+       struct samr_OpenAlias r;
+       struct samr_DeleteDomAlias d;
+       struct policy_handle alias_handle;
+       struct samr_Name sname;
+
+       printf("testing DeleteAlias_byname\n");
+       init_samr_Name(&sname, name);
+
+       n.in.handle = domain_handle;
+       n.in.num_names = 1;
+       n.in.names = &sname;
+       status = dcerpc_samr_LookupNames(p, mem_ctx, &n);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto failed;
+       }
+
+       r.in.handle = domain_handle;
+       r.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
+       r.in.rid = n.out.rids.ids[0];
+       r.out.acct_handle = &alias_handle;
+       status = dcerpc_samr_OpenAlias(p, mem_ctx, &r);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto failed;
+       }
+
+       d.in.handle = &alias_handle;
+       d.out.handle = &alias_handle;
+       status = dcerpc_samr_DeleteDomAlias(p, mem_ctx, &d);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto failed;
+       }
+
+       return True;
+
+failed:
+       printf("DeleteUser_byname(%s) failed - %s\n", name, nt_errstr(status));
+       return False;
+}
+
+static BOOL test_DeleteAlias(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+                                    struct policy_handle *alias_handle)
+{
+       struct samr_DeleteDomAlias d;
+       NTSTATUS status;
+       BOOL ret;
+       printf("Testing DeleteAlias\n");
+
+       d.in.handle = alias_handle;
+       d.out.handle = alias_handle;
+
+       status = dcerpc_samr_DeleteDomAlias(p, mem_ctx, &d);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("DeleteAlias failed - %s\n", nt_errstr(status));
+               ret = False;
+       }
+
+       return ret;
+}
+
+static BOOL test_CreateAlias(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+                           struct policy_handle *domain_handle, 
+                            struct policy_handle *alias_handle, 
+                            const struct dom_sid *domain_sid)
+{
+       NTSTATUS status;
+       struct samr_CreateDomAlias r;
+       struct samr_Name name;
+       uint32 rid;
+       BOOL ret = True;
+
+       init_samr_Name(&name, TEST_ALIASNAME);
+       r.in.handle = domain_handle;
+       r.in.aliasname = &name;
+       r.in.access_mask = SEC_RIGHT_MAXIMUM_ALLOWED;
+       r.out.acct_handle = alias_handle;
+       r.out.rid = &rid;
+
+       printf("Testing CreateAlias (%s)\n", r.in.aliasname->name);
+
+       status = dcerpc_samr_CreateDomAlias(p, mem_ctx, &r);
+
+       if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
+               printf("Server refused create of '%s'\n", r.in.aliasname->name);
+               return True;
+       }
+
+       if (NT_STATUS_EQUAL(status, NT_STATUS_ALIAS_EXISTS)) {
+               if (!test_DeleteAlias_byname(p, mem_ctx, domain_handle, r.in.aliasname->name)) {
+                       return False;
+               }
+               status = dcerpc_samr_CreateDomAlias(p, mem_ctx, &r);
+       }
+
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("CreateAlias failed - %s\n", nt_errstr(status));
+               return False;
+       }
+
+       if (!test_alias_ops(p, mem_ctx, alias_handle, domain_handle, domain_sid)) {
+               ret = False;
+       }
+
+       return ret;
+}
+
+static BOOL test_CreateUser(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+                           struct policy_handle *domain_handle, struct policy_handle *user_handle)
+{
+       NTSTATUS status;
+       struct samr_CreateUser r;
+       struct samr_QueryUserInfo q;
+       uint32 rid;
+
+       /* This call creates a 'normal' account - check that it really does */
+       const uint32 acct_flags = ACB_NORMAL;
+       struct samr_Name name;
+       BOOL ret = True;
+
+       init_samr_Name(&name, TEST_USERNAME);
+
+       r.in.handle = domain_handle;
+       r.in.username = &name;
+       r.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
+       r.out.acct_handle = user_handle;
+       r.out.rid = &rid;
+
+       printf("Testing CreateUser(%s)\n", r.in.username->name);
+
+       status = dcerpc_samr_CreateUser(p, mem_ctx, &r);
+
+       if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
+               printf("Server refused create of '%s'\n", r.in.username->name);
+               ZERO_STRUCTP(user_handle);
+               return True;
+       }
+
+       if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
+               if (!test_DeleteUser_byname(p, mem_ctx, domain_handle, r.in.username->name)) {
+                       return False;
+               }
+               status = dcerpc_samr_CreateUser(p, mem_ctx, &r);
+       }
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("CreateUser failed - %s\n", nt_errstr(status));
+               return False;
+       }
+
+
+       q.in.handle = user_handle;
+       q.in.level = 16;
+
+       status = dcerpc_samr_QueryUserInfo(p, mem_ctx, &q);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("QueryUserInfo level %u failed - %s\n", 
+                      q.in.level, nt_errstr(status));
+               ret = False;
+       } else {
+               if ((q.out.info->info16.acct_flags & acct_flags) != acct_flags) {
+                       printf("QuerUserInfo level 16 failed, it returned 0x%08x (%u) when we expected flags of 0x%08x (%u)\n",
+                              q.out.info->info16.acct_flags, q.out.info->info16.acct_flags, 
+                              acct_flags, acct_flags);
+                       ret = False;
+               }
+       }
+
+       if (!test_user_ops(p, mem_ctx, user_handle)) {
+               ret = False;
+       }
+
+       return ret;
+}
+
+
+static BOOL test_DeleteUser(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+                           struct policy_handle *user_handle)
+{
+       struct samr_DeleteUser d;
+       NTSTATUS status;
+       BOOL ret;
+
+       printf("Testing DeleteUser\n");
+
+       d.in.handle = user_handle;
+       d.out.handle = user_handle;
+
+       status = dcerpc_samr_DeleteUser(p, mem_ctx, &d);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("DeleteUser failed - %s\n", nt_errstr(status));
+               ret = False;
+       }
+
+       return ret;
+}
+
+static BOOL test_CreateUser2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+                            struct policy_handle *handle)
+{
+       NTSTATUS status;
+       struct samr_CreateUser2 r;
+       struct samr_QueryUserInfo q;
+       struct samr_DeleteUser d;
+       struct policy_handle acct_handle;
+       uint32 rid;
+       struct samr_Name name;
+       BOOL ret = True;
+       int i;
+
+       struct {
+               uint32 acct_flags;
+               const char *account_name;
+               NTSTATUS nt_status;
+       } account_types[] = {
+               { ACB_NORMAL, TEST_USERNAME, NT_STATUS_OK },
+               { ACB_NORMAL | ACB_DISABLED, TEST_USERNAME, NT_STATUS_INVALID_PARAMETER },
+               { ACB_NORMAL | ACB_PWNOEXP, TEST_USERNAME, NT_STATUS_INVALID_PARAMETER },
+               { ACB_WSTRUST, TEST_MACHINENAME, NT_STATUS_OK },
+               { ACB_WSTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
+               { ACB_WSTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
+               { ACB_SVRTRUST, TEST_MACHINENAME, NT_STATUS_OK },
+               { ACB_SVRTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
+               { ACB_SVRTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
+               { ACB_DOMTRUST, TEST_DOMAINNAME, NT_STATUS_OK },
+               { ACB_DOMTRUST | ACB_DISABLED, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
+               { ACB_DOMTRUST | ACB_PWNOEXP, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
+               { 0, TEST_USERNAME, NT_STATUS_INVALID_PARAMETER },
+               { ACB_DISABLED, TEST_USERNAME, NT_STATUS_INVALID_PARAMETER },
+               { 0, NULL, NT_STATUS_INVALID_PARAMETER }
+       };
+
+       for (i = 0; account_types[i].account_name; i++) {
+               uint32 acct_flags = account_types[i].acct_flags;
+               uint32 access_granted;
+
+               init_samr_Name(&name, account_types[i].account_name);
+
+               r.in.handle = handle;
+               r.in.username = &name;
+               r.in.acct_flags = acct_flags;
+               r.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
+               r.out.acct_handle = &acct_handle;
+               r.out.access_granted = &access_granted;
+               r.out.rid = &rid;
+               
+               printf("Testing CreateUser2(%s)\n", r.in.username->name);
+               
+               status = dcerpc_samr_CreateUser2(p, mem_ctx, &r);
+               
+               if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
+                       printf("Server refused create of '%s'\n", r.in.username->name);
+                       continue;
+
+               } else if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
+                       if (!test_DeleteUser_byname(p, mem_ctx, handle, r.in.username->name)) {
+                               return False;
+                       }
+                       status = dcerpc_samr_CreateUser2(p, mem_ctx, &r);
+
+               }
+               if (!NT_STATUS_EQUAL(status, account_types[i].nt_status)) {
+                       printf("CreateUser2 failed gave incorrect error return - %s (should be %s)\n", 
+                              nt_errstr(status), nt_errstr(account_types[i].nt_status));
+                       ret = False;
+               }
+               
+               if (NT_STATUS_IS_OK(status)) {
+                       q.in.handle = &acct_handle;
+                       q.in.level = 16;
+                       
+                       status = dcerpc_samr_QueryUserInfo(p, mem_ctx, &q);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               printf("QueryUserInfo level %u failed - %s\n", 
+                                      q.in.level, nt_errstr(status));
+                               ret = False;
+                       } else {
+                               if ((q.out.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, 
+                                              acct_flags);
+                                       ret = False;
+                               }
+                       }
+               
+                       if (!test_user_ops(p, mem_ctx, &acct_handle)) {
+                               ret = False;
+                       }
+
+                       printf("Testing DeleteUser (createuser2 test)\n");
+               
+                       d.in.handle = &acct_handle;
+                       d.out.handle = &acct_handle;
+                       
+                       status = dcerpc_samr_DeleteUser(p, mem_ctx, &d);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               printf("DeleteUser failed - %s\n", nt_errstr(status));
+                               ret = False;
+                       }
+               }
+       }
+
+       return ret;
+}
+
+static BOOL test_QueryAliasInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+                               struct policy_handle *handle)
+{
+       NTSTATUS status;
+       struct samr_QueryAliasInfo r;
+       uint16 levels[] = {1, 2, 3};
+       int i;
+       BOOL ret = True;
+
+       for (i=0;i<ARRAY_SIZE(levels);i++) {
+               printf("Testing QueryAliasInfo level %u\n", levels[i]);
+
+               r.in.handle = handle;
+               r.in.level = levels[i];
+
+               status = dcerpc_samr_QueryAliasInfo(p, mem_ctx, &r);
+               if (!NT_STATUS_IS_OK(status)) {
+                       printf("QueryAliasInfo level %u failed - %s\n", 
+                              levels[i], nt_errstr(status));
+                       ret = False;
+               }
+       }
+
+       return ret;
+}
+
+static BOOL test_QueryGroupInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+                               struct policy_handle *handle)
+{
+       NTSTATUS status;
+       struct samr_QueryGroupInfo r;
+       uint16 levels[] = {1, 2, 3, 4};
+       int i;
+       BOOL ret = True;
+
+       for (i=0;i<ARRAY_SIZE(levels);i++) {
+               printf("Testing QueryGroupInfo level %u\n", levels[i]);
+
+               r.in.handle = handle;
+               r.in.level = levels[i];
+
+               status = dcerpc_samr_QueryGroupInfo(p, mem_ctx, &r);
+               if (!NT_STATUS_IS_OK(status)) {
+                       printf("QueryGroupInfo level %u failed - %s\n", 
+                              levels[i], nt_errstr(status));
+                       ret = False;
+               }
+       }
+
+       return ret;
+}
+
 static BOOL test_QueryUserInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
                               struct policy_handle *handle)
 {
@@ -43,8 +856,6 @@ static BOOL test_QueryUserInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                               levels[i], nt_errstr(status));
                        ret = False;
                }
-
-               NDR_PRINT_UNION_DEBUG(samr_UserInfo, r.in.level, r.out.info);
        }
 
        return ret;
@@ -56,6 +867,7 @@ static BOOL test_OpenUser(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        NTSTATUS status;
        struct samr_OpenUser r;
        struct policy_handle acct_handle;
+       BOOL ret = True;
 
        printf("Testing OpenUser(%u)\n", rid);
 
@@ -70,11 +882,103 @@ static BOOL test_OpenUser(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                return False;
        }
 
+       if (!test_QuerySecurity(p, mem_ctx, &acct_handle)) {
+               ret = False;
+       }
+
        if (!test_QueryUserInfo(p, mem_ctx, &acct_handle)) {
+               ret = False;
+       }
+
+       if (!test_GetUserPwInfo(p, mem_ctx, &acct_handle)) {
+               ret = False;
+       }
+
+       if (!test_GetGroupsForUser(p,mem_ctx, &acct_handle)) {
+               ret = False;
+       }
+
+       if (!test_Close(p, mem_ctx, &acct_handle)) {
+               ret = False;
+       }
+
+       return ret;
+}
+
+static BOOL test_OpenGroup(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+                          struct policy_handle *handle, uint32 rid)
+{
+       NTSTATUS status;
+       struct samr_OpenGroup r;
+       struct policy_handle acct_handle;
+       BOOL ret = True;
+
+       printf("Testing OpenGroup(%u)\n", rid);
+
+       r.in.handle = handle;
+       r.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
+       r.in.rid = rid;
+       r.out.acct_handle = &acct_handle;
+
+       status = dcerpc_samr_OpenGroup(p, mem_ctx, &r);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("OpenGroup(%u) failed - %s\n", rid, nt_errstr(status));
                return False;
        }
-       
-       return True;
+
+       if (!test_QuerySecurity(p, mem_ctx, &acct_handle)) {
+               ret = False;
+       }
+
+       if (!test_QueryGroupInfo(p, mem_ctx, &acct_handle)) {
+               ret = False;
+       }
+
+       if (!test_Close(p, mem_ctx, &acct_handle)) {
+               ret = False;
+       }
+
+       return ret;
+}
+
+static BOOL test_OpenAlias(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+                          struct policy_handle *handle, uint32 rid)
+{
+       NTSTATUS status;
+       struct samr_OpenAlias r;
+       struct policy_handle acct_handle;
+       BOOL ret = True;
+
+       printf("Testing OpenAlias(%u)\n", rid);
+
+       r.in.handle = handle;
+       r.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
+       r.in.rid = rid;
+       r.out.acct_handle = &acct_handle;
+
+       status = dcerpc_samr_OpenAlias(p, mem_ctx, &r);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("OpenAlias(%u) failed - %s\n", rid, nt_errstr(status));
+               return False;
+       }
+
+       if (!test_QuerySecurity(p, mem_ctx, &acct_handle)) {
+               ret = False;
+       }
+
+       if (!test_QueryAliasInfo(p, mem_ctx, &acct_handle)) {
+               ret = False;
+       }
+
+       if (!test_GetMembersInAlias(p, mem_ctx, &acct_handle)) {
+               ret = False;
+       }
+
+       if (!test_Close(p, mem_ctx, &acct_handle)) {
+               ret = False;
+       }
+
+       return ret;
 }
 
 static BOOL test_EnumDomainUsers(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
@@ -85,6 +989,8 @@ static BOOL test_EnumDomainUsers(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        uint32 resume_handle=0;
        int i;
        BOOL ret = True;
+       struct samr_LookupNames n;
+       struct samr_LookupRids  lr ;
 
        printf("Testing EnumDomainUsers\n");
 
@@ -100,18 +1006,47 @@ static BOOL test_EnumDomainUsers(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                return False;
        }
        
-       NDR_PRINT_DEBUG(samr_SamArray, r.out.sam);
-
        if (!r.out.sam) {
                return False;
        }
 
+       if (r.out.sam->count == 0) {
+               return True;
+       }
+
        for (i=0;i<r.out.sam->count;i++) {
                if (!test_OpenUser(p, mem_ctx, handle, r.out.sam->entries[i].idx)) {
                        ret = False;
                }
        }
 
+       printf("Testing LookupNames\n");
+       n.in.handle = handle;
+       n.in.num_names = r.out.sam->count;
+       n.in.names = talloc(mem_ctx, r.out.sam->count * sizeof(struct samr_Name));
+       for (i=0;i<r.out.sam->count;i++) {
+               n.in.names[i] = r.out.sam->entries[i].name;
+       }
+       status = dcerpc_samr_LookupNames(p, mem_ctx, &n);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("LookupNames failed - %s\n", nt_errstr(status));
+               ret = False;
+       }
+
+
+       printf("Testing LookupRids\n");
+       lr.in.handle = handle;
+       lr.in.num_rids = r.out.sam->count;
+       lr.in.rids = talloc(mem_ctx, r.out.sam->count * sizeof(uint32));
+       for (i=0;i<r.out.sam->count;i++) {
+               lr.in.rids[i] = r.out.sam->entries[i].idx;
+       }
+       status = dcerpc_samr_LookupRids(p, mem_ctx, &lr);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("LookupRids failed - %s\n", nt_errstr(status));
+               ret = False;
+       }
+
        return ret;     
 }
 
@@ -121,6 +1056,8 @@ static BOOL test_EnumDomainGroups(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        NTSTATUS status;
        struct samr_EnumDomainGroups r;
        uint32 resume_handle=0;
+       int i;
+       BOOL ret = True;
 
        printf("Testing EnumDomainGroups\n");
 
@@ -135,9 +1072,17 @@ static BOOL test_EnumDomainGroups(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                return False;
        }
        
-       NDR_PRINT_DEBUG(samr_SamArray, r.out.sam);
+       if (!r.out.sam) {
+               return False;
+       }
 
-       return True;    
+       for (i=0;i<r.out.sam->count;i++) {
+               if (!test_OpenGroup(p, mem_ctx, handle, r.out.sam->entries[i].idx)) {
+                       ret = False;
+               }
+       }
+
+       return ret;
 }
 
 static BOOL test_EnumDomainAliases(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
@@ -146,6 +1091,8 @@ static BOOL test_EnumDomainAliases(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        NTSTATUS status;
        struct samr_EnumDomainAliases r;
        uint32 resume_handle=0;
+       int i;
+       BOOL ret = True;
 
        printf("Testing EnumDomainAliases\n");
 
@@ -160,9 +1107,46 @@ static BOOL test_EnumDomainAliases(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                return False;
        }
        
-       NDR_PRINT_DEBUG(samr_SamArray, r.out.sam);
+       if (!r.out.sam) {
+               return False;
+       }
 
-       return True;    
+       for (i=0;i<r.out.sam->count;i++) {
+               if (!test_OpenAlias(p, mem_ctx, handle, r.out.sam->entries[i].idx)) {
+                       ret = False;
+               }
+       }
+
+       return ret;     
+}
+
+static BOOL test_QueryDisplayInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+                                 struct policy_handle *handle)
+{
+       NTSTATUS status;
+       struct samr_QueryDisplayInfo r;
+       BOOL ret = True;
+       uint16 levels[] = {1, 2, 3, 4, 5};
+       int i;
+
+       for (i=0;i<ARRAY_SIZE(levels);i++) {
+               printf("Testing QueryDisplayInfo level %u\n", levels[i]);
+
+               r.in.handle = handle;
+               r.in.level = levels[i];
+               r.in.start_idx = 0;
+               r.in.max_entries = 1000;
+               r.in.buf_size = (uint32)-1;
+
+               status = dcerpc_samr_QueryDisplayInfo(p, mem_ctx, &r);
+               if (!NT_STATUS_IS_OK(status)) {
+                       printf("QueryDisplayInfo level %u failed - %s\n", 
+                              levels[i], nt_errstr(status));
+                       ret = False;
+               }
+       }
+       
+       return ret;     
 }
 
 static BOOL test_QueryDomainInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
@@ -187,19 +1171,23 @@ static BOOL test_QueryDomainInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                        ret = False;
                        continue;
                }
-
-               NDR_PRINT_UNION_DEBUG(samr_DomainInfo, r.in.level, r.out.info);
        }
 
        return True;    
 }
 
 static BOOL test_OpenDomain(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
-                           struct policy_handle *handle, struct dom_sid2 *sid)
+                           struct policy_handle *handle, struct dom_sid *sid)
 {
        NTSTATUS status;
        struct samr_OpenDomain r;
        struct policy_handle domain_handle;
+       struct policy_handle user_handle;
+       struct policy_handle alias_handle;
+       BOOL ret = True;
+
+       ZERO_STRUCT(user_handle);
+       ZERO_STRUCT(alias_handle);
 
        printf("Testing OpenDomain\n");
 
@@ -214,23 +1202,57 @@ static BOOL test_OpenDomain(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                return False;
        }
 
+       if (!test_CreateUser2(p, mem_ctx, &domain_handle)) {
+               ret = False;
+       }
+
+       if (!test_CreateUser(p, mem_ctx, &domain_handle, &user_handle)) {
+               ret = False;
+       }
+
+       if (!test_CreateAlias(p, mem_ctx, &domain_handle, &alias_handle, sid)) {
+               ret = False;
+       }
+
+       if (!test_QuerySecurity(p, mem_ctx, &domain_handle)) {
+               ret = False;
+       }
+
        if (!test_QueryDomainInfo(p, mem_ctx, &domain_handle)) {
-               return False;
+               ret = False;
        }
 
        if (!test_EnumDomainUsers(p, mem_ctx, &domain_handle)) {
-               return False;
+               ret = False;
        }
 
        if (!test_EnumDomainGroups(p, mem_ctx, &domain_handle)) {
-               return False;
+               ret = False;
        }
 
        if (!test_EnumDomainAliases(p, mem_ctx, &domain_handle)) {
-               return False;
+               ret = False;
        }
 
-       return True;    
+       if (!test_QueryDisplayInfo(p, mem_ctx, &domain_handle)) {
+               ret = False;
+       }
+
+       if (!policy_handle_empty(&user_handle) &&
+           !test_DeleteUser(p, mem_ctx, &user_handle)) {
+               ret = False;
+       }
+
+       if (!policy_handle_empty(&alias_handle) &&
+           !test_DeleteAlias(p,mem_ctx, &alias_handle)) {
+               ret = False;
+       }
+
+       if (!test_Close(p, mem_ctx, &domain_handle)) {
+               ret = False;
+       }
+
+       return ret;
 }
 
 static BOOL test_LookupDomain(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
@@ -250,8 +1272,6 @@ static BOOL test_LookupDomain(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                return False;
        }
 
-       NDR_PRINT_DEBUG(dom_sid2, r.out.sid);
-
        if (!test_OpenDomain(p, mem_ctx, handle, r.out.sid)) {
                return False;
        }
@@ -266,7 +1286,6 @@ static BOOL test_EnumDomains(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        NTSTATUS status;
        struct samr_EnumDomains r;
        uint32 resume_handle = 0;
-       uint32 num_entries=0;
        int i;
        BOOL ret = True;
 
@@ -274,7 +1293,6 @@ static BOOL test_EnumDomains(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        r.in.resume_handle = &resume_handle;
        r.in.buf_size = (uint32)-1;
        r.out.resume_handle = &resume_handle;
-       r.out.num_entries = &num_entries;
 
        status = dcerpc_samr_EnumDomains(p, mem_ctx, &r);
        if (!NT_STATUS_IS_OK(status)) {
@@ -282,8 +1300,6 @@ static BOOL test_EnumDomains(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                return False;
        }
 
-       NDR_PRINT_DEBUG(samr_SamArray, r.out.sam);
-
        if (!r.out.sam) {
                return False;
        }
@@ -304,7 +1320,10 @@ static BOOL test_Connect(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 {
        NTSTATUS status;
        struct samr_Connect r;
+       struct samr_Connect2 r2;
        struct samr_Connect4 r4;
+       struct samr_Connect5 r5;
+       BOOL ret = True;
 
        r.in.system_name = 0;
        r.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
@@ -313,7 +1332,17 @@ static BOOL test_Connect(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        status = dcerpc_samr_Connect(p, mem_ctx, &r);
        if (!NT_STATUS_IS_OK(status)) {
                printf("Connect failed - %s\n", nt_errstr(status));
-               return False;
+               ret = False;
+       }
+
+       r2.in.system_name = "";
+       r2.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
+       r2.out.handle = handle;
+
+       status = dcerpc_samr_Connect2(p, mem_ctx, &r2);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("Connect2 failed - %s\n", nt_errstr(status));
+               ret = False;
        }
 
        r4.in.system_name = "";
@@ -324,10 +1353,27 @@ static BOOL test_Connect(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        status = dcerpc_samr_Connect4(p, mem_ctx, &r4);
        if (!NT_STATUS_IS_OK(status)) {
                printf("Connect4 failed - %s\n", nt_errstr(status));
-               return False;
+               ret = False;
        }
 
-       return True;
+       r5.in.system_name = "";
+       r5.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
+       r5.in.unknown0 = 1; /*Magic values I took from a WinXP pro workstation       */
+       r5.in.unknown1 = 1; /*tests failed with NT_STATUS_NET_WRITE_FAULT if         */
+       r5.in.unknown2 = 3; /*unknown0 and unknown1 where something other than 1     */
+       r5.in.unknown3 = 0; /*unkown2 and unknown3 could be varied and had no effect */
+       r5.out.handle = handle;
+
+       status = dcerpc_samr_Connect5(p, mem_ctx, &r5);
+       if (!NT_STATUS_IS_OK(status)) {
+               /*This fails for a Win2000pro machine, but succeeds for
+                 WinXPpro  --  Kai
+                */
+               printf("Connect5 failed - %s\n", nt_errstr(status));
+               /*ret = False; Should this test fail? */
+       }
+
+       return ret;
 }
 
 
@@ -341,19 +1387,32 @@ BOOL torture_rpc_samr(int dummy)
 
        mem_ctx = talloc_init("torture_rpc_samr");
 
-       status = torture_rpc_connection(&p, "samr");
+       status = torture_rpc_connection(&p, 
+                                       DCERPC_SAMR_NAME,
+                                       DCERPC_SAMR_UUID,
+                                       DCERPC_SAMR_VERSION);
        if (!NT_STATUS_IS_OK(status)) {
                return False;
        }
-       
+
        if (!test_Connect(p, mem_ctx, &handle)) {
                ret = False;
        }
 
+       if (!test_QuerySecurity(p, mem_ctx, &handle)) {
+               ret = False;
+       }
+
        if (!test_EnumDomains(p, mem_ctx, &handle)) {
                ret = False;
        }
 
+       if (!test_Close(p, mem_ctx, &handle)) {
+               ret = False;
+       }
+
+       talloc_destroy(mem_ctx);
+
         torture_rpc_close(p);
 
        return ret;