s4-torture: LookupSids3 is only available over NCACN_IP_TCP.
[kai/samba.git] / source4 / torture / rpc / lsa.c
index 3f91afedd6ddc110650213936afbde05bca7e6ba..f420ec183386105990ec5c64d7b6663654bf7388 100644 (file)
@@ -24,6 +24,7 @@
 #include "librpc/gen_ndr/ndr_lsa_c.h"
 #include "librpc/gen_ndr/netlogon.h"
 #include "librpc/gen_ndr/ndr_drsblobs.h"
+#include "librpc/gen_ndr/ndr_netlogon_c.h"
 #include "lib/events/events.h"
 #include "libcli/security/security.h"
 #include "libcli/auth/libcli_auth.h"
@@ -31,6 +32,7 @@
 #include "param/param.h"
 #include "../lib/crypto/crypto.h"
 #define TEST_MACHINENAME "lsatestmach"
+#define TRUSTPW "12345678"
 
 static void init_lsa_String(struct lsa_String *name, const char *s)
 {
@@ -148,23 +150,6 @@ bool test_lsa_OpenPolicy2(struct dcerpc_binding_handle *b,
        return test_lsa_OpenPolicy2_ex(b, tctx, handle, NT_STATUS_OK);
 }
 
-static const char *sid_type_lookup(enum lsa_SidType r)
-{
-       switch (r) {
-               case SID_NAME_USE_NONE: return "SID_NAME_USE_NONE"; break;
-               case SID_NAME_USER: return "SID_NAME_USER"; break;
-               case SID_NAME_DOM_GRP: return "SID_NAME_DOM_GRP"; break;
-               case SID_NAME_DOMAIN: return "SID_NAME_DOMAIN"; break;
-               case SID_NAME_ALIAS: return "SID_NAME_ALIAS"; break;
-               case SID_NAME_WKN_GRP: return "SID_NAME_WKN_GRP"; break;
-               case SID_NAME_DELETED: return "SID_NAME_DELETED"; break;
-               case SID_NAME_INVALID: return "SID_NAME_INVALID"; break;
-               case SID_NAME_UNKNOWN: return "SID_NAME_UNKNOWN"; break;
-               case SID_NAME_COMPUTER: return "SID_NAME_COMPUTER"; break;
-       }
-       return "Invalid sid type\n";
-}
-
 static bool test_LookupNames(struct dcerpc_binding_handle *b,
                             struct torture_context *tctx,
                             struct policy_handle *handle,
@@ -176,19 +161,28 @@ static bool test_LookupNames(struct dcerpc_binding_handle *b,
        struct lsa_String *names;
        uint32_t count = 0;
        int i;
+       uint32_t *input_idx;
 
        torture_comment(tctx, "\nTesting LookupNames with %d names\n", tnames->count);
 
        sids.count = 0;
        sids.sids = NULL;
 
+
+       r.in.num_names = 0;
+
+       input_idx = talloc_array(tctx, uint32_t, tnames->count);
        names = talloc_array(tctx, struct lsa_String, tnames->count);
+
        for (i=0;i<tnames->count;i++) {
-               init_lsa_String(&names[i], tnames->names[i].name.string);
+               if (tnames->names[i].sid_type != SID_NAME_UNKNOWN) {
+                       init_lsa_String(&names[r.in.num_names], tnames->names[i].name.string);
+                       input_idx[r.in.num_names] = i;
+                       r.in.num_names++;
+               }
        }
 
        r.in.handle = handle;
-       r.in.num_names = tnames->count;
        r.in.names = names;
        r.in.sids = &sids;
        r.in.level = 1;
@@ -201,7 +195,7 @@ static bool test_LookupNames(struct dcerpc_binding_handle *b,
                                   "LookupNames failed");
        if (NT_STATUS_EQUAL(r.out.result, STATUS_SOME_UNMAPPED) ||
            NT_STATUS_EQUAL(r.out.result, NT_STATUS_NONE_MAPPED)) {
-               for (i=0;i< tnames->count;i++) {
+               for (i=0;i< r.in.num_names;i++) {
                        if (i < count && sids.sids[i].sid_type == SID_NAME_UNKNOWN) {
                                torture_comment(tctx, "LookupName of %s was unmapped\n",
                                       tnames->names[i].name.string);
@@ -219,22 +213,23 @@ static bool test_LookupNames(struct dcerpc_binding_handle *b,
                return false;
        }
 
-       for (i=0;i< tnames->count;i++) {
+       for (i=0;i< r.in.num_names;i++) {
                if (i < count) {
-                       if (sids.sids[i].sid_type != tnames->names[i].sid_type) {
+                       if (sids.sids[i].sid_type != tnames->names[input_idx[i]].sid_type) {
                                torture_comment(tctx, "LookupName of %s got unexpected name type: %s\n",
-                                      tnames->names[i].name.string, sid_type_lookup(sids.sids[i].sid_type));
+                                               tnames->names[input_idx[i]].name.string,
+                                               sid_type_lookup(sids.sids[i].sid_type));
                                return false;
                        }
                        if ((sids.sids[i].sid_type == SID_NAME_DOMAIN) &&
                            (sids.sids[i].rid != (uint32_t)-1)) {
                                torture_comment(tctx, "LookupName of %s got unexpected rid: %d\n",
-                                       tnames->names[i].name.string, sids.sids[i].rid);
+                                       tnames->names[input_idx[i]].name.string, sids.sids[i].rid);
                                return false;
                        }
                } else if (i >=count) {
                        torture_comment(tctx, "LookupName of %s failed to return a result\n",
-                              tnames->names[i].name.string);
+                              tnames->names[input_idx[i]].name.string);
                        return false;
                }
        }
@@ -394,14 +389,22 @@ static bool test_LookupNames2(struct dcerpc_binding_handle *b,
 
        sids.count = 0;
        sids.sids = NULL;
+       uint32_t *input_idx;
 
+       r.in.num_names = 0;
+
+       input_idx = talloc_array(tctx, uint32_t, tnames->count);
        names = talloc_array(tctx, struct lsa_String, tnames->count);
+
        for (i=0;i<tnames->count;i++) {
-               init_lsa_String(&names[i], tnames->names[i].name.string);
+               if (tnames->names[i].sid_type != SID_NAME_UNKNOWN) {
+                       init_lsa_String(&names[r.in.num_names], tnames->names[i].name.string);
+                       input_idx[r.in.num_names] = i;
+                       r.in.num_names++;
+               }
        }
 
        r.in.handle = handle;
-       r.in.num_names = tnames->count;
        r.in.names = names;
        r.in.sids = &sids;
        r.in.level = 1;
@@ -446,19 +449,26 @@ static bool test_LookupNames3(struct dcerpc_binding_handle *b,
        struct lsa_String *names;
        uint32_t count = 0;
        int i;
+       uint32_t *input_idx;
 
        torture_comment(tctx, "\nTesting LookupNames3 with %d names\n", tnames->count);
 
        sids.count = 0;
        sids.sids = NULL;
 
+       r.in.num_names = 0;
+
+       input_idx = talloc_array(tctx, uint32_t, tnames->count);
        names = talloc_array(tctx, struct lsa_String, tnames->count);
        for (i=0;i<tnames->count;i++) {
-               init_lsa_String(&names[i], tnames->names[i].name.string);
+               if (tnames->names[i].sid_type != SID_NAME_UNKNOWN) {
+                       init_lsa_String(&names[r.in.num_names], tnames->names[i].name.string);
+                       input_idx[r.in.num_names] = i;
+                       r.in.num_names++;
+               }
        }
 
        r.in.handle = handle;
-       r.in.num_names = tnames->count;
        r.in.names = names;
        r.in.sids = &sids;
        r.in.level = 1;
@@ -501,15 +511,23 @@ static bool test_LookupNames4(struct dcerpc_binding_handle *b,
        struct lsa_String *names;
        uint32_t count = 0;
        int i;
+       uint32_t *input_idx;
 
        torture_comment(tctx, "\nTesting LookupNames4 with %d names\n", tnames->count);
 
        sids.count = 0;
        sids.sids = NULL;
 
+       r.in.num_names = 0;
+
+       input_idx = talloc_array(tctx, uint32_t, tnames->count);
        names = talloc_array(tctx, struct lsa_String, tnames->count);
        for (i=0;i<tnames->count;i++) {
-               init_lsa_String(&names[i], tnames->names[i].name.string);
+               if (tnames->names[i].sid_type != SID_NAME_UNKNOWN) {
+                       init_lsa_String(&names[r.in.num_names], tnames->names[i].name.string);
+                       input_idx[r.in.num_names] = i;
+                       r.in.num_names++;
+               }
        }
 
        r.in.num_names = tnames->count;
@@ -571,7 +589,8 @@ static bool test_LookupSids(struct dcerpc_binding_handle *b,
 
        torture_assert_ntstatus_ok(tctx, dcerpc_lsa_LookupSids_r(b, tctx, &r),
                "LookupSids failed");
-       if (!NT_STATUS_IS_OK(r.out.result)) {
+       if (!NT_STATUS_IS_OK(r.out.result) &&
+           !NT_STATUS_EQUAL(r.out.result, STATUS_SOME_UNMAPPED)) {
                torture_comment(tctx, "LookupSids failed - %s\n",
                                nt_errstr(r.out.result));
                return false;
@@ -615,7 +634,8 @@ static bool test_LookupSids2(struct dcerpc_binding_handle *b,
 
        torture_assert_ntstatus_ok(tctx, dcerpc_lsa_LookupSids2_r(b, tctx, &r),
                "LookupSids2 failed");
-       if (!NT_STATUS_IS_OK(r.out.result)) {
+       if (!NT_STATUS_IS_OK(r.out.result) &&
+           !NT_STATUS_EQUAL(r.out.result, STATUS_SOME_UNMAPPED)) {
                torture_comment(tctx, "LookupSids2 failed - %s\n",
                                nt_errstr(r.out.result));
                return false;
@@ -733,7 +753,8 @@ bool test_many_LookupSids(struct dcerpc_pipe *p,
                        return false;
                }
        } else if (p->conn->security_state.auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL &&
-                  p->conn->security_state.auth_info->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
+                  p->conn->security_state.auth_info->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY &&
+                  (p->binding->transport == NCACN_IP_TCP || p->binding->transport == NCALRPC)) {
                struct lsa_LookupSids3 r;
                struct lsa_RefDomainList *domains = NULL;
                struct lsa_TransNameArray2 names;
@@ -848,7 +869,7 @@ static bool test_LookupSids_async(struct dcerpc_binding_handle *b,
        }
 
        while (replies >= 0 && replies < num_async_requests) {
-               event_loop_once(tctx->ev);
+               tevent_loop_once(tctx->ev);
        }
 
        talloc_free(req);
@@ -1400,7 +1421,7 @@ static bool test_CreateSecret(struct dcerpc_pipe *p,
                r5.in.new_val->size = enc_key.length;
 
 
-               msleep(200);
+               smb_msleep(200);
                torture_comment(tctx, "Testing SetSecret (existing value should move to old)\n");
 
                torture_assert_ntstatus_ok(tctx, dcerpc_lsa_SetSecret_r(b, tctx, &r5),
@@ -2335,7 +2356,7 @@ static bool test_CreateTrustedDomain(struct dcerpc_binding_handle *b,
                                ret = false;
                        } else {
                                if (strcmp(info->info_ex.netbios_name.string, trustinfo.name.string) != 0) {
-                                       torture_comment(tctx, "QueryTrustedDomainInfo returned inconsistant short name: %s != %s\n",
+                                       torture_comment(tctx, "QueryTrustedDomainInfo returned inconsistent short name: %s != %s\n",
                                               info->info_ex.netbios_name.string, trustinfo.name.string);
                                        ret = false;
                                }
@@ -2376,28 +2397,251 @@ static bool test_CreateTrustedDomain(struct dcerpc_binding_handle *b,
        return ret;
 }
 
-static bool test_CreateTrustedDomainEx2(struct dcerpc_pipe *p,
-                                       struct torture_context *tctx,
-                                       struct policy_handle *handle,
-                                       uint32_t num_trusts)
+static bool gen_authinfo_internal(TALLOC_CTX *mem_ctx, const char *password,
+                                 DATA_BLOB session_key,
+                                 struct lsa_TrustDomainInfoAuthInfoInternal **_authinfo_internal)
+{
+       struct lsa_TrustDomainInfoAuthInfoInternal *authinfo_internal;
+       struct trustDomainPasswords auth_struct;
+       struct AuthenticationInformation *auth_info_array;
+       size_t converted_size;
+       DATA_BLOB auth_blob;
+       enum ndr_err_code ndr_err;
+
+       authinfo_internal = talloc_zero(mem_ctx, struct lsa_TrustDomainInfoAuthInfoInternal);
+       if (authinfo_internal == NULL) {
+               return false;
+       }
+
+       auth_info_array = talloc_array(mem_ctx,
+                                      struct AuthenticationInformation, 1);
+       if (auth_info_array == NULL) {
+               return false;
+       }
+
+       generate_random_buffer(auth_struct.confounder, sizeof(auth_struct.confounder));
+
+       auth_info_array[0].AuthType = TRUST_AUTH_TYPE_CLEAR;
+
+       if (!convert_string_talloc(mem_ctx, CH_UNIX, CH_UTF16, password,
+                                 strlen(password),
+                                 &auth_info_array[0].AuthInfo.clear.password,
+                                 &converted_size)) {
+               return false;
+       }
+
+       auth_info_array[0].AuthInfo.clear.size = converted_size;
+
+       auth_struct.outgoing.count = 1;
+       auth_struct.outgoing.current.count = 1;
+       auth_struct.outgoing.current.array = auth_info_array;
+       auth_struct.outgoing.previous.count = 0;
+       auth_struct.outgoing.previous.array = NULL;
+
+       auth_struct.incoming.count = 1;
+       auth_struct.incoming.current.count = 1;
+       auth_struct.incoming.current.array = auth_info_array;
+       auth_struct.incoming.previous.count = 0;
+       auth_struct.incoming.previous.array = NULL;
+
+
+       ndr_err = ndr_push_struct_blob(&auth_blob, mem_ctx, &auth_struct,
+                                      (ndr_push_flags_fn_t)ndr_push_trustDomainPasswords);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               return false;
+       }
+
+       arcfour_crypt_blob(auth_blob.data, auth_blob.length, &session_key);
+
+       authinfo_internal->auth_blob.size = auth_blob.length;
+       authinfo_internal->auth_blob.data = auth_blob.data;
+
+       *_authinfo_internal = authinfo_internal;
+
+       return true;
+}
+
+static bool gen_authinfo(TALLOC_CTX *mem_ctx, const char *password,
+                        struct lsa_TrustDomainInfoAuthInfo **_authinfo)
+{
+       struct lsa_TrustDomainInfoAuthInfo *authinfo;
+       struct lsa_TrustDomainInfoBuffer *info_buffer;
+       size_t converted_size;
+
+       authinfo = talloc_zero(mem_ctx, struct lsa_TrustDomainInfoAuthInfo);
+       if (authinfo == NULL) {
+               return false;
+       }
+
+       info_buffer = talloc_zero(mem_ctx, struct lsa_TrustDomainInfoBuffer);
+       if (info_buffer == NULL) {
+               return false;
+       }
+
+       info_buffer->AuthType = TRUST_AUTH_TYPE_CLEAR;
+
+       if (!convert_string_talloc(mem_ctx, CH_UNIX, CH_UTF16, password,
+                                 strlen(password),
+                                 &info_buffer->data.data,
+                                 &converted_size)) {
+               return false;
+       }
+
+       info_buffer->data.size = converted_size;
+
+       authinfo->incoming_count = 1;
+       authinfo->incoming_current_auth_info = info_buffer;
+       authinfo->incoming_previous_auth_info = NULL;
+       authinfo->outgoing_count = 1;
+       authinfo->outgoing_current_auth_info = info_buffer;
+       authinfo->outgoing_previous_auth_info = NULL;
+
+       *_authinfo = authinfo;
+
+       return true;
+}
+
+static bool check_pw_with_ServerAuthenticate3(struct dcerpc_pipe *p,
+                                            struct torture_context *tctx,
+                                            uint32_t negotiate_flags,
+                                            struct cli_credentials *machine_credentials,
+                                            struct netlogon_creds_CredentialState **creds_out)
+{
+       struct netr_ServerReqChallenge r;
+       struct netr_ServerAuthenticate3 a;
+       struct netr_Credential credentials1, credentials2, credentials3;
+       struct netlogon_creds_CredentialState *creds;
+       struct samr_Password mach_password;
+       uint32_t rid;
+       const char *machine_name;
+       const char *plain_pass;
+       struct dcerpc_binding_handle *b = p->binding_handle;
+
+       machine_name = cli_credentials_get_workstation(machine_credentials);
+       plain_pass = cli_credentials_get_password(machine_credentials);
+
+       r.in.server_name = NULL;
+       r.in.computer_name = machine_name;
+       r.in.credentials = &credentials1;
+       r.out.return_credentials = &credentials2;
+
+       generate_random_buffer(credentials1.data, sizeof(credentials1.data));
+
+       torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerReqChallenge_r(b, tctx, &r),
+               "ServerReqChallenge failed");
+       torture_assert_ntstatus_ok(tctx, r.out.result, "ServerReqChallenge failed");
+
+       E_md4hash(plain_pass, mach_password.hash);
+
+       a.in.server_name = NULL;
+       a.in.account_name = talloc_asprintf(tctx, "%s$", machine_name);
+       a.in.secure_channel_type = cli_credentials_get_secure_channel_type(machine_credentials);
+       a.in.computer_name = machine_name;
+       a.in.negotiate_flags = &negotiate_flags;
+       a.in.credentials = &credentials3;
+       a.out.return_credentials = &credentials3;
+       a.out.negotiate_flags = &negotiate_flags;
+       a.out.rid = &rid;
+
+       creds = netlogon_creds_client_init(tctx, a.in.account_name,
+                                          a.in.computer_name,
+                                          &credentials1, &credentials2,
+                                          &mach_password, &credentials3,
+                                          negotiate_flags);
+
+       torture_assert(tctx, creds != NULL, "memory allocation");
+
+       torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerAuthenticate3_r(b, tctx, &a),
+               "ServerAuthenticate3 failed");
+       if (!NT_STATUS_IS_OK(a.out.result)) {
+               if (!NT_STATUS_EQUAL(a.out.result, NT_STATUS_ACCESS_DENIED)) {
+                       torture_assert_ntstatus_ok(tctx, a.out.result,
+                                                  "ServerAuthenticate3 failed");
+               }
+               return false;
+       }
+       torture_assert(tctx, netlogon_creds_client_check(creds, &credentials3), "Credential chaining failed");
+
+       /* Prove that requesting a challenge again won't break it */
+       torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerReqChallenge_r(b, tctx, &r),
+               "ServerReqChallenge failed");
+       torture_assert_ntstatus_ok(tctx, r.out.result, "ServerReqChallenge failed");
+
+       *creds_out = creds;
+       return true;
+}
+
+static bool check_dom_trust_pw(struct dcerpc_pipe *p,
+                              struct torture_context *tctx,
+                              const char *trusted_dom_name,
+                              const char *password)
+{
+       struct cli_credentials *credentials;
+       char *dummy;
+       struct netlogon_creds_CredentialState *creds;
+       struct dcerpc_pipe *pipe;
+       NTSTATUS status;
+       bool ok;
+
+       credentials = cli_credentials_init(tctx);
+       if (credentials == NULL) {
+               return false;
+       }
+
+       dummy = talloc_asprintf(tctx, "%s$", trusted_dom_name);
+       if (dummy == NULL) {
+               return false;
+       }
+
+       cli_credentials_set_username(credentials, dummy, CRED_SPECIFIED);
+       cli_credentials_set_password(credentials, password, CRED_SPECIFIED);
+       cli_credentials_set_workstation(credentials,
+                                       trusted_dom_name, CRED_SPECIFIED);
+       cli_credentials_set_secure_channel_type(credentials, SEC_CHAN_DOMAIN);
+
+       status = dcerpc_pipe_connect_b(tctx, &pipe, p->binding,
+                                      &ndr_table_netlogon,
+                                      cli_credentials_init_anon(tctx),
+                                      tctx->ev, tctx->lp_ctx);
+       if (!NT_STATUS_IS_OK(status)) {
+               torture_comment(tctx, "dcerpc_pipe_connect_b failed.\n");
+               return false;
+       }
+
+       ok = check_pw_with_ServerAuthenticate3(pipe, tctx,
+                                              NETLOGON_NEG_AUTH2_ADS_FLAGS,
+                                              credentials, &creds);
+       talloc_free(pipe);
+
+       return ok;
+}
+
+static bool test_CreateTrustedDomainEx_common(struct dcerpc_pipe *p,
+                                             struct torture_context *tctx,
+                                             struct policy_handle *handle,
+                                             uint32_t num_trusts,
+                                             bool ex2_call)
 {
        NTSTATUS status;
        bool ret = true;
-       struct lsa_CreateTrustedDomainEx2 r;
+       struct lsa_CreateTrustedDomainEx r;
+       struct lsa_CreateTrustedDomainEx2 r2;
        struct lsa_TrustDomainInfoInfoEx trustinfo;
-       struct lsa_TrustDomainInfoAuthInfoInternal authinfo;
-       struct trustDomainPasswords auth_struct;
-       DATA_BLOB auth_blob;
+       struct lsa_TrustDomainInfoAuthInfoInternal *authinfo_internal;
+       struct lsa_TrustDomainInfoAuthInfo *authinfo;
        struct dom_sid **domsid;
        struct policy_handle *trustdom_handle;
        struct lsa_QueryTrustedDomainInfo q;
        union lsa_TrustedDomainInfo *info = NULL;
        DATA_BLOB session_key;
-       enum ndr_err_code ndr_err;
        int i;
        struct dcerpc_binding_handle *b = p->binding_handle;
 
-       torture_comment(tctx, "\nTesting CreateTrustedDomainEx2 for %d domains\n", num_trusts);
+       if (ex2_call) {
+               torture_comment(tctx, "\nTesting CreateTrustedDomainEx2 for %d domains\n", num_trusts);
+       } else {
+               torture_comment(tctx, "\nTesting CreateTrustedDomainEx for %d domains\n", num_trusts);
+       }
 
        domsid = talloc_array(tctx, struct dom_sid *, num_trusts);
        trustdom_handle = talloc_array(tctx, struct policy_handle, num_trusts);
@@ -2433,40 +2677,82 @@ static bool test_CreateTrustedDomainEx2(struct dcerpc_pipe *p,
 
                trustinfo.trust_attributes = LSA_TRUST_ATTRIBUTE_USES_RC4_ENCRYPTION;
 
-               generate_random_buffer(auth_struct.confounder, sizeof(auth_struct.confounder));
-
-               auth_struct.outgoing.count = 0;
-               auth_struct.incoming.count = 0;
+               if (!gen_authinfo_internal(tctx, TRUSTPW, session_key, &authinfo_internal)) {
+                       torture_comment(tctx, "gen_authinfo_internal failed");
+                       ret = false;
+               }
 
-               ndr_err = ndr_push_struct_blob(&auth_blob, tctx, lp_iconv_convenience(tctx->lp_ctx), &auth_struct,
-                                              (ndr_push_flags_fn_t)ndr_push_trustDomainPasswords);
-               if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-                       torture_comment(tctx, "ndr_push_struct_blob of trustDomainPasswords structure failed");
+               if (!gen_authinfo(tctx, TRUSTPW, &authinfo)) {
+                       torture_comment(tctx, "gen_authinfonfo failed");
                        ret = false;
                }
 
-               arcfour_crypt_blob(auth_blob.data, auth_blob.length, &session_key);
+               if (ex2_call) {
 
-               authinfo.auth_blob.size = auth_blob.length;
-               authinfo.auth_blob.data = auth_blob.data;
+                       r2.in.policy_handle = handle;
+                       r2.in.info = &trustinfo;
+                       r2.in.auth_info_internal = authinfo_internal;
+                       r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+                       r2.out.trustdom_handle = &trustdom_handle[i];
 
-               r.in.policy_handle = handle;
-               r.in.info = &trustinfo;
-               r.in.auth_info = &authinfo;
-               r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
-               r.out.trustdom_handle = &trustdom_handle[i];
+                       torture_assert_ntstatus_ok(tctx,
+                               dcerpc_lsa_CreateTrustedDomainEx2_r(b, tctx, &r2),
+                               "CreateTrustedDomainEx2 failed");
 
-               torture_assert_ntstatus_ok(tctx, dcerpc_lsa_CreateTrustedDomainEx2_r(b, tctx, &r),
-                       "CreateTrustedDomainEx2 failed");
-               if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_OBJECT_NAME_COLLISION)) {
+                       status = r2.out.result;
+               } else {
+
+                       r.in.policy_handle = handle;
+                       r.in.info = &trustinfo;
+                       r.in.auth_info = authinfo;
+                       r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+                       r.out.trustdom_handle = &trustdom_handle[i];
+
+                       torture_assert_ntstatus_ok(tctx,
+                               dcerpc_lsa_CreateTrustedDomainEx_r(b, tctx, &r),
+                               "CreateTrustedDomainEx failed");
+
+                       status = r.out.result;
+               }
+
+               if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
                        test_DeleteTrustedDomain(b, tctx, handle, trustinfo.netbios_name);
-                       torture_assert_ntstatus_ok(tctx, dcerpc_lsa_CreateTrustedDomainEx2_r(b, tctx, &r),
-                               "CreateTrustedDomainEx2 failed");
+                       if (ex2_call) {
+                               torture_assert_ntstatus_ok(tctx,
+                                       dcerpc_lsa_CreateTrustedDomainEx2_r(b, tctx, &r2),
+                                       "CreateTrustedDomainEx2 failed");
+                               status = r2.out.result;
+                       } else {
+                               torture_assert_ntstatus_ok(tctx,
+                                       dcerpc_lsa_CreateTrustedDomainEx_r(b, tctx, &r),
+                                       "CreateTrustedDomainEx2 failed");
+                               status = r.out.result;
+                       }
                }
-               if (!NT_STATUS_IS_OK(r.out.result)) {
-                       torture_comment(tctx, "CreateTrustedDomainEx failed2 - %s\n", nt_errstr(r.out.result));
+               if (!NT_STATUS_IS_OK(status)) {
+                       torture_comment(tctx, "CreateTrustedDomainEx failed2 - %s\n", nt_errstr(status));
                        ret = false;
                } else {
+                       /* For outbound and MIT trusts there is no trust account */
+                       if (trustinfo.trust_direction != 2 &&
+                           trustinfo.trust_type != 3) {
+
+                               if (torture_setting_bool(tctx, "samba3", false) ||
+                                   torture_setting_bool(tctx, "samba4", false)) {
+                                       torture_comment(tctx, "skipping trusted domain auth tests against samba");
+                               } else {
+                                       if (check_dom_trust_pw(p, tctx, trust_name,
+                                                               "x" TRUSTPW "x")) {
+                                               torture_comment(tctx, "Password check passed unexpectedly\n");
+                                               ret = false;
+                                       }
+                                       if (!check_dom_trust_pw(p, tctx, trust_name,
+                                                               TRUSTPW)) {
+                                               torture_comment(tctx, "Password check failed\n");
+                                               ret = false;
+                                       }
+                               }
+                       }
 
                        q.in.trustdom_handle = &trustdom_handle[i];
                        q.in.level = LSA_TRUSTED_DOMAIN_INFO_INFO_EX;
@@ -2481,7 +2767,7 @@ static bool test_CreateTrustedDomainEx2(struct dcerpc_pipe *p,
                                ret = false;
                        } else {
                                if (strcmp(info->info_ex.netbios_name.string, trustinfo.netbios_name.string) != 0) {
-                                       torture_comment(tctx, "QueryTrustedDomainInfo returned inconsistant short name: %s != %s\n",
+                                       torture_comment(tctx, "QueryTrustedDomainInfo returned inconsistent short name: %s != %s\n",
                                               info->info_ex.netbios_name.string, trustinfo.netbios_name.string);
                                        ret = false;
                                }
@@ -2525,6 +2811,22 @@ static bool test_CreateTrustedDomainEx2(struct dcerpc_pipe *p,
        return ret;
 }
 
+static bool test_CreateTrustedDomainEx2(struct dcerpc_pipe *p,
+                                       struct torture_context *tctx,
+                                       struct policy_handle *handle,
+                                       uint32_t num_trusts)
+{
+       return test_CreateTrustedDomainEx_common(p, tctx, handle, num_trusts, true);
+}
+
+static bool test_CreateTrustedDomainEx(struct dcerpc_pipe *p,
+                                      struct torture_context *tctx,
+                                      struct policy_handle *handle,
+                                      uint32_t num_trusts)
+{
+       return test_CreateTrustedDomainEx_common(p, tctx, handle, num_trusts, false);
+}
+
 static bool test_QueryDomainInfoPolicy(struct dcerpc_binding_handle *b,
                                 struct torture_context *tctx,
                                 struct policy_handle *handle)
@@ -2938,7 +3240,7 @@ struct torture_suite *torture_rpc_lsa_lookup_names(TALLOC_CTX *mem_ctx)
        struct torture_suite *suite;
        struct torture_rpc_tcase *tcase;
 
-       suite = torture_suite_create(mem_ctx, "LSA-LOOKUPNAMES");
+       suite = torture_suite_create(mem_ctx, "lsa.lookupnames");
 
        tcase = torture_suite_add_rpc_iface_tcase(suite, "lsa",
                                                  &ndr_table_lsarpc);
@@ -2980,6 +3282,10 @@ static bool testcase_TrustedDomains(struct torture_context *tctx,
                ret = false;
        }
 
+       if (!test_CreateTrustedDomainEx(p, tctx, handle, state->num_trusts)) {
+               ret = false;
+       }
+
        if (!test_CreateTrustedDomainEx2(p, tctx, handle, state->num_trusts)) {
                ret = false;
        }
@@ -3001,7 +3307,7 @@ struct torture_suite *torture_rpc_lsa_trusted_domains(TALLOC_CTX *mem_ctx)
 
        state->num_trusts = 12;
 
-       suite = torture_suite_create(mem_ctx, "LSA-TRUSTED-DOMAINS");
+       suite = torture_suite_create(mem_ctx, "lsa.trusted.domains");
 
        tcase = torture_suite_add_rpc_iface_tcase(suite, "lsa",
                                                  &ndr_table_lsarpc);
@@ -3056,7 +3362,7 @@ struct torture_suite *torture_rpc_lsa_privileges(TALLOC_CTX *mem_ctx)
        struct torture_suite *suite;
        struct torture_rpc_tcase *tcase;
 
-       suite = torture_suite_create(mem_ctx, "LSA-PRIVILEGES");
+       suite = torture_suite_create(mem_ctx, "lsa.privileges");
 
        tcase = torture_suite_add_rpc_iface_tcase(suite, "lsa",
                                                  &ndr_table_lsarpc);