summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2005-05-10 23:33:56 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:16:37 -0500
commit2f2fc84a7c6724f6eab39bf301be70ba5bec15cc (patch)
tree13eb42b0238a5744bb2f368f8e686d350287afe5
parent398a3130f5166d4a4d455529ae3048316510f867 (diff)
downloadsamba-2f2fc84a7c6724f6eab39bf301be70ba5bec15cc.tar.gz
samba-2f2fc84a7c6724f6eab39bf301be70ba5bec15cc.tar.bz2
samba-2f2fc84a7c6724f6eab39bf301be70ba5bec15cc.zip
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)
-rw-r--r--source4/libcli/cldap/cldap.c5
-rw-r--r--source4/libcli/cldap/cldap.h2
-rw-r--r--source4/librpc/idl/nbt.idl72
-rw-r--r--source4/librpc/ndr/libndr.h1
-rw-r--r--source4/librpc/ndr/ndr.c39
-rw-r--r--source4/torture/ldap/cldap.c20
6 files changed, 106 insertions, 33 deletions
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
@@ -325,6 +325,23 @@ void ndr_print_debug(ndr_print_fn_t fn, const char *name, void *ptr)
}
/*
+ 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()
*/
void ndr_print_function_debug(ndr_print_function_t fn, const char *name, int flags, void *ptr)
@@ -781,6 +798,28 @@ NTSTATUS ndr_pull_struct_blob_all(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, vo
}
/*
+ 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
*/
NTSTATUS ndr_push_struct_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
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);
}
}