diff --git a/winsup/cygwin/sec_auth.cc b/winsup/cygwin/sec_auth.cc index a7610c71f..a15778db0 100644 --- a/winsup/cygwin/sec_auth.cc +++ b/winsup/cygwin/sec_auth.cc @@ -379,41 +379,6 @@ sid_in_token_groups (PTOKEN_GROUPS grps, cygpsid sid) return false; } -static void -get_token_group_sidlist (cygsidlist &grp_list, PTOKEN_GROUPS my_grps) -{ - if (my_grps) - { - grp_list += well_known_local_sid; - grp_list += well_known_console_logon_sid; - if (sid_in_token_groups (my_grps, well_known_dialup_sid)) - grp_list *= well_known_dialup_sid; - if (sid_in_token_groups (my_grps, well_known_network_sid)) - grp_list *= well_known_network_sid; - if (sid_in_token_groups (my_grps, well_known_batch_sid)) - grp_list *= well_known_batch_sid; - grp_list *= well_known_interactive_sid; -#if 0 - /* Don't add the SERVICE group when switching the user context. - That's much too dangerous, since the service group adds the - SE_IMPERSONATE_NAME privilege to the user. After all, the - process started with this token is not the service process - anymore anyway. */ - if (sid_in_token_groups (my_grps, well_known_service_sid)) - grp_list *= well_known_service_sid; -#endif - if (sid_in_token_groups (my_grps, well_known_this_org_sid)) - grp_list *= well_known_this_org_sid; - grp_list *= well_known_users_sid; - } - else - { - grp_list += well_known_local_sid; - grp_list *= well_known_interactive_sid; - grp_list *= well_known_users_sid; - } -} - bool get_server_groups (cygsidlist &grp_list, PSID usersid, acct_disabled_chk_t check_account_disabled) @@ -470,180 +435,6 @@ get_server_groups (cygsidlist &grp_list, PSID usersid, return true; } -static bool -get_initgroups_sidlist (cygsidlist &grp_list, PSID usersid, PSID pgrpsid, - PTOKEN_GROUPS my_grps) -{ - if (well_known_system_sid != usersid) - get_token_group_sidlist (grp_list, my_grps); - if (!get_server_groups (grp_list, usersid, CHK_DISABLED)) - return false; - - /* special_pgrp true if pgrpsid is not in normal groups */ - grp_list += pgrpsid; - return true; -} - -static bool -get_setgroups_sidlist (cygsidlist &tmp_list, PSID usersid, - PTOKEN_GROUPS my_grps, user_groups &groups) -{ - get_token_group_sidlist (tmp_list, my_grps); - if (!get_server_groups (tmp_list, usersid, CHK_DISABLED)) - return false; - for (int gidx = 0; gidx < groups.sgsids.count (); gidx++) - tmp_list += groups.sgsids.sids[gidx]; - tmp_list += groups.pgsid; - return true; -} - -/* Fixed size TOKEN_PRIVILEGES list to reflect privileges given to the - SYSTEM account by default. */ -const struct -{ - DWORD PrivilegeCount; - LUID_AND_ATTRIBUTES Privileges[28]; -} sys_privs = -{ - 28, - { - { { SE_CREATE_TOKEN_PRIVILEGE, 0 }, - SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT }, - { { SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, 0 }, - SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT }, - { { SE_LOCK_MEMORY_PRIVILEGE, 0 }, - SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT }, - { { SE_INCREASE_QUOTA_PRIVILEGE, 0 }, - SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT }, - { { SE_TCB_PRIVILEGE, 0 }, - SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT }, - { { SE_SECURITY_PRIVILEGE, 0 }, - SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT }, - { { SE_TAKE_OWNERSHIP_PRIVILEGE, 0 }, - SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT }, - { { SE_LOAD_DRIVER_PRIVILEGE, 0 }, - SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT }, - { { SE_SYSTEM_PROFILE_PRIVILEGE, 0 }, - SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT }, - { { SE_SYSTEMTIME_PRIVILEGE, 0 }, - SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT }, - { { SE_PROF_SINGLE_PROCESS_PRIVILEGE, 0 }, - SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT }, - { { SE_INC_BASE_PRIORITY_PRIVILEGE, 0 }, - SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT }, - { { SE_CREATE_PAGEFILE_PRIVILEGE, 0 }, - SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT }, - { { SE_CREATE_PERMANENT_PRIVILEGE, 0 }, - SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT }, - { { SE_BACKUP_PRIVILEGE, 0 }, - SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT }, - { { SE_RESTORE_PRIVILEGE, 0 }, - SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT }, - { { SE_SHUTDOWN_PRIVILEGE, 0 }, - SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT }, - { { SE_DEBUG_PRIVILEGE, 0 }, - SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT }, - { { SE_AUDIT_PRIVILEGE, 0 }, - SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT }, - { { SE_SYSTEM_ENVIRONMENT_PRIVILEGE, 0 }, - SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT }, - { { SE_CHANGE_NOTIFY_PRIVILEGE, 0 }, - SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT }, - { { SE_UNDOCK_PRIVILEGE, 0 }, - SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT }, - { { SE_MANAGE_VOLUME_PRIVILEGE, 0 }, - SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT }, - { { SE_IMPERSONATE_PRIVILEGE, 0 }, - SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT }, - { { SE_CREATE_GLOBAL_PRIVILEGE, 0 }, - SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT }, - { { SE_INCREASE_WORKING_SET_PRIVILEGE, 0 }, - SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT }, - { { SE_TIME_ZONE_PRIVILEGE, 0 }, - SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT }, - { { SE_CREATE_SYMBOLIC_LINK_PRIVILEGE, 0 }, - SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT } - } -}; - -static PTOKEN_PRIVILEGES -get_priv_list (LSA_HANDLE lsa, cygsid &usersid, cygsidlist &grp_list, - size_t &size, cygpsid *mandatory_integrity_sid) -{ - PLSA_UNICODE_STRING privstrs; - ULONG cnt; - PTOKEN_PRIVILEGES privs = NULL; - - if (usersid == well_known_system_sid) - { - if (mandatory_integrity_sid) - *mandatory_integrity_sid = mandatory_system_integrity_sid; - return (PTOKEN_PRIVILEGES) &sys_privs; - } - - if (mandatory_integrity_sid) - *mandatory_integrity_sid = mandatory_medium_integrity_sid; - - for (int grp = -1; grp < grp_list.count (); ++grp) - { - if (grp == -1) - { - if (LsaEnumerateAccountRights (lsa, usersid, &privstrs, &cnt) - != STATUS_SUCCESS) - continue; - } - else if (LsaEnumerateAccountRights (lsa, grp_list.sids[grp], - &privstrs, &cnt) != STATUS_SUCCESS) - continue; - for (ULONG i = 0; i < cnt; ++i) - { - LUID priv; - PTOKEN_PRIVILEGES tmp; - DWORD tmp_count; - bool high_integrity; - - if (!privilege_luid (privstrs[i].Buffer, priv, high_integrity)) - continue; - - if (privs) - { - DWORD pcnt = privs->PrivilegeCount; - LUID_AND_ATTRIBUTES *p = privs->Privileges; - for (; pcnt > 0; --pcnt, ++p) - if (priv.HighPart == p->Luid.HighPart - && priv.LowPart == p->Luid.LowPart) - goto next_account_right; - } - - tmp_count = privs ? privs->PrivilegeCount : 0; - size = sizeof (DWORD) - + (tmp_count + 1) * sizeof (LUID_AND_ATTRIBUTES); - tmp = (PTOKEN_PRIVILEGES) realloc (privs, size); - if (!tmp) - { - if (privs) - free (privs); - LsaFreeMemory (privstrs); - debug_printf ("realloc (privs) failed."); - return NULL; - } - tmp->PrivilegeCount = tmp_count; - privs = tmp; - privs->Privileges[privs->PrivilegeCount].Luid = priv; - privs->Privileges[privs->PrivilegeCount].Attributes = - SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT; - ++privs->PrivilegeCount; - if (mandatory_integrity_sid && high_integrity) - *mandatory_integrity_sid = mandatory_high_integrity_sid; - - next_account_right: - ; - } - LsaFreeMemory (privstrs); - } - return privs; -} - /* Accept a token if - the requested usersid matches the TokenUser and - if setgroups has been called: @@ -654,9 +445,8 @@ get_priv_list (LSA_HANDLE lsa, cygsid &usersid, cygsidlist &grp_list, they match and verify only the primary groups. The requested primary group must appear in the token. The primary group in the token is a group associated with the usersid, - except if the token is internal and the group is in the token SD - (see create_token). In that latter case that group must match the - requested primary group. */ + except if the token is internal and the group is in the token SD. In + that latter case that group must match the requested primary group. */ bool verify_token (HANDLE token, cygsid &usersid, user_groups &groups, bool *pintern) { @@ -786,160 +576,6 @@ account_restriction (NTSTATUS status) return type; } -HANDLE -create_token (cygsid &usersid, user_groups &new_groups) -{ - NTSTATUS status; - LSA_HANDLE lsa = NULL; - - cygsidlist tmp_gsids (cygsidlist_auto, 12); - - SECURITY_QUALITY_OF_SERVICE sqos = - { sizeof sqos, SecurityImpersonation, SECURITY_STATIC_TRACKING, FALSE }; - OBJECT_ATTRIBUTES oa = { sizeof oa, 0, 0, 0, 0, &sqos }; - /* Up to Windows 7, when using an authentication LUID other than "Anonymous", - Windows whoami prints the wrong username, the one from the login session, - not the one from the actual user token of the process. This is apparently - fixed in Windows 8. However, starting with Windows 8, access rights of - the anonymous logon session is further restricted. Therefore we create - the new user token with the authentication id of the local service - account. Hopefully that's sufficient. */ - const LUID auth_luid_7 = ANONYMOUS_LOGON_LUID; - const LUID auth_luid_8 = LOCALSERVICE_LUID; - LUID auth_luid = wincap.has_broken_whoami () ? auth_luid_7 : auth_luid_8; - LARGE_INTEGER exp = { QuadPart:INT64_MAX }; - - TOKEN_USER user; - PTOKEN_GROUPS new_tok_gsids = NULL; - PTOKEN_PRIVILEGES privs = NULL; - TOKEN_OWNER owner; - TOKEN_PRIMARY_GROUP pgrp; - TOKEN_DEFAULT_DACL dacl = {}; - TOKEN_SOURCE source; - TOKEN_STATISTICS stats; - memcpy (source.SourceName, "Cygwin.1", 8); - source.SourceIdentifier.HighPart = 0; - source.SourceIdentifier.LowPart = 0x0101; - - HANDLE token = NULL; - HANDLE primary_token = NULL; - - tmp_pathbuf tp; - PTOKEN_GROUPS my_tok_gsids = NULL; - cygpsid mandatory_integrity_sid; - ULONG size; - size_t psize = 0; - - /* SE_CREATE_TOKEN_NAME privilege needed to call NtCreateToken. */ - push_self_privilege (SE_CREATE_TOKEN_PRIVILEGE, true); - - /* Open policy object. */ - if (!(lsa = lsa_open_policy (NULL, POLICY_EXECUTE))) - goto out; - - /* User, owner, primary group. */ - user.User.Sid = usersid; - user.User.Attributes = 0; - owner.Owner = usersid; - - /* Retrieve authentication id and group list from own process. */ - if (hProcToken) - { - /* Switching user context to SYSTEM doesn't inherit the authentication - id of the user account running current process. */ - if (usersid == well_known_system_sid) - /* nothing to do */; - else - { - status = NtQueryInformationToken (hProcToken, TokenStatistics, - &stats, sizeof stats, &size); - if (!NT_SUCCESS (status)) - debug_printf ("NtQueryInformationToken(hProcToken, " - "TokenStatistics), %y", status); - } - - /* Retrieving current processes group list to be able to inherit - some important well known group sids. */ - my_tok_gsids = (PTOKEN_GROUPS) tp.w_get (); - status = NtQueryInformationToken (hProcToken, TokenGroups, my_tok_gsids, - 2 * NT_MAX_PATH, &size); - if (!NT_SUCCESS (status)) - { - debug_printf ("NtQueryInformationToken(hProcToken, TokenGroups), " - "%y", status); - my_tok_gsids = NULL; - } - } - - /* Create list of groups, the user is member in. */ - if (new_groups.issetgroups ()) - { - if (!get_setgroups_sidlist (tmp_gsids, usersid, my_tok_gsids, new_groups)) - goto out; - } - else if (!get_initgroups_sidlist (tmp_gsids, usersid, new_groups.pgsid, - my_tok_gsids)) - goto out; - - /* Primary group. */ - pgrp.PrimaryGroup = new_groups.pgsid; - - /* Create a TOKEN_GROUPS list from the above retrieved list of sids. */ - new_tok_gsids = (PTOKEN_GROUPS) - alloca (sizeof (DWORD) + (tmp_gsids.count () + 1) - * sizeof (SID_AND_ATTRIBUTES)); - new_tok_gsids->GroupCount = tmp_gsids.count (); - for (DWORD i = 0; i < new_tok_gsids->GroupCount; ++i) - { - new_tok_gsids->Groups[i].Sid = tmp_gsids.sids[i]; - new_tok_gsids->Groups[i].Attributes = SE_GROUP_MANDATORY - | SE_GROUP_ENABLED_BY_DEFAULT - | SE_GROUP_ENABLED; - } - - /* Retrieve list of privileges of that user. Based on the usersid and - the returned privileges, get_priv_list sets the mandatory_integrity_sid - pointer to the correct MIC SID for UAC. */ - if (!(privs = get_priv_list (lsa, usersid, tmp_gsids, psize, - &mandatory_integrity_sid))) - goto out; - - new_tok_gsids->Groups[new_tok_gsids->GroupCount].Attributes = - SE_GROUP_INTEGRITY | SE_GROUP_INTEGRITY_ENABLED; - new_tok_gsids->Groups[new_tok_gsids->GroupCount++].Sid - = mandatory_integrity_sid; - - /* Let's be heroic... */ - status = NtCreateToken (&token, TOKEN_ALL_ACCESS, &oa, TokenImpersonation, - &auth_luid, &exp, &user, new_tok_gsids, privs, &owner, - &pgrp, &dacl, &source); - if (status) - __seterrno_from_nt_status (status); - else - { - /* Convert to primary token. */ - if (!DuplicateTokenEx (token, MAXIMUM_ALLOWED, &sec_none, - SecurityImpersonation, TokenPrimary, - &primary_token)) - { - __seterrno (); - debug_printf ("DuplicateTokenEx %E"); - primary_token = NULL; - } - } - -out: - pop_self_privilege (); - if (token != INVALID_HANDLE_VALUE) - CloseHandle (token); - if (privs && privs != (PTOKEN_PRIVILEGES) &sys_privs) - free (privs); - lsa_close_policy (lsa); - - debug_printf ("%p = create_token ()", primary_token); - return primary_token; -} - #define SFU_LSA_KEY_SUFFIX L"_microsoft_sfu_utility" HANDLE diff --git a/winsup/cygwin/security.h b/winsup/cygwin/security.h index 3e6688cd9..651f6d0e8 100644 --- a/winsup/cygwin/security.h +++ b/winsup/cygwin/security.h @@ -457,8 +457,6 @@ int setacl (HANDLE, path_conv &, int, struct acl *, bool &); /* Set impersonation or restricted token. */ void set_imp_token (HANDLE token, int type); -/* Function creating a token by calling NtCreateToken. */ -HANDLE create_token (cygsid &usersid, user_groups &groups); /* LSA private key storage authentication, same as when using service logons. */ HANDLE lsaprivkeyauth (struct passwd *pw); /* Kerberos or MsV1 S4U logon. */ diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc index c9e1fb6d2..98b588698 100644 --- a/winsup/cygwin/spawn.cc +++ b/winsup/cygwin/spawn.cc @@ -752,11 +752,9 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv, sa = sec_user ((PSECURITY_ATTRIBUTES) alloca (1024), ::cygheap->user.sid ()); /* We're creating a window station per user, not per logon - session First of all we might not have a valid logon session - for the user (logon by create_token), and second, it doesn't - make sense in terms of security to create a new window - station for every logon of the same user. It just fills up - the system with window stations for no good reason. */ + session. It doesn't make sense in terms of security to + create a new window station for every logon of the same user. + It just fills up the system with window stations. */ hwst = CreateWindowStationW (::cygheap->user.get_windows_id (sid), 0, GENERIC_READ | GENERIC_WRITE, sa); if (!hwst) diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index b68d1f215..3a652c4f4 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -3607,8 +3607,7 @@ seteuid32 (uid_t uid) debug_printf ("Found token %p", new_token); /* If no impersonation token is available, try to authenticate using - LSA private data stored password, LSA authentication using our own - LSA module, or, as last chance, NtCreateToken. */ + LSA private data stored password, or, if that fails, S4U logon. */ if (new_token == NULL) { if (!(new_token = lsaprivkeyauth (pw_new))) @@ -3621,23 +3620,9 @@ seteuid32 (uid_t uid) extract_nt_dom_user (pw_new, domain, user); if (!(new_token = s4uauth (true, domain, user, status))) { - if (status != STATUS_INVALID_PARAMETER) - { - debug_printf ("s4uauth failed, bail out"); - cygheap->user.reimpersonate (); - return -1; - } - /* If s4uauth fails with status code STATUS_INVALID_PARAMETER, - we're running on a system not implementing MsV1_0S4ULogon - (Windows 7 WOW64). Fall back to create_token in this single - case only. */ - debug_printf ("s4uauth failed, try create_token."); - if (!(new_token = create_token (usersid, groups))) - { - debug_printf ("create_token failed, bail out"); - cygheap->user.reimpersonate (); - return -1; - } + debug_printf ("s4uauth failed, bail out"); + cygheap->user.reimpersonate (); + return -1; } }