r11528: Separate finding dcs from initializing a domain. Makes it easier to possibly
authorVolker Lendecke <vlendec@samba.org>
Sat, 5 Nov 2005 23:46:57 +0000 (23:46 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:45:49 +0000 (13:45 -0500)
support cldap and other stuff in the future.

This temporarily disables wbinfo -t, but that will come back soon.

Try an ldap bind using gss-spnego. This got me krb5 binds against "our" w2k3
and a trusted w2k, although with some memleaks from krb5 and a BAD_OPTION
tgs-rep error.

Volker

12 files changed:
source/libcli/ldap/ldap_client.h
source/winbind/config.mk
source/winbind/wb_async_helpers.c
source/winbind/wb_async_helpers.h
source/winbind/wb_dom_info.c [new file with mode: 0644]
source/winbind/wb_dom_info_trusted.c [new file with mode: 0644]
source/winbind/wb_init_domain.c
source/winbind/wb_samba3_cmd.c
source/winbind/wb_samba3_protocol.c
source/winbind/wb_server.c
source/winbind/wb_server.h
source/winbind/wb_sid2domain.c

index b61f765b4089bcf17255846e4b75be68bf711a53..38e043da1f6e85ca3594b0204d508dc1a7f28a4c 100644 (file)
@@ -21,6 +21,8 @@
 */
 
 
+#include "libcli/ldap/ldap.h"
+
 enum ldap_request_state {LDAP_REQUEST_SEND, LDAP_REQUEST_PENDING, LDAP_REQUEST_DONE};
 
 /* this is the handle that the caller gets when an async ldap message
index 6ed4f51cfc2794e229ce065000539a6b240eea55..d940a4daf138a536f768fde1277ef1cf2da85a5f 100644 (file)
@@ -10,6 +10,8 @@ INIT_OBJ_FILES = \
                wb_samba3_protocol.o \
                wb_samba3_cmd.o \
                wb_init_domain.o \
+               wb_dom_info.o \
+               wb_dom_info_trusted.o \
                wb_sid2domain.o \
                wb_connect_lsa.o \
                wb_connect_sam.o \
index f00c0725b4443be786eff09eadf527d0376d8956..915638abb726a45dc706ab6ac2c9a914259956fc 100644 (file)
@@ -666,6 +666,8 @@ NTSTATUS wb_lsa_lookupnames(TALLOC_CTX *mem_ctx,
        return wb_lsa_lookupnames_recv(c, mem_ctx, sids);
 }
 
+#if 0
+
 struct cmd_checkmachacc_state {
        struct composite_context *ctx;
        struct wbsrv_call *call;
@@ -730,6 +732,7 @@ NTSTATUS wb_cmd_checkmachacc(struct wbsrv_call *call)
        struct composite_context *c = wb_cmd_checkmachacc_send(call);
        return wb_cmd_checkmachacc_recv(c);
 }
+#endif
 
 struct samr_getuserdomgroups_state {
        struct composite_context *ctx;
index 413747090c3d9b6619de6746e262bd8a4f2b5072..532cd9730ceb4cd07e4e24d77ccd89fb4ed70a77 100644 (file)
@@ -34,7 +34,3 @@ struct wb_sid_object {
        const char *name;
 };
 
-struct wb_dom_info {
-       const char *name;
-       const struct dom_sid *sid;
-};
diff --git a/source/winbind/wb_dom_info.c b/source/winbind/wb_dom_info.c
new file mode 100644 (file)
index 0000000..5be28cc
--- /dev/null
@@ -0,0 +1,166 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   Get a struct wb_dom_info for a domain using DNS, netbios, possibly cldap
+   etc.
+
+   Copyright (C) Volker Lendecke 2005
+   
+   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
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   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.
+*/
+
+#include "includes.h"
+#include "libcli/composite/composite.h"
+#include "libcli/smb_composite/smb_composite.h"
+#include "winbind/wb_async_helpers.h"
+#include "winbind/wb_server.h"
+#include "smbd/service_stream.h"
+#include "smbd/service_task.h"
+#include "librpc/gen_ndr/nbt.h"
+#include "librpc/gen_ndr/ndr_irpc.h"
+#include "librpc/gen_ndr/samr.h"
+#include "lib/messaging/irpc.h"
+
+struct get_dom_info_state {
+       struct composite_context *ctx;
+       struct wbsrv_service *service;
+       struct nbtd_getdcname r;
+       struct wb_dom_info *info;
+};
+
+static void get_dom_info_recv_addrs(struct composite_context *ctx);
+static void get_dom_info_recv_dcname(struct irpc_request *ireq);
+
+struct composite_context *wb_get_dom_info_send(TALLOC_CTX *mem_ctx,
+                                              struct wbsrv_service *service,
+                                              const char *domain_name,
+                                              const struct dom_sid *sid)
+{
+       struct composite_context *result, *ctx;
+       struct get_dom_info_state *state;
+       struct nbt_name name;
+
+       result = talloc(mem_ctx, struct composite_context);
+       if (result == NULL) goto failed;
+       result->state = COMPOSITE_STATE_IN_PROGRESS;
+       result->async.fn = NULL;
+       result->event_ctx = service->task->event_ctx;
+
+       state = talloc(result, struct get_dom_info_state);
+       if (state == NULL) goto failed;
+       state->ctx = result;
+       result->private_data = state;
+
+       state->service = service;
+
+       state->info = talloc_zero(state, struct wb_dom_info);
+       if (state->info == NULL) goto failed;
+
+       state->info->name = talloc_strdup(state->info, domain_name);
+       if (state->info->name == NULL) goto failed;
+       state->info->sid = dom_sid_dup(state->info, sid);
+       if (state->info->sid == NULL) goto failed;
+
+       make_nbt_name(&name, state->info->name, NBT_NAME_LOGON);
+
+       ctx = resolve_name_send(&name, result->event_ctx,
+                               lp_name_resolve_order());
+       if (ctx == NULL) goto failed;
+
+       ctx->async.fn = get_dom_info_recv_addrs;
+       ctx->async.private_data = state;
+       return result;
+
+ failed:
+       talloc_free(result);
+       return NULL;
+}
+
+static void get_dom_info_recv_addrs(struct composite_context *ctx)
+{
+       struct get_dom_info_state *state =
+               talloc_get_type(ctx->async.private_data,
+                               struct get_dom_info_state);
+       uint32_t *nbt_servers;
+       struct irpc_request *ireq;
+
+       state->ctx->status = resolve_name_recv(ctx, state->info,
+                                              &state->info->dc_address);
+       if (!composite_is_ok(state->ctx)) return;
+
+       nbt_servers = irpc_servers_byname(state->service->task->msg_ctx,
+                                         "nbt_server");
+       if ((nbt_servers == NULL) || (nbt_servers[0] == 0)) {
+               composite_error(state->ctx, NT_STATUS_NO_LOGON_SERVERS);
+               return;
+       }
+
+       state->r.in.domainname = state->info->name;
+       state->r.in.ip_address = state->info->dc_address;
+       state->r.in.my_computername = lp_netbios_name();
+       state->r.in.my_accountname = talloc_asprintf(state, "%s$",
+                                                    lp_netbios_name());
+       if (composite_nomem(state->r.in.my_accountname, state->ctx)) return;
+       state->r.in.account_control = ACB_WSTRUST;
+       state->r.in.domain_sid = dom_sid_dup(state, state->info->sid);
+       if (composite_nomem(state->r.in.domain_sid, state->ctx)) return;
+
+       ireq = irpc_call_send(state->service->task->msg_ctx, nbt_servers[0],
+                             &dcerpc_table_irpc, DCERPC_NBTD_GETDCNAME,
+                             &state->r, state);
+       composite_continue_irpc(state->ctx, ireq, get_dom_info_recv_dcname,
+                               state);
+}
+
+static void get_dom_info_recv_dcname(struct irpc_request *ireq)
+{
+       struct get_dom_info_state *state =
+               talloc_get_type(ireq->async.private,
+                               struct get_dom_info_state);
+
+
+       state->ctx->status = irpc_call_recv(ireq);
+       talloc_free(ireq);
+       if (!composite_is_ok(state->ctx)) return;
+
+       state->info->dc_name = talloc_steal(state->info, state->r.out.dcname);
+       composite_done(state->ctx);
+}
+
+NTSTATUS wb_get_dom_info_recv(struct composite_context *ctx,
+                             TALLOC_CTX *mem_ctx,
+                             struct wb_dom_info **result)
+{
+       NTSTATUS status = composite_wait(ctx);
+       if (NT_STATUS_IS_OK(status)) {
+               struct get_dom_info_state *state =
+                       talloc_get_type(ctx->private_data,
+                                       struct get_dom_info_state);
+               *result = talloc_steal(mem_ctx, state->info);
+       }
+       talloc_free(ctx);
+       return status;
+}
+
+NTSTATUS wb_get_dom_info(TALLOC_CTX *mem_ctx,
+                        struct wbsrv_service *service,
+                        const char *domain_name,
+                        const struct dom_sid *sid,
+                        struct wb_dom_info **result)
+{
+       struct composite_context *ctx =
+               wb_get_dom_info_send(mem_ctx, service, domain_name, sid);
+       return wb_get_dom_info_recv(ctx, mem_ctx, result);
+}
diff --git a/source/winbind/wb_dom_info_trusted.c b/source/winbind/wb_dom_info_trusted.c
new file mode 100644 (file)
index 0000000..ce9e5b9
--- /dev/null
@@ -0,0 +1,240 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   Get a struct wb_dom_info for a trusted domain, relying on "our" DC.
+
+   Copyright (C) Volker Lendecke 2005
+   
+   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
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   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.
+*/
+
+#include "includes.h"
+#include "libcli/composite/composite.h"
+#include "libcli/smb_composite/smb_composite.h"
+#include "winbind/wb_async_helpers.h"
+#include "winbind/wb_server.h"
+#include "smbd/service_stream.h"
+#include "smbd/service_task.h"
+#include "librpc/gen_ndr/nbt.h"
+#include "librpc/gen_ndr/ndr_netlogon.h"
+
+struct trusted_dom_info_state {
+       struct composite_context *ctx;
+       struct wbsrv_service *service;
+       struct wbsrv_domain *my_domain;
+
+       struct netr_DsRGetDCName d;
+       struct netr_GetAnyDCName g;
+
+       struct wb_dom_info *info;
+};
+
+static void trusted_dom_info_recv_domain(struct composite_context *ctx);
+static void trusted_dom_info_recv_dsr(struct rpc_request *req);
+static void trusted_dom_info_recv_dcname(struct rpc_request *req);
+static void trusted_dom_info_recv_dcaddr(struct composite_context *ctx);
+
+struct composite_context *wb_trusted_dom_info_send(TALLOC_CTX *mem_ctx,
+                                                  struct wbsrv_service *service,
+                                                  const char *domain_name,
+                                                  const struct dom_sid *sid)
+{
+       struct composite_context *result, *ctx;
+       struct trusted_dom_info_state *state;
+
+       result = talloc(mem_ctx, struct composite_context);
+       if (result == NULL) goto failed;
+       result->state = COMPOSITE_STATE_IN_PROGRESS;
+       result->async.fn = NULL;
+       result->event_ctx = service->task->event_ctx;
+
+       state = talloc(result, struct trusted_dom_info_state);
+       if (state == NULL) goto failed;
+       state->ctx = result;
+       result->private_data = state;
+
+       state->info = talloc_zero(state, struct wb_dom_info);
+       if (state->info == NULL) goto failed;
+
+       state->service = service;
+
+       state->info->sid = dom_sid_dup(state->info, sid);
+       if (state->info->sid == NULL) goto failed;
+
+       state->info->name = talloc_strdup(state->info, domain_name);
+       if (state->info->name == NULL) goto failed;
+
+       ctx = wb_sid2domain_send(state, service, service->primary_sid);
+       if (ctx == NULL) goto failed;
+
+       ctx->async.fn = trusted_dom_info_recv_domain;
+       ctx->async.private_data = state;
+       return result;
+
+ failed:
+       talloc_free(result);
+       return NULL;
+}
+
+static void trusted_dom_info_recv_domain(struct composite_context *ctx)
+{
+       struct trusted_dom_info_state *state =
+               talloc_get_type(ctx->async.private_data,
+                               struct trusted_dom_info_state);
+       struct rpc_request *req;
+
+       state->ctx->status = wb_sid2domain_recv(ctx, &state->my_domain);
+       if (!composite_is_ok(state->ctx)) return;
+
+       state->d.in.server_unc =
+               talloc_asprintf(state, "\\\\%s",
+                               state->my_domain->info->dc_name);
+       if (composite_nomem(state->d.in.server_unc,
+                           state->ctx)) return;
+
+       state->d.in.domain_name = state->info->name;
+       state->d.in.domain_guid = NULL;
+       state->d.in.site_guid = NULL;
+       state->d.in.flags = 0x40000000;
+
+       req = dcerpc_netr_DsRGetDCName_send(state->my_domain->netlogon_pipe,
+                                           state, &state->d);
+       composite_continue_rpc(state->ctx, req, trusted_dom_info_recv_dsr,
+                              state);
+}
+
+/*
+ * dcerpc_netr_DsRGetDCName has replied
+ */
+
+static void trusted_dom_info_recv_dsr(struct rpc_request *req)
+{
+       struct trusted_dom_info_state *state =
+               talloc_get_type(req->async.private,
+                               struct trusted_dom_info_state);
+
+       state->ctx->status = dcerpc_ndr_request_recv(req);
+       if (!NT_STATUS_IS_OK(state->ctx->status)) {
+               DEBUG(9, ("dcerpc_ndr_request_recv returned %s\n",
+                         nt_errstr(state->ctx->status)));
+               goto fallback;
+       }
+
+       state->ctx->status =
+               werror_to_ntstatus(state->d.out.result);
+       if (!NT_STATUS_IS_OK(state->ctx->status)) {
+               DEBUG(9, ("dsrgetdcname returned %s\n",
+                         nt_errstr(state->ctx->status)));
+               goto fallback;
+       }
+
+       /* Hey, that was easy! */
+
+       state->info->dc_name = talloc_steal(state->info,
+                                           state->d.out.info->dc_unc);
+       if (*state->info->dc_name == '\\') state->info->dc_name++;
+       if (*state->info->dc_name == '\\') state->info->dc_name++;
+
+       state->info->dc_address = talloc_steal(state->info,
+                                              state->d.out.info->dc_address);
+       if (*state->info->dc_address == '\\') state->info->dc_address++;
+       if (*state->info->dc_address == '\\') state->info->dc_address++;
+
+       state->info->dns_name = talloc_steal(state->info,
+                                            state->d.out.info->domain_name);
+
+       composite_done(state->ctx);
+       return;
+
+ fallback:
+
+       state->g.in.logon_server = talloc_asprintf(
+               state, "\\\\%s",
+               dcerpc_server_name(state->my_domain->netlogon_pipe));
+       state->g.in.domainname = state->info->name;
+
+       req = dcerpc_netr_GetAnyDCName_send(state->my_domain->netlogon_pipe,
+                                           state, &state->g);
+       if (composite_nomem(req, state->ctx)) return;
+
+       composite_continue_rpc(state->ctx, req, trusted_dom_info_recv_dcname,
+                              state);
+}
+
+static void trusted_dom_info_recv_dcname(struct rpc_request *req)
+{
+       struct trusted_dom_info_state *state =
+               talloc_get_type(req->async.private,
+                               struct trusted_dom_info_state);
+       struct composite_context *ctx;
+       struct nbt_name name;
+
+       state->ctx->status = dcerpc_ndr_request_recv(req);
+       if (!composite_is_ok(state->ctx)) return;
+       state->ctx->status = werror_to_ntstatus(state->g.out.result);
+       if (!composite_is_ok(state->ctx)) return;
+
+       state->info->dc_name = talloc_steal(state->info,
+                                           state->g.out.dcname);
+
+       if (*state->info->dc_name == '\\') state->info->dc_name++;
+       if (*state->info->dc_name == '\\') state->info->dc_name++;
+       
+       make_nbt_name(&name, state->info->dc_name, 0x20);
+       ctx = resolve_name_send(&name, state->service->task->event_ctx,
+                               lp_name_resolve_order());
+
+       composite_continue(state->ctx, ctx, trusted_dom_info_recv_dcaddr,
+                          state);
+}
+
+static void trusted_dom_info_recv_dcaddr(struct composite_context *ctx)
+{
+       struct trusted_dom_info_state *state =
+               talloc_get_type(ctx->async.private_data,
+                               struct trusted_dom_info_state);
+
+       state->ctx->status = resolve_name_recv(ctx, state->info,
+                                              &state->info->dc_address);
+       if (!composite_is_ok(state->ctx)) return;
+
+       composite_done(state->ctx);
+}
+
+NTSTATUS wb_trusted_dom_info_recv(struct composite_context *ctx,
+                                 TALLOC_CTX *mem_ctx,
+                                 struct wb_dom_info **result)
+{
+       NTSTATUS status = composite_wait(ctx);
+       if (NT_STATUS_IS_OK(status)) {
+               struct trusted_dom_info_state *state =
+                       talloc_get_type(ctx->private_data,
+                                       struct trusted_dom_info_state);
+               *result = talloc_steal(mem_ctx, state->info);
+       }
+       talloc_free(ctx);
+       return status;
+}
+
+NTSTATUS wb_trusted_dom_info(TALLOC_CTX *mem_ctx,
+                            struct wbsrv_service *service,
+                            const char *domain_name,
+                            const struct dom_sid *sid,
+                            struct wb_dom_info **result)
+{
+       struct composite_context *ctx =
+               wb_trusted_dom_info_send(mem_ctx, service, domain_name, sid);
+       return wb_trusted_dom_info_recv(ctx, mem_ctx, result);
+}
index c5082a9a3ee8b3b7146c6bcd9de969605d43f157..21ea668043bb572b9976682d2e10f98083886365 100644 (file)
@@ -39,6 +39,8 @@
 #include "librpc/gen_ndr/ndr_lsa.h"
 #include "libcli/auth/credentials.h"
 
+#include "libcli/ldap/ldap_client.h"
+
 
 /*
  * Initialize a domain:
@@ -67,29 +69,11 @@ struct init_domain_state {
        struct wbsrv_domain *domain;
        struct wbsrv_service *service;
 
-       int num_dcs;
-       struct nbt_dc_name *dcs;
-       const char *dcaddr;
-
        struct smb_composite_connect conn;
 
-       struct dcerpc_pipe *auth2_pipe;
-       struct dcerpc_pipe *netlogon_pipe;
-
-       struct dcerpc_pipe *lsa_pipe;
-       struct policy_handle *lsa_policy;
-
-       struct dcerpc_pipe *samr_pipe;
-       struct policy_handle *samr_handle;
-       struct policy_handle *domain_handle;
-
-       struct ldap_connection *ldap_conn;
-
        struct lsa_QueryInfoPolicy queryinfo;
 };
 
-static void init_domain_recv_dcs(struct composite_context *ctx);
-static void init_domain_recv_dcip(struct composite_context *ctx);
 static void init_domain_recv_tree(struct composite_context *ctx);
 static void init_domain_recv_netlogoncreds(struct composite_context *ctx);
 static void init_domain_recv_netlogonpipe(struct composite_context *ctx);
@@ -98,13 +82,14 @@ static void init_domain_recv_queryinfo(struct rpc_request *req);
 static void init_domain_recv_ldapconn(struct composite_context *ctx);
 static void init_domain_recv_samr(struct composite_context *ctx);
 
-struct composite_context *wb_init_domain_send(struct wbsrv_service *service,
-                                             struct wbsrv_domain *domain)
+struct composite_context *wb_init_domain_send(TALLOC_CTX *mem_ctx,
+                                             struct wbsrv_service *service,
+                                             struct wb_dom_info *dom_info)
 {
        struct composite_context *result, *ctx;
        struct init_domain_state *state;
 
-       result = talloc(domain, struct composite_context);
+       result = talloc(mem_ctx, struct composite_context);
        if (result == NULL) goto failed;
        result->state = COMPOSITE_STATE_IN_PROGRESS;
        result->async.fn = NULL;
@@ -116,112 +101,43 @@ struct composite_context *wb_init_domain_send(struct wbsrv_service *service,
        result->private_data = state;
 
        state->service = service;
-       state->domain = domain;
-
-       if (domain->dcname != NULL) {
-               struct nbt_name name;
-               make_nbt_name(&name, domain->dcname, 0x20);
-               ctx = resolve_name_send(&name, result->event_ctx,
-                                       lp_name_resolve_order());
-               if (ctx == NULL) goto failed;
-               ctx->async.fn = init_domain_recv_dcip;
-               ctx->async.private_data = state;
-               return result;
-       }
 
-       if (state->domain->schannel_creds != NULL) {
-               talloc_free(state->domain->schannel_creds);
-       }
+       state->domain = talloc(state, struct wbsrv_domain);
+       if (state->domain == NULL) goto failed;
+
+       state->domain->info = talloc_reference(state->domain, dom_info);
+       if (state->domain->info == NULL) goto failed;
 
        state->domain->schannel_creds = cli_credentials_init(state->domain);
        if (state->domain->schannel_creds == NULL) goto failed;
+
        cli_credentials_set_conf(state->domain->schannel_creds);
        state->ctx->status =
                cli_credentials_set_machine_account(state->domain->
                                                    schannel_creds);
        if (!NT_STATUS_IS_OK(state->ctx->status)) goto failed;
 
-       ctx = wb_finddcs_send(state, domain->name, domain->sid,
-                             result->event_ctx, service->task->msg_ctx);
-       if (ctx == NULL) goto failed;
-
-       ctx->async.fn = init_domain_recv_dcs;
-       ctx->async.private_data = state;
-       return result;
-
- failed:
-       talloc_free(result);
-       return NULL;
-}
-
-static void init_domain_recv_dcs(struct composite_context *ctx)
-{
-       struct init_domain_state *state =
-               talloc_get_type(ctx->async.private_data,
-                               struct init_domain_state);
-
-       state->ctx->status = wb_finddcs_recv(ctx, state, &state->num_dcs,
-                                            &state->dcs);
-       if (!composite_is_ok(state->ctx)) return;
-
-       if (state->num_dcs < 1) {
-               composite_error(state->ctx, NT_STATUS_NO_LOGON_SERVERS);
-               return;
-       }
-
-       state->dcaddr = state->dcs[0].address;
-
-       state->domain->dcname = talloc_reference(state->domain,
-                                                state->dcs[0].name);
-       if (composite_nomem(state->domain->dcname, state->ctx)) return;
-
-       state->conn.in.dest_host = state->dcs[0].address;
+       state->conn.in.dest_host = dom_info->dc_address;
        state->conn.in.port = 0;
-       state->conn.in.called_name = state->dcs[0].name;
+       state->conn.in.called_name = dom_info->dc_name;
        state->conn.in.service = "IPC$";
        state->conn.in.service_type = "IPC";
-       state->conn.in.workgroup = state->domain->name;
-
+       state->conn.in.workgroup = dom_info->name;
        state->conn.in.credentials = state->domain->schannel_creds;
 
-       if (state->conn.in.credentials == NULL) {
-               state->conn.in.credentials = cli_credentials_init(state);
-               if (composite_nomem(state->conn.in.credentials, state->ctx)) {
-                       return;
-               }
-               cli_credentials_set_conf(state->conn.in.credentials);
-               cli_credentials_set_anonymous(state->conn.in.credentials);
-       }
-               
        state->conn.in.fallback_to_anonymous = True;
 
        ctx = smb_composite_connect_send(&state->conn, state->domain,
-                                        state->ctx->event_ctx);
-       composite_continue(state->ctx, ctx, init_domain_recv_tree, state);
-}
-
-static void init_domain_recv_dcip(struct composite_context *ctx)
-{
-       struct init_domain_state *state =
-               talloc_get_type(ctx->async.private_data,
-                               struct init_domain_state);
-
-       state->ctx->status = resolve_name_recv(ctx, state, &state->dcaddr);
-       if (!composite_is_ok(state->ctx)) return;
-
-       state->conn.in.dest_host = state->dcaddr;
-       state->conn.in.port = 0;
-       state->conn.in.called_name = state->domain->dcname;
-       state->conn.in.service = "IPC$";
-       state->conn.in.service_type = "IPC";
-       state->conn.in.workgroup = state->domain->name;
-       state->conn.in.credentials = state->domain->schannel_creds;
+                                        result->event_ctx);
+       if (ctx == NULL) goto failed;
 
-       state->conn.in.fallback_to_anonymous = True;
+       ctx->async.fn = init_domain_recv_tree;
+       ctx->async.private_data = state;
+       return result;
 
-       ctx = smb_composite_connect_send(&state->conn, state->domain,
-                                        state->ctx->event_ctx);
-       composite_continue(state->ctx, ctx, init_domain_recv_tree, state);
+ failed:
+       talloc_free(result);
+       return NULL;
 }
 
 static void init_domain_recv_tree(struct composite_context *ctx)
@@ -235,7 +151,7 @@ static void init_domain_recv_tree(struct composite_context *ctx)
        if ((state->domain->schannel_creds != NULL) &&
            (!cli_credentials_is_anonymous(state->domain->schannel_creds)) &&
            ((lp_server_role() == ROLE_DOMAIN_MEMBER) &&
-            (dom_sid_equal(state->domain->sid,
+            (dom_sid_equal(state->domain->info->sid,
                            state->service->primary_sid)))) {
                ctx = wb_get_schannel_creds_send(state,
                                                 state->domain->schannel_creds,
@@ -255,37 +171,36 @@ static void init_domain_recv_netlogoncreds(struct composite_context *ctx)
        struct init_domain_state *state =
                talloc_get_type(ctx->async.private_data,
                                struct init_domain_state);
+       struct dcerpc_pipe *auth2_pipe;
        struct smbcli_tree *tree = NULL;
 
-       state->ctx->status = wb_get_schannel_creds_recv(ctx, state,
-                                                       &state->auth2_pipe);
+       state->ctx->status =
+               wb_get_schannel_creds_recv(ctx, state, &auth2_pipe);
        if (!composite_is_ok(state->ctx)) return;
 
        if (!lp_winbind_sealed_pipes()) {
-               state->netlogon_pipe = talloc_reference(state,
-                                                       state->auth2_pipe);
+               state->domain->netlogon_pipe = talloc_reference(state->domain,
+                                                               auth2_pipe);
                ctx = wb_connect_lsa_send(state, state->conn.out.tree, NULL);
                composite_continue(state->ctx, ctx, init_domain_recv_lsa,
                                   state);
                return;
        }
 
-       state->netlogon_pipe = dcerpc_pipe_init(state, state->ctx->event_ctx);
-       if (composite_nomem(state->netlogon_pipe, state->ctx)) return;
-
-       if (state->auth2_pipe != NULL) {
-               tree = dcerpc_smb_tree(state->auth2_pipe->conn);
-       }
+       state->domain->netlogon_pipe =
+               dcerpc_pipe_init(state->domain, state->ctx->event_ctx);
+       if (composite_nomem(state->domain->netlogon_pipe, state->ctx)) return;
 
+       tree = dcerpc_smb_tree(auth2_pipe->conn);
        if (tree == NULL) {
                composite_error(state->ctx, NT_STATUS_INTERNAL_ERROR);
                return;
        }
 
-       ctx = dcerpc_pipe_open_smb_send(state->netlogon_pipe->conn, tree,
-                                       "\\netlogon");
-       composite_continue(state->ctx, ctx,
-                          init_domain_recv_netlogonpipe, state);
+       ctx = dcerpc_pipe_open_smb_send(state->domain->netlogon_pipe->conn,
+                                       tree, "\\netlogon");
+       composite_continue(state->ctx, ctx, init_domain_recv_netlogonpipe,
+                          state);
 }
 
 static void init_domain_recv_netlogonpipe(struct composite_context *ctx)
@@ -297,9 +212,10 @@ static void init_domain_recv_netlogonpipe(struct composite_context *ctx)
        state->ctx->status = dcerpc_pipe_open_smb_recv(ctx);
        if (!composite_is_ok(state->ctx)) return;
 
-       state->netlogon_pipe->conn->flags |= (DCERPC_SIGN | DCERPC_SEAL);
+       state->domain->netlogon_pipe->conn->flags |=
+               (DCERPC_SIGN | DCERPC_SEAL);
        state->ctx->status =
-               dcerpc_bind_auth_password(state->netlogon_pipe,
+               dcerpc_bind_auth_password(state->domain->netlogon_pipe,
                                          DCERPC_NETLOGON_UUID,
                                          DCERPC_NETLOGON_VERSION, 
                                          state->domain->schannel_creds,
@@ -320,19 +236,19 @@ static void init_domain_recv_lsa(struct composite_context *ctx)
 
        struct rpc_request *req;
 
-       state->ctx->status = wb_connect_lsa_recv(ctx, state,
+       state->ctx->status = wb_connect_lsa_recv(ctx, state->domain,
                                                 &state->domain->lsa_auth_type,
-                                                &state->lsa_pipe,
-                                                &state->lsa_policy);
+                                                &state->domain->lsa_pipe,
+                                                &state->domain->lsa_policy);
        if (!composite_is_ok(state->ctx)) return;
 
        /* Give the tree to the pipes. */
-//     talloc_unlink(state, state->conn.out.tree);
+       talloc_unlink(state, state->conn.out.tree);
 
-       state->queryinfo.in.handle = state->lsa_policy;
+       state->queryinfo.in.handle = state->domain->lsa_policy;
        state->queryinfo.in.level = LSA_POLICY_INFO_ACCOUNT_DOMAIN;
 
-       req = dcerpc_lsa_QueryInfoPolicy_send(state->lsa_pipe, state,
+       req = dcerpc_lsa_QueryInfoPolicy_send(state->domain->lsa_pipe, state,
                                              &state->queryinfo);
        composite_continue_rpc(state->ctx, req,
                               init_domain_recv_queryinfo, state);
@@ -353,31 +269,33 @@ static void init_domain_recv_queryinfo(struct rpc_request *req)
 
        dominfo = &state->queryinfo.out.info->account_domain;
 
-       if (strcasecmp(state->domain->name, dominfo->name.string) != 0) {
+       if (strcasecmp(state->domain->info->name, dominfo->name.string) != 0) {
                DEBUG(2, ("Expected domain name %s, DC %s said %s\n",
-                         state->domain->name,
-                         dcerpc_server_name(state->lsa_pipe),
+                         state->domain->info->name,
+                         dcerpc_server_name(state->domain->lsa_pipe),
                          dominfo->name.string));
                composite_error(state->ctx, NT_STATUS_INVALID_DOMAIN_STATE);
                return;
        }
 
-       if (!dom_sid_equal(state->domain->sid, dominfo->sid)) {
+       if (!dom_sid_equal(state->domain->info->sid, dominfo->sid)) {
                DEBUG(2, ("Expected domain sid %s, DC %s said %s\n",
-                         dom_sid_string(state, state->domain->sid),
-                         dcerpc_server_name(state->lsa_pipe),
+                         dom_sid_string(state, state->domain->info->sid),
+                         dcerpc_server_name(state->domain->lsa_pipe),
                          dom_sid_string(state, dominfo->sid)));
                composite_error(state->ctx, NT_STATUS_INVALID_DOMAIN_STATE);
                return;
        }
 
-       state->ldap_conn = ldap_new_connection(state, state->ctx->event_ctx);
-       composite_nomem(state->ldap_conn, state->ctx);
+       state->domain->ldap_conn =
+               ldap_new_connection(state->domain, state->ctx->event_ctx);
+       composite_nomem(state->domain->ldap_conn, state->ctx);
 
-       ldap_url = talloc_asprintf(state, "ldap://%s/", state->dcaddr);
+       ldap_url = talloc_asprintf(state, "ldap://%s/",
+                                  state->domain->info->dc_address);
        composite_nomem(ldap_url, state->ctx);
 
-       ctx = ldap_connect_send(state->ldap_conn, ldap_url);
+       ctx = ldap_connect_send(state->domain->ldap_conn, ldap_url);
        composite_continue(state->ctx, ctx, init_domain_recv_ldapconn, state);
 }
 
@@ -388,16 +306,25 @@ static void init_domain_recv_ldapconn(struct composite_context *ctx)
                                struct init_domain_state);
 
        state->ctx->status = ldap_connect_recv(ctx);
-       DEBUG(0, ("ldap_connect returned %s\n",
-                 nt_errstr(state->ctx->status)));
+       if (NT_STATUS_IS_OK(state->ctx->status)) {
+               state->domain->ldap_conn->host =
+                       talloc_strdup(state->domain->ldap_conn,
+                                     state->domain->info->dc_name);
+               state->ctx->status =
+                       ldap_bind_sasl(state->domain->ldap_conn,
+                                      state->domain->schannel_creds);
+               DEBUG(0, ("ldap_bind returned %s\n",
+                         nt_errstr(state->ctx->status)));
+       }
 
-       state->samr_pipe = dcerpc_pipe_init(state, state->ctx->event_ctx);
-       if (composite_nomem(state->samr_pipe, state->ctx)) return;
+       state->domain->samr_pipe =
+               dcerpc_pipe_init(state->domain, state->ctx->event_ctx);
+       if (composite_nomem(state->domain->samr_pipe, state->ctx)) return;
 
        ctx = wb_connect_sam_send(state, state->conn.out.tree,
                                  state->domain->lsa_auth_type,
                                  state->domain->schannel_creds,
-                                 state->domain->sid);
+                                 state->domain->info->sid);
        composite_continue(state->ctx, ctx, init_domain_recv_samr, state);
 }
 
@@ -407,61 +334,34 @@ static void init_domain_recv_samr(struct composite_context *ctx)
                talloc_get_type(ctx->async.private_data,
                                struct init_domain_state);
 
-       state->ctx->status = wb_connect_sam_recv(ctx, state, &state->samr_pipe,
-                                                &state->samr_handle,
-                                                &state->domain_handle);
+       state->ctx->status = wb_connect_sam_recv(
+               ctx, state->domain, &state->domain->samr_pipe,
+               &state->domain->samr_handle, &state->domain->domain_handle);
        if (!composite_is_ok(state->ctx)) return;
 
        composite_done(state->ctx);
 }
 
-NTSTATUS wb_init_domain_recv(struct composite_context *c)
+NTSTATUS wb_init_domain_recv(struct composite_context *c,
+                            TALLOC_CTX *mem_ctx,
+                            struct wbsrv_domain **result)
 {
        NTSTATUS status = composite_wait(c);
        if (NT_STATUS_IS_OK(status)) {
                struct init_domain_state *state =
                        talloc_get_type(c->private_data,
                                        struct init_domain_state);
-               struct wbsrv_domain *domain = state->domain;
-
-               talloc_free(domain->netlogon_auth2_pipe);
-               domain->netlogon_auth2_pipe =
-                       talloc_steal(domain, state->auth2_pipe);
-
-               talloc_free(domain->netlogon_pipe);
-               domain->netlogon_pipe =
-                       talloc_steal(domain, state->netlogon_pipe);
-
-               talloc_free(domain->lsa_pipe);
-               domain->lsa_pipe =
-                       talloc_steal(domain, state->lsa_pipe);
-
-               talloc_free(domain->lsa_policy);
-               domain->lsa_policy =
-                       talloc_steal(domain, state->lsa_policy);
-
-               talloc_free(domain->samr_pipe);
-               domain->samr_pipe =
-                       talloc_steal(domain, state->samr_pipe);
-
-               talloc_free(domain->samr_handle);
-               domain->samr_handle =
-                       talloc_steal(domain, state->samr_handle);
-
-               talloc_free(domain->domain_handle);
-               domain->domain_handle =
-                       talloc_steal(domain, state->domain_handle);
-
-               domain->initialized = True;
+               *result = talloc_steal(mem_ctx, state->domain);
        }
        talloc_free(c);
        return status;
 }
 
-NTSTATUS wb_init_domain(struct wbsrv_service *service,
-                       struct wbsrv_domain *domain)
+NTSTATUS wb_init_domain(TALLOC_CTX *mem_ctx, struct wbsrv_service *service,
+                       struct wb_dom_info *dom_info,
+                       struct wbsrv_domain **result)
 {
        struct composite_context *c =
-               wb_init_domain_send(service, domain);
-       return wb_init_domain_recv(c);
+               wb_init_domain_send(mem_ctx, service, dom_info);
+       return wb_init_domain_recv(c, mem_ctx, result);
 }
index a5e7cb722b39a5228d821f46c9b92c97d4133c1f..d7496c2263298119df8c7b4c81e3e2bcd682592d 100644 (file)
@@ -136,6 +136,7 @@ NTSTATUS wbsrv_samba3_ping(struct wbsrv_samba3_call *s3call)
        return NT_STATUS_OK;
 }
 
+#if 0
 /* 
    Validate that we have a working pipe to the domain controller.
    Return any NT error found in the process
@@ -169,6 +170,7 @@ static void checkmachacc_recv_creds(struct composite_context *ctx)
 
        wbsrv_samba3_async_auth_epilogue(status, s3call);
 }
+#endif
 
 /*
   Find the name of a suitable domain controller, by query on the
index f9e4c54ce2102bafc3d56359efd6738a61425899..f9eb7a09d45885a5e5591e8b46499d5e4f5e87f0 100644 (file)
@@ -75,8 +75,10 @@ NTSTATUS wbsrv_samba3_handle_call(struct wbsrv_call *call)
        case WINBINDD_INTERFACE_VERSION:
                return wbsrv_samba3_interface_version(s3call);
 
+#if 0
        case WINBINDD_CHECK_MACHACC:
                return wbsrv_samba3_check_machacc(s3call);
+#endif
 
        case WINBINDD_PING:
                return wbsrv_samba3_ping(s3call);
index d12adfc9d436040bf7a95cf2c20caf952541a981..a66bc0832f14c001a56e3613494e89aa0bcd92ec 100644 (file)
@@ -248,32 +248,6 @@ static const struct wbsrv_protocol_ops wbsrv_samba3_protocol_ops = {
        .push_reply             = wbsrv_samba3_push_reply
 };
 
-static NTSTATUS init_my_domain(TALLOC_CTX *mem_ctx,
-                              struct wbsrv_domain **domain)
-{
-       struct wbsrv_domain *result;
-
-       result = talloc_zero(mem_ctx, struct wbsrv_domain);
-       NT_STATUS_HAVE_NO_MEMORY(result);
-
-       result->name = talloc_strdup(result, lp_workgroup());
-       if (result->name == NULL) {
-               talloc_free(result);
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       result->sid = secrets_get_domain_sid(result, lp_workgroup());
-       if (result->sid == NULL) {
-               talloc_free(result);
-               return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
-       }
-
-       result->initialized = False;
-
-       *domain = result;
-       return NT_STATUS_OK;
-}
-
 /*
   startup the winbind task
 */
@@ -304,16 +278,14 @@ static void winbind_task_init(struct task_server *task)
        if (!service) goto nomem;
        service->task   = task;
 
-       status = init_my_domain(service, &service->domains);
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(0, ("Could not init my domain: %s\n",
-                         nt_errstr(status)));
-               task_server_terminate(task, nt_errstr(status));
+       service->primary_sid = secrets_get_domain_sid(service,
+                                                     lp_workgroup());
+       if (service->primary_sid == NULL) {
+               task_server_terminate(
+                       task, nt_errstr(NT_STATUS_CANT_ACCESS_DOMAIN_INFO));
                return;
        }
 
-       service->primary_sid = talloc_reference(service, service->domains->sid);
-
        /* setup the unprivileged samba3 socket */
        listen_socket = talloc(service, struct wbsrv_listen_socket);
        if (!listen_socket) goto nomem;
index 0407d89371cc6d97504ba92ac71bbf9adebe527e..09afffb0c9ab4b5d27d3932f690e96bda00a5737 100644 (file)
@@ -45,16 +45,20 @@ struct wbsrv_samconn {
        NTSTATUS (*seqnum_recv)(struct composite_context *, uint64_t *);
 };
 
-struct wbsrv_domain {
-       struct wbsrv_domain *next, *prev;
-
-       BOOL initialized;
-
+struct wb_dom_info {
        const char *name;
+       const char *dns_name;
        const struct dom_sid *sid;
-       const char *dcname;
-       const char *dc_dnsname;
+
+       const char *dc_name;
+       const char *dc_dns_name;
        const char *dc_address;
+};
+
+struct wbsrv_domain {
+       struct wbsrv_domain *next, *prev;
+
+       struct wb_dom_info *info;
 
        struct dcerpc_pipe *lsa_pipe;
        struct policy_handle *lsa_policy;
@@ -66,12 +70,8 @@ struct wbsrv_domain {
 
        struct ldap_connection *ldap_conn;
 
-       struct dcerpc_pipe *netlogon_auth2_pipe;
        struct dcerpc_pipe *netlogon_pipe;
        struct cli_credentials *schannel_creds;
-
-       BOOL busy;
-       struct domain_request_state *request_queue;
 };
 
 /* 
index 8940c8e9b7e1382670d0ffb0d1b861a688c3e164..70f8f4c6263c60798325ed15e5f29d2603b132fc 100644 (file)
 #include "winbind/wb_async_helpers.h"
 #include "include/dlinklist.h"
 
-static const char *sam_name(void)
-{
-       if (lp_server_role() == ROLE_STANDALONE) {
-               return lp_netbios_name();
-       }
-       return lp_workgroup();
-}
-
-static struct wbsrv_domain *find_primary_domain(struct wbsrv_service *service)
-{
-       const char *my_domain_name = sam_name();
-       struct wbsrv_domain *domain;
-
-       for (domain = service->domains; domain!=NULL; domain = domain->next) {
-               if (strcasecmp(domain->name, my_domain_name) == 0) {
-                       break;
-               }
-       }
-       return domain;
-}
-
 static struct wbsrv_domain *find_domain_from_sid(struct wbsrv_service *service,
                                                 const struct dom_sid *sid)
 {
        struct wbsrv_domain *domain;
 
        for (domain = service->domains; domain!=NULL; domain = domain->next) {
-               if (dom_sid_equal(domain->sid, sid)) {
+               if (dom_sid_equal(domain->info->sid, sid)) {
                        break;
                }
-               if (dom_sid_in_domain(domain->sid, sid)) {
+               if (dom_sid_in_domain(domain->info->sid, sid)) {
                        break;
                }
        }
@@ -71,22 +50,14 @@ static struct wbsrv_domain *find_domain_from_sid(struct wbsrv_service *service,
 struct sid2domain_state {
        struct composite_context *ctx;
        struct wbsrv_service *service;
-       const struct dom_sid *sid;
-
-       const char *domain_name;
-       const char *dc_name;
-       struct dom_sid *domain_sid;
+       struct dom_sid *sid;
 
-       struct wbsrv_domain *my_domain;
-       struct wbsrv_domain *result;
-
-       struct netr_DsRGetDCName dsr_getdcname;
-       struct netr_GetAnyDCName getdcname;
+       struct wbsrv_domain *domain;
 };
 
+static void sid2domain_recv_dom_info(struct composite_context *ctx);
 static void sid2domain_recv_name(struct composite_context *ctx);
-static void sid2domain_recv_dsr_dcname(struct rpc_request *req);
-static void sid2domain_recv_dcname(struct composite_context *ctx);
+static void sid2domain_recv_trusted_dom_info(struct composite_context *ctx);
 static void sid2domain_recv_init(struct composite_context *ctx);
 
 struct composite_context *wb_sid2domain_send(TALLOC_CTX *mem_ctx,
@@ -111,24 +82,20 @@ struct composite_context *wb_sid2domain_send(TALLOC_CTX *mem_ctx,
        state->sid = dom_sid_dup(state, sid);
        if (state->sid == NULL) goto failed;
 
-       state->result = find_domain_from_sid(service, sid);
-       if (state->result != NULL) {
+       state->domain = find_domain_from_sid(service, sid);
+       if (state->domain != NULL) {
                result->status = NT_STATUS_OK;
-               if (!state->result->initialized) {
-                       ctx = wb_init_domain_send(service, state->result);
-                       if (ctx == NULL) goto failed;
-                       ctx->async.fn = sid2domain_recv_init;
-                       ctx->async.private_data = state;
-                       return result;
-               }
                composite_trigger_done(result);
                return result;
        }
 
-       state->my_domain = find_primary_domain(service);
-       if (state->my_domain == NULL) {
-               result->status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
-               composite_trigger_error(result);
+       if (dom_sid_equal(service->primary_sid, sid) ||
+           dom_sid_in_domain(service->primary_sid, sid)) {
+               ctx = wb_get_dom_info_send(state, service, lp_workgroup(),
+                                          service->primary_sid);
+               if (ctx == NULL) goto failed;
+               ctx->async.fn = sid2domain_recv_dom_info;
+               ctx->async.private_data = state;
                return result;
        }
 
@@ -141,110 +108,62 @@ struct composite_context *wb_sid2domain_send(TALLOC_CTX *mem_ctx,
  failed:
        talloc_free(result);
        return NULL;
+
 }
 
-static void sid2domain_recv_name(struct composite_context *ctx)
+static void sid2domain_recv_dom_info(struct composite_context *ctx)
 {
        struct sid2domain_state *state =
                talloc_get_type(ctx->async.private_data,
                                struct sid2domain_state);
-       struct rpc_request *req;
-       struct wb_sid_object *name;
+       struct wb_dom_info *info;
 
-       state->ctx->status = wb_cmd_lookupsid_recv(ctx, state, &name);
+       state->ctx->status = wb_get_dom_info_recv(ctx, state, &info);
        if (!composite_is_ok(state->ctx)) return;
 
-       if (name->type == SID_NAME_UNKNOWN) {
-               composite_error(state->ctx, NT_STATUS_NO_SUCH_DOMAIN);
-               return;
-       }
+       ctx = wb_init_domain_send(state, state->service, info);
 
-       state->domain_name = name->domain;
-       state->domain_sid = dom_sid_dup(state, state->sid);
-       if (composite_nomem(state->domain_sid, state->ctx)) return;
-
-       if (name->type != SID_NAME_DOMAIN) {
-               state->domain_sid->num_auths -= 1;
-       }
-
-       state->dsr_getdcname.in.server_unc =
-               talloc_asprintf(state, "\\\\%s", state->my_domain->dcname);
-       if (composite_nomem(state->dsr_getdcname.in.server_unc,
-                           state->ctx)) return;
-
-       state->dsr_getdcname.in.domain_name = state->domain_name;
-       state->dsr_getdcname.in.domain_guid = NULL;
-       state->dsr_getdcname.in.site_guid = NULL;
-       state->dsr_getdcname.in.flags = 0x40000000;
-
-       req = dcerpc_netr_DsRGetDCName_send(state->my_domain->netlogon_pipe,
-                                           state, &state->dsr_getdcname);
-       composite_continue_rpc(state->ctx, req, sid2domain_recv_dsr_dcname,
-                              state);
+       composite_continue(state->ctx, ctx, sid2domain_recv_init, state);
 }
 
-static void sid2domain_recv_dsr_dcname(struct rpc_request *req)
+static void sid2domain_recv_name(struct composite_context *ctx)
 {
        struct sid2domain_state *state =
-               talloc_get_type(req->async.private,
+               talloc_get_type(ctx->async.private_data,
                                struct sid2domain_state);
-       struct composite_context *ctx;
+       struct wb_sid_object *name;
 
-       state->ctx->status = dcerpc_ndr_request_recv(req);
-       if (!NT_STATUS_IS_OK(state->ctx->status)) {
-               DEBUG(9, ("dcerpc_ndr_request_recv returned %s\n",
-                         nt_errstr(state->ctx->status)));
-               goto fallback;
-       }
+       state->ctx->status = wb_cmd_lookupsid_recv(ctx, state, &name);
+       if (!composite_is_ok(state->ctx)) return;
 
-       state->ctx->status =
-               werror_to_ntstatus(state->dsr_getdcname.out.result);
-       if (!NT_STATUS_IS_OK(state->ctx->status)) {
-               DEBUG(9, ("dsrgetdcname returned %s\n",
-                         nt_errstr(state->ctx->status)));
-               goto fallback;
+       if (name->type == SID_NAME_UNKNOWN) {
+               composite_error(state->ctx, NT_STATUS_NO_SUCH_DOMAIN);
+               return;
        }
 
-       DEBUG(0, ("unc: %s, addr: %s, addr_type: %d, domain_name: %s, "
-                 "forest_name: %s\n", 
-                 state->dsr_getdcname.out.info->dc_unc, 
-                 state->dsr_getdcname.out.info->dc_address, 
-                 state->dsr_getdcname.out.info->dc_address_type, 
-                 state->dsr_getdcname.out.info->domain_name,
-                 state->dsr_getdcname.out.info->forest_name));
+       if (name->type != SID_NAME_DOMAIN) {
+               state->sid->num_auths -= 1;
+       }
 
- fallback:
+       ctx = wb_trusted_dom_info_send(state, state->service, name->domain,
+                                      state->sid);
 
-       ctx = wb_cmd_getdcname_send(state, state->service, state->domain_name);
-       composite_continue(state->ctx, ctx, sid2domain_recv_dcname, state);
+       composite_continue(state->ctx, ctx, sid2domain_recv_trusted_dom_info,
+                          state);
 }
 
-static void sid2domain_recv_dcname(struct composite_context *ctx)
+static void sid2domain_recv_trusted_dom_info(struct composite_context *ctx)
 {
        struct sid2domain_state *state =
                talloc_get_type(ctx->async.private_data,
                                struct sid2domain_state);
+       struct wb_dom_info *info;
 
-       state->ctx->status = wb_cmd_getdcname_recv(ctx, state,
-                                                  &state->dc_name);
+       state->ctx->status = wb_trusted_dom_info_recv(ctx, state, &info);
        if (!composite_is_ok(state->ctx)) return;
 
-       state->result = talloc_zero(state, struct wbsrv_domain);
-       if (composite_nomem(state->result, state->ctx)) return;
+       ctx = wb_init_domain_send(state, state->service, info);
 
-       state->result->name = talloc_steal(state->result, state->domain_name);
-       state->result->sid = talloc_steal(state->result, state->domain_sid);
-       state->result->dcname = talloc_steal(state->result, state->dc_name);
-
-       state->result->schannel_creds = cli_credentials_init(state->result);
-       if (composite_nomem(state->result->schannel_creds, state->ctx)) return;
-       cli_credentials_set_conf(state->result->schannel_creds);
-       cli_credentials_set_machine_account(state->result->schannel_creds);
-
-       talloc_steal(state->service, state->result);
-       DLIST_ADD(state->service->domains, state->result);
-
-       ctx = wb_init_domain_send(state->service, state->result);
        composite_continue(state->ctx, ctx, sid2domain_recv_init, state);
 }
 
@@ -253,13 +172,25 @@ static void sid2domain_recv_init(struct composite_context *ctx)
        struct sid2domain_state *state =
                talloc_get_type(ctx->async.private_data,
                                struct sid2domain_state);
+       struct wbsrv_domain *existing;
 
-       state->ctx->status = wb_init_domain_recv(ctx);
+       state->ctx->status = wb_init_domain_recv(ctx, state,
+                                                &state->domain);
        if (!composite_is_ok(state->ctx)) {
                DEBUG(10, ("Could not init domain\n"));
                return;
        }
 
+       existing = find_domain_from_sid(state->service, state->sid);
+       if (existing != NULL) {
+               DEBUG(5, ("Initialized domain twice, dropping second one\n"));
+               talloc_free(state->domain);
+               state->domain = existing;
+       }
+
+       talloc_steal(state->service, state->domain);
+       DLIST_ADD(state->service->domains, state->domain);
+
        composite_done(state->ctx);
 }
 
@@ -271,7 +202,7 @@ NTSTATUS wb_sid2domain_recv(struct composite_context *ctx,
                struct sid2domain_state *state =
                        talloc_get_type(ctx->private_data,
                                        struct sid2domain_state);
-               *result = state->result;
+               *result = state->domain;
        }
        talloc_free(ctx);
        return status;