This is the mail archive of the cygwin@sourceware.cygnus.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

ntsec documentation [was Re: grep 2.4 and permission denied]


Jay Bromley wrote:
> [...]
> Also, I am curious as to what setting the CYGWIN=ntsec environment
> setting really does. I haven't been able to find too much about this.
> I would appreciate any pointers about how permissions work in cygwin.

Hi all,

this is a good reason to publish the latest version of the ntsec
documentation. It's part of the developers snapshots but hasn't
yet find it's way to the net documentation. I have attached the
html version of the document.

Please mail questions/suggestions/patches/flames regarding ntsec or
it's documentation to this mailing list.

Have fun,
Corinna
Title: NT security and the ntsec usage

NT security and the ntsec usage

The design goal of the ntsec patch was to get a more UNIX like permission structure based upon the security features of Windows NT. To describe the changes, I will give a short overview of NT security in chapter one.

Chapter two discusses the changes in ntsec related to privileges on processes.

Chapter three shows the basics of UNIX like setting of file permissions.

Chapter four talks about the advanced settings introduced in release 1.1

Chapter five illustrates the permission mapping leak of Windows NT.

Chapter six describes in short the new acl API since release 1.1

The setting of UNIX like object permissions is controlled by the new CYGWIN variable setting (no)ntsec. On NT ntsec is now turned on by default.

NT security

The NT security allows a process to allow or deny access of different kind to `objects'. `Objects' are files, processes, threads, semaphores, etc.

The main data structure of NT security is the `security descriptor' (SD) structure. It explains the permissions, that are granted (or denied) to an object and contains information, that is related to so called `security identifiers' (SID).

A SID is a unique identifier for users, groups and domains. SIDs are comparable to UNIX UIDs and GIDs, but are more complicated because they are unique across networks. Example:

SID of a system `foo':

  S-1-5-21-165875785-1005667432-441284377

SID of a user `johndoe' of the system `foo':

  S-1-5-21-165875785-1005667432-441284377-1023

The above example shows the convention for printing SIDs. The leading `S' should show that it is a SID. The next number is a version number which is always 1. The next number is the so called `top-level authority' that identifies the source that issued the SID.

While each system in a NT network has it's own SID, the situation is modified in NT domains: The SID of the domain controller is the base SID for each domain user. If an NT user has one account as domain user and another account on his local machine, this accounts are under any circumstances DIFFERENT, regardless of the usage of the same user name and password!

SID of a domain `bar':

  S-1-5-21-186985262-1144665072-740312968

SID of a user `johndoe' in the domain `bar':

  S-1-5-21-186985262-1144665072-740312968-1207

The last part of the SID, the so called `relative identifier' (RID), is by default used as UID and/or GID under cygwin. As the name and the above example implies, this id is unique only relative to one system or domain.

Note, that it's possible, that an user has the same RID on two different systems. The resulting SIDs are nevertheless different, so the SIDs are representing different users in an NT network.

There is a big difference between UNIX IDs and NT SIDs, the existence of the so called `well known groups'. For example UNIX has no GID for the group of `all users'. NT has an SID for them, called `Everyone' in the English versions. The SIDs of well-known groups are not unique across an NT network but their meanings are unmistakable. Examples of well-known groups:

everyone                        S-1-1-0
creator/owner                   S-1-3-0
batch process (via `at')        S-1-5-3
authenticated users             S-1-5-11
system                          S-1-5-18

The last important group of SIDs are the `predefined groups'. This groups are used mainly on systems outside of domains to simplify the administration of user permissions. The corresponding SIDs are not unique across the network so they are interpreted only locally:

administrators                  S-1-5-32-544
users                           S-1-5-32-545
guests                          S-1-5-32-546
...

Now, how are permissions given to objects? A process may assign an SD to the object. The SD of an object consists of three parts:

  • the SID of the owner

  • the SID of the group

  • a list of SIDs with their permissions, called `access control list' (ACL)

UNIX is able to create three different permissions, the permissions for the owner, for the group and for the world. In contrast the ACL has a potentially infinite number of members. Every member is a so called `access control element' (ACE). An ACE contains three parts:

  • the type of the ACE

  • permissions, described with a DWORD

  • the SID, for which the above mentioned permissions are set

The two important types of ACEs are the `access allowed ACE' and the `access denied ACE'. The ntsec patch only uses `access allowed ACEs'.

The possible permissions on objects are more complicated than in UNIX. For example, the permission to delete an object is different from the write permission.

With the aforementioned method NT is able to grant or revoke permissions to objects in a far more specific way. But what about cygwin? In a POSIX environment it would be fine to have the security behavior of a POSIX system. The NT security model is MOSTLY able to reproduce the POSIX model. The ntsec patch tries to do this in cygwin.

You ask "Mostly? Why mostly???" Because there's a leak in the NT model. I will describe that in detail in chapter 4.

The creation of explicit object security is a bit complicated, so typically only two simple variations are used:

  • default permissions, computed by the operating system

  • each permission to everyone

For parameters to functions that create or open securable objects another data structure is used, the `security attributes' (SA). This structure contains an SD and a flag, that specifies whether the returned handle to the created or opened object is inherited to child processes or not. This property is not important for the ntsec patch description, so in this document SDs and SAs are more or less identical.

Process privileges

Any process started under control of cygwin has a semaphore attached to it, that is used for signaling purposes. The creation of this semaphore can be found in sigproc.cc, function `getsem'. The first parameter to the function call `CreateSemaphore' is an SA. Without ntsec patch this SA assigns default security to the semaphore. There is a simple disadvantage: Only the owner of the process may send signals to it. Or, in other words, if the owner of the process is not a member of the administrators' group, no administrator may kill the process! This is especially annoying, if processes are started via service manager.

The ntsec patch now assigns an SA to the process control semaphore, that has each permission set for the user of the process, for the administrators' group and for `system', which is a synonym for the operating system itself. The creation of this SA is done by the function `sec_user', that can be found in `shared.cc'. Each member of the administrators' group is now allowed to send signals to any process created in cygwin, regardless of the process owner.

Moreover, each process now has the appropriate security settings, when it is started via `CreateProcess'. You will find this in function `spawn_guts' in module `spawn.cc'. The security settings for starting a process in another user context have to add the sid of the new user, too. In the case of the `CreateProcessAsUser' call, sec_user creates an SA with an additional entry for the sid of the new user.

File permissions

If ntsec is turned on, file permissions are set as in UNIX. An SD is assigned to the file containing the owner and group and ACEs for the owner, the group and `Everyone'.

The complete settings of UNIX like permissions can be found in the file `security.cc'. The two functions `get_nt_attribute' and `set_nt_attribute' are the main code. The reading and writing of the SDs is done by the functions `read_sd' and `write_sd'. `write_sd' uses the function `BackupRead' instead of the simpler function `SetFileSecurity' because the latter is unable to set owners different from the caller.

If you are creating a file `foo' outside of cygwin, you will see something like the following on ls -ln:

If your login is member of the administrators' group:

  rwxrwxrwx 1  544  513  ... foo

if not:

  rwxrwxrwx 1  1000  513  ... foo

Note the user and group IDs. 544 is the UID of the administrators' group. This is a `feature' :-P of WinNT. If one is a member of the administrators' group, every file, that he has created is owned by the administrators' group, instead by him.

The second example shows the UID of the first user, that has been created with NT's the user administration tool. The users and groups are sequentially numbered, starting with 1000. Users and groups are using the same numbering scheme, so a user and a group don't share the same ID.

In both examples the GID 513 is of special interest. This GID is a well known group with different naming in local systems and domains. Outside of domains the group is named 'None' (`Kein' in German, `Aucun' in French, etc.), in domains it is named 'Domain Users'. Unfortunately, the group `None' is never shown in the user admin tool outside of domains! This is very confusing but it seems that this has no negativ influences.

To work correctly the ntsec patch depends on reasoned files /etc/passwd/ and /etc/group. In cygwin release 1.0 the names and the IDs must correspond to the appropriate NT IDs! The IDs used in cygwin are the RID of the NT SID, as mentioned earlier. An SID of e.g. the user `corinna' on my NT workstation:

  S-1-5-21-165875785-1005667432-441284377-1000

Note the last number: It's the RID 1000, the cygwin's UID.

Unfortunately, workstations and servers outside of domains are not able to set primary groups! In these cases, where there is no correlation of users to primary groups, NT returns 513 (None) as primary group, regardless of the membership to existing local groups.

when using mkpasswd -l -g on such systems, you have to change the primary group by hand if `None' as primary group is not what you want (and I'm sure, it's not what you want!)

To get help in creating correct passwd and group files, look at the following examples, that are part of my files. With the exception of my personal user entry, all entries are well known entries. For a better understanding, the names are translated to the equivalents of the English NT version.

Example 2-1. /etc/passwd

everyone:*:0:0:::
system:*:18:18:::
administrator::500:544::/home/root:/bin/bash
guest:*:501:546:::
administrators:*:544:544::/home/root:
corinna::1000:547:Corinna Vinschen:/home/corinna:/bin/tcsh

Example 2-2. /etc/group

everyone::0:
system::18:
none::513:
administrators::544:
users::545:
guests::546:
powerusers::547:

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

  • Because NT assigns them to files as owners, a ls -l is often better readable.

  • Moreover it's possible to assigned them to files as owners with cygwin's chown.

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.

New since Cygwin release 1.1

In Cygwin release 1.1 a new technique of using the /etc/passwd and /etc/group is introduced.

Both files may now contain SIDs of users and groups. They are saved in the last field of pw_gecos in /etc/passwd and in the gr_passwd field in /etc/group.

This has the following advantages:

  • ntsec works better in domain environments.

  • Accounts (users and groups) may get another name in cygwin that their NT account name. The name in /etc/passwd or /etc/group is transparently used by cygwin applications (eg. chown, chmod, ls):

    root::500:513::/home/root:/bin/sh

    instead of

    adminstrator::500:513::/home/root:/bin/sh

    Caution: If you like to use the account as login account via telnet etc. you have to remain the name unchanged or you have to use a special version of login which will be part of the release 1.1 soon.

  • Cygwin UIDs and GIDs are now not necessarily the RID part of the NT SID:

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

    instead of

    root::500:513::/home/root:/bin/sh
  • 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:

    Example 2-3. /etc/passwd:

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

    Example 2-4. /etc/group:

    root:S-1-5-32-544:0:

The tools mkpasswd and mkgroup create the needed entries by default. If you don't want that you can use the options -s or --no-sids. In this case ntsec behaves like the previous version.

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

As aforementioned you are able to use cygwin account names different from the NT account names. If you want to login thru `telnet' or something else you have to use the special login. You may then add another field to pw_gecos which contains the NT user name including it's domain. So you are able to login as each domain user. The syntax is easy: Just add an entry of the form U-ntdomain\ntusername to the pw_gecos field. Note that the SID must still remain the last field in pw_gecos!

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

For a local user just drop the domain:

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

In each case the password of the user is taken from the NT user database, NOT from the passwd file!

The mapping leak

Now its time to point out the leak in the NT permissions. The official documentation explains in short the following:

  • access allow ACEs are accumulated regarding to the group membership of the caller.

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

  • ALl access denied ACEs _should_ precede any access allowed ACE.

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 prefered order.

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.

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

rw-r-xrw-

1st try:

UserAllow:   110
GroupAllow:  101
OthersAllow: 110

Hmm, because of the accumulation of allow rights the user may execute because the group may execute.

2st try:

UserDeny:    001
GroupAllow:  101
OthersAllow: 110

Now the user may read and write but not execute. Better? No! Unfortunately the group may write now because others may write.

3rd try:

UserDeny:    001
GroupDeny:   010
GroupAllow:  001
OthersAllow: 110

Now the group may not write as intended but unfortunately the user may not write anymore, too. 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.

The only chance:

UserDeny:    001
UserAllow:   010
GroupDeny:   010
GroupAllow:  001
OthersAllow: 110

Again: This works for both, NT4 and W2K. Only the GUIs aren't able to deal with that order.

New acl API

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 sys/acl.h as:

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

The a_perm member of the aclent_t type contains only the bits for read, write and execute as in the file mode. If eg. 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.

The new API calls are

acl(2), facl(2)
aclcheck(3),
aclsort(3),
acltomode(3), aclfrommode(3),
acltopbits(3), aclfrompbits(3),
acltotext(3), aclfromtext(3)

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

Online man pages for the aforementioned commands and API calls can be found on eg. http://docs.sun.com

--
Want to unsubscribe from this list?
Send a message to cygwin-unsubscribe@sourceware.cygnus.com

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]