From 03e3cf9846bece4a38aa587d6864412235b8045b Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Thu, 22 May 2014 14:50:24 +0000 Subject: [PATCH] * ldap.cc (cyg_ldap::fetch_ad_account): Take additional domain string parameter. Convert into likely rootDSE string if not NULL, and use in subsequent call to ldap_search_stW. Add comment to explain that this is not the exactly correct solution. * ldap.h (cyg_ldap::fetch_ad_account): Change prototype accordingly. * uinfo.cc (pwdgrp::fetch_account_from_windows): Always use loc_ldap in call to fetch_posix_offset to make sure we're fetchoinmg the posix offsets from *our* domain controller. Only set domain variable to non-NULL if the account is from a trusted domain. Use domain in call to cyg_ldap::fetch_ad_account. --- winsup/cygwin/ChangeLog | 13 +++++++++++++ winsup/cygwin/ldap.cc | 30 +++++++++++++++++++++++++----- winsup/cygwin/ldap.h | 2 +- winsup/cygwin/uinfo.cc | 11 ++++------- 4 files changed, 43 insertions(+), 13 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 98ec62506..2975beef5 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,16 @@ +2014-05-22 Corinna Vinschen + + * ldap.cc (cyg_ldap::fetch_ad_account): Take additional domain string + parameter. Convert into likely rootDSE string if not NULL, and use in + subsequent call to ldap_search_stW. Add comment to explain that this + is not the exactly correct solution. + * ldap.h (cyg_ldap::fetch_ad_account): Change prototype accordingly. + * uinfo.cc (pwdgrp::fetch_account_from_windows): Always use loc_ldap + in call to fetch_posix_offset to make sure we're fetchoinmg the posix + offsets from *our* domain controller. Only set domain variable to + non-NULL if the account is from a trusted domain. Use domain in call + to cyg_ldap::fetch_ad_account. + 2014-05-22 Corinna Vinschen * gmon.h: Pull in profile.h. Explain why. diff --git a/winsup/cygwin/ldap.cc b/winsup/cygwin/ldap.cc index 8fde7c133..89f9b37f2 100644 --- a/winsup/cygwin/ldap.cc +++ b/winsup/cygwin/ldap.cc @@ -200,13 +200,14 @@ cyg_ldap::close () } bool -cyg_ldap::fetch_ad_account (PSID sid, bool group) +cyg_ldap::fetch_ad_account (PSID sid, bool group, PCWSTR domain) { - WCHAR filter[140], *f; + WCHAR filter[140], *f, *rdse = rootdse; LONG len = (LONG) RtlLengthSid (sid); PBYTE s = (PBYTE) sid; static WCHAR hex_wchars[] = L"0123456789abcdef"; ULONG ret; + tmp_pathbuf tp; if (msg) { @@ -226,17 +227,36 @@ cyg_ldap::fetch_ad_account (PSID sid, bool group) *f++ = hex_wchars[*s++ & 0xf]; } wcpcpy (f, L")"); + if (domain) + { + /* FIXME: This is a hack. The most correct solution is probably to + open a connection to the DC of the trusted domain. But this always + takes extra time, so we're trying to avoid it. If this results in + problems, we know what to do. */ + rdse = tp.w_get (); + PWCHAR r = rdse; + for (PWCHAR dotp = (PWCHAR) domain; dotp && *dotp; domain = dotp) + { + dotp = wcschr (domain, L'.'); + if (dotp) + *dotp++ = L'\0'; + if (r > rdse) + *r++ = L','; + r = wcpcpy (r, L"DC="); + r = wcpcpy (r, domain); + } + } attr = group ? group_attr : user_attr; - if ((ret = ldap_search_stW (lh, rootdse, LDAP_SCOPE_SUBTREE, filter, + if ((ret = ldap_search_stW (lh, rdse, LDAP_SCOPE_SUBTREE, filter, attr, 0, &tv, &msg)) != LDAP_SUCCESS) { debug_printf ("ldap_search_stW(%W,%W) error 0x%02x", - rootdse, filter, ret); + rdse, filter, ret); return false; } if (!(entry = ldap_first_entry (lh, msg))) { - debug_printf ("No entry for %W in rootdse %W", filter, rootdse); + debug_printf ("No entry for %W in rootdse %W", filter, rdse); return false; } return true; diff --git a/winsup/cygwin/ldap.h b/winsup/cygwin/ldap.h index 9d8a40346..a2bf0bde8 100644 --- a/winsup/cygwin/ldap.h +++ b/winsup/cygwin/ldap.h @@ -51,7 +51,7 @@ public: operator PLDAP () const { return lh; } bool open (PCWSTR in_domain); void close (); - bool fetch_ad_account (PSID sid, bool group); + bool fetch_ad_account (PSID sid, bool group, PCWSTR domain = NULL); bool enumerate_ad_accounts (PCWSTR domain, bool group); bool next_account (cygsid &sid); uint32_t fetch_posix_offset_for_domain (PCWSTR domain); diff --git a/winsup/cygwin/uinfo.cc b/winsup/cygwin/uinfo.cc index 409d0edbd..9c9428f64 100644 --- a/winsup/cygwin/uinfo.cc +++ b/winsup/cygwin/uinfo.cc @@ -1445,7 +1445,7 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, cyg_ldap *pldap) for (ULONG idx = 0; (td = cygheap->dom.trusted_domain (idx)); ++idx) { - fetch_posix_offset (td, cldap); + fetch_posix_offset (td, &loc_ldap); if (td->PosixOffset > posix_offset && td->PosixOffset <= arg.id) posix_offset = (this_td = td)->PosixOffset; } @@ -1501,7 +1501,6 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, cyg_ldap *pldap) #endif name_style = (cygheap->pg.nss_prefix_always ()) ? fully_qualified : plus_prepended; - domain = cygheap->dom.account_flat_name (); is_domain_account = false; } /* Account domain account? */ @@ -1511,7 +1510,6 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, cyg_ldap *pldap) if (cygheap->dom.member_machine () || !cygheap->pg.nss_prefix_auto ()) name_style = fully_qualified; - domain = cygheap->dom.account_flat_name (); is_domain_account = false; } /* Domain member machine? */ @@ -1530,7 +1528,6 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, cyg_ldap *pldap) later on. So, don't set domain here to non-NULL, unless you're sure you have also changed subsequent assumptions that domain is NULL if it's a primary domain account. */ - domain = NULL; if (!cygheap->pg.nss_prefix_auto ()) name_style = fully_qualified; } @@ -1547,7 +1544,7 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, cyg_ldap *pldap) { domain = td->DnsDomainName; posix_offset = - fetch_posix_offset (td, cldap); + fetch_posix_offset (td, &loc_ldap); break; } @@ -1593,7 +1590,7 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, cyg_ldap *pldap) /* Use LDAP to fetch domain account infos. */ if (!cldap->open (NULL)) break; - if (cldap->fetch_ad_account (sid, is_group ())) + if (cldap->fetch_ad_account (sid, is_group (), domain)) { PWCHAR val; @@ -1860,7 +1857,7 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, cyg_ldap *pldap) if (td->DomainSid && RtlEqualSid (sid, td->DomainSid)) { domain = td->NetbiosDomainName; - posix_offset = fetch_posix_offset (td, cldap); + posix_offset = fetch_posix_offset (td, &loc_ldap); break; } }