r23792: convert Samba4 to GPLv3
[ira/wip.git] / source4 / torture / rpc / drsuapi.c
index 88ff85d8da72d9771f62bcac6f70af18395e569f..5b2e92cf36a178e5b19fb0e4bc5d37e857375b02 100644 (file)
@@ -5,10 +5,11 @@
 
    Copyright (C) Andrew Tridgell 2003
    Copyright (C) Stefan (metze) Metzmacher 2004
-   
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2006
+
    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
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
-#include "librpc/gen_ndr/ndr_drsuapi.h"
-
-struct DsPrivate {
-       struct policy_handle bind_handle;
-       struct GUID bind_guid;
-       const char *domain_obj_dn;
-       const char *domain_guid_str;
-       const char *domain_dns_name;
-       struct GUID domain_guid;
-       struct drsuapi_DsGetDCInfo2 dcinfo;
-};
-
-static BOOL test_DsBind(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
-                     struct DsPrivate *priv)
+#include "torture/torture.h"
+#include "librpc/gen_ndr/ndr_drsuapi_c.h"
+#include "torture/rpc/rpc.h"
+
+#define TEST_MACHINE_NAME "torturetest"
+
+BOOL test_DsBind(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+                struct DsPrivate *priv)
 {
        NTSTATUS status;
        struct drsuapi_DsBind r;
@@ -65,454 +59,125 @@ static BOOL test_DsBind(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        return ret;
 }
 
-static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+static BOOL test_DsGetDomainControllerInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
                      struct DsPrivate *priv)
 {
        NTSTATUS status;
-       struct drsuapi_DsCrackNames r;
-       struct drsuapi_DsNameString names[1];
+       struct drsuapi_DsGetDomainControllerInfo r;
        BOOL ret = True;
-       const char *dns_domain;
-       const char *nt4_domain;
-       const char *FQDN_1779_name;
-
-       ZERO_STRUCT(r);
-       r.in.bind_handle                = &priv->bind_handle;
-       r.in.level                      = 1;
-       r.in.req.req1.unknown1          = 0x000004e4;
-       r.in.req.req1.unknown2          = 0x00000407;
-       r.in.req.req1.count             = 1;
-       r.in.req.req1.names             = names;
-       r.in.req.req1.format_flags      = DRSUAPI_DS_NAME_FLAG_NO_FLAGS;
-
-       r.in.req.req1.format_offered    = DRSUAPI_DS_NAME_FORMAT_CANONICAL;
-       r.in.req.req1.format_desired    = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;
-       names[0].str = talloc_asprintf(mem_ctx, "%s/", lp_realm());
-
-       printf("testing DsCrackNames with name '%s' desired format:%d\n",
-                       names[0].str, r.in.req.req1.format_desired);
-
-       status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       }
-
-       if (!ret) {
-               return ret;
-       }
-
-       dns_domain = r.out.ctr.ctr1->array[0].dns_domain_name;
-       nt4_domain = r.out.ctr.ctr1->array[0].result_name;
-
-       r.in.req.req1.format_desired    = DRSUAPI_DS_NAME_FORMAT_GUID;
-
-       printf("testing DsCrackNames with name '%s' desired format:%d\n",
-                       names[0].str, r.in.req.req1.format_desired);
-
-       status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       }
-
-       if (!ret) {
-               return ret;
-       }
-
-       priv->domain_dns_name = r.out.ctr.ctr1->array[0].dns_domain_name;
-       priv->domain_guid_str = r.out.ctr.ctr1->array[0].result_name;
-       GUID_from_string(priv->domain_guid_str, &priv->domain_guid);
-
-
-       r.in.req.req1.format_offered    = DRSUAPI_DS_NAME_FORMAT_GUID;
-       r.in.req.req1.format_desired    = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;
-       names[0].str = priv->domain_guid_str;
-
-       printf("testing DsCrackNames with name '%s' desired format:%d\n",
-                       names[0].str, r.in.req.req1.format_desired);
-
-       status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       }
-
-       if (!ret) {
-               return ret;
-       }
-
-       r.in.req.req1.format_offered    = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;
-       r.in.req.req1.format_desired    = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
-       names[0].str = nt4_domain;
-
-       printf("testing DsCrackNames with name '%s' desired format:%d\n",
-                       names[0].str, r.in.req.req1.format_desired);
-
-       status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       }
-
-       if (!ret) {
-               return ret;
-       }
-
-       priv->domain_obj_dn = r.out.ctr.ctr1->array[0].result_name;
-
-       r.in.req.req1.format_offered    = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;
-       r.in.req.req1.format_desired    = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
-       names[0].str = talloc_asprintf(mem_ctx, "%s%s$", nt4_domain, priv->dcinfo.netbios_name);
-
-       printf("testing DsCrackNames with name '%s' desired format:%d\n",
-                       names[0].str, r.in.req.req1.format_desired);
-
-       status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       }
-
-       if (!ret) {
-               return ret;
-       }
-
-       FQDN_1779_name = r.out.ctr.ctr1->array[0].result_name;
-
-       r.in.req.req1.format_offered    = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
-       r.in.req.req1.format_desired    = DRSUAPI_DS_NAME_FORMAT_CANONICAL;
-       names[0].str = FQDN_1779_name;
-
-       printf("testing DsCrackNames with name '%s' desired format:%d\n",
-                       names[0].str, r.in.req.req1.format_desired);
-
-       status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       }
-
-       if (!ret) {
-               return ret;
-       }
-
-       r.in.req.req1.format_desired    = DRSUAPI_DS_NAME_FORMAT_DISPLAY;
-
-       printf("testing DsCrackNames with name '%s' desired format:%d\n",
-                       names[0].str, r.in.req.req1.format_desired);
-
-       status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       }
-
-       if (!ret) {
-               return ret;
-       }
-
-       r.in.req.req1.format_desired    = DRSUAPI_DS_NAME_FORMAT_GUID;
-
-       printf("testing DsCrackNames with name '%s' desired format:%d\n",
-                       names[0].str, r.in.req.req1.format_desired);
-
-       status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       }
-
-       if (!ret) {
-               return ret;
-       }
-
-       r.in.req.req1.format_desired    = DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL;
-
-       printf("testing DsCrackNames with name '%s' desired format:%d\n",
-                       names[0].str, r.in.req.req1.format_desired);
-
-       status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       }
-
-       if (!ret) {
-               return ret;
-       }
-
-       r.in.req.req1.format_desired    = DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL;
-
-       printf("testing DsCrackNames with name '%s' desired format:%d\n",
-                       names[0].str, r.in.req.req1.format_desired);
-
-       status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       }
-
-       if (!ret) {
-               return ret;
-       }
-
-       r.in.req.req1.format_offered    = DRSUAPI_DS_NAME_FORMAT_GUID;
-       r.in.req.req1.format_desired    = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
-       names[0].str = GUID_string2(mem_ctx, &priv->dcinfo.site_guid);
-
-       printf("testing DsCrackNames with Site GUID '%s' desired format:%d\n",
-                       names[0].str, r.in.req.req1.format_desired);
-
-       status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       }
-
-       if (!ret) {
-               return ret;
-       }
-
-       r.in.req.req1.format_desired    = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;
-       names[0].str = GUID_string2(mem_ctx, &priv->dcinfo.computer_guid);
-
-       printf("testing DsCrackNames with Computer GUID '%s' desired format:%d\n",
-                       names[0].str, r.in.req.req1.format_desired);
-
-       status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       }
-
-       if (!ret) {
-               return ret;
-       }
-
-       r.in.req.req1.format_offered    = DRSUAPI_DS_NAME_FORMAT_GUID;
-       r.in.req.req1.format_desired    = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
-       names[0].str = GUID_string2(mem_ctx, &priv->dcinfo.server_guid);
-
-       printf("testing DsCrackNames with Server GUID '%s' desired format:%d\n",
-                       names[0].str, r.in.req.req1.format_desired);
-
-       status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       }
-
-       if (!ret) {
-               return ret;
-       }
-
-       r.in.req.req1.format_offered    = DRSUAPI_DS_NAME_FORMAT_GUID;
-       r.in.req.req1.format_desired    = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
-       names[0].str = GUID_string2(mem_ctx, &priv->dcinfo.ntds_guid);
-
-       printf("testing DsCrackNames with NTDS GUID '%s' desired format:%d\n",
-                       names[0].str, r.in.req.req1.format_desired);
-
-       status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       }
-
-       if (!ret) {
-               return ret;
-       }
-
-       r.in.req.req1.format_offered    = DRSUAPI_DS_NAME_FORMAT_GUID;
-       r.in.req.req1.format_desired    = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
-       names[0].str = GUID_string2(mem_ctx, &priv->bind_guid);
-
-       printf("testing DsCrackNames with BIND GUID '%s' desired format:%d\n",
-                       names[0].str, r.in.req.req1.format_desired);
+       BOOL found = False;
+       int i, j, k;
+       
+       struct {
+               const char *name;
+               WERROR expected;
+       } names[] = { 
+               {       
+                       .name = torture_join_dom_netbios_name(priv->join),
+                       .expected = WERR_OK
+               },
+               {
+                       .name = torture_join_dom_dns_name(priv->join),
+                       .expected = WERR_OK
+               },
+               {
+                       .name = "__UNKNOWN_DOMAIN__",
+                       .expected = WERR_DS_OBJ_NOT_FOUND
+               },
+               {
+                       .name = "unknown.domain.samba.example.com",
+                       .expected = WERR_DS_OBJ_NOT_FOUND
+               },
+       };
+       int levels[] = {1, 2};
+       int level;
+
+       for (i=0; i < ARRAY_SIZE(levels); i++) {
+               for (j=0; j < ARRAY_SIZE(names); j++) {
+                       level = levels[i];
+                       r.in.bind_handle = &priv->bind_handle;
+                       r.in.level = 1;
+                       
+                       r.in.req.req1.domain_name = names[j].name;
+                       r.in.req.req1.level = level;
+                       
+                       printf("testing DsGetDomainControllerInfo level %d on domainname '%s'\n",
+                              r.in.req.req1.level, r.in.req.req1.domain_name);
+               
+                       status = dcerpc_drsuapi_DsGetDomainControllerInfo(p, mem_ctx, &r);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               const char *errstr = nt_errstr(status);
+                               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
+                                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
+                               }
+                               printf("dcerpc_drsuapi_DsGetDomainControllerInfo level %d\n"
+                                      "    with dns domain failed - %s\n",
+                                      r.in.req.req1.level, errstr);
+                               ret = False;
+                       } else if (!W_ERROR_EQUAL(r.out.result, names[j].expected)) {
+                               printf("DsGetDomainControllerInfo level %d\n"
+                                      "    with dns domain failed - %s, expected %s\n",
+                                      r.in.req.req1.level, win_errstr(r.out.result),
+                                      win_errstr(names[j].expected));
+                               ret = False;
+                       }
+               
+                       if (!W_ERROR_IS_OK(r.out.result)) {
+                               /* If this was an error, we can't read the result structure */
+                               continue;
+                       }
 
-       status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
+                       if (r.in.req.req1.level != r.out.level_out) {
+                               printf("dcerpc_drsuapi_DsGetDomainControllerInfo level in (%d) != out (%d)\n",
+                                      r.in.req.req1.level, r.out.level_out);
+                               ret = False;
+                               /* We can't safely read the result structure */
+                               continue;
+                       }
+                       switch (level) {
+                       case 1:
+                               for (k=0; k < r.out.ctr.ctr1.count; k++) {
+                                       if (strcasecmp_m(r.out.ctr.ctr1.array[k].netbios_name, 
+                                                        torture_join_netbios_name(priv->join)) == 0) {
+                                               found = True;
+                                               break;
+                                       }
+                               }
+                               break;
+                       case 2:
+                               for (k=0; k < r.out.ctr.ctr2.count; k++) {
+                                       if (strcasecmp_m(r.out.ctr.ctr2.array[k].netbios_name, 
+                                                        torture_join_netbios_name(priv->join)) == 0) {
+                                               found = True;
+                                               priv->dcinfo    = r.out.ctr.ctr2.array[k];
+                                               break;
+                                       }
+                               }
+                               break;
+                       }
+                       if (!found) {
+                               printf("dcerpc_drsuapi_DsGetDomainControllerInfo level %d: Failed to find the domain controller (%s) we just created during the join\n",
+                                      r.in.req.req1.level,
+                                      torture_join_netbios_name(priv->join));
+                               ret = False;
+                       }
                }
-               printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
        }
 
-       if (!ret) {
+       if (lp_parm_bool(-1, "torture", "samba4", False)) {
+               printf("skipping DsGetDomainControllerInfo level -1 test against Samba4\n");
                return ret;
        }
 
-       return ret;
-}
-
-static BOOL test_DsGetDCInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
-                     struct DsPrivate *priv)
-{
-       NTSTATUS status;
-       struct drsuapi_DsGetDomainControllerInfo r;
-       BOOL ret = True;
-
        r.in.bind_handle = &priv->bind_handle;
        r.in.level = 1;
-
-       r.in.req.req1.domain_name = talloc_strdup(mem_ctx, lp_realm());
-       r.in.req.req1.level = 1;
-
-       printf("testing DsGetDomainControllerInfo level %d on domainname '%s'\n",
-                       r.in.req.req1.level, r.in.req.req1.domain_name);
-
-       status = dcerpc_drsuapi_DsGetDomainControllerInfo(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsGetDomainControllerInfo level %d\n"
-                       "    with dns domain failed - %s\n",
-                       r.in.req.req1.level, errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsGetDomainControllerInfo level %d\n"
-                       "    with dns domain failed - %s\n",
-                       r.in.req.req1.level, win_errstr(r.out.result));
-               ret = False;
-       }
-
-       r.in.req.req1.level = 2;
-
-       printf("testing DsGetDomainControllerInfo level %d on domainname '%s'\n",
-                       r.in.req.req1.level, r.in.req.req1.domain_name);
-
-       status = dcerpc_drsuapi_DsGetDomainControllerInfo(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsGetDomainControllerInfo level %d\n"
-                       "    with dns domain failed - %s\n",
-                       r.in.req.req1.level, errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsGetDomainControllerInfo level %d\n"
-                       "    with dns domain failed - %s\n",
-                       r.in.req.req1.level, win_errstr(r.out.result));
-               ret = False;
-       } else {
-               if (r.out.ctr.ctr2.count > 0) {
-                       priv->dcinfo    = r.out.ctr.ctr2.array[0];
-               }
-       }
-
+       
+       r.in.req.req1.domain_name = "__UNKNOWN_DOMAIN__"; /* This is clearly ignored for this level */
        r.in.req.req1.level = -1;
-
+       
        printf("testing DsGetDomainControllerInfo level %d on domainname '%s'\n",
-                       r.in.req.req1.level, r.in.req.req1.domain_name);
-
+              r.in.req.req1.level, r.in.req.req1.domain_name);
+       
        status = dcerpc_drsuapi_DsGetDomainControllerInfo(p, mem_ctx, &r);
        if (!NT_STATUS_IS_OK(status)) {
                const char *errstr = nt_errstr(status);
@@ -520,67 +185,41 @@ static BOOL test_DsGetDCInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                        errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
                }
                printf("dcerpc_drsuapi_DsGetDomainControllerInfo level %d\n"
-                       "    with dns domain failed - %s\n",
-                       r.in.req.req1.level, errstr);
+                      "    with dns domain failed - %s\n",
+                                      r.in.req.req1.level, errstr);
                ret = False;
        } else if (!W_ERROR_IS_OK(r.out.result)) {
                printf("DsGetDomainControllerInfo level %d\n"
-                       "    with dns domain failed - %s\n",
-                       r.in.req.req1.level, win_errstr(r.out.result));
+                      "    with dns domain failed - %s\n",
+                      r.in.req.req1.level, win_errstr(r.out.result));
                ret = False;
        }
-
-       r.in.req.req1.domain_name = talloc_strdup(mem_ctx, lp_workgroup());
-       r.in.req.req1.level = 2;
-
-       printf("testing DsGetDomainControllerInfo level %d on domainname '%s'\n",
-                       r.in.req.req1.level, r.in.req.req1.domain_name);
-
-       status = dcerpc_drsuapi_DsGetDomainControllerInfo(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
+       
+       {
+               const char *dc_account = talloc_asprintf(mem_ctx, "%s\\%s$",
+                                                        torture_join_dom_netbios_name(priv->join), 
+                                                        priv->dcinfo.netbios_name);
+               for (k=0; k < r.out.ctr.ctr01.count; k++) {
+                       if (strcasecmp_m(r.out.ctr.ctr01.array[k].client_account, 
+                                        dc_account)) {
+                               found = True;
+                               break;
+                       }
                }
-               printf("dcerpc_drsuapi_DsGetDomainControllerInfo level %d\n"
-                       "    with netbios domain failed - %s\n",
-                       r.in.req.req1.level, errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsGetDomainControllerInfo level %d\n"
-                       "    with netbios domain failed - %s\n",
-                       r.in.req.req1.level, win_errstr(r.out.result));
-               ret = False;
-       }
-
-       r.in.req.req1.domain_name = "__UNKNOWN_DOMAIN__";
-       r.in.req.req1.level = 2;
-
-       printf("testing DsGetDomainControllerInfo level %d on domainname '%s'\n",
-                       r.in.req.req1.level, r.in.req.req1.domain_name);
-
-       status = dcerpc_drsuapi_DsGetDomainControllerInfo(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
+               if (!found) {
+                       printf("dcerpc_drsuapi_DsGetDomainControllerInfo level %d: Failed to find the domain controller (%s) in last logon records\n",
+                              r.in.req.req1.level,
+                              dc_account);
+                       ret = False;
                }
-               printf("dcerpc_drsuapi_DsGetDomainControllerInfo level %d\n"
-                       "    with invalid domain failed - %s\n",
-                       r.in.req.req1.level, errstr);
-               ret = False;
-       } else if (!W_ERROR_EQUAL(r.out.result, WERR_DS_OBJ_NOT_FOUND)) {
-               printf("DsGetDomainControllerInfo level %d\n"
-                       "    with invalid domain not expected error (WERR_DS_OBJ_NOT_FOUND) - %s\n",
-                       r.in.req.req1.level, win_errstr(r.out.result));
-               ret = False;
        }
 
+
        return ret;
 }
 
 static BOOL test_DsWriteAccountSpn(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
-                       struct DsPrivate *priv)
+                                  struct DsPrivate *priv)
 {
        NTSTATUS status;
        struct drsuapi_DsWriteAccountSpn r;
@@ -698,7 +337,7 @@ static BOOL test_DsReplicaGetInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                        "__IGNORED__"
                },{
                        DRSUAPI_DS_REPLICA_GET_INFO2,
-                       DRSUAPI_DS_REPLICA_INFO_CURSURS05,
+                       DRSUAPI_DS_REPLICA_INFO_CURSORS05,
                        NULL
                },{
                        DRSUAPI_DS_REPLICA_GET_INFO2,
@@ -707,6 +346,11 @@ static BOOL test_DsReplicaGetInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                }
        };
 
+       if (lp_parm_bool(-1, "torture", "samba4", False)) {
+               printf("skipping DsReplicaGetInfo test against Samba4\n");
+               return True;
+       }
+
        r.in.bind_handle        = &priv->bind_handle;
 
        for (i=0; i < ARRAY_SIZE(array); i++) {
@@ -780,6 +424,11 @@ static BOOL test_DsReplicaSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                return True;
        }
 
+       if (lp_parm_bool(-1, "torture", "samba4", False)) {
+               printf("skipping DsReplicaSync test against Samba4\n");
+               return True;
+       }
+
        ZERO_STRUCT(null_guid);
        ZERO_STRUCT(null_sid);
 
@@ -797,8 +446,8 @@ static BOOL test_DsReplicaSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                        nc.dn                                   = priv->domain_obj_dn?priv->domain_obj_dn:"";
 
                        r.in.req.req1.naming_context            = &nc;
-                       r.in.req.req1.guid1                     = priv->dcinfo.ntds_guid;
-                       r.in.req.req1.string1                   = NULL;
+                       r.in.req.req1.source_dsa_guid           = priv->dcinfo.ntds_guid;
+                       r.in.req.req1.other_info                = NULL;
                        r.in.req.req1.options                   = 16;
                        break;
                }
@@ -838,6 +487,11 @@ static BOOL test_DsReplicaUpdateRefs(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                }
        };
 
+       if (lp_parm_bool(-1, "torture", "samba4", False)) {
+               printf("skipping DsReplicaUpdateRefs test against Samba4\n");
+               return True;
+       }
+
        ZERO_STRUCT(null_guid);
        ZERO_STRUCT(null_sid);
 
@@ -900,57 +554,76 @@ static BOOL test_DsGetNCChanges(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                }
        };
 
+       if (lp_parm_bool(-1, "torture", "samba4", False)) {
+               printf("skipping DsGetNCChanges test against Samba4\n");
+               return True;
+       }
+
        ZERO_STRUCT(null_guid);
        ZERO_STRUCT(null_sid);
-       
+
        for (i=0; i < ARRAY_SIZE(array); i++) {
                printf("testing DsGetNCChanges level %d\n",
                        array[i].level);
 
                r.in.bind_handle        = &priv->bind_handle;
-               r.in.level              = array[i].level;
+               r.in.level              = &array[i].level;
 
-               switch (r.in.level) {
+               switch (*r.in.level) {
                case 5:
-                       nc.guid                         = null_guid;
-                       nc.sid                          = null_sid;
-                       nc.dn                           = priv->domain_obj_dn?priv->domain_obj_dn:"";
-
-                       r.in.req.req5.guid1             = null_guid;
-                       r.in.req.req5.guid2             = null_guid;
-                       r.in.req.req5.naming_context    = &nc;
-                       r.in.req.req5.usn1.usn1         = 0;
-                       r.in.req.req5.usn1.usn2         = 0;
-                       r.in.req.req5.usn1.usn3         = 0;
-                       r.in.req.req5.coursor           = NULL;
-                       r.in.req.req5.unknown1          = 0;/*0x10201C70;*/
-                       r.in.req.req5.unknown2          = 0;/*402;*/
-                       r.in.req.req5.unknown3          = 0;/*402116;*/
-                       r.in.req.req5.unknown4          = 0;
-                       r.in.req.req5.h1                = 0;
+                       nc.guid = null_guid;
+                       nc.sid  = null_sid;
+                       nc.dn   = priv->domain_obj_dn?priv->domain_obj_dn:"";
+
+                       r.in.req.req5.destination_dsa_guid              = GUID_random();
+                       r.in.req.req5.source_dsa_invocation_id          = null_guid;
+                       r.in.req.req5.naming_context                    = &nc;
+                       r.in.req.req5.highwatermark.tmp_highest_usn     = 0;
+                       r.in.req.req5.highwatermark.reserved_usn        = 0;
+                       r.in.req.req5.highwatermark.highest_usn         = 0;
+                       r.in.req.req5.uptodateness_vector               = NULL;
+                       r.in.req.req5.replica_flags                     = 0;
+                       if (lp_parm_bool(-1, "drsuapi","compression", False)) {
+                               r.in.req.req5.replica_flags             |= DRSUAPI_DS_REPLICA_NEIGHBOUR_COMPRESS_CHANGES;
+                       }
+                       r.in.req.req5.max_object_count                  = 0;
+                       r.in.req.req5.max_ndr_size                      = 0;
+                       r.in.req.req5.unknown4                          = 0;
+                       r.in.req.req5.h1                                = 0;
 
                        break;
                case 8:
-                       nc.guid                         = null_guid;
-                       nc.sid                          = null_sid;
-                       nc.dn                           = priv->domain_obj_dn?priv->domain_obj_dn:"";
-
-                       r.in.req.req8.guid1             = null_guid;
-                       r.in.req.req8.guid2             = null_guid;
-                       r.in.req.req8.naming_context    = &nc;
-                       r.in.req.req8.usn1.usn1         = 0;
-                       r.in.req.req8.usn1.usn2         = 0;
-                       r.in.req.req8.usn1.usn3         = 0;
-                       r.in.req.req8.coursor           = NULL;
-                       r.in.req.req8.unknown1          = 0;/*0x10201C70;*/
-                       r.in.req.req8.unknown2          = 0;/*402;*/
-                       r.in.req.req8.unknown3          = 0;/*402116;*/
-                       r.in.req.req8.unknown4          = 0;
-                       r.in.req.req8.h1                = 0;
-                       r.in.req.req8.unique_ptr1       = 0;
-                       r.in.req.req8.unique_ptr2       = 0;
-                       r.in.req.req8.ctr12.count       = 0;
-                       r.in.req.req8.ctr12.array       = NULL;
+                       nc.guid = null_guid;
+                       nc.sid  = null_sid;
+                       nc.dn   = priv->domain_obj_dn?priv->domain_obj_dn:"";
+
+                       r.in.req.req8.destination_dsa_guid              = GUID_random();
+                       r.in.req.req8.source_dsa_invocation_id          = null_guid;
+                       r.in.req.req8.naming_context                    = &nc;
+                       r.in.req.req8.highwatermark.tmp_highest_usn     = 0;
+                       r.in.req.req8.highwatermark.reserved_usn        = 0;
+                       r.in.req.req8.highwatermark.highest_usn         = 0;
+                       r.in.req.req8.uptodateness_vector               = NULL;
+                       r.in.req.req8.replica_flags                     = 0;
+                       if (lp_parm_bool(-1,"drsuapi","compression",False)) {
+                               r.in.req.req8.replica_flags             |= DRSUAPI_DS_REPLICA_NEIGHBOUR_COMPRESS_CHANGES;
+                       }
+                       if (lp_parm_bool(-1,"drsuapi","neighbour_writeable",True)) {
+                               r.in.req.req8.replica_flags             |= DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE;
+                       }
+                       r.in.req.req8.replica_flags                     |= DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
+                                                                       | DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS
+                                                                       | DRSUAPI_DS_REPLICA_NEIGHBOUR_RETURN_OBJECT_PARENTS
+                                                                       | DRSUAPI_DS_REPLICA_NEIGHBOUR_NEVER_SYNCED
+                                                                       ;
+                       r.in.req.req8.max_object_count                  = 402;
+                       r.in.req.req8.max_ndr_size                      = 402116;
+                       r.in.req.req8.unknown4                          = 0;
+                       r.in.req.req8.h1                                = 0;
+                       r.in.req.req8.unique_ptr1                       = 0;
+                       r.in.req.req8.unique_ptr2                       = 0;
+                       r.in.req.req8.mapping_ctr.num_mappings          = 0;
+                       r.in.req.req8.mapping_ctr.mappings              = NULL;
 
                        break;
                }
@@ -972,8 +645,63 @@ static BOOL test_DsGetNCChanges(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        return ret;
 }
 
-static BOOL test_DsUnbind(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
-                       struct DsPrivate *priv)
+BOOL test_QuerySitesByCost(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+                          struct DsPrivate *priv)
+{
+       NTSTATUS status;
+       struct drsuapi_QuerySitesByCost r;
+       BOOL ret = True;
+
+       const char *my_site = "Default-First-Site-Name";
+       const char *remote_site1 = "smbtorture-nonexisting-site1";
+       const char *remote_site2 = "smbtorture-nonexisting-site2";
+
+       r.in.bind_handle = &priv->bind_handle;
+       r.in.level = 1;
+       r.in.req.req1.site_from = talloc_strdup(mem_ctx, my_site);
+       r.in.req.req1.num_req = 2;
+       r.in.req.req1.site_to = talloc_zero_array(mem_ctx, const char *, r.in.req.req1.num_req);
+       r.in.req.req1.site_to[0] = talloc_strdup(mem_ctx, remote_site1);
+       r.in.req.req1.site_to[1] = talloc_strdup(mem_ctx, remote_site2);
+       r.in.req.req1.flags = 0;
+
+       status = dcerpc_drsuapi_QuerySitesByCost(p, mem_ctx, &r);
+       if (!NT_STATUS_IS_OK(status)) {
+               const char *errstr = nt_errstr(status);
+               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
+                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
+               }
+               printf("drsuapi_QuerySitesByCost - %s\n", errstr);
+               ret = False;
+       } else if (!W_ERROR_IS_OK(r.out.result)) {
+               printf("QuerySitesByCost failed - %s\n", win_errstr(r.out.result));
+               ret = False;
+       }
+
+       if (W_ERROR_IS_OK(r.out.result)) {
+
+               if (!W_ERROR_EQUAL(r.out.ctr.ctr1.info[0].error_code, WERR_DS_OBJ_NOT_FOUND) ||
+                   !W_ERROR_EQUAL(r.out.ctr.ctr1.info[1].error_code, WERR_DS_OBJ_NOT_FOUND)) { 
+                       printf("expected error_code WERR_DS_OBJ_NOT_FOUND, got %s\n", 
+                               win_errstr(r.out.ctr.ctr1.info[0].error_code));
+                       ret = False;
+               }
+
+               if ((r.out.ctr.ctr1.info[0].site_cost != (uint32_t) -1) ||
+                   (r.out.ctr.ctr1.info[1].site_cost != (uint32_t) -1)) {
+                       printf("expected site_cost %d, got %d\n", 
+                               (uint32_t) -1, r.out.ctr.ctr1.info[0].site_cost);
+                       ret = False;
+               }
+       }
+
+       return ret;
+
+
+}
+
+BOOL test_DsUnbind(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+                  struct DsPrivate *priv)
 {
        NTSTATUS status;
        struct drsuapi_DsUnbind r;
@@ -1000,33 +728,41 @@ static BOOL test_DsUnbind(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        return ret;
 }
 
-BOOL torture_rpc_drsuapi(void)
+BOOL torture_rpc_drsuapi(struct torture_context *torture)
 {
         NTSTATUS status;
         struct dcerpc_pipe *p;
        TALLOC_CTX *mem_ctx;
        BOOL ret = True;
        struct DsPrivate priv;
+       struct cli_credentials *machine_credentials;
 
        mem_ctx = talloc_init("torture_rpc_drsuapi");
 
+       ZERO_STRUCT(priv);
+
+       priv.join = torture_join_domain(TEST_MACHINE_NAME, ACB_SVRTRUST, 
+                                      &machine_credentials);
+       if (!priv.join) {
+               talloc_free(mem_ctx);
+               printf("Failed to join as BDC\n");
+               return False;
+       }
+
        status = torture_rpc_connection(mem_ctx, 
                                        &p, 
-                                       DCERPC_DRSUAPI_NAME,
-                                       DCERPC_DRSUAPI_UUID,
-                                       DCERPC_DRSUAPI_VERSION);
+                                       &dcerpc_table_drsuapi);
        if (!NT_STATUS_IS_OK(status)) {
+               torture_leave_domain(priv.join);
                talloc_free(mem_ctx);
                return False;
        }
 
-       printf("Connected to DRAUAPI pipe\n");
-
-       ZERO_STRUCT(priv);
-
        ret &= test_DsBind(p, mem_ctx, &priv);
-
-       ret &= test_DsGetDCInfo(p, mem_ctx, &priv);
+#if 0
+       ret &= test_QuerySitesByCost(p, mem_ctx, &priv);
+#endif
+       ret &= test_DsGetDomainControllerInfo(p, mem_ctx, &priv);
 
        ret &= test_DsCrackNames(p, mem_ctx, &priv);
 
@@ -1044,5 +780,58 @@ BOOL torture_rpc_drsuapi(void)
 
        talloc_free(mem_ctx);
 
+       torture_leave_domain(priv.join);
+
+       return ret;
+}
+
+
+BOOL torture_rpc_drsuapi_cracknames(struct torture_context *torture)
+{
+        NTSTATUS status;
+        struct dcerpc_pipe *p;
+       TALLOC_CTX *mem_ctx;
+       BOOL ret = True;
+       struct DsPrivate priv;
+       struct cli_credentials *machine_credentials;
+
+       mem_ctx = talloc_init("torture_rpc_drsuapi");
+
+       printf("Connected to DRAUAPI pipe\n");
+
+       ZERO_STRUCT(priv);
+
+       priv.join = torture_join_domain(TEST_MACHINE_NAME, ACB_SVRTRUST, 
+                                      &machine_credentials);
+       if (!priv.join) {
+               talloc_free(mem_ctx);
+               printf("Failed to join as BDC\n");
+               return False;
+       }
+
+       status = torture_rpc_connection(mem_ctx, 
+                                       &p, 
+                                       &dcerpc_table_drsuapi);
+       if (!NT_STATUS_IS_OK(status)) {
+               torture_leave_domain(priv.join);
+               talloc_free(mem_ctx);
+               return False;
+       }
+
+       ret &= test_DsBind(p, mem_ctx, &priv);
+
+       if (ret) {
+               /* We don't care if this fails, we just need some info from it */
+               test_DsGetDomainControllerInfo(p, mem_ctx, &priv);
+               
+               ret &= test_DsCrackNames(p, mem_ctx, &priv);
+               
+               ret &= test_DsUnbind(p, mem_ctx, &priv);
+       }
+       talloc_free(mem_ctx);
+
+       torture_leave_domain(priv.join);
+
        return ret;
 }
+