From ba98dd4989db16028a2690d382ab178524ce765b Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 21 Apr 2008 19:26:32 +0200 Subject: libads: Use libnbt for CLDAP reply parsing. Guenther (This used to be commit 751f3064a508341c0ebae45e8de9f5311d915d70) --- source3/libads/cldap.c | 105 +++++-------------------------------------- source3/libads/ldap.c | 24 +++++----- source3/libsmb/dsgetdcname.c | 34 +++++++------- source3/utils/net_ads.c | 45 +++++++++---------- 4 files changed, 61 insertions(+), 147 deletions(-) diff --git a/source3/libads/cldap.c b/source3/libads/cldap.c index 39e736f28a..6068ca4faf 100644 --- a/source3/libads/cldap.c +++ b/source3/libads/cldap.c @@ -20,72 +20,6 @@ #include "includes.h" -/* - These seem to be strings as described in RFC1035 4.1.4 and can be: - - - a sequence of labels ending in a zero octet - - a pointer - - a sequence of labels ending with a pointer - - A label is a byte where the first two bits must be zero and the remaining - bits represent the length of the label followed by the label itself. - Therefore, the length of a label is at max 64 bytes. Under RFC1035, a - sequence of labels cannot exceed 255 bytes. - - A pointer consists of a 14 bit offset from the beginning of the data. - - struct ptr { - unsigned ident:2; // must be 11 - unsigned offset:14; // from the beginning of data - }; - - This is used as a method to compress the packet by eliminated duplicate - domain components. Since a UDP packet should probably be < 512 bytes and a - DNS name can be up to 255 bytes, this actually makes a lot of sense. -*/ -static unsigned pull_netlogon_string(char *ret, const char *ptr, - const char *data) -{ - char *pret = ret; - int followed_ptr = 0; - unsigned ret_len = 0; - - memset(pret, 0, MAX_DNS_LABEL); - do { - if ((*ptr & 0xc0) == 0xc0) { - uint16 len; - - if (!followed_ptr) { - ret_len += 2; - followed_ptr = 1; - } - len = ((ptr[0] & 0x3f) << 8) | ptr[1]; - ptr = data + len; - } else if (*ptr) { - uint8 len = (uint8)*(ptr++); - - if ((pret - ret + len + 1) >= MAX_DNS_LABEL) { - DEBUG(1,("DC returning too long DNS name\n")); - return 0; - } - - if (pret != ret) { - *pret = '.'; - pret++; - } - memcpy(pret, ptr, len); - pret += len; - ptr += len; - - if (!followed_ptr) { - ret_len += (len + 1); - } - } - } while (*ptr); - - return followed_ptr ? ret_len : ret_len + 1; -} - /* do a cldap netlogon query */ @@ -182,7 +116,7 @@ static void gotalarm_sig(void) /* receive a cldap netlogon reply */ -static int recv_cldap_netlogon(int sock, struct cldap_netlogon_reply *reply) +static int recv_cldap_netlogon(int sock, struct nbt_cldap_netlogon_5 *reply) { int ret; ASN1_DATA data; @@ -193,7 +127,8 @@ static int recv_cldap_netlogon(int sock, struct cldap_netlogon_reply *reply) int i1; /* half the time of a regular ldap timeout, not less than 3 seconds. */ unsigned int al_secs = MAX(3,lp_ldap_timeout()/2); - char *p; + union nbt_cldap_netlogon p; + enum ndr_err_code ndr_err; blob = data_blob(NULL, 8192); if (blob.data == NULL) { @@ -247,33 +182,17 @@ static int recv_cldap_netlogon(int sock, struct cldap_netlogon_reply *reply) return -1; } - p = (char *)os3.data; - - reply->type = IVAL(p, 0); p += 4; - reply->flags = IVAL(p, 0); p += 4; - - memcpy(&reply->guid.info, p, UUID_FLAT_SIZE); - p += UUID_FLAT_SIZE; - - p += pull_netlogon_string(reply->forest, p, (const char *)os3.data); - p += pull_netlogon_string(reply->domain, p, (const char *)os3.data); - p += pull_netlogon_string(reply->hostname, p, (const char *)os3.data); - p += pull_netlogon_string(reply->netbios_domain, p, (const char *)os3.data); - p += pull_netlogon_string(reply->netbios_hostname, p, (const char *)os3.data); - p += pull_netlogon_string(reply->unk, p, (const char *)os3.data); - - if (reply->type == SAMLOGON_AD_R) { - p += pull_netlogon_string(reply->user_name, p, (const char *)os3.data); - } else { - *reply->user_name = 0; + ndr_err = ndr_pull_union_blob_all(&os3, talloc_tos(), &p, 5, + (ndr_pull_flags_fn_t)ndr_pull_nbt_cldap_netlogon); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + return -1; } - p += pull_netlogon_string(reply->server_site_name, p, (const char *)os3.data); - p += pull_netlogon_string(reply->client_site_name, p, (const char *)os3.data); + *reply = p.logon5; - reply->version = IVAL(p, 0); - reply->lmnt_token = SVAL(p, 4); - reply->lm20_token = SVAL(p, 6); + if (DEBUGLEVEL >= 10) { + NDR_PRINT_UNION_DEBUG(nbt_cldap_netlogon, 5, &p); + } data_blob_free(&os1); data_blob_free(&os2); @@ -289,7 +208,7 @@ static int recv_cldap_netlogon(int sock, struct cldap_netlogon_reply *reply) do a cldap netlogon query. Always 389/udp *******************************************************************/ -bool ads_cldap_netlogon(const char *server, const char *realm, struct cldap_netlogon_reply *reply) +bool ads_cldap_netlogon(const char *server, const char *realm, struct nbt_cldap_netlogon_5 *reply) { int sock; int ret; diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c index a9eff48b3e..b4a977056e 100644 --- a/source3/libads/ldap.c +++ b/source3/libads/ldap.c @@ -176,7 +176,7 @@ bool ads_closest_dc(ADS_STRUCT *ads) bool ads_try_connect(ADS_STRUCT *ads, const char *server ) { char *srv; - struct cldap_netlogon_reply cldap_reply; + struct nbt_cldap_netlogon_5 cldap_reply; if (!server || !*server) { return False; @@ -199,7 +199,7 @@ bool ads_try_connect(ADS_STRUCT *ads, const char *server ) /* Check the CLDAP reply flags */ - if ( !(cldap_reply.flags & ADS_LDAP) ) { + if ( !(cldap_reply.server_type & ADS_LDAP) ) { DEBUG(1,("ads_try_connect: %s's CLDAP reply says it is not an LDAP server!\n", srv)); SAFE_FREE( srv ); @@ -215,20 +215,20 @@ bool ads_try_connect(ADS_STRUCT *ads, const char *server ) SAFE_FREE(ads->config.client_site_name); SAFE_FREE(ads->server.workgroup); - ads->config.flags = cldap_reply.flags; - ads->config.ldap_server_name = SMB_STRDUP(cldap_reply.hostname); - strupper_m(cldap_reply.domain); - ads->config.realm = SMB_STRDUP(cldap_reply.domain); + ads->config.flags = cldap_reply.server_type; + ads->config.ldap_server_name = SMB_STRDUP(cldap_reply.pdc_dns_name); + ads->config.realm = SMB_STRDUP(cldap_reply.dns_domain); + strupper_m(ads->config.realm); ads->config.bind_path = ads_build_dn(ads->config.realm); - if (*cldap_reply.server_site_name) { + if (*cldap_reply.server_site) { ads->config.server_site_name = - SMB_STRDUP(cldap_reply.server_site_name); + SMB_STRDUP(cldap_reply.server_site); } - if (*cldap_reply.client_site_name) { + if (*cldap_reply.client_site) { ads->config.client_site_name = - SMB_STRDUP(cldap_reply.client_site_name); + SMB_STRDUP(cldap_reply.client_site); } - ads->server.workgroup = SMB_STRDUP(cldap_reply.netbios_domain); + ads->server.workgroup = SMB_STRDUP(cldap_reply.domain); ads->ldap.port = LDAP_PORT; if (!interpret_string_addr(&ads->ldap.ss, srv, 0)) { @@ -242,7 +242,7 @@ bool ads_try_connect(ADS_STRUCT *ads, const char *server ) SAFE_FREE(srv); /* Store our site name. */ - sitename_store( cldap_reply.domain, cldap_reply.client_site_name ); + sitename_store( cldap_reply.domain, cldap_reply.client_site); return True; } diff --git a/source3/libsmb/dsgetdcname.c b/source3/libsmb/dsgetdcname.c index 00841f0684..531ab11622 100644 --- a/source3/libsmb/dsgetdcname.c +++ b/source3/libsmb/dsgetdcname.c @@ -196,7 +196,7 @@ static NTSTATUS dsgetdcname_cache_refresh(TALLOC_CTX *mem_ctx, const char *site_name, struct netr_DsRGetDCNameInfo *info) { - struct cldap_netlogon_reply r; + struct nbt_cldap_netlogon_5 r; /* check if matching entry is older then 15 minutes, if yes, send * CLDAP/MAILSLOT ping again and store the cached data */ @@ -606,12 +606,11 @@ static NTSTATUS process_dc_dns(TALLOC_CTX *mem_ctx, { int i = 0; bool valid_dc = false; - struct cldap_netlogon_reply r; + struct nbt_cldap_netlogon_5 r; const char *dc_hostname, *dc_domain_name; const char *dc_address; uint32_t dc_address_type; uint32_t dc_flags; - struct GUID dc_guid; for (i=0; ildap.ss); if ( !ads_cldap_netlogon(addr, ads->server.realm, &reply ) ) { @@ -106,8 +105,7 @@ static int net_ads_cldap_netlogon(ADS_STRUCT *ads) break; } - smb_uuid_unpack(reply.guid, &tmp_guid); - d_printf("GUID: %s\n", smb_uuid_string(talloc_tos(), tmp_guid)); + d_printf("GUID: %s\n", smb_uuid_string(talloc_tos(), reply.domain_uuid)); d_printf("Flags:\n" "\tIs a PDC: %s\n" @@ -120,31 +118,30 @@ static int net_ads_cldap_netlogon(ADS_STRUCT *ads) "\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"); + (reply.server_type & ADS_PDC) ? "yes" : "no", + (reply.server_type & ADS_GC) ? "yes" : "no", + (reply.server_type & ADS_LDAP) ? "yes" : "no", + (reply.server_type & ADS_DS) ? "yes" : "no", + (reply.server_type & ADS_KDC) ? "yes" : "no", + (reply.server_type & ADS_TIMESERV) ? "yes" : "no", + (reply.server_type & ADS_CLOSEST) ? "yes" : "no", + (reply.server_type & ADS_WRITABLE) ? "yes" : "no", + (reply.server_type & ADS_GOOD_TIMESERV) ? "yes" : "no", + (reply.server_type & ADS_NDNC) ? "yes" : "no"); printf("Forest:\t\t\t%s\n", reply.forest); - printf("Domain:\t\t\t%s\n", reply.domain); - printf("Domain Controller:\t%s\n", reply.hostname); + printf("Domain:\t\t\t%s\n", reply.dns_domain); + printf("Domain Controller:\t%s\n", reply.pdc_dns_name); - printf("Pre-Win2k Domain:\t%s\n", reply.netbios_domain); - printf("Pre-Win2k Hostname:\t%s\n", reply.netbios_hostname); + printf("Pre-Win2k Domain:\t%s\n", reply.domain); + printf("Pre-Win2k Hostname:\t%s\n", reply.pdc_name); - if (*reply.unk) printf("Unk:\t\t\t%s\n", reply.unk); if (*reply.user_name) printf("User name:\t%s\n", reply.user_name); - printf("Server Site Name :\t\t%s\n", reply.server_site_name); - printf("Client Site Name :\t\t%s\n", reply.client_site_name); + printf("Server Site Name :\t\t%s\n", reply.server_site); + printf("Client Site Name :\t\t%s\n", reply.client_site); - d_printf("NT Version: %d\n", reply.version); + d_printf("NT Version: %d\n", reply.nt_version); d_printf("LMNT Token: %.2x\n", reply.lmnt_token); d_printf("LM20 Token: %.2x\n", reply.lm20_token); @@ -379,7 +376,7 @@ static int net_ads_workgroup(int argc, const char **argv) { ADS_STRUCT *ads; char addr[INET6_ADDRSTRLEN]; - struct cldap_netlogon_reply reply; + struct nbt_cldap_netlogon_5 reply; if (!ADS_ERR_OK(ads_startup_nobind(False, &ads))) { d_fprintf(stderr, "Didn't find the cldap server!\n"); @@ -397,7 +394,7 @@ static int net_ads_workgroup(int argc, const char **argv) return -1; } - d_printf("Workgroup: %s\n", reply.netbios_domain); + d_printf("Workgroup: %s\n", reply.domain); ads_destroy(&ads); -- cgit