From ad8d295e7c02a289d11b7ab3e7c7e36af934adde Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Tue, 24 Feb 2015 20:52:57 +0000 Subject: [PATCH] * ldap.h: Remove index macros. (class cyg_ldap): Remove members srch_msg and srch_entry. (cyg_ldap::get_string_attribute): Remove private method taking index argument. (cyg_ldap::get_num_attribute): Ditto. Add method taking attribute name. (cyg_ldap::get_primary_gid): Adjust to aforementioned change. (cyg_ldap::get_unix_uid): Ditto. (cyg_ldap::get_unix_gid): Ditto. * ldap.cc: Throughout, use msg and entry in place of srch_msg and srch_entry. (std_user_attr): Add sAMAccountName and objectSid. (group_attr): Ditto. (cyg_ldap::close): Drop handling of srch_msg and srch_entry. (cyg_ldap::get_string_attribute): Move earlier in file. (cyg_ldap::get_num_attribute): Ditto. (cyg_ldap::enumerate_ad_accounts): Add comments for clarity. Use group_attr or user_attr rather than sid_attr to fetch all desired attributes for an account right away. (cyg_ldap::next_account): Store found SID in last_fetched_sid to skip calls to fetch_ad_account from fetch_account_from_windows. (cyg_ldap::get_string_attribute): Remove method taking index argument. (cyg_ldap::get_num_attribute): Ditto. * pwdgrp.h (class pg_ent): Fix formatting. Add member dom. * passwd.cc (pg_ent::enumerate_ad): Store current flat domain name in dom. Construct fetch_acc_t argument from LDAP attributes and call fetch_account_from_windows with that. * userinfo.h (enum fetch_user_arg_type_t): Rename FULL_grp_arg to FULL_acc_arg. Change throughout. (struct fetch_acc_t): Rename from fetch_full_grp_t. Change throughout. (struct fetch_user_arg_t): Rename full_grp to full_acc. Change throughout. --- winsup/cygwin/ChangeLog | 34 +++++++++++++++ winsup/cygwin/grp.cc | 18 ++++---- winsup/cygwin/ldap.cc | 93 ++++++++++++++++++++-------------------- winsup/cygwin/ldap.h | 24 ++++------- winsup/cygwin/passwd.cc | 20 +++++++-- winsup/cygwin/pwdgrp.h | 31 +++++++------- winsup/cygwin/uinfo.cc | 20 ++++----- winsup/cygwin/userinfo.h | 6 +-- 8 files changed, 144 insertions(+), 102 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 21a62461e..fc8b0d678 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,37 @@ +2015-02-24 Corinna Vinschen + + * ldap.h: Remove index macros. + (class cyg_ldap): Remove members srch_msg and srch_entry. + (cyg_ldap::get_string_attribute): Remove private method taking index + argument. + (cyg_ldap::get_num_attribute): Ditto. Add method taking attribute name. + (cyg_ldap::get_primary_gid): Adjust to aforementioned change. + (cyg_ldap::get_unix_uid): Ditto. + (cyg_ldap::get_unix_gid): Ditto. + * ldap.cc: Throughout, use msg and entry in place of srch_msg and + srch_entry. + (std_user_attr): Add sAMAccountName and objectSid. + (group_attr): Ditto. + (cyg_ldap::close): Drop handling of srch_msg and srch_entry. + (cyg_ldap::get_string_attribute): Move earlier in file. + (cyg_ldap::get_num_attribute): Ditto. + (cyg_ldap::enumerate_ad_accounts): Add comments for clarity. + Use group_attr or user_attr rather than sid_attr to fetch all desired + attributes for an account right away. + (cyg_ldap::next_account): Store found SID in last_fetched_sid to + skip calls to fetch_ad_account from fetch_account_from_windows. + (cyg_ldap::get_string_attribute): Remove method taking index argument. + (cyg_ldap::get_num_attribute): Ditto. + * pwdgrp.h (class pg_ent): Fix formatting. Add member dom. + * passwd.cc (pg_ent::enumerate_ad): Store current flat domain name + in dom. Construct fetch_acc_t argument from LDAP attributes and + call fetch_account_from_windows with that. + * userinfo.h (enum fetch_user_arg_type_t): Rename FULL_grp_arg to + FULL_acc_arg. Change throughout. + (struct fetch_acc_t): Rename from fetch_full_grp_t. Change throughout. + (struct fetch_user_arg_t): Rename full_grp to full_acc. Change + throughout. + 2015-02-24 Corinna Vinschen * fhandler.h (class fhandler_base): Add was_nonblocking status flag. diff --git a/winsup/cygwin/grp.cc b/winsup/cygwin/grp.cc index 676dd7672..5e5f1d810 100644 --- a/winsup/cygwin/grp.cc +++ b/winsup/cygwin/grp.cc @@ -145,35 +145,35 @@ internal_getgrsid_cachedonly (cygpsid &sid) for each group. This is quite a bit faster, especially in slower environments. */ static struct group * __attribute__((used)) -internal_getgrfull (fetch_full_grp_t &full_grp, cyg_ldap *pldap) +internal_getgrfull (fetch_acc_t &full_acc, cyg_ldap *pldap) { struct group *ret; cygheap->pg.nss_init (); /* Check caches first. */ if (cygheap->pg.nss_cygserver_caching () - && (ret = cygheap->pg.grp_cache.cygserver.find_group (full_grp.sid))) + && (ret = cygheap->pg.grp_cache.cygserver.find_group (full_acc.sid))) return ret; if (cygheap->pg.nss_grp_files () - && (ret = cygheap->pg.grp_cache.file.find_group (full_grp.sid))) + && (ret = cygheap->pg.grp_cache.file.find_group (full_acc.sid))) return ret; if (cygheap->pg.nss_grp_db () - && (ret = cygheap->pg.grp_cache.win.find_group (full_grp.sid))) + && (ret = cygheap->pg.grp_cache.win.find_group (full_acc.sid))) return ret; /* Ask sources afterwards. */ if (cygheap->pg.nss_cygserver_caching () && (ret = cygheap->pg.grp_cache.cygserver.add_group_from_cygserver - (full_grp.sid))) + (full_acc.sid))) return ret; if (cygheap->pg.nss_grp_files ()) { cygheap->pg.grp_cache.file.check_file (); if ((ret = cygheap->pg.grp_cache.file.add_group_from_file - (full_grp.sid))) + (full_acc.sid))) return ret; } if (cygheap->pg.nss_grp_db ()) - return cygheap->pg.grp_cache.win.add_group_from_windows (full_grp, pldap); + return cygheap->pg.grp_cache.win.add_group_from_windows (full_acc, pldap); return NULL; } @@ -647,14 +647,14 @@ internal_getgroups (int gidsetsize, gid_t *grouplist, cyg_ldap *pldap, { for (ULONG ncnt = 0; ncnt < scnt; ++ncnt) { - fetch_full_grp_t full_grp = + fetch_acc_t full_acc = { .sid = sidp_buf[ncnt], .name = &nlst[ncnt].Name, .dom = &dlst->Domains[nlst[ncnt].DomainIndex].Name, .acc_type = nlst[ncnt].Use }; - if ((grp = internal_getgrfull (full_grp, pldap))) + if ((grp = internal_getgrfull (full_acc, pldap))) { if (cnt < gidsetsize) grouplist[cnt] = grp->gr_gid; diff --git a/winsup/cygwin/ldap.cc b/winsup/cygwin/ldap.cc index 890ab38df..4935d467f 100644 --- a/winsup/cygwin/ldap.cc +++ b/winsup/cygwin/ldap.cc @@ -34,6 +34,8 @@ static PWCHAR rootdse_attr[] = static const PCWSTR std_user_attr[] = { + L"sAMAccountName", + L"objectSid", L"primaryGroupID", L"uidNumber", L"cygwinUnixUid", /* TODO */ @@ -55,7 +57,8 @@ static const PCWSTR std_user_attr[] = static PWCHAR group_attr[] = { - (PWCHAR) L"cn", + (PWCHAR) L"sAMAccountName", + (PWCHAR) L"objectSid", (PWCHAR) L"gidNumber", (PWCHAR) L"cygwinUnixGid", /* TODO */ NULL @@ -283,9 +286,9 @@ cyg_ldap::next_page_s () do { ret = ldap_get_next_page_s (lh, srch_id, NULL, CYG_LDAP_ENUM_PAGESIZE, - &total, &srch_msg); + &total, &msg); } - while (ret == LDAP_SUCCESS && ldap_count_entries (lh, srch_msg) == 0); + while (ret == LDAP_SUCCESS && ldap_count_entries (lh, msg) == 0); if (ret && ret != LDAP_NO_RESULTS_RETURNED) debug_printf ("ldap_result() error 0x%02x", ret); return ret; @@ -367,8 +370,6 @@ cyg_ldap::close () ldap_search_abandon_page (lh, srch_id); if (lh) ldap_unbind (lh); - if (srch_msg) - ldap_msgfree (srch_msg); if (msg) ldap_msgfree (msg); if (val) @@ -380,10 +381,29 @@ cyg_ldap::close () val = NULL; def_context = NULL; srch_id = NULL; - srch_msg = srch_entry = NULL; last_fetched_sid = NO_SID; } +PWCHAR +cyg_ldap::get_string_attribute (PCWSTR name) +{ + if (val) + ldap_value_freeW (val); + val = ldap_get_valuesW (lh, entry, (PWCHAR) name); + if (val) + return val[0]; + return NULL; +} + +uint32_t +cyg_ldap::get_num_attribute (PCWSTR name) +{ + PWCHAR ret = get_string_attribute (name); + if (ret) + return (uint32_t) wcstoul (ret, NULL, 10); + return (uint32_t) -1; +} + #define ACCOUNT_FILTER_START L"(&(|(&(objectCategory=Person)" \ "(objectClass=User))" \ "(objectClass=Group))" \ @@ -478,19 +498,26 @@ cyg_ldap::enumerate_ad_accounts (PCWSTR domain, bool group) if (!group) filter = L"(&(objectCategory=Person)" "(objectClass=User)" - /* 512 == ADS_UF_NORMAL_ACCOUNT */ + /* 512 == ADS_UF_NORMAL_ACCOUNT + Without checking this flag we'd enumerate undesired accounts + like, e.g., interdomain trusts. */ "(userAccountControl:" LDAP_MATCHING_RULE_BIT_AND ":=512)" "(objectSid=*))"; else if (!domain) + /* From the local domain, we fetch well-known groups. */ filter = L"(&(objectClass=Group)" "(objectSid=*))"; else + /* From foreign domains, we don't. */ filter = L"(&(objectClass=Group)" /* 1 == BUILTIN_LOCAL_GROUP */ "(!(groupType:" LDAP_MATCHING_RULE_BIT_AND ":=1))" "(objectSid=*))"; + if (!user_attr) + cygheap->pg.init_ldap_user_attr (); + attr = group ? group_attr : user_attr; srch_id = ldap_search_init_pageW (lh, def_context, LDAP_SCOPE_SUBTREE, - (PWCHAR) filter, sid_attr, 0, NULL, NULL, + (PWCHAR) filter, attr, 0, NULL, NULL, INFINITE, CYG_LDAP_ENUM_PAGESIZE, NULL); if (srch_id == NULL) { @@ -507,25 +534,25 @@ cyg_ldap::next_account (cygsid &sid) ULONG ret; PLDAP_BERVAL *bval; - if (srch_entry) + if (entry) { - if ((srch_entry = ldap_next_entry (lh, srch_entry)) - && (bval = ldap_get_values_lenW (lh, srch_entry, sid_attr[0]))) + if ((entry = ldap_next_entry (lh, entry)) + && (bval = ldap_get_values_lenW (lh, entry, (PWCHAR) L"objectSid"))) { - sid = (PSID) bval[0]->bv_val; + last_fetched_sid = sid = (PSID) bval[0]->bv_val; ldap_value_free_len (bval); return NO_ERROR; } - ldap_msgfree (srch_msg); - srch_msg = srch_entry = NULL; + ldap_msgfree (msg); + msg = entry = NULL; } ret = next_page (); if (ret == NO_ERROR) { - if ((srch_entry = ldap_first_entry (lh, srch_msg)) - && (bval = ldap_get_values_lenW (lh, srch_entry, sid_attr[0]))) + if ((entry = ldap_first_entry (lh, msg)) + && (bval = ldap_get_values_lenW (lh, entry, (PWCHAR) L"objectSid"))) { - sid = (PSID) bval[0]->bv_val; + last_fetched_sid = sid = (PSID) bval[0]->bv_val; ldap_value_free_len (bval); return NO_ERROR; } @@ -574,33 +601,7 @@ cyg_ldap::fetch_posix_offset_for_domain (PCWSTR domain) debug_printf ("No entry for %W in def_context %W", filter, def_context); return UINT32_MAX; } - return get_num_attribute (0); -} - -PWCHAR -cyg_ldap::get_string_attribute (PCWSTR name) -{ - if (val) - ldap_value_freeW (val); - val = ldap_get_valuesW (lh, entry, (PWCHAR) name); - if (val) - return val[0]; - return NULL; -} - -PWCHAR -cyg_ldap::get_string_attribute (int idx) -{ - return get_string_attribute (attr[idx]); -} - -uint32_t -cyg_ldap::get_num_attribute (int idx) -{ - PWCHAR ret = get_string_attribute (attr[idx]); - if (ret) - return (uint32_t) wcstoul (ret, NULL, 10); - return (uint32_t) -1; + return get_num_attribute (tdom_attr[0]); } #define UXID_FILTER_GRP L"(&(objectClass=Group)" \ @@ -625,7 +626,7 @@ cyg_ldap::fetch_unix_sid_from_ad (uint32_t id, cygsid &sid, bool group) if (search (def_context, LDAP_SCOPE_SUBTREE, filter, sid_attr) != 0) return false; if ((entry = ldap_first_entry (lh, msg)) - && (bval = ldap_get_values_lenW (lh, entry, sid_attr[0]))) + && (bval = ldap_get_values_lenW (lh, entry, (PWCHAR) L"objectSid"))) { sid = (PSID) bval[0]->bv_val; ldap_value_free_len (bval); @@ -664,7 +665,7 @@ cyg_ldap::fetch_unix_name_from_rfc2307 (uint32_t id, bool group) debug_printf ("No entry for %W in def_context %W", filter, def_context); return NULL; } - return get_string_attribute (0); + return get_string_attribute (attr[0]); } uid_t diff --git a/winsup/cygwin/ldap.h b/winsup/cygwin/ldap.h index 9209d854b..4b696df22 100644 --- a/winsup/cygwin/ldap.h +++ b/winsup/cygwin/ldap.h @@ -17,12 +17,6 @@ details. */ #include #pragma pop_macro ("DECLSPEC_IMPORT") -#define LDAP_USER_PGRP_ATTR 0 -#define LDAP_USER_UID_ATTR 1 - -#define LDAP_GROUP_NAME_ATTR 0 -#define LDAP_GROUP_GID_ATTR 1 - class cyg_ldap { PLDAP lh; PWCHAR def_context; @@ -31,7 +25,6 @@ class cyg_ldap { PWCHAR *attr; bool isAD; PLDAPSearch srch_id; - PLDAPMessage srch_msg, srch_entry; cygsid last_fetched_sid; inline int map_ldaperr_to_errno (ULONG lerr); @@ -41,13 +34,11 @@ class cyg_ldap { inline int next_page (); bool fetch_unix_sid_from_ad (uint32_t id, cygsid &sid, bool group); PWCHAR fetch_unix_name_from_rfc2307 (uint32_t id, bool group); - PWCHAR get_string_attribute (int idx); - uint32_t get_num_attribute (int idx); public: cyg_ldap () : lh (NULL), def_context (NULL), msg (NULL), entry (NULL), - val (NULL), isAD (false), srch_id (NULL), srch_msg (NULL), - srch_entry (NULL), last_fetched_sid (NO_SID) + val (NULL), isAD (false), srch_id (NULL), + last_fetched_sid (NO_SID) {} ~cyg_ldap () { close (); } @@ -60,6 +51,8 @@ public: operator PLDAP () const { return lh; } int open (PCWSTR in_domain); void close (); + PWCHAR get_string_attribute (PCWSTR name); + uint32_t get_num_attribute (PCWSTR name); bool fetch_ad_account (PSID sid, bool group, PCWSTR domain = NULL); int enumerate_ad_accounts (PCWSTR domain, bool group); int next_account (cygsid &sid); @@ -67,11 +60,10 @@ public: uid_t remap_uid (uid_t uid); gid_t remap_gid (gid_t gid); /* User only */ - gid_t get_primary_gid () { return get_num_attribute (LDAP_USER_PGRP_ATTR); } - gid_t get_unix_uid () { return get_num_attribute (LDAP_USER_UID_ATTR); } + gid_t get_primary_gid () { return get_num_attribute (L"primaryGroupID"); } + gid_t get_unix_uid () { return get_num_attribute (L"uidNumber"); } /* group only */ PWCHAR get_group_name () - { return get_string_attribute (LDAP_GROUP_NAME_ATTR); } - gid_t get_unix_gid () { return get_num_attribute (LDAP_GROUP_GID_ATTR); } - PWCHAR get_string_attribute (PCWSTR name); + { return get_string_attribute (L"sAMAccountName"); } + gid_t get_unix_gid () { return get_num_attribute (L"gidNumber"); } }; diff --git a/winsup/cygwin/passwd.cc b/winsup/cygwin/passwd.cc index b8ed09466..825b2e0a8 100644 --- a/winsup/cygwin/passwd.cc +++ b/winsup/cygwin/passwd.cc @@ -1,7 +1,7 @@ /* passwd.cc: getpwnam () and friends Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, - 2009, 2010, 2011, 2012, 2013, 2014 Red Hat, Inc. + 2009, 2010, 2011, 2012, 2013, 2014, 2015 Red Hat, Inc. This file is part of Cygwin. @@ -600,6 +600,7 @@ pg_ent::enumerate_ad () if (!nss_db_enum_primary () || cldap.enumerate_ad_accounts (NULL, group) != NO_ERROR) continue; + RtlInitUnicodeString (&dom, cygheap->dom.primary_flat_name ()); } else if ((td = cygheap->dom.trusted_domain (resume - 1))) { @@ -616,6 +617,7 @@ pg_ent::enumerate_ad () || cldap.enumerate_ad_accounts (td->DnsDomainName, group) != NO_ERROR) continue; + RtlInitUnicodeString (&dom, td->NetbiosDomainName); } else { @@ -628,9 +630,21 @@ pg_ent::enumerate_ad () int ret = cldap.next_account (sid); if (ret == NO_ERROR) { + fetch_acc_t full; fetch_user_arg_t arg; - arg.type = SID_arg; - arg.sid = &sid; + UNICODE_STRING name; + + arg.type = FULL_acc_arg; + arg.full_acc = &full; + full.sid = sid; + RtlInitUnicodeString (&name, + cldap.get_string_attribute (L"sAMAccountName")); + full.name = &name; + full.dom = &dom; + if (sid_sub_auth (sid, 0) == SECURITY_BUILTIN_DOMAIN_RID) + full.acc_type = SidTypeAlias; + else + full.acc_type = group ? SidTypeGroup : SidTypeUser; char *line = pg.fetch_account_from_windows (arg, &cldap); if (line) return pg.add_account_post_fetch (line, false); diff --git a/winsup/cygwin/pwdgrp.h b/winsup/cygwin/pwdgrp.h index ad2108063..fe0cd8b6b 100644 --- a/winsup/cygwin/pwdgrp.h +++ b/winsup/cygwin/pwdgrp.h @@ -159,7 +159,7 @@ public: { return (struct group *) add_account_from_windows (name, pldap); } struct group *add_group_from_windows (uint32_t id, cyg_ldap *pldap = NULL) { return (struct group *) add_account_from_windows (id, pldap); } - struct group *add_group_from_windows (fetch_full_grp_t &full_grp, + struct group *add_group_from_windows (fetch_acc_t &full_acc, cyg_ldap *pldap = NULL); struct group *find_group (cygpsid &sid); struct group *find_group (const char *name); @@ -169,20 +169,21 @@ public: class pg_ent { protected: - pwdgrp pg; - bool group; - pg_pwd pwd; - pg_grp grp; - NT_readline rl; - cyg_ldap cldap; - PCHAR buf; - ULONG cnt; - ULONG max; - ULONG_PTR resume; - int enums; /* ENUM_xxx values defined in sys/cygwin.h. */ - PCWSTR enum_tdoms; - bool from_files; - bool from_db; + pwdgrp pg; + bool group; + pg_pwd pwd; + pg_grp grp; + NT_readline rl; + cyg_ldap cldap; + PCHAR buf; + ULONG cnt; + ULONG max; + ULONG_PTR resume; + int enums; /* ENUM_xxx values defined in sys/cygwin.h. */ + PCWSTR enum_tdoms; + bool from_files; + bool from_db; + UNICODE_STRING dom; enum { rewound = 0, from_cache, diff --git a/winsup/cygwin/uinfo.cc b/winsup/cygwin/uinfo.cc index c24d528f3..9a17b397f 100644 --- a/winsup/cygwin/uinfo.cc +++ b/winsup/cygwin/uinfo.cc @@ -1547,11 +1547,11 @@ pwdgrp::add_account_from_windows (uint32_t id, cyg_ldap *pldap) /* Called from internal_getgrfull, in turn called from internal_getgroups. */ struct group * -pwdgrp::add_group_from_windows (fetch_full_grp_t &full_grp, cyg_ldap *pldap) +pwdgrp::add_group_from_windows (fetch_acc_t &full_acc, cyg_ldap *pldap) { fetch_user_arg_t arg; - arg.type = FULL_grp_arg; - arg.full_grp = &full_grp; + arg.type = FULL_acc_arg; + arg.full_acc = &full_acc; char *line = fetch_account_from_windows (arg, pldap); if (!line) return NULL; @@ -1759,14 +1759,14 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, cyg_ldap *pldap) switch (arg.type) { - case FULL_grp_arg: + case FULL_acc_arg: { - sid = arg.full_grp->sid; - *wcpncpy (name, arg.full_grp->name->Buffer, - arg.full_grp->name->Length / sizeof (WCHAR)) = L'\0'; - *wcpncpy (dom, arg.full_grp->dom->Buffer, - arg.full_grp->dom->Length / sizeof (WCHAR)) = L'\0'; - acc_type = arg.full_grp->acc_type; + sid = arg.full_acc->sid; + *wcpncpy (name, arg.full_acc->name->Buffer, + arg.full_acc->name->Length / sizeof (WCHAR)) = L'\0'; + *wcpncpy (dom, arg.full_acc->dom->Buffer, + arg.full_acc->dom->Length / sizeof (WCHAR)) = L'\0'; + acc_type = arg.full_acc->acc_type; ret = acc_type != SidTypeUnknown; } break; diff --git a/winsup/cygwin/userinfo.h b/winsup/cygwin/userinfo.h index ba957273e..dc7eb5658 100644 --- a/winsup/cygwin/userinfo.h +++ b/winsup/cygwin/userinfo.h @@ -14,12 +14,12 @@ enum fetch_user_arg_type_t { SID_arg, NAME_arg, ID_arg, - FULL_grp_arg, + FULL_acc_arg, }; #ifdef __INSIDE_CYGWIN__ -struct fetch_full_grp_t { +struct fetch_acc_t { cygpsid sid; PUNICODE_STRING name; PUNICODE_STRING dom; @@ -33,7 +33,7 @@ struct fetch_user_arg_t cygpsid *sid; const char *name; uint32_t id; - fetch_full_grp_t *full_grp; + fetch_acc_t *full_acc; }; /* Only used in fetch_account_from_file/line. */ size_t len;