summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2005-04-14 07:40:23 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:11:33 -0500
commite284a262942eb8c69d7862cb61bf4542baec6032 (patch)
tree74c000adaa7fbe5b73e943272050d612112ff3a3
parent8c4e06004cf5e95ea861440ef0ec0b4ddacf4c10 (diff)
downloadsamba-e284a262942eb8c69d7862cb61bf4542baec6032.tar.gz
samba-e284a262942eb8c69d7862cb61bf4542baec6032.tar.bz2
samba-e284a262942eb8c69d7862cb61bf4542baec6032.zip
r6338: ADS style GETDC response now works well enough that WinXP can join
Samba4 without Samba3 nmbd (This used to be commit f4d07d7d3b6973b503d8c98f177471dd6cebfa92)
-rw-r--r--source4/libcli/nbt/nbtname.c12
-rw-r--r--source4/librpc/idl/nbt.idl28
-rw-r--r--source4/nbt_server/dgram/netlogon.c82
-rw-r--r--source4/torture/nbt/dgram.c2
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
@@ -66,6 +66,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
*/
void nbtd_mailslot_netlogon_handler(struct dgram_mailslot_handler *dgmslot,
@@ -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 */