diff options
author | Andrew Tridgell <tridge@samba.org> | 2010-09-14 20:10:51 +1000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2010-09-15 15:39:36 +1000 |
commit | 59d415f43f72146b15a721e928cf346777239bfc (patch) | |
tree | e6bd1c56d75e328256bdb0f2e67795fee52c1c08 | |
parent | 99f514f233fb1b3dcdd19cd2cc9ca9130ea841c8 (diff) | |
download | samba-59d415f43f72146b15a721e928cf346777239bfc.tar.gz samba-59d415f43f72146b15a721e928cf346777239bfc.tar.bz2 samba-59d415f43f72146b15a721e928cf346777239bfc.zip |
s4-finddc: use NBT lookup for a 1C name if joining a short domain name
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>
-rw-r--r-- | source4/libcli/finddc.h | 2 | ||||
-rw-r--r-- | source4/libcli/finddcs_cldap.c | 111 | ||||
-rw-r--r-- | source4/libnet/libnet_lookup.c | 5 | ||||
-rw-r--r-- | source4/libnet/py_net.c | 2 | ||||
-rw-r--r-- | source4/scripting/python/samba/netcmd/join.py | 3 | ||||
-rw-r--r-- | source4/winbind/wb_dom_info.c | 2 |
6 files changed, 105 insertions, 20 deletions
diff --git a/source4/libcli/finddc.h b/source4/libcli/finddc.h index 9e6e2dfe83..3f1caf9ce5 100644 --- a/source4/libcli/finddc.h +++ b/source4/libcli/finddc.h @@ -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_* */ diff --git a/source4/libcli/finddcs_cldap.c b/source4/libcli/finddcs_cldap.c index 4d721f9d6e..949002bd51 100644 --- a/source4/libcli/finddcs_cldap.c +++ b/source4/libcli/finddcs_cldap.c @@ -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 diff --git a/source4/libnet/libnet_lookup.c b/source4/libnet/libnet_lookup.c index c6af75b4e3..3677c2a31e 100644 --- a/source4/libnet/libnet_lookup.c +++ b/source4/libnet/libnet_lookup.c @@ -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; diff --git a/source4/libnet/py_net.c b/source4/libnet/py_net.c index b019d7c2fc..8ff383036e 100644 --- a/source4/libnet/py_net.c +++ b/source4/libnet/py_net.c @@ -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, diff --git a/source4/scripting/python/samba/netcmd/join.py b/source4/scripting/python/samba/netcmd/join.py index e7e5941c63..bce9162e45 100644 --- a/source4/scripting/python/samba/netcmd/join.py +++ b/source4/scripting/python/samba/netcmd/join.py @@ -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": diff --git a/source4/winbind/wb_dom_info.c b/source4/winbind/wb_dom_info.c index bd1f3c5ff6..d2ce8a9f0a 100644 --- a/source4/winbind/wb_dom_info.c +++ b/source4/winbind/wb_dom_info.c @@ -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) { |