To quote Satya's paper: "The fundamental question is: Can agent X
perform operation Y on object Z". The discussion here breaks up in
- A protection database is used to group principals
conveniently. This goes beyond Unix users and groups in that
transtive group membership is taken into account
- Access Control Lists are attached to directory vnodes. Access
Control lists allow much finer granularity of access principally
through two mechanisms:
- Access for an arbitrary number of principals can be specified,
not just for "owner", "group", "others"
- Negative rights can be assigned which override positive ones
In more detail the structure of these two components are held in:
Note that transitive Membership and exclusion of membership relations
among members and groups can be defined. Satya's papers explains
several importance advantages and possibilities for using the system
based on this scheme.
- the protection database is has entries which are users or
groups. The attributes of users and groups are:
At the moment the precomputed CPS and access lists are not used.
- users, and groups. Groups and users are identified with 32 bit
integers, positive for users, negative for groups. These integers
should not be reused.
- Users have a list of groups to which they belong and which
they own. Groups have a list of groups to which they belong and of
users and groups belonging to the group.
- A precomputed Current Protection Subdomain, the CPS for each
user and group. Informally the CPS of a user or group X is the set of
groups of which X is a member, directly or indirectly, including X
- An access list which defines which groups and users may
and may not change the entry in the protection database.
- Some exceptional groups and users are defined, such as
System:Administrators and System:Anyuser and user Anonymous.
- The counter part are the Access Control Lists or
ACLs, stored right behind the shared part of large Vnodes in
server RVM. ACL's have attributes pairs of
- a right or negative right; such rights are read, write,
lookup, insert, delete, administer.
- a group or user to which the right applies.
The total rights are the union of the rights of members of the CPS of
the user. The negative rights are also a union and overide positive
rights in case of conflict.
When a client first contacts a server the RPC routine
srvproc2.cc) is called. This calls
clientproc.cc). BuildClient gets the ViceId
from the username if necessary. A ClientEntry client is malloced and a
the routine SetUsername is called to fill in more details. Finally
AL_GetInternalCPS is called which builds up the CPS for the client
AL_GetInternalCPS gets to the guts of the protection database file. It
mallocs the length needed to encode the CPS and hangs it off the
The algorithm to check permissions is short and sweet and explained in
Satya's paper. The detailed checks are in libal but it is instructive
to step momentarily to the server code. Before performing an
operation the server will do a Check_XX_Semantics routine which among
other things checks permissions:
- It gets a pointer to the ACL for the large Vnode.
- It enters the GetRights routine which does some complicated
checking of rights for anonymous users before calling AL_CheckRights
using the CPS attached to the client and the ACL.
This system is ready for a rewrite, although the ideas are fine. Let's
step through some of the ingredients.
The .pdb .pcf mystery
When setting up a Coda server the system administrator can combine
existing Unix password files and groups files into a .pdb file using
the program pwd2pdb. This is merely a convenient tool to quickly get
a usable .pdb file the structure of which has been described above.
A perl script could do this equally well and might easily do a
precomputation of the CPS. The .pdb file is a text file which has a
very useful comment at the top describing it's structure:
# VICE protection database #
# Lines such as these are comments. Comments and whitespace are ignored.
# This file consists of user entries and group entries in no particular order.
# An empty entry indicates the end.
# A user entry has the form:
# UserName UserId
# "Is a group I directly belong to"_List
# "Is a group in my CPS"_List
# "Is a group owned by me"_List
# Access List
# A group entry has the form:
# GroupName GroupId OwnerId
# "Is a group I directly belong to"_List
# "Is a group in my CPS"_List
# "Is a user or group who is a direct member of me"_List
# Access List
# A simple list has the form ( i1 i2 i3 ..... )
# An access list has two tuple lists:
# one for positive and the other for negative rights:
# (+ (i1 r1) (i2 r2) ...)
# (- (i1 r1) (i2 r2) ...)
The program pcfgen is much more obscure, yet does something
elementary: it creates a file vice.pcf containing 5 arrays:
The offset of a user entry in the pdb file
The offset of a group entry in the pdb file
An array of concatenated, null terminated strings of
usernames and groupnames. The names are sorted alphabetically.
The sorted entry number of uid i
The ofset of the i-th entry in LitPool
Contains in spot i the sorted entry number of group with
gid i in the LitPool
The offset of entry i in the LitPool
The AL_Initialize routine creates these arrays in VM for the
server to access them. Finally the AL_GetInternalCPS builds a CPS
by parsing the .pdb file at the offset given by the array entries,
using a lex parser for pdb files. Transitive group membership and
unexplained excluded entries from groups are not implemented.
Much of the AL implementation is now out of date or was incomplete to
start with. The following points give a possible solution to this
Local and Coda user id's.
It is not desirable that a userid should be the same on every client,
particularly in the case of access to multiple coda clusters. Venus
should have access to a translation table on the client (probably
owned by root on the client) which translates local id's to remote
Coda ids for various cells.
The pdb and pcf database
This database describes a wonderful structure but the implementation
- It is undesirable to have to keep vice.pdb, vice.pcf and the
password database auth2.pwd in sync. The utilities to move databases
synchrnously indicate the history of these problems on busy servers.
- There is no way a client can modify the pdb. All
operations only modify the auth2.pwd file.
- The database is huge and large index tables and string table
might needlessly be held in the Coda server's vm.
- The system is extremely difficult to understand (particularly
if one hasn't read this document or Satya's paper).
We propose therefore to make a pts server in one or two forms:
- The protection database could very conveniently be held in
an LDAP database. These database servers could run on every fileserver
and replicas can be held in sync using slurpd, the LDAP replication
tool. This is similar but more sophisticated than the replication of
kerberos databases between mastern and slave KDC's.
- Updates go to the master LDAP server, like in Kerberos.
- The same LDAP database could serve GetVolInfo requests. I will
come back to this.
- LDAP is already kerberized and has tight access control.
- The list of routines to change is short and sweet:
- some others
- The list of things we can remove from AL is long and spicy:
- the pdb stuff can go: it will be easy to create entries in
the ldap pdb
- the pcf stuff and the internal versions of the seek arrays
can go. This eliminates major hassles with lex and flex we have had.
- routines keeping cached pdb and pcf informatin up to date can
- A user of pts should be authenticated.
- CPS's attached to ClientEntry's should be refetched when
updated (currently nothing is done when the
.pdb file is modified to modify existing CPS's in client entry's
. (How does ubiq do this?). Possibilities:
- Best: the ldap server when notified
by slurpd of an update would prod the fileserver to re-fetch the
CPS. This might not be possible without modifying ldapd.
- The pts client program gets all servers from LDAP and places
an RPC2 with all of them to drop the cached CPS structures which it
has just modified.
- A LDAP server should contain a table of userid's for which the
pdb has been modified. Every fileserver should periodically read this
list and refetch the client CPS's.
- Client programs to modify entries could be short and sweet,
with one exception: they should recompute the precomputed CPS in
- The implementation of a fully features PTS server with a nice
client program is very simple: the ldap server has all the basic
Alternatively, we stick with the distribution of pdb databases through
Update. The following modifications seems desirable:
- We need a pts type server to modify the pdb database. This has
to run on the SCM and should change the auth2.pwd and pdb databases in
- The database format for the pdb and pcf file is really not
great and should be replaced by a collection of (g)dbm database
files. This would also work for the volume databases.
The disadvantage of the second approach is that we effectively need to
construct a networked database server for pdb files, while ldap is
such a tool. The advantage is that we will control the code entirely
rather than rely on 3rd parties construction.