r6720: added support for the remaining 2 types of CLDAP netlogon
authorAndrew Tridgell <tridge@samba.org>
Tue, 10 May 2005 23:33:56 +0000 (23:33 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:16:37 +0000 (13:16 -0500)
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
source4/libcli/cldap/cldap.h
source4/librpc/idl/nbt.idl
source4/librpc/ndr/libndr.h
source4/librpc/ndr/ndr.c
source4/torture/ldap/cldap.c

index 7caf5a08102c73d3e5035b014738df869f3dfac9..a28afc68778c756c80a4036e5ade97be8349dcf4 100644 (file)
@@ -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)));
index 5ed7df15c79895d665c6d6cba67498b7d84876cf..a8bba7edbea6f39acae39297efa2587ceb3f0d9c 100644 (file)
@@ -127,7 +127,7 @@ struct cldap_netlogon {
                uint8_t version;
        } in;
        struct {
-               struct nbt_cldap_netlogon netlogon;
+               union nbt_cldap_netlogon netlogon;
        } out;
 };
 
index 3719b2fdade63a50478a59a24d5f158c57b27f67..2468e4e8bf52de9e807df616edee99061b1de2d4 100644 (file)
        /*******************************************/
        /* 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;
                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;
 
        /*******************************************/
index 738e5d61c99bf5dacc7649c4511089ba689edefd..ddf9664b9b519964d75dc6cf3dc18fe9c33d464a 100644 (file)
@@ -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)
index 79af5967c754e7ac56186b6e04dfbc82e6f18234..7beb64942a29424b6e95922f88f0da373ffb7d53 100644 (file)
@@ -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
 */
index 23bb7f5ba003e353982f6e2de843a56bd06a9589..24cbc184add1637991d329c04cf001f6e89685eb 100644 (file)
@@ -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);
                }
        }