aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2008-12-02 17:07:40 +0000
committerCorinna Vinschen <corinna@vinschen.de>2008-12-02 17:07:40 +0000
commite39e660c5466419d5226fd26109e5e2e5b384962 (patch)
tree57518aab37a20ed5890b7825d02d5724b5b7c03f
parentea7630b0ff6ddcb520c7f8a60e74e06de213b3c7 (diff)
downloadnewlib-e39e660c5466419d5226fd26109e5e2e5b384962.zip
newlib-e39e660c5466419d5226fd26109e5e2e5b384962.tar.gz
newlib-e39e660c5466419d5226fd26109e5e2e5b384962.tar.bz2
* ntsec.sgml: Finishing up changes for 1.7.
-rw-r--r--winsup/doc/ChangeLog4
-rw-r--r--winsup/doc/ntsec.sgml608
2 files changed, 422 insertions, 190 deletions
diff --git a/winsup/doc/ChangeLog b/winsup/doc/ChangeLog
index 1e29b59..9f57e4e 100644
--- a/winsup/doc/ChangeLog
+++ b/winsup/doc/ChangeLog
@@ -1,3 +1,7 @@
+2008-12-02 Corinna Vinschen <corinna@vinschen.de>
+
+ * ntsec.sgml: Finishing up changes for 1.7.
+
2008-12-01 Corinna Vinschen <corinna@vinschen.de>
* ntsec.sgml: Further changes for 1.7. Switch from "NT" to "Windows".
diff --git a/winsup/doc/ntsec.sgml b/winsup/doc/ntsec.sgml
index 3d568e1..349170f 100644
--- a/winsup/doc/ntsec.sgml
+++ b/winsup/doc/ntsec.sgml
@@ -6,7 +6,7 @@ the authentication model is used to allow to switch the user context 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 option</link>
+controlled by the <link linkend="mount-table">mount</link> option
<literal>(no)acl</literal> which is set to <literal>acl</literal> by
default.</para>
@@ -67,9 +67,9 @@ The next two numbers are the authority which shows the initiated what
kind of SID this is. There are a couple of builtin accounts and
accounts with very special meaning. However, computer and domain SIDs
always start with "S-1-5-21". The next three numbers, all 32 bit values,
-are the unique 96 bit identifier of the comupter system. This is
+are the unique 96 bit identifier of the computer system. This is
hopefully unique all over the world, but in practice it's sufficient if
-the comuter SIDs are unique within a single Windows network.</para>
+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
@@ -97,7 +97,7 @@ controller and you would like to create a domain account "johndoe":</para>
S-1-5-21-186985262-1144665072-740312968-1207
</screen>
-<para>Ok, so you now have two accounts called johndoe, one account
+<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
@@ -110,7 +110,7 @@ Different SID, different account. Full stop.
<para>The last part of the SID, the so called "Relative IDentifier" (RID),
is by default used as UID and/or GID under Cygwin when you create the
<filename>/etc/passwd</filename> and <filename>/etc/group</filename>
-files using the <command>mkpasswd</command> and <command>mkgroup</command>
+files using the <command><link linkend="mkpasswd">mkpasswd</link></command> and <command><link linkend="mkgroup">mkgroup</link></command>
tools. Domain account UIDs and GIDs are offset by 10000 by default
which might be a bit low for very big organizations. Fortunately there's
an option in both tools to change the offset...</para>
@@ -121,8 +121,9 @@ for the group of "all users" or "world" or "others". The last three rwx
bits in a 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 more circumstances instead of actual users or groups. Here
-are a few examples for well-known SIDs:</para>
+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...
@@ -140,7 +141,7 @@ SYSTEM S-1-5-18 A special account which has all
an uber-root account.
</screen>
-<para>For a full list please refer to
+<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>.
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
@@ -166,8 +167,8 @@ 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 mamber of the administrators
-group on "foo", when logging in on "foo". Neat, isn't it?</para>
+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
@@ -194,6 +195,16 @@ data. But there's a problem with the definition of a "correct" ACL
which disallows to map certain POSIX permissions cleanly. See
<xref linkend="ntsec-mapping"></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 Solaris
+API to access Windows ACLs in a Unixy way. At the time of writing this
+document, the Cygwin implementation of the Solaris API isn't quite up
+to speed. For instance, it doesn't handle access denied ACEs gracefully.
+So, use with care. Online man pages for the Solaris ACL API can be
+found on <ulink url="http://docs.sun.com">http://docs.sun.com</ulink>.</para>
+
</sect2>
<sect2 id="ntsec-files"><title id="ntsec-files.title">File permissions</title>
@@ -206,7 +217,7 @@ SIDs, and a DACL which contains ACEs for the owner, the group and for
<para>To use Windows security correctly, Cygwin depends on the files
<filename>/etc/passwd</filename> and <filename>/etc/group</filename>.
-These files define the traslation between the Cygwin uid/gid and the
+These files define the translation between the Cygwin uid/gid and the
Windows SID. The SID is stored in the pw_gecos field in
<filename>/etc/passwd</filename>, and in the gr_passwd field in
<filename>/etc/group</filename>. Since the pw_gecos field can contain
@@ -218,10 +229,9 @@ usually do this for you.</para>
<para>Another interesting entry in the pw_gecos field (which is also
usually created by running <command>mkpasswd</command>) is the Windows user
-name entry. It takes the form "U-domain\username" and is typically used
-by services to authenticate a user. Logging in through <command>ssh</command>
-or <command>telnet</command> are two typical scenarios.
-</para>
+name entry. It takes the form "U-domain\username" and is sometimes used
+by services to authenticate a user. Logging in through
+<command>telnet</command> is a common scenario.</para>
<para>A typical snippet from <filename>/etc/passwd</filename>:</para>
@@ -237,12 +247,13 @@ corinna:unused:11001:11125:U-BAR\corinna,S-1-5-21-2913048732-1697188782-34488111
<para>The SYSTEM entry is usually needed by services. The Administrators
entry (Huh? A group in /etc/passwd?) is only here to allow
-<command>ls</command> to print some file ownerships correctly. Windows
-doesn't care if the owner of a file is a user or a group. In older
-versions of Windows NT the default ownership for files created by an
-administrator account was set to the group Administrators instead of to
-the creating user account. This has changed, but for those older
-systems it's convenient to have the Administrators group in
+<command>ls</command> and similar commands to print some file ownerships
+correctly. Windows doesn't care if the owner of a file is a user or a
+group. In older versions of Windows NT the default ownership for files
+created by an administrator account was set to the group Administrators
+instead of to the creating user account. This has changed, but you can
+still switch to this setting on newer systems. So it's convenient to
+have the Administrators group in
<filename>/etc/passwd</filename>.</para>
<para>The really interesting entries are the next two. The Administrator
@@ -251,7 +262,7 @@ account in the domain BAR. The information given in the pw_gecos field
are all we need to exactly identify an account, and to have a two way
translation, from Windows account name/SID to Cygwin account name uid and
vice versa. Having this complete information allows us to choose a Cygwin
-name and uid which doesn't have to match the Windows account at all. As
+user name and uid which doesn't have to match the Windows account at all. As
long as the pw_gecos information is available, we're on the safe side:</para>
<example id="ntsec-passwd-tweaked">
@@ -292,10 +303,11 @@ which in turn is member of the well-known group "Users". So, if it's
more feasible in your environment that the user's primary group is
"Users", just set the user's primary group in <filename>/etc/passwd</filename>
to the Cygwin uid of "Users" (see in <filename>/etc/group</filename>,
-default 545).</para>
+default 545) and let the user create files with a default group ownership
+of "Users".</para>
<para>However, here's a WARNING: If you want to do similar changes to
-your files, please do that only if you're feeling comfortably with the
+your files, please do that only if you're feeling comfortable with the
concepts. Otherwise don't be surprised if some stuff doesn't work
anymore. If you screwed up things, revert to <filename>/etc/passwd</filename>
and <filename>/etc/group</filename> files created by mkpasswd
@@ -306,6 +318,78 @@ strangely.</para>
</sect2>
+<sect2 id="ntsec-ids"><title id="ntsec-ids.title">Special values of user and group ids</title>
+
+<para>If the current user is not present in
+<filename>/etc/passwd</filename>, that user's uid is set to a
+special value of 400. The user name for the current user will always be
+shown correctly. If another user (or a Windows group, treated as a
+user) is not present in <filename>/etc/passwd</filename>, the uid of
+that user will have a special value of -1 (which would be shown by
+<command>ls</command> as 65535). The user name shown in this case will
+be '????????'.</para>
+
+<para>If the current user is not present in
+<filename>/etc/passwd</filename>, that user's login gid is set to a
+special value of 401. The gid 401 is shown as 'mkpasswd',
+indicating the command that should be run to alleviate the
+situation.</para>
+
+<para>If another user is not present in
+<filename>/etc/passwd</filename>, that user's login gid is set to a
+special value of -1. If the user is present in
+<filename>/etc/passwd</filename>, but that user's group is not in
+<filename>/etc/group</filename> and is not the login group of that user,
+the gid is set to a special value of -1. The name of this group
+(id -1) will be shown as '????????'.</para>
+
+<para>If the current user is present in
+<filename>/etc/passwd</filename>, but that user's login group is not
+present in <filename>/etc/group</filename>, the group name will be shown
+as 'mkgroup', again indicating the appropriate command.</para>
+
+<para>A special case is if the current user's primary group SID is noted
+in the user's <filename>/etc/passwd</filename> entry using another group
+id than the group entry of the same group SID in
+<filename>/etc/group</filename>. This should be noted and corrected.
+The group name printed in this case is
+'passwd/group_GID_clash(PPP/GGG)', with PPP being the gid as noted
+in <filename>/etc/passwd</filename> and GGG the gid as noted in
+<filename>/etc/group</filename>.</para>
+
+<para>To summarize:</para>
+<itemizedlist spacing="compact">
+
+<listitem><para>If the current user doesn't show up in
+<filename>/etc/passwd</filename>, it's <emphasis>group</emphasis> will
+be named 'mkpasswd'.</para></listitem>
+
+<listitem><para>Otherwise, if the login group of the current user isn't
+in <filename>/etc/group</filename>, it will be named 'mkgroup'.</para>
+</listitem>
+
+<listitem><para>Otherwise a group not in <filename>/etc/group</filename>
+will be shown as '????????' and a user not in
+<filename>/etc/passwd</filename> will be shown as "????????".</para>
+</listitem>
+
+<listitem><para>If different group ids are used for a group with the same
+SID, the group name is shown as 'passwd/group_GID_clash(PPP/GGG)' with
+PPP and GGG being the different group ids.</para></listitem>
+
+</itemizedlist>
+
+<para>
+Note that, since the special user and group names are just indicators,
+nothing prevents you from actually having a user named `mkpasswd' in
+<filename>/etc/passwd</filename> (or a group named `mkgroup' in
+<filename>/etc/group</filename>). If you do that, however, be aware of
+the possible confusion.
+</para>
+
+</sect2>
+
+
<sect2 id="ntsec-mapping"><title id="ntsec-mapping.title">The POSIX permission mapping leak</title>
<para>As promised earlier, here's the problem when trying to map the
@@ -320,16 +404,16 @@ documentation explains in short the following:</para>
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.</para></listitem>
+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 _should_ precede any access
-allowed ACE. ACLs following this rule are called "canonical"</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
@@ -343,7 +427,7 @@ the Windows NT4 explorer is completely unable to deal with access denied ACEs
while the Windows 2000 and later properties dialog rearranges the order of the
ACEs to canonical order before you can read them. Thank God, the sort
order remains unchanged if one presses the Cancel button. But don't
-even _think_ of pressing OK...</para>
+even <emphasis role='bold'>think</emphasis> of pressing OK...</para>
<para>Canonical ACLs are unable to reflect each possible combination
of POSIX permissions. Example:</para>
@@ -405,43 +489,49 @@ aren't able (or willing) to deal with that order.</para>
</sect2>
-<sect2 id="ntsec-setuid"><title id="ntsec-setuid.title">Switching the user context</title>
-<para>POSIX applications which have to switch the user context are using
-the <command>setuid</command> and <command>seteuid</command> calls.</para>
+<sect2 id="ntsec-setuid-overview"><title id="ntsec-setuid-overview.title">Switching the user context</title>
-<para>Windows doesn't support the concept of these calls in a simple
+<para>POSIX applications which have to switch the user context are using
+the <command>setuid</command> and <command>seteuid</command> calls.
+Windows doesn't support the concept of these calls in a simple
fashion and switching the user context in Windows is generally a tricky
process with lots of "behind the scenes" magic involved.</para>
-<!-- TODO: The rest of the file... -->
+<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 to define threads with restricted
+permissions. To switch the user context the process has to request such
+an access token for the new user.</para>
-<para>Windows uses so-called `access tokens' to identify a user and it's
-permissions. To switch the user context the application has to request
-such an `access token'. This is typically done by calling the Win32 API
-function <command>LogonUser</command>. The access token is returned and
-either used in <command>ImpersonateLoggedOnUser</command> to change user
-context of the current process or in <command>CreateProcessAsUser</command>
-to change user context of a spawned child process. An important restriction
-is that the application using <command>LogonUser</command> must have special
-permissions:</para>
-
-<screen>
-"Act as part of the operating system"
-"Replace process level token"
-"Increase quotas"
-</screen>
+</sect2>
-<para>Note that administrators do not have all these user rights set
-by default.</para>
+<sect2 id="ntsec-logonuser"><title id="ntsec-logonuser.title">Switching the user context with password authentication</title>
-<para>Two new Cygwin calls are introduced to support porting
-<command>setuid</command> applications with a minimum of effort. 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. The call to <command>sexec</command> is not needed
-anymore. Porting a <command>setuid</command> application is illustrated by
-a short example:</para>
+<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>. 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. 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 are really 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 to patch 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[
@@ -462,26 +552,25 @@ a short example:</para>
#ifdef __CYGWIN__
/* Patch the typical password test. */
- if (is_winnt)
- {
- HANDLE token;
-
- /* Try to get the access token from NT. */
- token = cygwin_logon_user (user_pwd_entry, cleartext_password);
- if (token == INVALID_HANDLE_VALUE)
- error_exit;
- /* Inform Cygwin about the new impersonation token.
- Cygwin is able now, to switch to that user context by
- setuid or seteuid calls. */
- cygwin_set_impersonation_token (token);
- }
- else
-#endif /* CYGWIN */
- /* Use standard method for W9X as well. */
+ {
+ 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 is able now, to switch to that user context by
+ setuid or seteuid calls. */
+ cygwin_set_impersonation_token (token);
+ }
+#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_password))
error_exit;
+#endif /* CYGWIN */
[...]
@@ -494,157 +583,296 @@ a short example:</para>
</screen>
-<para>The new Cygwin call to retrieve an access token is defined as follows:</para>
+</sect2>
-<screen>
-#include &lt;windows.h&gt;
-#include &lt;sys/cygwin.h&gt;
+<sect2 id="ntsec-nopasswd1"><title id="ntsec-nopasswd1.title">Switching the user context without password, Method 1: Create a token from scratch</title>
+
+<para>So far unfortunate for the implementation of a
+<command>set(e)uid</command> call is the fact that the calling process
+needs the password of the user it wants to switch to. Applications like
+<command>sshd</command> wishing to switch the user context after a
+successful public key authentication, or <command>cron</command> which
+has to switch the user without any authentication are stuck here. But
+there are other ways to get new user tokens.</para>
+
+<para>One way is just to create a user token from scratch. This is
+accomplished by using an (officially undocumented) function on the NT
+function level. The NT function level is closer to the actual kernel
+than the Win32 level. Actually the Win32 functions are implemented
+using the NT functions. The function we're interested in is
+<command>NtCreateToken</command>. This function allows to specify
+user, groups, permissions and almost everything you need to create
+a user token, without the need to specify the user password. The
+only restriction for using this function is that the calling process
+needs the "Create a token object" user right, which only the
+SYSTEM user account has by default, and which is considered the most
+dangerous right a user can have on Windows systems.</para>
+
+<para>That sounds good. 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 <command>NtCreateToken</command>
+has a few drawbacks.</para>
+
+<para>First of all, beginning with Windows Server 2003,
+the permission "Create a token object" gets explicitely removed from
+the SYSTEM user's access token, when starting services under that
+account. That requires 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 also 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>What that means is this. Consider a service started under the
+SYSTEM account (up to Windows XP) 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>
+
+<para>Last but not least, 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
+<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>
-HANDLE
-cygwin_logon_user (struct passwd *pw, const char *cleartext_password)
+<screen>
+bash$ net use '\\server\share' /user:DOMAIN\my_user my_users_password
</screen>
-<para>You can call that function as often as you want for different user
-logons and remember the access tokens for further calls to the second function.</para>
+<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>
-#include &lt;windows.h&gt;
-#include &lt;sys/cygwin.h&gt;
-
-void
-cygwin_set_impersonation_token (HANDLE hToken);
+bash$ grep foo //server/share/foofile
</screen>
-<para> is the call to inform Cygwin about the user context to which further
-calls to <command>setuid</command>/<command>seteuid</command> should switch to.
-While you always need the correct access token to do a
-<command>setuid</command>/<command>seteuid</command> to another user's context,
-you are always able to use <command>setuid</command>/<command>seteuid</command>
-to return to your own user context by giving your own uid as parameter.</para>
-
-<para>If you have remembered several access tokens from calls to
-<command>cygwin_logon_user</command> you can switch to different user
-contexts by observing the following order:</para>
-
-<screen>
+</sect2>
- cygwin_set_impersonation_token (user1_token);
- seteuid (user1_uid);
+<sect2 id="ntsec-nopasswd2"><title id="ntsec-nopasswd2.title">Switching the user context without password, Method 2: LSA authentication package</title>
+
+<para>Caveat: The method described in this chapter only works starting
+with Windows 2000. Windows NT4 users have to use one of the other
+methods described in this document.</para>
+
+<para>So 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>This method has two advantages over the <command>NtCreateToken</command>
+method.</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>
-[...]
+</sect2>
- seteuid (own_uid);
- cygwin_set_impersonation_token (user2_token);
- seteuid (user2_uid);
+<!-- TODO: The rest of the file... -->
-[...]
+<sect2 id="ntsec-nopasswd3"><title id="ntsec-nopasswd3.title">Switching the user context without password, Method 3: With password</title>
+
+<para>Ok, so we have solved almost any problem, except for the network
+access problem. 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 thing 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. Just keep in mind that this
+requires to set the environment variable CYGWIN to contain the word
+"server" before running <command>passwd -R</command>, if it's not
+already set anyway. See <xref linkend="using-cygwinenv"></xref>.
+Example:</para>
- seteuid (own_uid);
- cygwin_set_impersonation_token (user1_token);
- seteuid (user1_uid);
+<screen>
+bash$ echo $CYGWIN
+tty
+bash$ export CYGWIN="tty server"
+bash$ passwd -R
+</screen>
-etc.
+<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:</para>
+<screen>
+bash$ date
+Tue Dec 2 16:28:03 CET 2008
+bash$ at 16:29 /interactive regedit.exe
</screen>
-</sect2>
+<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>
-<sect2 id="ntsec-switch"><title id="ntsec-switch.title">Switching User
-Context</title>
+<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 savely 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
+savely use this method.</para>
-<para>
-Since Cygwin release 1.3.3, applications that are members of the
-Administrators group and have the <command>Create a token
-object</command>, <command>Replace a process level token</command> and
-<command>Increase Quota</command> user rights can switch user
-context without giving a password by just calling the usual
-<command>setuid</command>, <command>seteuid</command>,
-<command>setgid</command> and <command>setegid</command> functions.
-</para>
-<para>
-Up to Windows XP the <systemitem
-class="username">SYSTEM</systemitem> user has these privileges and can
-run services such as <command>sshd</command>. However, startung with Windows 2003
-<systemitem class="username">SYSTEM</systemitem> lacks the
-<command>Create a token object</command> right, so it is necessary to
-create a special user with all the necessary rights, as
-well as <command>Logon as a service</command>, to run such services.
-For security reasons this user should be denied the rights to logon
-interactively or over the network. All this is done by configuration
-scripts such as <command>ssh-host-config</command>.
-</para>
-<para>
-An important restriction of this method is that a process started
-without a password cannot access network shares which require
-authentication. This also applies to subprocesses which switched user
-context without a password. Therefore, when using
-<command>ssh</command> or <command>rsh</command> without a password, it
-is typically not possible to access network drives.
-</para>
+<para>In all other cases, don't use this method. You have been warned.</para>
</sect2>
-<sect2 id="ntsec-ids"><title id="ntsec-ids.title">Special values of user and group
-ids</title>
+<sect2 id="ntsec-setuid-impl"><title id="ntsec-setuid-impl.title">Switching the user context, how does that all fit together?</title>
-<para>
-If the current user is not present in <filename>/etc/passwd</filename>,
-that user's user id is set to a special value of 400. The user name for
-the current user will always be shown correctly. If another user
-(or a Windows group, treated as a user) is not present in
-<filename>/etc/passwd</filename>, the user id of that user will have a
-special value of -1 (which would be shown by <command>ls</command> as
-65535). The user name shown in this case will be '????????'.
-</para>
+<para>Now we learned about four 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>
-If the current user is not present in <filename>/etc/passwd</filename>,
-that user's login group id is set to a special value of 401. If another
-user is not present in <filename>/etc/passwd</filename>, that user's login
-group id is set to a special value of -1. If the user is present in
-<filename>/etc/passwd</filename>, but that user's group is not in
-<filename>/etc/group</filename> and is not the login group of that user,
-the group id is set to a special value of -1. The name of this group
-(id -1) will be shown as '????????'.
-In releases of Cygwin before 1.3.20, the group id 401 had a group name
-'None'. Since Cygwin release 1.3.20, the group id 401 is shown as
-'mkpasswd', indicating the command that should be run to alleviate the
-situation.
-</para>
+<para>The answer is, all four 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>
-Also, since Cygwin release 1.3.20, if the current user is present in
-<filename>/etc/passwd</filename>, but that user's login group is not
-present in <filename>/etc/group</filename>, the group name will be shown
-as 'mkgroup', again indicating the appropriate command.
-</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>To summarize:</para>
-<itemizedlist spacing="compact">
+<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>If the current user doesn't show up in
-<filename>/etc/passwd</filename>, it's <emphasis>group</emphasis> will
-be named 'mkpasswd'.</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, if the login group of the current user isn't
-in <filename>/etc/group</filename>, it will be named 'mkgroup'.</para>
+<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 a group not in <filename>/etc/group</filename>
-will be shown as '????????' and a user not in
-<filename>/etc/passwd</filename> will be shown as "????????".</para>
+<listitem>
+<para>Last chance, try to use the <command>NtCreateToken</command> call
+to create a token. If that works, use this token.</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>
-<para>
-Note that, since the special user and group names are just indicators,
-nothing prevents you from actually having a user named `mkpasswd' in
-<filename>/etc/passwd</filename> (or a group named `mkgroup' in
-<filename>/etc/group</filename>). If you do that, however, be aware of
-the possible confusion.
-</para>
-
</sect2>
</sect1>