From 2f2fc84a7c6724f6eab39bf301be70ba5bec15cc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 May 2005 23:33:56 +0000 Subject: r6720: added support for the remaining 2 types of CLDAP netlogon response. To work around the fact that the type of the returned data is not encoded in the packet, this required adding ndr_pull_union_blob() which allows us to pull a blob into a union with a specified switch value, in this case the switch value comes from the calling NtVer field. (This used to be commit bd27e626c27be72913d1a1569ee6e2e2711df84e) --- source4/libcli/cldap/cldap.c | 5 +-- source4/libcli/cldap/cldap.h | 2 +- source4/librpc/idl/nbt.idl | 72 +++++++++++++++++++++++++++++++++----------- source4/librpc/ndr/libndr.h | 1 + source4/librpc/ndr/ndr.c | 39 ++++++++++++++++++++++++ source4/torture/ldap/cldap.c | 20 +++++------- 6 files changed, 106 insertions(+), 33 deletions(-) (limited to 'source4') diff --git a/source4/libcli/cldap/cldap.c b/source4/libcli/cldap/cldap.c index 7caf5a0810..a28afc6877 100644 --- a/source4/libcli/cldap/cldap.c +++ b/source4/libcli/cldap/cldap.c @@ -451,8 +451,9 @@ NTSTATUS cldap_netlogon_recv(struct cldap_request *req, } data = search.out.response->attributes[0].values; - status = ndr_pull_struct_blob_all(data, mem_ctx, &io->out.netlogon, - (ndr_pull_flags_fn_t)ndr_pull_nbt_cldap_netlogon); + status = ndr_pull_union_blob(data, mem_ctx, &io->out.netlogon, + io->in.version & 0xF, + (ndr_pull_flags_fn_t)ndr_pull_nbt_cldap_netlogon); if (!NT_STATUS_IS_OK(status)) { DEBUG(2,("cldap failed to parse netlogon response of type 0x%02x\n", SVAL(data->data, 0))); diff --git a/source4/libcli/cldap/cldap.h b/source4/libcli/cldap/cldap.h index 5ed7df15c7..a8bba7edbe 100644 --- a/source4/libcli/cldap/cldap.h +++ b/source4/libcli/cldap/cldap.h @@ -127,7 +127,7 @@ struct cldap_netlogon { uint8_t version; } in; struct { - struct nbt_cldap_netlogon netlogon; + union nbt_cldap_netlogon netlogon; } out; }; diff --git a/source4/librpc/idl/nbt.idl b/source4/librpc/idl/nbt.idl index 3719b2fdad..2468e4e8bf 100644 --- a/source4/librpc/idl/nbt.idl +++ b/source4/librpc/idl/nbt.idl @@ -452,24 +452,38 @@ /*******************************************/ /* CLDAP netlogon response */ - typedef enum { - CLDAP_NETLOGON_19 = 0x13, - CLDAP_NETLOGON_23 = 0x17 - } nbt_cldap_netlogon_command; + /* note that these structures are very similar to, but not + quite identical to, the netlogon structures above */ - /* cldap type 19 netlogon response */ typedef struct { + [value(19)] uint16 type; nstring pdc_name; nstring unknown; nstring domain_name; uint32 nt_version; uint16 lmnt_token; uint16 lm20_token; - } nbt_cldap_netlogon_19; + } nbt_cldap_netlogon_1; - /* cldap type 23 netlogon response */ typedef struct { - [flag(NDR_ALIGN4)] DATA_BLOB _pad; + [value(19)] uint16 type; + nstring pdc_name; + nstring unknown; + nstring domain_name; + GUID domain_uuid; + GUID unknown_uuid; + nbt_string forest; + nbt_string dns_domain; + nbt_string pdc_dns_name; + ipv4address pdc_ip; + nbt_server_type server_type; + uint32 nt_version; + uint16 lmnt_token; + uint16 lm20_token; + } nbt_cldap_netlogon_2; + + typedef struct { + [value(23)] uint32 type; nbt_server_type server_type; GUID domain_uuid; nbt_string forest; @@ -483,16 +497,40 @@ uint32 nt_version; uint16 lmnt_token; uint16 lm20_token; - } nbt_cldap_netlogon_23; + } nbt_cldap_netlogon_3; - typedef [nodiscriminant] union { - [case(CLDAP_NETLOGON_19)] nbt_cldap_netlogon_19 logon19; - [case(CLDAP_NETLOGON_23)] nbt_cldap_netlogon_23 logon23; - } nbt_cldap_netlogon_info; - - typedef [flag(NDR_NOALIGN),public] struct { - nbt_cldap_netlogon_command command; - [switch_is(command)] nbt_cldap_netlogon_info info; + typedef struct { + [value(23)] uint32 type; + nbt_server_type server_type; + GUID domain_uuid; + nbt_string forest; + nbt_string dns_domain; + nbt_string pdc_dns_name; + nbt_string domain; + nbt_string pdc_name; + nbt_string user_name; + nbt_string site_name; + nbt_string site_name2; + uint8 unknown; + uint32 unknown2; + [flag(NDR_BIG_ENDIAN)] + ipv4address pdc_ip; + uint32 unknown3[2]; + uint32 nt_version; + uint16 lmnt_token; + uint16 lm20_token; + } nbt_cldap_netlogon_4; + + typedef [flag(NDR_NOALIGN),public,nodiscriminant] union { + [case(0)] nbt_cldap_netlogon_1 logon1; + [case(1)] nbt_cldap_netlogon_1 logon1; + [case(2)] nbt_cldap_netlogon_2 logon2; + [case(3)] nbt_cldap_netlogon_2 logon2; + [case(4)] nbt_cldap_netlogon_3 logon3; + [case(5)] nbt_cldap_netlogon_3 logon3; + [case(6)] nbt_cldap_netlogon_3 logon3; + [case(7)] nbt_cldap_netlogon_3 logon3; + [default] nbt_cldap_netlogon_4 logon4; } nbt_cldap_netlogon; /*******************************************/ diff --git a/source4/librpc/ndr/libndr.h b/source4/librpc/ndr/libndr.h index 738e5d61c9..ddf9664b9b 100644 --- a/source4/librpc/ndr/libndr.h +++ b/source4/librpc/ndr/libndr.h @@ -138,6 +138,7 @@ struct ndr_print { /* useful macro for debugging */ #define NDR_PRINT_DEBUG(type, p) ndr_print_debug((ndr_print_fn_t)ndr_print_ ##type, #p, p) +#define NDR_PRINT_UNION_DEBUG(type, level, p) ndr_print_union_debug((ndr_print_fn_t)ndr_print_ ##type, #p, level, p) #define NDR_PRINT_FUNCTION_DEBUG(type, flags, p) ndr_print_function_debug((ndr_print_function_t)ndr_print_ ##type, #type, flags, p) #define NDR_PRINT_BOTH_DEBUG(type, p) NDR_PRINT_FUNCTION_DEBUG(type, NDR_BOTH, p) #define NDR_PRINT_OUT_DEBUG(type, p) NDR_PRINT_FUNCTION_DEBUG(type, NDR_OUT, p) diff --git a/source4/librpc/ndr/ndr.c b/source4/librpc/ndr/ndr.c index 79af5967c7..7beb64942a 100644 --- a/source4/librpc/ndr/ndr.c +++ b/source4/librpc/ndr/ndr.c @@ -324,6 +324,23 @@ void ndr_print_debug(ndr_print_fn_t fn, const char *name, void *ptr) talloc_free(ndr); } +/* + a useful helper function for printing idl unions via DEBUG() +*/ +void ndr_print_union_debug(ndr_print_fn_t fn, const char *name, uint32_t level, void *ptr) +{ + struct ndr_print *ndr; + + ndr = talloc_zero(NULL, struct ndr_print); + if (!ndr) return; + ndr->print = ndr_print_debug_helper; + ndr->depth = 1; + ndr->flags = 0; + ndr_print_set_switch_value(ndr, ptr, level); + fn(ndr, name, ptr); + talloc_free(ndr); +} + /* a useful helper function for printing idl function calls via DEBUG() */ @@ -780,6 +797,28 @@ NTSTATUS ndr_pull_struct_blob_all(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, vo return status; } +/* + pull a union from a blob using NDR, given the union discriminator +*/ +NTSTATUS ndr_pull_union_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p, + uint32_t level, ndr_pull_flags_fn_t fn) +{ + struct ndr_pull *ndr; + NTSTATUS status; + + ndr = ndr_pull_init_blob(blob, mem_ctx); + if (!ndr) { + return NT_STATUS_NO_MEMORY; + } + ndr_pull_set_switch_value(ndr, p, level); + status = fn(ndr, NDR_SCALARS|NDR_BUFFERS, p); + if (!NT_STATUS_IS_OK(status)) return status; + if (ndr->offset != ndr->data_size) { + return NT_STATUS_BUFFER_TOO_SMALL; + } + return status; +} + /* push a struct to a blob using NDR */ diff --git a/source4/torture/ldap/cldap.c b/source4/torture/ldap/cldap.c index 23bb7f5ba0..24cbc184ad 100644 --- a/source4/torture/ldap/cldap.c +++ b/source4/torture/ldap/cldap.c @@ -37,25 +37,19 @@ static BOOL test_cldap_netlogon(TALLOC_CTX *mem_ctx, const char *dest) struct cldap_netlogon search; int i; - search.in.dest_address = dest; - search.in.realm = lp_realm(); - search.in.host = lp_netbios_name(); - search.in.version = 6; - status = cldap_netlogon(cldap, mem_ctx, &search); + search.in.dest_address = dest; + search.in.realm = lp_realm(); + search.in.host = lp_netbios_name(); - if (!NT_STATUS_IS_OK(status)) { - printf("netlogon failed - %s\n", nt_errstr(status)); - } else { - NDR_PRINT_DEBUG(nbt_cldap_netlogon, &search.out.netlogon); - } - - for (i=0;i<20;i++) { + for (i=0;i<256;i++) { search.in.version = i; + printf("Trying netlogon level %d\n", i); status = cldap_netlogon(cldap, mem_ctx, &search); if (!NT_STATUS_IS_OK(status)) { printf("netlogon[%d] failed - %s\n", i, nt_errstr(status)); } else { - NDR_PRINT_DEBUG(nbt_cldap_netlogon, &search.out.netlogon); + NDR_PRINT_UNION_DEBUG(nbt_cldap_netlogon, i & 0xF, + &search.out.netlogon); } } -- cgit