+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)