r10953: Add a new function to form a canonicalName out of a DN to ldb_dn.c
authorAndrew Bartlett <abartlet@samba.org>
Thu, 13 Oct 2005 04:24:49 +0000 (04:24 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:39:45 +0000 (13:39 -0500)
Use this new function in the client and server for the CrackNames
case, where we particularly need it.

Andrew Bartlett
(This used to be commit 380037ee09ef8293bdb288d6c015e7c80f180a30)

source4/lib/ldb/common/ldb_dn.c
source4/lib/ldb/include/ldb.h
source4/rpc_server/drsuapi/drsuapi_cracknames.c
source4/torture/rpc/drsuapi_cracknames.c

index b497de142bd8993474f75e4694dcf23ae1eaaa09..abe8985f9d7d7c9326b7fa3347fd6549e13e7cb2 100644 (file)
@@ -839,3 +839,58 @@ struct ldb_dn_component *ldb_dn_get_rdn(void *mem_ctx, const struct ldb_dn *dn)
        return rdn;
 }
 
+static char *ldb_dn_canonical(void *mem_ctx, const struct ldb_dn *dn, int ex_format) {
+       int i;
+       char *cracked = NULL;
+       for (i = dn->comp_num - 1 ; i >= 0; i--) {
+               if (strcasecmp(dn->components[i].name, "dc") != 0) {
+                       break;
+               }
+               if (cracked) {
+                       cracked = talloc_asprintf(mem_ctx, "%s.%s", dn->components[i].value.data,
+                                                 cracked);
+               } else {
+                       cracked = talloc_strdup(mem_ctx, dn->components[i].value.data);
+               }
+               if (!cracked) {
+                       return NULL;
+               }
+       }
+
+       /* Only domain components */
+       if (i < 0) {
+               if (ex_format) {
+                       cracked = talloc_asprintf(mem_ctx, "%s\n", cracked);
+               } else {
+                       cracked = talloc_asprintf(mem_ctx, "%s/", cracked);
+               }
+               return cracked;
+       }
+
+       for (; i > 0; i--) {
+               cracked = talloc_asprintf(mem_ctx, "%s/%s", cracked, 
+                                         dn->components[i].value.data);
+               if (!cracked) {
+                       return NULL;
+               }
+       }
+
+       /* Last one */
+       if (ex_format) {
+               cracked = talloc_asprintf(mem_ctx, "%s\n%s", cracked, 
+                                         dn->components[i].value.data);
+       } else {
+               cracked = talloc_asprintf(mem_ctx, "%s/%s", cracked, 
+                                         dn->components[i].value.data);
+       }
+       return cracked;
+}
+
+char *ldb_dn_canonical_string(void *mem_ctx, const struct ldb_dn *dn) {
+       return ldb_dn_canonical(mem_ctx, dn, 0);
+
+}
+
+char *ldb_dn_canonical_ex_string(void *mem_ctx, const struct ldb_dn *dn) {
+       return ldb_dn_canonical(mem_ctx, dn, 1);
+}
index fd3577a470f19f557c43a391db0e69b27dbfc6bc..27313613ab9cb2f7dec9f6b519443d28c7e28cc9 100644 (file)
@@ -502,4 +502,6 @@ int ldb_msg_copy_attr(struct ldb_message *msg, const char *attr, const char *rep
 char *ldb_timestring(void *mem_ctx, time_t t);
 time_t ldb_string_to_time(const char *s);
 
+char *ldb_dn_canonical_string(void *mem_ctx, const struct ldb_dn *dn);
+char *ldb_dn_canonical_ex_string(void *mem_ctx, const struct ldb_dn *dn);
 #endif
index 29ca1a4527e1fd5b7b8d8c9e17b3cddca471dd6e..c1a6c19978501f72c4a84dcc17bb45713473b49b 100644 (file)
@@ -41,6 +41,11 @@ static WERROR DsCrackNameOneName(struct drsuapi_bind_state *b_state, TALLOC_CTX
                                 uint32_t format_flags, uint32_t format_offered, uint32_t format_desired,
                                 const char *name, struct drsuapi_DsNameInfo1 *info1);
 
+static WERROR DsCrackNameOneSyntactical(TALLOC_CTX *mem_ctx,
+                                       uint32_t format_offered, uint32_t format_desired,
+                                       const struct ldb_dn *name_dn, const char *name, 
+                                       struct drsuapi_DsNameInfo1 *info1);
+
 static enum drsuapi_DsNameStatus LDB_lookup_spn_alias(krb5_context context, struct ldb_context *ldb_ctx, 
                                   TALLOC_CTX *mem_ctx,
                                   const char *alias_from,
@@ -82,7 +87,7 @@ static enum drsuapi_DsNameStatus LDB_lookup_spn_alias(krb5_context context, stru
                mapping = talloc_strdup(mem_ctx, 
                                        (const char *)spnmappings->values[i].data);
                if (!mapping) {
-                       DEBUG(1, ("LDB_lookup_spn_alias: ldb_search: dn: %s did not have an sPNMapping", service_dn_str));
+                       DEBUG(1, ("LDB_lookup_spn_alias: ldb_search: dn: %s did not have an sPNMapping\n", service_dn_str));
                        return DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
                }
                
@@ -90,7 +95,7 @@ static enum drsuapi_DsNameStatus LDB_lookup_spn_alias(krb5_context context, stru
                
                p = strchr(mapping, '=');
                if (!p) {
-                       DEBUG(1, ("ldb_search: dn: %s sPNMapping malformed: %s", 
+                       DEBUG(1, ("ldb_search: dn: %s sPNMapping malformed: %s\n", 
                                  service_dn_str, mapping));
                        return DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
                }
@@ -109,7 +114,7 @@ static enum drsuapi_DsNameStatus LDB_lookup_spn_alias(krb5_context context, stru
                        }
                } while (p);
        }
-       DEBUG(1, ("LDB_lookup_spn_alias: no alias for service %s applicable", alias_from));
+       DEBUG(1, ("LDB_lookup_spn_alias: no alias for service %s applicable\n", alias_from));
        return DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
 }
 
@@ -137,8 +142,9 @@ static WERROR DsCrackNameSPNAlias(struct drsuapi_bind_state *b_state, TALLOC_CTX
        }
        
        /* grab cifs/, http/ etc */
+       
+       /* This is checked for in callers, but be safe */
        if (principal->name.name_string.len < 2) {
-               DEBUG(5, ("could not find principal in DB, alias not applicable"));
                info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
                return WERR_OK;
        }
@@ -167,6 +173,7 @@ static WERROR DsCrackNameSPNAlias(struct drsuapi_bind_state *b_state, TALLOC_CTX
                return WERR_NOMEM;
        }
        
+       /* reform principal */
        ret = krb5_unparse_name_norealm(smb_krb5_context->krb5_context, principal, &new_princ);
 
        krb5_free_principal(smb_krb5_context->krb5_context, principal);
@@ -175,7 +182,6 @@ static WERROR DsCrackNameSPNAlias(struct drsuapi_bind_state *b_state, TALLOC_CTX
                return WERR_NOMEM;
        }
        
-       /* reform principal */
        wret = DsCrackNameOneName(b_state, mem_ctx, format_flags, format_offered, format_desired,
                                  new_princ, info1);
        free(new_princ);
@@ -201,7 +207,7 @@ static WERROR DsCrackNameUPN(struct drsuapi_bind_state *b_state, TALLOC_CTX *mem
                return WERR_OK;
        }
 
-       ret = krb5_parse_name(smb_krb5_context->krb5_context, name, &principal);
+       ret = krb5_parse_name_mustrealm(smb_krb5_context->krb5_context, name, &principal);
        if (ret) {
                info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
                return WERR_OK;
@@ -349,6 +355,14 @@ static WERROR DsCrackNameOneName(struct drsuapi_bind_state *b_state, TALLOC_CTX
                WERR_TALLOC_CHECK(result_filter);
                break;
        }
+       case DRSUAPI_DS_NAME_FORMAT_DISPLAY: {
+               domain_filter = NULL;
+
+               result_filter = talloc_asprintf(mem_ctx, "(|(displayName=%s)(samAccountName=%s))",
+                                               name, name);
+               WERR_TALLOC_CHECK(result_filter);
+               break;
+       }
        
        case DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY: {
                struct dom_sid *sid = dom_sid_parse_talloc(mem_ctx, name);
@@ -398,11 +412,11 @@ static WERROR DsCrackNameOneName(struct drsuapi_bind_state *b_state, TALLOC_CTX
                krb5_principal principal;
                char *unparsed_name_short;
                ret = krb5_parse_name_norealm(smb_krb5_context->krb5_context, name, &principal);
-               if (ret) {
+               if (ret || (principal->name.name_string.len < 2)) {
                        info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
                        return WERR_OK;
                }
-               
+
                domain_filter = NULL;
                
                ret = krb5_unparse_name_norealm(smb_krb5_context->krb5_context, principal, &unparsed_name_short);
@@ -424,6 +438,11 @@ static WERROR DsCrackNameOneName(struct drsuapi_bind_state *b_state, TALLOC_CTX
        }
 
        }
+
+       if (format_flags & DRSUAPI_DS_NAME_FLAG_SYNTACTICAL_ONLY) {
+               return DsCrackNameOneSyntactical(mem_ctx, format_offered, format_desired,
+                                                name_dn, name, info1);
+       }
        
        return DsCrackNameOneFilter(b_state, mem_ctx, 
                                    smb_krb5_context, 
@@ -433,6 +452,38 @@ static WERROR DsCrackNameOneName(struct drsuapi_bind_state *b_state, TALLOC_CTX
                                    info1);
 }
 
+static WERROR DsCrackNameOneSyntactical(TALLOC_CTX *mem_ctx,
+                                       uint32_t format_offered, uint32_t format_desired,
+                                       const struct ldb_dn *name_dn, const char *name, 
+                                       struct drsuapi_DsNameInfo1 *info1)
+{
+       char *cracked;
+       if (format_offered != DRSUAPI_DS_NAME_FORMAT_FQDN_1779) {
+               info1->status = DRSUAPI_DS_NAME_STATUS_NO_SYNTACTICAL_MAPPING;
+               return WERR_OK;
+       }
+
+       switch (format_desired) {
+       case DRSUAPI_DS_NAME_FORMAT_CANONICAL: 
+               cracked = ldb_dn_canonical_string(mem_ctx, name_dn);
+               break;
+       case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX:
+               cracked = ldb_dn_canonical_ex_string(mem_ctx, name_dn);
+               break;
+       default:
+               info1->status = DRSUAPI_DS_NAME_STATUS_NO_SYNTACTICAL_MAPPING;
+               return WERR_OK;
+       }
+       info1->status = DRSUAPI_DS_NAME_STATUS_OK;
+       info1->result_name      = cracked;
+       if (!cracked) {
+               return WERR_NOMEM;
+       }
+       
+       return WERR_OK; 
+       
+}
+
 static WERROR DsCrackNameOneFilter(struct drsuapi_bind_state *b_state, TALLOC_CTX *mem_ctx,
                                   struct smb_krb5_context *smb_krb5_context,
                                   uint32_t format_flags, uint32_t format_offered, uint32_t format_desired,
@@ -449,32 +500,42 @@ static WERROR DsCrackNameOneFilter(struct drsuapi_bind_state *b_state, TALLOC_CT
 
        /* here we need to set the attrs lists for domain and result lookups */
        switch (format_desired) {
-               case DRSUAPI_DS_NAME_FORMAT_FQDN_1779: {
-                       const char * const _domain_attrs[] = { "ncName", "dnsRoot", NULL};
-                       const char * const _result_attrs[] = { "distinguishedName", NULL};
-                       
-                       domain_attrs = _domain_attrs;
-                       result_attrs = _result_attrs;
-                       break;
-               }
-               case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT: {
-                       const char * const _domain_attrs[] = { "ncName", "dnsRoot", "nETBIOSName", NULL};
-                       const char * const _result_attrs[] = { "sAMAccountName", "objectSid", NULL};
-                       
-                       domain_attrs = _domain_attrs;
-                       result_attrs = _result_attrs;
-                       break;
-               }
-               case DRSUAPI_DS_NAME_FORMAT_GUID: {
-                       const char * const _domain_attrs[] = { "ncName", "dnsRoot", NULL};
-                       const char * const _result_attrs[] = { "objectGUID", NULL};
-                       
-                       domain_attrs = _domain_attrs;
-                       result_attrs = _result_attrs;
-                       break;
-               }
-               default:
-                       return WERR_OK;
+       case DRSUAPI_DS_NAME_FORMAT_FQDN_1779:
+       case DRSUAPI_DS_NAME_FORMAT_CANONICAL:
+       case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX: {
+               const char * const _domain_attrs[] = { "ncName", "dnsRoot", NULL};
+               const char * const _result_attrs[] = { NULL};
+               
+               domain_attrs = _domain_attrs;
+               result_attrs = _result_attrs;
+               break;
+       }
+       case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT: {
+               const char * const _domain_attrs[] = { "ncName", "dnsRoot", "nETBIOSName", NULL};
+               const char * const _result_attrs[] = { "sAMAccountName", "objectSid", NULL};
+               
+               domain_attrs = _domain_attrs;
+               result_attrs = _result_attrs;
+               break;
+       }
+       case DRSUAPI_DS_NAME_FORMAT_GUID: {
+               const char * const _domain_attrs[] = { "ncName", "dnsRoot", NULL};
+               const char * const _result_attrs[] = { "objectGUID", NULL};
+               
+               domain_attrs = _domain_attrs;
+               result_attrs = _result_attrs;
+               break;
+       }
+       case DRSUAPI_DS_NAME_FORMAT_DISPLAY: {
+               const char * const _domain_attrs[] = { "ncName", "dnsRoot", NULL};
+               const char * const _result_attrs[] = { "displayName", "samAccountName", NULL};
+               
+               domain_attrs = _domain_attrs;
+               result_attrs = _result_attrs;
+               break;
+       }
+       default:
+               return WERR_OK;
        }
 
        if (domain_filter) {
@@ -534,7 +595,8 @@ static WERROR DsCrackNameOneFilter(struct drsuapi_bind_state *b_state, TALLOC_CT
                                              format_flags, format_offered, format_desired,
                                              name, info1);
                }
-               break;
+               info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
+               return WERR_OK;
        case -1:
                info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
                return WERR_OK;
@@ -552,6 +614,16 @@ static WERROR DsCrackNameOneFilter(struct drsuapi_bind_state *b_state, TALLOC_CT
                info1->status           = DRSUAPI_DS_NAME_STATUS_OK;
                return WERR_OK;
        }
+       case DRSUAPI_DS_NAME_FORMAT_CANONICAL:
+               return DsCrackNameOneSyntactical(mem_ctx, 
+                                                DRSUAPI_DS_NAME_FORMAT_FQDN_1779, 
+                                                DRSUAPI_DS_NAME_FORMAT_CANONICAL,
+                                                result_res[0]->dn, name, info1);
+       case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX:
+               return DsCrackNameOneSyntactical(mem_ctx, 
+                                                DRSUAPI_DS_NAME_FORMAT_FQDN_1779, 
+                                                DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX,
+                                                result_res[0]->dn, name, info1);
        case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT: {
                const struct dom_sid *sid = samdb_result_dom_sid(mem_ctx, result_res[0], "objectSid");
                const char *_acc = "", *_dom = "";
@@ -616,6 +688,18 @@ static WERROR DsCrackNameOneFilter(struct drsuapi_bind_state *b_state, TALLOC_CT
                info1->status           = DRSUAPI_DS_NAME_STATUS_OK;
                return WERR_OK;
        }
+       case DRSUAPI_DS_NAME_FORMAT_DISPLAY: {
+               info1->result_name      = samdb_result_string(result_res[0], "displayName", NULL);
+               if (!info1->result_name) {
+                       info1->result_name      = samdb_result_string(result_res[0], "sAMAccountName", NULL);
+               } 
+               if (!info1->result_name) {
+                       info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
+               } else {
+                       info1->status = DRSUAPI_DS_NAME_STATUS_OK;
+               }
+               return WERR_OK;
+       }
        default:
                return WERR_OK;
        }
index 9ebeab2a8b49341e90b5c6ffad050c29b8786012..b37825d85c476c708a9a0f693e6ff26d0332fbd3 100644 (file)
@@ -25,6 +25,7 @@
 #include "includes.h"
 #include "librpc/gen_ndr/ndr_drsuapi.h"
 #include "torture/rpc/drsuapi.h"
+#include "ldb/include/ldb.h"
 
 static BOOL test_DsCrackNamesMatrix(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
                                    struct DsPrivate *priv, const char *dn,
@@ -35,7 +36,6 @@ static BOOL test_DsCrackNamesMatrix(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        NTSTATUS status;
        BOOL ret = True;
        struct drsuapi_DsCrackNames r;
-       struct drsuapi_DsNameString names[1];
        enum drsuapi_DsNameFormat formats[] = {
                DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
                DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
@@ -48,6 +48,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)];
@@ -208,6 +209,10 @@ BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        const char *dns_domain;
        const char *nt4_domain;
        const char *FQDN_1779_name;
+       struct ldb_dn *FQDN_1779_dn;
+       struct ldb_dn *realm_dn;
+       const char *realm_canonical;
+       const char *realm_canonical_ex;
        const char *user_principal_name;
        const char *service_principal_name;
        const char *canonical_name;
@@ -305,6 +310,27 @@ BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        if (!ret) {
                return ret;
        }
+       
+       realm_dn =  ldb_dn_explode(mem_ctx, r.out.ctr.ctr1->array[0].result_name);
+       realm_canonical = ldb_dn_canonical_string(mem_ctx, realm_dn);
+
+       if (strcmp(realm_canonical, 
+                  talloc_asprintf(mem_ctx, "%s/", lp_realm()))!= 0) {
+               printf("local Round trip on canonical name failed: %s != %s!\n",
+                      realm_canonical, 
+                      talloc_asprintf(mem_ctx, "%s/", lp_realm()));
+                   return False;
+       };
+
+       realm_canonical_ex = ldb_dn_canonical_ex_string(mem_ctx, realm_dn);
+
+       if (strcmp(realm_canonical_ex, 
+                  talloc_asprintf(mem_ctx, "%s\n", lp_realm()))!= 0) {
+               printf("local Round trip on canonical ex name failed: %s != %s!\n",
+                      realm_canonical, 
+                      talloc_asprintf(mem_ctx, "%s\n", lp_realm()));
+                   return False;
+       };
 
        r.in.req.req1.format_offered    = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;
        r.in.req.req1.format_desired    = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
@@ -364,63 +390,10 @@ BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 
        FQDN_1779_name = 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_CANONICAL;
-       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);
-
-       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;
-       }
+       FQDN_1779_dn = ldb_dn_explode(mem_ctx, FQDN_1779_name);
 
-       if (!ret) {
-               return ret;
-       }
-
-       canonical_name = 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_CANONICAL_EX;
-       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);
-
-       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;
-       }
-
-       canonical_ex_name = r.out.ctr.ctr1->array[0].result_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);
        service_principal_name = talloc_asprintf(mem_ctx, "HOST/%s", test_dc);
@@ -714,15 +687,14 @@ BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                                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", 
+                               printf("DsCrackNames unexpected status %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)) {
+                       } else 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);