                                                                  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 $
