In the very early code path where `dll_crt0_1 ()` calls
`user_shared->initialize ()`, the Cygwin runtime calls `internal_pwsid ()`
to initialize the user name in preparation for reading the `fstab` file.
In case `db_home: env` is defined in `/etc/nsswitch.conf`, we need to
look at the environment variable `HOME` and use it, if set.
When all of this happens, though, the `pinfo_init ()` function has had no
chance to run yet (and therefore, `environ_init ()`). At this stage,
therefore, `getenv ()`'s `findenv_func ()` call still finds `getearly ()`
and we get the _verbatim_ value of `HOME`. That is, the Windows form.
But we need the "POSIX" form.
To add insult to injury, later calls to `getpwuid (getuid ())` will
receive a cached version of the home directory via
`cygheap->pg.pwd_cache.win.find_user ()` thanks to the first
`internal_pwsid ()` call caching the result via
`add_user_from_cygserver ()`, read: we will never receive the converted
`HOME` but always the Windows variant.
So, contrary to the assumptions made in 27376c60a9 (Allow deriving the
current user's home directory via the HOME variable, 2023-03-28), we
cannot assume that `getenv ("HOME")` returned a "POSIX" path.
This is a real problem. Even setting aside that common callers of
`getpwuid ()` (such as OpenSSH) are unable to handle Windows paths in the
`pw_dir` attribute, the Windows path never makes it back to the caller
unscathed. The value returned from `fetch_home_env ()` is not actually
used as-is. Instead, the `fetch_account_from_windows ()` method uses it
to write a pseudo `/etc/passwd`-formatted line that is _then_ parsed via
the `pwdgrp::parse_passwd ()` method which sees no problem with
misinterpreting the colon after the drive letter as a field separator of
that `/etc/passwd`-formatted line, and instead of a Windows path, we now
have a mere drive letter.
Let's detect when the `HOME` value is still in Windows format in
`fetch_home_env ()`, and convert it in that case.
For good measure, interpret this "Windows format" not only to include
absolute paths with drive prefixes, but also UNC paths.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
The account under which Azure Web Apps run is an IIS APPOOL account that
is generated on the fly.
These are special because the virtual machines on which thes Apps run
are not domain-joined, yet the accounts are domain accounts.
To support the use case where such a Web App needs to call `ssh` (e.g.
to deploy from a Git repository that is accessible only via SSH), we do
need OpenSSH's `getpwuid (getuid ())` invocation to work.
But currently it does not. Concretely, `getuid ()` returns -1 for these
accounts, and OpenSSH fails to find the correct home directory
(_especially_ when that home directory was overridden via a `db_home:
env` line in `/etc/nsswitch.conf`).
This can be verified e.g. in a Kudu console (for details about Kudu
consoles, see https://github.com/projectkudu/kudu/wiki/Kudu-console):
the domain is `IIS APPPOOL`, the account name is the name of the Azure
Web App, the SID starts with 'S-1-5-82-`, and
`pwdgrp::fetch_account_from_windows()` runs into the code path where
"[...] the domain returned by LookupAccountSid is not our machine name,
and if our machine is no domain member, we lose. We have nobody to ask
for the POSIX offset."
Since these IIS APPPOOL accounts are relatively similar to AzureAD
accounts in this scenario, let's imitate the latter to support also the
former.
Reported-by: David Ebbo <david.ebbo@gmail.com>
Helped-by: Corinna Vinschen <corinna@vinschen.de>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
We should not blindly set the home directory of the SYSTEM account (or
of Microsoft accounts) to `/home/<name>`, especially
`/etc/nsswitch.conf` defines `db_home: env`, in which case we want to
respect the `HOME` variable.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This patch hails from Git for Windows (where the Cygwin runtime is used
in the form of a slightly modified MSYS2 runtime), where it is a
well-established technique to let the `$HOME` variable define where the
current user's home directory is, falling back to `$HOMEDRIVE$HOMEPATH`
and `$USERPROFILE`.
The idea is that we want to share user-specific settings between
programs, whether they be Cygwin, MSYS2 or not. Unfortunately, we
cannot blindly activate the "db_home: windows" setting because in some
setups, the user's home directory is set to a hidden directory via an
UNC path (\\share\some\hidden\folder$) -- something many programs
cannot handle correctly, e.g. `cmd.exe` and other native Windows
applications that users want to employ as Git helpers.
The established technique is to allow setting the user's home directory
via the environment variables mentioned above: `$HOMEDRIVE$HOMEPATH` or
`$USERPROFILE`. This has the additional advantage that it is much
faster than querying the Windows user database.
Of course this scheme needs to be opt-in. For that reason, it needs
to be activated explicitly via `db_home: env` in `/etc/nsswitch.conf`.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
fetch_account_from_windows shortcuts the current user in that
it takes the user's domain SID and just adds the matching RID
from the token's primary group to create a group SID.
How wrong this is can be very simply reproduced:
Assuming you run a native process, like cmd, with primary group
set to the Administrators builtin group. Run Cygwin's id(1) as
child process. id(1) will print a non-existent group as primary
group and also add it to the group list.
This can only be avoided by not special casing the current user
and thus not creating a group SID from partial information.
Fixes: 6cc7c925ce ("(pwdgrp::fetch_account_from_windows): Default primary group for the
current user to primary group from user token.")
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
internal_getlogin overwrites the process token primary group if it
differs from the primary group as stored in the passwd DB.
However, this also overwrites the primary group of the process if
it has been deliberately changed by a former process (e. g., newgrp),
and the current process has a non-Cygwin process as parent.
Our docs claim we restrict overwriting the primary group to local,
non-domain user accounts anyway, and it was actually meant this way.
So check for exactly that before overwriting the primary group
in the token: It's only allowed if the user is a local account
and the primary group in the token is still the default group
"None".
Fixes: 6cc7c925ce ("(internal_getlogin): Give primary group
from user token more weight.")
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Originally the code was written to allow three ways of prefixing
accounts and to freely define a domain/account separator. This code
has been disabled even before being officially released, and it was
never re-enabled. Given there has been no complaints for eight years
now, drop this code eventually. Just add a macro to define the
domain/account separator statically.
Fixes: cc332c9e27 ("(cygheap_pwdgrp::nss_init_line): Disable db_prefix
and db_separator settings. Add comment")
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Remove "32" or "64" from each of the following names: acl32,
aclcheck32, aclfrommode32, aclfrompbits32, aclfromtext32, aclsort32,
acltomode32, acltopbits32, acltotext32, facl32, fchown32, fcntl64,
fstat64, _fstat64, _fstat64_r, ftruncate64, getgid32, getgrent32,
getgrgid32, getgrnam32, getgroups32, getpwuid32, getpwuid_r32,
getuid32, getuid32, initgroups32, lseek64, lstat64, mknod32, mmap64,
setegid32, seteuid32, setgid32, setgroups32, setregid32, setreuid32,
setuid32, stat64, _stat64_r, truncate64.
Remove prototypes and macro definitions of these names.
Remove "#ifndef __INSIDE_CYGWIN__" from some headers so that the new
names will be available when compiling Cygwin.
Remove aliases that are no longer needed.
Include <unistd.h> in fhandler_clipboard.cc for the declarations of
geteuid and getegid.
Remove the definitions of the following: acl, aclcheck, aclfrommode,
aclfrompbits, aclfromtext, aclsort, acltomode, acltopbits, acltotext,
chown, fchown, _fcntl, fstat, _fstat_r, ftruncate, getegid, geteuid, getgid,
getgrent, getgrgid, getgrnam, getgroups, getpwduid, getpwuid,
getpwuid_r, getuid, initgroups, lacl, lacl32, lchown, lseek, lstat,
mknod, mmap, setegid, seteuid, setgid, setgroups, setregid, setreuid,
setuid, stat, _stat_r, truncate.
[For most of these, the corresponding 64-bit entry points are obtained
by exporting aliases. For example, acl is an alias for acl32, and
truncate is an alias for truncate64.]
Remove the following structs and all code using them (which is 32-bit
only): __stat32, __group16, __flock32, __aclent16_t.
Remove the typedefs of __blkcnt32_t __dev16_t, __ino32_t, which are
used only in code that has been removed.
Put the typedefs of __uid16_t and __gid16_t in one header, instead of
one header if __INSIDE_CYGWIN__ is defined and a different header
otherwise.
Rather than fetching the system Windows directory at dll init time
only on 32 bit, fetch it on all platforms. Store as WCHAR and
UNICODE_STRING. Use where appropriate to simplify code.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This patch has been inspired by the Linux kernel patch
294f69e662d1 compiler_attributes.h: Add 'fallthrough' pseudo keyword for switch/case use
written by Joe Perches <joe AT perches DOT com> based on an idea from
Dan Carpenter <dan DOT carpenter AT oracle DOT com>. The following text
is from the original log message:
Reserve the pseudo keyword 'fallthrough' for the ability to convert the
various case block /* fallthrough */ style comments to appear to be an
actual reserved word with the same gcc case block missing fallthrough
warning capability.
All switch/case blocks now should end in one of:
break;
fallthrough;
goto <label>;
return [expression];
continue;
In C mode, GCC supports the __fallthrough__ attribute since 7.1,
the same time the warning and the comment parsing were introduced.
Cygwin-only: add an explicit -Wimplicit-fallthrough=5 to the build
flags.
The implicit assumption seemed to be that any subsequent occurence of
the same setting in nsswitch.conf is supposed to rewrite the previous
ones completely. This was not the case if the third or any further
schema was previously defined and the last line defined less than that
(but at least 2), for example:
```
db_home: windows cygwin /myhome/%U
db_home: cygwin desc
```
Let's document this behavior as well.
Signed-off-by: David Macek <david.macek.0@gmail.com>
If the first scheme in db_* was invalid, the code would think there
were no schemes specified and replace the second scheme with
NSS_SCHEME_DESC.
Signed-off-by: David Macek <david.macek.0@gmail.com>
Revert "Cywin: user profile: unload impersonation user profile on exit"
Revert "Cygwin: seteuid: allow inheriting impersonation user profile handle"
Revert "Cygwin: user profile: add debug output to unload_user_profile"
Revert "Cygwin: user profile: Make an effort to unload unused user profiles"
This reverts commit bcb33dc4f0.
This reverts commit dd3730ed9c.
This reverts commit 8eee25241e.
This reverts commit 71b8777a71.
This patchset actually results in the following problem:
- After a couple of ssh logon/logoff attempts, an interactive session
of the same user loging in, is broken.
Apparently UnloadUserProfile manages to unload the user's profile
even while a parallel interactive session still uses the user's
profile.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Does this work? There's not much feedback given.
TODO: We might want to try unloading the user profile at process
exit as well, FWIW.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Commit 4e34a39b5c made sure all user and
group names are case-correct, but it introduced a hefty performance hit
on starting the first Cygwin process.
Adding an ldap call for each AD group in a user token takes its toll in
bigger AD environments with lots of groups in a user token. Real-life
example: 300 groups w/ roundtrip time to the LDAP server of 0.25 secs
per call...
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This reverts commit 7c34811440.
This potentially allows to circumvent OpenSSHs user/group name matching,
unless the Admin knows to add every local user twice or to use patterns,
e.g.:
Match user MACHINE+user,.+user
Match user *+user
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
The solution from commit 9a3cc77b2a
didn't work for foreign domain accounts. Rather than calling
LookupAccountSid we now use the info when we fetch it anyway
via LDAP or Net*GetInfo. Only in case of domain groups we have
to add an LDAP call explicitly.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Make sure a domain+username fits into the local name buffer.
The former buffer size didn't take adding a domain name to
a really_really_long_user_name into account.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
When looking up valid accounts by name, LookupAccountName returns
a SID and a case-correct domain name. However, the name was input
and LookupAccountName is case-insensitive, so the name is not
necessarily written the same way as in SAM or AD.
Fix that by doing a reverse lookup on the just fetched SID. This
fetches the account name in the correct case. Override the
incoming name with the case correct name from LookupAccountSid.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
VirtualQueryEx, called by fixup_mmaps_after_fork, requires
PROCESS_QUERY_INFORMATION permissions per MSDN. However, testing
shows that PROCESS_QUERY_LIMITED_INFORMATION is sufficient when
running the same code on Windows 8.1 or Windows 10. Fix the code
to give the forked child always PROCESS_QUERY_INFORMATION perms
on Windows Vista/7 and respective server releases.
Revert now unneeded patch to check_token_membership as well.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
- Exec'ed/spawned processes don't need PROCESS_DUP_HANDLE. Remove that
permission from the parent handle.
- PROCESS_QUERY_LIMITED_INFORMATION doesn't work for Windows 7 if the
process is started as a service. Add PROCESS_QUERY_INFORMATION for
pre-Windows 8 in that case.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Starting with Windows 10, LookupAccountSid/Name return valid
info for the login session with new SID_NAME_USE value
SidTypeLogonSession. To return the same info as on pre-Windows 10,
we have to handle this type.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
First cut, still incomplete
* fhandler_socket is now base class for other socket classes
* fhandler_socket_inet handles AF_INET and AF_INET6 sockets
* fhandler_socket_local handles AF_LOCAL/AF_UNIX sockets
* finally get rid of fdsock by using set_socket_handle in accept4
* align file-related calls (fstat, fstatvfs, fchown, fchmod, facl)
to Linux.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
No real domain, no DC, no infos via NetUserGetInfo... nothing. Just nothing.
Use fixed uid 0x1000 (4096) for AzureAD user and gid 0x1001 (4097) for
AzureAD group. Note that this group is part of the user token, but it's
not the primary group. The primary group SID is, unfortunately, the
user's SID.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Bump GPLv2+ to GPLv3+ for some files, clarify BSD 2-clause.
Everything else stays under GPLv3+.
New Linking Exception exempts resulting executables from LGPLv3 section 4.
Add CONTRIBUTORS file to keep track of licensing.
Remove 'Copyright Red Hat Inc' comments.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
So far any group in the user's token could be used as primary group.
Windows doesn't check if the primary group is enabled or not, it just
has no meaning. From a POSIXy point of view it can lead to weird
results though.
* uinfo.cc (check_token_membership): New static function.
(internal_getlogin): Only allow enabled groups as primary group.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
A user token can be up to 64K in size. Using 32K buffers for TOKEN_GROUPS
may be insufficient.
* uinfo.cc (get_logon_sid): Use 64K buffers for the TOKEN_GROUPS
array.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
So far creating cygsids requires to generate an "S-1-..." string
which is then converted to a SID by cygsid::getfromstr.
Add two new methods:
- cygsid::create (DWORD auth, DWORD subauth_count, ...)
... is a variable length list of subauth_count DWORD values being
the actual subauths.
- cygsid::append (DWORD rid)
allows to append a single RID to an alreaday constituted SID.
* security.h (cygsid::create): Declare public.
(cygsid::append): Ditto.
* sec_helper.cc (cygsid::create): Implement.
(cygsid::append): Implement.
* uinfo.cc (pwdgrp::fetch_account_from_windows): Use both new
methods as appropriate. Drop setting csid from string. Create
SID strings for printing SIDs only.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
* uinfo.cc (pwdgrp::fetch_account_from_windows): Only create 1-5-32-x
SIDs from ids for x <= 999.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
* strfuncs.cc (sys_cp_wcstombs): Always return number of multibytes
without trailing NUL as the documentation implies. Throughout Cygwin,
fix usage to align to this pattern.
* fhandler_process.cc (format_process_winexename): Drop trailing NUL
and LF from output.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>