From e284a262942eb8c69d7862cb61bf4542baec6032 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 14 Apr 2005 07:40:23 +0000 Subject: r6338: ADS style GETDC response now works well enough that WinXP can join Samba4 without Samba3 nmbd (This used to be commit f4d07d7d3b6973b503d8c98f177471dd6cebfa92) --- source4/libcli/nbt/nbtname.c | 12 +++++- source4/librpc/idl/nbt.idl | 28 +++++++++---- source4/nbt_server/dgram/netlogon.c | 82 +++++++++++++++++++++++++++++++++++++ source4/torture/nbt/dgram.c | 2 +- 4 files changed, 114 insertions(+), 10 deletions(-) diff --git a/source4/libcli/nbt/nbtname.c b/source4/libcli/nbt/nbtname.c index f7d19d11cf..5f344d9c6d 100644 --- a/source4/libcli/nbt/nbtname.c +++ b/source4/libcli/nbt/nbtname.c @@ -144,6 +144,11 @@ NTSTATUS ndr_push_nbt_string(struct ndr_push *ndr, int ndr_flags, const char *s) return NT_STATUS_OK; } + if (s == NULL || *s == 0) { + return ndr_push_bytes(ndr, "", 1); + } + + fullname = talloc_strdup(ndr, ""); NT_STATUS_HAVE_NO_MEMORY(fullname); @@ -162,11 +167,14 @@ NTSTATUS ndr_push_nbt_string(struct ndr_push *ndr, int ndr_flags, const char *s) so, we can use a NBT name pointer. This allows us to fit longer names into the packet */ fulllen = strlen(fullname)+1; - for (i=0;i + fulllen < ndr->offset;i++) { + for (i=0;i + fulllen <= ndr->offset;i++) { if (ndr->data[i] == fullname[0] && memcmp(fullname, &ndr->data[i], fulllen) == 0) { + uint8_t b[2]; talloc_free(fullname); - return ndr_push_uint16(ndr, NDR_SCALARS, 0xC000 | i); + b[0] = 0xC0 | (i>>8); + b[1] = (i&0xFF); + return ndr_push_bytes(ndr, b, 2); } } diff --git a/source4/librpc/idl/nbt.idl b/source4/librpc/idl/nbt.idl index a28c029b7d..3dd5816474 100644 --- a/source4/librpc/idl/nbt.idl +++ b/source4/librpc/idl/nbt.idl @@ -330,11 +330,12 @@ /*******************************************/ /* \MAILSLOT\NET\NETLOGON mailslot requests */ typedef enum { - NETLOGON_QUERY_FOR_PDC = 0x7, - NETLOGON_ANNOUNCE_UAS = 0xa, - NETLOGON_RESPONSE_FROM_PDC = 0xc, - NETLOGON_QUERY_FOR_PDC2 = 0x12, - NETLOGON_RESPONSE_FROM_PDC2 = 0x17 + NETLOGON_QUERY_FOR_PDC = 0x7, + NETLOGON_ANNOUNCE_UAS = 0xa, + NETLOGON_RESPONSE_FROM_PDC = 0xc, + NETLOGON_QUERY_FOR_PDC2 = 0x12, + NETLOGON_RESPONSE_FROM_PDC2 = 0x17, + NETLOGON_RESPONSE_FROM_PDC_USER = 0x19 } nbt_netlogon_command; /* query for pdc request */ @@ -371,15 +372,27 @@ uint16 lm20_token; } nbt_netlogon_response_from_pdc; + typedef [bitmap32bit] bitmap { + NBT_SERVER_PDC = 0x00000001, + NBT_SERVER_GC = 0x00000004, + NBT_SERVER_LDAP = 0x00000008, + NBT_SERVER_DS = 0x00000010, + NBT_SERVER_KDC = 0x00000020, + NBT_SERVER_TIMESERV = 0x00000040, + NBT_SERVER_CLOSEST = 0x00000080, + NBT_SERVER_WRITABLE = 0x00000100, + NBT_SERVER_GOOD_TIMESERV = 0x00000200 + } nbt_server_type; + /* response from pdc - type2 */ typedef struct { [flag(NDR_ALIGN4)] DATA_BLOB _pad; - uint32 server_type; + nbt_server_type server_type; GUID domain_uuid; nbt_string forest; nbt_string dns_domain; nbt_string pdc_dns_name; - astring domain; + nbt_string domain; nbt_string pdc_name; nbt_string user_name; nbt_string site_name; @@ -428,6 +441,7 @@ [case(NETLOGON_ANNOUNCE_UAS)] nbt_netlogon_announce_uas uas; [case(NETLOGON_RESPONSE_FROM_PDC)] nbt_netlogon_response_from_pdc response; [case(NETLOGON_RESPONSE_FROM_PDC2)] nbt_netlogon_response_from_pdc2 response2; + [case(NETLOGON_RESPONSE_FROM_PDC_USER)] nbt_netlogon_response_from_pdc2 response2; } nbt_netlogon_request; typedef [flag(NDR_NOALIGN),public] struct { diff --git a/source4/nbt_server/dgram/netlogon.c b/source4/nbt_server/dgram/netlogon.c index 91da11299a..d47c45a875 100644 --- a/source4/nbt_server/dgram/netlogon.c +++ b/source4/nbt_server/dgram/netlogon.c @@ -65,6 +65,85 @@ static void nbtd_netlogon_getdc(struct dgram_mailslot_handler *dgmslot, } +/* + reply to a ADS style GETDC request + */ +static void nbtd_netlogon_getdc2(struct dgram_mailslot_handler *dgmslot, + struct nbt_dgram_packet *packet, + const char *src_address, int src_port, + struct nbt_netlogon_packet *netlogon) +{ + struct nbt_name *name = &packet->data.msg.dest_name; + struct nbt_netlogon_packet reply; + struct nbt_netlogon_response_from_pdc2 *pdc; + struct ldb_context *samctx; + const char *attrs[] = {"realm", "dnsDomain", "objectGUID", NULL}; + struct ldb_message **res; + int ret; + + /* only answer getdc requests on the PDC or LOGON names */ + if (name->type != NBT_NAME_PDC && name->type != NBT_NAME_LOGON) { + return; + } + + samctx = samdb_connect(packet); + if (samctx == NULL) { + DEBUG(2,("Unable to open sam in getdc reply\n")); + return; + } + + /* try and find the domain */ + ret = gendb_search(samctx, samctx, NULL, &res, attrs, + "(&(name=%s)(objectClass=domainDNS))", name->name); + if (ret != 1) { + DEBUG(2,("Unable to find domain '%s' in sam\n", name->name)); + return; + } + + /* setup a GETDC reply */ + ZERO_STRUCT(reply); + if (netlogon->req.pdc2.user_name[0]) { + reply.command = NETLOGON_RESPONSE_FROM_PDC_USER; + } else { + reply.command = NETLOGON_RESPONSE_FROM_PDC2; + } + pdc = &reply.req.response2; + + /* TODO: accurately depict which services we are running */ + pdc->server_type = + NBT_SERVER_PDC | NBT_SERVER_GC | NBT_SERVER_LDAP | + NBT_SERVER_DS | NBT_SERVER_KDC | NBT_SERVER_TIMESERV | + NBT_SERVER_CLOSEST | NBT_SERVER_WRITABLE | NBT_SERVER_GOOD_TIMESERV; + + pdc->domain_uuid = samdb_result_guid(res[0], "objectGUID"); + pdc->forest = samdb_result_string(res[0], "realm", lp_realm()); + pdc->dns_domain = samdb_result_string(res[0], "dnsDomain", lp_realm()); + + /* TODO: get our full DNS name from somewhere else */ + pdc->pdc_dns_name = talloc_asprintf(packet, "%s.%s", + lp_netbios_name(), pdc->dns_domain); + pdc->domain = name->name; + pdc->pdc_name = lp_netbios_name(); + pdc->user_name = netlogon->req.pdc2.user_name; + /* TODO: we need to make sure these are in our DNS zone */ + pdc->site_name = "Default-First-Site-Name"; + pdc->site_name2 = "Default-First-Site-Name"; + pdc->unknown = 0x10; /* what is this? */ + pdc->unknown2 = 2; /* and this ... */ + pdc->pdc_ip = socket_get_my_addr(dgmslot->dgmsock->sock, packet); + pdc->nt_version = 13; + pdc->lmnt_token = 0xFFFF; + pdc->lm20_token = 0xFFFF; + + packet->data.msg.dest_name.type = 0; + + dgram_mailslot_netlogon_reply(dgmslot->dgmsock, + packet, + netlogon->req.pdc2.mailslot_name, + &reply); +} + + /* handle incoming netlogon mailslot requests */ @@ -102,6 +181,9 @@ void nbtd_mailslot_netlogon_handler(struct dgram_mailslot_handler *dgmslot, case NETLOGON_QUERY_FOR_PDC: nbtd_netlogon_getdc(dgmslot, packet, src_address, src_port, netlogon); break; + case NETLOGON_QUERY_FOR_PDC2: + nbtd_netlogon_getdc2(dgmslot, packet, src_address, src_port, netlogon); + break; default: DEBUG(2,("unknown netlogon op %d from %s:%d\n", netlogon->command, src_address, src_port)); diff --git a/source4/torture/nbt/dgram.c b/source4/torture/nbt/dgram.c index b1dd92621c..5726e68471 100644 --- a/source4/torture/nbt/dgram.c +++ b/source4/torture/nbt/dgram.c @@ -297,7 +297,7 @@ BOOL torture_nbt_dgram(void) BOOL ret = True; name.name = lp_workgroup(); - name.type = NBT_NAME_PDC; + name.type = NBT_NAME_LOGON; name.scope = NULL; /* do an initial name resolution to find its IP */ -- cgit