tort: RPC-CRACKNAMES test case refactored
[ira/wip.git] / source4 / torture / rpc / drsuapi_cracknames.c
index 260d43a8c2d95e150d4d510133710b020a029a79..537788244607bbfa0ed99dab80ab3b5acb94b6b1 100644 (file)
@@ -9,7 +9,7 @@
 
    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"
-#include "torture/rpc/drsupai.h"
+#include "torture/torture.h"
+#include "librpc/gen_ndr/ndr_drsuapi_c.h"
+#include "torture/rpc/rpc.h"
+#include "ldb/include/ldb.h"
+#include "libcli/security/security.h"
 
-static BOOL test_DsCrackNamesMatrix(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+static bool test_DsCrackNamesMatrix(struct torture_context *tctx,
                                    struct DsPrivate *priv, const char *dn,
                                    const char *user_principal_name, const char *service_principal_name)
 {
-       
-
        NTSTATUS status;
-       BOOL ret = True;
+       const char *err_msg;
        struct drsuapi_DsCrackNames r;
-       struct drsuapi_DsNameString names[1];
+       union drsuapi_DsNameRequest req;
+       int32_t level_out;
+       union drsuapi_DsNameCtr ctr;
+       struct dcerpc_pipe *p = priv->pipe;
+       TALLOC_CTX *mem_ctx = priv;
+
        enum drsuapi_DsNameFormat formats[] = {
+               DRSUAPI_DS_NAME_FORMAT_UNKNOWN,
                DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
                DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
                DRSUAPI_DS_NAME_FORMAT_DISPLAY,
@@ -48,6 +54,7 @@ static BOOL test_DsCrackNamesMatrix(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY,
                DRSUAPI_DS_NAME_FORMAT_DNS_DOMAIN
        };
+       struct drsuapi_DsNameString names[ARRAY_SIZE(formats)];
        int i, j;
 
        const char *n_matrix[ARRAY_SIZE(formats)][ARRAY_SIZE(formats)];
@@ -56,67 +63,74 @@ static BOOL test_DsCrackNamesMatrix(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        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                        = &req;
+       r.in.req->req1.codepage         = 1252; /* german */
+       r.in.req->req1.language         = 0x00000407; /* german */
+       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.out.level_out                 = &level_out;
+       r.out.ctr                       = &ctr;
 
        n_matrix[0][0] = dn;
 
        for (i = 0; i < ARRAY_SIZE(formats); i++) {
-               r.in.req.req1.format_offered    = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
-               r.in.req.req1.format_desired    = formats[i];
+               r.in.req->req1.format_offered   = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
+               r.in.req->req1.format_desired   = formats[i];
                names[0].str = dn;
-               printf("testing DsCrackNames (matrix prep) with name '%s' from format: %d desired format:%d ",
-                      names[0].str, r.in.req.req1.format_offered, 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;
+                       err_msg = talloc_asprintf(mem_ctx,
+                                       "testing DsCrackNames (matrix prep) with name '%s' from format: %d desired format:%d failed - %s",
+                                       names[0].str, r.in.req->req1.format_offered, r.in.req->req1.format_desired, errstr);
+                       torture_fail(tctx, err_msg);
                } else if (!W_ERROR_IS_OK(r.out.result)) {
-                       printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-                       ret = False;
+                       err_msg = talloc_asprintf(mem_ctx,
+                                       "testing DsCrackNames (matrix prep) with name '%s' from format: %d desired format:%d failed - %s",
+                              names[0].str, r.in.req->req1.format_offered, r.in.req->req1.format_desired, win_errstr(r.out.result));
+                       torture_fail(tctx, err_msg);
                }
                        
-               if (!ret) {
-                       return ret;
-               }
                switch (formats[i]) {
                case DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL:  
-                       if (r.out.ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE) {
-                               printf(__location__ ": Unexpected error (%d): This name lookup should fail\n", 
-                                      r.out.ctr.ctr1->array[0].status);
-                               return False;
+                       if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE) {
+                               err_msg = talloc_asprintf(mem_ctx,
+                                               "Unexpected error (%d): This name lookup should fail",
+                                               r.out.ctr->ctr1->array[0].status);
+                               torture_fail(tctx, err_msg);
                        }
-                       printf ("(expected) error\n");
+                       torture_comment(tctx, __location__ ": (expected) error\n");
                        break;
                case DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL:
-                       if (r.out.ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_NO_MAPPING) {
-                               printf(__location__ ": Unexpected error (%d): This name lookup should fail\n", 
-                                      r.out.ctr.ctr1->array[0].status);
-                               return False;
+                       if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_NO_MAPPING) {
+                               err_msg = talloc_asprintf(mem_ctx,
+                                               "Unexpected error (%d): This name lookup should fail",
+                                               r.out.ctr->ctr1->array[0].status);
+                               torture_fail(tctx, err_msg);
                        }
-                       printf ("(expected) error\n");
+                       torture_comment(tctx, __location__ ": (expected) error\n");
                        break;
                case DRSUAPI_DS_NAME_FORMAT_DNS_DOMAIN: 
                case DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY: 
-                       if (r.out.ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR) {
-                               printf(__location__ ": Unexpected error (%d): This name lookup should fail\n", 
-                                      r.out.ctr.ctr1->array[0].status);
-                               return False;
+                       if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR) {
+                               err_msg = talloc_asprintf(mem_ctx,
+                                               "Unexpected error (%d): This name lookup should fail",
+                                               r.out.ctr->ctr1->array[0].status);
+                               torture_fail(tctx, err_msg);
                        }
-                       printf ("(expected) error\n");
+                       torture_comment(tctx, __location__ ": (expected) error\n");
                        break;
                default:
-                       if (r.out.ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
-                               printf("Error: %d\n", r.out.ctr.ctr1->array[0].status);
-                               return False;
+                       if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
+                               err_msg = talloc_asprintf(mem_ctx,
+                                               "DsCrackNames error: %d",
+                                               r.out.ctr->ctr1->array[0].status);
+                               torture_fail(tctx, err_msg);
                        }
                }
 
@@ -132,15 +146,15 @@ static BOOL test_DsCrackNamesMatrix(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                        n_from[i] = NULL;
                        break;
                default:
-                       n_from[i] = r.out.ctr.ctr1->array[0].result_name;
+                       n_from[i] = r.out.ctr->ctr1->array[0].result_name;
                        printf("%s\n", n_from[i]);
                }
        }
 
        for (i = 0; i < ARRAY_SIZE(formats); i++) {
                for (j = 0; j < ARRAY_SIZE(formats); j++) {
-                       r.in.req.req1.format_offered    = formats[i];
-                       r.in.req.req1.format_desired    = formats[j];
+                       r.in.req->req1.format_offered   = formats[i];
+                       r.in.req->req1.format_desired   = formats[j];
                        if (!n_from[i]) {
                                n_matrix[i][j] = NULL;
                                continue;
@@ -152,21 +166,20 @@ static BOOL test_DsCrackNamesMatrix(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                                if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
                                        errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
                                }
-                               printf("testing DsCrackNames (matrix) with name '%s' from format: %d desired format:%d failed - %s",
-                                      names[0].str, r.in.req.req1.format_offered, r.in.req.req1.format_desired, errstr);
-                               ret = False;
+                               err_msg = talloc_asprintf(mem_ctx,
+                                               "testing DsCrackNames (matrix) with name '%s' from format: %d desired format:%d failed - %s",
+                                               names[0].str, r.in.req->req1.format_offered, r.in.req->req1.format_desired, errstr);
+                               torture_fail(tctx, err_msg);
                        } else if (!W_ERROR_IS_OK(r.out.result)) {
-                               printf("testing DsCrackNames (matrix) with name '%s' from format: %d desired format:%d failed - %s",
-                                      names[0].str, r.in.req.req1.format_offered, r.in.req.req1.format_desired, 
-                                      win_errstr(r.out.result));
-                               ret = False;
+                               err_msg = talloc_asprintf(mem_ctx,
+                                               "testing DsCrackNames (matrix) with name '%s' from format: %d desired format:%d failed - %s",
+                                               names[0].str, r.in.req->req1.format_offered, r.in.req->req1.format_desired,
+                                               win_errstr(r.out.result));
+                               torture_fail(tctx, err_msg);
                        }
                        
-                       if (!ret) {
-                               return ret;
-                       }
-                       if (r.out.ctr.ctr1->array[0].status == DRSUAPI_DS_NAME_STATUS_OK) {
-                               n_matrix[i][j] = r.out.ctr.ctr1->array[0].result_name;
+                       if (r.out.ctr->ctr1->array[0].status == DRSUAPI_DS_NAME_STATUS_OK) {
+                               n_matrix[i][j] = r.out.ctr->ctr1->array[0].result_name;
                        } else {
                                n_matrix[i][j] = NULL;
                        }
@@ -184,48 +197,78 @@ static BOOL test_DsCrackNamesMatrix(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                        } else if (n_matrix[i][j] == NULL && formats[j] == DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL) {
                        } else if (n_matrix[i][j] == NULL && formats[j] == DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL) {
                        } else if (n_matrix[i][j] == NULL && n_from[j] != NULL) {
-                               printf("dcerpc_drsuapi_DsCrackNames mismatch - from %d to %d: %s should be %s\n", formats[i], formats[j], n_matrix[i][j], n_from[j]);
-                               ret = False;
+                               err_msg = talloc_asprintf(mem_ctx,
+                                               "dcerpc_drsuapi_DsCrackNames mismatch - from %d to %d: %s should be %s",
+                                               formats[i], formats[j], n_matrix[i][j], n_from[j]);
+                               torture_fail(tctx, err_msg);
                        } else if (n_matrix[i][j] != NULL && n_from[j] == NULL) {
-                               printf("dcerpc_drsuapi_DsCrackNames mismatch - from %d to %d: %s should be %s\n", formats[i], formats[j], n_matrix[i][j], n_from[j]);
-                               ret = False;
+                               err_msg = talloc_asprintf(mem_ctx,
+                                               "dcerpc_drsuapi_DsCrackNames mismatch - from %d to %d: %s should be %s",
+                                               formats[i], formats[j], n_matrix[i][j], n_from[j]);
+                               torture_fail(tctx, err_msg);
                        } else if (strcmp(n_matrix[i][j], n_from[j]) != 0) {
-                               printf("dcerpc_drsuapi_DsCrackNames mismatch - from %d to %d: %s should be %s\n", formats[i], formats[j], n_matrix[i][j], n_from[j]);
-                               ret = False;
+                               err_msg = talloc_asprintf(mem_ctx,
+                                               "dcerpc_drsuapi_DsCrackNames mismatch - from %d to %d: %s should be %s",
+                                               formats[i], formats[j], n_matrix[i][j], n_from[j]);
+                               torture_fail(tctx, err_msg);
                        }
                }
        }
-       return ret;
+
+       return true;
 }
 
-static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
-                             struct DsPrivate *priv, const char *test_dc)
+bool test_DsCrackNames(struct torture_context *tctx,
+                      struct DsPrivate *priv)
 {
        NTSTATUS status;
+       const char *err_msg;
        struct drsuapi_DsCrackNames r;
+       union drsuapi_DsNameRequest req;
+       int32_t level_out;
+       union drsuapi_DsNameCtr ctr;
        struct drsuapi_DsNameString names[1];
-       BOOL ret = True;
        const char *dns_domain;
        const char *nt4_domain;
        const char *FQDN_1779_name;
+       struct ldb_context *ldb;
+       struct ldb_dn *FQDN_1779_dn;
+       struct ldb_dn *realm_dn;
+       const char *realm_dn_str;
+       const char *realm_canonical;
+       const char *realm_canonical_ex;
        const char *user_principal_name;
+       char *user_principal_name_short;
        const char *service_principal_name;
+       const char *canonical_name;
+       const char *canonical_ex_name;
+       const char *dom_sid;
+       const char *test_dc = torture_join_netbios_name(priv->join);
+       struct dcerpc_pipe *p = priv->pipe;
+       TALLOC_CTX *mem_ctx = priv;
 
        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                        = &req;
+       r.in.req->req1.codepage         = 1252; /* german */
+       r.in.req->req1.language         = 0x00000407; /* german */
+       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_SID_OR_SID_HISTORY;
+       r.in.req->req1.format_desired   = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;
 
-       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());
+       r.out.level_out                 = &level_out;
+       r.out.ctr                       = &ctr;
+
+       dom_sid = dom_sid_string(mem_ctx, torture_join_sid(priv->join));
+       
+       names[0].str = dom_sid;
 
-       printf("testing DsCrackNames with name '%s' desired format:%d\n",
-                       names[0].str, r.in.req.req1.format_desired);
+       torture_comment(tctx, "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)) {
@@ -233,27 +276,24 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                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;
+               err_msg = talloc_asprintf(mem_ctx, "dcerpc_drsuapi_DsCrackNames failed - %s", errstr);
+               torture_fail(tctx, err_msg);
        } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       } else if (r.out.ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
-               printf("DsCrackNames failed on name - %d\n", r.out.ctr.ctr1->array[0].status);
-               ret = False;
+               err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed - %s", win_errstr(r.out.result));
+               torture_fail(tctx, err_msg);
+       } else if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
+               err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed on name - %d",
+                                         r.out.ctr->ctr1->array[0].status);
+               torture_fail(tctx, err_msg);
        }
 
-       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;
+       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;
+       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);
+       torture_comment(tctx, "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)) {
@@ -261,28 +301,25 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                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;
+               err_msg = talloc_asprintf(mem_ctx, "dcerpc_drsuapi_DsCrackNames failed - %s", errstr);
+               torture_fail(tctx, err_msg);
        } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       } else if (r.out.ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
-               printf("DsCrackNames failed on name - %d\n", r.out.ctr.ctr1->array[0].status);
-               ret = False;
+               err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed - %s", win_errstr(r.out.result));
+               torture_fail(tctx, err_msg);
+       } else if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
+               err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed on name - %d",
+                                         r.out.ctr->ctr1->array[0].status);
+               torture_fail(tctx, err_msg);
        }
 
-       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;
+       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_desired    = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
+       r.in.req->req1.format_desired   = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
 
-       printf("testing DsCrackNames with name '%s' desired format:%d\n",
-                       names[0].str, r.in.req.req1.format_desired);
+       torture_comment(tctx, "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)) {
@@ -290,53 +327,47 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                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;
+               err_msg = talloc_asprintf(mem_ctx, "dcerpc_drsuapi_DsCrackNames failed - %s", errstr);
+               torture_fail(tctx, err_msg);
        } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       } else if (r.out.ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
-               printf("DsCrackNames failed on name - %d\n", r.out.ctr.ctr1->array[0].status);
-               ret = False;
-       }
-
-       if (!ret) {
-               return ret;
+               err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed - %s", win_errstr(r.out.result));
+               torture_fail(tctx, err_msg);
+       } else if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
+               err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed on name - %d",
+                                         r.out.ctr->ctr1->array[0].status);
+               torture_fail(tctx, err_msg);
        }
 
-       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;
+       ldb = ldb_init(mem_ctx, tctx->ev);
+       
+       realm_dn_str = r.out.ctr->ctr1->array[0].result_name;
+       realm_dn =  ldb_dn_new(mem_ctx, ldb, realm_dn_str);
+       realm_canonical = ldb_dn_canonical_string(mem_ctx, realm_dn);
+
+       if (strcmp(realm_canonical,
+                  talloc_asprintf(mem_ctx, "%s/", dns_domain))!= 0) {
+               err_msg = talloc_asprintf(mem_ctx, "local Round trip on canonical name failed: %s != %s!",
+                                         realm_canonical,
+                                         talloc_asprintf(mem_ctx, "%s/", dns_domain));
+               torture_fail(tctx, err_msg);
+       };
 
-       printf("testing DsCrackNames with GUID '%s' desired format:%d\n",
-                       names[0].str, r.in.req.req1.format_desired);
+       realm_canonical_ex = ldb_dn_canonical_ex_string(mem_ctx, realm_dn);
 
-       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;
-       } else if (r.out.ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
-               printf("DsCrackNames failed on name - %d\n", r.out.ctr.ctr1->array[0].status);
-               ret = False;
-       }
-
-       if (!ret) {
-               return ret;
-       }
+       if (strcmp(realm_canonical_ex, 
+                  talloc_asprintf(mem_ctx, "%s\n", dns_domain))!= 0) {
+               err_msg = talloc_asprintf(mem_ctx, "local Round trip on canonical ex name failed: %s != %s!",
+                                         realm_canonical,
+                                         talloc_asprintf(mem_ctx, "%s\n", dns_domain));
+               torture_fail(tctx, err_msg);
+       };
 
-       r.in.req.req1.format_offered    = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;
-       r.in.req.req1.format_desired    = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
+       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);
+       torture_comment(tctx, "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)) {
@@ -344,28 +375,25 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                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;
+               err_msg = talloc_asprintf(mem_ctx, "dcerpc_drsuapi_DsCrackNames failed - %s", errstr);
+               torture_fail(tctx, err_msg);
        } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       } else if (r.out.ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
-               printf("DsCrackNames failed on name - %d\n", r.out.ctr.ctr1->array[0].status);
-               ret = False;
+               err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed - %s", win_errstr(r.out.result));
+               torture_fail(tctx, err_msg);
+       } else if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
+               err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed on name - %d",
+                                         r.out.ctr->ctr1->array[0].status);
+               torture_fail(tctx, err_msg);
        }
 
-       if (!ret) {
-               return ret;
-       }
+       priv->domain_obj_dn = r.out.ctr->ctr1->array[0].result_name;
 
-       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;
+       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, test_dc);
 
-       printf("testing DsCrackNames with name '%s' desired format:%d\n",
-                       names[0].str, r.in.req.req1.format_desired);
+       torture_comment(tctx, "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)) {
@@ -373,29 +401,25 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                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;
+               err_msg = talloc_asprintf(mem_ctx, "dcerpc_drsuapi_DsCrackNames failed - %s", errstr);
+               torture_fail(tctx, err_msg);
        } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       } else if (r.out.ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
-               printf("DsCrackNames failed on name - %d\n", r.out.ctr.ctr1->array[0].status);
-               ret = False;
-       }
-
-       if (!ret) {
-               return ret;
+               err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed - %s", win_errstr(r.out.result));
+               torture_fail(tctx, err_msg);
+       } else if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
+               err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed on name - %d",
+                                         r.out.ctr->ctr1->array[0].status);
+               torture_fail(tctx, err_msg);
        }
 
-       FQDN_1779_name = r.out.ctr.ctr1->array[0].result_name;
+       FQDN_1779_name = r.out.ctr->ctr1->array[0].result_name;
 
-       r.in.req.req1.format_offered    = DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL;
-       r.in.req.req1.format_desired    = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
-       names[0].str = talloc_asprintf(mem_ctx, "%s$@%s", test_dc, dns_domain);
-       user_principal_name = names[0].str;
+       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 = priv->domain_guid_str;
 
-       printf("testing DsCrackNames with name '%s' desired format:%d\n",
-                       names[0].str, r.in.req.req1.format_desired);
+       torture_comment(tctx, "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)) {
@@ -403,25 +427,36 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                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;
+               err_msg = talloc_asprintf(mem_ctx, "dcerpc_drsuapi_DsCrackNames failed - %s", errstr);
+               torture_fail(tctx, err_msg);
        } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       } else if (r.out.ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
-               printf("DsCrackNames failed on name - %d\n", r.out.ctr.ctr1->array[0].status);
-               ret = False;
+               err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed - %s", win_errstr(r.out.result));
+               torture_fail(tctx, err_msg);
+       } else if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
+               err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed on name - %d",
+                                         r.out.ctr->ctr1->array[0].status);
+               torture_fail(tctx, err_msg);
        }
 
-       if (!ret) {
-               return ret;
+       if (strcmp(priv->domain_dns_name, r.out.ctr->ctr1->array[0].dns_domain_name) != 0) {
+               err_msg = talloc_asprintf(mem_ctx,
+                               "DsCrackNames failed to return same DNS name - expected %s got %s",
+                               priv->domain_dns_name, r.out.ctr->ctr1->array[0].dns_domain_name);
+               torture_fail(tctx, err_msg);
        }
 
-       if (strcmp(r.out.ctr.ctr1->array[0].result_name, FQDN_1779_name) != 0) {
-               printf("DsCrackNames failed - %s != %s\n", r.out.ctr.ctr1->array[0].result_name, FQDN_1779_name);
-               return False;
-       }
+       FQDN_1779_dn = ldb_dn_new(mem_ctx, ldb, FQDN_1779_name);
+
+       canonical_name = ldb_dn_canonical_string(mem_ctx, FQDN_1779_dn);
+       canonical_ex_name = ldb_dn_canonical_ex_string(mem_ctx, FQDN_1779_dn);
+
+       user_principal_name = talloc_asprintf(mem_ctx, "%s$@%s", test_dc, dns_domain);
 
+       /* form up a user@DOMAIN */
+       user_principal_name_short = talloc_asprintf(mem_ctx, "%s$@%s", test_dc, nt4_domain);
+       /* variable nt4_domain includs a trailing \ */
+       user_principal_name_short[strlen(user_principal_name_short) - 1] = '\0';
+       
        service_principal_name = talloc_asprintf(mem_ctx, "HOST/%s", test_dc);
        {
                
@@ -431,8 +466,32 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                        const char *comment;
                        const char *str;
                        const char *expected_str;
+                       const char *expected_dns;
                        enum drsuapi_DsNameStatus status;
+                       enum drsuapi_DsNameStatus alternate_status;
+                       enum drsuapi_DsNameFlags flags;
+                       bool skip;
                } crack[] = {
+                       {
+                               .format_offered = DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
+                               .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
+                               .str = user_principal_name,
+                               .expected_str = FQDN_1779_name,
+                               .status = DRSUAPI_DS_NAME_STATUS_OK
+                       },
+                       {
+                               .format_offered = DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
+                               .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
+                               .str = user_principal_name_short,
+                               .expected_str = FQDN_1779_name,
+                               .status = DRSUAPI_DS_NAME_STATUS_OK
+                       },
+                       {
+                               .format_offered = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
+                               .format_desired = DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
+                               .str = FQDN_1779_name,
+                               .status = DRSUAPI_DS_NAME_STATUS_NO_MAPPING
+                       },
                        {
                                .format_offered = DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
                                .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
@@ -452,8 +511,48 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                                .format_offered = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
                                .format_desired = DRSUAPI_DS_NAME_FORMAT_CANONICAL,
                                .str = FQDN_1779_name,
+                               .expected_str = canonical_name,
+                               .status = DRSUAPI_DS_NAME_STATUS_OK
+                       },
+                       {
+                               .format_offered = DRSUAPI_DS_NAME_FORMAT_CANONICAL, 
+                               .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
+                               .str = canonical_name,
+                               .expected_str = FQDN_1779_name,
                                .status = DRSUAPI_DS_NAME_STATUS_OK
                        },
+                       {
+                               .format_offered = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
+                               .format_desired = DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX,
+                               .str = FQDN_1779_name,
+                               .expected_str = canonical_ex_name,
+                               .status = DRSUAPI_DS_NAME_STATUS_OK
+                       },
+                       {
+                               .format_offered = DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX, 
+                               .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
+                               .str = canonical_ex_name,
+                               .expected_str = FQDN_1779_name,
+                               .status = DRSUAPI_DS_NAME_STATUS_OK
+                       },
+                       {
+                               .format_offered = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
+                               .format_desired = DRSUAPI_DS_NAME_FORMAT_CANONICAL,
+                               .str = FQDN_1779_name,
+                               .comment = "DN to cannoical syntactial only",
+                               .status = DRSUAPI_DS_NAME_STATUS_OK,
+                               .expected_str = canonical_name,
+                               .flags = DRSUAPI_DS_NAME_FLAG_SYNTACTICAL_ONLY
+                       },
+                       {
+                               .format_offered = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
+                               .format_desired = DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX,
+                               .str = FQDN_1779_name,
+                               .comment = "DN to cannoical EX syntactial only",
+                               .status = DRSUAPI_DS_NAME_STATUS_OK,
+                               .expected_str = canonical_ex_name,
+                               .flags = DRSUAPI_DS_NAME_FLAG_SYNTACTICAL_ONLY
+                       },
                        {
                                .format_offered = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
                                .format_desired = DRSUAPI_DS_NAME_FORMAT_DISPLAY,
@@ -466,11 +565,53 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                                .str = FQDN_1779_name,
                                .status = DRSUAPI_DS_NAME_STATUS_OK
                        },
+                       {
+                               .format_offered = DRSUAPI_DS_NAME_FORMAT_GUID,
+                               .format_desired = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
+                               .str = priv->domain_guid_str,
+                               .comment = "Domain GUID to NT4 ACCOUNT",
+                               .expected_str = nt4_domain,
+                               .status = DRSUAPI_DS_NAME_STATUS_OK
+                       },
+                       {
+                               .format_offered = DRSUAPI_DS_NAME_FORMAT_GUID,
+                               .format_desired = DRSUAPI_DS_NAME_FORMAT_CANONICAL,
+                               .str = priv->domain_guid_str,
+                               .comment = "Domain GUID to Canonical",
+                               .expected_str = talloc_asprintf(mem_ctx, "%s/", dns_domain),
+                               .status = DRSUAPI_DS_NAME_STATUS_OK
+                       },
+                       {
+                               .format_offered = DRSUAPI_DS_NAME_FORMAT_GUID,
+                               .format_desired = DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX,
+                               .str = priv->domain_guid_str,
+                               .comment = "Domain GUID to Canonical EX",
+                               .expected_str = talloc_asprintf(mem_ctx, "%s\n", dns_domain),
+                               .status = DRSUAPI_DS_NAME_STATUS_OK
+                       },
                        {
                                .format_offered = DRSUAPI_DS_NAME_FORMAT_DISPLAY,
                                .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
                                .str = "CN=Microsoft Corporation,L=Redmond,S=Washington,C=US",
                                .comment = "display name for Microsoft Support Account",
+                               .status = DRSUAPI_DS_NAME_STATUS_OK,
+                               .alternate_status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE,
+                               .skip = torture_setting_bool(tctx, "samba4", false)
+                       },
+                       {
+                               .format_offered = DRSUAPI_DS_NAME_FORMAT_GUID,
+                               .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
+                               .str = GUID_string2(mem_ctx, torture_join_user_guid(priv->join)),
+                               .comment = "Account GUID -> DN",
+                               .expected_str = FQDN_1779_name,
+                               .status = DRSUAPI_DS_NAME_STATUS_OK
+                       },
+                       {
+                               .format_offered = DRSUAPI_DS_NAME_FORMAT_GUID,
+                               .format_desired = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
+                               .str = GUID_string2(mem_ctx, torture_join_user_guid(priv->join)),
+                               .comment = "Account GUID -> NT4 Account",
+                               .expected_str = talloc_asprintf(mem_ctx, "%s%s$", nt4_domain, test_dc),
                                .status = DRSUAPI_DS_NAME_STATUS_OK
                        },
                        {               
@@ -478,12 +619,22 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                                .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
                                .str = GUID_string2(mem_ctx, &priv->dcinfo.site_guid),
                                .comment = "Site GUID",
+                               .expected_str = priv->dcinfo.site_dn,
                                .status = DRSUAPI_DS_NAME_STATUS_OK
                        },
                        {
-                               .format_desired = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
+                               .format_offered = DRSUAPI_DS_NAME_FORMAT_GUID,
+                               .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
                                .str = GUID_string2(mem_ctx, &priv->dcinfo.computer_guid),
                                .comment = "Computer GUID",
+                               .expected_str = priv->dcinfo.computer_dn,
+                               .status = DRSUAPI_DS_NAME_STATUS_OK
+                       },
+                       {
+                               .format_offered = DRSUAPI_DS_NAME_FORMAT_GUID,
+                               .format_desired = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
+                               .str = GUID_string2(mem_ctx, &priv->dcinfo.computer_guid),
+                               .comment = "Computer GUID -> NT4 Account",
                                .status = DRSUAPI_DS_NAME_STATUS_OK
                        },
                        {
@@ -491,6 +642,7 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                                .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
                                .str = GUID_string2(mem_ctx, &priv->dcinfo.server_guid),
                                .comment = "Server GUID",
+                               .expected_str = priv->dcinfo.server_dn,
                                .status = DRSUAPI_DS_NAME_STATUS_OK
                        },
                        {
@@ -498,20 +650,15 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                                .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
                                .str = GUID_string2(mem_ctx, &priv->dcinfo.ntds_guid),
                                .comment = "NTDS GUID",
-                               .status = DRSUAPI_DS_NAME_STATUS_OK
-                       },
-                       {
-                               .format_offered = DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY,
-                               .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
-                               .str = SID_BUILTIN,
-                               .comment = "BUILTIN domain SID",
-                               .status = DRSUAPI_DS_NAME_STATUS_OK
+                               .expected_str = priv->dcinfo.ntds_dn,
+                               .status = DRSUAPI_DS_NAME_STATUS_OK,
+                               .skip = GUID_all_zero(&priv->dcinfo.ntds_guid)
                        },
                        {
                                .format_offered = DRSUAPI_DS_NAME_FORMAT_DISPLAY,
                                .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
                                .str = test_dc,
-                               .comment = "DISPAY NAME search for DC short name",
+                               .comment = "DISLPAY NAME search for DC short name",
                                .status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
                        },
                        {
@@ -519,7 +666,24 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                                .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
                                .str = talloc_asprintf(mem_ctx, "krbtgt/%s", dns_domain),
                                .comment = "Looking for KRBTGT as a serivce principal",
-                               .status = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY
+                               .status = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY,
+                               .expected_dns = dns_domain
+                       },
+                       {
+                               .format_offered = DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
+                               .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
+                               .str = talloc_asprintf(mem_ctx, "bogus/%s", dns_domain),
+                               .comment = "Looking for bogus serivce principal",
+                               .status = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY,
+                               .expected_dns = dns_domain
+                       },
+                       {
+                               .format_offered = DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
+                               .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
+                               .str = talloc_asprintf(mem_ctx, "bogus/%s.%s", test_dc, dns_domain),
+                               .comment = "Looking for bogus serivce on test DC",
+                               .status = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY,
+                               .expected_dns = talloc_asprintf(mem_ctx, "%s.%s", test_dc, dns_domain)
                        },
                        { 
                                .format_offered = DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
@@ -527,6 +691,15 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                                .str = talloc_asprintf(mem_ctx, "krbtgt"),
                                .status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
                        },
+                       { 
+                               .format_offered = DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
+                               .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
+                               .comment = "Looking for the kadmin/changepw service as a serivce principal",
+                               .str = talloc_asprintf(mem_ctx, "kadmin/changepw"),
+                               .status = DRSUAPI_DS_NAME_STATUS_OK,
+                               .expected_str = talloc_asprintf(mem_ctx, "CN=krbtgt,CN=Users,%s", realm_dn_str),
+                               .alternate_status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE
+                       },
                        {
                                .format_offered = DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
                                .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
@@ -535,6 +708,38 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                                                       dns_domain),
                                .status = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY
                        },
+                       {
+                               .format_offered = DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
+                               .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
+                               .str = talloc_asprintf(mem_ctx, "cifs/%s.%s@%s", 
+                                                      test_dc, dns_domain,
+                                                      "BOGUS"),
+                               .status = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY,
+                               .expected_dns = "BOGUS"
+                       },
+                       {
+                               .format_offered = DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
+                               .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
+                               .str = talloc_asprintf(mem_ctx, "cifs/%s.%s@%s", 
+                                                      test_dc, "REALLY",
+                                                      "BOGUS"),
+                               .status = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY,
+                               .expected_dns = "BOGUS"
+                       },
+                       {
+                               .format_offered = DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
+                               .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
+                               .str = talloc_asprintf(mem_ctx, "cifs/%s.%s", 
+                                                      test_dc, dns_domain),
+                               .status = DRSUAPI_DS_NAME_STATUS_OK
+                       },
+                       {
+                               .format_offered = DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
+                               .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
+                               .str = talloc_asprintf(mem_ctx, "cifs/%s", 
+                                                      test_dc),
+                               .status = DRSUAPI_DS_NAME_STATUS_OK
+                       },
                        {
                                .format_offered = DRSUAPI_DS_NAME_FORMAT_GUID,
                                .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
@@ -595,11 +800,46 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                                .str = talloc_asprintf(mem_ctx, "%s$", test_dc),
                                .status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
                        },
+                       {
+                               .format_offered = DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
+                               .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
+                               .comment = "Full Machine account as service principal",
+                               .str = user_principal_name,
+                               .status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
+                       },
                        {
                                .format_offered = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
                                .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
                                .comment = "Realm as an NT4 domain lookup",
-                               .str = talloc_asprintf(mem_ctx, "%s\\", lp_realm()),
+                               .str = talloc_asprintf(mem_ctx, "%s\\", dns_domain),
+                               .status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
+                       }, 
+                       {
+                               .format_offered = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
+                               .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
+                               .comment = "BUILTIN\\ -> DN",
+                               .str = "BUILTIN\\",
+                               .status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
+                       }, 
+                       {
+                               .format_offered = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
+                               .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
+                               .comment = "NT AUTHORITY\\ -> DN",
+                               .str = "NT AUTHORITY\\",
+                               .status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
+                       }, 
+                       {
+                               .format_offered = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
+                               .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
+                               .comment = "NT AUTHORITY\\ANONYMOUS LOGON -> DN",
+                               .str = "NT AUTHORITY\\ANONYMOUS LOGON",
+                               .status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
+                       }, 
+                       {
+                               .format_offered = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
+                               .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
+                               .comment = "NT AUTHORITY\\SYSTEM -> DN",
+                               .str = "NT AUTHORITY\\SYSTEM",
                                .status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
                        }, 
                        {
@@ -607,40 +847,99 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                                .format_desired = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
                                .comment = "BUITIN SID -> NT4 account",
                                .str = SID_BUILTIN,
-                               .status = DRSUAPI_DS_NAME_STATUS_NO_MAPPING
+                               .status = DRSUAPI_DS_NAME_STATUS_NO_MAPPING,
+                               .alternate_status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE
                        }, 
+                       {
+                               .format_offered = DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY,
+                               .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
+                               .str = SID_BUILTIN,
+                               .comment = "Builtin Domain SID -> DN",
+                               .status = DRSUAPI_DS_NAME_STATUS_OK,
+                               .expected_str = talloc_asprintf(mem_ctx, "CN=Builtin,%s", realm_dn_str),
+                               .alternate_status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE
+                       },
                        {
                                .format_offered = DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY,
                                .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
                                .str = SID_BUILTIN_ADMINISTRATORS,
-                               .status = DRSUAPI_DS_NAME_STATUS_OK
+                               .comment = "Builtin Administrors SID -> DN",
+                               .status = DRSUAPI_DS_NAME_STATUS_OK,
+                               .alternate_status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE
                        },
                        {
                                .format_offered = DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY,
                                .format_desired = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
                                .str = SID_BUILTIN_ADMINISTRATORS,
+                               .comment = "Builtin Administrors SID -> NT4 Account",
+                               .status = DRSUAPI_DS_NAME_STATUS_OK,
+                               .alternate_status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE
+                       },
+                       {
+                               .format_offered = DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY,
+                               .format_desired = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
+                               .str = SID_NT_ANONYMOUS,
+                               .comment = "NT Anonymous SID -> NT4 Account",
+                               .status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
+                       },
+                       {
+                               .format_offered = DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY,
+                               .format_desired = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
+                               .str = SID_NT_SYSTEM,
+                               .comment = "NT SYSTEM SID -> NT4 Account",
+                               .status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
+                       },
+                       {
+                               .format_offered = DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY,
+                               .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
+                               .comment = "Domain SID -> DN",
+                               .str = dom_sid,
+                               .expected_str = realm_dn_str,
+                               .status = DRSUAPI_DS_NAME_STATUS_OK
+                       },
+                       {
+                               .format_offered = DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY,
+                               .format_desired = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
+                               .comment = "Domain SID -> NT4 account",
+                               .str = dom_sid,
+                               .expected_str = nt4_domain,
                                .status = DRSUAPI_DS_NAME_STATUS_OK
                        },
                        {
                                .format_offered = DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
                                .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
+                               .comment = "invalid user principal name",
                                .str = "foo@bar",
-                               .status = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY
+                               .status = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY,
+                               .expected_dns = "bar"
                        },
+                       {
+                               .format_offered = DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
+                               .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
+                               .comment = "invalid user principal name in valid domain",
+                               .str = talloc_asprintf(mem_ctx, "invalidusername@%s", dns_domain),
+                               .status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
+                       }
                };
                int i;
                
                for (i=0; i < ARRAY_SIZE(crack); i++) {
-                       r.in.req.req1.format_offered = crack[i].format_offered; 
-                       r.in.req.req1.format_desired = crack[i].format_desired;
+                       const char *comment;
+                       r.in.req->req1.format_flags   = crack[i].flags;
+                       r.in.req->req1.format_offered = crack[i].format_offered;
+                       r.in.req->req1.format_desired = crack[i].format_desired;
                        names[0].str = crack[i].str;
                        
                        if (crack[i].comment) {
-                               printf("testing DsCrackNames '%s' with name '%s' desired format:%d\n",
-                                      crack[i].comment, names[0].str, r.in.req.req1.format_desired);
+                               comment = talloc_asprintf(mem_ctx, "'%s' with name '%s' desired format:%d\n",
+                                                         crack[i].comment, names[0].str, r.in.req->req1.format_desired);
                        } else {
-                               printf("testing DsCrackNames with name '%s' desired format:%d\n",
-                                      names[0].str, r.in.req.req1.format_desired);
+                               comment = talloc_asprintf(mem_ctx, "'%s' desired format:%d\n",
+                                      names[0].str, r.in.req->req1.format_desired);
+                       }
+                       if (crack[i].skip) {
+                               torture_comment(tctx, "skipping: %s", comment);
+                               continue;
                        }
                        status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
                        if (!NT_STATUS_IS_OK(status)) {
@@ -648,68 +947,75 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                                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;
+                               err_msg = talloc_asprintf(mem_ctx, "dcerpc_drsuapi_DsCrackNames failed - %s", errstr);
+                               torture_fail(tctx, err_msg);
                        } else if (!W_ERROR_IS_OK(r.out.result)) {
-                               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-                               ret = False;
-                       } else if (r.out.ctr.ctr1->array[0].status != crack[i].status) {
-                               printf("DsCrackNames unexpected error %d, wanted %d on name: %s\n", 
-                                      r.out.ctr.ctr1->array[0].status,
-                                      crack[i].status,
-                                      crack[i].str);
-                               ret = False;
-                       }
-                       if (crack[i].expected_str 
-                               && (strcmp(r.out.ctr.ctr1->array[0].result_name, 
-                                          crack[i].expected_str) != 0)) {
-                               printf("DsCrackNames failed - got %s, expected %s\n", 
-                                      r.out.ctr.ctr1->array[0].result_name, 
-                                      crack[i].expected_str);
-                               ret = False;
+                               err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed - %s", win_errstr(r.out.result));
+                               torture_fail(tctx, err_msg);
+                       } else if (r.out.ctr->ctr1->array[0].status != crack[i].status) {
+                               if (crack[i].alternate_status) {
+                                       if (r.out.ctr->ctr1->array[0].status != crack[i].alternate_status) {
+                                               err_msg = talloc_asprintf(mem_ctx,
+                                                               "DsCrackNames unexpected status %d, wanted %d or %d on: %s",
+                                                               r.out.ctr->ctr1->array[0].status,
+                                                               crack[i].status,
+                                                               crack[i].alternate_status,
+                                                               comment);
+                                               torture_fail(tctx, err_msg);
+                                       }
+                               } else {
+                                       err_msg = talloc_asprintf(mem_ctx,
+                                                       "DsCrackNames unexpected status %d, wanted %d on: %s\n",
+                                                       r.out.ctr->ctr1->array[0].status,
+                                                       crack[i].status,
+                                                       comment);
+                                       torture_fail(tctx, err_msg);
+                               }
+                       } else if (crack[i].expected_str
+                                  && (strcmp(r.out.ctr->ctr1->array[0].result_name,
+                                             crack[i].expected_str) != 0)) {
+                               if (strcasecmp(r.out.ctr->ctr1->array[0].result_name,
+                                              crack[i].expected_str) != 0) {
+                                       err_msg = talloc_asprintf(mem_ctx,
+                                                       "DsCrackNames failed - got %s, expected %s on %s",
+                                                       r.out.ctr->ctr1->array[0].result_name,
+                                                       crack[i].expected_str, comment);
+                                       torture_fail(tctx, err_msg);
+                               } else {
+                                       torture_comment(tctx,
+                                                       "(warning) DsCrackNames returned different case - got %s, expected %s on %s\n",
+                                                       r.out.ctr->ctr1->array[0].result_name,
+                                                       crack[i].expected_str, comment);
+                               }
+                       } else if (crack[i].expected_dns
+                                  && (strcmp(r.out.ctr->ctr1->array[0].dns_domain_name,
+                                             crack[i].expected_dns) != 0)) {
+                               err_msg = talloc_asprintf(mem_ctx,
+                                               "DsCrackNames failed - got DNS name %s, expected %s on %s",
+                                               r.out.ctr->ctr1->array[0].result_name,
+                                               crack[i].expected_str, comment);
+                               torture_fail(tctx, err_msg);
                        }
                }
        }
 
-       if (!test_DsCrackNamesMatrix(p, mem_ctx, priv, FQDN_1779_name, 
-                                    user_principal_name, service_principal_name)) {
-               ret = False;
-       }
-
-       return ret;
+       return test_DsCrackNamesMatrix(tctx, priv, FQDN_1779_name,
+                                       user_principal_name, service_principal_name);
 }
 
-BOOL torture_rpc_drsuapi_cracknames(void)
+/**
+ * CRACKNAMES test suite implementation
+ */
+void torture_rpc_drsuapi_cracknames_tcase(struct torture_suite *suite)
 {
-        NTSTATUS status;
-        struct dcerpc_pipe *p;
-       TALLOC_CTX *mem_ctx;
-       BOOL ret = True;
-       struct DsPrivate priv;
-
-       mem_ctx = talloc_init("torture_rpc_drsuapi");
-
-       status = torture_rpc_connection(mem_ctx, 
-                                       &p, 
-                                       DCERPC_DRSUAPI_NAME,
-                                       DCERPC_DRSUAPI_UUID,
-                                       DCERPC_DRSUAPI_VERSION);
-       if (!NT_STATUS_IS_OK(status)) {
-               talloc_free(mem_ctx);
-               return False;
-       }
-
-       printf("Connected to DRAUAPI pipe\n");
-
-       ZERO_STRUCT(priv);
-
-       ret &= test_DsBind(p, mem_ctx, &priv);
-
-       ret &= test_DsCrackNames(p, mem_ctx, &priv, lp_parm_string(-1, "torture", "host"));
+       typedef bool (*run_func) (struct torture_context *test, void *tcase_data);
 
-       ret &= test_DsUnbind(p, mem_ctx, &priv);
+       struct torture_test *test;
+       struct torture_tcase *tcase = torture_suite_add_tcase(suite, "CRACKNAMES");
 
-       talloc_free(mem_ctx);
+       torture_tcase_set_fixture(tcase,
+                                 torture_rpc_drsuapi_tcase_setup,
+                                 torture_rpc_drsuapi_tcase_teardown);
 
-       return ret;
+       test = torture_tcase_add_simple_test(tcase, "CRACKNAMES-TEST", (run_func)test_DsCrackNames);
 }