diff options
-rw-r--r-- | winsup/cygwin/ChangeLog | 20 | ||||
-rw-r--r-- | winsup/cygwin/autoload.cc | 2 | ||||
-rw-r--r-- | winsup/cygwin/cygheap.h | 38 | ||||
-rw-r--r-- | winsup/cygwin/fhandler_disk_file.cc | 8 | ||||
-rw-r--r-- | winsup/cygwin/pwdgrp.h | 39 | ||||
-rw-r--r-- | winsup/cygwin/sec_helper.cc | 8 | ||||
-rw-r--r-- | winsup/cygwin/uinfo.cc | 258 |
7 files changed, 192 insertions, 181 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index ee6da9755..c79a62684 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,23 @@ +2014-02-11 Corinna Vinschen <corinna@vinschen.de> + + * autoload.cc (NetLocalGroupGetInfo): Replace NetGroupGetInfo. + * cygheap.h (class cygheap_ugid_cache): Move ugid_cache_t type here + and rename. + (struct init_cygheap): Add cygheap_ugid_cache member "ugid_cache". + * pwdgrp.h (class ugid_cache_t): Remove here. + * fhandler_disk_file.cc (fhandler_base::fstat_by_nfs_ea): Accommodate + move of ugid_cache to cygheap. + * sec_helper.cc (get_sids_info): Ditto. + * uinfo.cc (ugid_cache): Remove. + (pwdgrp::fetch_account_from_windows): Define id_val globally. + Move SidTypeAlias handling into SidTypeUser/SidTypeGroup branch since + aliases are handled like groups in SAM. Accommodate move of ugid_cache + to cygheap. Consolidate code reading SAM comments into a single branch + for both, SidTypeUser and SidTypeAlias. For SidTypeAlias, fix thinko + and call NetLocalGroupGetInfo rather than NetGroupGetInfo. Simplify + code setting Cygwin primary group for SAM accounts. Add code to handle + UNIX uid/gid from SAM comment. + 2014-02-11 Christopher Faylor <me.cygwin2014@cgf.cx> * winsup.h (Interlocked*): Use intrinsic versions of Interlocked diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc index 15d185a84..1086bd872 100644 --- a/winsup/cygwin/autoload.cc +++ b/winsup/cygwin/autoload.cc @@ -610,7 +610,7 @@ LoadDLLfunc (WNetOpenEnumA, 20, mpr) LoadDLLfunc (DsEnumerateDomainTrustsW, 16, netapi32) LoadDLLfunc (DsGetDcNameW, 24, netapi32) LoadDLLfunc (NetApiBufferFree, 4, netapi32) -LoadDLLfunc (NetGroupGetInfo, 16, netapi32) +LoadDLLfunc (NetLocalGroupGetInfo, 16, netapi32) LoadDLLfunc (NetUseGetInfo, 16, netapi32) LoadDLLfunc (NetUserGetGroups, 28, netapi32) LoadDLLfunc (NetUserGetInfo, 16, netapi32) diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h index a6cfd9d44..9596161f3 100644 --- a/winsup/cygwin/cygheap.h +++ b/winsup/cygwin/cygheap.h @@ -434,6 +434,43 @@ public: inline bool nss_db_caching () const { return caching; } }; +class cygheap_ugid_cache +{ + struct idmap { + uint32_t nfs_id; + uint32_t cyg_id; + }; + class idmaps { + uint32_t _cnt; + uint32_t _max; + idmap *_map; + public: + uint32_t get (uint32_t id) const + { + for (uint32_t i = 0; i < _cnt; ++i) + if (_map[i].nfs_id == id) + return _map[i].cyg_id; + return (uint32_t) -1; + } + void add (uint32_t nfs_id, uint32_t cyg_id) + { + if (_cnt >= _max) + _map = (idmap *) crealloc (_map, (_max += 10) * sizeof (*_map)); + _map[_cnt].nfs_id = nfs_id; + _map[_cnt].cyg_id = cyg_id; + ++_cnt; + } + }; + idmaps uids; + idmaps gids; + +public: + uid_t get_uid (uid_t uid) const { return uids.get (uid); } + gid_t get_gid (gid_t gid) const { return gids.get (gid); } + void add_uid (uid_t nfs_uid, uid_t cyg_uid) { uids.add (nfs_uid, cyg_uid); } + void add_gid (gid_t nfs_gid, gid_t cyg_gid) { gids.add (nfs_gid, cyg_gid); } +}; + struct hook_chain { void **loc; @@ -459,6 +496,7 @@ struct init_cygheap: public mini_cygheap cygheap_root root; cygheap_domain_info dom; cygheap_pwdgrp pg; + cygheap_ugid_cache ugid_cache; cygheap_user user; user_heap_info user_heap; mode_t umask; diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc index aea390508..a44bfb8b6 100644 --- a/winsup/cygwin/fhandler_disk_file.cc +++ b/winsup/cygwin/fhandler_disk_file.cc @@ -347,8 +347,8 @@ fhandler_base::fstat_by_nfs_ea (struct stat *buf) the cache, try to fetch it from the configured RFC 2307 domain (see last comment in cygheap_domain_info::init() for more information) and add it to the mapping cache. */ - buf->st_uid = ugid_cache.get_uid (nfs_attr->uid); - buf->st_gid = ugid_cache.get_gid (nfs_attr->gid); + buf->st_uid = cygheap->ugid_cache.get_uid (nfs_attr->uid); + buf->st_gid = cygheap->ugid_cache.get_gid (nfs_attr->gid); if (buf->st_uid == ILLEGAL_UID) { uid_t map_uid = ILLEGAL_UID; @@ -358,7 +358,7 @@ fhandler_base::fstat_by_nfs_ea (struct stat *buf) map_uid = cldap.remap_uid (nfs_attr->uid); if (map_uid == ILLEGAL_UID) map_uid = MAP_UNIX_TO_CYGWIN_ID (nfs_attr->uid); - ugid_cache.add_uid (nfs_attr->uid, map_uid); + cygheap->ugid_cache.add_uid (nfs_attr->uid, map_uid); buf->st_uid = map_uid; } if (buf->st_gid == ILLEGAL_GID) @@ -370,7 +370,7 @@ fhandler_base::fstat_by_nfs_ea (struct stat *buf) map_gid = cldap.remap_gid (nfs_attr->gid); if (map_gid == ILLEGAL_GID) map_gid = MAP_UNIX_TO_CYGWIN_ID (nfs_attr->gid); - ugid_cache.add_gid (nfs_attr->gid, map_gid); + cygheap->ugid_cache.add_gid (nfs_attr->gid, map_gid); buf->st_gid = map_gid; } buf->st_rdev = makedev (nfs_attr->rdev.specdata1, diff --git a/winsup/cygwin/pwdgrp.h b/winsup/cygwin/pwdgrp.h index a93d2b979..4ed245104 100644 --- a/winsup/cygwin/pwdgrp.h +++ b/winsup/cygwin/pwdgrp.h @@ -141,42 +141,3 @@ public: struct group *find_group (const char *name); struct group *find_group (gid_t gid); }; - -class ugid_cache_t -{ - struct idmap { - uint32_t nfs_id; - uint32_t cyg_id; - }; - class idmaps { - uint32_t _cnt; - uint32_t _max; - idmap *_map; - public: - idmaps () : _cnt (0), _max (0), _map (NULL) {} - uint32_t get (uint32_t id) const - { - for (uint32_t i = 0; i < _cnt; ++i) - if (_map[i].nfs_id == id) - return _map[i].cyg_id; - return (uint32_t) -1; - } - void add (uint32_t nfs_id, uint32_t cyg_id) - { - if (_cnt >= _max) - _map = (idmap *) realloc (_map, (_max += 10) * sizeof (*_map)); - _map[_cnt].nfs_id = nfs_id; - _map[_cnt].cyg_id = cyg_id; - ++_cnt; - } - }; - idmaps uids; - idmaps gids; - -public: - uid_t get_uid (uid_t uid) const { return uids.get (uid); } - gid_t get_gid (gid_t gid) const { return gids.get (gid); } - void add_uid (uid_t nfs_uid, uid_t cyg_uid) { uids.add (nfs_uid, cyg_uid); } - void add_gid (gid_t nfs_gid, gid_t cyg_gid) { gids.add (nfs_gid, cyg_gid); } -}; -extern ugid_cache_t ugid_cache; diff --git a/winsup/cygwin/sec_helper.cc b/winsup/cygwin/sec_helper.cc index 8aeac2e5b..8a31693f1 100644 --- a/winsup/cygwin/sec_helper.cc +++ b/winsup/cygwin/sec_helper.cc @@ -314,7 +314,7 @@ get_sids_info (cygpsid owner_sid, cygpsid group_sid, uid_t * uidret, gid_t * gid last comment in cygheap_domain_info::init() for more information) and add it to the mapping cache. */ gid_t gid = sid_sub_auth_rid (group_sid); - gid_t map_gid = ugid_cache.get_gid (gid); + gid_t map_gid = cygheap->ugid_cache.get_gid (gid); if (map_gid == ILLEGAL_GID) { domain = cygheap->dom.get_rfc2307_domain (); @@ -322,7 +322,7 @@ get_sids_info (cygpsid owner_sid, cygpsid group_sid, uid_t * uidret, gid_t * gid map_gid = cldap.remap_gid (gid); if (map_gid == ILLEGAL_GID) map_gid = MAP_UNIX_TO_CYGWIN_ID (gid); - ugid_cache.add_gid (gid, map_gid); + cygheap->ugid_cache.add_gid (gid, map_gid); } *gidret = map_gid; } @@ -343,7 +343,7 @@ get_sids_info (cygpsid owner_sid, cygpsid group_sid, uid_t * uidret, gid_t * gid { /* Samba UNIX user. See comment above. */ uid_t uid = sid_sub_auth_rid (owner_sid); - uid_t map_uid = ugid_cache.get_uid (uid); + uid_t map_uid = cygheap->ugid_cache.get_uid (uid); if (map_uid == ILLEGAL_UID) { domain = cygheap->dom.get_rfc2307_domain (); @@ -351,7 +351,7 @@ get_sids_info (cygpsid owner_sid, cygpsid group_sid, uid_t * uidret, gid_t * gid map_uid = cldap.remap_uid (uid); if (map_uid == ILLEGAL_UID) map_uid = MAP_UNIX_TO_CYGWIN_ID (uid); - ugid_cache.add_uid (uid, map_uid); + cygheap->ugid_cache.add_uid (uid, map_uid); } *uidret = map_uid; } diff --git a/winsup/cygwin/uinfo.cc b/winsup/cygwin/uinfo.cc index d522b9f7b..2bf10ac7f 100644 --- a/winsup/cygwin/uinfo.cc +++ b/winsup/cygwin/uinfo.cc @@ -548,8 +548,6 @@ pwdgrp::add_line (char *eptr) return eptr; } -ugid_cache_t ugid_cache; - void cygheap_pwdgrp::init () { @@ -1100,6 +1098,7 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group) WCHAR sidstr[128]; /* Temporary stuff. */ ULONG posix_offset = 0; + uint32_t id_val; cyg_ldap cldap; bool ldap_open = false; @@ -1240,8 +1239,6 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group) Skip primary domain. */ if (!td->PosixOffset && !(td->Flags & DS_DOMAIN_PRIMARY)) { - uint32_t id_val; - if (!ldap_open && !(ldap_open = cldap.open (NULL))) id_val = cygheap->dom.lowest_tdo_posix_offset - 0x01000000; @@ -1287,18 +1284,29 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group) if a process is running as LocalSystem service. */ if (acc_type == SidTypeUser && sid_sub_auth_count (sid) <= 3) acc_type = SidTypeWellKnownGroup; - /* Alias? There are two types, the builtin aliases like "Administrators" - and the local groups in SAM. Handle local groups as groups. */ - else if (acc_type == SidTypeAlias - && sid_sub_auth (sid, 0) == SECURITY_NT_NON_UNIQUE) - acc_type = SidTypeGroup; - switch (acc_type) { case SidTypeUser: case SidTypeGroup: + case SidTypeAlias: + /* Predefined alias? */ + if (acc_type == SidTypeAlias + && sid_sub_auth (sid, 0) != SECURITY_NT_NON_UNIQUE) + { +#ifdef INTERIX_COMPATIBLE + posix_offset = 0x30000; + uid = 0x1000 * sid_sub_auth (sid, 0) + + (sid_sub_auth_rid (sid) & 0xffff); +#else + posix_offset = 0; +#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? */ - if (!wcscmp (dom, cygheap->dom.account_flat_name ())) + else if (!wcscmp (dom, cygheap->dom.account_flat_name ())) { posix_offset = 0x30000; if (cygheap->dom.member_machine () @@ -1345,8 +1353,6 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group) fetch it. */ if (!posix_offset) { - uint32_t id_val; - if (!ldap_open && !(ldap_open = cldap.open (NULL))) { /* We're probably running under a local account, @@ -1385,7 +1391,8 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group) return NULL; } /* Generate values. */ - uid = posix_offset + sid_sub_auth_rid (sid); + if (uid == ILLEGAL_UID) + uid = posix_offset + sid_sub_auth_rid (sid); gid = posix_offset + DOMAIN_GROUP_RID_USERS; /* Default. */ if (is_domain_account) @@ -1396,9 +1403,7 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group) if (cldap.fetch_ad_account (sid, group)) { PWCHAR val; - uint32_t id_val; - - if (!group) + if (acc_type == SidTypeUser) { if ((id_val = cldap.get_primary_gid ()) != ILLEGAL_GID) gid = posix_offset + id_val; @@ -1419,10 +1424,11 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group) id mapping on the fly. */ id_val = cldap.get_unix_uid (); if (id_val != ILLEGAL_UID - && ugid_cache.get_uid (id_val) == ILLEGAL_UID) - ugid_cache.add_uid (id_val, uid); + && cygheap->ugid_cache.get_uid (id_val) + == ILLEGAL_UID) + cygheap->ugid_cache.add_uid (id_val, uid); } - else + else /* SidTypeGroup */ { if ((val = cldap.get_group_name ()) && wcscmp (name, val)) @@ -1430,136 +1436,124 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group) * sizeof (WCHAR)), val); id_val = cldap.get_unix_gid (); if (id_val != ILLEGAL_GID - && ugid_cache.get_gid (id_val) == ILLEGAL_GID) - ugid_cache.add_gid (id_val, uid); + && cygheap->ugid_cache.get_gid (id_val) + == ILLEGAL_GID) + cygheap->ugid_cache.add_gid (id_val, uid); } } } /* Otherwise check account domain (local SAM).*/ - else if (acc_type == SidTypeUser) + else { NET_API_STATUS nas; PUSER_INFO_4 ui; - - nas = NetUserGetInfo (domain, name, 4, (PBYTE *) &ui); - if (nas != NERR_Success) - debug_printf ("NetUserGetInfo(%W,%W) %u", domain, name, nas); - else + PLOCALGROUP_INFO_1 gi; + PCWSTR comment; + PWCHAR pgrp = NULL; + PWCHAR uxid = NULL; + struct { + PCWSTR str; + size_t len; + PWCHAR *tgt; + bool group; + } search[] = { + { L"name=\"", 6, &user, true }, + { L"unix=\"", 6, &uxid, true }, + { L"home=\"", 6, &home, false }, + { L"shell=\"", 7, &shell, false }, + { L"group=\"", 7, &pgrp, false }, + { NULL, 0, NULL } + }; + PWCHAR s, e; + + if (acc_type == SidTypeUser) { - PWCHAR pgrp = NULL; - struct { - PCWSTR str; - size_t len; - PWCHAR *tgt; - } search[] = { - { L"name=\"", 6, &user }, - { L"home=\"", 6, &home }, - { L"shell=\"", 7, &shell }, - { L"group=\"", 7, &pgrp } - }; - PWCHAR s, e; - - /* Fetch primary group. */ - gid = posix_offset + ui->usri4_primary_group_id; - /* Local SAM accounts have only a handful attributes - available to home users. Therefore, fetch different - Cygwin user name, Cygwin home dir, and Cygwin login - shell from the "Description" field in XML short - style. */ - if ((s = wcsstr (ui->usri4_comment, L"<cygwin ")) - && (e = wcsstr (s + 8, L"/>"))) + nas = NetUserGetInfo (NULL, name, 4, (PBYTE *) &ui); + if (nas != NERR_Success) { - s += 8; - *e = L'\0'; - while (*s) - { - while (*s == L' ') - ++s; - for (size_t i = 0; - i < sizeof search / sizeof search[0]; - ++i) - if (!wcsncmp (s, search[i].str, search[i].len)) - { - s += search[i].len; - if ((e = wcschr (s, L'"')) - && (i > 0 || wcsncmp (name, s, e - s))) - { - *search[i].tgt = - (PWCHAR) alloca ((e - s + 1) - * sizeof (WCHAR)); - *wcpncpy (*search[i].tgt, s, e - s) = L'\0'; - s = e + 1; - } - else - { - *s = L'\0'; - break; - } - } - } + debug_printf ("NetUserGetInfo(%W) %u", name, nas); + break; } - NetApiBufferFree (ui); - if (pgrp) + /* Set comment variable for below attribute loop. */ + comment = ui->usri4_comment; + } + else /* SidTypeGroup || SidTypeAlias */ + { + nas = NetLocalGroupGetInfo (NULL, name, 1, (PBYTE *) &gi); + if (nas != NERR_Success) { - /* For setting the primary group, we have to test all - three possible Cygwin name variations: - - MACHINE+group, +group, group - */ - char gname[2 * (DNLEN + UNLEN + 1)]; - char *sep; - struct group *gr; - - sep += sys_wcstombs (sep = gname, 2 * DNLEN + 1, domain); - *sep = cygheap->pg.nss_separator ()[0]; - sys_wcstombs (sep + 1, 2 * UNLEN + 1, pgrp); - if ((gr = internal_getgrnam (gname)) - || (gr = internal_getgrnam (sep)) - || (gr = internal_getgrnam (sep + 1))) - gid = gr->gr_gid; + debug_printf ("NetLocalGroupGetInfo(%W) %u", name, nas); + break; } + /* Set comment variable for below attribute loop. */ + comment = gi->lgrpi1_comment; } - } - else /* SidTypeGroup */ - { - NET_API_STATUS nas; - PGROUP_INFO_3 gi; - - nas = NetGroupGetInfo (domain, name, 3, (PBYTE *) &gi); - if (nas != NERR_Success) - debug_printf ("NetGroupGetInfo(%W,%W) %u", domain, name, nas); + /* Local SAM accounts have only a handful attributes + available to home users. Therefore, fetch additional + passwd/group attributes from the "Description" field + in XML short style. */ + if ((s = wcsstr (comment, L"<cygwin ")) + && (e = wcsstr (s + 8, L"/>"))) + { + s += 8; + *e = L'\0'; + while (*s) + { + bool found = false; + + while (*s == L' ') + ++s; + for (size_t i = 0; search[i].str; ++i) + if ((acc_type == SidTypeUser || search[i].group) + && !wcsncmp (s, search[i].str, search[i].len)) + { + s += search[i].len; + if ((e = wcschr (s, L'"')) + && (i > 0 || wcsncmp (name, s, e - s))) + { + *search[i].tgt = + (PWCHAR) alloca ((e - s + 1) + * sizeof (WCHAR)); + *wcpncpy (*search[i].tgt, s, e - s) = L'\0'; + s = e + 1; + found = true; + } + else + break; + } + if (!found) + break; + } + } + if (acc_type == SidTypeUser) + NetApiBufferFree (ui); else + NetApiBufferFree (gi); + if (pgrp) { - PWCHAR s, e; - - /* Fetch different Cygwin group name from description. */ - if ((s = wcsstr (gi->grpi3_comment, L"<cygwin ")) - && (e = wcsstr (s + 8, L"/>"))) + /* For setting the primary group, we have to test + with and without prepended separator. */ + char gname[2 * UNLEN + 2]; + struct group *gr; + + *gname = cygheap->pg.nss_separator ()[0]; + sys_wcstombs (gname + 1, 2 * UNLEN + 1, pgrp); + if ((gr = internal_getgrnam (gname)) + || (gr = internal_getgrnam (gname + 1))) + gid = gr->gr_gid; + } + if (uxid && ((id_val = wcstoul (uxid, &e, 10)), !*e)) + { + if (acc_type == SidTypeUser) { - s += 8; - *e = L'\0'; - while (*s) - { - while (*s == L' ') - ++s; - if (!wcsncmp (s, L"name=\"", 6)) - { - s += 6; - if ((e = wcschr (s, L'"'))) - { - *wcpncpy (name = namebuf, s, e - s) = L'\0'; - s = e + 1; - } - else - break; - } - } + if (cygheap->ugid_cache.get_uid (id_val) == ILLEGAL_UID) + cygheap->ugid_cache.add_uid (id_val, uid); } - NetApiBufferFree (gi); + else if (cygheap->ugid_cache.get_gid (id_val) == ILLEGAL_GID) + cygheap->ugid_cache.add_gid (id_val, uid); } } break; - case SidTypeAlias: case SidTypeWellKnownGroup: name_style = (cygheap->pg.nss_prefix_always ()) ? fully_qualified : plus_prepended; @@ -1569,8 +1563,7 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group) { uid = 0x1000 * sid_sub_auth (sid, 0) + (sid_sub_auth_rid (sid) & 0xffff); - if (sid_sub_auth (sid, 0) > SECURITY_BUILTIN_DOMAIN_RID) - name_style = fully_qualified; + name_style = fully_qualified; } else uid = 0x10000 + 0x100 * sid_id_auth (sid) @@ -1585,7 +1578,6 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group) { uid = 0x1000 * sid_sub_auth (sid, 0) + (sid_sub_auth_rid (sid) & 0xffff); - //name_style = fully_qualified; } #endif /* Special case for "Everyone". We don't want to return Everyone |