proposal.txt Experimental Authentication and Authorization Token Management Extensions in the FreeBSD Kernel Robert Watson Introduction FreeBSD, a derivative of the 4.4BSD-Lite research operating system developed at the University of California at Berkeley, is used in a variety of networked and stand-alone computing environments. FreeBSD makes use of a simple yet flexible user-based authorization model following the UNIX example. However, this model is not scalable across large computing infrastructures with multiple administrative domains, and the model does not interact well with the differing paradigms supported by a variety of network operating systems. While FreeBSD does support user-land extensions to make use of the Kerberos distributed authentication environment, this support is not closely tied into the operating system, and is not cleanly supported. Similarly, it does not interact well with a variety of cross-platform distributed file systems such as AFS, Coda, and CIFS which make use of distributed authentication environments. This document proposes a set of extensions to the FreeBSD kernel providing both authentication and authorization "tokens", allowing greater flexibility in supporting a variety of authentication and authorization models. Tokens are the kernel's representation of a fragment of data relating to the capabilities and keying material associated with a set of processes, or Process Authentication Group (PAG). It is hoped that this architecture is sufficiently flexible to provide easy support for the various strains of Kerberos, as well as distributed file systems making use of cryptographic tokens. Additionally, the architecture should provide a context for maintaining IPsec keying material associated with processes and sessions. The authorization token support allows for a more flexible UNIX security policy by providing an alternative to the set-user-id and set-group-id binary approach currently employed, reducing the risks associated with this often all-or-nothing approach to protection domain extension. Architecture PAGs Under the traditional BSD model, each process has a credential structure made up of a numeric user-id, as well as an array (often up to 16 entries permitted) of numeric group-ids associated with it. To support the crossing of protection boundaries, additional numeric user-ids were added to the structure for special-case situations (such as setuid programs). With the token support, the granularity of association is a Process Authentication Group (PAG) -- a group of processes with the same authorization or authentication properties. In the real world, a PAG might be associated with a user session over which there is one set of network authentication tokens in use, and over which a set of pipes and UNIX files might be shared. Tokens Each PAG is associated with a set of "tokens". A token is represented in the kernel by a structure with the following members: Unique token identifier Name Realm Rights Type (major, minor, minorminor) Public and Private opaque data fields Creation time Expiration time Creator identifier The unique token identifier is represented using a 64-bit value, and must be unique over a kernel run session (that is, across a single boot). The rights field describes the set of actions that a process may perform on the token, as well as defining its behavior over a variety of token-related operations in the kernel. The expiration time specifies a distinct time after which the kernel may garbage collect the structure, and must prevent access to or use of the token for any authentication or authorization activities (XXXXX -- this is not necessarily useful, as garbage collecting (GC) is expensive; is it desirable to GC old tokens? The EXPIRE right may address this). The creator identity indicates the source of the token (on the granularity of either the kernel, or a specific set of hard-coded authorization token types) so that processes and the kernel may evaluate the reliability of the token's contents. The remainder of the fields are specific to the type of token, where the type may be determined through inspection of the numeric major, minor, and minorminor type fields in the token. For example, when the major field is set to 1, this indicates a capability allowing certain actions on the local system (if the creator field is set appropriately). A major type of 2 is used to indicate that the token contains a Kerberos 4 ticket. The name and realm are strings providing necessary supporting information to use or identify the token -- in the context of Kerberos 4, these store the Kerberos principal and Kerberos realm of the ticket. The public and private data fields also having meaning specific to the token type. For Kerberos tickets, these fields contain the encrypted and clear-text ticket information. Tokens might also be used to store public/private key information. The name and realm might be used to describe the source of the key and associated principal information; the public and private portions might contain the keys of the same name. Where fields are inappropriate in the context of a particular type of token, they may be null or 0-length. Reflection Tokens Situations exist where a process in a PAG may want to "prove" that it has a token with a particular name, type, and creator, but not provide access to the token itself (that is, not delegate the use of the token). In this case, the kernel provides a "reflection" service. This is implemented through the creation of a new token where the type fields are the negative of their normal values. The data fields are rendered empty, but name, realm, expiration and creation fields take on the same values as the original. The unique identifier for the token will be different from the original. The rights field will be modified such that the reflection is unmodifiable, but may be deleted (even if the original could not be). (XXXXX -- limits transitivity? inheritance? transferability?) Token-related System and Library Calls The token structures are maintained entirely by the kernel token-managing code, but may be accessed by both user processes in a PAG referencing them, and by other portions of the kernel. Additionally, tokens may sometimes by referenced by processes not in their PAGs, but with authorization tokens allowing them to inspect specific types of tokens belonging to other processes, when interacting with those processes. The rights of a token determine what kinds of calls may succeed on the token. A single system call is used by the token loadable kernel module; a set of calls is multiplexed into the system call to provide a rich token-manipulation functionality. Currently, the library calls provide only a wrapping service (that is, cleaning up the interface). However, a more extensive degree of functionality could be provided in the library interface for handling sets of tokens, as well as evaluating reliability of tokens. t_newpag() This call creates a new PAG, removes the current process from its existing PAG, and adds it to the new PAG. Additionally, any tokens that are marked with the "inheritable" right automatically have references to them added in the new PAG. All rights on the token remain the same, as the rights are associated with the token itself, not with the reference to it. This call might fail if a resource limit is exceeded. t_getpag() This call returns the unique identifier associated with the PAG of the current process. t_createtoken() Create a new token based on the arguments passed. Not all fields of a token may be set through this call (for example, the creator field, and certain combinations of types that only the kernel may create). A reference to the token is added in the current processes PAG, and the unique token identifier of the new token returned. This call might fail if resource limits are exceeded. t_readtoken() Return a copy of the fields of the specified token at the time of the call. Only fields permitted to by read by the rights of the token are copied (others will be rendered null or 0-length). Rights-related modifications of the returned token may be determined by inspecting the rights on the tokens. The ability to read a token does not provide the ability to duplicate, reproduce, or modify the token, as not all fields may be read, or set. t_modifytoken() Modifies specified fields of the token (if the rights permit) by replacing current values with the argument's values. If a token is modified, it's creator field will be reset to that of the current entity, as the token may no longer reflect the creator's intent. This call will only succeed on tokens in the current process's PAG, if the MODIFY right is set on the token, and if the final version of the token is a type of token the process could have created (that is, with appropriate types, etc). t_reflecttoken() Create a new "reflection token" of the token described by the argument, and return its unique identifier. Reflection tokens (described above) provide "proof" that a PAG has a token; however, they may not be used for anything beyond this, and have cleared data fields to prevent leaks of keys. Reflections may not be made of reflections, and a reflection is not modifiable. The DELETE right will be set on all reflections, however. Reflections may be made of tokens without the READ right, as the reflection will not contain the data fields of the original token. t_deletetoken() With the appropriate rights set, a process may remove the token from its PAG. This may not result in the removal of the token from the system as a whole, as references may exist in other PAGs. t_findtoken() This call searches the current processes PAG for a token matching the description passed in the form of a token structure. Any set of fields may be matched against; the caller may also provide a minimum tokenid to return, so as to implement a search of the token space (suitable for use in listing all tokens the process has access to, for example). The fields to match are specified via a field bitmask argument to the syscall. This call might be useful in retrieving specific types of tokens, possibly with specific names. The unique token identifier for the resulting token is returned; a call to t_readtoken() may then be used to retrieve the token if desired. Other calls t_setdebug() This may be used to set the debug level of the token module. Various events will be reported via the kernel's printf() routine on the console (and to syslog). The level passed as an argument represents the maximum level of debug messages to be printed. Some sample levels include: 0 Print no debug messages 1 Print interesting (serious error, event) debug messages 2 Print less interesting debug messages (warnings) 5 Print lots of debug messages (calls to functions, etc) Only the super-user may modify the debug level. t_prettyprint() This is a library call to print out a token's contents. Other Token Behavior Transferring of Tokens (Not Yet Implemented) It is desirable that some tokens have be "transferable" between PAGs not hierarchical children of one another (that is, transferable outside of the scope of the newpag() call). It is likely that the implementation of this feature would be done via UNIX domain sockets, in the same manner as file descriptor passing, although this is not yet entirely clear. A transfered token would actually be a copy of the original token with almost identical properties. Tokens would only be transferable if their rights allowed it -- that is, if they had either the "Transferable" right, or the "TransferableOnce" right. Upon a transfer, the "TransferableOnce" right would be disabled in the transferred copy. As the transferred tokens are only copies, later changes to the tokens are independent of one-another. Additionally, the DELETE right will be enabled on all transferred copies of a token, regardless of the original rights. The unique identifier for the token will be different between the two copies. Transferring would only be allowed where both the sender and the recipient authorize it. Rights A number of rights are associated with tokens; these rights are enforced by the kernel as necessary. READ The public and private data fields of the token may be read by a user process in a PAG that references this token. All other fields of a token are readable regardless of this value MODIFY Fields of the token may be modified, including the name, realm, public and private data, and expiration time. Additionally, the rights field may be modified. Without the MODIFY right, none of the fields in the token may be changed by a user process. DELETE If the DELETE right is set, a user process in a PAG with a reference to the token may delete the reference from its PAG (although the token itself will not be deleted until all references are removed, or the expiration has passed and the EXPIRE right was set). INHERIT If the INHERIT right is set, a reference to the token will be available after a call to t_newpag(). EXPIRE The kernel will enforce the expiration of a token only if the EXPIRE right is set. In this manner, tokens may be retained beyond their expiration field value. This may be useful in situations where network time is not well synchronized, and a user token may represent a network authentication ticket, and the expiration field is copied. (Not yet implemented) TRANSFERABLE If the TRANSFERABLE right is set, this token may be transfered to another PAG via the transfer facility described above. TRANSFERABLEONCE If the TRANSFERABLEONCE right is set, the token may be transfered, but the right will be turned off in the transferred copy. Combined with disabling the MODIFY right, TRANSFERABLEONCE can be used to limit the scope of tokens provided by a token managing daemon. Local Privilege Tokens (Not Yet Implemented) To provide a replacement for the existing authorization model used in BSD, the major type 1 is reserved for local privilege tokens. Local privilege tokens will be observed by the kernel (and other service providers) only when the creator field is set appropriately. The following local privilege token minor types are defined: TOKEN_LPRIV_TOKEND Possession of this token authorizes the creation of tokens with a creator id of TOKEND. TOKEN_LPRIV_UID The minorminor field contains a historic UNIX UID, and may be used to emulate historic authorization behavior. TOKEN_LPRIV_GID The minorminor field contains a historic UNIX gid... TOKEN_LPRIV_UDPBIND Processes with this token in their PAG may bind the UDP port listed in minorminor. (0 indicates any port) TOKEN_LPRIV_TCPBIND Processes with this token in their PAG may bind the TCP port listed in minorminor. (0 indicates any port) TOKEN_LPRIV_KILL Processes with this token in their PAG may deliver the signal number listed in minorminor to any process. (0 indicates any signal) Other local privilege tokens might be defined and implemented within the access control portions of the kernel, and in other locations. TokenD The TOKEND creator identity is intended for authorized token management daemons. That is, the TokenD process would run in a PAG with the TOKEN_LPRIV_TOKEND token present, and would create tokens with this in the creator field. With an appropriate sysctl set at boot time, the kernel would accept tokens with this creator field as well as the KERNEL creator field value for service authorization. The token daemon might transfer tokens to other PAGs when appropriate authentication is provided to the daemon (via a transfered token, data provided on a pipe, a reflected token, etc). In this manner, a policy engine could be implemented in user space for the distribution of tokens providing local privilege. While this would not be needed for Kerberos tokens (which any user process could create, as they can be authenticated via a third party), a user process could present system administration Kerberos tickets in a token to retrieve a local administrative token allowing it to reboot the machine. In this context, the READ/MODIFY/TRANSFERABLE/TRANSFERABLEONCE rights provide protection of the tokens provided with the TokenD identity as creator. Privileged Token Access In AFS and Coda, the majority of the file retrieval and network services exist in a user-land cache manager (Venus). As AFS and Coda tokens are used to set up encrypted RPC sessions with the file servers, the daemon requires access to these tokens during the user's session. Additionally, the kernel portion of the file systems must somehow associate requests for file access with the users session. Kernel Tokens clearly provide some of the services needed to implement this cleanly (current, a special device is used to move tokens between the user-land token management code, the kernel, and the cache manager). However, it is not clear how best the cache manager should retrieve references to the tokens it requires. The kernel might provide PAG information along with requests (instead of the current UID information it passes) to the cache manager. The cache manager might be given the ability (via a local Privileged Token) to read tokens not in its own PAG. Such a token would be kept in the PAG of the cache manager, and might be provided by the token daemon. There exist a number of other possible avenues by which the tokens might be shared, including use of the transfer facility. Further exploration of the issue is required. Conclusion Kernel tokens provide a more general authentication and authorization mechanism in a UNIX-style operating environment, and may prove more flexible when distributed authentication systems are merged into the existing UNIX authorization scheme. The current implementation provides only a subset of the desired features of a kernel token managing mechanism. It is also not designed for efficiency; rather, a proof-of-concept. For use in a real-world environment, serious performance issues would need to be considered, as well as memory-footprint, and closer integration with the existing process structure. The local token capability behavior might best be implemented differently internally (such as a bitmask of capabilities in the process structure), and only be exposed via a token interface, for example. Also, as token retrieval is current an expensive operation, it might be desirable to cache frequently used information in the current credential structure, or provide easy access to specific tokens that kernel subsystems might be interested in. These issues may be best explored through experimentation in potential uses of such a system. Please see the attached NOTES file for a description of the syscalls in detail, sample programs, and suggestions for future improvement of the implementation. $Id: proposal.txt,v 1.6 1998/06/26 18:15:39 robert Exp $