This document proposes a convention to allow Windows NT users to be represented on POSIX-based systems and Unix users to be represented on NT-based and compatible systems, such as Windows NT 3.5, 4.0, 5.0, and Samba. The convention has relevance to POSIX-based Windows NT compatible systems such as Samba, in order to allow such systems to interoperate in a diverse Windows NT Domain environment, even though POSIX systems currently have neither native support for the Windows NT Security model nor support for the concept of remote POSIX users.
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF), its areas, and its working groups. Note that other groups may also distribute working documents as Internet-Drafts.Internet Drafts are draft documents valid for a maximum of six months, and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet- Drafts as reference material or to cite them other than as "work in progress."
The list of current Internet-Drafts can be accessed at
http://www.ietf.org/ietf/lid-abstracts.txtThe list of Internet-Draft Shadow Directories can be accessed at
http://www.ietf.org/shadow.html
The key words "MUST", "MUST NOT", "SHOULD", and "MAY" in this document are to be interpreted as described in RFC 2119.
draft-lkcl-sidtouidmap-00.txt expires end of June 2000.
A SID (for example S-1-5-32-544) uses all but the last 32-bit component of SIDs to represent a Windows NT Domain (for example, S-1-5-32), and the last component (for example 544), known as a Relative Identifer, to represent a user. Two users are therefore known to be in the same Windows NT Domain if all but the last 32-bit component (the RID) of their SIDs are identical.
POSIX may have some SID or SID-equivalent user representation added to it, at some time in the future. For those POSIX systems that do not have SIDs, but where interoperability in a Windows NT Domain environment is still required, this document describes a convention that can be followed to provide a mapping between SIDs and local POSIX uids.
It is not required that sites will follow the POSIX convention of having the same Unix uid to represent the same physical user on multiple POSIX platforms (normally implemented by having a unified Unix password database such as a NIS or NIS+ database, or even by copying an /etc/passwd file over to multiple local POSIX systems). However, if this POSIX convention is not followed, this document does not propose to solve the problems caused to Unix users by not following the aforementioned convention. Coincidentally, however, the proposal does help to present a unified view of those Windows NT-compatible POSIX systems - to Windows NT users only.
The first section in this document defines a SURS table, and outlines the situations where a SURS mapping table is needed. The second section outlines proposals on how to populate a SURS table automatically, describes problems that may be encountered when automatic population of SURS tables fails, and potential solutions and their pitfalls.
The implementation of the mechanism to resolve uids from SIDs and vice- versa is not an authoritative part of this document. However, suggested implementations, the requirements of such implementations, their suitability and the restrictions they impose, are described in the third section.
This document does not specify how to generate SIDs associated with users and groups in a Windows NT-compatible Accounts database (SAM database). This document does not specify how to generate uids associated with users and groups for a POSIX-based, or compatible, password database. This document does not specify or dictate how SIDs are created, or even whether they should be created, from uids, and vice-versa.
The reader should be aware of the security issues regarding the creation of SIDs and uids to represent users and groups, in particular that the deletion of users or groups without clearing out the use of those SIDs or uids on files and directories, and that the creation and use of spurious (randomly created) SIDs or uids for use on files and directories can have serious security consequences. Deleted SIDs or uids should not be reused in case their reuse grants access to unauthorised users of pre-owned files and directories. Spurious SIDs or uids could be unexpectedly generated and then used twice or more, with unpredictable and unacceptable consequences.
Great care should be taken, therefore, to ensure that SIDs and uids remain unique on a network for their foreseeable lifetime, even if SIDs are automatically generated from uids, or vice-versa. The reason for mentioning this at all is that implementors should be aware of security issues as viewed from both NT and POSIX viewpoints, and SURS tables are a critical link between these two worlds.
As has been stated, the purpose of a SURS mapping table is to map from SIDs to uids and vice-versa. Therefore, the table MUST contain one-to-one mappings between SIDs and uids. A SID in a table MUST be unique. A uid in a table MUST also be unique.
In the same way that an /etc/passwd file can be copied across multiple POSIX systems, or a remote Unix password database can be used such as a NIS or NIS+ database, a single SURS mapping table implementation is defined as, but not limited to, one of the following:
Let us therefore examine some scenarios in which an NT client accesses a file on a POSIX system running Samba. Samba is a POSIX-compliant and Windows NT Domain-compliant File, Print and Login Server, which is taken to be the definition of this word within the scope of this document, to represent all such NT-compatible and POSIX-compliant systems.
This section describes a scenario in which a user is a member of a Domain for which a Samba Server is responsible. The user authenticates against the Samba Server and accesses files on it.
It is worth mentioning that because the Samba Server is responsible for user doej, the implementation may be that user doej only actually really exists in a Unix password database. If this is the case, then to create a SID for user doej, the following steps are likely to occur:
This does appear to be slightly superflous, to resolve a POSIX uid to a SID, only to resolve it back to a uid again. If the POSIX-based system is only intended to provide File, Print and Login services only to its own Windows NT Domain users, then these steps are, in fact, completely unnecessary. Under these circumstances, in fact, the concept of a SID can be totally dropped from the equation; no resolution of SIDs is ever required, internally or externally.
However, the Samba Server must still operate under the circumstances where it does not in fact own the SAM database against which the user doej can be authenticated, and from which the user doej's profile (including the SID) can be retrieved. This scenario is described in the next section.
This section describes a scenario in which a user is a member of a remote Domain for which a Samba Server is not responsible. The user authenticates against the Samba Server, which in turn authenticates against the user's remote Domain, and the user then accesses files on the Samba Server.
The remote Domain can be the Domain that the Samba Server is a member of, or it could even be a Trusted Domain Controller with which the Samba Server has a trust relationship established. In either case, the remote Domain could be managed by a Samba Primary Domain Controller, or it could be managed by a Windows NT Primary Domain Controller (it is important to note, however, that this distinction is, for all practical purposes, irrelevant).
It is worth mentioning that under the circumstances where the remote Domain Controller is a Samba Server named bar, the implementation of the Samba Server bar's authentication database may in fact be a Unix-based one. Exactly the same steps therefore have to be carried out as described in the previous section. The optimisation that allows us to cut the SID from the previous picture cannot be applied in this case, as bar cannot dictate what local uid foo uses to represent the user doej, and vice-versa. Even if it turns out that foo and bar use exactly the same uid, the local POSIX uid that foo uses is local to foo, and similarly for bar. The only information that foo and bar are guaranteed to have to uniquely identify the user doej is doej's SID, so that is what foo and bar both have to work from.
In the scenario in which there are two Samba Servers, there are also two POSIX systems (with Samba running on each). Let us suppose that the same physical user, known in the NT world as doej and also known in the Unix world as doej wishes to access files created as the NT user doej in the Unix world as doej. This is a reasonable expectation. For this expectation to be fulfilled (namely, that files created on Samba Servers foo and bar by NT user doej should also be accessible by the Unix user doej using, for example, NFS), then either the same SURS table MUST be used by both Samba Servers foo and bar, OR there should be identical SURS entries in each SURS mapping table used by Samba Servers foo and bar that resolves the SID for NT user DOMAIN1\doej to the Unix uid representing the Unix user doej in both tables, one used by foo and the other used by bar. More on this concept, later.
Note that if the POSIX convention that the physical Unix user doej is represented on both POSIX systems foo and bar as the same Unix uid is NOT followed, then the requirement to map the NT user DOMAIN1\doej to the same Unix uid does most emphatically NOT apply: each such system MUST use different SURS tables. More on this concept, later.
This section describes how to generate Unix file permissions from NT Security-Descriptor file permissions, and vice-versa. Firstly, the two mechanisms are briefly described, followed by a description of how to map between Unix file permissions and NT Security Descriptors. This document is not intended to be an authority on this subject, but is intended to provide sufficient information on how to use SURS tables to map between NT and Unix file / directory permissions.
3.3.1: Windows NT Security Descriptors
Security Descriptors (SDs) describe access rights. SDs can be placed on objects, for example files and directories. An SD contains Access Control Lists (ACLs). An ACL is constructed from Access Control Entries (ACEs). An ACE associates a Security Descriptor (SID) with an access mask (permissions), which is used to grant or deny a user, group or other entity the permissions specified.
For example, an SD can be constructed with an ACL that has two ACEs, that grants Everyone (SID S-1-1) Read-Only access as one ACE and grants Administrators (SID S-1-5-32-544) Full Control. If this SD is associated with a file, the file can be read by everyone but can be modified, read, write or deleted by Administrators.
Traditional Unix file permissions are implemented as a bit field. Three of these bits represent read, write and execute permissions (rwx) for the user. Three more represent the permissions (rwx) for the group associated with the file, and three more bits represent the permissions (rwx) that everyone else is granted. If a bit is set, that permission (read, write or execute) is granted to user, group or "other", respectively. Conversely, if a bit is clear, that permission is denied.
Some Unix systems have Access Control List (ACL) implementations that can be associated with files and directories. The ACL will have Access Control Entries (ACEs), and each ACE will have a Unix user (uid) or Unix group (gid) associated with an access mask (rwx and sometimes other permissions).
3.3.3: SURS mapping for File permissions
A Security Descriptor's Access Control Entries (ACEs) contain SIDs. A Unix file permission set, traditional or ACL-based, contains Unix uids and Unix gids. Each SID must be mapped to a uid or gid and vice-versa, using a SURS mapping table. In this way, Unix file permissions can be converted to an NT Security Descriptor, and vice-versa.
There are a couple of problems that need to be raised. Firstly, the Windows NT access mask is much more verbose (32 bits) than the Unix permission set (3 bits). Therefore, some of these bits need to be either dropped or mapped to multiple bits as required, to give the best representation that is possible (for example, some bits specifically dictate what happens when a file or directory is created, and these bits are only relevant to Security Descriptors that are set on directories). This is beyond the scope of this document.
Secondly, the well-known SID S-1-1 represents the concept in the NT Security Model of "Everyone", and could explicitly be mapped to the Unix "other" concept. If this is not acceptable, then the well-known SID that represents "Authenticated Users" could be considered.
Thirdly, it is possible to create Security Descriptors that may contain more permissions than can be represented, say, in a traditional Unix file permission set. Once mapped, the permissions granted to Unix users should be equal to or less than those granted to NT users, via the NT security descriptor. As the Unix file security model can be considered to be a subset of the NT file security model, it is always possible to map Unix permissions to NT permissions. In the unlikely event where this turns out not to be the case, the permissions granted to Windows NT users should be equal to or less than those granted to Unix users, via the Unix file / directory permissions.
Fourthly, a SID can represent a User, Domain Group, Local Group or a Well-known Group (for example, "Power Users" or "Account Operators"). A SID, and therefore a user or a group, can therefore be granted ownership of a file. There is normally no means to grant ownership of a file to a Unix group (but there are exceptions on some Unix file systems). A solution to this problem is beyond the scope of this document, however implementors may wish to consider creating a Unix user (with no login rights) to represent the group, as well as having a Unix group with the same name, with the created Unix user's primary group being the Unix group of the same name. In this way, ownership of a Unix file can be granted to an NT group by setting the owner to be the Unix user specifically created for this (and no other) purpose.
The POSIX convention to represent the same physical Unix user as the same uid on separate local POSIX systems need not be followed all the time. There are situations where this may not be necessary, possible or desired:
Under each of these circumstances, there may still be a requirement to map these disparate POSIX uids to SIDs. To do this, it is therefore necessary to identify each separate Unix password database and associate one SURS mapping table with each. It is beyond the scope of this document to mandate exactly how this should be done. However, some examples of where the associations are required are listed here:
Where it cannot be determined whether an individual POSIX subsystem follows the POSIX user / rid convention, the SURS table that POSIX system should be using, to map its local POSIX uids to SIDs, is undefined.
It may be difficult to determine whether a Unix user is in /etc/passwd or in the remote NIS database, particularly as the implementation of getpwnam() and getpwuid() (or equivalents) is usually designed to hide this. Under these circumstances, the SURS tables themselves MAY be used to determine which uid is actually in which Unix database (local or remote). If this is required, then the local SURS table MUST be populated with all the required entries in the local /etc/passwd database. The assumption is that if a SID or a uid is resolved in the local SURS table, then it can be deduced that the the uid must exist in the local /etc/passwd database.
When a Unix uid exists in both a local password database (e.g /etc/passwd) and also in a remote password database (e.g a NIS or NIS+ database), which SURS table that POSIX system should be using, to map its local POSIX uids to SIDs, is undefined.
The use of multiple SURS tables has the benefit of presenting a unified view, albeit an NT-based view, of limited and potentially disparate POSIX systems. Each SURS table may contain the same SIDs, however the uids may be different, and most notably, those uids are relevant only to the local POSIX system that references the Unix password database associated with the SURS table or tables it uses.
The administrative task of creating and then updating SURS tables as new users are added to Unix and NT password databases could be an inconsiderate burden, particularly in large networks, and particularly if there are several separate Unix password databases (which includes local /etc/passwd databases), each of which has its own unique SURS table. This section therefore describes some mechanisms that may wish to be considered in order to automate this task. Automatic (algorithmic) generation of SURS tables is covered in other sections of this document, as it is not considered to be automatic population of SURS tables.
If it is unacceptable to reject unknown users that are not in the SURS table, then automatic population must be considered. There are two situations in which the automatic population of a SURS table may occur:
Mechanisms to automatically populate SURS tables may be based on the NT and Unix user names and the Domain name. For example, to create a SID entry when the Unix uid is known, the following steps should be carried out:
To create a Unix uid entry when the SID is known, the following steps should be carried out:
It is inappropriate for this document to specify how to deal with, or to deal with, situations in which the automatic population of a SURS table fails due to getpwnam(), getpwuid(), LsaLookupNames() and LsaLookupSids() (or the equivalents of these four functions) failing to provide useable or any mappings. However, here are some suggestions:
If this approach is taken, these are the ONLY situations in which the one-to-one mapping in SURS tables can be broken, and the automatic SURS table population algorithms described above should take this into account. It should be noted, however, that this may cause considerable problems if not handled carefully.
The reason for maintaining unique entries in SURS tables is so that only a uid or only a SID needs to be maintained inside a Samba Server to represent a user. If the mapping between uids and SIDs is no longer unique, the uid and SID mapping needs to be stored as internal state or as part of the file system inside a Samba Server, to represent a user for the duration of the session that the user has access to the server or the lifetime of the user's files and directories - not just the uid or just the SID.
Therefore, the underlying file system MUST be capable of storing the uid and the SID associated with the file, or a separate database used to associate uid, SID and filename. The association MUST be maintained up-to-date, even though it may be possible for a Unix user to modify ownership of a file. Only implementors with complete control over the file system and operating system should therefore really consider this as a practical approach.
It should be noted that the approach selected MUST not compromise security through either the Unix world or the NT world, and so should be designed carefully, or not implemented at all.
This section describes some SURS mapping systems, and describes the situations in which they are appropriate to use, and the implications of the restrictions that they might impose.
Samba 2.0.x (the Open Source Project, not Samba as defined within the scope of this document) uses an algorithmic mapping from POSIX uid to RID. The SID is assumed always to be the Domain SID of the SAM database that the Samba Server (Samba as defined within the scope of this document) is responsible for.
If the Samba Server is configured as a member of a Domain, it is only possible for that Samba Server to support ACLs that contain Local NT User Accounts that the Samba Server is responsible for. No Domain Users, including those that the Samba Server is a member of, can be supported. No Domain Users can be granted permissions on a Samba Server's files or directories unless there happens to be a Domain User with the same user name as a user in the Samba Server's Local SAM database. The SID for the user that the Samba Server grants permissions to access the file will be different from the SID that the Domain User really is on the remote host, which immediately presents a security problem on who should really be granted access to the file. This becomes even more of a problem if you have multiple Samba 2.0.x Servers as members of the same Domain.
If the Samba Server is configured as a Primary Domain Controller, it is only possible for that Samba Server to support ACLs that contain Domain User Accounts that the Samb Server is responsible for. No Local Users and no Trusted Domain Users can access the Samba Server unless there happens to be a Domain User with the same user name and same password in the Samba Server's Local SAM database. The SID for the user that the Samba Server uses will be different from the SID that the Domain User really is on the remote host.
This algorithm is therefore only appropriate for situations in which there is only one Samba Server, and there are no other Domains on the same network. The only benefit to this approach, therefore, is to allow owners of files to modify permissions on files using the NT security tab, and only for Samba Domain users.
It should also be noted that Aliases in the BUILTIN Domain, such as "Account Operators", "Administrators", "Power Users", "Replicators" etc are also excluded from being able to be mapped to POSIX uids, using this scheme, as the scheme only supports one domain, therefore the Domain SIDs excluded also include the BUILTIN Domain SID, S-1-5-32.
/*
Unix SMB/Netbios implementation.
Version 1.9.
Samba utility functions
Copyright (C) Andrew Tridgell 1992-1999
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*******************************************************************
Converts NT user RID to a UNIX uid.
********************************************************************/
uid_t pdb_user_rid_to_uid(uint32 user_rid)
{
return (uid_t)(((user_rid & (~USER_RID_TYPE))- 1000)/RID_MULTIPLIER);
}
/*******************************************************************
Converts NT user RID to a UNIX gid.
********************************************************************/
gid_t pdb_user_rid_to_gid(uint32 user_rid)
{
return (uid_t)(((user_rid & (~GROUP_RID_TYPE))- 1000)/RID_MULTIPLIER);
}
/*******************************************************************
converts UNIX uid to an NT User RID.
********************************************************************/
uint32 pdb_uid_to_user_rid(uid_t uid)
{
return (((((uint32)uid)*RID_MULTIPLIER) + 1000) | USER_RID_TYPE);
}
/*******************************************************************
converts NT Group RID to a UNIX uid.
********************************************************************/
uint32 pdb_gid_to_group_rid(gid_t gid)
{
return (((((uint32)gid)*RID_MULTIPLIER) + 1000) | GROUP_RID_TYPE);
}
Microsoft has a POSIX subsystem in Windows NT. This subsystem maps SIDs into 32-bit uids. There are a few assumptions and restrictions:
This scheme is suitable for use in multi-Domain environments, however it controls the uid space and therefore cannot be fitted in with existing POSIX environments, which will have pre-existing uids in use on files and directories in that POSIX environment.
typedef uint32 uid_t;
/* can be used to map a SID to a POSIX uid (32 bit) */
uid_t map_sid_to_uid(SID sid)
{
uint32 rid;
uint32 uid_offset = 0x0;
SID dom_sid;
/* split a SID into its last RID and the rest, e.g
S-1-5-21-aaa-bbb-ccc-10001 into
S-1-5-21-aaa-bbb-ccc and 10001 */
split_sid(sid, dom_sid, rid);
/* our own SAM database */
if (dom_sid == my_sam_sid)
{
return (rid & 0xffff);
}
/* the SAM of the Domain we are a member of */
if (is_member_of_domain() && dom_sid == domain_member_sid)
{
uid_offset += 0x10000;
return (rid & 0xffff) + uid_offset;
}
/* all other Trusted Domains */
while ((trusted_domain == gettrustdcsident()) != NULL)
{
uid_offset += 0x10000;
if (dom_sid == trusted_domain)
{
return (rid & 0xffff) + uid_offset;
}
}
return -1; /* oops! */
}
A database can be used to store arbitrary mappings. Algorithmic schemes have the advantage of being fast, and they pre-populate a SURS table automatically. They are, however, inflexible, and cannot cater for all circumstances (for example, adding a new Trusted Domain). They also have the potential disadvantage of not using the entire uid range, which may be severely limited (16-bit) in the first place.
The requirements of a SURS database are that the two fields, uid and SID, MUST both be unique and MUST both be primary keys. The addition of entries to a SURS database MUST be atomic, such that the two fields are unique. Simultaneous read access MUST be possible. Simultaneous write access is an implementation-specific consideration.
Writing to a SURS database is likely to be relatively infrequent, and SHOULD be controlled by an appropriate authority, for security reasons, anyway. The same security considerations that apply to uids and SIDs MUST be extended to SURS tables.
The use of LDAP to store SURS tables fits these requirements, nicely. LDAP implementations are typically optimised to provide frequent, simultaneous read access.
A remote management interface, such as DCE/RPC or ONC/RPC could be considered, particularly as such interfaces tend to work just as well remotely as they do locally. A naming convention could be chosen to select an appropriate SURS table (for example, using the name of the NIS or NIS+ domain, or "local" to represent /etc/passwd).
Fast and frequent access to the SURS tables is not expected. The typical operations that generate SURS lookups are file creation, changes to file ownership, modification of file permissions and user logins. All of these either tend to be infrequent or carried out as part of user interaction. Typical access to a SURS table should therefore fall into a range of the order of milliseconds.
If high-speed access to the SURS tables is required, then a shared memory or other cached copy of the SURS table should be considered. Entries in the table are permanently-lived (at least, as long-lived as the uid and SID entries in them) so this is a viable consideration. Any entries that are not in the cache can be obtained from the appropriate SURS table and added to the cache. The cache MUST be treated the same as SURS tables themselves, i.e. entries in one cache MUST NOT be confused with entries in, or carried over to, another cache.
When a Unix password database is updated (new entries added), the SURS tables associated with the POSIX systems that use that password database will also need to be updated.
A combined approach could be considered by running tools or scripts that completely regenerate the entire SURS table associated with the updated password database, including downloading the newly generated SURS table to all POSIX systems that use the updated password database.
DEC Pathworks, which runs on the VMS Operating System, also uses SIDs. It is therefore necessary to solve the same problems that the use of SURS tables solves, and the script approach is one that is being used at some sites.
Luke Kenneth Casson Leighton
Internet Security Systems,
300 Embassy Row,
6600 Peachtree-Dunwoody Rd. N.E.
Atlanta GA 30328.
U.S.
Email: lkcl@samba.org
draft-lkcl-sidtouidmap-00.txt expires end of June 2000.