diff options
Diffstat (limited to 'source4/nbt_server')
-rw-r--r-- | source4/nbt_server/config.mk | 2 | ||||
-rw-r--r-- | source4/nbt_server/dgram/browse.c | 1 | ||||
-rw-r--r-- | source4/nbt_server/dgram/netlogon.c | 153 | ||||
-rw-r--r-- | source4/nbt_server/dgram/request.c | 4 | ||||
-rw-r--r-- | source4/nbt_server/irpc.c | 82 |
5 files changed, 95 insertions, 147 deletions
diff --git a/source4/nbt_server/config.mk b/source4/nbt_server/config.mk index bb5dec7661..b17fd4ce52 100644 --- a/source4/nbt_server/config.mk +++ b/source4/nbt_server/config.mk @@ -46,7 +46,7 @@ PRIVATE_DEPENDENCIES = \ # End SUBSYSTEM NBTD_DGRAM ####################### -NBTD_DGRAM_OBJ_FILES = $(addprefix $(nbt_serversrcdir)/dgram/, request.o netlogon.o ntlogon.o browse.o) +NBTD_DGRAM_OBJ_FILES = $(addprefix $(nbt_serversrcdir)/dgram/, request.o netlogon.o browse.o) $(eval $(call proto_header_template,$(nbt_serversrcdir)/dgram/proto.h,$(NBTD_DGRAM_OBJ_FILES:.o=.c))) diff --git a/source4/nbt_server/dgram/browse.c b/source4/nbt_server/dgram/browse.c index 2e12fa114a..36f0160e1b 100644 --- a/source4/nbt_server/dgram/browse.c +++ b/source4/nbt_server/dgram/browse.c @@ -49,6 +49,7 @@ static const char *nbt_browse_opcode_string(enum nbt_browse_opcode r) */ void nbtd_mailslot_browse_handler(struct dgram_mailslot_handler *dgmslot, struct nbt_dgram_packet *packet, + const char *mailslot_name, struct socket_address *src) { struct nbt_browse_packet *browse = talloc(dgmslot, struct nbt_browse_packet); diff --git a/source4/nbt_server/dgram/netlogon.c b/source4/nbt_server/dgram/netlogon.c index 7fae6bc1f6..c66089523b 100644 --- a/source4/nbt_server/dgram/netlogon.c +++ b/source4/nbt_server/dgram/netlogon.c @@ -4,7 +4,8 @@ NBT datagram netlogon server Copyright (C) Andrew Tridgell 2005 - + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008 + 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 3 of the License, or @@ -26,9 +27,10 @@ #include "dsdb/samdb/samdb.h" #include "auth/auth.h" #include "util/util_ldb.h" -#include "librpc/gen_ndr/ndr_nbt.h" #include "param/param.h" #include "smbd/service_task.h" +#include "cldap_server/cldap_server.h" +#include "libcli/security/security.h" /* reply to a GETDC request @@ -36,17 +38,18 @@ static void nbtd_netlogon_getdc(struct dgram_mailslot_handler *dgmslot, struct nbtd_interface *iface, struct nbt_dgram_packet *packet, + const char *mailslot_name, const struct socket_address *src, struct nbt_netlogon_packet *netlogon) { struct nbt_name *name = &packet->data.msg.dest_name; struct nbtd_interface *reply_iface = nbtd_find_reply_iface(iface, src->addr, false); - struct nbt_netlogon_packet reply; struct nbt_netlogon_response_from_pdc *pdc; const char *ref_attrs[] = {"nETBIOSName", NULL}; struct ldb_message **ref_res; struct ldb_context *samctx; struct ldb_dn *partitions_basedn; + struct nbt_netlogon_response netlogon_response; int ret; /* only answer getdc requests on the PDC or LOGON names */ @@ -60,6 +63,11 @@ static void nbtd_netlogon_getdc(struct dgram_mailslot_handler *dgmslot, return; } + if (!samdb_is_pdc(samctx)) { + DEBUG(2, ("Not a PDC, so not processing LOGON_PRIMARY_QUERY\n")); + return; + } + partitions_basedn = samdb_partitions_dn(samctx, packet); ret = gendb_search(samctx, packet, partitions_basedn, &ref_res, ref_attrs, @@ -72,10 +80,11 @@ static void nbtd_netlogon_getdc(struct dgram_mailslot_handler *dgmslot, } /* setup a GETDC reply */ - ZERO_STRUCT(reply); - reply.command = NETLOGON_RESPONSE_FROM_PDC; - pdc = &reply.req.response; + ZERO_STRUCT(netlogon_response); + netlogon_response.response_type = NETLOGON_GET_PDC; + pdc = &netlogon_response.get_pdc; + pdc->command = NETLOGON_RESPONSE_FROM_PDC; pdc->pdc_name = lp_netbios_name(iface->nbtsrv->task->lp_ctx); pdc->unicode_pdc_name = pdc->pdc_name; pdc->domain_name = samdb_result_string(ref_res[0], "nETBIOSName", name->name);; @@ -83,38 +92,32 @@ static void nbtd_netlogon_getdc(struct dgram_mailslot_handler *dgmslot, pdc->lmnt_token = 0xFFFF; pdc->lm20_token = 0xFFFF; - - packet->data.msg.dest_name.type = 0; - dgram_mailslot_netlogon_reply(reply_iface->dgmsock, packet, lp_netbios_name(iface->nbtsrv->task->lp_ctx), netlogon->req.pdc.mailslot_name, - &reply); + &netlogon_response); } /* reply to a ADS style GETDC request */ -static void nbtd_netlogon_getdc2(struct dgram_mailslot_handler *dgmslot, - struct nbtd_interface *iface, - struct nbt_dgram_packet *packet, - const struct socket_address *src, - struct nbt_netlogon_packet *netlogon) +static void nbtd_netlogon_samlogon(struct dgram_mailslot_handler *dgmslot, + struct nbtd_interface *iface, + struct nbt_dgram_packet *packet, + const char *mailslot_name, + const struct socket_address *src, + struct nbt_netlogon_packet *netlogon) { struct nbt_name *name = &packet->data.msg.dest_name; struct nbtd_interface *reply_iface = nbtd_find_reply_iface(iface, src->addr, false); - struct nbt_netlogon_packet reply; - struct nbt_netlogon_response_from_pdc2 *pdc; struct ldb_context *samctx; - const char *ref_attrs[] = {"nETBIOSName", "dnsRoot", "ncName", NULL}; - const char *dom_attrs[] = {"objectGUID", NULL}; - struct ldb_message **ref_res, **dom_res; - int ret; - const char **services = lp_server_services(iface->nbtsrv->task->lp_ctx); const char *my_ip = reply_iface->ip_address; - struct ldb_dn *partitions_basedn; + struct dom_sid *sid; + struct nbt_netlogon_response netlogon_response; + NTSTATUS status; + if (!my_ip) { DEBUG(0, ("Could not obtain own IP address for datagram socket\n")); return; @@ -131,90 +134,35 @@ static void nbtd_netlogon_getdc2(struct dgram_mailslot_handler *dgmslot, return; } - partitions_basedn = samdb_partitions_dn(samctx, packet); - - ret = gendb_search(samctx, packet, partitions_basedn, &ref_res, ref_attrs, - "(&(&(nETBIOSName=%s)(objectclass=crossRef))(ncName=*))", - name->name); - - if (ret != 1) { - DEBUG(2,("Unable to find domain reference '%s' in sam\n", name->name)); - return; + if (netlogon->req.logon.sid_size) { + if (strcasecmp(mailslot_name, NBT_MAILSLOT_NTLOGON) == 0) { + DEBUG(2,("NBT netlogon query failed because SID specified in request to NTLOGON\n")); + /* SID not permitted on NTLOGON (for some reason...) */ + return; + } + sid = &netlogon->req.logon.sid; + } else { + sid = NULL; } - /* try and find the domain */ - ret = gendb_search_dn(samctx, packet, - samdb_result_dn(samctx, samctx, ref_res[0], "ncName", NULL), - &dom_res, dom_attrs); - if (ret != 1) { - DEBUG(2,("Unable to find domain from reference '%s' in sam\n", - ldb_dn_get_linearized(ref_res[0]->dn))); + status = fill_netlogon_samlogon_response(samctx, packet, NULL, name->name, sid, NULL, + netlogon->req.logon.user_name, src->addr, + netlogon->req.logon.nt_version, iface->nbtsrv->task->lp_ctx, &netlogon_response.samlogon); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(2,("NBT netlogon query failed domain=%s sid=%s version=%d - %s\n", + name->name, dom_sid_string(packet, sid), netlogon->req.logon.nt_version, nt_errstr(status))); return; } - /* setup a GETDC reply */ - ZERO_STRUCT(reply); - reply.command = NETLOGON_RESPONSE_FROM_PDC2; - -#if 0 - /* newer testing shows that the reply command type is not - changed based on whether a username is given in the - reply. This was what was causing the w2k join to be so - slow */ - if (netlogon->req.pdc2.user_name[0]) { - reply.command = NETLOGON_RESPONSE_FROM_PDC_USER; - } -#endif - - pdc = &reply.req.response2; - - /* TODO: accurately depict which services we are running */ - pdc->server_type = - NBT_SERVER_PDC | NBT_SERVER_GC | - NBT_SERVER_DS | NBT_SERVER_TIMESERV | - NBT_SERVER_CLOSEST | NBT_SERVER_WRITABLE | - NBT_SERVER_GOOD_TIMESERV; - - /* hmm, probably a better way to do this */ - if (str_list_check(services, "ldap")) { - pdc->server_type |= NBT_SERVER_LDAP; - } - - if (str_list_check(services, "kdc")) { - pdc->server_type |= NBT_SERVER_KDC; - } - - pdc->domain_uuid = samdb_result_guid(dom_res[0], "objectGUID"); - pdc->forest = samdb_result_string(ref_res[0], "dnsRoot", - lp_realm(iface->nbtsrv->task->lp_ctx)); - pdc->dns_domain = samdb_result_string(ref_res[0], "dnsRoot", - lp_realm(iface->nbtsrv->task->lp_ctx)); - - /* TODO: get our full DNS name from somewhere else */ - pdc->pdc_dns_name = talloc_asprintf(packet, "%s.%s", - strlower_talloc(packet, - lp_netbios_name(iface->nbtsrv->task->lp_ctx)), - pdc->dns_domain); - pdc->domain = samdb_result_string(ref_res[0], "nETBIOSName", name->name);; - pdc->pdc_name = lp_netbios_name(iface->nbtsrv->task->lp_ctx); - pdc->user_name = netlogon->req.pdc2.user_name; - /* TODO: we need to make sure these are in our DNS zone */ - pdc->server_site = "Default-First-Site-Name"; - pdc->client_site = "Default-First-Site-Name"; - pdc->unknown = 0x10; /* what is this? */ - pdc->unknown2 = 2; /* and this ... */ - pdc->pdc_ip = my_ip; - pdc->nt_version = 13; - pdc->lmnt_token = 0xFFFF; - pdc->lm20_token = 0xFFFF; + netlogon_response.response_type = NETLOGON_SAMLOGON; packet->data.msg.dest_name.type = 0; dgram_mailslot_netlogon_reply(reply_iface->dgmsock, packet, lp_netbios_name(iface->nbtsrv->task->lp_ctx), - netlogon->req.pdc2.mailslot_name, - &reply); + netlogon->req.logon.mailslot_name, + &netlogon_response); } @@ -223,6 +171,7 @@ static void nbtd_netlogon_getdc2(struct dgram_mailslot_handler *dgmslot, */ void nbtd_mailslot_netlogon_handler(struct dgram_mailslot_handler *dgmslot, struct nbt_dgram_packet *packet, + const char *mailslot_name, struct socket_address *src) { NTSTATUS status = NT_STATUS_NO_MEMORY; @@ -246,15 +195,17 @@ void nbtd_mailslot_netlogon_handler(struct dgram_mailslot_handler *dgmslot, DEBUG(2,("netlogon request to %s from %s:%d\n", nbt_name_string(netlogon, name), src->addr, src->port)); - status = dgram_mailslot_netlogon_parse(dgmslot, netlogon, packet, netlogon); + status = dgram_mailslot_netlogon_parse_request(dgmslot, netlogon, packet, netlogon); if (!NT_STATUS_IS_OK(status)) goto failed; switch (netlogon->command) { - case NETLOGON_QUERY_FOR_PDC: - nbtd_netlogon_getdc(dgmslot, iface, packet, src, netlogon); + case LOGON_PRIMARY_QUERY: + nbtd_netlogon_getdc(dgmslot, iface, packet, mailslot_name, + src, netlogon); break; - case NETLOGON_QUERY_FOR_PDC2: - nbtd_netlogon_getdc2(dgmslot, iface, packet, src, netlogon); + case LOGON_SAM_LOGON_REQUEST: + nbtd_netlogon_samlogon(dgmslot, iface, packet, mailslot_name, + src, netlogon); break; default: DEBUG(2,("unknown netlogon op %d from %s:%d\n", diff --git a/source4/nbt_server/dgram/request.c b/source4/nbt_server/dgram/request.c index 205a544209..277b64741d 100644 --- a/source4/nbt_server/dgram/request.c +++ b/source4/nbt_server/dgram/request.c @@ -35,8 +35,10 @@ static const struct { const char *mailslot_name; dgram_mailslot_handler_t handler; } mailslot_handlers[] = { + /* Handle both NTLOGON and NETLOGON in the same function, as + * they are very similar */ { NBT_MAILSLOT_NETLOGON, nbtd_mailslot_netlogon_handler }, - { NBT_MAILSLOT_NTLOGON, nbtd_mailslot_ntlogon_handler }, + { NBT_MAILSLOT_NTLOGON, nbtd_mailslot_netlogon_handler }, { NBT_MAILSLOT_BROWSE, nbtd_mailslot_browse_handler } }; diff --git a/source4/nbt_server/irpc.c b/source4/nbt_server/irpc.c index 8f2f7fc2c2..3a70c98041 100644 --- a/source4/nbt_server/irpc.c +++ b/source4/nbt_server/irpc.c @@ -49,7 +49,7 @@ static NTSTATUS nbtd_information(struct irpc_message *msg, /* - winbind needs to be able to do a getdc request, but some windows + winbind needs to be able to do a getdc request, but most (all?) windows servers always send the reply to port 138, regardless of the request port. To cope with this we use a irpc request to the NBT server which has port 138 open, and thus can receive the replies @@ -59,55 +59,48 @@ struct getdc_state { struct nbtd_getdcname *req; }; -static void getdc_recv_ntlogon_reply(struct dgram_mailslot_handler *dgmslot, - struct nbt_dgram_packet *packet, - struct socket_address *src) +static void getdc_recv_netlogon_reply(struct dgram_mailslot_handler *dgmslot, + struct nbt_dgram_packet *packet, + const char *mailslot_name, + struct socket_address *src) { struct getdc_state *s = talloc_get_type(dgmslot->private, struct getdc_state); - - struct nbt_ntlogon_packet ntlogon; + const char *p; + struct nbt_netlogon_response netlogon; NTSTATUS status; - status = dgram_mailslot_ntlogon_parse(dgmslot, packet, packet, - &ntlogon); + status = dgram_mailslot_netlogon_parse_response(dgmslot, packet, packet, + &netlogon); if (!NT_STATUS_IS_OK(status)) { DEBUG(5, ("dgram_mailslot_ntlogon_parse failed: %s\n", nt_errstr(status))); goto done; } + /* We asked for version 1 only */ + if (netlogon.response_type == NETLOGON_SAMLOGON + && netlogon.samlogon.ntver != NETLOGON_NT_VERSION_1) { + status = NT_STATUS_INVALID_NETWORK_RESPONSE; + goto done; + } + status = NT_STATUS_NO_LOGON_SERVERS; - DEBUG(10, ("reply: command=%d\n", ntlogon.command)); + p = netlogon.samlogon.nt4.server; - switch (ntlogon.command) { - case NTLOGON_SAM_LOGON: - DEBUG(0, ("Huh -- got NTLOGON_SAM_LOGON as reply\n")); - break; - case NTLOGON_SAM_LOGON_REPLY: - case NTLOGON_SAM_LOGON_REPLY15: { - const char *p = ntlogon.req.reply.server; - - DEBUG(10, ("NTLOGON_SAM_LOGON_REPLY: server: %s, user: %s, " - "domain: %s\n", p, ntlogon.req.reply.user_name, - ntlogon.req.reply.domain)); - - if (*p == '\\') p += 1; - if (*p == '\\') p += 1; - - s->req->out.dcname = talloc_strdup(s->req, p); - if (s->req->out.dcname == NULL) { - DEBUG(0, ("talloc failed\n")); - status = NT_STATUS_NO_MEMORY; - goto done; - } - status = NT_STATUS_OK; - break; - } - default: - DEBUG(0, ("Got unknown packet: %d\n", ntlogon.command)); - break; + DEBUG(10, ("NTLOGON_SAM_LOGON_REPLY: server: %s, user: %s, " + "domain: %s\n", p, netlogon.samlogon.nt4.user_name, + netlogon.samlogon.nt4.domain)); + + if (*p == '\\') p += 1; + if (*p == '\\') p += 1; + + s->req->out.dcname = talloc_strdup(s->req, p); + if (s->req->out.dcname == NULL) { + DEBUG(0, ("talloc failed\n")); + status = NT_STATUS_NO_MEMORY; + goto done; } done: @@ -121,8 +114,8 @@ static NTSTATUS nbtd_getdcname(struct irpc_message *msg, talloc_get_type(msg->private, struct nbtd_server); struct nbtd_interface *iface = nbtd_find_request_iface(server, req->in.ip_address, true); struct getdc_state *s; - struct nbt_ntlogon_packet p; - struct nbt_ntlogon_sam_logon *r; + struct nbt_netlogon_packet p; + struct NETLOGON_SAM_LOGON_REQUEST *r; struct nbt_name src, dst; struct socket_address *dest; struct dgram_mailslot_handler *handler; @@ -137,11 +130,11 @@ static NTSTATUS nbtd_getdcname(struct irpc_message *msg, s->req = req; handler = dgram_mailslot_temp(iface->dgmsock, NBT_MAILSLOT_GETDC, - getdc_recv_ntlogon_reply, s); + getdc_recv_netlogon_reply, s); NT_STATUS_HAVE_NO_MEMORY(handler); ZERO_STRUCT(p); - p.command = NTLOGON_SAM_LOGON; + p.command = LOGON_SAM_LOGON_REQUEST; r = &p.req.logon; r->request_count = 0; r->computer_name = req->in.my_computername; @@ -149,7 +142,7 @@ static NTSTATUS nbtd_getdcname(struct irpc_message *msg, r->mailslot_name = handler->mailslot_name; r->acct_control = req->in.account_control; r->sid = *req->in.domain_sid; - r->nt_version = 1; + r->nt_version = NETLOGON_NT_VERSION_1; r->lmnt_token = 0xffff; r->lm20_token = 0xffff; @@ -160,9 +153,10 @@ static NTSTATUS nbtd_getdcname(struct irpc_message *msg, req->in.ip_address, 138); NT_STATUS_HAVE_NO_MEMORY(dest); - status = dgram_mailslot_ntlogon_send(iface->dgmsock, DGRAM_DIRECT_GROUP, - &dst, dest, - &src, &p); + status = dgram_mailslot_netlogon_send(iface->dgmsock, + &dst, dest, + NBT_MAILSLOT_NETLOGON, + &src, &p); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("dgram_mailslot_ntlogon_send failed: %s\n", nt_errstr(status))); |