From 439b7db7850cb69d8119308c5b6f16d1e596161f Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Tue, 6 May 2014 12:02:48 +0000 Subject: [PATCH] * grp.cc (internal_getgroups): Drop unused cygsid variable. * sec_helper.cc (cygpsid::pstring): Use sid_sub_auth_count macro. (cygsid::get_sid): Use MAX_SUBAUTH_CNT rather than wrong constant 8. Don't call memcpy to copy subauthorities into SID, use assignment. (cygsid::getfromstr): Use MAX_SUBAUTH_CNT rather than wrong constant 8. * security.h (MAX_SUBAUTH_CNT): New definition. Set to 11 to cover Microsoft Accounts. (MAX_SID_LEN): Define in terms of SID member sizes and MAX_SUBAUTH_CNT. (DBGSID): Use MAX_SUBAUTH_CNT to define size of SubAuthority array. * uinfo.cc (pwdgrp::fetch_account_from_windows): Handle Micosoft Accounts. Handle them as well known group. Compare domain names case-insensitive. * winlean.h (PIPE_REJECT_REMOTE_CLIENTS): Drop temporary definition since Mingw64 catched up. (DNLEN): Redefine as 16. Explain why. --- winsup/cygwin/ChangeLog | 18 ++++++++++++++++++ winsup/cygwin/grp.cc | 2 -- winsup/cygwin/sec_helper.cc | 15 ++++++++------- winsup/cygwin/security.h | 8 +++++--- winsup/cygwin/uinfo.cc | 20 +++++++++++++------- winsup/cygwin/winlean.h | 14 ++++++++------ 6 files changed, 52 insertions(+), 25 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 9c1d25fdc..80c17d494 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,21 @@ +2014-05-06 Corinna Vinschen + + * grp.cc (internal_getgroups): Drop unused cygsid variable. + * sec_helper.cc (cygpsid::pstring): Use sid_sub_auth_count macro. + (cygsid::get_sid): Use MAX_SUBAUTH_CNT rather than wrong constant 8. + Don't call memcpy to copy subauthorities into SID, use assignment. + (cygsid::getfromstr): Use MAX_SUBAUTH_CNT rather than wrong constant 8. + * security.h (MAX_SUBAUTH_CNT): New definition. Set to 11 to cover + Microsoft Accounts. + (MAX_SID_LEN): Define in terms of SID member sizes and MAX_SUBAUTH_CNT. + (DBGSID): Use MAX_SUBAUTH_CNT to define size of SubAuthority array. + * uinfo.cc (pwdgrp::fetch_account_from_windows): Handle Micosoft + Accounts. Handle them as well known group. Compare domain names + case-insensitive. + * winlean.h (PIPE_REJECT_REMOTE_CLIENTS): Drop temporary definition + since Mingw64 catched up. + (DNLEN): Redefine as 16. Explain why. + 2014-05-05 Corinna Vinschen * net.cc (cygwin_getsockopt): Rearrange code slightly and handle diff --git a/winsup/cygwin/grp.cc b/winsup/cygwin/grp.cc index d941c0f9b..e1b28ae34 100644 --- a/winsup/cygwin/grp.cc +++ b/winsup/cygwin/grp.cc @@ -512,8 +512,6 @@ internal_getgroups (int gidsetsize, gid_t *grouplist, cyg_ldap *pldap) status = NtQueryInformationToken (tok, TokenGroups, groups, size, &size); if (NT_SUCCESS (status)) { - cygsid sid; - for (DWORD pg = 0; pg < groups->GroupCount; ++pg) { cygpsid sid = groups->Groups[pg].Sid; diff --git a/winsup/cygwin/sec_helper.cc b/winsup/cygwin/sec_helper.cc index 122776f43..6f7921aa5 100644 --- a/winsup/cygwin/sec_helper.cc +++ b/winsup/cygwin/sec_helper.cc @@ -198,7 +198,7 @@ cygpsid::pstring (char *nsidstr) const strcpy (nsidstr, "S-1-"); t = nsidstr + sizeof ("S-1-") - 1; t += __small_sprintf (t, "%u", sid_id_auth (psid)); - for (i = 0; i < *RtlSubAuthorityCountSid (psid); ++i) + for (i = 0; i < sid_sub_auth_count (psid); ++i) t += __small_sprintf (t, "-%lu", sid_sub_auth (psid, i)); return t; } @@ -218,7 +218,7 @@ cygsid::get_sid (DWORD s, DWORD cnt, DWORD *r, bool well_known) SID_IDENTIFIER_AUTHORITY sid_auth = { SECURITY_NULL_SID_AUTHORITY }; # define SECURITY_NT_AUTH 5 - if (s > 255 || cnt < 1 || cnt > 8) + if (s > 255 || cnt < 1 || cnt > MAX_SUBAUTH_CNT) { psid = NO_SID; return NULL; @@ -226,8 +226,9 @@ cygsid::get_sid (DWORD s, DWORD cnt, DWORD *r, bool well_known) sid_auth.Value[5] = s; set (); RtlInitializeSid (psid, &sid_auth, cnt); + PDBGSID dsid = (PDBGSID) psid; for (i = 0; i < cnt; ++i) - memcpy ((char *) psid + 8 + sizeof (DWORD) * i, &r[i], sizeof (DWORD)); + dsid->SubAuthority[i] = r[i]; /* If the well_known flag isn't set explicitely, we check the SID for being a well-known SID ourselves. That's necessary because this cygsid is created from a SID string, usually from /etc/passwd or @@ -247,12 +248,12 @@ cygsid::getfromstr (PCWSTR nsidstr, bool well_known) { PWCHAR lasts; DWORD s, cnt = 0; - DWORD r[8]; + DWORD r[MAX_SUBAUTH_CNT]; if (nsidstr && !wcsncmp (nsidstr, L"S-1-", 4)) { s = wcstoul (nsidstr + 4, &lasts, 10); - while (cnt < 8 && *lasts == '-') + while (cnt < MAX_SUBAUTH_CNT && *lasts == '-') r[cnt++] = wcstoul (lasts + 1, &lasts, 10); if (!*lasts) return get_sid (s, cnt, r, well_known); @@ -265,12 +266,12 @@ cygsid::getfromstr (const char *nsidstr, bool well_known) { char *lasts; DWORD s, cnt = 0; - DWORD r[8]; + DWORD r[MAX_SUBAUTH_CNT]; if (nsidstr && !strncmp (nsidstr, "S-1-", 4)) { s = strtoul (nsidstr + 4, &lasts, 10); - while (cnt < 8 && *lasts == '-') + while (cnt < MAX_SUBAUTH_CNT && *lasts == '-') r[cnt++] = strtoul (lasts + 1, &lasts, 10); if (!*lasts) return get_sid (s, cnt, r, well_known); diff --git a/winsup/cygwin/security.h b/winsup/cygwin/security.h index 7af737fd7..9b1edbc84 100644 --- a/winsup/cygwin/security.h +++ b/winsup/cygwin/security.h @@ -44,8 +44,10 @@ void uinfo_init (); #define gid16togid32(g16) ((g16)==ILLEGAL_GID16?ILLEGAL_GID:(gid_t)(g16)) #endif - -#define MAX_SID_LEN 40 +#define MAX_SUBAUTH_CNT 11 +#define MAX_SID_LEN (2 * sizeof (BYTE) \ + + sizeof (SID_IDENTIFIER_AUTHORITY) \ + + MAX_SUBAUTH_CNT * sizeof (DWORD)) #define MAX_DACL_LEN(n) (sizeof (ACL) \ + (n) * (sizeof (ACCESS_ALLOWED_ACE) - sizeof (DWORD) + MAX_SID_LEN)) #define SD_MIN_SIZE (sizeof (SECURITY_DESCRIPTOR) + MAX_DACL_LEN (1)) @@ -99,7 +101,7 @@ typedef struct { BYTE Revision; BYTE SubAuthorityCount; SID_IDENTIFIER_AUTHORITY IdentifierAuthority; - DWORD SubAuthority[8]; + DWORD SubAuthority[MAX_SUBAUTH_CNT]; } DBGSID, *PDBGSID; /* Macro to define variable length SID structures */ diff --git a/winsup/cygwin/uinfo.cc b/winsup/cygwin/uinfo.cc index 10716a3cd..48dd08ab1 100644 --- a/winsup/cygwin/uinfo.cc +++ b/winsup/cygwin/uinfo.cc @@ -1384,8 +1384,13 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, cyg_ldap *pldap) if (ret) { /* Builtin account? SYSTEM, for instance, is returned as SidTypeUser, - if a process is running as LocalSystem service. */ - if (acc_type == SidTypeUser && sid_sub_auth_count (sid) <= 3) + if a process is running as LocalSystem service. + Microsoft Account? These show up in the user's group list, using the + undocumented security authority 11. Even though this is officially a + user account, it only matters as part of the group list, so we convert + it to a well-known group here. */ + if (acc_type == SidTypeUser + && (sid_sub_auth_count (sid) <= 3 || sid_id_auth (sid) == 11)) acc_type = SidTypeWellKnownGroup; switch (acc_type) { @@ -1409,7 +1414,7 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, cyg_ldap *pldap) is_domain_account = false; } /* Account domain account? */ - else if (!wcscmp (dom, cygheap->dom.account_flat_name ())) + else if (!wcscasecmp (dom, cygheap->dom.account_flat_name ())) { posix_offset = 0x30000; if (cygheap->dom.member_machine () @@ -1422,7 +1427,7 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, cyg_ldap *pldap) else if (cygheap->dom.member_machine ()) { /* Primary domain account? */ - if (!wcscmp (dom, cygheap->dom.primary_flat_name ())) + if (!wcscasecmp (dom, cygheap->dom.primary_flat_name ())) { posix_offset = 0x100000; /* In theory domain should have been set to @@ -1447,7 +1452,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) - if (!wcscmp (dom, td->NetbiosDomainName)) + if (!wcscasecmp (dom, td->NetbiosDomainName)) { domain = td->DnsDomainName; posix_offset = @@ -1636,8 +1641,9 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, cyg_ldap *pldap) } break; case SidTypeWellKnownGroup: - name_style = (cygheap->pg.nss_prefix_always ()) ? fully_qualified - : plus_prepended; + name_style = (cygheap->pg.nss_prefix_always () + || sid_id_auth (sid) == 11) /* Microsoft Account */ + ? fully_qualified : plus_prepended; #ifdef INTERIX_COMPATIBLE if (sid_id_auth (sid) == 5 /* SECURITY_NT_AUTHORITY */ && sid_sub_auth_count (sid) > 1) diff --git a/winsup/cygwin/winlean.h b/winsup/cygwin/winlean.h index c50cf747a..162994854 100644 --- a/winsup/cygwin/winlean.h +++ b/winsup/cygwin/winlean.h @@ -1,6 +1,6 @@ /* winlean.h - Standard "lean" windows include - Copyright 2010, 2011, 2012, 2013 Red Hat, Inc. + Copyright 2010, 2011, 2012, 2013, 2014 Red Hat, Inc. This file is part of Cygwin. @@ -58,11 +58,6 @@ details. */ #include #include -/* Temporary kludge for missing flag in Mingw64's w32api. */ -#ifndef PIPE_REJECT_REMOTE_CLIENTS -#define PIPE_REJECT_REMOTE_CLIENTS 8 -#endif - #ifdef __undef_IN #undef IN #endif @@ -79,6 +74,13 @@ details. */ #undef CRITICAL #endif +/* So-called "Microsoft Account" SIDs have a netbios domain name + "MicrosoftAccounts". The problem is, while DNLEN is 15, that domain + name is 16 chars :-P So we override DNLEN here to be 16, so that calls + to LookupAccountSid/Name don't fail if the buffer is based on DNLEN. */ +#undef DNLEN +#define DNLEN 16 + /* When Terminal Services are installed, the GetWindowsDirectory function does not return the system installation dir, but a user specific directory instead. That's not what we have in mind when calling GetWindowsDirectory