Security Identifier / User Identifier Resolution System

Luke Kenneth Casson Leighton <lkcl@samba.org>

24th December 1999

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.

1: draft-lkcl-sidtouidmap-00.txt

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

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

2: Introduction

POSIX systems currently only support Local Unix Users, represented by a User Identifier (uid). Windows NT supports Local and Remote NT Users, represented by a Security Identifer (SID). In order for POSIX systems to represent remote users on other POSIX systems, a convention exists where the same physical Unix user uses the same Local Unix uid on multiple POSIX systems. Windows NT does not suffer from this problem, as SIDs are constructed from up to eight 32-bit components, which is more than sufficient to allow globally unique identification of users, even across remote hosts.

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.

3: Definition and uses of a SURS Mapping Table

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:

  • Multiple copies of the same identical table, on multiple POSIX systems. The means by which the table is copied to those systems, and kept up-to-date, is an implementation-specific issue.
  • A single actual table, accessed remotely by multiple POSIX systems.
  • Identical automatic SURS table population algorithms in use on multiple POSIX systems, the use of which MUST result in identical entries in the SURS table used by each POSIX system. Each table need not be identical, just the entries in each table.
  • The issues that dictate which SURS table (or tables) a single POSIX system or a group of POSIX systems must use are discussed later in this document.

    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.

    3.1: Windows NT user as a member of a Samba Domain

    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.

  • A user doej of a Samba Server Domain accesses a Samba Server, foo. This results in an authentication request that contains the user name doej, and password credentials.
  • The Samba Server checks that doej's password credentials are correct. Assuming that the credentials are correct, the Samba Server retrieves a profile for user doej from its NT-equivalent password database, which includes the SID for user doej. The Samba Server is responsible for user doej, therefore it can create this SID in any method it sees fit to choose.
  • The Samba Server looks up doej's SID in the SURS mapping table. Assuming that there is an entry for doej's SID, a POSIX uid will be retrieved. It is also assumed that this local POSIX uid is valid (and by definition only valid) on the local POSIX system that the Samba Server is running on.
  • The POSIX uid is used internally in the Samba Server should the user doej be allowed to create or access files on that local Samba Server.
  • 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:

  • It is assumed (but not required) that the NT user doej has the same name as a Unix user, doej, and that a Unix user doej exists in a Unix password database that the Samba Server can access.
  • The Unix user doej must be resolved to a POSIX uid, for example by using the standard POSIX function getpwuid() (or equivalent).
  • The uid must be resolved in a SURS table to a SID.
  • 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.

    3.2: Windows NT user as a member of a Domain

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

  • A user doej from DOMAIN1 accesses a Samba Server, foo. This results in an authentication request that contains the user name doej and the Domain name DOMAIN1, and password credentials.
  • The Samba Server finds the PDC for DOMAIN1 and asks the PDC if the user DOMAIN1\doej's password credentials are correct. The PDC for DOMAIN1 responds yes or no. Assuming that the PDC for DOMAIN1 responds with a yes, the Samba Server trusts this response. The PDC also returns a user profile for doej, which includes doej's SID.
  • The Samba Server looks up doej's SID in the SURS mapping table. Assuming that there is an entry for doej's SID, a POSIX uid will be retrieved. It is also assumed that this local POSIX uid is valid (and by definition only valid) on the local POSIX system that the Samba Server is running on.
  • The POSIX uid is used internally in the Samba Server should the user DOMAIN1\doej be allowed to create or access files on that local Samba Server.
  • 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.

    3.3: NT Security Descriptor File permissions and Unix File permissions

    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.

    3.3.2: Unix File permissions

    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.

    4: Use of multiple SURS tables

    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:

  • The actual number of Unix users on a network may exceed the number of users that can be represented uniquely on the local POSIX systems being used (particularly if the uid is only stored in 16 bits).
  • It may be desirable, for organisational reasons, to have separate password databases on the same network from which local POSIX systems obtain their uids, thereby separating groups of POSIX systems from each other. Any users that need to access both groups will have to have different Unix user names (one in each password database), or maybe the same user name and the same password, but potentially a different uid in each password database.
  • For security reasons and to make data recovery and administration easier, some Unix accounts such as root may be stored in a local password database (for example, /etc/passwd), and any other accounts may be stored in a remote password database (for example, NIS or NIS+). The implementation of getpwnam() and getpwuid() (or equivalents) will merge these two databases seamlessly, which may cause problems that are outlined later.
  • Totally separate, unrelated Unix networks use the same uids world-wide, many times over. This may not seem like it has any relevance at all, until two corporations that use completely different password databases with totally different Unix uid to username mappings merge into one company, and users in one corporation are expected to be able to access files on the other corporation's Unix file servers.
  • 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:

  • For a network in which a group of POSIX systems use identical copies of or the same password database, one SURS table MUST be used per group of POSIX systems.
  • For each POSIX system that has a different local password database from all other POSIX systems (e.g. /etc/passwd for security and administrative reasons) and also a remote password database (e.g a NIS or NIS+ database), a separate SURS table MUST be associated with each. In the unique situation where every single POSIX system that uses the same remote password database also has identical entries in each and every local password database, only one SURS table is needed for the entire group of POSIX systems, associated with the "hybrid" password database used by that group.
  • For a network where the POSIX convention of having the same physical Unix user represented as the same uid number on multiple local POSIX systems is NOT followed, each such POSIX system on that network MUST have a separate SURS table.
  • 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.

    5: Automatic SURS table population

    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:

  • A Unix user accesses, creates or is granted ownership of a file on a POSIX system, and it is expected that a Windows NT user may also access the same file at a later date. It is not normally expected that Unix file security be validated against a Windows NT Security system, however this case is mentioned here for completeness, and in case there existed, in the future, an nss_ntdom module that could be installed on POSIX systems. The nss_ntdom module would need to automatically populate a SURS table for each uid that was discovered not to be currently mapped to a known SID.
  • An NT user accesses, creates, or takes ownership of, a file or directory for the first time on a local POSIX system, and there is no known uid in the SURS table for the NT user's SID.
  • 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:

  • From the Unix uid (e.g 501), resolve the Unix name (doej) using the getpwuid() (or equivalent) function of the local POSIX system.
  • Using a suitable mapping function (beyond the scope of this document), map the Unix name doej to a Windows NT Domain name (DOMAIN1) and a Windows NT User name (doej) in that domain.
  • Contact the Domain Controller for the selected Domain (DOMAIN1) and resolve the SID for the NT user name (DOMAIN1\doej) using the Microsoft MSDN function LsaLookupNames (or its over-the-wire equivalent).
  • Check that the SID (for example, S-1-5-21-domain1-100501) does not already have a SURS mapping in the SURS table. If it does, an alternative mapping, or a more appropriate mapping function, should be considered.
  • Assuming that the SID is already unique in the SURS table, add an entry that associates the SID (S-1-5-21-domain1-100501) with the uid (501).
  • To create a Unix uid entry when the SID is known, the following steps should be carried out:

  • From the NT SID (e.g S-1-5-21-domain1-100501), resolve the NT Domain name and NT User name using the Microsoft MSDN function LsaLookupSids (or its over-the-wire equivalent).
  • Using a suitable mapping function (beyond the scope of this document), map the NT Domain (DOMAIN1) and NT User name (doej) to a Unix user name (doej) that will be appropriate and relevant to the local POSIX system.
  • Using the local POSIX system's getpwnam() (or equivalent) function, resolve a uid (501) from the Unix name (doej). If this cannot be done successfully, then a better mapping algorithm should be chosen or an alternative mapping used.
  • Check that the uid (for example, 501), does not already have a SURS mapping in the SURS table. If it does, an alternative mapping, or a more appropriate mapping algorithm, should be considered.
  • Assuming that the uid is already unique in the SURS table, add an entry that associates the uid (501) with the SID (S-1-5-21-domain1-100501).
  • 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:

  • Where it is not possible to map an NT User to a Unix uid, a special Unix uid MAY be used, such as one that maps to a guest Unix account, particularly one that has no login rights on the local POSIX system.
  • Where it is not possible to map a Unix uid to an NT user, a special NT user name MAY be used, such as one that maps to a special, local NT account such as the Guest user or a user that is specifically added to the Guests or Domain Guests group, particularly a user account that is Disabled (and therefore cannot be used to log in).
  • 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.

    6: SURS Mapping Implementations

    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.

    6.1: Samba 2.0.6 Algorithmic Local Mapping

    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);
    } 
    

    6.2: Microsoft POSIX subsystem Algorithmic Mapping

    Microsoft has a POSIX subsystem in Windows NT. This subsystem maps SIDs into 32-bit uids. There are a few assumptions and restrictions:

  • No RID of any Domain SID is expected to exceed 65536. If there are more than 65536 users and groups in any Domain, this scheme will fail.
  • Microsoft controls the uid space, and does not provide any Unix authorisation mechanisms such as /etc/passwd or NIS. The control over the uid space is based on algorithmically generating uids from RIDs. It is therefore not possible to follow the POSIX uid / user convention normally applied to have a Microsoft POSIX system interact with other non-Microsoft POSIX systems with respect to uids except by forcing non-Microsoft POSIX systems to use the uids created by the Microsoft mapping algorithm.
  • The uids generated are 32-bits long. Therefore, any non-Microsoft POSIX system that only supports 16-bit uids cannot follow the POSIX uid / user convention to share uid space.
  • Unknown Domain SIDs cannot be mapped to uids, and vice-versa.
  • 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! */
    }
    

    6.3: Mapping using a Database

    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.

    7: Mapping using Algorithms implemented in tools or scripts

    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.

    8: Credits

    CrosStor Ltd
    for intense discussions and insisting that NIS databases be involved.

    Jeremy Allison, Samba Team
    for even more intense discussions that brought up the issue of the local POSIX uid convention, without which this document would be easy to misunderstand, both its intent and its content.

    Nicolas Williams
    for taking time to listen and provide feedback.

    9: Author's Address

    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.