static bool pdb_samba_dsdb_get_trusteddom_pw(struct pdb_methods *m,
				      const char *domain, char** pwd,
				      struct dom_sid *sid,
				      time_t *pass_last_set_time)
{
	struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
		m->private_data, struct pdb_samba_dsdb_state);
	TALLOC_CTX *tmp_ctx = talloc_stackframe();
	const char * const attrs[] = {
		"securityIdentifier",
		"flatName",
		"trustPartner",
		"trustAuthOutgoing",
		"whenCreated",
		"msDS-SupportedEncryptionTypes",
		"trustAttributes",
		"trustDirection",
		"trustType",
		NULL
	};
	struct ldb_message *msg;
	const struct ldb_val *password_val;
	int trust_direction_flags;
	int trust_type;
	int i;
	DATA_BLOB password_utf16;
	struct trustAuthInOutBlob password_blob;
	struct AuthenticationInformationArray *auth_array;
	char *password_talloc;
	size_t password_len;
	enum ndr_err_code ndr_err;
	NTSTATUS status;
	const char *netbios_domain = NULL;
	const struct dom_sid *domain_sid = NULL;

	status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
				       attrs, tmp_ctx, &msg);
	if (!NT_STATUS_IS_OK(status)) {
		/*
		 * This can be called to work out of a domain is
		 * trusted, rather than just to get the password
		 */
		DEBUG(2, ("Failed to get trusted domain password for %s - %s.  "
			  "It may not be a trusted domain.\n", domain,
			  nt_errstr(status)));
		TALLOC_FREE(tmp_ctx);
		return false;
	}

	netbios_domain = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
	if (netbios_domain == NULL) {
		DEBUG(2, ("Trusted domain %s has to flatName defined.\n",
			  domain));
		TALLOC_FREE(tmp_ctx);
		return false;
	}

	domain_sid = samdb_result_dom_sid(tmp_ctx, msg, "securityIdentifier");
	if (domain_sid == NULL) {
		DEBUG(2, ("Trusted domain %s has no securityIdentifier defined.\n",
			  domain));
		TALLOC_FREE(tmp_ctx);
		return false;
	}

	trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
	if (!(trust_direction_flags & LSA_TRUST_DIRECTION_OUTBOUND)) {
		DBG_WARNING("Trusted domain %s is not an outbound trust.\n",
			    domain);
		TALLOC_FREE(tmp_ctx);
		return false;
	}

	trust_type = ldb_msg_find_attr_as_int(msg, "trustType", 0);
	if (trust_type == LSA_TRUST_TYPE_MIT) {
		DBG_WARNING("Trusted domain %s is not an AD trust "
			    "(trustType == LSA_TRUST_TYPE_MIT).\n", domain);
		TALLOC_FREE(tmp_ctx);
		return false;
	}

	password_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
	if (password_val == NULL) {
		DEBUG(2, ("Failed to get trusted domain password for %s, "
			  "attribute trustAuthOutgoing not returned.\n", domain));
		TALLOC_FREE(tmp_ctx);
		return false;
	}

	ndr_err = ndr_pull_struct_blob(password_val, tmp_ctx, &password_blob,
				(ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		DEBUG(0, ("Failed to get trusted domain password for %s, "
			  "attribute trustAuthOutgoing could not be parsed %s.\n",
			  domain,
			  ndr_map_error2string(ndr_err)));
		TALLOC_FREE(tmp_ctx);
		return false;
	}

	auth_array = &password_blob.current;

	for (i=0; i < auth_array->count; i++) {
		if (auth_array->array[i].AuthType == TRUST_AUTH_TYPE_CLEAR) {
			break;
		}
	}

	if (i == auth_array->count) {
		DEBUG(0, ("Trusted domain %s does not have a "
			  "clear-text password stored\n",
			  domain));
		TALLOC_FREE(tmp_ctx);
		return false;
	}

	password_utf16 = data_blob_const(auth_array->array[i].AuthInfo.clear.password,
					 auth_array->array[i].AuthInfo.clear.size);

	/*
	 * In the future, make this function return a
	 * cli_credentials that can store a MD4 hash with cli_credential_set_nt_hash()
	 * but for now convert to UTF8 and fail if the string can not be converted.
	 *
	 * We can't safely convert the random strings windows uses into
	 * utf8.
	 */
	if (!convert_string_talloc(tmp_ctx,
				   CH_UTF16MUNGED, CH_UTF8,
				   password_utf16.data, password_utf16.length,
				   (void *)&password_talloc,
				   &password_len)) {
		DEBUG(0, ("FIXME: Could not convert password for trusted domain %s"
			  " to UTF8. This may be a password set from Windows.\n",
			  domain));
		TALLOC_FREE(tmp_ctx);
		return false;
	}
	*pwd = SMB_STRNDUP(password_talloc, password_len);
	if (pass_last_set_time) {
		*pass_last_set_time = nt_time_to_unix(auth_array->array[i].LastUpdateTime);
	}

	if (sid != NULL) {
		sid_copy(sid, domain_sid);
	}

	TALLOC_FREE(tmp_ctx);
	return true;
}
static bool pdb_samba_dsdb_get_trusteddom_pw(struct pdb_methods *m,
				      const char *domain, char** pwd,
				      struct dom_sid *sid,
				      time_t *pass_last_set_time)
{
	struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
		m->private_data, struct pdb_samba_dsdb_state);
	TALLOC_CTX *tmp_ctx = talloc_stackframe();
	const char * const attrs[] = {
		"securityIdentifier",
		"flatName",
		"trustPartner",
		"trustAuthOutgoing",
		"whenCreated",
		"msDS-SupportedEncryptionTypes",
		"trustAttributes",
		"trustDirection",
		"trustType",
		NULL
	};
	struct ldb_message *msg;
	const struct ldb_val *password_val;
	int trust_direction_flags;
	int trust_type;
	int i;
	DATA_BLOB password_utf16;
	struct trustAuthInOutBlob password_blob;
	struct AuthenticationInformationArray *auth_array;
	char *password_talloc;
	size_t password_len;
	enum ndr_err_code ndr_err;
	NTSTATUS status;
	const char *netbios_domain = NULL;
	const struct dom_sid *domain_sid = NULL;

	status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
				       attrs, tmp_ctx, &msg);
	if (!NT_STATUS_IS_OK(status)) {
		 
		DEBUG(2, ("Failed to get trusted domain password for %s - %s.  "
			  "It may not be a trusted domain.\n", domain,
			  nt_errstr(status)));
		TALLOC_FREE(tmp_ctx);
		return false;
	}

	netbios_domain = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
	if (netbios_domain == NULL) {
		DEBUG(2, ("Trusted domain %s has to flatName defined.\n",
			  domain));
		TALLOC_FREE(tmp_ctx);
		return false;
	}

	domain_sid = samdb_result_dom_sid(tmp_ctx, msg, "securityIdentifier");
	if (domain_sid == NULL) {
		DEBUG(2, ("Trusted domain %s has no securityIdentifier defined.\n",
			  domain));
		TALLOC_FREE(tmp_ctx);
		return false;
	}

	trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
	if (!(trust_direction_flags & LSA_TRUST_DIRECTION_OUTBOUND)) {
		DBG_WARNING("Trusted domain %s is not an outbound trust.\n",
			    domain);
		TALLOC_FREE(tmp_ctx);
		return false;
	}

	trust_type = ldb_msg_find_attr_as_int(msg, "trustType", 0);
	if (trust_type == LSA_TRUST_TYPE_MIT) {
		DBG_WARNING("Trusted domain %s is not an AD trust "
			    "(trustType == LSA_TRUST_TYPE_MIT).\n", domain);
		TALLOC_FREE(tmp_ctx);
		return false;
	}

	password_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
	if (password_val == NULL) {
		DEBUG(2, ("Failed to get trusted domain password for %s, "
			  "attribute trustAuthOutgoing not returned.\n", domain));
		TALLOC_FREE(tmp_ctx);
		return false;
	}

	ndr_err = ndr_pull_struct_blob(password_val, tmp_ctx, &password_blob,
				(ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		DEBUG(0, ("Failed to get trusted domain password for %s, "
			  "attribute trustAuthOutgoing could not be parsed %s.\n",
			  domain,
			  ndr_map_error2string(ndr_err)));
		TALLOC_FREE(tmp_ctx);
		return false;
	}

	auth_array = &password_blob.current;

	for (i=0; i < auth_array->count; i++) {
		if (auth_array->array[i].AuthType == TRUST_AUTH_TYPE_CLEAR) {
			break;
		}
	}

	if (i == auth_array->count) {
		DEBUG(0, ("Trusted domain %s does not have a "
			  "clear-text password stored\n",
			  domain));
		TALLOC_FREE(tmp_ctx);
		return false;
	}

	password_utf16 = data_blob_const(auth_array->array[i].AuthInfo.clear.password,
					 auth_array->array[i].AuthInfo.clear.size);

	 
	if (!convert_string_talloc(tmp_ctx,
				   CH_UTF16MUNGED, CH_UTF8,
				   password_utf16.data, password_utf16.length,
				   (void *)&password_talloc,
				   &password_len)) {
		DEBUG(0, ("FIXME: Could not convert password for trusted domain %s"
			  " to UTF8. This may be a password set from Windows.\n",
			  domain));
		TALLOC_FREE(tmp_ctx);
		return false;
	}
	*pwd = SMB_STRNDUP(password_talloc, password_len);
	if (pass_last_set_time) {
		*pass_last_set_time = nt_time_to_unix(auth_array->array[i].LastUpdateTime);
	}

	if (sid != NULL) {
		sid_copy(sid, domain_sid);
	}

	TALLOC_FREE(tmp_ctx);
	return true;
}