Welcome to mirror list, hosted at ThFree Co, Russian Federation.

ntsec.sgml « doc « winsup - cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: b44c04919377d2d996b7f3c2681a92f4e4668e65 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
<sect1 id="ntsec"><title>NT security</title>

<para>The setting of POSIX like object permissions is controlled by the 
<link linkend="mount-table">mount option</link> <literal>(no)acl</literal>
which is set to <literal>acl</literal> by default.  The design goal
is to utilize the Windows access control API to implement real POSIX
permissions.</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>

<sect2 id="ntsec-common"><title>NT security</title>

<para>In the NT security model, almost any "object" is securable.
"Objects" are files, processes, threads, semaphores, etc.</para>

<para>Every object has a data structure called "security descriptor" (SD)
attached.  The SD contains all information necessary to control who can
how access an object.  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.</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 AD
domains.  SIDs are basically comparable to POSIX UIDs and 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.  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 leading "S" has no further meaning except to show that this is
a SID.  The next number is a version number which is always 1 so far.
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
hopefully unique all over the world, but in practice it's sufficient if
the comuter 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>Ok, 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 NOT identical.
For all the machines know there are two different accounts, one is
"FOO\johndoe", the other one is "BAR\johndoe" or "johndoe@bar.local".
Different SID, different account.  Full stop.
</para>

<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>
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>

<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 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>

<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
<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
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 mamber of the administrators
group on "foo", when logging in on "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.</para>

</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 in POSIX.
Basically this is done by defining a SD 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>To use NT 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
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
more information than just a SID, there are some rules for the layout.
It's required that the SID is the last entry of the pw_gecos field,
assuming that the entries in pw_gecos are comma-separated.  The
commands <command>mkpasswd</command> and <command>mkgroup</command>
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>

<para>A typical snippet from <filename>/etc/passwd</filename>:</para>

<example id="ntsec-passwd">
<title>/etc/passwd:</title>
<screen>
SYSTEM:*:18:544:,S-1-5-18::
Administrators:*:544:544:,S-1-5-32-544::
Administrator:unused:500:513:U-FOO\Administrator,S-1-5-21-790525478-115176313-839522115-500:/home/Administrator:/bin/bash
corinna:unused:11001:11125:U-BAR\corinna,S-1-5-21-2913048732-1697188782-3448811101-1001:/home/corinna:/bin/tcsh
</screen>
</example>

<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
<filename>/etc/passwd</filename>.</para>

<para>The really interesting entries are the next two.  The Administrator
entry is for the local administrator, the corinna entry matches the corinna
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
long as the pw_gecos information is available, we're on the safe side:</para>

<example id="ntsec-passwd-tweaked">
<title>/etc/passwd, tweaked:</title>
<screen>
root:unused:0:513:U-FOO\Administrator,S-1-5-21-790525478-115176313-839522115-500:/home/Administrator:/bin/bash
thursday_next:unused:11001:11125:U-BAR\corinna,S-1-5-21-2913048732-1697188782-3448811101-1001:/home/corinna:/bin/tcsh
</screen>
</example>

<para>  The above <filename>/etc/passwd</filename> will still work fine.
You can now login via <command>ssh</command> as the user "root", and
Cygwin dutyfully translates "root" into the Windows user
"FOO\Administrators" and files owned by FOO\Administrators are shown to
have the uid 0 when calling <command>ls -ln</command>.  All you do you're
actually doing as Administrator.  Files created as root will be owned by
FOO\Administrator.  And the domain user BAR\corinna can now happily
pretend to be Thursday Next, but will wake up sooner or later finding
out she's still actually the domain user BAR\corinna...</para>

<para>Do I have to mention that you can also rename groups in
<filename>/etc/group</filename>?  As long as the SID is present and correct,
all is well.  This allows for instance to rename the "Administrators" group
to "root" as well:</para>

<example id="ntsec-group-tweaked">
<title>/etc/group, tweaked:</title>
<screen>
root:S-1-5-32-544:544:
</screen>
</example>

<para>Last but not least you can also change the primary group of a user
in <filename>/etc/passwd</filename>.  The only requirement is that the user
is actually a member of the new primary group in Windows.  For instance,
normal users in a domain environment are members in the group "Domain Users",
which in turn is member of the well-known group "Users".  Additionally let's
assume the user is also a member of the newly created group .  The default
primary group for users is 

<!-- TODO: The rest of the file... -->

</para>

<para>As you can see, I changed my primary group membership from 513 (None)
to 547 (powerusers).  So all files I created inside of Cygwin were now owned
by the powerusers group instead of None.  This is the way I liked it.</para>

<para>Groups may be mentioned in the passwd file, too. This has two
advantages:</para>

<itemizedlist spacing="compact">
<listitem><para>Because NT assigns them to files as owners, a
<command>ls -l</command> is often more readable.</para></listitem>
<listitem><para>Moreover it's possible to assigned them to files as
owners with Cygwin's <command>chown</command>.</para></listitem>
</itemizedlist>

<para>The group `system' is the aforementioned synonym for the operating system
itself and is normally the owner of processes that are started through
service manager. The same is true for files that are created by
processes, which are started through service manager.</para>

</sect2>

<sect2 id="ntsec-sids"><title id="ntsec-sids.title">NT SIDs in Cygwin</title>

<para>This has the following advantages:</para>
<itemizedlist spacing="compact">
<listitem><para>ntsec works better in domain environments.</para></listitem>
<listitem><para>Accounts (users and groups) may get another name in
Cygwin than their NT account name. The name in <filename>/etc/passwd</filename>
or <filename>/etc/group</filename> is transparently used by Cygwin
applications (e.g. <command>chown</command>, <command>chmod</command>,
<command>ls</command>):</para>

<screen>
root::500:513::/home/root:/bin/sh
</screen>

<para>instead of</para>

<screen>
adminstrator::500:513::/home/root:/bin/sh
</screen>

<para>Caution: If you like to use the account as login account via
<command>telnet</command> etc. you have to remain the name unchanged or
you have to use the special version of <command>login</command> which is
part of the standard Cygwin distribution since 1.1.</para></listitem>
<listitem><para>Cygwin UIDs and GIDs are now not necessarily the RID
part of the NT SID:</para>

<screen>
root::0:513:S-1-5-21-54355234-56236534-345635656-500:/home/root:/bin/sh
</screen>

<para>instead of</para>

<screen>
root::500:513::/home/root:/bin/sh
</screen>

</listitem>
<listitem><para>As in U*X systems UIDs and GIDs numbering scheme now
don't influence each other. So it's possible to have same Id's for a
user and a group:</para>
<example id="ntsec-passwd-root">
<title>/etc/passwd:</title>
<screen>
root::0:0:S-1-5-21-54355234-56236534-345635656-500:/home/root:/bin/sh
</screen>
</example>

<example id="ntsec-group-root">
<title>/etc/group:</title>
<screen>
root:S-1-5-32-544:0:
</screen>
</example>
</listitem>
</itemizedlist>

<para>The tools <command>mkpasswd</command> and <command>mkgroup</command>
create the needed entries by default. If you don't want that you can use
the options <literal>-s</literal> or <literal>--no-sids</literal>. I suggest
not to do this since ntsec works better when having the SIDs available.</para>

<para>Please note that the pw_gecos field in <filename>/etc/passwd</filename>
is defined as a comma separated list. The SID has to be the last field!</para>

<screen>
the_king::1:1:Elvis Presley,U-STILLHERE\elvis,S-1-5-21-1234-5678-9012-1000:/bin/sh
</screen>

<para>For a local user just drop the domain:</para>

<screen>
the_king::1:1:Elvis Presley,U-elvis,S-1-5-21-1234-5678-9012-1000:/bin/sh
</screen>

<para>In either case the password of the user is taken from the NT user
database, NOT from the passwd file!</para>

<para>As in the previous chapter I give my personal
<filename>/etc/passwd</filename> and <filename>/etc/group</filename> as
examples.  Please note that I've changed these files heavily!  There's no
need to change them that way, it's just for testing purposes and...
for fun.</para>

<example id="ntsec-passwd-ex-2">
<title>/etc/passwd</title>
<screen>
root:*:0:0:Administrators group,S-1-5-32-544::
SYSTEM:*:18:18:,S-1-5-18:/home/system:/bin/bash
admin:*:500:513:,S-1-5-21-1844237615-436374069-1060284298-500:/home/Administrator:/bin/bash
corinna:*:100:0:Corinna Vinschen,S-1-5-21-1844237615-436374069-1060284298-1003:/home/corinna:/bin/tcsh
Guest:*:501:546:,S-1-5-21-1844237615-436374069-1060284298-501:/home/Guest:/bin/bash
</screen>
</example>

<example id="ntsec-group-ex-2">
<title>/etc/group</title>
<screen>
root:S-1-5-32-544:0:
local:S-1-2-0:2:
network:S-1-5-2:3:
interactive:S-1-5-4:4:
authenticatedusers:S-1-5-11:5:
SYSTEM:S-1-5-18:18:
local_svc:S-1-5-19:19:
netwrk_svc:S-1-5-20:20:
none:S-1-5-21-1844237615-436374069-1060284298-513:513:
bckup_op:S-1-5-32-551:551:
guests:S-1-5-32-546:546:
pwrusers:S-1-5-32-547:547:
replicator:S-1-5-32-552:552:
users:S-1-5-32-545:545:
</screen>
</example>

<para>If you want to do similar changes to your files, please do that only
if you're feeling comfortably with the concepts.  Otherwise don't be surprised
if some stuff doesn't work anymore.  If you screwed up things, revert to files
created by mkpasswd and mkgroup.  Especially don't change the UID or the name
of user SYSTEM.  Even if that works mostly, some Cygwin applications running
as local service under that account could suddenly start behaving strangely.
</para>

</sect2>

<sect2 id="ntsec-mapping"><title id="ntsec-mapping.title">The mapping leak</title>

<para>Now its time to point out the leak in the NT permissions.
The official documentation explains in short the following:</para>
<itemizedlist spacing="compact">
<listitem><para>access allow ACEs are accumulated regarding to the
group membership of the caller.</para></listitem>
<listitem><para>The order of ACEs is important. The system reads them
in sequence until either any needed right is denied or all needed rights
are granted. Later ACEs are then not taken into account.</para></listitem>
<listitem><para>All access denied ACEs _should_ precede any
access allowed ACE.</para></listitem>
</itemizedlist>

<para>Note that the last rule is a preference, not a law. NT will correctly
deal with the ACL regardless of the sequence order. The second rule is
not modified to get the ACEs in the preferred order.</para>

<para>Unfortunately the security tab of the NT4 explorer is completely
unable to deal with access denied ACEs while the explorer of W2K rearranges
the order of the ACEs before you can read them. Thank God, the sort order
remains unchanged if one presses the Cancel button.</para>

<para>You still ask "Where is the leak?" NT ACLs are unable to reflect each
possible combination of POSIX permissions. Example:</para>

<screen>
rw-r-xrw-
</screen>

<para>1st try:</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>2st 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>3rd 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 official rules 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 for both, NT4 and W2K. Only the GUIs aren't
able to deal with that order.</para>

</sect2>

<sect2 id="ntsec-aclfuncs"><title id="ntsec-aclfuncs.title">The ACL API</title>

<para>For dealing with ACLs Cygwin now has the ACL API as it's
implemented in newer versions of Solaris. The new data structure
for a single ACL entry (ACE in NT terminology) is defined in
<filename>sys/acl.h</filename> as:</para>

<screen>
typedef struct acl {
  int     a_type;  /* entry type */
  uid_t   a_id;    /* UID | GID */
  mode_t  a_perm;  /* permissions */
} aclent_t;
</screen>

<para>The a_perm member of the aclent_t type contains only the bits
for read, write and execute as in the file mode. If e.g. read permission
is granted, all read bits (S_IRUSR, S_IRGRP, S_IROTH) are set.
CLASS_OBJ or MASK ACL entries are not fully implemented yet.</para>

<para>The new API calls are</para>

<screen>
acl(2), facl(2)
aclcheck(3),
aclsort(3),
acltomode(3), aclfrommode(3),
acltopbits(3), aclfrompbits(3),
acltotext(3), aclfromtext(3)
</screen>

<para>Like in Solaris, Cygwin has two new commands for working with
ACLs on the command line: <command>getfacl</command> and
<command>setfacl</command>.</para>

<para>Online man pages for the aforementioned commands and API calls can be
found on <ulink url="http://docs.sun.com">http://docs.sun.com</ulink> </para>

</sect2>

<sect2 id="ntsec-setuid"><title id="ntsec-setuid.title">New setuid concept</title>

<para>POSIX applications which have to switch the user context are using
the <command>setuid</command> and <command>seteuid</command> calls which
are not part of the Windows API.
Nevertheless these calls are supported under Windows NT/W2K since Cygwin
release 1.1.3.  Because of the nature of NT security an application which
needs the ability has to be patched, though.</para>

<para>NT 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 NT 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>

<para>Note that administrators do not have all these user rights set 
by default.</para>

<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>

<screen>
<![CDATA[
/* First include all needed cygwin stuff. */
#ifdef __CYGWIN__
#include <windows.h>
#include <sys/cygwin.h>
/* Use the following define to determine the Windows version */
#define is_winnt        (GetVersion() < 0x80000000)
#endif

[...]

  struct passwd *user_pwd_entry = getpwnam (username);
  char *cleartext_password = getpass ("Password:");

[...]

#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. */
    hashed_password = crypt (cleartext_password, salt);
    if (!user_pwd_entry ||
        strcmp (hashed_password, user_pwd_entry->pw_password))
      error_exit;

[...]

  /* Everything else remains the same! */

  setegid (user_pwd_entry->pw_gid);
  seteuid (user_pwd_entry->pw_uid);
  execl ("/bin/sh", ...);
]]>

</screen>

<para>The new Cygwin call to retrieve an access token is defined as follows:</para>

<screen>
#include &lt;windows.h&gt;
#include &lt;sys/cygwin.h&gt;

HANDLE
cygwin_logon_user (struct passwd *pw, const char *cleartext_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>

<screen>
#include &lt;windows.h&gt;
#include &lt;sys/cygwin.h&gt;

void
cygwin_set_impersonation_token (HANDLE hToken);
</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>

  cygwin_set_impersonation_token (user1_token);
  seteuid (user1_uid);

[...]

  seteuid (own_uid);
  cygwin_set_impersonation_token (user2_token);
  seteuid (user2_uid);

[...]

  seteuid (own_uid);
  cygwin_set_impersonation_token (user1_token);
  seteuid (user1_uid);

etc.

</screen>

</sect2>

<sect2 id="ntsec-switch"><title id="ntsec-switch.title">Switching User
Context</title>

<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>
On NT and Windows 2000 the <systemitem
class="username">SYSTEM</systemitem> user has these privileges and can
run services such as <command>sshd</command>. However, on 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>

</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 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>
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>
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>

<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>

</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>