From b39fa2c88da849c7a0bd6a745357b57690501e3d Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Thu, 27 Feb 2014 12:57:27 +0000 Subject: [PATCH] * autoload.cc (CheckTokenMembership): Import. * external.cc (cygwin_internal): Call get_uid/get_gid instead of get_id. * grp.cc (internal_getgrsid): Take additional cyg_ldap pointer. Forward to pwdgrp::add_group_from_windows. (internal_getgrnam): Ditto. (internal_getgrgid): Ditto. (gr_ent::enumerate_local): Drop ugid_caching bool from call to pwdgrp::fetch_account_from_windows. (getgroups32): Rename from internal_getgroups and drop getgroups32 stub. Drop srchsid parameter and code handling it. Add local cyg_ldap instance and forward to internal_getgrXXX. (getgroups): Call getgroups32. (get_groups): Add local cyg_ldap instance and forward to internal_getgrXXX. (getgrouplist): Ditto. (setgroups32): Ditto. * ldap.cc (cyg_ldap::open): Don't call close. Return true if connection is already open. (cyg_ldap::remap_uid): Forward this to internal_getpwsid. (cyg_ldap::remap_gid): Forward this to internal_getgrsid. * passwd.cc (internal_getpwsid): Take additional cyg_ldap pointer. Forward to pwdgrp::add_user_from_windows. (internal_getpwnam): Ditto. (internal_getpwuid): Ditto. (pg_ent::enumerate_builtin): Drop ugid_caching bool from call to pwdgrp::fetch_account_from_windows. (pg_ent::enumerate_sam): Ditto. (pg_ent::enumerate_ad): Ditto. Forward local cldap instead. * pwdgrp.h (internal_getpwsid): Align declaration to above change. (internal_getpwnam): Ditto. (internal_getpwuid): Ditto. (internal_getgrsid): Ditto. (internal_getgrgid): Ditto. (internal_getgrnam): Ditto. (internal_getgroups): Drop declaration. (pwdgrp::add_account_from_windows): Align declaration to below change. (pwdgrp::add_user_from_windows): Ditto. (pwdgrp::add_group_from_windows): Ditto. * sec_acl.cc (setacl): Add local cyg_ldap instance and forward to internal_getpwuid and internal_getgrgid. (getacl): Add local cyg_ldap instance and forward to cygpsid::get_id. (aclfromtext32): Add local cyg_ldap instance and forward to internal_getpwnam and internal_getgrnam. * sec_helper.cc (cygpsid::get_id): Take additional cyg_ldap pointer. Forward to internal_getgrsid and internal_getpwsid. (get_sids_info): Drop ldap_open. Forward local cldap to internal_getpwsid and internal_getgrXXX. Call CheckTokenMembership rather than internal_getgroups. * security.h (cygpsid::get_id): Add cyg_ldap pointer, drop default parameter. (cygpsid::get_uid): Add cyg_ldap pointer. Call get_id accordingly. (cygpsid::get_gid): Ditto. * uinfo.cc (internal_getlogin): Add local cyg_ldap instance and forward to internal_getpwXXX and internal_getgrXXX calls. (pwdgrp::add_account_from_windows): Take additional cyg_ldap pointer. Forward to pwdgrp::fetch_account_from_windows. (fetch_posix_offset): Drop ldap_open argument and handling. Get cyg_ldap instance as pointer. (pwdgrp::fetch_account_from_windows): Take additional cyg_ldap pointer. Use it if it's not NULL, local instance otherwise. Drop ldap_open. Drop fetching extended group arguments from AD for speed. --- winsup/cygwin/ChangeLog | 64 +++++++++++++++++ winsup/cygwin/autoload.cc | 1 + winsup/cygwin/external.cc | 4 +- winsup/cygwin/grp.cc | 87 ++++++++++------------- winsup/cygwin/ldap.cc | 9 ++- winsup/cygwin/passwd.cc | 18 ++--- winsup/cygwin/pwdgrp.h | 58 ++++++++-------- winsup/cygwin/sec_acl.cc | 17 +++-- winsup/cygwin/sec_helper.cc | 27 ++++---- winsup/cygwin/security.h | 8 ++- winsup/cygwin/uinfo.cc | 134 ++++++++++++++++-------------------- 11 files changed, 238 insertions(+), 189 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 492e3594c..5ba1e3e9d 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,67 @@ +2014-02-27 Corinna Vinschen + + * autoload.cc (CheckTokenMembership): Import. + * external.cc (cygwin_internal): Call get_uid/get_gid instead of get_id. + * grp.cc (internal_getgrsid): Take additional cyg_ldap pointer. + Forward to pwdgrp::add_group_from_windows. + (internal_getgrnam): Ditto. + (internal_getgrgid): Ditto. + (gr_ent::enumerate_local): Drop ugid_caching bool from call to + pwdgrp::fetch_account_from_windows. + (getgroups32): Rename from internal_getgroups and drop getgroups32 stub. + Drop srchsid parameter and code handling it. Add local cyg_ldap + instance and forward to internal_getgrXXX. + (getgroups): Call getgroups32. + (get_groups): Add local cyg_ldap instance and forward to + internal_getgrXXX. + (getgrouplist): Ditto. + (setgroups32): Ditto. + * ldap.cc (cyg_ldap::open): Don't call close. Return true if connection + is already open. + (cyg_ldap::remap_uid): Forward this to internal_getpwsid. + (cyg_ldap::remap_gid): Forward this to internal_getgrsid. + * passwd.cc (internal_getpwsid): Take additional cyg_ldap pointer. + Forward to pwdgrp::add_user_from_windows. + (internal_getpwnam): Ditto. + (internal_getpwuid): Ditto. + (pg_ent::enumerate_builtin): Drop ugid_caching bool from call to + pwdgrp::fetch_account_from_windows. + (pg_ent::enumerate_sam): Ditto. + (pg_ent::enumerate_ad): Ditto. Forward local cldap instead. + * pwdgrp.h (internal_getpwsid): Align declaration to above change. + (internal_getpwnam): Ditto. + (internal_getpwuid): Ditto. + (internal_getgrsid): Ditto. + (internal_getgrgid): Ditto. + (internal_getgrnam): Ditto. + (internal_getgroups): Drop declaration. + (pwdgrp::add_account_from_windows): Align declaration to below change. + (pwdgrp::add_user_from_windows): Ditto. + (pwdgrp::add_group_from_windows): Ditto. + * sec_acl.cc (setacl): Add local cyg_ldap instance and forward to + internal_getpwuid and internal_getgrgid. + (getacl): Add local cyg_ldap instance and forward to cygpsid::get_id. + (aclfromtext32): Add local cyg_ldap instance and forward to + internal_getpwnam and internal_getgrnam. + * sec_helper.cc (cygpsid::get_id): Take additional cyg_ldap pointer. + Forward to internal_getgrsid and internal_getpwsid. + (get_sids_info): Drop ldap_open. Forward local cldap to + internal_getpwsid and internal_getgrXXX. Call CheckTokenMembership + rather than internal_getgroups. + * security.h (cygpsid::get_id): Add cyg_ldap pointer, drop default + parameter. + (cygpsid::get_uid): Add cyg_ldap pointer. Call get_id accordingly. + (cygpsid::get_gid): Ditto. + * uinfo.cc (internal_getlogin): Add local cyg_ldap instance and forward + to internal_getpwXXX and internal_getgrXXX calls. + (pwdgrp::add_account_from_windows): Take additional cyg_ldap pointer. + Forward to pwdgrp::fetch_account_from_windows. + (fetch_posix_offset): Drop ldap_open argument and handling. Get + cyg_ldap instance as pointer. + (pwdgrp::fetch_account_from_windows): Take additional cyg_ldap pointer. + Use it if it's not NULL, local instance otherwise. Drop ldap_open. + Drop fetching extended group arguments from AD for speed. + 2014-02-27 Corinna Vinschen * path.cc (find_fast_cwd_pointer): Fix preceeding comment. diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc index 65999de46..822a30a44 100644 --- a/winsup/cygwin/autoload.cc +++ b/winsup/cygwin/autoload.cc @@ -536,6 +536,7 @@ wsock_init () LoadDLLprime (ws2_32, _wsock_init, 0) +LoadDLLfunc (CheckTokenMembership, 12, advapi32) LoadDLLfunc (CreateProcessAsUserW, 44, advapi32) LoadDLLfunc (DeregisterEventSource, 4, advapi32) LoadDLLfunc (LogonUserW, 24, advapi32) diff --git a/winsup/cygwin/external.cc b/winsup/cygwin/external.cc index a99cfef33..8eec5b1db 100644 --- a/winsup/cygwin/external.cc +++ b/winsup/cygwin/external.cc @@ -380,13 +380,13 @@ cygwin_internal (cygwin_getinfo_types t, ...) case CW_GET_UID_FROM_SID: { cygpsid psid = va_arg (arg, PSID); - res = psid.get_id (false, NULL); + res = psid.get_uid (NULL); } break; case CW_GET_GID_FROM_SID: { cygpsid psid = va_arg (arg, PSID); - res = psid.get_id (true, NULL); + res = psid.get_gid (NULL); } break; case CW_GET_BINMODE: diff --git a/winsup/cygwin/grp.cc b/winsup/cygwin/grp.cc index 2ced0678e..31bfeda2b 100644 --- a/winsup/cygwin/grp.cc +++ b/winsup/cygwin/grp.cc @@ -117,7 +117,7 @@ pwdgrp::find_group (gid_t gid) } struct group * -internal_getgrsid (cygpsid &sid) +internal_getgrsid (cygpsid &sid, cyg_ldap *pldap) { struct group *ret; @@ -134,7 +134,7 @@ internal_getgrsid (cygpsid &sid) { if ((ret = cygheap->pg.grp_cache.win.find_group (sid))) return ret; - return cygheap->pg.grp_cache.win.add_group_from_windows (sid); + return cygheap->pg.grp_cache.win.add_group_from_windows (sid, pldap); } return NULL; } @@ -148,7 +148,7 @@ internal_getgrsid_from_db (cygpsid &sid) } struct group * -internal_getgrnam (const char *name) +internal_getgrnam (const char *name, cyg_ldap *pldap) { struct group *ret; @@ -165,13 +165,13 @@ internal_getgrnam (const char *name) { if ((ret = cygheap->pg.grp_cache.win.find_group (name))) return ret; - return cygheap->pg.grp_cache.win.add_group_from_windows (name); + return cygheap->pg.grp_cache.win.add_group_from_windows (name, pldap); } return NULL; } struct group * -internal_getgrgid (gid_t gid) +internal_getgrgid (gid_t gid, cyg_ldap *pldap) { struct group *ret; @@ -191,7 +191,7 @@ internal_getgrgid (gid_t gid) return cygheap->pg.grp_cache.win.add_group_from_windows (gid); } else if (gid == ILLEGAL_GID) - return cygheap->pg.grp_cache.win.add_group_from_windows (gid); + return cygheap->pg.grp_cache.win.add_group_from_windows (gid, pldap); return NULL; } @@ -389,7 +389,7 @@ gr_ent::enumerate_local () fetch_user_arg_t arg; arg.type = SID_arg; arg.sid = &sid; - char *line = pg.fetch_account_from_windows (arg, true, false); + char *line = pg.fetch_account_from_windows (arg, true); if (line) return pg.add_account_post_fetch (line, false); } @@ -459,19 +459,21 @@ endgrent_filtered (void *gr) ((gr_ent *) gr)->endgrent (); } -int -internal_getgroups (int gidsetsize, gid_t *grouplist, cygpsid *srchsid) +extern "C" int +getgroups32 (int gidsetsize, gid_t *grouplist) { NTSTATUS status; - HANDLE hToken = NULL; + HANDLE tok; ULONG size; int cnt = 0; struct group *grp; + cyg_ldap cldap; - if (!srchsid && cygheap->user.groups.issetgroups ()) + if (cygheap->user.groups.issetgroups ()) { for (int pg = 0; pg < cygheap->user.groups.sgsids.count (); ++pg) - if ((grp = internal_getgrsid (cygheap->user.groups.sgsids.sids[pg]))) + if ((grp = internal_getgrsid (cygheap->user.groups.sgsids.sids[pg], + &cldap))) { if (cnt < gidsetsize) grouplist[cnt] = grp->gr_gid; @@ -483,45 +485,32 @@ internal_getgroups (int gidsetsize, gid_t *grouplist, cygpsid *srchsid) } /* If impersonated, use impersonation token. */ - if (cygheap->user.issetuid ()) - hToken = cygheap->user.primary_token (); - else - hToken = hProcToken; + tok = cygheap->user.issetuid () ? cygheap->user.primary_token () : hProcToken; - status = NtQueryInformationToken (hToken, TokenGroups, NULL, 0, &size); + status = NtQueryInformationToken (tok, TokenGroups, NULL, 0, &size); if (NT_SUCCESS (status) || status == STATUS_BUFFER_TOO_SMALL) { PTOKEN_GROUPS groups = (PTOKEN_GROUPS) alloca (size); - status = NtQueryInformationToken (hToken, TokenGroups, groups, - size, &size); + status = NtQueryInformationToken (tok, TokenGroups, groups, size, &size); if (NT_SUCCESS (status)) { cygsid sid; - if (srchsid) + for (DWORD pg = 0; pg < groups->GroupCount; ++pg) { - for (DWORD pg = 0; pg < groups->GroupCount; ++pg) - if ((cnt = (*srchsid == groups->Groups[pg].Sid))) - break; - } - else - { - for (DWORD pg = 0; pg < groups->GroupCount; ++pg) + cygpsid sid = groups->Groups[pg].Sid; + if ((grp = internal_getgrsid (sid, &cldap))) { - cygpsid sid = groups->Groups[pg].Sid; - if ((grp = internal_getgrsid (sid))) + if ((groups->Groups[pg].Attributes + & (SE_GROUP_ENABLED | SE_GROUP_INTEGRITY_ENABLED)) + && sid != well_known_world_sid) { - if ((groups->Groups[pg].Attributes - & (SE_GROUP_ENABLED | SE_GROUP_INTEGRITY_ENABLED)) - && sid != well_known_world_sid) - { - if (cnt < gidsetsize) - grouplist[cnt] = grp->gr_gid; - ++cnt; - if (gidsetsize && cnt > gidsetsize) - goto error; - } + if (cnt < gidsetsize) + grouplist[cnt] = grp->gr_gid; + ++cnt; + if (gidsetsize && cnt > gidsetsize) + goto error; } } } @@ -536,12 +525,6 @@ error: return -1; } -extern "C" int -getgroups32 (int gidsetsize, gid_t *grouplist) -{ - return internal_getgroups (gidsetsize, grouplist); -} - #ifdef __x86_64__ EXPORT_ALIAS (getgroups32, getgroups) #else @@ -558,7 +541,7 @@ getgroups (int gidsetsize, __gid16_t *grouplist) if (gidsetsize > 0 && grouplist) grouplist32 = (gid_t *) alloca (gidsetsize * sizeof (gid_t)); - int ret = internal_getgroups (gidsetsize, grouplist32); + int ret = getgroups32 (gidsetsize, grouplist32); if (gidsetsize > 0 && grouplist) for (int i = 0; i < ret; ++ i) @@ -572,9 +555,11 @@ getgroups (int gidsetsize, __gid16_t *grouplist) static void get_groups (const char *user, gid_t gid, cygsidlist &gsids) { + cyg_ldap cldap; + cygheap->user.deimpersonate (); - struct passwd *pw = internal_getpwnam (user); - struct group *grp = internal_getgrgid (gid); + struct passwd *pw = internal_getpwnam (user, &cldap); + struct group *grp = internal_getgrgid (gid, &cldap); cygsid usersid, grpsid; if (usersid.getfrompw (pw)) get_server_groups (gsids, usersid, pw); @@ -614,6 +599,7 @@ getgrouplist (const char *user, gid_t gid, gid_t *groups, int *ngroups) int ret = 0; int cnt = 0; struct group *grp; + cyg_ldap cldap; /* Note that it's not defined if groups or ngroups may be NULL! GLibc does not check the pointers on entry and just uses them. @@ -626,7 +612,7 @@ getgrouplist (const char *user, gid_t gid, gid_t *groups, int *ngroups) cygsidlist tmp_gsids (cygsidlist_auto, 12); get_groups (user, gid, tmp_gsids); for (int i = 0; i < tmp_gsids.count (); i++) - if ((grp = internal_getgrsid (tmp_gsids.sids[i])) != NULL) + if ((grp = internal_getgrsid (tmp_gsids.sids[i], &cldap)) != NULL) { if (groups && cnt < *ngroups) groups[cnt] = grp->gr_gid; @@ -656,13 +642,14 @@ setgroups32 (int ngroups, const gid_t *grouplist) cygsidlist gsids (cygsidlist_alloc, ngroups); struct group *grp; + cyg_ldap cldap; if (ngroups && !gsids.sids) return -1; for (int gidx = 0; gidx < ngroups; ++gidx) { - if ((grp = internal_getgrgid (grouplist[gidx])) + if ((grp = internal_getgrgid (grouplist[gidx], &cldap)) && gsids.addfromgr (grp)) continue; debug_printf ("No sid found for gid %u", grouplist[gidx]); diff --git a/winsup/cygwin/ldap.cc b/winsup/cygwin/ldap.cc index 740995a61..cb16b9de8 100644 --- a/winsup/cygwin/ldap.cc +++ b/winsup/cygwin/ldap.cc @@ -145,7 +145,10 @@ cyg_ldap::open (PCWSTR domain) static LARGE_INTEGER last_rediscover; ULONG ret; - close (); + /* Already open? */ + if (lh) + return true; + GetSystemTimeAsFileTime ((LPFILETIME) &start); /* FIXME? connect_ssl can take ages even when failing, so we're trying to do everything the non-SSL (but still encrypted) way. */ @@ -512,7 +515,7 @@ cyg_ldap::remap_uid (uid_t uid) { if (fetch_unix_sid_from_ad (uid, user, false) && user != NO_SID - && (pw = internal_getpwsid (user))) + && (pw = internal_getpwsid (user, this))) return pw->pw_uid; } else if ((name = fetch_unix_name_from_rfc2307 (uid, false))) @@ -536,7 +539,7 @@ cyg_ldap::remap_gid (gid_t gid) { if (fetch_unix_sid_from_ad (gid, group, true) && group != NO_SID - && (gr = internal_getgrsid (group))) + && (gr = internal_getgrsid (group, this))) return gr->gr_gid; } else if ((name = fetch_unix_name_from_rfc2307 (gid, true))) diff --git a/winsup/cygwin/passwd.cc b/winsup/cygwin/passwd.cc index 1a5564904..d27f424b1 100644 --- a/winsup/cygwin/passwd.cc +++ b/winsup/cygwin/passwd.cc @@ -101,7 +101,7 @@ pwdgrp::find_user (uid_t uid) } struct passwd * -internal_getpwsid (cygpsid &sid) +internal_getpwsid (cygpsid &sid, cyg_ldap *pldap) { struct passwd *ret; @@ -118,7 +118,7 @@ internal_getpwsid (cygpsid &sid) { if ((ret = cygheap->pg.pwd_cache.win.find_user (sid))) return ret; - return cygheap->pg.pwd_cache.win.add_user_from_windows (sid); + return cygheap->pg.pwd_cache.win.add_user_from_windows (sid, pldap); } return NULL; } @@ -132,7 +132,7 @@ internal_getpwsid_from_db (cygpsid &sid) } struct passwd * -internal_getpwnam (const char *name) +internal_getpwnam (const char *name, cyg_ldap *pldap) { struct passwd *ret; @@ -149,13 +149,13 @@ internal_getpwnam (const char *name) { if ((ret = cygheap->pg.pwd_cache.win.find_user (name))) return ret; - return cygheap->pg.pwd_cache.win.add_user_from_windows (name); + return cygheap->pg.pwd_cache.win.add_user_from_windows (name, pldap); } return NULL; } struct passwd * -internal_getpwuid (uid_t uid) +internal_getpwuid (uid_t uid, cyg_ldap *pldap) { struct passwd *ret; @@ -172,7 +172,7 @@ internal_getpwuid (uid_t uid) { if ((ret = cygheap->pg.pwd_cache.win.find_user (uid))) return ret; - return cygheap->pg.pwd_cache.win.add_user_from_windows (uid); + return cygheap->pg.pwd_cache.win.add_user_from_windows (uid, pldap); } else if (uid == ILLEGAL_UID) return cygheap->pg.pwd_cache.win.add_user_from_windows (uid); @@ -500,7 +500,7 @@ pg_ent::enumerate_builtin () fetch_user_arg_t arg; arg.type = SID_arg; arg.sid = &sid; - char *line = pg.fetch_account_from_windows (arg, group, false); + char *line = pg.fetch_account_from_windows (arg, group); return pg.add_account_post_fetch (line, false); } @@ -547,7 +547,7 @@ pg_ent::enumerate_sam () fetch_user_arg_t arg; arg.type = SID_arg; arg.sid = &sid; - char *line = pg.fetch_account_from_windows (arg, group, false); + char *line = pg.fetch_account_from_windows (arg, group); if (line) return pg.add_account_post_fetch (line, false); } @@ -596,7 +596,7 @@ pg_ent::enumerate_ad () fetch_user_arg_t arg; arg.type = SID_arg; arg.sid = &sid; - char *line = pg.fetch_account_from_windows (arg, group, false); + char *line = pg.fetch_account_from_windows (arg, group, &cldap); if (line) return pg.add_account_post_fetch (line, false); } diff --git a/winsup/cygwin/pwdgrp.h b/winsup/cygwin/pwdgrp.h index 808bddb9f..5a8267cea 100644 --- a/winsup/cygwin/pwdgrp.h +++ b/winsup/cygwin/pwdgrp.h @@ -12,17 +12,20 @@ details. */ #pragma once +#include "sync.h" +#include "ldap.h" +#include "miscfuncs.h" + /* These functions are needed to allow searching and walking through the passwd and group lists */ -extern struct passwd *internal_getpwsid (cygpsid &); +extern struct passwd *internal_getpwsid (cygpsid &, cyg_ldap * = NULL); extern struct passwd *internal_getpwsid_from_db (cygpsid &sid); -extern struct passwd *internal_getpwnam (const char *); -extern struct passwd *internal_getpwuid (uid_t); -extern struct group *internal_getgrsid (cygpsid &); +extern struct passwd *internal_getpwnam (const char *, cyg_ldap * = NULL); +extern struct passwd *internal_getpwuid (uid_t, cyg_ldap * = NULL); +extern struct group *internal_getgrsid (cygpsid &, cyg_ldap * = NULL); extern struct group *internal_getgrsid_from_db (cygpsid &sid); -extern struct group *internal_getgrgid (gid_t); -extern struct group *internal_getgrnam (const char *); -int internal_getgroups (int, gid_t *, cygpsid * = NULL); +extern struct group *internal_getgrgid (gid_t, cyg_ldap * = NULL); +extern struct group *internal_getgrnam (const char *, cyg_ldap * = NULL); /* These functions are called from mkpasswd/mkgroup via cygwin_internal. */ void *setpwent_filtered (int enums, PCWSTR enum_tdoms); @@ -32,10 +35,6 @@ void *setgrent_filtered (int enums, PCWSTR enum_tdoms); void *getgrent_filtered (void *gr); void endgrent_filtered (void *gr); -#include "sync.h" -#include "ldap.h" -#include "miscfuncs.h" - enum fetch_user_arg_type_t { SID_arg, NAME_arg, @@ -107,13 +106,16 @@ class pwdgrp void *add_account_from_file (cygpsid &sid); void *add_account_from_file (const char *name); void *add_account_from_file (uint32_t id); - void *add_account_from_windows (cygpsid &sid, bool group); - void *add_account_from_windows (const char *name, bool group); - void *add_account_from_windows (uint32_t id, bool group); + void *add_account_from_windows (cygpsid &sid, bool group, + cyg_ldap *pldap = NULL); + void *add_account_from_windows (const char *name, bool group, + cyg_ldap *pldap = NULL); + void *add_account_from_windows (uint32_t id, bool group, + cyg_ldap *pldap = NULL); char *fetch_account_from_line (fetch_user_arg_t &arg, const char *line); char *fetch_account_from_file (fetch_user_arg_t &arg); char *fetch_account_from_windows (fetch_user_arg_t &arg, bool group, - bool ugid_caching = true); + cyg_ldap *pldap = NULL); pwdgrp *prep_tls_pwbuf (); pwdgrp *prep_tls_grbuf (); @@ -131,12 +133,13 @@ public: { return (struct passwd *) add_account_from_file (name); } struct passwd *add_user_from_file (uint32_t id) { return (struct passwd *) add_account_from_file (id); } - struct passwd *add_user_from_windows (cygpsid &sid) - { return (struct passwd *) add_account_from_windows (sid, false); } - struct passwd *add_user_from_windows (const char *name) - { return (struct passwd *) add_account_from_windows (name, false); } - struct passwd *add_user_from_windows (uint32_t id) - { return (struct passwd *) add_account_from_windows (id, false); } + struct passwd *add_user_from_windows (cygpsid &sid, cyg_ldap *pldap = NULL) + { return (struct passwd *) add_account_from_windows (sid, false, pldap); } + struct passwd *add_user_from_windows (const char *name, + cyg_ldap* pldap = NULL) + { return (struct passwd *) add_account_from_windows (name, false, pldap); } + struct passwd *add_user_from_windows (uint32_t id, cyg_ldap *pldap = NULL) + { return (struct passwd *) add_account_from_windows (id, false, pldap); } struct passwd *find_user (cygpsid &sid); struct passwd *find_user (const char *name); struct passwd *find_user (uid_t uid); @@ -149,12 +152,13 @@ public: { return (struct group *) add_account_from_file (name); } struct group *add_group_from_file (uint32_t id) { return (struct group *) add_account_from_file (id); } - struct group *add_group_from_windows (cygpsid &sid) - { return (struct group *) add_account_from_windows (sid, true); } - struct group *add_group_from_windows (const char *name) - { return (struct group *) add_account_from_windows (name, true); } - struct group *add_group_from_windows (uint32_t id) - { return (struct group *) add_account_from_windows (id, true); } + struct group *add_group_from_windows (cygpsid &sid, cyg_ldap *pldap = NULL) + { return (struct group *) add_account_from_windows (sid, true, pldap); } + struct group *add_group_from_windows (const char *name, + cyg_ldap *pldap = NULL) + { return (struct group *) add_account_from_windows (name, true, pldap); } + struct group *add_group_from_windows (uint32_t id, cyg_ldap *pldap = NULL) + { return (struct group *) add_account_from_windows (id, true, pldap); } struct group *find_group (cygpsid &sid); struct group *find_group (const char *name); struct group *find_group (gid_t gid); diff --git a/winsup/cygwin/sec_acl.cc b/winsup/cygwin/sec_acl.cc index 099df061c..ec5876099 100644 --- a/winsup/cygwin/sec_acl.cc +++ b/winsup/cygwin/sec_acl.cc @@ -94,6 +94,7 @@ setacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp, struct passwd *pw; struct group *gr; int pos; + cyg_ldap cldap; RtlCreateAcl (acl, ACL_MAXIMUM_SIZE, ACL_REVISION); @@ -157,7 +158,7 @@ setacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp, break; case USER: case DEF_USER: - if (!(pw = internal_getpwuid (aclbufp[i].a_id)) + if (!(pw = internal_getpwuid (aclbufp[i].a_id, &cldap)) || !sid.getfrompw (pw)) { set_errno (EINVAL); @@ -179,7 +180,7 @@ setacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp, break; case GROUP: case DEF_GROUP: - if (!(gr = internal_getgrgid (aclbufp[i].a_id)) + if (!(gr = internal_getgrgid (aclbufp[i].a_id, &cldap)) || !sid.getfromgr (gr)) { set_errno (EINVAL); @@ -282,6 +283,7 @@ getacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp) BOOLEAN dummy; uid_t uid; gid_t gid; + cyg_ldap cldap; status = RtlGetOwnerSecurityDescriptor (sd, (PSID *) &owner_sid, &dummy); if (!NT_SUCCESS (status)) @@ -289,7 +291,7 @@ getacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp) __seterrno_from_nt_status (status); return -1; } - uid = owner_sid.get_uid (); + uid = owner_sid.get_uid (&cldap); status = RtlGetGroupSecurityDescriptor (sd, (PSID *) &group_sid, &dummy); if (!NT_SUCCESS (status)) @@ -297,7 +299,7 @@ getacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp) __seterrno_from_nt_status (status); return -1; } - gid = group_sid.get_gid (); + gid = group_sid.get_gid (&cldap); aclent_t lacl[MAX_ACL_ENTRIES]; memset (&lacl, 0, MAX_ACL_ENTRIES * sizeof (aclent_t)); @@ -367,7 +369,7 @@ getacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp) id = ILLEGAL_GID; } else - id = ace_sid.get_id (true, &type); + id = ace_sid.get_id (TRUE, &type, &cldap); if (!type) continue; @@ -836,6 +838,7 @@ aclfromtext32 (char *acltextp, int *) int pos = 0; strcpy (buf, acltextp); char *lasts; + cyg_ldap cldap; for (char *c = strtok_r (buf, ",", &lasts); c; c = strtok_r (NULL, ",", &lasts)) @@ -855,7 +858,7 @@ aclfromtext32 (char *acltextp, int *) c += 5; if (isalpha (*c)) { - struct passwd *pw = internal_getpwnam (c); + struct passwd *pw = internal_getpwnam (c, &cldap); if (!pw) { set_errno (EINVAL); @@ -883,7 +886,7 @@ aclfromtext32 (char *acltextp, int *) c += 5; if (isalpha (*c)) { - struct group *gr = internal_getgrnam (c); + struct group *gr = internal_getgrnam (c, &cldap); if (!gr) { set_errno (EINVAL); diff --git a/winsup/cygwin/sec_helper.cc b/winsup/cygwin/sec_helper.cc index 8a31693f1..23dfc94e8 100644 --- a/winsup/cygwin/sec_helper.cc +++ b/winsup/cygwin/sec_helper.cc @@ -93,7 +93,7 @@ cygpsid::operator== (const char *nsidstr) const } uid_t -cygpsid::get_id (BOOL search_grp, int *type) +cygpsid::get_id (BOOL search_grp, int *type, cyg_ldap *pldap) { /* First try to get SID from group, then passwd */ uid_t id = ILLEGAL_UID; @@ -103,7 +103,7 @@ cygpsid::get_id (BOOL search_grp, int *type) struct group *gr; if (cygheap->user.groups.pgsid == psid) id = myself->gid; - else if ((gr = internal_getgrsid (*this))) + else if ((gr = internal_getgrsid (*this, pldap))) id = gr->gr_gid; if (id != ILLEGAL_UID) { @@ -117,7 +117,7 @@ cygpsid::get_id (BOOL search_grp, int *type) struct passwd *pw; if (*this == cygheap->user.sid ()) id = myself->uid; - else if ((pw = internal_getpwsid (*this))) + else if ((pw = internal_getpwsid (*this, pldap))) id = pw->pw_uid; if (id != ILLEGAL_UID && type) *type = USER; @@ -297,10 +297,9 @@ get_sids_info (cygpsid owner_sid, cygpsid group_sid, uid_t * uidret, gid_t * gid { struct passwd *pw; struct group *gr = NULL; - bool ret = false; + BOOL ret = false; PWCHAR domain; cyg_ldap cldap; - bool ldap_open = false; owner_sid.debug_print ("get_sids_info: owner SID ="); group_sid.debug_print ("get_sids_info: group SID ="); @@ -318,7 +317,7 @@ get_sids_info (cygpsid owner_sid, cygpsid group_sid, uid_t * uidret, gid_t * gid if (map_gid == ILLEGAL_GID) { domain = cygheap->dom.get_rfc2307_domain (); - if ((ldap_open = cldap.open (domain))) + if (cldap.open (domain)) map_gid = cldap.remap_gid (gid); if (map_gid == ILLEGAL_GID) map_gid = MAP_UNIX_TO_CYGWIN_ID (gid); @@ -326,7 +325,7 @@ get_sids_info (cygpsid owner_sid, cygpsid group_sid, uid_t * uidret, gid_t * gid } *gidret = map_gid; } - else if ((gr = internal_getgrsid (group_sid))) + else if ((gr = internal_getgrsid (group_sid, &cldap))) *gidret = gr->gr_gid; else *gidret = ILLEGAL_GID; @@ -335,9 +334,11 @@ get_sids_info (cygpsid owner_sid, cygpsid group_sid, uid_t * uidret, gid_t * gid { *uidret = myself->uid; if (*gidret == myself->gid) - ret = true; + ret = TRUE; else - ret = (internal_getgroups (0, NULL, &group_sid) > 0); + CheckTokenMembership (cygheap->user.issetuid () + ? cygheap->user.imp_token () : NULL, + group_sid, &ret); } else if (sid_id_auth (owner_sid) == 22) { @@ -347,7 +348,7 @@ get_sids_info (cygpsid owner_sid, cygpsid group_sid, uid_t * uidret, gid_t * gid if (map_uid == ILLEGAL_UID) { domain = cygheap->dom.get_rfc2307_domain (); - if ((ldap_open || cldap.open (domain))) + if (cldap.open (domain)) map_uid = cldap.remap_uid (uid); if (map_uid == ILLEGAL_UID) map_uid = MAP_UNIX_TO_CYGWIN_ID (uid); @@ -355,11 +356,11 @@ get_sids_info (cygpsid owner_sid, cygpsid group_sid, uid_t * uidret, gid_t * gid } *uidret = map_uid; } - else if ((pw = internal_getpwsid (owner_sid))) + else if ((pw = internal_getpwsid (owner_sid, &cldap))) { *uidret = pw->pw_uid; if (gr || (*gidret != ILLEGAL_GID - && (gr = internal_getgrgid (*gidret)))) + && (gr = internal_getgrgid (*gidret, &cldap)))) for (int idx = 0; gr->gr_mem[idx]; ++idx) if ((ret = strcasematch (pw->pw_name, gr->gr_mem[idx]))) break; @@ -367,7 +368,7 @@ get_sids_info (cygpsid owner_sid, cygpsid group_sid, uid_t * uidret, gid_t * gid else *uidret = ILLEGAL_UID; - return ret; + return (bool) ret; } PSECURITY_DESCRIPTOR diff --git a/winsup/cygwin/security.h b/winsup/cygwin/security.h index f283674dc..887634ae0 100644 --- a/winsup/cygwin/security.h +++ b/winsup/cygwin/security.h @@ -138,6 +138,8 @@ extern "C" } #endif +class cyg_ldap; + class cygpsid { protected: PSID psid; @@ -146,9 +148,9 @@ public: cygpsid (PSID nsid) { psid = nsid; } operator PSID () const { return psid; } const PSID operator= (PSID nsid) { return psid = nsid;} - uid_t get_id (BOOL search_grp, int *type = NULL); - int get_uid () { return get_id (FALSE); } - int get_gid () { return get_id (TRUE); } + uid_t get_id (BOOL search_grp, int *type, cyg_ldap *pldap); + int get_uid (cyg_ldap *pldap) { return get_id (FALSE, NULL, pldap); } + int get_gid (cyg_ldap *pldap) { return get_id (TRUE, NULL, pldap); } PWCHAR pstring (PWCHAR nsidstr) const; PWCHAR string (PWCHAR nsidstr) const; diff --git a/winsup/cygwin/uinfo.cc b/winsup/cygwin/uinfo.cc index 20b218851..e39e08601 100644 --- a/winsup/cygwin/uinfo.cc +++ b/winsup/cygwin/uinfo.cc @@ -118,11 +118,12 @@ internal_getlogin (cygheap_user &user) { struct passwd *pw = NULL; struct group *gr, *gr2; + cyg_ldap cldap; cygpsid psid = user.sid (); - pw = internal_getpwsid (psid); + pw = internal_getpwsid (psid, &cldap); - if (!pw && !(pw = internal_getpwnam (user.name ()))) + if (!pw && !(pw = internal_getpwnam (user.name (), &cldap))) debug_printf ("user not found in /etc/passwd"); else { @@ -131,13 +132,13 @@ internal_getlogin (cygheap_user &user) myself->uid = pw->pw_uid; myself->gid = pw->pw_gid; user.set_name (pw->pw_name); - if (gsid.getfromgr (gr = internal_getgrgid (pw->pw_gid))) + if (gsid.getfromgr (gr = internal_getgrgid (pw->pw_gid, &cldap))) { /* We might have a group file with a group entry for the current user's primary group, but the current user has no entry in passwd. If so, pw_gid is taken from windows and might disagree with the gr_gid from the group file. Overwrite it brutally. */ - if ((gr2 = internal_getgrsid (gsid)) && gr2 != gr) + if ((gr2 = internal_getgrsid (gsid, &cldap)) && gr2 != gr) myself->gid = pw->pw_gid = gr2->gr_gid; /* Set primary group to the group in /etc/passwd. */ if (gsid != user.groups.pgsid) @@ -975,12 +976,12 @@ pwdgrp::add_account_from_file (uint32_t id) } void * -pwdgrp::add_account_from_windows (cygpsid &sid, bool group) +pwdgrp::add_account_from_windows (cygpsid &sid, bool group, cyg_ldap *pldap) { fetch_user_arg_t arg; arg.type = SID_arg; arg.sid = &sid; - char *line = fetch_account_from_windows (arg, group); + char *line = fetch_account_from_windows (arg, group, pldap); if (!line) return NULL; if (cygheap->pg.nss_db_caching ()) @@ -989,12 +990,12 @@ pwdgrp::add_account_from_windows (cygpsid &sid, bool group) } void * -pwdgrp::add_account_from_windows (const char *name, bool group) +pwdgrp::add_account_from_windows (const char *name, bool group, cyg_ldap *pldap) { fetch_user_arg_t arg; arg.type = NAME_arg; arg.name = name; - char *line = fetch_account_from_windows (arg, group); + char *line = fetch_account_from_windows (arg, group, pldap); if (!line) return NULL; if (cygheap->pg.nss_db_caching ()) @@ -1003,12 +1004,12 @@ pwdgrp::add_account_from_windows (const char *name, bool group) } void * -pwdgrp::add_account_from_windows (uint32_t id, bool group) +pwdgrp::add_account_from_windows (uint32_t id, bool group, cyg_ldap *pldap) { fetch_user_arg_t arg; arg.type = ID_arg; arg.id = id; - char *line = fetch_account_from_windows (arg, group); + char *line = fetch_account_from_windows (arg, group, pldap); if (!line) return NULL; if (cygheap->pg.nss_db_caching ()) @@ -1134,13 +1135,13 @@ pwdgrp::fetch_account_from_file (fetch_user_arg_t &arg) } static ULONG -fetch_posix_offset (PDS_DOMAIN_TRUSTSW td, bool &ldap_open, cyg_ldap &cldap) +fetch_posix_offset (PDS_DOMAIN_TRUSTSW td, cyg_ldap *cldap) { uint32_t id_val; if (!td->PosixOffset && !(td->Flags & DS_DOMAIN_PRIMARY) && td->DomainSid) { - if (!ldap_open && !(ldap_open = cldap.open (NULL))) + if (!cldap->open (NULL)) { /* We're probably running under a local account, so we're not allowed to fetch any information from AD beyond the most obvious. Never @@ -1149,7 +1150,7 @@ fetch_posix_offset (PDS_DOMAIN_TRUSTSW td, bool &ldap_open, cyg_ldap &cldap) - 0x01000000; } else - id_val = cldap.fetch_posix_offset_for_domain (td->DnsDomainName); + id_val = cldap->fetch_posix_offset_for_domain (td->DnsDomainName); if (id_val) { td->PosixOffset = id_val; @@ -1163,7 +1164,7 @@ fetch_posix_offset (PDS_DOMAIN_TRUSTSW td, bool &ldap_open, cyg_ldap &cldap) char * pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group, - bool ugid_caching) + cyg_ldap *pldap) { /* Used in LookupAccount calls. */ WCHAR namebuf[UNLEN + 1], *name = namebuf; @@ -1172,7 +1173,7 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group, DWORD nlen = UNLEN + 1; DWORD dlen = DNLEN + 1; DWORD slen = MAX_SID_LEN; - cygpsid sid = NO_SID; + cygpsid sid (NO_SID); SID_NAME_USE acc_type; BOOL ret = false; /* Cygwin user name style. */ @@ -1190,13 +1191,13 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group, PWCHAR user = NULL; PWCHAR home = NULL; PWCHAR gecos = NULL; + /* Temporary stuff. */ PWCHAR p; WCHAR sidstr[128]; - /* Temporary stuff. */ ULONG posix_offset = 0; uint32_t id_val; - cyg_ldap cldap; - bool ldap_open = false; + cyg_ldap loc_ldap; + cyg_ldap *cldap = pldap ?: &loc_ldap; /* Initialize */ if (!cygheap->dom.init ()) @@ -1219,9 +1220,9 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group, DC for some weird reason. Use LDAP instead. */ PWCHAR val; - if ((ldap_open = cldap.open (NULL)) - && cldap.fetch_ad_account (sid, group) - && (val = cldap.get_group_name ())) + if (cldap->open (NULL) + && cldap->fetch_ad_account (sid, group) + && (val = cldap->get_group_name ())) { wcpcpy (name, val); wcpcpy (dom, L"BUILTIN"); @@ -1355,7 +1356,7 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group, for (ULONG idx = 0; (td = cygheap->dom.trusted_domain (idx)); ++idx) { - fetch_posix_offset (td, ldap_open, cldap); + fetch_posix_offset (td, cldap); if (td->PosixOffset > posix_offset && td->PosixOffset <= arg.id) posix_offset = td->PosixOffset; } @@ -1452,7 +1453,7 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group, { domain = td->DnsDomainName; posix_offset = - fetch_posix_offset (td, ldap_open, cldap); + fetch_posix_offset (td, cldap); break; } @@ -1474,60 +1475,44 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group, /* Generate values. */ if (uid == ILLEGAL_UID) uid = posix_offset + sid_sub_auth_rid (sid); - gid = posix_offset + DOMAIN_GROUP_RID_USERS; /* Default. */ if (is_domain_account) { - /* Use LDAP to fetch domain account infos. */ - if (!ldap_open && !cldap.open (NULL)) + if (acc_type != SidTypeUser) break; - if (cldap.fetch_ad_account (sid, group)) + + gid = posix_offset + DOMAIN_GROUP_RID_USERS; /* Default. */ + /* Use LDAP to fetch domain account infos. */ + if (!cldap->open (NULL)) + break; + if (cldap->fetch_ad_account (sid, group)) { PWCHAR val; - if (acc_type == SidTypeUser) + + if ((id_val = cldap->get_primary_gid ()) != ILLEGAL_GID) + gid = posix_offset + id_val; + if ((val = cldap->get_user_name ()) + && wcscmp (name, val)) + user = wcscpy ((PWCHAR) alloca ((wcslen (val) + 1) + * sizeof (WCHAR)), val); + if ((val = cldap->get_gecos ())) + gecos = wcscpy ((PWCHAR) alloca ((wcslen (val) + 1) + * sizeof (WCHAR)), val); + if ((val = cldap->get_home ())) + home = wcscpy ((PWCHAR) alloca ((wcslen (val) + 1) + * sizeof (WCHAR)), val); + if ((val = cldap->get_shell ())) + shell = wcscpy ((PWCHAR) alloca ((wcslen (val) + 1) + * sizeof (WCHAR)), val); + /* Check and, if necessary, add unix<->windows id mapping on + the fly, unless we're called from getpwent. */ + if (!pldap) { - if ((id_val = cldap.get_primary_gid ()) != ILLEGAL_GID) - gid = posix_offset + id_val; - if ((val = cldap.get_user_name ()) - && wcscmp (name, val)) - user = wcscpy ((PWCHAR) alloca ((wcslen (val) + 1) - * sizeof (WCHAR)), val); - if ((val = cldap.get_gecos ())) - gecos = wcscpy ((PWCHAR) alloca ((wcslen (val) + 1) - * sizeof (WCHAR)), val); - if ((val = cldap.get_home ())) - home = wcscpy ((PWCHAR) alloca ((wcslen (val) + 1) - * sizeof (WCHAR)), val); - if ((val = cldap.get_shell ())) - shell = wcscpy ((PWCHAR) alloca ((wcslen (val) + 1) - * sizeof (WCHAR)), val); - /* Check and, if necessary, add unix<->windows - id mapping on the fly. */ - if (ugid_caching) - { - id_val = cldap.get_unix_uid (); - if (id_val != ILLEGAL_UID - && cygheap->ugid_cache.get_uid (id_val) - == ILLEGAL_UID) - cygheap->ugid_cache.add_uid (id_val, uid); - } - } - else /* SidTypeGroup */ - { - if ((val = cldap.get_group_name ()) - && wcscmp (name, val)) - user = wcscpy ((PWCHAR) alloca ((wcslen (val) + 1) - * sizeof (WCHAR)), val); - /* Check and, if necessary, add unix<->windows - id mapping on the fly. */ - if (ugid_caching) - { - id_val = cldap.get_unix_gid (); - if (id_val != ILLEGAL_GID - && cygheap->ugid_cache.get_gid (id_val) - == ILLEGAL_GID) - cygheap->ugid_cache.add_gid (id_val, uid); - } + id_val = cldap->get_unix_uid (); + if (id_val != ILLEGAL_UID + && cygheap->ugid_cache.get_uid (id_val) + == ILLEGAL_UID) + cygheap->ugid_cache.add_uid (id_val, uid); } } } @@ -1629,12 +1614,11 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group, *gname = cygheap->pg.nss_separator ()[0]; sys_wcstombs (gname + 1, 2 * UNLEN + 1, pgrp); - if ((gr = internal_getgrnam (gname)) - || (gr = internal_getgrnam (gname + 1))) + if ((gr = internal_getgrnam (gname, cldap)) + || (gr = internal_getgrnam (gname + 1, cldap))) gid = gr->gr_gid; } - if (ugid_caching && uxid - && ((id_val = wcstoul (uxid, &e, 10)), !*e)) + if (!pldap && uxid && ((id_val = wcstoul (uxid, &e, 10)), !*e)) { if (acc_type == SidTypeUser) { @@ -1744,7 +1728,7 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group, if (td->DomainSid && RtlEqualSid (sid, td->DomainSid)) { domain = td->NetbiosDomainName; - posix_offset = fetch_posix_offset (td, ldap_open, cldap); + posix_offset = fetch_posix_offset (td, cldap); break; } }