6867660301
Windows Explorer shows a warning with Cygwin-created DACLs, but putting the text of the warning into Google doesn't lead to the relevant Cygwin docs. Let's copy the warning text into the docs in the hopes of helping confused users. Most of the credit for the wording belongs to Yaakov Selkowitz. Latest inquiry: <https://cygwin.com/pipermail/cygwin/2020-May/244814.html> Signed-off-by: David Macek <david.macek.0@gmail.com>
2605 lines
95 KiB
XML
2605 lines
95 KiB
XML
<?xml version="1.0" encoding='UTF-8'?>
|
|
<!DOCTYPE sect1 PUBLIC "-//OASIS//DTD DocBook V4.5//EN"
|
|
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
|
|
|
|
<sect1 id="ntsec"><title>POSIX accounts, permission, and security</title>
|
|
|
|
<para>This section discusses how the Windows security model is
|
|
utilized in Cygwin to implement POSIX account information, POSIX-like
|
|
permissions, and how the Windows authentication model is used to allow
|
|
cygwin applications to switch users in a POSIX-like fashion.</para>
|
|
|
|
<para>The setting of POSIX-like file and directory permissions is
|
|
controlled by the <link linkend="mount-table">mount</link> option
|
|
<literal>(no)acl</literal> which is set to <literal>acl</literal> by
|
|
default.</para>
|
|
|
|
<para>We start with a short overview. Note that this overview must
|
|
be necessarily short. If you want to learn more about the Windows security
|
|
model, see the <ulink url="http://msdn.microsoft.com/en-us/library/aa374860(VS.85).aspx">Access Control</ulink> article in MSDN documentation.</para>
|
|
|
|
<para>POSIX concepts and in particular the POSIX security model are not
|
|
discussed here, but assumed to be understood by the reader. If you
|
|
don't know the POSIX security model, search the web for beginner
|
|
documentation.</para>
|
|
|
|
<sect2 id="ntsec-common"><title>Brief overview of Windows security</title>
|
|
|
|
<para>In the Windows security model, almost any "object" is securable.
|
|
"Objects" are files, processes, threads, semaphores, etc.</para>
|
|
|
|
<para>Every object has a data structure attached, called a "security
|
|
descriptor" (SD). The SD contains all information necessary to control
|
|
who can access an object, and to determine what they are allowed to do
|
|
to or with it. The SD of an object consists of five parts:</para>
|
|
|
|
<itemizedlist spacing="compact">
|
|
<listitem><para>Flags which control several aspects of this SD. This is
|
|
not discussed here.</para></listitem>
|
|
<listitem><para>The SID of the object owner.</para></listitem>
|
|
<listitem><para>The SID of the object owner group.</para></listitem>
|
|
<listitem><para>A list of "Access Control Entries" (ACE), called the
|
|
"Discretionary Access Control List" (DACL).</para></listitem>
|
|
<listitem><para>Another list of ACEs, called the "Security Access Control List"
|
|
(SACL), which doesn't matter for our purpose. We ignore it here.</para></listitem>
|
|
</itemizedlist>
|
|
|
|
<para>Every ACE contains a so-called "Security IDentifier" (SID) and
|
|
other stuff which is explained a bit later. Let's talk about the SID first.
|
|
</para>
|
|
|
|
<para>A SID is a unique identifier for users, groups, computers and
|
|
Active Directory (AD) domains. SIDs are basically comparable to POSIX
|
|
user ids (UIDs) and group ids (GIDs), but are more complicated because
|
|
they are unique across multiple machines or domains. A SID is a
|
|
structure of multiple numerical values. There's a convenient convention
|
|
to type SIDs, as a string of numerical fields separated by hyphen
|
|
characters. Here's an example:</para>
|
|
|
|
<para>SID of a machine "foo":</para>
|
|
|
|
<screen>
|
|
S-1-5-21-165875785-1005667432-441284377
|
|
</screen>
|
|
|
|
<para>SID of a user "johndoe" of the system "foo":</para>
|
|
|
|
<screen>
|
|
S-1-5-21-165875785-1005667432-441284377-1023
|
|
</screen>
|
|
|
|
<para>The first field is always "S", which is just a notational convention
|
|
to show that this is a SID. The second field is the version number of
|
|
the SID structure, So far there exists only one version of SIDs, so this
|
|
field is always 1. The third and fourth fields represent the "authority"
|
|
which can be thought of as a type or category of SIDs. There are a
|
|
couple of builtin accounts and accounts with very special meaning which
|
|
have certain well known values in these third and fourth fields.
|
|
However, computer and domain SIDs always start with "S-1-5-21". The
|
|
next three fields, all 32 bit values, represent the unique 96 bit
|
|
identifier of the computer system. This is a hopefully unique value all
|
|
over the world, but in practice it's sufficient if the computer SIDs are
|
|
unique within a single Windows network.</para>
|
|
|
|
<para>As you can see in the above example, SIDs of users (and groups)
|
|
are identical to the computer SID, except for an additional part, the
|
|
so-called "relative identifier" (RID). So the SID of a user is always
|
|
uniquely attached to the system on which the account has been generated.</para>
|
|
|
|
<para>It's a bit different in domains. The domain has its own SID, and
|
|
that SID is identical to the SID of the first domain controller, on
|
|
which the domain is created. Domain user SIDs look exactly like the
|
|
computer user SIDs, the leading part is just the domain SID and the RID
|
|
is created when the user is created.</para>
|
|
|
|
<para>Ok, consider you created a new domain "bar" on some new domain
|
|
controller and you would like to create a domain account "johndoe":</para>
|
|
|
|
<para>SID of a domain "bar.local":</para>
|
|
|
|
<screen>
|
|
S-1-5-21-186985262-1144665072-740312968
|
|
</screen>
|
|
|
|
<para>SID of a user "johndoe" in the domain "bar.local":</para>
|
|
|
|
<screen>
|
|
S-1-5-21-186985262-1144665072-740312968-1207
|
|
</screen>
|
|
|
|
<para>So you now have two accounts called johndoe, one account
|
|
created on the machine "foo", one created in the domain "bar.local".
|
|
Both have different SIDs and not even the RID is the same. How do
|
|
the systems know it's the same account? After all, the name is
|
|
the same, right? The answer is, these accounts are <emphasis
|
|
role='bold'>not</emphasis> identical. All machines on the network will
|
|
treat these SIDs as identifying two separate accounts. One is
|
|
"FOO\johndoe", the other one is "BAR\johndoe" or "johndoe@bar.local".
|
|
Different SID, different account. Full stop. </para>
|
|
|
|
<para>Starting with Cygwin 1.7.34, Cygwin uses an automatic, internal
|
|
translation from Windows SID to POSIX UID/GID. This mechanism, which is
|
|
the preferred method for the SID<=>UID/GID mapping, is described in
|
|
detail in <xref linkend="ntsec-mapping"></xref>.</para>
|
|
|
|
<para>Prior to Cygwin 1.7.34, the last part of the SID, the so called
|
|
"Relative IDentifier" (RID), was by default used as UID and/or GID
|
|
when you created the <filename>/etc/passwd</filename> and
|
|
<filename>/etc/group</filename> files using the
|
|
<command><link linkend="mkpasswd">mkpasswd</link></command> and
|
|
<command><link linkend="mkgroup">mkgroup</link></command> tools.
|
|
These tools as well as reading accounts from <filename>/etc/passwd</filename>
|
|
and <filename>/etc/group</filename> files is still present in recent
|
|
versions of Cygwin, but you should switch to the aforementioned
|
|
automatic translation, unless you have very specific needs. Again,
|
|
see <xref linkend="ntsec-mapping"></xref> for the details.</para>
|
|
|
|
<para>Do you still remember the SIDs with special meaning? In offical
|
|
notation they are called "well-known SIDs". For example, POSIX has no GID
|
|
for the group of "all users" or "world" or "others". The last three rwx
|
|
bits in a unix-style permission value just represent the permissions for
|
|
"everyone who is not the owner or is member of the owning group".
|
|
Windows has a SID for these poor souls, the "Everyone" SID. Other
|
|
well-known SIDs represent circumstances under which a process is
|
|
running, rather than actual users or groups. Here are a few examples
|
|
for well-known SIDs:</para>
|
|
|
|
<screen>
|
|
Everyone S-1-1-0 Simply everyone...
|
|
Batch S-1-5-3 Processes started via the task
|
|
scheduler are member of this group.
|
|
Interactive S-1-5-4 Only processes of users which are
|
|
logged in via an interactive
|
|
session are members here.
|
|
Authenticated Users S-1-5-11 Users which have gone through
|
|
the authentication process and
|
|
survived. Anonymously accessing
|
|
users are not incuded here.
|
|
SYSTEM S-1-5-18 A special account which has all
|
|
kinds of dangerous rights, sort of
|
|
an uber-root account.
|
|
</screen>
|
|
|
|
<para>For a full list please refer to the MSDN document <ulink
|
|
url="http://msdn.microsoft.com/en-us/library/aa379649.aspx">Well-known
|
|
SIDs</ulink>. The Cygwin package called "csih" provides a tool,
|
|
/usr/lib/csih/getAccountName.exe, which can be used to print the
|
|
(possibly localized) name for the various well-known SIDS.</para>
|
|
|
|
<para>Naturally, well-known SIDs are the same on each machine, so they are
|
|
not unique to a machine or domain. They have the same meaning across
|
|
the Windows network.</para>
|
|
|
|
<para>Additionally, there are a couple of well-known builtin groups,
|
|
which have the same SID on every machine and which have certain user
|
|
rights by default:</para>
|
|
|
|
<screen>
|
|
administrators S-1-5-32-544
|
|
users S-1-5-32-545
|
|
guests S-1-5-32-546
|
|
...
|
|
</screen>
|
|
|
|
<para>For instance, every account is usually member in the "Users"
|
|
group. All administrator accounts are member of the "Administrators"
|
|
group. That's all about it as far as single machines are involved. In
|
|
a domain environment it's a bit more tricky. Since these SIDs are not
|
|
unique to a machine, every domain user and every domain group can be a
|
|
member of these well known groups. Consider the domain group "Domain
|
|
Admins". This group is by default in the "Administrators" group. Let's
|
|
assume the above computer called "foo" is a member machine of the domain
|
|
"bar.local". If you stick the user "BAR\johndoe" into the group "Domain
|
|
Admins", this guy will automatically be a member of the administrators
|
|
group on "foo" when logging on to "foo". Neat, isn't it?</para>
|
|
|
|
<para>Back to ACE and ACL. POSIX is able to create three different
|
|
permissions, the permissions for the owner, for the group and for the
|
|
world. In contrast the Windows ACL has a potentially infinite number of
|
|
members... as long as they fit into 64K. Every member is an ACE.
|
|
ACE consist of three parts:</para>
|
|
|
|
<itemizedlist spacing="compact">
|
|
<listitem><para>The type of the ACE (allow ACE or deny ACE).</para></listitem>
|
|
<listitem><para>Permission bits, 32 of them.</para></listitem>
|
|
<listitem><para>The SID for which the permissions are allowed or denied.</para></listitem>
|
|
</itemizedlist>
|
|
|
|
<para>The two (for us) important types of ACEs are the "access allowed
|
|
ACE" and the "access denied ACE". As the names imply, the allow ACE
|
|
tells the system to allow the given permissions to the SID, the deny ACE
|
|
results in denying the specific permission bits.</para>
|
|
|
|
<para>The possible permissions on objects are more detailed than in
|
|
POSIX. For example, the permission to delete an object is different
|
|
from the permission to change object data, and even changing object data
|
|
can be separated into different permission bits for different kind of
|
|
data. But there's a problem with the definition of a "correct" ACL
|
|
which disallows mapping of certain POSIX permissions cleanly. See
|
|
<xref linkend="ntsec-files"></xref>.</para>
|
|
|
|
<para>POSIX is able to create only three different permissions? Not quite.
|
|
Newer operating systems and file systems on POSIX systems also provide
|
|
access control lists. Two different APIs exist for accessing these
|
|
ACLs, the Solaris API and the POSIX API. Cygwin implements the original
|
|
Solaris API to access Windows ACLs in a Unixy way. Online man pages for the
|
|
Solaris ACL API can be found on
|
|
<ulink url="http://docs.oracle.com">http://docs.oracle.com</ulink>.
|
|
For an overview see <ulink url="http://docs.oracle.com/cd/E23824_01/html/821-1474/acl-5.html#scrolltoc">acl(5)</ulink>.</para>
|
|
|
|
</sect2>
|
|
|
|
<sect2 id="ntsec-mapping"><title id="ntsec-mapping.title">Mapping Windows accounts to POSIX accounts</title>
|
|
|
|
<para>
|
|
For as long as Cygwin has existed, it has stored user and group information in
|
|
<filename>/etc/passwd</filename> and <filename>/etc/group</filename> files.
|
|
Under the assumption that these files would never be too large, the first
|
|
process in a process tree, as well as every execing process within the tree
|
|
would parse them into structures in memory. Thus every Cygwin process would
|
|
contain an expanded copy of the full information from
|
|
<filename>/etc/passwd</filename> and <filename>/etc/group</filename>.
|
|
</para>
|
|
|
|
<para>
|
|
This approach has a few downsides. One of them is that the idea that these
|
|
files will always be small, is flawed. Another one is that reading the entire
|
|
file is most of the time entirely useless, since most processes only
|
|
need information on their own user and the primary group. Last but not
|
|
least, the passwd and group files have to be maintained separately from
|
|
the already existing Windows user databases, the local SAM and Active
|
|
Directory.
|
|
</para>
|
|
|
|
<para>
|
|
On the other hand, we have to have this mapping between Windows SIDs and
|
|
POSIX uid/gid values, so we need a mechanism to convert SIDs to uid/gid
|
|
values and vice versa.
|
|
</para>
|
|
|
|
<para>
|
|
Microsoft "Services for UNIX" (SFU) (deprecated since Windows 8/Server 2012)
|
|
never used passwd/group files. Rather, SFU used a fixed, computational mapping
|
|
between SIDs and POSIX uid/gid which even has Active Directory support. It
|
|
allows us to generate uid/gid values from SIDs and vice versa. The mechanism is
|
|
documented, albeit in a confusing way and spread over multiple MSDN articles.
|
|
</para>
|
|
|
|
<para>
|
|
Starting with Cygwin 1.7.34, Cygwin utilizes an approach inspired by the
|
|
mapping method as implemented by SFU, with a few differences for backward
|
|
compatibility and to handle some border cases differently.
|
|
</para>
|
|
|
|
<sect3 id="ntsec-mapping-how"><title id="ntsec-mapping-how.title">Mapping Windows SIDs to POSIX uid/gid values</title>
|
|
|
|
<para>
|
|
The following description assumes you're comfortable with the concept of
|
|
Windows SIDs and RIDs. For a brief introduction, see
|
|
<xref linkend="ntsec-common"></xref>.
|
|
</para>
|
|
|
|
<para>
|
|
Cygwin's mapping between SIDs and uid/gid values works in two ways.
|
|
</para>
|
|
|
|
<itemizedlist spacing="compact">
|
|
<listitem><para>Read <filename>/etc/passwd<filename> and
|
|
</filename>/etc/group</filename> files if they exist, just as in the olden
|
|
days, mainly for backward compatibility.</para></listitem>
|
|
<listitem><para>If no files are present, or if an entry is missing in the files,
|
|
ask Windows.</para></listitem>
|
|
</itemizedlist>
|
|
|
|
<para>
|
|
At least, that's the default behaviour now. It will be configurable
|
|
using a file <filename>/etc/nsswitch.conf</filename>, which is discussed in
|
|
<xref linkend="ntsec-mapping-nsswitch"></xref>. Let's explore the default
|
|
for now.
|
|
</para>
|
|
|
|
<para>
|
|
If the passwd or group files are present, they will be scanned on demand as
|
|
soon as a mapping from SIDs to uid/gid or account names is required. The new
|
|
mechanism will never read the entire file into memory, but only scan for
|
|
the requested entry and cache this one in memory.
|
|
</para>
|
|
|
|
<para>
|
|
If no entry is found, or no passwd or group file was present, Cygwin
|
|
will ask the OS.
|
|
</para>
|
|
|
|
<note>
|
|
<para>
|
|
If the first process in a Cygwin process tree determines that no
|
|
<filename>/etc/passwd</filename> or <filename>/etc/group</filename> file is
|
|
present, no other process in the entire process tree will try to read the files
|
|
later on. This is done for self-preservation. It's rather bad if the uid
|
|
or gid of a user changes during the lifetime of a process tree.
|
|
</para>
|
|
|
|
<para>
|
|
For the same reason, if you delete the <filename>/etc/passwd</filename>
|
|
or <filename>/etc/group</filename> file, this will be ignored. The passwd
|
|
and group records read from the files will persist in memory until either a
|
|
new <filename>/etc/passwd</filename> or <filename>/etc/group</filename>
|
|
is created, or you exit all processes in the current process tree.
|
|
</para>
|
|
|
|
<para>
|
|
See the note in <xref linkend="ntsec-mapping-nsswitch"></xref> for some
|
|
comprehensive examples.
|
|
</para>
|
|
</note>
|
|
|
|
<para>
|
|
So if we've drawn a blank reading the files, we're going to ask the OS.
|
|
First thing, we ask the local machine for the SID or the username. The
|
|
OS functions
|
|
<ulink url="http://msdn.microsoft.com/en-us/library/windows/desktop/aa379166%28v=vs.85%29.aspx">LookupAccountSid</ulink>
|
|
and
|
|
<ulink url="http://msdn.microsoft.com/en-us/library/windows/desktop/aa379159%28v=vs.85%29.aspx">LookupAccountName</ulink>
|
|
are pretty intelligent. They have all the stuff built in to ask for any
|
|
account of the local machine, the Active Directory domain of the machine,
|
|
the Global Catalog of the forest of the domain, as well as any trusted
|
|
domain of our forest for the information. One OS call and we're
|
|
practically done...
|
|
</para>
|
|
|
|
<para>
|
|
Except, the calls only return the mapping between SID, account name and the
|
|
account's domain. We don't have a mapping to POSIX uid/gid and we're missing
|
|
information on the user's home dir and login shell.
|
|
</para>
|
|
|
|
<para>
|
|
Let's discuss the SID<=>uid/gid mapping first. Here's how it works.
|
|
</para>
|
|
|
|
<itemizedlist spacing="compact">
|
|
|
|
<listitem>
|
|
<para>
|
|
<ulink url="http://msdn.microsoft.com/en-us/library/aa379649.aspx">Well-known
|
|
SIDs</ulink>
|
|
in the NT_AUTHORITY domain of the S-1-5-RID type, or aliases of the
|
|
S-1-5-32-RID type are mapped to the uid/gid value RID. Examples:
|
|
</para>
|
|
|
|
<screen>
|
|
"SYSTEM" S-1-5-18 <=> uid/gid: 18
|
|
"Users" S-1-5-32-545 <=> uid/gid: 545
|
|
</screen>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
Other well-known SIDs in the NT_AUTHORITY domain (S-1-5-X-RID):
|
|
</para>
|
|
|
|
<screen>
|
|
S-1-5-X-RID <=> uid/gid: 0x1000 * X + RID
|
|
</screen>
|
|
|
|
<para>Example:</para>
|
|
|
|
<screen>
|
|
"NTLM Authentication" S-1-5-64-10 <=> uid/gid: 0x4000A == 262154
|
|
</screen>
|
|
</listitem>
|
|
|
|
<listitem><para>
|
|
Other well-known SIDs:
|
|
</para>
|
|
|
|
<screen>
|
|
S-1-X-Y <=> uid/gid: 0x10000 + 0x100 * X + Y
|
|
</screen>
|
|
|
|
<para>Example:</para>
|
|
|
|
<screen>
|
|
"LOCAL" S-1-2-0 <=> uid/gid: 0x10200 == 66048
|
|
"Creator Group" S-1-3-1 <=> uid/gid: 0x10301 == 66305
|
|
</screen>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
Logon SIDs: The LogonSid of the current user's session is converted to the
|
|
fixed uid 0xfff == 4095 and named "CurrentSession". Any other LogonSid is
|
|
converted to the fixed uid 0xffe == 4094 and named "OtherSession".
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
Mandatory Labels:
|
|
</para>
|
|
|
|
<screen>
|
|
S-1-16-RID <=> uid/gid: 0x60000 + RID
|
|
</screen>
|
|
|
|
<para>Example:</para>
|
|
|
|
<screen>
|
|
"Medium Mandatory Level" S-1-16-8192 <=> uid/gid: 0x62000 == 401408
|
|
</screen>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
Accounts from the local machine's user DB (SAM):
|
|
</para>
|
|
|
|
<screen>
|
|
S-1-5-21-X-Y-Z-RID <=> uid/gid: 0x30000 + RID
|
|
</screen>
|
|
|
|
<para>Example:</para>
|
|
|
|
<screen>
|
|
"Administrator" S-1-5-21-X-Y-Z-500 <=> uid/gid: 0x301f4 == 197108
|
|
</screen>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
Accounts from the machine's primary domain:
|
|
</para>
|
|
|
|
<screen>
|
|
S-1-5-21-X-Y-Z-RID <=> uid/gid: 0x100000 + RID
|
|
</screen>
|
|
|
|
<para>Example:</para>
|
|
|
|
<screen>
|
|
"Domain Users" S-1-5-21-X-Y-Z-513 <=> uid/gid: 0x100201 == 1049089
|
|
</screen>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
Accounts from a trusted domain of the machine's primary domain:
|
|
</para>
|
|
|
|
<screen>
|
|
S-1-5-21-X-Y-Z-RID <=> uid/gid: trustPosixOffset(domain) + RID
|
|
</screen>
|
|
|
|
<para>
|
|
<literal>trustPosixOffset</literal>? This needs a bit of explanation. This
|
|
value exists in Windows domains already since before Active Directory days.
|
|
What happens is this. If you create a domain trust between two domains, a
|
|
trustedDomain entry will be added to both databases. It describes how
|
|
<emphasis>this</emphasis> domain trusts the <emphasis>other</emphasis> domain.
|
|
One attribute of a trust is a 32 bit value called
|
|
<literal>trustPosixOffset</literal> For each new trust,
|
|
<literal>trustPosixOffset</literal> will get some automatic value. In recent
|
|
AD domain implementations, the first trusted domain will get
|
|
<literal>trustPosixOffset</literal> set to 0x80000000. Following domains will
|
|
get lower values. Unfortunately the domain admins are allowed to set the
|
|
<literal>trustPosixOffset</literal> value for each trusted domain to some
|
|
arbitrary 32 bit value, no matter what the other
|
|
<literal>trustPosixOffset</literal> are set to, thus allowing any kind of
|
|
collisions between the <literal>trustPosixOffset</literal> values of domains.
|
|
That's not exactly helpful, but as the user of this value, we have to
|
|
<emphasis>trust</emphasis> the domain admins to set
|
|
<literal>trustPosixOffset</literal> to sensible values, or to keep it at the
|
|
system chosen defaults.
|
|
</para>
|
|
|
|
<para>
|
|
So, for the first (or only) trusted domain of your domain, the automatic offset
|
|
is 0x80000000. An example for a user of that trusted domain is
|
|
</para>
|
|
|
|
<screen>
|
|
S-1-5-21-X-Y-Z-1234 <=> uid/gid 0x800004d2 == 2147484882
|
|
</screen>
|
|
|
|
<para>
|
|
There's one problem with this approach. Assuming you're running in the context
|
|
of a local SAM user on a domain member machine. Local users don't have the
|
|
right to fetch this kind of domain information from the DC, they'll get
|
|
permission denied. In this case Cygwin will fake a sensible
|
|
<literal>trustPosixOffset</literal> value.
|
|
</para>
|
|
|
|
<para>
|
|
Another problem is if the AD administrators chose an unreasonably small
|
|
<literal>trustPosixOffset</literal> value. Anything below the hexadecimal
|
|
value 0x100000 (the POSIX offset of the primary domain) is bound to produce
|
|
collisions with system accounts as well as local accounts. The right thing
|
|
to do in this case is to notify your administrator of the problem and to ask
|
|
for moving the offset to a more reasonable value. However, to reduce the
|
|
probability for collisions, Cygwin overrides this offset with a sensible
|
|
fixed replacement offset.
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
Local accounts from another machine in the network:
|
|
</para>
|
|
|
|
<para>
|
|
There's no SID<=>uid/gid mapping implemented for this case. The problem
|
|
is, there's no way to generate a bijective mapping. There's no central place
|
|
which keeps an analogue of the <literal>trustPosixOffset</literal>, and there's
|
|
the additional problem that the
|
|
<ulink url="http://msdn.microsoft.com/en-us/library/windows/desktop/aa379166%28v=vs.85%29.aspx">LookupAccountSid</ulink>
|
|
and
|
|
<ulink url="http://msdn.microsoft.com/en-us/library/windows/desktop/aa379159%28v=vs.85%29.aspx">LookupAccountName</ulink>
|
|
functions cannnot resolve the SIDs, unless they know the name of the machine
|
|
this SID comes from. And even then it will probably suffer a
|
|
<literal>Permission denied</literal> error when trying to ask the machine
|
|
for its local account.
|
|
</para>
|
|
</listitem>
|
|
|
|
</itemizedlist>
|
|
|
|
<para>
|
|
Now we have a semi-bijective mapping between SIDs and POSIX uid/gid values,
|
|
but given that we have potentially users and groups in different domains having
|
|
the same name, how do we uniquely distinguish between them by name? Well, we
|
|
can do that by making their names unique in a per-machine way. Dependent on
|
|
the domain membership of the account, and dependent of the machine being a
|
|
domain member or not, the user and group names will be generated using a domain
|
|
prefix and a separator character between domain and account name.
|
|
The <!-- default --> separator character is the plus sign, <literal>+</literal>.
|
|
</para>
|
|
|
|
<itemizedlist spacing="compact">
|
|
|
|
<listitem>
|
|
<para>
|
|
Well-known and builtin accounts will be named as in Windows:
|
|
</para>
|
|
|
|
<screen>
|
|
"SYSTEM", "LOCAL", "Medium Mandatory Level", ...
|
|
</screen>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
If the machine is not a domain member machine, only local accounts can be resolved
|
|
into names, so for ease of use, just the account names are used as Cygwin
|
|
user/group names:
|
|
</para>
|
|
|
|
<screen>
|
|
"corinna", "bigfoot", "None", ...
|
|
</screen>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
If the machine is a domain member machine, all accounts from the primary domain
|
|
of the machine are mapped to Cygwin names without domain prefix:
|
|
</para>
|
|
|
|
<screen>
|
|
"corinna", "bigfoot", "Domain Users", ...
|
|
</screen>
|
|
|
|
<para>
|
|
while accounts from other domains are prepended by their domain:
|
|
</para>
|
|
|
|
<screen>
|
|
"DOMAIN1+corinna", "DOMAIN2+bigfoot", "DOMAIN3+Domain Users", ...
|
|
</screen>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
Local machine accounts of a domain member machine get a Cygwin user name the
|
|
same way as accounts from another domain: The local machine name gets
|
|
prepended:
|
|
</para>
|
|
|
|
<screen>
|
|
"MYMACHINE+corinna", "MYMACHINE+bigfoot", "MYMACHINE+None", ...
|
|
</screen>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
If LookupAccountSid fails, Cygwin checks the accounts against the known trusted
|
|
domains. If the account is from one of the trusted domains, an artificial
|
|
account name is created. It consists of the domain name, and a special name
|
|
created from the account RID:
|
|
</para>
|
|
|
|
<screen>
|
|
"MY_DOM+User(1234)", "MY_DOM+Group(5678)"
|
|
</screen>
|
|
|
|
<para>
|
|
Otherwise we know nothing about this SID, so it will be mapped to the
|
|
fake accounts <literal>Unknown+User</literal>/<literal>Unknown+Group</literal>
|
|
with uid/gid -1.
|
|
</para>
|
|
</listitem>
|
|
|
|
</itemizedlist>
|
|
|
|
</sect3>
|
|
|
|
<sect3 id="ntsec-mapping-caching"><title id="ntsec-mapping-caching.title">Caching account information</title>
|
|
|
|
<para>
|
|
The information fetched from the Windows account database or the
|
|
<filename>/etc/passwd</filename> and <filename>/etc/group</filename> files is
|
|
cached by the process. The cached information is inherited by Cygwin child
|
|
processes. A Cygwin process invoked from a Windows command, such as CMD.exe,
|
|
will start a new Cygwin process tree and the caching starts from scratch
|
|
(unless <command><link linkend="using-cygserver">cygserver</link></command> is
|
|
running, but read on).
|
|
</para>
|
|
|
|
<para>
|
|
While usually working fine, this has some drawbacks. Consider a shell calling
|
|
<command>id</command>. <command>id</command> fetches all group information
|
|
from the current token and caches them. Unfortunately <command>id</command>
|
|
doesn't start any child processes, so the information is lost as soon as
|
|
<command>id</command> exits.
|
|
</para>
|
|
|
|
<para>
|
|
But there's another caching mechanism available. If
|
|
<command><link linkend="using-cygserver">cygserver</link></command> is running
|
|
it will provide passwd and group entry caching for all processes in every Cygwin
|
|
process tree started after
|
|
<command><link linkend="using-cygserver">cygserver</link></command>. So, if
|
|
you start a Cygwin Terminal and
|
|
<command><link linkend="using-cygserver">cygserver</link></command> is running
|
|
at the time, <command>mintty</command>, the shell, and all child processes will
|
|
use <command><link linkend="using-cygserver">cygserver</link></command> caching.
|
|
If you start a Cygwin Terminal and
|
|
<command><link linkend="using-cygserver">cygserver</link></command> is not
|
|
running at the time, none of the processes started inside this terminal window
|
|
will use <command><link linkend="using-cygserver">cygserver</link></command>
|
|
caching.
|
|
</para>
|
|
|
|
<para>
|
|
The advantage of
|
|
<command><link linkend="using-cygserver">cygserver</link></command> caching is
|
|
that it's system-wide and, as long as
|
|
<command><link linkend="using-cygserver">cygserver</link></command> is running,
|
|
unforgetful. Every Cygwin process on the system will have the
|
|
<command><link linkend="using-cygserver">cygserver</link></command> cache at
|
|
its service. Additionally, all information requested from
|
|
<command><link linkend="using-cygserver">cygserver</link></command> once, will
|
|
be cached inside the process itself and, again, propagated to child processes.
|
|
</para>
|
|
|
|
<para>
|
|
If you automatically start Cygwin processes as Windows services at system
|
|
startup, you may wish to consider starting
|
|
<command><link linkend="using-cygserver">cygserver</link></command> first in
|
|
order to take advantage of this system-wide caching. To assure that
|
|
<command><link linkend="using-cygserver">cygserver</link></command> has started
|
|
prior to starting <command>sshd</command> or other Cygwin processes, you may
|
|
wish to create service startup dependencies.
|
|
<command><link linkend="using-cygserver">Cygserver</link></command> should
|
|
probably wait for Windows TCPIP and AFD services before it starts, and then
|
|
other Cygwin process should start after
|
|
<command><link linkend="using-cygserver">cygserver</link></command>. Example
|
|
Windows commands to accomplish this (after the services already exist) are
|
|
shown below. You will need an administrative prompt to run the
|
|
<command>sc config</command> commands.
|
|
</para>
|
|
|
|
<screen>
|
|
# Delay Cygserver until TCPIP and AFD have started
|
|
# Note the (odd) required space character after "depend="
|
|
|
|
sc config cygserver depend= tcpip/afd
|
|
|
|
# Delay sshd until after Cygserver has started
|
|
# Again note the (odd) required space character after "depend="
|
|
|
|
sc config sshd depend= cygserver
|
|
|
|
# View the Cygserver service details
|
|
|
|
sc qc cygserver
|
|
</screen>
|
|
|
|
<para>
|
|
Note that this <command>sc config</command> command
|
|
<emphasis>replaces</emphasis> any existing dependencies. The above changes
|
|
will not impact the running instance, only future instances.
|
|
</para>
|
|
|
|
<screen>
|
|
# To remove all dependencies from the cygserver service
|
|
|
|
sc config cygserver depend= /
|
|
</screen>
|
|
|
|
</sect3>
|
|
|
|
<sect3 id="ntsec-mapping-passwdinfo"><title id="ntsec-mapping-passwdinfo.title">Cygwin user names, home dirs, login shells</title>
|
|
|
|
<para>
|
|
Obviously, if you don't maintain <filename>passwd</filename> and
|
|
<filename>group</filename> files, you need to have a way to maintain the other
|
|
fields of a passwd entry as well. A couple of things come to mind:
|
|
</para>
|
|
|
|
<itemizedlist spacing="compact">
|
|
|
|
<listitem>
|
|
<para>
|
|
You want to use a Cygwin username different from your Windows username.
|
|
</para>
|
|
|
|
<note><para>
|
|
This is only supported via <filename>/etc/passwd</filename>. A Cygwin
|
|
username maintained in the Windows user databases would require very costly
|
|
(read: slow) search operations.
|
|
</para></note>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
You want to change the primary group of a user. For AD accounts this is
|
|
not supported. The primary group of a user is always the Windows
|
|
primary group set in Active Directory and can't be changed. For SAM
|
|
accounts, you can add the primary group to the SAM
|
|
<literal>description</literal> field of the user. See <xref
|
|
linkend="ntsec-mapping-nsswitch-desc"></xref> for more info.
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
You want a home dir different from the default
|
|
<filename>/home/$USERNAME</filename>.
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
You want to specify a different login shell than <filename>/bin/bash</filename>.
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
You want to add specific content to the pw_gecos field.
|
|
</para>
|
|
</listitem>
|
|
|
|
</itemizedlist>
|
|
|
|
<para>
|
|
For simple needs you can create <filename>/etc/passwd</filename> and/or
|
|
<filename>/etc/group</filename> files with entries for your account
|
|
and tweak that.
|
|
</para>
|
|
|
|
<para>
|
|
For bigger installations, maintaining per-client files is rather troublesome.
|
|
Also, no two environments are the same, so the needs are pretty different.
|
|
Therefore Cygwin supports configuring how to fetch home directory,
|
|
login shell, and gecos information in /etc/nsswitch.conf. See the next
|
|
section for detailed information how to configure Cygwin's account handling.
|
|
</para>
|
|
|
|
</sect3>
|
|
|
|
<sect3 id="ntsec-mapping-nsswitch"><title id="ntsec-mapping-nsswitch.title">The <filename>/etc/nsswitch.conf</filename> file</title>
|
|
|
|
<para>
|
|
On Linux and some other UNIXy OSes, we have a file called
|
|
<ulink url="http://linux.die.net/man/5/nsswitch.conf">/etc/nsswitch.conf</ulink>.
|
|
Among other things, it determines how passwd and group entries are generated.
|
|
That's what Cygwin now provides as well.
|
|
</para>
|
|
|
|
<para>
|
|
The <filename>/etc/nsswitch.conf</filename> file is optional. If you don't
|
|
have one, Cygwin uses sensible defaults.
|
|
</para>
|
|
|
|
<note>
|
|
<para>
|
|
The <filename>/etc/nsswitch.conf</filename> file is read exactly once by
|
|
the first process of a Cygwin process tree. If there was no
|
|
<filename>/etc/nsswitch.conf</filename> file when this first process started,
|
|
then no other process in the running Cygwin process tree will try to read the
|
|
file.
|
|
</para>
|
|
|
|
<para>
|
|
If you create or change <filename>/etc/nsswitch.conf</filename>, you have to
|
|
restart all Cygwin processes that need to see the change. If the process
|
|
you want to see the change is a child of another process, you need to restart
|
|
all of that process's parents, too.
|
|
</para>
|
|
|
|
<para>
|
|
For example, if you run <command>vim</command> inside the default Cygwin
|
|
Terminal, <command>vim</command> is a child of your shell, which is a child
|
|
of <command>mintty</command>. If you edit
|
|
<filename>/etc/nsswitch.conf</filename> in that <command>vim</command>
|
|
instance, your shell won't immediately see the change, nor will
|
|
<command>vim</command> if you restart it from that same shell instance.
|
|
This is because both are getting their nsswitch information from their
|
|
ancestor, <command>mintty</command>. You have to start a fresh terminal
|
|
window for the change to take effect.
|
|
</para>
|
|
|
|
<para>
|
|
By contrast, if you leave that Cygwin Terminal window open after making the
|
|
change to <filename>/etc/nsswitch.conf</filename>, then restart a Cygwin
|
|
service like <command>cron</command>, <command>cron</command> will see the
|
|
change, because it is not a child of <command>mintty</command> or any other
|
|
Cygwin process. (Technically, it is a child of <command>cygrunsrv</command>,
|
|
but that instance also restarts when you restart the service.)
|
|
</para>
|
|
|
|
<para>
|
|
The reason we point all this out is that the requirements for restarting
|
|
things are not quite as stringent as when you replace
|
|
<filename>cygwin1.dll</filename>. If you have three process trees, you have
|
|
three independent copies of the nsswitch information. If you start a fresh
|
|
process tree, it will see the changes. As long as any process in an existing
|
|
process tree remains running, all processes in that tree will continue to use
|
|
the old information.
|
|
</para>
|
|
</note>
|
|
|
|
<para>
|
|
So, what settings can we perform with <filename>/etc/nsswitch.conf</filename>?
|
|
Let's start with an example <filename>/etc/nsswitch.conf</filename> file
|
|
set up to all default values:
|
|
</para>
|
|
|
|
<screen>
|
|
# /etc/nsswitch.conf
|
|
passwd: files db
|
|
group: files db
|
|
<!--
|
|
db_prefix: auto
|
|
db_separator: + -->
|
|
db_enum: cache builtin
|
|
db_home: /home/%U
|
|
db_shell: /bin/bash
|
|
db_gecos: <empty>
|
|
</screen>
|
|
|
|
<sect4 id="ntsec-mapping-nsswitch-syntax"><title id="ntsec-mapping-nsswitch-syntax.title">The <filename>/etc/nsswitch.conf</filename> syntax</title>
|
|
|
|
<para>
|
|
The first line, starting with a hash <literal>#</literal> is a comment.
|
|
The hash character starts a comment, just as in shell scripts. Everything
|
|
up to the end of the line is ignored. So this:
|
|
</para>
|
|
|
|
<screen>
|
|
foo: bar # baz
|
|
</screen>
|
|
|
|
<para>
|
|
means, set "foo" to value "bar", ignore everything after the hash.
|
|
</para>
|
|
|
|
<para>
|
|
The other lines define the available settings. The first word up to a
|
|
colon is a keyword. Note that the colon <emphasis>must</emphasis> follow
|
|
immediately after the keyword. This is a valid line:
|
|
</para>
|
|
|
|
<screen>
|
|
foo: bar
|
|
</screen>
|
|
|
|
<para>
|
|
This is not valid:
|
|
</para>
|
|
|
|
<screen>
|
|
foo : bar
|
|
</screen>
|
|
|
|
<para>
|
|
Apart from this restriction, the remainder of the line can have as
|
|
many spaces and TABs as you like.
|
|
</para>
|
|
|
|
<para>
|
|
When the same keyword occurs multiple times, the last one wins, as if the
|
|
previous ones were ignored.
|
|
</para>
|
|
|
|
</sect4>
|
|
|
|
<sect4 id="ntsec-mapping-nsswitch-pwdgrp"><title id="ntsec-mapping-nsswitch-pwdgrp.title">The <literal>passwd:</literal> and <literal>group:</literal> settings</title>
|
|
|
|
<para>
|
|
The two lines starting with the keywords <literal>passwd:</literal> and
|
|
<literal>group:</literal> define where Cygwin gets its passwd and group
|
|
information from. <literal>files</literal> means, fetch the information
|
|
from the corresponding file in the /etc directory. <literal>db</literal>
|
|
means, fetch the information from the Windows account databases, the SAM
|
|
for local accounts, Active Directory for domain account. Examples:
|
|
</para>
|
|
|
|
<screen>
|
|
passwd: files
|
|
</screen>
|
|
|
|
<para>
|
|
Read passwd entries only from /etc/passwd.
|
|
</para>
|
|
|
|
<screen>
|
|
group: db
|
|
</screen>
|
|
|
|
<para>
|
|
Read group entries only from SAM/AD.
|
|
</para>
|
|
|
|
<screen>
|
|
group: files # db
|
|
</screen>
|
|
|
|
<para>
|
|
Read group entries only from <filename>/etc/group</filename>
|
|
(<literal>db</literal> is only a comment).
|
|
</para>
|
|
|
|
<screen>
|
|
passwd: files db
|
|
</screen>
|
|
|
|
<para>
|
|
Read passwd entries from <filename>/etc/passwd</filename>. If a user account
|
|
isn't found, try to find it in SAM or AD. This is the default for both,
|
|
passwd and group information.
|
|
</para>
|
|
|
|
<screen>
|
|
group: db files
|
|
</screen>
|
|
|
|
<para>
|
|
This is a valid entry, but the order will be ignored by Cygwin. If both
|
|
settings, <literal>files</literal> and <literal>db</literal> are specified,
|
|
Cygwin will always try the files first, then the db.
|
|
</para>
|
|
|
|
<para>
|
|
<literal>passwd:</literal> and <literal>group:</literal> are the two basic
|
|
settings defining where to get the account information from. The following
|
|
settings starting with <literal>db_</literal> define certain aspects of the
|
|
Windows account database search and how to generate <literal>passwd</literal>
|
|
and <literal>group</literal> information from the database.
|
|
</para>
|
|
|
|
</sect4>
|
|
|
|
<!--
|
|
|
|
DESCRIPTION OF db_prefix AND db_separator
|
|
|
|
Keep in for reference
|
|
|
|
|
|
<itemizedlist spacing="compact">
|
|
|
|
<listitem>
|
|
<para>
|
|
<literal>db_prefix:</literal> determines how the Cygwin user or group name
|
|
is created. The recognized values are:
|
|
</para>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>auto</literal></term>
|
|
<listitem>
|
|
<para>
|
|
This is the default. If your account is from the primary domain of your
|
|
machine, or if your machine is a standalone machine (not a domain member),
|
|
your Cygwin account name is just the Windows account name.
|
|
</para>
|
|
|
|
<para>
|
|
If your account is from another domain, or if you're logged in as
|
|
local user on a domain machine, the Cygwin username will be the
|
|
combination of Windows domainname and username, with the separator
|
|
char in between:
|
|
</para>
|
|
|
|
<segmentedlist><?dbhtml list-presentation="table"?>
|
|
<seglistitem>
|
|
<seg><literal>MY_DOM+username</literal></seg>
|
|
<seg>(foreign domain)</seg>
|
|
</seglistitem>
|
|
<seglistitem>
|
|
<seg><literal>MACHINE+username</literal></seg>
|
|
<seg>(local account)</seg>
|
|
</seglistitem>
|
|
</segmentedlist>
|
|
|
|
<para>
|
|
Builtin accounts are simply used as is:
|
|
</para>
|
|
|
|
<segmentedlist><?dbhtml list-presentation="table"?>
|
|
<seglistitem>
|
|
<seg><literal>LOCAL</literal></seg>
|
|
</seglistitem>
|
|
<seglistitem>
|
|
<seg><literal>Users</literal></seg>
|
|
</seglistitem>
|
|
</segmentedlist>
|
|
|
|
<para>
|
|
Unknown accounts on NFS or Samba shares (that is, accounts which cannot be
|
|
mapped to Windows user accounts via
|
|
<ulink url="https://tools.ietf.org/html/rfc2307">RFC 2307</ulink>) get a
|
|
Cygwin account name consisting of the artificial domains
|
|
<literal>Unix_User</literal> or <literal>Unix_Group</literal> and the
|
|
uid/gid value, for instance:
|
|
</para>
|
|
|
|
<segmentedlist><?dbhtml list-presentation="table"?>
|
|
<seglistitem>
|
|
<seg><literal>Unix_User+0</literal></seg>
|
|
<seg>(root)</seg>
|
|
</seglistitem>
|
|
<seglistitem>
|
|
<seg><literal>Unix_Group+10</literal></seg>
|
|
<seg>(wheel)</seg>
|
|
</seglistitem>
|
|
</segmentedlist>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>primary</literal></term>
|
|
<listitem>
|
|
<para>
|
|
Like <literal>auto</literal>, but primary domain accounts will be
|
|
prepended by the domainname as well.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>always</literal></term>
|
|
<listitem>
|
|
<para>
|
|
All accounts, even the builtin accounts, will have the domain name
|
|
prepended:
|
|
</para>
|
|
|
|
<segmentedlist><?dbhtml list-presentation="table"?>
|
|
<seglistitem>
|
|
<seg><literal>BUILTIN+Users</literal></seg>
|
|
</seglistitem>
|
|
</segmentedlist>
|
|
|
|
<para>
|
|
A special case are builtin accounts which have an emtpy domain name.
|
|
These will be prependend by just the separator character in
|
|
<literal>always</literal> mode:
|
|
</para>
|
|
|
|
<segmentedlist><?dbhtml list-presentation="table"?>
|
|
<seglistitem>
|
|
<seg><literal>+LOCAL</literal></seg>
|
|
</seglistitem>
|
|
</segmentedlist>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
<literal>db_separator:</literal> defines the spearator char used to prepend the
|
|
domain name to the user or group name. The default is the plus character
|
|
<literal>+</literal>.
|
|
</para>
|
|
|
|
<screen>
|
|
MY_DOM+username
|
|
</screen>
|
|
|
|
<para>
|
|
With <literal>db_separator:</literal>, you can define any ASCII char except
|
|
space, tab, carriage return, line feed, and the colon, as separator char.
|
|
Example:
|
|
</para>
|
|
|
|
<screen>
|
|
db_separator: \
|
|
</screen>
|
|
|
|
<para>
|
|
This results in usernames with the backslash as separator:
|
|
</para>
|
|
|
|
<screen>
|
|
MY_DOM\username
|
|
</screen>
|
|
|
|
</listitem>
|
|
|
|
</itemizedlist>
|
|
-->
|
|
|
|
<sect4 id="ntsec-mapping-nsswitch-enum"><title id="ntsec-mapping-nsswitch-enum.title">The <literal>db_enum:</literal> setting</title>
|
|
|
|
<para>
|
|
<literal>db_enum:</literal> defines the depth of a database search, if an
|
|
application calls one of the enumeration functions
|
|
<ulink url="http://linux.die.net/man/3/getpwent">getpwent</ulink>
|
|
or <ulink url="http://linux.die.net/man/3/getgrent">getgrent</ulink>.
|
|
The problem with these functions is, they neither allow to define how many
|
|
entries will be enumerated when calling them in a loop, nor do they
|
|
allow to add some filter criteria. They were designed back in the days,
|
|
when only <filename>/etc/passwd</filename> and <filename>/etc/group</filename>
|
|
files existed and the number of user accounts on a typical UNIX system was
|
|
seldomly a three-digit number.
|
|
</para>
|
|
|
|
<para>
|
|
These days, with user and group databases sometimes going in the
|
|
six-digit range, they are a potential burden. For that reason, Cygwin
|
|
does not enumerate all user or group accounts by default, but rather
|
|
just a very small list, consisting only of the accounts cached in memory
|
|
by the current process, as well as a handful of predefined builtin
|
|
accounts.
|
|
</para>
|
|
|
|
<para>
|
|
<literal>db_enum:</literal> allows to specify the accounts to enumerate in a
|
|
fine-grained manner. It takes a list of sources as argument:
|
|
</para>
|
|
|
|
<screen>
|
|
db_enum: source1 source2 ...
|
|
</screen>
|
|
|
|
<para>
|
|
The recognized sources are the following:
|
|
</para>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>none</literal></term>
|
|
<listitem>No output from
|
|
<function>getpwent</function>/<function>getgrent</function>
|
|
at all.</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>all</literal></term>
|
|
<listitem>The opposite. Enumerates accounts from all known sources,
|
|
including all trusted domains.</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>cache</literal></term>
|
|
<listitem>Enumerate all accounts currently cached in memory.</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>builtin</literal></term>
|
|
<listitem>Enumerate the predefined builtin accounts for backward
|
|
compatibility. These are five passwd accounts (SYSTEM,
|
|
LocalService, NetworkService, Administrators, TrustedInstaller)
|
|
and two group accounts (SYSTEM and TrustedInstaller).</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>files</literal></term>
|
|
<listitem>Enumerate the accounts from <filename>/etc/passwd</filename> or
|
|
<filename>/etc/group</filename>.</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>local</literal></term>
|
|
<listitem>Enumerate all accounts from the local SAM.</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>primary</literal></term>
|
|
<listitem>Enumerate all accounts from the primary domain.</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>alltrusted</literal></term>
|
|
<listitem>Enumerate all accounts from all trusted domains.</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>some.domain</literal></term>
|
|
<listitem>Enumerate all accounts from the trusted domain some.domain. The
|
|
trusted domain can be given as Netbios flat name (MY_DOMAIN) or
|
|
as dns domain name (my_domain.corp). In contrast to the
|
|
aforementioned fixed source keywords, distinct domain names are
|
|
caseinsensitive. Only domains which are actually trusted domains
|
|
are enumerated. Unknown domains are simply ignored.</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
|
|
<para>
|
|
Please note that <function>getpwent</function>/<function>getgrent</function>
|
|
do <emphasis>not</emphasis> test if an account was already listed from another
|
|
source, so an account can easily show up twice or three times. Such a test
|
|
would be rather tricky, nor does the Linux implementation perform such test.
|
|
Here are a few examples for <filename>/etc/nsswitch.conf</filename>:
|
|
</para>
|
|
|
|
<screen>
|
|
db_enum: none
|
|
</screen>
|
|
|
|
<para>
|
|
No output from <function>getpwent</function>/<function>getgrent</function>
|
|
at all. The first call to the function immediately returns a NULL pointer.
|
|
</para>
|
|
|
|
<screen>
|
|
db_enum: cache files
|
|
</screen>
|
|
|
|
<para>
|
|
Enumerate all accounts cached by the current process, plus all entries
|
|
from either the /etc/passwd or /etc/group file.
|
|
</para>
|
|
|
|
<screen>
|
|
db_enum: cache local primary
|
|
</screen>
|
|
|
|
<para>
|
|
Enumerate all accounts cached by the current process, all accounts from the SAM
|
|
of the local machine, and all accounts from the primary domain of the machine.
|
|
</para>
|
|
|
|
<screen>
|
|
db_enum: local primary alltrusted
|
|
</screen>
|
|
|
|
<para>
|
|
Enumerate the accounts from the machine's SAM, from the primary domain of the
|
|
machine, and from all trusted domains.
|
|
</para>
|
|
|
|
<screen>
|
|
db_enum: primary domain1.corp sub.domain.corp domain2.net
|
|
</screen>
|
|
|
|
<para>
|
|
Enumerate the accounts from the primary domain and from the domains
|
|
domain1.corp, sub.domain.corp and domain2.net.
|
|
</para>
|
|
|
|
<screen>
|
|
db_enum: all
|
|
</screen>
|
|
|
|
<para>
|
|
Enumerate everything and the kitchen sink.
|
|
</para>
|
|
|
|
</sect4>
|
|
|
|
<sect4 id="ntsec-mapping-nsswitch-passwd"><title id="ntsec-mapping-nsswitch-passwd.title">Settings defining how to create the <literal>passwd</literal> entry</title>
|
|
|
|
<para>
|
|
<filename>/etc/nsswitch.conf</filename> supports three settings to configure
|
|
where to get the pw_dir, pw_shell, and pw_gecos content of a
|
|
<literal>passwd</literal> entry from:
|
|
</para>
|
|
|
|
<screen>
|
|
db_home: schema... # Define how to fetch the pw_dir entry.
|
|
db_shell: schema... # Define how to fetch the pw_shell entry.
|
|
db_gecos: schema... # Define how to fetch the pw_gecos entry.
|
|
</screen>
|
|
|
|
"schema..." is a list of up to four space-separated schemata:
|
|
|
|
<screen>
|
|
db_FOO: schema1 schema2 ...
|
|
</screen>
|
|
|
|
<para>
|
|
When generating a passwd entry, Cygwin tries the schemata in order. If
|
|
the first schema returns an empty string, it skips to the second, and so
|
|
on. Schemata only supported on AD are silently skipped for SAM accounts
|
|
and on non-AD machines.
|
|
</para>
|
|
|
|
<para>
|
|
Four schemata are predefined, two schemata are variable. The predefined
|
|
schemata are the following:
|
|
</para>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>windows</literal></term>
|
|
<listitem>Utilizes typical Windows settings. Supported for AD and SAM
|
|
accounts.</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>cygwin</literal></term>
|
|
<listitem>Utilizes the cygwinUser AD schema extension. This schema
|
|
extension is available via a schema extension file
|
|
<filename>/usr/share/cygwin/cygwin.ldif</filename>.
|
|
See <xref linkend="ntsec-mapping-nsswitch-cygwin"></xref> for
|
|
more information.</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>unix</literal></term>
|
|
<listitem>Utilizes the posixAccount schema attributes per
|
|
<ulink url="https://tools.ietf.org/html/rfc2307">RFC 2307</ulink>.
|
|
The posixAccount schema is available by default in Windows
|
|
Server, but typically only utilized when installing the
|
|
Active Directory "Server for NIS" feature (which is deprecated
|
|
since Server 2012 R2).
|
|
See also <xref linkend="ntsec-mapping-nsswitch-posix"></xref>.
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>desc</literal></term>
|
|
<listitem>Utilizes XML-style attributes in the description attribute.
|
|
Supported for AD and SAM accounts.
|
|
See <xref linkend="ntsec-mapping-nsswitch-desc"></xref>
|
|
for a more detailed description.</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
|
|
<para>
|
|
The variable schemata are as follows. Note that the leading characters
|
|
(<literal>@</literal> and <literal>/</literal>) are an integral part of the
|
|
definition.
|
|
</para>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>@ad_attribute</literal></term>
|
|
<listitem><literal>ad_attribute</literal> is any arbitrary AD attribute
|
|
name which should (ideally) be available in the User class or
|
|
in any attached auxiliary class. It's always treated as a
|
|
single string argument. Only the first string of a multi-string
|
|
attributes will be read.</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>/path</literal></term>
|
|
<listitem>An arbitrary string, typically a path. The leading slash is
|
|
required. Given that a single, fixed path for all users
|
|
only makes marginal sense, the /path schema supports wildcards.
|
|
A wildcard is a per-cent (<literal>%</literal>) character,
|
|
followed by another character giving the meaning. The supported
|
|
wildcard characters are:
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>%u</literal></term>
|
|
<listitem>The Cygwin username (that's lowercase
|
|
<literal>u</literal>).</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>%U</literal></term>
|
|
<listitem>The Windows username (that's uppercase
|
|
<literal>U</literal>).</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>%D</literal></term>
|
|
<listitem>Windows domain in NetBIOS style.</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>%H</literal></term>
|
|
<listitem>Windows home directory in POSIX style. Note that,
|
|
for the <literal>db_home:</literal> setting, this
|
|
only makes sense right after the preceeding slash,
|
|
as in
|
|
<screen>
|
|
db_home: /%H/cygwin
|
|
</screen>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>%_</literal></term>
|
|
<listitem>Since space and TAB characters are used to separate
|
|
the schemata, a space in the filename has to be
|
|
given as <literal>%_</literal> (that's an
|
|
underscore).</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>%%</literal></term>
|
|
<listitem>A per-cent character.</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
<para>Any other <literal>%X</literal> expression is treated as if
|
|
the character <literal>X</literal> has been given alone.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
|
|
<para>
|
|
The exact meaning of a schema depends on the setting it's used for. The
|
|
following sections explain the settings in detail.
|
|
</para>
|
|
|
|
</sect4>
|
|
|
|
<sect4 id="ntsec-mapping-nsswitch-home">
|
|
<sectioninfo>
|
|
<title role="texinfo-node">The <literal>db_home</literal> setting</title>
|
|
</sectioninfo>
|
|
<title id="ntsec-mapping-nsswitch-home.title">The <literal>db_home:</literal> setting</title>
|
|
|
|
<para>
|
|
The <literal>db_home:</literal> setting defines how Cygwin fetches the user's
|
|
home directory, or, more precise, the content of the <literal>pw_dir</literal>
|
|
member of the user's passwd entry. The following list describes the meaning
|
|
of each schema when used with <literal>db_home:</literal>
|
|
</para>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>windows</literal></term>
|
|
<listitem>The user's home directory is set to the same directory which is
|
|
used as Windows home directory. This is the
|
|
<!--
|
|
<literal>homeDrive</literal> AD attribute if set, or the
|
|
<literal>homeDirectory</literal> AD attribute if
|
|
<literal>homeDrive</literal> is not set.
|
|
-->
|
|
<literal>homeDirectory</literal> AD attribute.
|
|
For SAM accounts, this is equivalent to the "Home folder" setting
|
|
in SAM. If both attributes are unset, Cygwin falls back to the
|
|
user's local profile directory, typically something along the
|
|
lines of <filename>C:\Users\$USERNAME</filename>. Of course, the
|
|
Windows directory is converted to POSIX-style by Cygwin.
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>cygwin</literal></term>
|
|
<listitem>AD only: The user's home directory is set to the POSIX path given
|
|
in the <literal>cygwinHome</literal> attribute from the
|
|
<literal>cygwinUser</literal> auxiliary class.
|
|
See also <xref linkend="ntsec-mapping-nsswitch-cygwin"></xref>.
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>unix</literal></term>
|
|
<listitem>AD only: The user's home directory is set to the POSIX path given
|
|
in the <literal>unixHomeDirectory</literal> attribute from the
|
|
<literal>posixAccount</literal> auxiliary class.
|
|
See also <xref linkend="ntsec-mapping-nsswitch-posix"></xref>.
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>desc</literal></term>
|
|
<listitem>The user's home directory is set to the POSIX path given in the
|
|
home="..." XML-alike setting in the user's
|
|
<literal>description</literal> attribute in SAM or AD.
|
|
See <xref linkend="ntsec-mapping-nsswitch-desc"></xref>
|
|
for a detailed description.</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>@ad_attribute</literal></term>
|
|
<listitem>AD only: The user's home directory is set to the path given
|
|
in the <literal>ad_attribute</literal> attribute. The path
|
|
can be given as Windows or POSIX path.</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>/path</literal></term>
|
|
<listitem>The user's home directory is set to the given POSIX path.
|
|
Remember the wildcards described in
|
|
<xref linkend="ntsec-mapping-nsswitch-passwd"></xref>.</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Fallback</term>
|
|
<listitem>If none of the schemes given for <literal>db_home:</literal>
|
|
define a non-empty directory, the user's home directory is set to
|
|
<filename>/home/$USERNAME</filename>.</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
|
|
<para>
|
|
<literal>db_home:</literal> defines no default schemata. If this setting is not
|
|
present in <filename>/etc/nsswitch.conf</filename>, the aforementioned fallback
|
|
takes over, which is equivalent to a <filename>/etc/nsswitch.conf</filename>
|
|
settting of
|
|
</para>
|
|
|
|
<screen>
|
|
db_home: /home/%U
|
|
</screen>
|
|
|
|
</sect4>
|
|
|
|
<sect4 id="ntsec-mapping-nsswitch-shell">
|
|
<sectioninfo>
|
|
<title role="texinfo-node">The <literal>db_shell</literal> setting</title>
|
|
</sectioninfo>
|
|
<title id="ntsec-mapping-nsswitch-shell.title">The <literal>db_shell:</literal> setting</title>
|
|
|
|
<para>
|
|
The <literal>db_shell:</literal> setting defines how Cygwin fetches the user's
|
|
login shell, the content of the <literal>pw_shell</literal> member of the
|
|
user's passwd entry. The following list describes the meaning of each schema
|
|
when used with <literal>db_shell:</literal>
|
|
</para>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>windows</literal></term>
|
|
<listitem>The <literal>windows</literal> schema is ignored for now.
|
|
The logical choice would be CMD, but that introduces some
|
|
problems, for instance the fact that CMD has no concept of
|
|
running as <literal>login shell</literal>. This may change
|
|
in future.</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>cygwin</literal></term>
|
|
<listitem>AD only: The user's home directory is set to the POSIX path given
|
|
in the <literal>cygwinShell</literal> attribute from the
|
|
<literal>cygwinUser</literal> auxiliary class.
|
|
See also <xref linkend="ntsec-mapping-nsswitch-cygwin"></xref>.
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>unix</literal></term>
|
|
<listitem>AD only: The user's login shell is set to the POSIX path given
|
|
in the <literal>loginShell</literal> attribute from the
|
|
<literal>posixAccount</literal> auxiliary class.
|
|
See also <xref linkend="ntsec-mapping-nsswitch-posix"></xref>.
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>desc</literal></term>
|
|
<listitem>The user's login shell is set to the POSIX path given in the
|
|
shell="..." XML-alike setting in the user's
|
|
<literal>description</literal> attribute in SAM or AD.
|
|
See <xref linkend="ntsec-mapping-nsswitch-desc"></xref>
|
|
for a detailed description.</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>@ad_attribute</literal></term>
|
|
<listitem>AD only: The user's login shell is set to the path given
|
|
in the <literal>ad_attribute</literal> attribute. The path
|
|
can be given as Windows or POSIX path.</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>/path</literal></term>
|
|
<listitem>The user's login shell is set to the given POSIX path.
|
|
Albeit not being as important here, the wildcards described in
|
|
<xref linkend="ntsec-mapping-nsswitch-passwd"></xref>
|
|
are also available for specifying a login shell path.</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Fallback</term>
|
|
<listitem>If none of the schemes given for <literal>db_shell:</literal>
|
|
define a non-empty pathname, the user's login shell is set to
|
|
<filename>/bin/bash</filename>.</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
|
|
<para>
|
|
<literal>db_shell:</literal> defines no default schemata. If this setting is
|
|
not present in <filename>/etc/nsswitch.conf</filename>, the aforementioned
|
|
fallback takes over, which is equivalent to a
|
|
<filename>/etc/nsswitch.conf</filename> settting of
|
|
</para>
|
|
|
|
<screen>
|
|
db_shell: /bin/bash
|
|
</screen>
|
|
|
|
|
|
</sect4>
|
|
|
|
<sect4 id="ntsec-mapping-nsswitch-gecos">
|
|
<sectioninfo>
|
|
<title role="texinfo-node">The <literal>db_gecos</literal> setting</title>
|
|
</sectioninfo>
|
|
<title id="ntsec-mapping-nsswitch-gecos.title">The <literal>db_gecos:</literal> setting</title>
|
|
|
|
<para>
|
|
The <literal>db_gecos:</literal> setting defines how to fetch additional
|
|
content for the <literal>pw_gecos</literal> member of the user's passwd entry.
|
|
There's always a fixed, Cygwin-specific part in the <literal>pw_gecos</literal>
|
|
field for identifying the account. However, an administrator might want to
|
|
add informative content like, for instance, the user's full name. That's
|
|
what the <literal>db_gecos:</literal> setting is for.
|
|
The following list describes the meaning of each schema when used with
|
|
<literal>db_gecos:</literal>
|
|
</para>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>windows</literal></term>
|
|
<listitem>Add the AD <literal>displayName</literal> attribute or, for
|
|
SAM accounts, the "Full name" entry to the
|
|
<literal>pw_gecos</literal> field.</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>cygwin</literal></term>
|
|
<listitem>AD only: The content of the <literal>cygwinGecos</literal>
|
|
attribute from the <literal>cygwinUser</literal> auxiliary class
|
|
is added to <literal>pw_gecos</literal>.
|
|
See also <xref linkend="ntsec-mapping-nsswitch-cygwin"></xref>.
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>unix</literal></term>
|
|
<listitem>AD only: The content of the <literal>gecos</literal> attribute
|
|
from the <literal>posixAccount</literal> auxiliary class
|
|
is added to <literal>pw_gecos</literal>.
|
|
See also <xref linkend="ntsec-mapping-nsswitch-posix"></xref>.
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>desc</literal></term>
|
|
<listitem>The content of the gecos="..." XML-alike setting in the user's
|
|
<literal>description</literal> attribute in SAM or AD is added
|
|
to <literal>pw_gecos</literal>.
|
|
See <xref linkend="ntsec-mapping-nsswitch-desc"></xref>
|
|
for a detailed description.</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>@ad_attribute</literal></term>
|
|
<listitem>AD only: The content of the <literal>ad_attribute</literal>
|
|
attribute is added to <literal>pw_gecos</literal>.</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>/path</literal></term>
|
|
<listitem>The string following the slash is added to
|
|
<literal>pw_gecos</literal>. Here, the wildcards described in
|
|
<xref linkend="ntsec-mapping-nsswitch-passwd"></xref>
|
|
may come in handy.</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Fallback</term>
|
|
<listitem>If none of the schemes given for <literal>db_gecos:</literal>
|
|
define a non-empty string, nothing is added to
|
|
<literal>pw_gecos</literal>.</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
|
|
<para>
|
|
<literal>db_gecos:</literal> defines no default schemata.
|
|
</para>
|
|
|
|
</sect4>
|
|
|
|
<sect4 id="ntsec-mapping-nsswitch-cygwin"><title id="ntsec-mapping-nsswitch-cygwin.title">The <literal>cygwin</literal> schema</title>
|
|
|
|
<para>
|
|
The <literal>cygwin</literal> schema is based on a Cygwin-specific Active
|
|
Directory schema extension. Using this schema extension allows to maintain
|
|
Cygwin-specific settings entirely within AD, without colliding with any other
|
|
schema.
|
|
</para>
|
|
|
|
<para>
|
|
The cygwin schema extension is available in a default Cygwin installation
|
|
in the file <filename>/usr/share/cygwin/cygwin.ldif</filename>. To install
|
|
the schema extension, you have to be schema admin, and you have to run the
|
|
<command>ldifde</command> command on the schema master. The installation
|
|
itself is rather simple. Assuming you're schema admin and running a shell
|
|
with administrative privileges:
|
|
</para>
|
|
|
|
<screen>
|
|
$ cd /usr/share/cygwin
|
|
$ ldifde -i -f cygwin.ldif -k -c "CN=schema,CN=Configuration,DC=X" #schemaNamingContext
|
|
</screen>
|
|
|
|
<para>
|
|
Afterwards, the auxiliary class <literal>cygwinUser</literal> is attached to
|
|
the class <literal>User</literal>, and the auxiliary class
|
|
<literal>cygwinGroup</literal> is attached to the class
|
|
<literal>Group</literal>. The new attributes can be immediately edited
|
|
using <command>ADSI Edit</command>.
|
|
</para>
|
|
|
|
<para>
|
|
At the time of writing the following attributes are utilized by Cygwin:
|
|
</para>
|
|
|
|
<segmentedlist><?dbhtml list-presentation="table"?>
|
|
<seglistitem>
|
|
<seg><literal>cygwinHome</literal></seg>
|
|
<seg>Used as Cygwin home directory with <literal>db_home: cygwin</literal>.
|
|
See <xref linkend="ntsec-mapping-nsswitch-home"></xref>.</seg>
|
|
</seglistitem>
|
|
<seglistitem>
|
|
<seg><literal>cygwinShell</literal></seg>
|
|
<seg>Used as Cygwin login shell with <literal>db_shell: cygwin</literal>.
|
|
See <xref linkend="ntsec-mapping-nsswitch-shell"></xref>.</seg>
|
|
</seglistitem>
|
|
<seglistitem>
|
|
<seg><literal>cygwinGecos</literal></seg>
|
|
<seg>Content will be added to the pw_gecos field with
|
|
<literal>db_gecos: cygwin</literal>.
|
|
See <xref linkend="ntsec-mapping-nsswitch-gecos"></xref>.</seg>
|
|
</seglistitem>
|
|
<!--
|
|
<seglistitem>
|
|
<seg><literal>cygwinFstab</literal></seg>
|
|
<seg>yada yada yada</seg>
|
|
</seglistitem>
|
|
<seglistitem>
|
|
<seg><literal>cygwinUnixUid</literal></seg>
|
|
<seg>See <xref linkend="ntsec-mapping-nfs"></xref> and
|
|
<xref linkend="ntsec-mapping-samba"></xref>.</seg>
|
|
</seglistitem>
|
|
|
|
<para>
|
|
The group attributes utilized by Cygwin are:
|
|
</para>
|
|
|
|
</segmentedlist>
|
|
<seglistitem>
|
|
<seg><literal>cygwinUnixGid</literal></seg>
|
|
<seg>See <xref linkend="ntsec-mapping-nfs"></xref> and
|
|
<xref linkend="ntsec-mapping-samba"></xref>.</seg>
|
|
</seglistitem>
|
|
</segmentedlist>
|
|
-->
|
|
</segmentedlist>
|
|
|
|
</sect4>
|
|
|
|
<sect4 id="ntsec-mapping-nsswitch-posix"><title id="ntsec-mapping-nsswitch-posix.title">The <literal>unix</literal> schema</title>
|
|
|
|
<para>
|
|
The <literal>unix</literal> schema utilizes the
|
|
<literal>posixAccount</literal> attribute extension. This is one of two
|
|
schema extensions which are connected to AD accounts, available by default.
|
|
They are usually <emphasis role='bold'>not set</emphasis>, unless used by
|
|
the Active Directory <literal>Server for NIS</literal> feature (deprecated
|
|
since Server 2012 R2).
|
|
|
|
Two schemata are interesting for Cygwin, <literal>posixAccount</literal>,
|
|
connected to user accounts, and <literal>posixGroup</literal>, connected
|
|
to group accounts. Both follow the description of RFC 2307,
|
|
<ulink url="https://tools.ietf.org/html/rfc2307">an Approach for Using LDAP as
|
|
a Network Information Service</ulink>.
|
|
The user attributes utilized by Cygwin are:
|
|
</para>
|
|
|
|
<segmentedlist><?dbhtml list-presentation="table"?>
|
|
<seglistitem>
|
|
<seg><literal>unixHomeDirectory</literal></seg>
|
|
<seg>Used as Cygwin home directory with <literal>db_home: unix</literal>.
|
|
See <xref linkend="ntsec-mapping-nsswitch-home"></xref>.</seg>
|
|
</seglistitem>
|
|
<seglistitem>
|
|
<seg><literal>loginShell</literal></seg>
|
|
<seg>Used as Cygwin login shell with <literal>db_shell: unix</literal>.
|
|
See <xref linkend="ntsec-mapping-nsswitch-shell"></xref>.</seg>
|
|
</seglistitem>
|
|
<seglistitem>
|
|
<seg><literal>gecos</literal></seg>
|
|
<seg>Content will be added to the pw_gecos field with
|
|
<literal>db_gecos: unix</literal>.
|
|
See <xref linkend="ntsec-mapping-nsswitch-gecos"></xref>.</seg>
|
|
</seglistitem>
|
|
<seglistitem>
|
|
<seg><literal>uidNumber</literal></seg>
|
|
<seg>See <xref linkend="ntsec-mapping-nfs"></xref> and
|
|
<xref linkend="ntsec-mapping-samba"></xref>.</seg>
|
|
</seglistitem>
|
|
</segmentedlist>
|
|
|
|
<para>
|
|
The group attributes utilized by Cygwin are:
|
|
</para>
|
|
|
|
<segmentedlist><?dbhtml list-presentation="table"?>
|
|
<seglistitem>
|
|
<seg><literal>gidNumber</literal></seg>
|
|
<seg>See <xref linkend="ntsec-mapping-nfs"></xref> and
|
|
<xref linkend="ntsec-mapping-samba"></xref>.</seg>
|
|
</seglistitem>
|
|
</segmentedlist>
|
|
|
|
<para>
|
|
Apart from power shell scripting or inventing new CLI tools, these attributes
|
|
can be changed using the <literal>Attribute Editor</literal> tab in the user
|
|
properties dialog of the <literal>Active Directory Users and Computers</literal>
|
|
MMC snap-in. Alternatively, if the <literal>Server for NIS</literal>
|
|
administration feature has been installed, there will be a
|
|
<literal>UNIX Attributes</literal> tab which contains the required fields,
|
|
except for the gecos field. Last resort is <command>ADSI Edit</command>.
|
|
</para>
|
|
|
|
</sect4>
|
|
|
|
<sect4 id="ntsec-mapping-nsswitch-desc"><title id="ntsec-mapping-nsswitch-desc.title">The <literal>desc</literal> schema</title>
|
|
|
|
<para>
|
|
When using user accounts from the local account database, the SAM, there
|
|
are only a very limited number of settings available. In contrast to
|
|
Active Directory there's no way to add fields to a user's entry. You have
|
|
to make do with the fields available. The method to utilize the
|
|
<literal>description</literal> field has been mainly introduced for those
|
|
accounts, usually the only ones a home user has. However, for symmetry,
|
|
and because there may be a reason to use this in an AD environment, this
|
|
schema is also supported for AD users.
|
|
</para>
|
|
|
|
<note>
|
|
<para>
|
|
The presentation of local user account settings on Windows is confusing,
|
|
to say the least. The <literal>description</literal> field is not visible at
|
|
all in the user settings available via the <literal>User Accounts</literal>
|
|
control settings. And while it's called <literal>Description</literal> in the
|
|
<literal>Local Users and Groups</literal> MMC snap-in (available, for instance,
|
|
via the <literal>Computer Management</literal> GUI), in the command
|
|
line tool <command>net user</command> the same field is called
|
|
<literal>comment</literal>. The latter is especially confusing for
|
|
AD admins, because the <literal>comment</literal> attribute in AD is called
|
|
<literal>usercomment</literal> on the command line. Confused? Never mind,
|
|
you're not the only one...
|
|
</para>
|
|
</note>
|
|
|
|
<para>
|
|
Fortunately you can utilize the <literal>description</literal> field even if
|
|
you're running a "home edition" of Windows, by using the command line. The
|
|
<command>net user</command> command allows to set all values in the SAM, even
|
|
if the GUI is crippled.
|
|
</para>
|
|
|
|
<para>
|
|
A Cygwin SAM comment entry looks like this:
|
|
</para>
|
|
|
|
<screen>
|
|
<cygwin key="value" key="value" [...] />
|
|
</screen>
|
|
|
|
<para>
|
|
The supported keys are:
|
|
</para>
|
|
|
|
<segmentedlist><?dbhtml list-presentation="table"?>
|
|
<seglistitem>
|
|
<seg><literal>home="value"</literal></seg>
|
|
<seg>Sets the Cygwin home dir to value.</seg>
|
|
</seglistitem>
|
|
<seglistitem>
|
|
<seg><literal>shell="value"</literal></seg>
|
|
<seg>Sets the Cygwin login shell to value.</seg>
|
|
</seglistitem>
|
|
<seglistitem>
|
|
<seg><literal>gecos="value"</literal></seg>
|
|
<seg>Adds the string value to the user's gecos field.</seg>
|
|
</seglistitem>
|
|
</segmentedlist>
|
|
|
|
<para>
|
|
The next two settings are only supported for SAM accounts.
|
|
</para>
|
|
|
|
<segmentedlist><?dbhtml list-presentation="table"?>
|
|
<seglistitem>
|
|
<seg><literal>group="value"</literal></seg>
|
|
<seg>Sets the Cygwin primary group of the account to value, provided that
|
|
the user <emphasis>is</emphasis> already a member of that group.
|
|
This allows to override the default <literal>None</literal> primary
|
|
group for local accounts. One nice idea here is, for instance,
|
|
group="Users".</seg>
|
|
</seglistitem>
|
|
<seglistitem>
|
|
<seg><literal>unix="value"</literal></seg>
|
|
<seg>Sets the NFS/Samba uid of the user to the decimal value.
|
|
See <xref linkend="ntsec-mapping-nfs"></xref> and
|
|
<xref linkend="ntsec-mapping-samba"></xref>.</seg>
|
|
</seglistitem>
|
|
</segmentedlist>
|
|
|
|
<para>
|
|
The <cygwin .../> string can start at any point in the comment, but
|
|
you have to follow the rules:
|
|
</para>
|
|
|
|
<itemizedlist spacing="compact">
|
|
<listitem>
|
|
It starts with "<cygwin " and ends with "/>".
|
|
</listitem>
|
|
<listitem>
|
|
The "cygwin" string and the key names have to be lowercase.
|
|
</listitem>
|
|
<listitem>
|
|
No spaces between key and "value", just the equal sign.
|
|
</listitem>
|
|
<listitem>
|
|
The value must be placed within double quotes and it must not contain a double
|
|
quote itself. The double quotes are required for the decimal values as well!
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<note>
|
|
<para>
|
|
There's also a length restriction imposed by Windows. The
|
|
<literal>description</literal> entry has a maximum length of 1023 characters.
|
|
</para>
|
|
</note>
|
|
|
|
<para>
|
|
CMD example:
|
|
</para>
|
|
|
|
<screen>
|
|
net user corinna /comment:"<cygwin home=\"/home/foo\"/>"
|
|
</screen>
|
|
|
|
<para>
|
|
Bash example (use single quotes):
|
|
</para>
|
|
|
|
<screen>
|
|
net user corinna /comment:'<cygwin home="/home/foo"/>'
|
|
</screen>
|
|
|
|
<para>
|
|
For changing group comments, use the `net localgroup' command. The supported
|
|
key/value pair for SAM groups are:
|
|
</para>
|
|
|
|
<segmentedlist><?dbhtml list-presentation="table"?>
|
|
<seglistitem>
|
|
<seg><literal>unix="value"</literal></seg>
|
|
<seg>Sets the NFS/Samba gid of the group to the decimal value.
|
|
See <xref linkend="ntsec-mapping-nfs"></xref> and
|
|
<xref linkend="ntsec-mapping-samba"></xref>.</seg>
|
|
</seglistitem>
|
|
</segmentedlist>
|
|
|
|
</sect4>
|
|
|
|
</sect3>
|
|
|
|
<sect3 id="ntsec-mapping-nfs"><title id="ntsec-mapping-nfs.title">NFS account mapping</title>
|
|
|
|
<para>
|
|
Microsoft's NFS client does not map the uid/gid values on the NFS shares
|
|
to SIDs. There's no such thing as a (fake) security descriptor returned
|
|
to the application. Rather, via an undocumented API an application can
|
|
fetch <ulink url="https://tools.ietf.org/html/rfc1813">RFC 1813</ulink>
|
|
compatible NFSv3 stat information from the share. This is what Cygwin is
|
|
using to show stat information for files on NFS shares.
|
|
</para>
|
|
|
|
<para>
|
|
The problem is, while all other information in this stat record, like
|
|
timestamps, file size etc., can be used by Cygwin, Cygwin had no way to
|
|
map the values of the st_uid and st_gid members to a Windows SID for a
|
|
long time. So it just faked the file owner info and claimed that it's
|
|
you.
|
|
</para>
|
|
|
|
<para>
|
|
However, SFU has, over time, developed multiple methods to map UNIX
|
|
uid/gid values on NFS shares to Windows SIDs. You'll find the full
|
|
documentation of the mapping methods in
|
|
<ulink url="http://blogs.technet.com/b/filecab/archive/2012/10/09/nfs-identity-mapping-in-windows-server-2012.aspx">NFS Identity Mapping in Windows Server 2012</ulink>
|
|
</para>
|
|
|
|
<para>
|
|
Cygwin now utilizes the
|
|
<ulink url="https://tools.ietf.org/html/rfc2307">RFC 2307</ulink>
|
|
mapping for this purpose. This is most of the time provided by an AD domain,
|
|
but it could also be a standalone LDAP mapping server. Per
|
|
<ulink url="https://tools.ietf.org/html/rfc2307">RFC 2307</ulink>, the uid is
|
|
in the attribute <literal>uidNumber</literal>. For groups, the gid is in the
|
|
<literal>gidNumber</literal> attribute.
|
|
See <xref linkend="ntsec-mapping-nsswitch-posix"></xref>.
|
|
</para>
|
|
|
|
<para>
|
|
When Cygwin stat()s files on an NFS share, it asks the mapping server via
|
|
LDAP in two different ways, depending on the role of the mapping server.
|
|
</para>
|
|
|
|
<itemizedlist spacing="compact">
|
|
|
|
<listitem>
|
|
If the server is an AD domain controller, it asks for an account with
|
|
<literal>uidNumber</literal> attribute == <literal>st_uid</literal> field of
|
|
the stat record returned by NFS. If an account matches, AD returns the
|
|
Windows SID, so we have an immediate mapping from UNIX uid to a Windows SID,
|
|
if the user account has a valid <literal>uidNumber</literal> attribute. For
|
|
groups, the method is the same, just that Cygwin asks for a group with
|
|
<literal>gidNumber</literal> attribute == <literal>st_gid</literal> field of the
|
|
stat record.
|
|
</listitem>
|
|
|
|
<listitem>
|
|
If the server is a standalone LDAP mapping server Cygwin asks for the
|
|
same <literal>uidNumber</literal>/<literal>gidNumber</literal> attributes, but
|
|
it can't expect that the LDAP server knows anything about Windows SIDs.
|
|
Rather, the mapping server returns the account name. Cygwin then asks the
|
|
DC for an account with this name, and if that succeeds, we have a mapping
|
|
between UNIX uid/gid and Windows SIDs.
|
|
</listitem>
|
|
|
|
</itemizedlist>
|
|
|
|
<para>
|
|
The mapping will be cached for the lifetime of the process, and inherited
|
|
by child processes.
|
|
</para>
|
|
|
|
</sect3>
|
|
|
|
<sect3 id="ntsec-mapping-samba"><title id="ntsec-mapping-samba.title">Samba account mapping</title>
|
|
|
|
<para>
|
|
A fully set up Samba file server with domain integration is running winbindd to
|
|
map Windows SIDs to artificially created UNIX uids and gids, and this mapping is
|
|
transparent within the domain, so Cygwin doesn't have to do anything special.
|
|
</para>
|
|
|
|
<para>
|
|
However, setting up winbindd isn't for everybody, and it fails to map
|
|
Windows accounts to already existing UNIX users or groups. In contrast
|
|
to NFS, Samba returns security descriptors, but unmapped UNIX accounts
|
|
get special SIDs:
|
|
</para>
|
|
|
|
<itemizedlist spacing="compact">
|
|
|
|
<listitem>
|
|
A UNIX user account with uid X is mapped to the Windows SID S-1-22-1-X.
|
|
</listitem>
|
|
|
|
<listitem>
|
|
A UNIX group account with gid X is mapped to SID S-1-22-2-X.
|
|
</listitem>
|
|
|
|
</itemizedlist>
|
|
|
|
<para>
|
|
As you can see, even though we have SIDs, they just reflect the actual
|
|
uid/gid values on the UNIX box in the RID value. It's only marginally
|
|
different from the NFS method, so why not just use the same method as
|
|
for NFS?
|
|
</para>
|
|
|
|
<para>
|
|
That's what Cygwin will do. If it encounters a S-1-22-x-y SID, it
|
|
will perform the same
|
|
<ulink url="https://tools.ietf.org/html/rfc2307">RFC 2307</ulink>
|
|
mapping as for NFS shares.
|
|
</para>
|
|
|
|
<para>
|
|
For home users without any Windows domain or LDAP server per
|
|
<ulink url="https://tools.ietf.org/html/rfc2307">RFC 2307</ulink>,
|
|
but with a Linux machine running Samba, just add this information to
|
|
your SAM account. Assuming the uid of your Linux user account is 505
|
|
and the gid of your primary group is, say, 100, just add the values to
|
|
your SAM user and group accounts. The following example assumes you
|
|
didn't already add something else to the comment field.
|
|
</para>
|
|
|
|
<para>
|
|
To your user's SAM comment (remember: called <literal>Description</literal>
|
|
in the GUI),
|
|
add:
|
|
</para>
|
|
|
|
<screen>
|
|
<cygwin group="Users" unix="505"/>
|
|
</screen>
|
|
|
|
<para>
|
|
To the <literal>Users</literal> group SAM comment add:
|
|
</para>
|
|
|
|
<screen>
|
|
<cygwin unix="100"/>
|
|
</screen>
|
|
|
|
<para>
|
|
This should be sufficient to work on your Samba share and to see
|
|
all files owned by your Linux user account as your files.
|
|
</para>
|
|
|
|
</sect3>
|
|
|
|
</sect2>
|
|
|
|
<sect2 id="ntsec-files"><title id="ntsec-files.title">File permissions</title>
|
|
|
|
<para>On NTFS and if the <literal>noacl</literal> mount option is not
|
|
specified for a mount point, Cygwin sets file permissions as on POSIX
|
|
systems. Basically this is done by defining a Security Descriptor with the
|
|
matching owner and group SIDs, and a DACL which contains ACEs for the owner,
|
|
the group and for "Everyone", which represents what POSIX calls "others".</para>
|
|
|
|
<para>There's just one problem when trying to map the POSIX permission model
|
|
onto the Windows permission model.</para>
|
|
|
|
<para>There's a leak in the definition of a "correct" ACL which disallows a
|
|
certain POSIX permission setting. The official documentation explains in short
|
|
the following:</para>
|
|
|
|
<itemizedlist spacing="compact">
|
|
<listitem><para>The requested permissions are checked against all
|
|
ACEs of the user as well as all groups the user is member of. The
|
|
permissions given in these user and groups access allowed ACEs are
|
|
accumulated and the resulting set is the set of permissions of that
|
|
user given for that object.</para></listitem>
|
|
|
|
<listitem><para>The order of ACEs is important. The system reads them in
|
|
sequence until either any single requested permission is denied or all
|
|
requested permissions are granted. Reading stops when this condition is
|
|
met. Later ACEs are not taken into account.</para></listitem>
|
|
|
|
<listitem><para>All access denied ACEs <emphasis
|
|
role='bold'>should</emphasis> precede any access allowed ACE. ACLs
|
|
following this rule are called "canonical".</para></listitem>
|
|
</itemizedlist>
|
|
|
|
<para>Note that the last rule is a preference or a definition of
|
|
correctness. It's not an absolute requirement. All Windows kernels
|
|
will correctly deal with the ACL regardless of the order of allow and
|
|
deny ACEs. The second rule is not modified to get the ACEs in the
|
|
preferred order.</para>
|
|
|
|
<para>Unfortunately, the security tab in the file properties dialog of
|
|
the Windows Explorer will pop up a warning stating "The permissions on
|
|
... are incorrectly ordered, which may cause some entries to be
|
|
ineffective." Pressing the Cancel button of the properties dialog
|
|
fortunately leaves the sort order unchanged, but pressing OK will cause
|
|
Explorer to canonicalize the order of the ACEs, thereby invalidating
|
|
POSIX compatibility.</para>
|
|
|
|
<para>Canonical ACLs are unable to reflect each possible combination
|
|
of POSIX permissions. Example:</para>
|
|
|
|
<screen>
|
|
rw-r-xrw-
|
|
</screen>
|
|
|
|
<para>Ok, so here's the first try to create a matching ACL, assuming
|
|
the Windows permissions only have three bits, as their POSIX counterpart:
|
|
</para>
|
|
|
|
<screen>
|
|
UserAllow: 110
|
|
GroupAllow: 101
|
|
OthersAllow: 110
|
|
</screen>
|
|
|
|
<para>Hmm, because of the accumulation of allow rights the user may
|
|
execute because the group may execute.</para>
|
|
|
|
<para>Second try:</para>
|
|
|
|
<screen>
|
|
UserDeny: 001
|
|
GroupAllow: 101
|
|
OthersAllow: 110
|
|
</screen>
|
|
|
|
<para>Now the user may read and write but not execute. Better? No!
|
|
Unfortunately the group may write now because others may write.</para>
|
|
|
|
<para>Third try:</para>
|
|
|
|
<screen>
|
|
UserDeny: 001
|
|
GroupDeny: 010
|
|
GroupAllow: 001
|
|
OthersAllow: 110
|
|
</screen>
|
|
|
|
<para>Now the group may not write as intended but unfortunately the user may
|
|
not write anymore, either. How should this problem be solved? According to
|
|
the canonical order a UserAllow has to follow the GroupDeny but it's
|
|
easy to see that this can never be solved that way.</para>
|
|
|
|
<para>The only chance:</para>
|
|
|
|
<screen>
|
|
UserDeny: 001
|
|
UserAllow: 010
|
|
GroupDeny: 010
|
|
GroupAllow: 001
|
|
OthersAllow: 110
|
|
</screen>
|
|
|
|
<para>Again: This works on all supported versions of Windows. Only the GUIs
|
|
aren't able (or willing) to deal with that order.</para>
|
|
|
|
</sect2>
|
|
|
|
<sect2 id="ntsec-setuid-overview"><title id="ntsec-setuid-overview.title">Switching the user context</title>
|
|
|
|
<para>Windows users have been accustomed to the "Switch User" feature, which
|
|
switches the entire desktop to another user while leaving the original user's
|
|
desktop "suspended". Another Windows feature is the "Run as..." context menu
|
|
entry, which allows you to start an application using another user account
|
|
when right-clicking on applications and shortcuts.</para>
|
|
|
|
<para>On POSIX systems, this operation can be performed by processes
|
|
running under the privileged user accounts (usually the "root" user
|
|
account) on a per-process basis. This is called "switching the user
|
|
context" for that process, and is performed using the POSIX
|
|
<command>setuid</command> and <command>seteuid</command> system
|
|
calls.</para>
|
|
|
|
<para>While this sort of feature is available on Windows as well,
|
|
Windows does not support the concept of these calls in a simple fashion.
|
|
Switching the user context in Windows is generally a tricky process with
|
|
lots of "behind the scenes" magic involved.</para>
|
|
|
|
<para>Windows uses so-called `access tokens' to identify a user and its
|
|
permissions. Usually the access token is created at logon time and then
|
|
it's attached to the starting process. Every new process within a session
|
|
inherits the access token from its parent process. Every thread can
|
|
get its own access token, which allows, for instance, to define threads
|
|
with restricted permissions.</para>
|
|
|
|
<sect3 id="ntsec-logonuser"><title id="ntsec-logonuser.title">Switching the user context with password authentication</title>
|
|
|
|
<para>To switch the user context, the process has to request such an access
|
|
token for the new user. This is typically done by calling the Win32 API
|
|
function <command>LogonUser</command> with the user name and the user's
|
|
cleartext password as arguments. If the user exists and the password was
|
|
specified correctly, the access token is returned and either used in
|
|
<command>ImpersonateLoggedOnUser</command> to change the user context of
|
|
the current thread, or in <command>CreateProcessAsUser</command> to
|
|
change the user context of a spawned child process.</para>
|
|
|
|
<para>Later versions of Windows define new functions in this context and
|
|
there are also functions to manipulate existing access tokens (usually
|
|
only to restrict them). Windows Vista also adds subtokens which are
|
|
attached to other access tokens which plays an important role in the UAC
|
|
(User Access Control) facility of Vista and later. However, none of
|
|
these extensions to the original concept are important for this
|
|
documentation.</para>
|
|
|
|
<para>Back to this logon with password, how can this be used to
|
|
implement <command>set(e)uid</command>? Well, it requires modification
|
|
of the calling application. Two Cygwin functions have been introduced
|
|
to support porting <command>setuid</command> applications which only
|
|
require login with passwords. You only give Cygwin the right access
|
|
token and then you can call <command>seteuid</command> or
|
|
<command>setuid</command> as usual in POSIX applications. Porting such
|
|
a <command>setuid</command> application is illustrated by a short
|
|
example:</para>
|
|
|
|
<screen>
|
|
<![CDATA[
|
|
/* First include all needed cygwin stuff. */
|
|
#ifdef __CYGWIN__
|
|
#include <windows.h>
|
|
#include <sys/cygwin.h>
|
|
#endif
|
|
|
|
[...]
|
|
|
|
struct passwd *user_pwd_entry = getpwnam (username);
|
|
char *cleartext_password = getpass ("Password:");
|
|
|
|
[...]
|
|
|
|
#ifdef __CYGWIN__
|
|
/* Patch the typical password test. */
|
|
{
|
|
HANDLE token;
|
|
|
|
/* Try to get the access token from Windows. */
|
|
token = cygwin_logon_user (user_pwd_entry, cleartext_password);
|
|
if (token == INVALID_HANDLE_VALUE)
|
|
error_exit;
|
|
/* Inform Cygwin about the new impersonation token. */
|
|
cygwin_set_impersonation_token (token);
|
|
/* Cygwin is now able, to switch to that user context by setuid or seteuid calls. */
|
|
}
|
|
#else
|
|
/* Use standard method on non-Cygwin systems. */
|
|
hashed_password = crypt (cleartext_password, salt);
|
|
if (!user_pwd_entry ||
|
|
strcmp (hashed_password, user_pwd_entry->pw_passwd))
|
|
error_exit;
|
|
#endif /* CYGWIN */
|
|
|
|
[...]
|
|
|
|
/* Everything else remains the same! */
|
|
|
|
setegid (user_pwd_entry->pw_gid);
|
|
seteuid (user_pwd_entry->pw_uid);
|
|
execl ("/bin/sh", ...);
|
|
]]>
|
|
|
|
</screen>
|
|
|
|
</sect3>
|
|
|
|
<sect3 id="ntsec-nopasswd1"><title id="ntsec-nopasswd1.title">Switching the user context without password, Method 1: Kerberos/MsV1_0 S4U authentication</title>
|
|
|
|
<para>An unfortunate aspect of the implementation of
|
|
<command>set(e)uid</command> is the fact that the calling process
|
|
requires the password of the user to switch to. Applications such as
|
|
<command>sshd</command> wishing to switch the user context after a
|
|
successful public key authentication, or the <command>cron</command>
|
|
application which, again, wants to switch the user without any authentication
|
|
are stuck here. But there are other ways to get new user tokens.</para>
|
|
|
|
<para>Starting with Cygwin 3.0, Cygwin tries to create a token by using
|
|
<literal>Windows S4U authentication</literal> by default. For a quick
|
|
description, see
|
|
<ulink url="https://blogs.msdn.microsoft.com/winsdk/2015/08/28/logon-as-a-user-without-a-password/">this blog posting</ulink>. Cygwin versions prior
|
|
to 3.0 tried to creat a user token from scratch using an officially
|
|
undocumented function <command>NtCreateToken</command> which
|
|
is now disabled.</para>
|
|
|
|
<para>So we just start the servers which have to switch the user context
|
|
(<command>sshd</command>, <command>inetd</command>, <command>cron</command>,
|
|
...) as Windows services under the SYSTEM (or LocalSystem in the GUI)
|
|
account and everything just works. Unfortunately that's too simple.
|
|
Using <literal>S4U</literal> has a drawback.</para>
|
|
|
|
<para>Annoyingly, you don't have the usual comfortable access
|
|
to network shares. The reason is that the token has been created
|
|
without knowing the password. The password are your credentials
|
|
necessary for network access. Thus, if you logon with a password, the
|
|
password is stored hidden as "token credentials" within the access token
|
|
and used as default logon to access network resources. Since these
|
|
credentials are missing from the token created with <literal>S4U</literal>
|
|
or <command>NtCreateToken</command>, you only can access network shares
|
|
from the new user's process tree by using explicit authentication, on
|
|
the command line for instance:</para>
|
|
|
|
<screen>
|
|
bash$ net use '\\server\share' /user:DOMAIN\my_user my_users_password
|
|
</screen>
|
|
|
|
<para>Note that, on some systems, you can't even define a drive letter
|
|
to access the share, and under some circumstances the drive letter you
|
|
choose collides with a drive letter already used in another session.
|
|
Therefore it's better to get used to accessing these shares using the UNC
|
|
path as in</para>
|
|
|
|
<screen>
|
|
bash$ grep foo //server/share/foofile
|
|
</screen>
|
|
|
|
<!--
|
|
<para>First of all, the permission "Create a token object" gets explicitly
|
|
removed from the SYSTEM user's access token, when starting services under that
|
|
account. That requires us to create a new account with this specific
|
|
permission just to run this kind of services. But that's a minor
|
|
problem.</para>
|
|
|
|
<para>A more important problem is that using <command>NtCreateToken</command>
|
|
is not sufficient to create a new logon session for the new user. What
|
|
does that mean? Every logon usually creates a new logon session.
|
|
A logon session has a couple of attributes which are unique to the
|
|
session. One of these attributes is the fact, that Windows functions
|
|
identify the user domain and user name not by the SID of the access
|
|
token owner, but only by the logon session the process is running under.</para>
|
|
|
|
<para>This has the following unfortunate consequence. Consider a
|
|
service started under the SYSTEM account switches the user context to
|
|
DOMAIN\my_user using a token created directly by calling the
|
|
<command>NtCreateToken</command> function. A process running under
|
|
this new access token might want to know under which user account it's
|
|
running. The corresponding SID is returned correctly, for instance
|
|
S-1-5-21-1234-5678-9012-77777. However, if the same process asks the OS
|
|
for the user name of this SID something wierd happens. For instance,
|
|
the <command>LookupAccountSid</command> function will not return
|
|
"DOMAIN\my_user", but "NT AUTHORITY\SYSTEM" as the user name.</para>
|
|
|
|
<para>You might ask "So what?" After all, this only <emphasis
|
|
role='bold'>looks</emphasis> bad, but functionality and permission-wise
|
|
everything should be ok. And Cygwin knows about this shortcoming so it
|
|
will return the correct Cygwin username when asked. Unfortunately this
|
|
is more complicated. Some native, non-Cygwin Windows applications will
|
|
misbehave badly in this situation. A well-known example are certain versions
|
|
of Visual-C++.</para>
|
|
|
|
</sect3>
|
|
|
|
<sect3 id="ntsec-nopasswd2"><title id="ntsec-nopasswd2.title">Switching the user context without password, Method 2: LSA authentication package</title>
|
|
|
|
<para>We're looking for another way to switch the user context without
|
|
having to provide the password. Another technique is to create an
|
|
LSA authentication package. LSA is an acronym for "Local Security Authority"
|
|
which is a protected part of the operating system which only allows changes
|
|
to become active when rebooting the system after the change. Also, as soon as
|
|
the LSA encounters serious problems (for instance, one of the protected
|
|
LSA processes died), it triggers a system reboot. LSA is the part of
|
|
the OS which cares for the user logons and which also creates logon
|
|
sessions.</para>
|
|
|
|
<para>An LSA authentication package is a DLL which has to be installed
|
|
as part of the LSA. This is done by tweaking a special registry key.
|
|
Cygwin provides such an authentication package. It has to be installed
|
|
and the machine has to be rebooted to activate it. This is the job of the
|
|
shell script <filename>/usr/bin/cyglsa-config</filename> which is part of
|
|
the Cygwin package.</para>
|
|
|
|
<para>After running <filename>/usr/bin/cyglsa-config</filename> and
|
|
rebooting the system, the LSA authentication package is used by Cygwin
|
|
when <command>set(e)uid</command> is called by an application. The
|
|
created access token using this method has its own logon session.</para>
|
|
|
|
<para>The very special and very dangerous "Create a token object" user
|
|
right is not required by a user using this method. Other privileged
|
|
user rights are still necessary, especially the "Act as part of the
|
|
operating system" right, but that's just business as usual.</para>
|
|
|
|
<para>The user is correctly identified, even by delicate native applications
|
|
which choke on that using the <command>NtCreateToken</command> method.</para>
|
|
|
|
<para>Disadvantages? Yes, sure, this is Windows. The access token
|
|
created using LSA authentication still lacks the credentials for network
|
|
access. After all, there still hasn't been any password authentication
|
|
involved. The requirement to reboot after every installation or
|
|
deinstallation of the cygwin LSA authentication DLL is just a minor
|
|
inconvenience compared to that...</para>
|
|
|
|
<para>Nevertheless, this is already a lot better than what we get by
|
|
using <command>NtCreateToken</command>, isn't it?</para>
|
|
-->
|
|
|
|
</sect3>
|
|
|
|
<sect3 id="ntsec-nopasswd3"><title id="ntsec-nopasswd3.title">Switching the user context without password, Method 2: With password</title>
|
|
|
|
<para>Not being able to access network shares without having to specify
|
|
a cleartext password on the command line or in a script is a harsh problem
|
|
for automated logons for testing purposes and similar stuff.</para>
|
|
|
|
<para>Fortunately there is a solution, but it has its own drawbacks.
|
|
But, first things first, how does it work? The title of this section
|
|
says it all. Instead of trying to logon without password, we just logon
|
|
with password. The password gets stored two-way encrypted in a hidden,
|
|
obfuscated area of the registry, the LSA private registry area. This
|
|
part of the registry contains, for instance, the passwords of the Windows
|
|
services which run under some non-default user account.</para>
|
|
|
|
<para>So what we do is to utilize this registry area for the purpose of
|
|
<command>set(e)uid</command>. The Cygwin command <command><link
|
|
linkend="passwd">passwd</link> -R</command> allows a user to specify
|
|
his/her password for storage in this registry area. When this user
|
|
tries to login using ssh with public key authentication, Cygwin's
|
|
<command>set(e)uid</command> examines the LSA private registry area and
|
|
searches for a Cygwin specific key which contains the password. If it
|
|
finds it, it calls <command>LogonUser</command> under the hood, using
|
|
this password. If that works, <command>LogonUser</command> returns an
|
|
access token with all credentials necessary for network access.</para>
|
|
|
|
<para>For good measure, and since this way to implement
|
|
<command>set(e)uid</command> is not only used by Cygwin but also by
|
|
Microsoft's SFU (Services for Unix), we also look for a key stored by
|
|
SFU (using the SFU command <command>regpwd</command>) and use that if it's
|
|
available.</para>
|
|
|
|
<para>We got it. A full access token with its own logon session, with
|
|
all network credentials. Hmm, that's heaven...</para>
|
|
|
|
<para>Back on earth, what about the drawbacks?</para>
|
|
|
|
<para>First, adding a password to the LSA private registry area
|
|
requires administrative access. So calling <command>passwd -R</command>
|
|
as a normal user will fail! Cygwin provides a workaround for
|
|
this. If <command>cygserver</command> is started as a service running
|
|
under the SYSTEM account (which is the default way to run
|
|
<command>cygserver</command>) you can use <command>passwd -R</command>
|
|
as normal, non-privileged user as well.</para>
|
|
|
|
<para>Second, as aforementioned, the password is two-way encrypted in a
|
|
hidden, obfuscated registry area. Only SYSTEM has access to this area
|
|
for listing purposes, so, even as an administrator, you can't examine
|
|
this area with regedit. Right? No. Every administrator can start
|
|
regedit as SYSTEM user, the Internet is your friend here.</para>
|
|
|
|
<para>Additionally, if an administrator knows under which name
|
|
the private key is stored (which is well-known since the algorithms
|
|
used to create the Cygwin and SFU keys are no secret), every administrator
|
|
can access the password of all keys stored this way in the registry.</para>
|
|
|
|
<para>Conclusion: If your system is used exclusively by you, and if
|
|
you're also the only administrator of your system, and if your system is
|
|
adequately locked down to prevent malicious access, you can safely use
|
|
this method. If your machine is part of a network which has
|
|
dedicated administrators, and you're not one of these administrators,
|
|
but you (think you) can trust your administrators, you can probably
|
|
safely use this method.</para>
|
|
|
|
<para>In all other cases, don't use this method. You have been warned.</para>
|
|
|
|
</sect3>
|
|
|
|
<sect3 id="ntsec-setuid-impl"><title id="ntsec-setuid-impl.title">Switching the user context, how does it all fit together?</title>
|
|
|
|
<para>Now we learned about three different ways to switch the user
|
|
context using the <command>set(e)uid</command> system call, but
|
|
how does <command>set(e)uid</command> really work? Which method does it
|
|
use now?</para>
|
|
|
|
<para>The answer is, all three of them. So here's a brief overview
|
|
what <command>set(e)uid</command> does under the hood:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>When <command>set(e)uid</command> is called, it tests if the
|
|
user context had been switched by an earlier call already, and if the
|
|
new user account is the privileged user account under which the process
|
|
had been started originally. If so, it just switches to the original
|
|
access token of the process it had been started with.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
Next, it tests if an access token has been stored by an earlier call
|
|
to <command>cygwin_set_impersonation_token</command>. If so, it tests
|
|
if that token matches the requested user account. If so, the stored
|
|
token is used for the user context switch.</para>
|
|
|
|
<para>
|
|
If not, there's no predefined token which can just be used for
|
|
the user context switch, so we have to create a new token. The order
|
|
is as follows.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Check if the user has stored the logon password in the LSA
|
|
private registry area, either under a Cygwin key, or under a SFU key.
|
|
If so, use this to call <command>LogonUser</command>. If this
|
|
succeeds, we use the resulting token for the user context switch.</para>
|
|
</listitem>
|
|
<!--
|
|
<listitem>
|
|
<para>Otherwise, check if the Cygwin-specifc LSA authentication package
|
|
has been installed and is functional. If so, use the appropriate LSA
|
|
calls to communicate with the Cygwin LSA authentication package and
|
|
use the returned token.</para>
|
|
</listitem>
|
|
-->
|
|
<listitem>
|
|
<para>Otherwise, use the default <literal>S4U</literal> authentication
|
|
to create a token.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Older systems, like WOW64 under Windows 7 64 bit, don't support
|
|
<literal>S4U</literal> authentication for local machine accounts. On
|
|
these systems Cygwin falls back to an old and otherwise deprecated
|
|
method to create a user token from scratch. The underlying system call
|
|
is undocumented and has an unfortunate requirement: We have to create a
|
|
special account with dangerous permissions to perform this action.
|
|
Therefore this is only enabled on affected systems.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>If all of the above fails, our process has insufficient privileges
|
|
to switch the user context at all, so <command>set(e)uid</command>
|
|
fails and returns -1, setting errno to EPERM.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
</sect3>
|
|
|
|
</sect2>
|
|
|
|
</sect1>
|