s4-finddc: use NBT lookup for a 1C name if joining a short domain name
authorAndrew Tridgell <tridge@samba.org>
Tue, 14 Sep 2010 10:10:51 +0000 (20:10 +1000)
committerAndrew Tridgell <tridge@samba.org>
Wed, 15 Sep 2010 05:39:36 +0000 (15:39 +1000)
once we get the 1C lookup reply, use a CLDAP query to find the details
for the server

Pair-Programmed-With: Andrew Bartlett <abartlet@samba.org>

source4/libcli/finddc.h
source4/libcli/finddcs_cldap.c
source4/libnet/libnet_lookup.c
source4/libnet/py_net.c
source4/scripting/python/samba/netcmd/join.py
source4/winbind/wb_dom_info.c

index 9e6e2dfe83bb7cf62e73ada97880dc1df3ba1192..3f1caf9ce545196cc54b0aa56f92b99cb732f8d1 100644 (file)
@@ -23,7 +23,7 @@
 
 struct finddcs {
        struct {
-               const char *dns_domain_name;
+               const char *domain_name;
                const char *site_name; /* optional */
                struct dom_sid *domain_sid; /* optional */
                uint32_t minimum_dc_flags; /* DS_SERVER_* */
index 4d721f9d6e382c2447f214a0aa71ecad8fbe614c..949002bd51d1587b93f406389d5552e045198b8f 100644 (file)
@@ -34,7 +34,7 @@
 struct finddcs_cldap_state {
        struct tevent_context *ev;
        struct tevent_req *req;
-       const char *dns_domain_name;
+       const char *domain_name;
        struct dom_sid *domain_sid;
        const char **srv_addresses;
        uint32_t minimum_dc_flags;
@@ -45,6 +45,15 @@ struct finddcs_cldap_state {
 
 static void finddcs_cldap_srv_resolved(struct composite_context *ctx);
 static void finddcs_cldap_netlogon_replied(struct tevent_req *req);
+static bool finddcs_cldap_srv_lookup(struct finddcs_cldap_state *state,
+                                    struct finddcs *io,
+                                    struct resolve_context *resolve_ctx,
+                                    struct tevent_context *event_ctx);
+static bool finddcs_cldap_nbt_lookup(struct finddcs_cldap_state *state,
+                                    struct finddcs *io,
+                                    struct resolve_context *resolve_ctx,
+                                    struct tevent_context *event_ctx);
+static void finddcs_cldap_name_resolved(struct composite_context *ctx);
 
 
 /*
@@ -58,9 +67,6 @@ struct tevent_req *finddcs_cldap_send(TALLOC_CTX *mem_ctx,
 {
        struct finddcs_cldap_state *state;
        struct tevent_req *req;
-       const char *srv_name;
-       struct composite_context *creq;
-       struct nbt_name name;
 
        req = tevent_req_create(mem_ctx, &state, struct finddcs_cldap_state);
        if (req == NULL) {
@@ -70,8 +76,8 @@ struct tevent_req *finddcs_cldap_send(TALLOC_CTX *mem_ctx,
        state->req = req;
        state->ev = event_ctx;
        state->minimum_dc_flags = io->in.minimum_dc_flags;
-       state->dns_domain_name = talloc_strdup(state, io->in.dns_domain_name);
-       if (tevent_req_nomem(state->dns_domain_name, req)) {
+       state->domain_name = talloc_strdup(state, io->in.domain_name);
+       if (tevent_req_nomem(state->domain_name, req)) {
                return tevent_req_post(req, event_ctx);
        }
 
@@ -84,12 +90,37 @@ struct tevent_req *finddcs_cldap_send(TALLOC_CTX *mem_ctx,
                state->domain_sid = NULL;
        }
 
-       /* step1: lookup _ldap._tcp.* */
+       if (strchr(state->domain_name, '.')) {
+               /* looks like a DNS name */
+               if (!finddcs_cldap_srv_lookup(state, io, resolve_ctx, event_ctx)) {
+                       return tevent_req_post(req, event_ctx);
+               }
+       } else {
+               if (!finddcs_cldap_nbt_lookup(state, io, resolve_ctx, event_ctx)) {
+                       return tevent_req_post(req, event_ctx);
+               }
+       }
+
+       return req;
+}
+
+/*
+  start a SRV DNS lookup
+ */
+static bool finddcs_cldap_srv_lookup(struct finddcs_cldap_state *state,
+                                    struct finddcs *io,
+                                    struct resolve_context *resolve_ctx,
+                                    struct tevent_context *event_ctx)
+{
+       const char *srv_name;
+       struct composite_context *creq;
+       struct nbt_name name;
+
        if (io->in.site_name) {
                srv_name = talloc_asprintf(state, "_ldap._tcp.%s._sites.%s",
-                                          io->in.site_name, io->in.dns_domain_name);
+                                          io->in.site_name, io->in.domain_name);
        } else {
-               srv_name = talloc_asprintf(state, "_ldap._tcp.%s", io->in.dns_domain_name);
+               srv_name = talloc_asprintf(state, "_ldap._tcp.%s", io->in.domain_name);
        }
 
        make_nbt_name(&name, srv_name, 0);
@@ -97,15 +128,35 @@ struct tevent_req *finddcs_cldap_send(TALLOC_CTX *mem_ctx,
        creq = resolve_name_ex_send(resolve_ctx, state,
                                    RESOLVE_NAME_FLAG_FORCE_DNS | RESOLVE_NAME_FLAG_DNS_SRV,
                                    0, &name, event_ctx);
-       if (tevent_req_nomem(creq, req)) {
-               return tevent_req_post(req, event_ctx);
+       if (tevent_req_nomem(creq, state->req)) {
+               return false;
        }
        creq->async.fn = finddcs_cldap_srv_resolved;
        creq->async.private_data = state;
 
-       return req;
+       return true;
 }
 
+/*
+  start a NBT name lookup for domain<1C>
+ */
+static bool finddcs_cldap_nbt_lookup(struct finddcs_cldap_state *state,
+                                    struct finddcs *io,
+                                    struct resolve_context *resolve_ctx,
+                                    struct tevent_context *event_ctx)
+{
+       struct composite_context *creq;
+       struct nbt_name name;
+
+       make_nbt_name(&name, state->domain_name, NBT_NAME_LOGON);
+       creq = resolve_name_send(resolve_ctx, state, &name, event_ctx);
+       if (tevent_req_nomem(creq, state->req)) {
+               return false;
+       }
+       creq->async.fn = finddcs_cldap_name_resolved;
+       creq->async.private_data = state;
+       return true;
+}
 
 /*
   fire off a CLDAP query to the next server
@@ -127,7 +178,9 @@ static void finddcs_cldap_next_server(struct finddcs_cldap_state *state)
        state->netlogon->in.dest_address = state->srv_addresses[state->srv_address_index];
        /* we should get the port from the SRV response */
        state->netlogon->in.dest_port = 389;
-       state->netlogon->in.realm = state->dns_domain_name;
+       if (strchr(state->domain_name, '.')) {
+               state->netlogon->in.realm = state->domain_name;
+       }
        if (state->domain_sid) {
                state->netlogon->in.domain_sid = dom_sid_string(state, state->domain_sid);
                if (tevent_req_nomem(state->netlogon->in.domain_sid, state->req)) {
@@ -181,6 +234,38 @@ static void finddcs_cldap_netlogon_replied(struct tevent_req *subreq)
        tevent_req_done(state->req);
 }
 
+/*
+   handle NBT name lookup reply
+ */
+static void finddcs_cldap_name_resolved(struct composite_context *ctx)
+{
+       struct finddcs_cldap_state *state =
+               talloc_get_type(ctx->async.private_data, struct finddcs_cldap_state);
+       const char *address;
+       NTSTATUS status;
+
+       status = resolve_name_recv(ctx, state, &address);
+       if (tevent_req_nterror(state->req, status)) {
+               return;
+       }
+
+       state->srv_addresses = talloc_array(state, const char *, 2);
+       if (tevent_req_nomem(state->srv_addresses, state->req)) {
+               return;
+       }
+       state->srv_addresses[0] = address;
+       state->srv_addresses[1] = NULL;
+
+       state->srv_address_index = 0;
+
+       status = cldap_socket_init(state, state->ev, NULL, NULL, &state->cldap);
+       if (tevent_req_nterror(state->req, status)) {
+               return;
+       }
+
+       finddcs_cldap_next_server(state);
+}
+
 
 /*
  * Having got a DNS SRV answer, fire off the first CLDAP request
index c6af75b4e371e2b12e0d47b5f35a8c5e70aaa20e..3677c2a31e79125e242a4a0194d94226dfd9565b 100644 (file)
@@ -195,7 +195,10 @@ struct tevent_req *libnet_LookupDCs_send(struct libnet_context *ctx,
        struct finddcs finddcs_io;
 
        ZERO_STRUCT(finddcs_io);
-       finddcs_io.in.dns_domain_name = lpcfg_realm(ctx->lp_ctx);
+       finddcs_io.in.domain_name = lpcfg_realm(ctx->lp_ctx);
+       if (strcmp(finddcs_io.in.domain_name, "") == 0) {
+               finddcs_io.in.domain_name = lpcfg_workgroup(ctx->lp_ctx);
+       }
        finddcs_io.in.minimum_dc_flags = NBT_SERVER_LDAP | NBT_SERVER_DS | NBT_SERVER_WRITABLE;
 
 
index b019d7c2fcf60a8cb2b99415727e59ec73a1b42d..8ff383036e2d2bdfdf29e3104029cb1b97464ab9 100644 (file)
@@ -479,7 +479,7 @@ static PyObject *py_net_finddc(py_net_Object *self, PyObject *args)
        mem_ctx = talloc_new(self->mem_ctx);
 
        ZERO_STRUCT(io);
-       io.in.dns_domain_name = domain_name;
+       io.in.domain_name = domain_name;
        io.in.minimum_dc_flags = server_type;
 
        status = finddcs_cldap(mem_ctx, &io,
index e7e5941c630b0c348be83effdfd3958f8c31caf0..bce9162e4587c02e85c06ae651bcdebf0db4ea49 100644 (file)
@@ -57,9 +57,6 @@ class cmd_join(Command):
         if not role is None:
             role = role.upper()
 
-        if domain.find('.') == -1:
-            raise CommandError("Please use the full DNS domain name, not the short form for '%s'" % domain)
-
         if role is None:
             secure_channel_type = SEC_CHAN_WKSTA
         elif role == "BDC":
index bd1f3c5ff694d561b0bcb8931313b391cdcdd882..d2ce8a9f0a8c55a98a256d85d508464302dc1792 100644 (file)
@@ -70,7 +70,7 @@ struct composite_context *wb_get_dom_info_send(TALLOC_CTX *mem_ctx,
        if (dom_sid == NULL) goto failed;
 
        ZERO_STRUCT(finddcs_io);
-       finddcs_io.in.dns_domain_name  = dns_domain_name;
+       finddcs_io.in.domain_name      = dns_domain_name;
        finddcs_io.in.domain_sid       = dom_sid;
        finddcs_io.in.minimum_dc_flags = NBT_SERVER_LDAP | NBT_SERVER_DS;
        if (service->sec_channel_type == SEC_CHAN_RODC) {