[PATCH] More CLDAP changes (last round hopefully)

Anthony Liguori aliguor at us.ibm.com
Thu Feb 27 20:20:41 GMT 2003


Last round of changes to the Samba CLDAP code.  Every byte is now 
accounted for in the response packet so we shouldn't have anymore parsing 
errors.  It should apply cleanly against HEAD.

Index: source/utils/net_ads_cldap.c
===================================================================
RCS file: /cvsroot/samba/source/utils/net_ads_cldap.c,v
retrieving revision 1.6
diff -u -r1.6 net_ads_cldap.c
--- source/utils/net_ads_cldap.c        12 Nov 2002 23:15:52 -0000 1.6
+++ source/utils/net_ads_cldap.c        26 Feb 2003 22:57:53 -0000
@@ -2,6 +2,7 @@
    Samba Unix/Linux SMB client library 
    net ads cldap functions 
    Copyright (C) 2001 Andrew Tridgell (tridge at samba.org)
+   Copyright (C) 2003 Jim McDonough (jmcd at us.ibm.com)
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -23,60 +24,69 @@
 
 #ifdef HAVE_ADS
 
+struct netlogon_string {
+       uint32 comp_len;
+       char **component;
+       uint8 extra_flag;
+};
+
 struct cldap_netlogon_reply {
-       uint32 version;
+       uint32 type;
        uint32 flags;
        GUID guid;
-       char *domain;
-       char *server_name;
-       char *domain_flatname;
-       char *server_flatname;
-       char *dns_name;
-       uint32 unknown2[2];
-};
 
+       struct netlogon_string forest;
+       struct netlogon_string domain;
+       struct netlogon_string hostname;
 
-/*
-  pull a length prefixed string from a packet
-  return number of bytes consumed
-*/
-static unsigned pull_len_string(char **ret, const char *p)
-{
-       unsigned len = *p;
-       (*ret) = NULL;
-       if (len == 0) return 1;
-       (*ret) = smb_xstrndup(p+1, len);
-       return len+1;
-}
+       struct netlogon_string netbios_domain;
+       struct netlogon_string netbios_hostname;
+
+       struct netlogon_string user_name;
+       struct netlogon_string site_name;
+
+       struct netlogon_string unk0;
+
+       uint32 version;
+       uint16 lmnt_token;
+       uint16 lm20_token;
+};
 
 /*
-  pull a dotted string from a packet
-  return number of bytes consumed
+  These strings are rather interesting... They are composed of a series 
of
+  length encoded strings, terminated by either 1) a zero length string or 
2)
+  a 0xc0 byte with what appears to be a one byte flags immediately 
following.
 */
-static unsigned pull_dotted_string(char **ret, const char *p)
+static unsigned pull_netlogon_string(struct netlogon_string *ret,const 
char *d)
 {
-       char *s;
-       unsigned len, total_len=0;
+       char *s, *p = (char *)d;
 
-       (*ret) = NULL;
+       ZERO_STRUCTP(ret);
 
-       while ((len = pull_len_string(&s, p)) > 1) {
-               if (total_len) {
-                       char *s2;
-                       asprintf(&s2, "%s.%s", *ret, s);
-                       SAFE_FREE(*ret);
-                       (*ret) = s2;
+       do {
+               unsigned len = (unsigned char)*p;
+               p++;
+
+               if (len > 0 && len != 0xc0) {
+                       ret->component = realloc(ret->component,
+                                                ++ret->comp_len *
+                                                sizeof(char *));
+
+                       ret->component[ret->comp_len - 1] = 
+                               smb_xstrndup(p, len);
+                       p += len;
                } else {
-                       (*ret) = s;
+                       if (len == 0xc0) {
+                               ret->extra_flag = *p;
+                               p++;
+                       };
+                       break;
                }
-               total_len += len;
-               p += len;
-       }
+       } while (1);
 
-       return total_len + 1;
+       return (p - d);
 }
 
-
 /*
   do a cldap netlogon query
 */
@@ -190,19 +200,25 @@
 
        p = os3.data;
 
-       reply->version = IVAL(p, 0); p += 4;
+       reply->type = IVAL(p, 0); p += 4;
        reply->flags = IVAL(p, 0); p += 4;
+
        memcpy(&reply->guid.info, p, GUID_SIZE);
        p += GUID_SIZE;
-       p += pull_dotted_string(&reply->domain, p);
-       p += 2; /* 0xc018 - whats this? */
-       p += pull_len_string(&reply->server_name, p);
-       p += 2; /* 0xc018 - whats this? */
-       p += pull_len_string(&reply->domain_flatname, p);
-       p += 1;
-       p += pull_len_string(&reply->server_flatname, p);
-       p += 2;
-       p += pull_len_string(&reply->dns_name, p);
+
+       p += pull_netlogon_string(&reply->forest, p);
+       p += pull_netlogon_string(&reply->domain, p);
+       p += pull_netlogon_string(&reply->hostname, p);
+       p += pull_netlogon_string(&reply->netbios_domain, p);
+       p += pull_netlogon_string(&reply->netbios_hostname, p);
+       p += pull_netlogon_string(&reply->user_name, p);
+       p += pull_netlogon_string(&reply->site_name, p);
+
+       p += pull_netlogon_string(&reply->unk0, p);
+
+       reply->version = IVAL(p, 0);
+       reply->lmnt_token = SVAL(p, 4);
+       reply->lm20_token = SVAL(p, 6);
 
        data_blob_free(&os1);
        data_blob_free(&os2);
@@ -212,17 +228,49 @@
        return 0;
 }
 
+/*
+  free a netlogon string
+*/
+static void netlogon_string_free(struct netlogon_string *str)
+{
+       int i;
+
+       for (i = 0; i < str->comp_len; ++i) {
+               SAFE_FREE(str->component[i]);
+       }
+       SAFE_FREE(str->component);
+}
 
 /*
   free a cldap reply packet
 */
 static void cldap_reply_free(struct cldap_netlogon_reply *reply)
 {
-       SAFE_FREE(reply->domain);
-       SAFE_FREE(reply->server_name);
-       SAFE_FREE(reply->domain_flatname);
-       SAFE_FREE(reply->server_flatname);
-       SAFE_FREE(reply->dns_name);
+       netlogon_string_free(&reply->forest);
+       netlogon_string_free(&reply->domain);
+       netlogon_string_free(&reply->hostname);
+       netlogon_string_free(&reply->netbios_domain);
+       netlogon_string_free(&reply->netbios_hostname);
+       netlogon_string_free(&reply->user_name);
+       netlogon_string_free(&reply->site_name);
+       netlogon_string_free(&reply->unk0);
+}
+
+void d_print_netlogon_string(const char *label, struct netlogon_string 
*str)
+{
+       int i;
+
+       if (str->comp_len) {
+               d_printf("%s", label);
+               if (str->extra_flag) {
+                       d_printf("[%d]", str->extra_flag);
+               }
+               d_printf(": ");
+               for (i = 0; i < str->comp_len; ++i) {
+                       d_printf("%s%s", (i ? "." : ""), 
str->component[i]);
+               }
+               d_printf("\n");
+       }
 }
 
 /*
@@ -246,7 +294,6 @@
        if (ret != 0) {
                return ret;
        }
-
        ret = recv_cldap_netlogon(sock, &reply);
        close(sock);
 
@@ -254,15 +301,48 @@
                return -1;
        }
 
-       d_printf("Version: 0x%x\n", reply.version);
+       d_printf("Information for Domain Controller: %s\n\n", 
+                ads->config.ldap_server_name);
+
+       d_printf("Response Type: 0x%x\n", reply.type);
        d_printf("GUID: "); 
        print_guid(&reply.guid);
-       d_printf("Flags:   0x%x\n", reply.flags);
-       d_printf("Domain: %s\n", reply.domain);
-       d_printf("Server Name: %s\n", reply.server_name);
-       d_printf("Flatname: %s\n", reply.domain_flatname);
-       d_printf("Server Name2: %s\n", reply.server_flatname);
-       d_printf("DNS Name: %s\n", reply.dns_name);
+       d_printf("Flags:\n"
+                "\tIs a PDC:                                   %s\n"
+                "\tIs a GC of the forest:                      %s\n"
+                "\tIs an LDAP server:                          %s\n"
+                "\tSupports DS:                                %s\n"
+                "\tIs running a KDC:                           %s\n"
+                "\tIs running time services:                   %s\n"
+                "\tIs the closest DC:                          %s\n"
+                "\tIs writable:                                %s\n"
+                "\tHas a hardware clock:                       %s\n"
+                "\tIs a non-domain NC serviced by LDAP server: %s\n",
+                (reply.flags & ADS_PDC) ? "yes" : "no",
+                (reply.flags & ADS_GC) ? "yes" : "no",
+                (reply.flags & ADS_LDAP) ? "yes" : "no",
+                (reply.flags & ADS_DS) ? "yes" : "no",
+                (reply.flags & ADS_KDC) ? "yes" : "no",
+                (reply.flags & ADS_TIMESERV) ? "yes" : "no",
+                (reply.flags & ADS_CLOSEST) ? "yes" : "no",
+                (reply.flags & ADS_WRITABLE) ? "yes" : "no",
+                (reply.flags & ADS_GOOD_TIMESERV) ? "yes" : "no",
+                (reply.flags & ADS_NDNC) ? "yes" : "no");
+
+       d_print_netlogon_string("Forest", &reply.forest);
+       d_print_netlogon_string("Domain", &reply.domain);
+       d_print_netlogon_string("Hostname", &reply.hostname);
+
+       d_print_netlogon_string("Pre-Win2k Domain", 
&reply.netbios_domain);
+       d_print_netlogon_string("Pre-Win2k Hostname", 
&reply.netbios_hostname);
+
+       d_print_netlogon_string("User name", &reply.user_name);
+       d_print_netlogon_string("Site Name", &reply.site_name);
+       d_print_netlogon_string("Unknown Field", &reply.unk0);
+
+       d_printf("NT Version: %d\n", reply.version);
+       d_printf("LMNT Token: %0.2x\n", reply.lmnt_token);
+       d_printf("LM20 Token: %0.2x\n", reply.lm20_token);
 
        cldap_reply_free(&reply);
 

Anthony Liguori
Linux/Active Directory Interoperability
Linux Technology Center (LTC) - IBM Austin
E-mail: aliguor at us.ibm.com
Phone: (512) 838-1208
Tie Line: 678-1208


More information about the samba-technical mailing list