AFS-3 Programmer’s Reference: Protection Server Interface

Edward R. Zayas

Transarc Corporation

Version 1.0 of 27 August 1991 14:28 \begin{matrix}c \\ ◯ \end{matrix}Copyright 1991 Transarc Corporation

All Rights Reserved FS-00-D163

AFS-3 PtServer Spec

Contents

1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.2 Scope . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.3 Document Layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.4 Related Documents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

2 Protection Server Architecture . . . . . . . . . . . . . . . . . . . . . . . . 4

2.1 Building Blocks: Users and Groups . . . . . . . . . . . . . . . . . . . . . 4 2.1.1 Introduction and References . . . . . . . . . . . . . . . . . . . . . 4 2.1.2 User and Group Names . . . . . . . . . . . . . . . . . . . . . . . 5 2.1.3 Built-In Groups . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 2.1.4 Current Protection Subdomain (CPS) . . . . . . . . . . . . . . . 7 2.1.5 Foreign Users . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 2.1.6 Superset and Subset Instances . . . . . . . . . . . . . . . . . . . 8

2.2 The Protection Database . . . . . . . . . . . . . . . . . . . . . . . . . . 9 2.2.1 Layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 2.2.2 PDB Entry Privacy Bits . . . . . . . . . . . . . . . . . . . . . . . 10 2.2.3 Database Replication . . . . . . . . . . . . . . . . . . . . . . . . 11

2.3 The ptserver Process . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 2.3.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 2.3.2 Command Line Switches . . . . . . . . . . . . . . . . . . . . . . 12 2.3.3 Threading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

3 Protection Server Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 3.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 3.2 Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

3.2.1 Interface Function Opcodes . . . . . . . . . . . . . . . . . . . . . 15 3.2.2 Size and Configuration Quantities . . . . . . . . . . . . . . . . . 15 3.2.3 Mask Bits for PR SetFieldsEntry() . . . . . . . . . . . . . . . . . 16 3.2.4 Reserved IDs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 3.2.5 Bits for struct prentry flags Field . . . . . . . . . . . . . . . 17 3.2.6 Privacy Bits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

Table of Contents  i  August 28, 1991 12:16

3.2.7 Miscellaneous . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 3.3 Structures and Typedefs . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

3.3.1 struct prheader . . . . . . . . . . . . . . . . . . . . . . . . . . 20 3.3.2 struct prentry . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 3.3.3 struct contentry . . . . . . . . . . . . . . . . . . . . . . . . . . 23 3.3.4 struct prdebugentry . . . . . . . . . . . . . . . . . . . . . . . . 24 3.3.5 struct prcheckentry . . . . . . . . . . . . . . . . . . . . . . . . 25 3.3.6 typedef prname . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 3.3.7 tyepdef namelist . . . . . . . . . . . . . . . . . . . . . . . . . . 26 3.3.8 typedef idlist . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 3.3.9 typedef prlist . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

3.4 Error Codes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 3.5 Macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

3.5.1 set header word() . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 3.5.2 inc header word() . . . . . . . . . . . . . . . . . . . . . . . . . . 29

3.6 Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 3.6.1 PR NameToID . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 3.6.2 PR IDToName . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 3.6.3 PR NewEntry . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 3.6.4 PR INewEntry . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 3.6.5 PR ListEntry . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 3.6.6 PR DumpEntry . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 3.6.7 PR ChangeEntry . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 3.6.8 PR SetFieldsEntry . . . . . . . . . . . . . . . . . . . . . . . . . . 39 3.6.9 PR Delete . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 3.6.10 PR WhereIsIt . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 3.6.11 PR AddToGroup . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 3.6.12 PR RemoveFromGroup . . . . . . . . . . . . . . . . . . . . . . . 43 3.6.13 PR ListMax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 3.6.14 PR SetMax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 3.6.15 PR ListElements . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 3.6.16 PR GetCPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 3.6.17 PR ListOwned . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 3.6.18 PR IsAMemberOf . . . . . . . . . . . . . . . . . . . . . . . . . . 49

Table of Contents  ii  August 28, 1991 12:16

Chapter 1

Overview

1.1 Introduction

In AFS, protection of files is accomplished by the use of Access Control Lists (ACLs) at the directory level. It is undesirable to allow ACLs to grow without reasonable bounds, as the ACLs themselves are stored as part of the directory they govern. Encoding the full string names of the individual users listed in the ACL is clearly a waste of space, so their numerical identities are stored instead. Also, it was deemed useful to allow the use of a single identity to specify a group of users, all of whom share the identical access to the files in the associated directory.

The Protection Server manages the AFS Protection Database, or PDB. This database maintains information on individual AFS users as well as groups of related AFS users. The Protection Server provides the service whereby properly-authorized AFS agents may reference and manipulate this database. Specifically, it exports an RPC interface through which callers may:

• Map back and forth between printable user/group names and their equivalent numerical identifiers.

• Query the information held for any given AFS user or group.

• Create, modify, and delete the records in the PDB where the above information is held.

• Generate a list of all identities with which a given individual user is associated. Along with the user’s login name, this list consists of all AFS groups to which they belong. This list is referred to as the user’s Current Protection Subdomain, or CPS.

1.2 Scope

This paper describes the design and structure of the AFS Protection Server. The scope of this work is to provide readers with a sufficiently detailed description of the Protection Server so that they may construct client applications that call the server’s RPC interface routines.

1.3 Document Layout

The second chapter discusses various aspects of the Protection Server’s architecture. First, the notions and characteristics of AFS users and groups are covered. The set of built-in AFS groups is then described. Next, the important notion of a Current Protection Subdomain (CPS), is examined. Two unimplemented yet externally visible Protection Server features are discussed, namely “foreign” users and superset/subset instances of individual users. Following this, the makeup of the Protection Database (PDB) managed by the Protection Server is presented. Finally, the ptserver process that implements the Protection Server is explored.

The third and final chapter provides a detailed examination of the programmer-visible Protection Server constants and structures, along with a full specification of the API for the RPC-based Protection Server functionality.

1.4 Related Documents

This document is a member of a documentation suite providing programmer-level specifications as to the operation and interfaces offered by the various AFS servers and agents, as well as the underlying RPC system they use to communicate. The full suite of related AFS specification documents is listed below:

• AFS-3 Programmer’s Reference: Architectural Overview: This paper provides an architectual overview of the AFS distributed file system, describing the full set of servers and agents in a coherent way, illustrating their relationships to each other and examining their interactions.

• AFS-3 Programmer’s Reference: File Server/Cache Manager Interface: This document describes the File Server and Cache Manager agents, which provide the backbone file managment services for AFS. The collection of File Servers for a cell supply centralized file storage for that site, and allow clients running the Cache Manager component to acces those files in a high-performance, secure fashion.

• AFS-3 Programmer’s Reference:Volume Server/Volume Location Server Interface: This document describes the services through which “containers” of related user data are located and managed.

• AFS-3 Programmer’s Reference: BOS Server Interface: This paper explains the “nanny” service for AFS server agents, supervising and controlling their execution as well as handling deployment of new server software. The BOS Server assists in the administrability of the AFS environment.

• AFS-3 Programmer’s Reference: Specification for the Rx Remote Procedure Call Facility: This document specifies the design and operation of the remote procedure call and lightweight process packages used by AFS.

In addition to these papers, the AFS 3.1 product is delivered with its own user, administrator, installation, and command reference documents.

Chapter 2

Protection Server Architecture

This chapter is responsible for presenting the general architecture of the Protection Server. First, the building blocks it works with, the notions of user and group, are examined in detail. Following this, the nature and organization of the Protection Database (PDB) is discussed. Finally, the makeup and command line arguments of the ptserver process itself are covered.

2.1 Building Blocks: Users and Groups

2.1.1 Introduction and References

A detailed treatment of the AFS notions of user and group is available in the chapter entitled The Protection Database in the AFS System Administrator’s Guide [5]. This section will serve to present its main points, focus on certain aspects, and amplify on certain others. Readers wishing to get a fuller picture are encouraged to study the given citation.

Users and groups are the two basic entities tracked and manipulated by the Protection Server as it maintains the PDB. A user is simply an individual who is capable of authenticating to the local AFS cell. A group is a list of individual users. In particular, a group may not have another group as one of its members.

Users and groups may both be dynamically created and deleted within AFS. While only administratively-qualified people may create new users, any authenticated individual may create groups without possessing any special system privileges. Each AFS user is granted a group creation quota, placing an upper limit on the number of groups they may generate at any one time.

All AFS user identifiers in the PDB are denoted by positive integers, and all group identifiers by negative integers. Zero is a reserved value in this domain.

2.1.2 User and Group Names

Names for individual AFS users are those strings typed to the login and klog programs, and are the string representations of the user’s account with AFS. The Protection Server transforms all names to lower-case for storage and comparison purposes. Names for AFS groups fall into the following two categories:

• Prefixed names: These group names are composed of two distinct sections, separated by a colon. The prefix, or part before the colon, identifies the user or group marked as the owner of the group. The latter part of the name identifies the name of the group proper, as chosen by its creator.

• Non-prefixed names: Groups whose names lack the prefix portion described above (and the associated colon) may also be created. These are typically used when creating other normal prefixed group names for which a “generic” owner is desired. For example, a non-prefixed group named accounting may be created, and populated with the administrators of a company’s accounting department. This allows for the creation of a group called accounting:payable created to handle the files within those directories controlled by the Accounts Payable personnel. Since this new group is owned by all members of the accounting group, any one of them may administer this group

2.1.3 Built-In Groups

When the Protection Server initializes a new PDB, it automatically creates entries for the following three specialized groups:

• system:anyuser: Any individual who accesses AFS files is considered by the system to be a member of this group, whether or not they are authenticated within the given cell. This group is unusual in that it doesn’t have a stable membership. In fact, it doesn’t have an explicit list of members. Instead, the system:anyuser “membership” grows and shrink as file accesses occur, with users being (conceptually) added and deleted automatically as they interact with the system. Because of the way the system:anyuser group is implemented by the Protection Server, with its non-standard representation and dynamic membership changes, an application may not use the standard Protection Server interface operations to manipulate this group.

The system:anyuser group is typically put on the ACL of those directories for which some specific level of completely public access is desired, covering anyone at any site in the greater AFS community.

• system:authuser: Any individual in possession of a valid Kerberos ticket minted by the cell’s Authentication Server is treated as a member of this group. Just as with system:anyuser, this special group does not have a stable membership, and its members are not explicitly added and deleted via calls to the Protection Server interface. If you acquire a ticket within the cell, you are automatically “added” to the group. If the ticket expires or it gets thrown away by the user via an unlog operation, then the given individual will automatically be “removed” from the group.

The system:authuser group is usually put on the ACL of those directories for which some specific level of intra-site access is desired. Anyone holding a valid ticket within the cell will be allowed to perform the set of accesses specified by the ACL entry, regardless of their precise individual ID.

• system:administrators: This built-in group defines the set of users capable of performing certain important administrative operations within the cell. Members of this group have explicit “a” (Administer) rights on every directory’s ACL in the cell. Members of the system:administrators group, for example, are the only ones capable of issuing privileged commands within the pts utility, which invokes the functions defined in the Protection Server RPC interface (described in detail in Section 3.6). Similarly, only system:administrators members can use privileged fs commands, making them capable of changing volume quotas. This group is not like the other two described above in that it does have a stable membership. Individuals must be added to and deleted from this group explicitly with the appropriate pts commands.

The system:administrators group is typically put on the ACL of those directories which contain sensitive administrative information, or on those places where only administrators are allowed to make changes. All members of this group have implicit rights to change the ACL on any AFS directory within their cell. Thus, they don’t have to actually appear on an ACL, or have “a” rights enabled in their ACL entry if they do appear, to be able to modify the ACL.

2.1.4 Current Protection Subdomain (CPS)

When a user attempts to perform an operation on an AFS file, the File Server receiving the request must determine whether the caller has adequate access privileges. Specifically, it must collect the complete set of identities associated with the caller and then compare them against the set listed in the appropriate ACL. If the File Server discovers that the caller or one of the groups of which he is a member appears in the ACL with the necessary rights, then the operation is honored. Should such an entry not be found, then the operation is rejected with a protection violation error.

The complete set of identities with which a user is associated, namely the user’s own numerical ID, the set of groups to which the user belongs, along with the special identities available to AFS principals (e.g., system:anyuser is referred to as the Current Protection Subdomain or CPS. An individual user’s CPS may change dynamically in response to the creation and deletion of groups in which they are members.

The File Server calculates a caller’s CPS on a per-connection basis by calling the Protection Server. When the first call on a given Rx connection arrives, the File Server calculates the requestor’s CPS and stores it with the caller’s records. Note, however, that there is no callback mechanism that applies to the File Server’s view of CPS information. Should a user be added to or removed from a group, the File Servers that have already calculated that user’s CPS in response to previous calls from that user are not informed of the update, and thus are left with stale information in these cases.

There are two ways that these caches may be brought up to date. If callers become quiescent for some period of time, their records will be garbage-collected by the File Server. The next file system operation from one of these users will generate a new File Server record containing the recalculated CPS. This correction may take longer than the caller is willing to wait, however (on the order of two hours). The second method is more direct, resulting in an immediate CPS recomputation. The user need simply re-authenticate with the klog utility program. This will generate a new (i.e., updated) Kerberos ticket representing the user’s identity. The first new Rx call made by this user will result in a new Rx connection, which in turn creates a new File Server client entry for the user complete with a freshly-determined CPS.

2.1.5 Foreign Users

In the original Protection Server design, it was envisioned that support for providing name-to-ID mappings for authenticated “foreign” users (i.e., those users holding Kerberos tickets generated by Authentication Servers in a different cell) would be provided. As envisioned, numerical AFS IDs would be allocated from the local PDB as needed by users as these principals were added to ACLs. Thus, access control would be extended to include handling these foreign identities.

This feature was never implemented, yet hooks were left throughout the Protection Server data structures and code for its future support. Some of these hooks are listed below.

• PRFOREIGN: The PRFOREIGN constant was meant to identify a PDB entry as belonging to a foreign user.

• PRCELL: The PRCELL constant was meant to identify a PDB entry defining the characteristics of a particular foreign cell.

• PR SF NUSERS: The PR SF NUSERS constant is used in the mask argument to the PR SetFieldsEntry() interface routine when the caller wishes to modify the PDB entry recording the quota an individual is granted for creating foreign user identities.

• maxforeign: This is a field in the PDB header (see the struct prheader description in Section 3.3.1) which records the largest foreign ID allocated to date.

• foreigncount: This is another field in the PDB header, and its job is to record the current number of foreign user entries.

• nusers: This is a field in the PDB entry data structure (see the struct prentry description in Section 3.3.2) which keeps track of the number of foreign user entries a particular individual has created. Note that there is also an nusers field in the user-visible version of the PDB entry data structure, struct prdebugentry.

2.1.6 Superset and Subset Instances

Another concept in the original Protection Server design that remains unimplemented in the current code is that of subset and superset instances of individual user identities. It seemed useful to allow for the dynamic creation of identities with restricted or amplified sets of access rights. For example, consider user herbert, a member of the system:administrators group. It would be possible for herbert to authenticate as a non-priviledged sub-identity, say herbert.fewprivs, as long as those administrative powers were not needed. This would insure that potentially destructive administrative operations would not be accidentally executed.

As with the unimplemented foreign user concept discussed in Section 2.1.5, there are a number of hooks in the Protection Server structures and code in support of the superset/subset notion. Some of these hooks are listed below.

• PRINST: This constant is used to mark a PDB entry as describing a superset or subset instance for a given AFS user.

• maxInst: The maxInst field in the PDB header (see the struct prheader description in Section 3.3.1) records the largest superset or subset ID created to date.

• instcount: This is another field in the PDB header, and it is responsible for recording the number of superset and subset instances currently registered in the system.

• instance: This is a field in the PDB entry data structure (see the struct prentry description in Section 3.3.2) which keeps track of the number of superset and subset instance entries a particular individual has created. Note that there is also an instance field in the user-visible version of the PDB entry data structure, struct

     prdebugentry.

2.2 The Protection Database

2.2.1 Layout

The organization of the Protection Database (PDB) is straightforward. At the beginning of the PDB is a header region, and it is immediately followed by the set of entry records for the users and groups in the system.

PDB entries are organized via two hash tables and several linked lists. Since PDB entries are normally looked up by either their string name or by their numerical ID, these entries are threaded into by-name and by-ID hash tables. There is a global free list maintained for deleted entries. There is also a global orphan list, which contains entries for all orphans, namely groups belonging to users that have been deleted from the PDB. In addition, each entry has a linked list containing the set of other entries which it owns.

The PDB entries store such information as the name and ID of the user or group, the IDs of its owner and its creator, the group creation quota, and a set of bit fields. These bits identify the entry’s type (e.g., individual user, group), state whether quota enforcement and access checking is enabled for the entry, and specify the “privacy bits” for the entry (See Section 2.2.2). Also included in a PDB entry is a set of IDs with which the given entry is associated. If the entry is marked as representing an individual user, then the IDs identify the groups to which that individual belongs. If the entry is marked as representing a group, then the IDs identify the individual members belonging to that group.

The PDB entry described above can hold only PRSIZE (10) of these associated IDs. This number was considered reasonable for most occasions. However, it is possible for a user to belong to more than 10 AFS groups, or for a group to have more than 10 individuals as members. This is accomplished by introducing the concept of continuation entries. These continuation entries are exactly the same size as the above “regular” or “main” entries, so they are allocated, deleted, and threaded much like the main ones. However, one of the bit fields mentioned above is used to mark them as continuations. While they mirror some of the information in the main entry, continuation entries are formatted so that most of the space is devoted to a larger ID array, holding up to COSIZE (39) entries. Continuation entries are threaded to the appropriate main entry, and are thus used to hold the “spillover” IDs that don’t fit there. An arbitrary number of continuation entries may be created for each AFS user or group represented in the PDB.

The PDB header, a struct prheader (as described in Section 3.3.1) contains such information as the PDB’s version number, the address of the beginning of the free list, the number of total users and groups recorded for the system, the largest user and group IDs allocated so far, and the hash tables used for looking up entries by name and by ID.

2.2.2 PDB Entry Privacy Bits

It is possible to limit the kind of information that users obtain about entries in the PDB. This per-entry limitation is implemented by defining a set of privacy bits in each PDB record. Normal users are authorized to control external access to their own entries, as well as the set of group entries they own. Members of the privileged system:administrators group may set the privacy bits on any entry in the PDB.

There are five privacy bits, each denoted by a corresponding letter in the interface offered by the pts utility, which interacts with the Protection Server:

• STATUS (s): Allows basic status for the entry itself to be seen.

• OWNED (o): Allows the users and groups owned by the entry to be listed.

• MEMBERSHIP (m): Allows the listing of the set of groups the individual user is a member of, or the set of users comprising the members of the given group.

• ADD (a): Allows users to be added to the group.

• REMOVE (r): Allows users to be removed from the group.

The pts utility sets up this list of rights to appear as five “slots”, one for each of the above letters. Three variations of the appropriate letter may appear in each slot, each representing a different set of people who possess the right:

• A hyphen in the slot indicates that only the entry’s owner and members of the system:administrators group have the access right. For user entries, this also indicates that the user has the right.

• A lowercase letter in the slot indicates that members of the group have the access right. This applies meaningfully to group entries only.

• An uppercase letter in the slot indicates that everyone has the access right. This is equivalent to the set of principals included in the system:anyuser group for ACLs.

Consider the example rights list SOmar associated with an AFS group entry. The two leading capital letters indicate that anyone can examine the group’s entry and list the groups that it owns. The three following lowercase letters specify that only members of the group itself may list, add, or remove its members, respectively.

The default rights list associated with a user entry in the PDB is S-----. This specifies that anyone may examine the entry itself, but that only the user and members of the system:administrators group can list the groups they own and the groups of which they are members. The add and delete operations do not apply to a user entry.

The default rights list for a group entry is S-M--, meaning that all users can obtain status information on the group entry and list the members of the group.

2.2.3 Database Replication

The PDB, along with other important AFS databases, may be replicated to multiple sites to improve its availability. The ubik replication package is used to implement this functionality for the PDB. A full description of ubik and of the quorum completion algorithm it implements may be found in [6] and [7]. The basic abstraction provided by ubik is that of a disk file replicated to multiple server locations. One of the machines is considered to be the synchronization site at any given time, handling all write operations on the database file. Read operations may be directed to any of the active members of the quorum, namely a subset of the replication sites large enough to insure integrity across such failures as individual server crashes and network partitions. All of the quorum members participate in regular elections to determine the current synchronization site. Should the machine acting as the current synchronization site crash, another synchronization site will be elected. The ubik algorithms allow server machines to enter and exit the quorum in an orderly and consistent fashion. All operations to one of these replicated “abstract files” are performed as part of a transaction. If all the related operations performed under a transaction are successful, then the transaction is committed, and the changes are made permanent. Otherwise, the transaction is aborted, and all of the operations for that transaction are undone.

2.3 The ptserver Process

2.3.1 Introduction

The user-space ptserver process implements the Protection Server. This program maintains the PDB replica at the site where it runs, and cooperates with all other ptserver processes running in the cell to propagate updates to the replicated database. It implements the RPC interface defined in the ptint.xg Rxgen definition file. As part of its startup sequence, it must discover the PDB version it has on its local disk, move to join the quorum of replication sites for the PDB, and get the latest version if its local copy is out of date. Once the ptserver synchronizes with the other PDB replication sites, it will begin accepting Protection Server calls.

2.3.2 Command Line Switches

The Protection Server accepts a set of command line switches. Using these switches, a set of server parameters and actions can be set. Under normal conditions, the Protection Server process is started up by the BOS Server on that machine, as described in [1]. So, in order to utilize any of these command-line options, the system administrator must define the Protection Server record (bnode) in such a way that these parameters are properly included. Note that the switch names must be typed exactly as listed, and that abbreviations are not allowed.

Here is a description of the set of currently-supported command line switches.

• -database <pathname>: Provide the pathname prefix for the local PDB file to bring up. A synonym for the -database switch is -db. If this switch is not provided, the default database file prefix is set to /usr/afs/db/prdb.

• -rebuild: Specify that the PDB is to be rebuilt before the given Protection Server begins offering its services. This command-line switch is currently a no-op.

2.3.3 Threading

As with all the other AFS server agents, the Protection Server is a multithreaded program. It is configured so that a minimum of two lightweight threads are guaranteed to be allocated to handle incoming RPC calls to the Protection Server, and a maximum of three threads are commissioned for this task.

Chapter 3

Protection Server Interface

3.1 Introduction

This chapter documents the API for the Protection Server facility, as defined by the ptint.xg Rxgen interface file and the ptserver.h include file. Descriptions of all the constants, structures, macros, and interface functions available to the application programmer appear in this exposition.

3.2 Constants

This section covers the basic constant definitions of interest to the Protection Server application programmer. These definitions appear in the ptint.h file, automatically generated from the ptint.xg Rxgen interface file, and in ptserver.h.

Each subsection is devoted to describing the constants falling into each of the following categories:

• Interface function opcodes

• Size and configuration quantities

• Mask bits for PR SetFieldsEntry()

• Reserved IDs

   • Bits for the struct prentry flags field

• Privacy bits

• Miscellaneous

3.2.1 Interface Function Opcodes

These constants, appearing in the ptopcodes.h Rxgen interface file for the Protection Server, define the opcodes for the RPC routines. Every Rx call on this interface contains this opcode, and the thread dispatcher uses it to select the proper code at the server site to carry out the call.

Name  Value Description

PRINEWUSER 500 Opcode for the PR NewUser() function. PRWHEREISIT 501 Opcode for the PR WhereIsIt() function. PRDUMPENTRY 502 Opcode for the PR DumpEntry() function. PRADDTOGROUP 503 Opcode for the PR AddToGroup() function. PRNAMETOID 504 Opcode for the PR NameToID() function. PRIDTONAME 505 Opcode for the PR IDToName() function. PRDELETE 506 Opcode for the PR Delete() function. PRREMOVEFROMGROUP 507 Opcode for the PR RemoveFromGroup() function. PRGETCPS 508 Opcode for the PR GetCPS() function. PRNEWENTRY 509 Opcode for the PR NewEntry() function. PRLISTMAX 510 Opcode for the PR ListMax() function. PRSETMAX 511 Opcode for the PR SetMax() function. PRLISTENTRY 512 Opcode for the PR ListEntry() function. PRCHANGEENTRY 513 Opcode for the PR ChangeEntry() function. PRLISTELEMENTS 514 Opcode for the PR ListElements() function. PRISAMEMBEROF 515 Opcode for the PR IsAMemberOf() . PRSETFIELDSENTRY 516 Opcode for the PR SetFieldsEntry() function. PRLISTOWNED 517 Opcode for the PR ListOwned() function. LOWEST 500 Lowest-numbered Protection Server opcode. HIGHEST 517 Highest-numbered Protection Server opcode.

3.2.2 Size and Configuration Quantities

This section presents some miscellaneous values defined within the Protection Server which have to do with sizes for various structures as well as general configuration facts. For example, maximum sizes for names used within the Protection Server as well as for lists generated and passed to clients are specified. Also, hash table sizes and ID array allocations within the PDB records are nailed down. Such configuration information as the currently-supported PDB database version number and the Rx service identifier advertised by the Protection Server for handling of its calls appears here.

Name  Value Description

PR MAXNAMELEN 64 Longest permissible AFS user or group name, including

the trailing null.

PR MAXGROUPS 5,000 Maximum number of group IDs which can fit into a

prlist variable-length array (See Section 3.3.9).

PR MAXLIST 5,000 Maximum number of string names or numerical IDs which can fit into a namelist or idlist variable-length array (see Sections 3.3.7 and 3.3.8).

PRSIZE 10 Maximum number of IDs kept in a struct prentry in

the PDB before having to resort to a continuation block.

COSIZE 39 Maximum number of IDs kept in a PDB continuation

block.

PRSRV 73 Rx service identifier for the Protection Server. ENTRYSIZE 192 Size in bytes of a PDB entry. HASHSIZE 8,191 Size of the internal nameHash and idHash Protection

Server hash lookup tables.

PRDBVERSION 0 PDB version number.

3.2.3 Mask Bits for PR SetFieldsEntry()

The PR SetFieldsEntry() interface call allows various fields of a PDB entry to be altered, as described in detail in Section 3.6.8. One of the arguments to that function is a mask whose bit values are used to select which fields are to be assigned. This section presents the valid sets of bits that can be passed in this mask parameter.

Name  Value Description

PR SF NGROUPS (1<<31) Set the field limiting group creation. PR SF NUSERS (1<<30) Set the field limiting creation of foreign users.

PR SF ALLBITS  0xff  Set all access (privacy) bits.

3.2.4 Reserved IDs

Certain AFS user and group IDs are reserved, and have special meaning to the system. This section reveals the set of reserved IDs and explains their significance.

Name  Value  Description
SYSADMINID  -204  This ID is used for the special

system:administrators group, namely those individuals declared to be capable of performing certain administrative AFS operations.

ANYUSERID -101 This ID is used for the special system:anyuser group, namely all AFS users, regardless of their authentication state.

AUTHUSERID -102 This ID is used for the special system:authuser group, namely all AFS users which hold valid Kerberos tickets within the local cell.

ANONYMOUSID 32,766 This ID is used for the special AFS user which corresponds to someone who has not generated tickets within the local cell.

PRBADID 0x80000000 This ID is reserved to indicate an AFS ID which is guaranteed to be “bad” (i.e., unused), and is used to mark empty slots in a PDB entry.

3.2.5 Bits for struct prentry flags Field

A flag field is maintained in the structure which defines the format of PDB records. These flag bits carry information as to the nature of the entry and whether such things as group creation quotas and special access checking is being obeyed. Specifically, the least-significant 6 bits identify the type of the PDB entry, and the next two bits determine whether enforcement of the above two policies is in effect. This section lays out the bits in this field and reports on their individual meanings.

Name  Value Description

PRTYPE 0x3f Bit mask isolating the type bits for a PDB entry. Only one

of these bits should be set.

PRFREE  1  The PDB entry is in the free list.
PRGRP  2  The PDB entry is a group entry.
PRCONT  4  The PDB entry is formatted as a continuation block.
PRCELL  8  The PDB entry is a cell entry (not used).
PRFOREIGN  16  The PDB entry is for a foreign user (not used).
PRINST  32  The PDB entry is for a sub/super instance of an identifier

(not used).

PRUSER 0 If all type bits (the low-order 6 bits) are 0, then the entry is

a user entry.

PRACCESS (1<<6) Access checking is enabled or this entry. PRQUOTA (1<<7) Group creation quota checking is enabled for this entry.

3.2.6 Privacy Bits

As presented in some detail in Section 2.2.2, the ability to list information regarding the individual PDB entries is controlled by a set of bits in the entry itself. This section covers the organization of these privacy bits. The bit aray is stored in the upper 16 bits of the flags field of the struct prentry defining the layout of PDB entries. Note, however, that the flags argument to the PR SetFieldsEntry() RPC interface routine which allows access to these bits expects these bits in the lower 16 bits of the word. For convenience, the PRIVATE SHIFT constant is defined so that programmers can shift the bit fields to their proper locations. There are a total of 8 bit positions defined. Two of the five rights (OWNERED, REMOVE) only require one bit to encode. The others (STATUS, MEMBERSHIP, and ADD) require two bits to represent, as they have more “levels” at which they may be set.

Name  Value  Description
PRIVATE SHIFT  16  Constant used to shift privacy

bits into proper position in the

flags field.

PRP REMOVE MEM (0x01 << PRIVATE SHIFT) Allows members of the given group to remove users from its membership.

PRP ADD MEM (0x02 << PRIVATE SHIFT) Allows members of a group to delete users from its membership.

PRP ADD ANY (0x04 << PRIVATE SHIFT) Allows anyone to add users to a

group’s membership.

PRP MEMBER MEM (0x08 << PRIVATE SHIFT) Allows members of a group to

list its membership set

PRP MEMBER ANY (0x10 << PRIVATE SHIFT) Allows anyone to list the membership set of a group, or list the set of groups to which a given individual belongs.

PRP OWNED ANY (0x20 << PRIVATE SHIFT) Allows the viewing of the list of groups owned by the given entry.

PRP STATUS MEM (0x40 << PRIVATE SHIFT) Allows members of a group to

get status on the given entry.

PRP STATUS ANY (0x80 << PRIVATE SHIFT) Allows anyone to get status on a given entry.

In addition to those constant definitions defined in the above table, there are two other constants that are useful in this realm. The PRP USER DEFAULT constant, set to (PRP STATUS ANY), defines the default access allowed to a user entry in the PDB when the PRACCESS bit is turned off. It states that any user may obtain status information on the entry, but only the given user and members of the system:administrators group can list the groups they own and the groups of which they are members. This corresponds to an interface specification of S-----. Similarly, the PRP GROUP DEFAULT constant, defined as (PRP STATUS ANY | PRP MEMBER ANY), dictates the standard access allowed for a group entry in the PDB. As set, any user may obtain status information on the entry and list the group’s members. This corresponds to an interface specification of S-M--.

3.2.7 Miscellaneous

The following constant definitions don’t fall easily into the above categrories, so are collected here.

Name  Value Description

PRSUCCESS 0 Defined to match the “successful” return value from

Protection Server routines.

PR REMEMBER TIMES 1 If non-zero, the Protection Server will record the clock times when a PDB entry was created, had an ID added to it, had an ID removed from it, and the time of the last change of any type. This information is held in the 5 reserved longwords in struct

                         prentry.

3.3 Structures and Typedefs

This section describes the major exported Protection Server data structures of interest to application programmers, along with the typedefs based upon those structures. Please note that some of the typedefs included here were made for the RPC stub generator, rxgen. Rxgen takes a specification of a server’s procedure call interface as input, and generates the proper server-side and client-side C stub code, along with any necessary C include files. These typedefs included for rxgen handling may be identified by the fact that they contain angle brackets as part of the definition.

3.3.1 struct prheader

This structure defines the format of the PDB header record. It is reponsible for recording information about the PDB as a whole. Examples of the knowledge stored here are the PDB’s version number, the address of the beginning of the free list, the number of users and groups in the system, the largest user and group IDs allocated so far, and the hash tables used for looking up entries by name and by ID. There are also some fields included here for features which have not been implemented, such as having foreign users in the PDB (users registered with another cell) and having superset or subset instances.

The PDB’s header region is not directly visible via the Protection Server interface, but such interface calls as PR ListMax(), PR SetMax(), and even PR ListOwned() when it’s used to deliver the orphan list report on the contents of some of the header’s fields, Fields

long version - The PDB’s database version number long headerSize - The size of this structure in bytes. long freePtr - Pointer to the first free PDB entry, namely the first entry in the

free list. long eofPtr - Pointer to the high-water mark in the PDB replicated file, namely

the first completely unused byte in the file and not any part of the free list. long maxGroup - The “largest” (most negative) group ID allocated to date. long maxID - The “largest” (most positive) user id allocated to date. long maxForeign - The largest foreign ID allocated to date (not implemented). long maxInst - The largest subset or superset ID allocated to date (not imple-

mented). long orphan - The list of groups owned by deleted users. long usercount - The total number of users for which there are PDB entries in the

system. long groupcount - The total number of groups for which there are PDB entries

in the system. long foreigncount - The number of registered foreign users (not implemented). long instcount - The number of subset and superset users in the system (not

implemented). long reserved[] - Five longword values reserved for future use. long nameHash[] - The name-based hash lookup table, an array of HASHSIZE

(8,191) PDB entry pointers. long idHash[HASHSIZE] - The ID-based hash lookup table, is implemented as

an array of HASHSIZE (8,191) PDB entry pointers.

3.3.2 struct prentry

This structure represents the format of the “main” PDB entry for an AFS user or group. Along with the other information concerning the given user or group, it holds up to PRSIZE (10) IDs. If the entry is for a user, then these IDs list the set of groups to which the individual belongs. If the entry is for a group, then the IDs represent the individuals that belong to the group. If there are more than PRSIZE IDs to keep track of for the entry, then it must use one or more continuation blocks, as defined by the struct contentry structure described in Section 3.3.3. Please note that “main” PDB entries and continuation entries are both the same size (ENTRYSIZE (192) bytes), but differ in format.

The reader should note that the struct prdebugentry defined in Section 3.3.4 below is identical to this structure. The prdebugentry version, though, is the externally-visible version, and is only used during debugging via the PR DumpEntry() interface routine.

Fields

long flags - These are bits having to do with the entry type, the operations enabled on this entry, and the access checks that will be performed. Please refer to Sections 3.2.5 and 3.2.6 for the legal values for this field.

long id - The associated user or group ID.

long cellid - The entry’s cell identifier (not used).

long next - A pointer to the next PDB block for the same entry, or the next block on the free list if the entry currently resides there.

reserved[] - This field consists of 5 (semi-)reserved unsigned longwords, put to use in different ways selectable at Protection Server compile-time. If the PR REMEMBER TIMES constant is defined to be non-zero, then the first four longwords are interpreted as fields whose names are createTime, addTime, removeTime, and changeTime. They refer respectively to the time of creation of the entry, the last time an ID was added to it, the last time an ID was removed from it, and the last time a change of any other kind was made. In this case, the fifth longword in the series is referred to as reserved[1]. Should the PR REMEMBER TIMES be set to zero at compilation time, the code will refer to these five longwords as reserved[5].

long entries[] - An array of AFS IDs associated with the given entry. If the entry represents a group, then each ID refers to an individual member of the group. If the entry represents an individual user, then each ID refers to a group to which that user belongs. This array holds a maximum of PRSIZE (10) entries.

long nextID - Next pointer in the by-ID PDB hash table.

long nextName - Next pointer in the by-name PDB hash table.

long owner - The AFS ID of this entry’s owner.

long creator - The AFS ID of the party which created this entry.

long ngroups - The number of groups this ID has created. If this is a group entry, ngroups is always 0. long nusers - The number of foreign user entries this ID has created (not used).

long count - The number of members/groups for this group/user.

long instance - The number of superset/subset instances for this user (not used).

long owned - A pointer to the head of a chain of groups owned by this entry. Note that both users and groups can own groups.

long nextOwned - The chain of groups for the owner of this entry.

long parent - Pointer to the entry’s superset instance (not used).

long sibling - Pointer to this entry’s sibling instance (not used).

long child - Pointer to this entry’s first child (not used).

char name[] - The printable name of the associated user or group. It has at most PR MAXNAMELEN (64) characters in it, including the trailing null.

3.3.3 struct contentry

This structure represents the format of a “continuation” PDB entry for an AFS user or group. Along with a subset of the information held in the “main” entry (of type struct prentry), it maintains up to COSIZE (39) additional IDs associate with the extended entry. If the entry is for a user, then these IDs list the set of groups to which the individual belongs. If the entry is for a group, then the IDs represent the individuals that belong to the group. As pointed out above, “main” PDB entries and continuation entries are both the same size (ENTRYSIZE (192) bytes), and simply differ in format.

Fields

long flags - These are bits having to do with the entry type, the operations enabled on this entry, and the access checks that will be performed. Please refer to Sections 3.2.5 and 3.2.6 for the legal values for this field.

long id - The associated user or group ID.

long cellid - The entry’s cell identifier (not used).

long next - A pointer to the next PDB block for the same entry, or the next block on the free list if the entry currently resides there.

long reserved[] - The set of 5 reserved words which may or may not hold certain time values related to the entry. If the PR REMEMBER TIMES constant is defined to be non-zero, then the first four longwords are interpreted as fields specifying the time of creation of the entry, the last time an ID was added to it, the last time an ID was removed from it, and the last time a change of any kind was made. The fifth longword in the series is still unused and reserved for future assignment.

long entries[] - An array of additional AFS IDs associated with the given entry’s main ID. If the entry represents a group, then each ID refers to an individual member of the group. If the entry represents an individual user, then each ID refers to a group to which that user belongs. This array holds a maximum of COSIZE (39) entries.

3.3.4 struct prdebugentry

This structure is identical to the basic PDB entry structure defined as struct prentry in Section 3.3.2, except for a minor spelling modification of one field (nextName in struct prentry, nextname in this structure). This construct is used exclusively by the PR DumpEntry() interface function. For the reader’s convenience, the description of its fields is repeated here.

Fields

long flags - These are bits having to do with the entry type, the operations enabled on this entry, and the access checks that will be performed. Please refer to Sections 3.2.5 and 3.2.6 for the legal values for this field.

long id - The associated user or group ID.

long cellid - The entry’s cell identifier (not used).

long next - A pointer to the next PDB block for the same entry, or the next block on the free list if the entry currently resides there.

reserved[] - This field consists of 5 (semi-)reserved unsigned longwords, put to use in different ways selectable at Protection Server compile-time. If the PR REMEMBER TIMES constant is defined to be non-zero, then the first four longwords are interpreted as fields whose names are createTime, addTime, removeTime, and changeTime. They refer respectively to the time of creation of the entry, the last time an ID was added to it, the last time an ID was removed from it, and the last time a change of any kind was made. In this case, the fifth longword in the series is referred to as reserved[1]. Should the PR REMEMBER TIMES be set to zero at compilation time, the code will refer to these five longwords as reserved[5].

long entries[] - An array of AFS IDs associated with the given entry. If the entry represents a group, then each ID refers to an individual member of the group.

If the entry represents an individual user, then each ID refers to a group to which that user belongs. This array holds a maximum of PRSIZE (10) entries.

long nextID - Next pointer in the by-ID PDB hash table. long nextname - Next pointer in the by-name PDB hash table. long owner - The AFS ID of this entry’s owner. long creator - The AFS ID of the party which created this entry. long ngroups - The number of groups this ID has created. If this is a group entry,

ngroups is always 0. long nusers - The number of foreign user entries this ID has created (not used). long count - The number of members/groups for this group/user. long instance - The number of superset/subset instances for this user (not used). long owned - The chain of groups owned by this entry. long nextOwned - The chain of groups for the owner of this entry. long parent - Pointer to the entry’s superset instance (not used). long sibling - Pointer to this entry’s sibling instance (not used). long child - Pointer to this entry’s first child (not used). char name[] - The printable name of the associated user or group. It has at most

PR MAXNAMELEN (64) characters in it, including the trailing null.

3.3.5 struct prcheckentry

This structure is a subset of the fields defined within the struct prentry described in Section 3.3.2. It is used to communicate the “user-visible” fields of a PDB entry to the average inquirer, and appears as an argument to the PR ListEntry() RPC interface call, described in Section 3.6.5. Fields

long flags - These are bits having to do with the entry type, the operations enabled on this entry, and the access checks that will be performed. Please refer to Sections 3.2.5 and 3.2.6 for the legal values for this field.

long id - The associated user or group ID. long owner - The AFS ID of this entry’s owner. long creator - The AFS ID of the party which created this entry. long ngroups - The number of groups this ID has created. If this is a group entry,

ngroups is always 0.

long nusers - The number of foreign user entries this ID has created (not used).

count - The number of members/groups for this group/user.

reserved[] - The set of 5 reserved words which may or may not hold certain time values related to the entry. If the PR REMEMBER TIMES constant is defined to be non-zero, then the first four longwords are interpreted as fields specifying the time of creation of the entry, the last time an ID was added to it, the last time an ID was removed from it, and the last time a change of any kind was made. The fifth longword in the series is still unused and reserved for future assignment.

name[] - The printable name of the associated user or group. It has at most PR MAXNAMELEN (64) characters in it, including the trailing null.

3.3.6 typedef prname
    typedef char prname[PR_MAXNAMELEN];

This typedef is used to define a variable which houses the printable name of an AFS principal. Such names may be up to PR MAXNAMELEN (64) characters long, including the trailing null. In turn, prname is used by the namelist typedef to create an array of these printable user names (see Section 3.3.7).

3.3.7 tyepdef namelist
    typedef prname namelist<PR_MAXLIST>;

This typedef is used by rxgen to define a C structure providing a variable-length array of printable AFS user names. It may carry up to PR MAXLIST (5,000) of these name entries, and contains the following fields:

Fields

namelist len - The number of name entries contained within the data region pointed to by the next field.

namelist val - A pointer to a sequence of namelist len AFS name entries.

The namelist typedef is used in the PR NameToID() and PR IDToName() RPC interface calls (see Sections 3.6.1 and 3.6.2 respectively).

3.3.8 typedef idlist
    typedef long idlist<PR_MAXLIST>;

This typedef is used by rxgen to define a C structure providing a variable-length array of numerical AFS user identifiers. It may carry up to PR MAXLIST (5,000) of these IDs, and contains the following fields:

Fields

idlist len - The number of longword IDs contained within the data region pointed to by the next field.

idlist val - A pointer to a sequence of idlist len numerical AFS user IDs.

The idlist typedef is used in the PR NameToID() and PR IDToName() RPC interface calls (see Sections 3.6.1 and 3.6.2 respectively).

3.3.9 typedef prlist
    typedef long prlist<PR_MAXGROUPS>;

This typedef is used by rxgen to define a C structure providing a variable-length array of AFS IDs. This structure is used as an argument to the PR GetCPS(), PR ListElements(), and PR ListOwned() (described in Sections 3.6.16, 3.6.15, and 3.6.17 respectively). It may carry up to PR MAXGROUPS (5,000) of these IDs, and sports the following fields:

Fields

prlist len - The number of longword AFS IDs contained within the data pointed to by the next field.

prlist val - A pointer to a sequence of prlist len IDs.

3.4 Error Codes

This section covers the set of error codes exported by the Protection Server, displaying the printable phrases with which they are associated.

Name  Value Description

PREXIST (267264L) Entry for name already exists. PRIDEXIST (267265L) Entry for id already exists. PRNOIDS (267266L) Couldn’t allocate an id for this entry. PRDBFAIL (267267L) Couldn’t read/write the database. PRNOENT (267268L) User or group doesn’t exist. PRPERM (267269L) Permission denied. PRNOTGROUP (267270L) No group specified. PRNOTUSER (267271L) No user specified. PRBADNAM (267272L) Badly formed name (group prefix doesn’t match

owner?).

PRBADARG (267273L) argument illegal or out of range. PRNOMORE (267274L) may not create more groups. PRDBBAD (267275L) database needs rebuilding. PRGROUPEMPTY (267276L) can’t make owner an empty group. PRINCONSISTENT (267277L) database is inconsistent. PRDBADDR (267278L) bad database address. PRTOOMANY (267279L) too many elements in group.

3.5 Macros

The Protection Server defines a pair of macros which are externally visible via the ptserver.h file. They are both used to operate on fields within the PDB header structure. These two macros are only invoked internally, and are not usable from a normal AFS application.

3.5.1 set header word()

   #define set_header_word(tt, field, value) \
       pr_Write((tt), 0, ((char *)&(cheader.field) - (char *)&cheader),   \
           ((cheader.field = (value)), (char *)&(cheader.field)),         \
           sizeof(long))

This macro is used to transactionally assign a field within the PDB header structure. The first argument, tt, is a pointer of type (struct ubik trans *), and communicates the ubik transaction under which this update is taking place. The next argument, field, identifies the name of the field within the PDB header to be changed. Finally, the value parameter represents the new value to be assigned to field. Only PDB header fields of type long may be assigned in this fashion.

3.5.2 inc header word()

    #define inc_header_word(tt, field, inc) \
        pr_Write((tt), 0, ((char *)&(cheader.field) - (char *)&cheader), \
            ((cheader.field = (htonl(ntohl(cheader.field)+(inc)))),      \

             (char *)&(cheader.field)),                                  \

            sizeof(long))

This macro is used to transactionally increment a field within the PDB header structure. The first argument, tt, is a pointer of type (struct ubik trans *), and communicates the ubik transaction under which this update is taking place. The next argument, field, identifies the name of the field within the PDB header to be changed. Finally, the inc parameter specifies the amount the chosen field should be incremented. Only PDB header fields of type long may be incremented in this fashion.

3.6 Functions

This section covers the Protection Server RPC interface routines. They are generated from the ptint.xg Rxgen file. The following is a summary fo the interface functions and their purpose:

Fcn Name  Description

PR NameToID() Perform name-to-ID translation(s). PR IDToName() Perform ID-to-name translation(s). PR NewEntry() Create a PDB entry for the given name. PR INewEntry() Create a PDB entry for the given name and ID. PR ListEntry() Get the contents of a PDB entry based on its ID. PR DumpEntry() Get the contents of a PDB entry based on its offset (for

debugging).

PR ChangeEntry() Change an existing PDB entry’s ID, name, and/or owner. PR SetFieldsEntry() Change miscellaneous fields in an existing PDB entry. PR Delete() Delete an existing PDB entry. PR WhereIsIt() Get the PDB byte offset of the entry for a given ID. This

is intended for debugging purposes.

PR AddToGroup() Add a user to a group. PR RemoveFromGroup() Remove a user from a chosen group. PR ListMax() Get the largest allocated user and group ID. PR SetMax() Set the largest allocated user and group ID. PR ListElements() List all IDs associated with a user or group. PR GetCPS() Get the CPS for the given ID. PR ListOwned() List all IDs owned by the given ID. PR IsAMemberOf() Is a given user ID a member of a specified group?.

At a higher level, these functions may be seen as belonging to four basic classes:

• Name to ID mapping, and vice-versa.

• Creation, inspection, modification, and deletion of PDB entries.

• Inquiries on selected PDB header fields.

• Ownership/membership queries and modifications.

3.6.1 PR NameToID — Perform name-to-ID translation(s)

int PR NameToID(IN struct rx connection *z conn,
                      IN namelist *nlist,
                      OUT idlist *ilist)

Description

This routine takes as an input parameter a variable-length array of AFS user names, nlist. Its job is to then translate each of the nlist->namelist len names into the appropriate numerical AFS user ID. Values greater than or equal to zero and less than or equal to PR MAXLIST (5,000) are legal values for nlist->namelist len. The output parameter, ilist, is used to store the list of IDs matching the given names. Exactly nlist->namelist len entries are allocated for the variable-length ilist output array.

Entries in the given nlist for which the Protection Server does not have a name-to-ID mapping are translated to ANONYMOUSID, the anonymous user ID. Since this is a potentially long-lived operation, a lightweight Protection Server thread executing this call offers itself for rescheduling every 50 translations. This threading activity is completely invisible to the caller.

The underlying ubik-based PDB is manipulated under a read transaction, and is readlocked for the duration of the operation.

Error Codes

PRTOOMANY An illegal value was found in the namelist len field within the nlist argument, either less than or equal to zero or more than PR MAXLIST (5,000).

PRDBBAD An error was found relating to the PDB.

3.6.2 PR IDToName — Perform ID-to-name translation(s)

int PR IDToName(IN struct rx connection *z conn,
                      IN idlist *ilist,
                      OUT namelist *nlist)

Description

This routine takes as an input parameter a variable-length array of numerical AFS user IDs, ilist. Its job is to then translate each of the ilist->idlist len IDs into the appropriate printable AFS user names. Values greater than or equal to zero and less than or equal to PR MAXLIST (5,000) are legal values for ilist->idlist len. The output parameter, nlist, is used to store the list of names matching the given IDs. Exactly ilist->idlist len entries are allocated for the variable-length nlist output array.

Entries in the given ilist for which the Protection Server does not have an ID-to-name mapping are translated to the string representation of the numerical ID, in base 10. Since this is a potentially long-lived operation, a lightweight Protection Server thread executing this call offers itself for rescheduling every 50 translations. This threading activity is completely invisible to the caller.

The underlying ubik-based PDB is manipulated under a read transaction, and is readlocked for the duration of the operation.

Error Codes

PRTOOMANY An illegal value was found in the ilist len field within the ilist argument, either less than or equal to zero or more than PR MAXLIST (5,000).

PRDBBAD An error was found relating to the PDB.

3.6.3 PR NewEntry — Create a PDB entry for the given name

int PR NewEntry(IN struct rx connection *z conn,
                     IN char *name,
                     IN long flag,
                     IN long oid,
                     OUT long *id)

Description

Create an entry in the PDB for a user or group with the given name, and whose owner’s ID is oid. The name parameter must have no more than PR MAXNAMELEN (64) characters, including the trailing null. The flags argument is used to communicate whether the entry is for a user or group. It may legally take on any of the values PRGRP, PRUSER, or PRFOREIGN (although foreign IDs are not implemented), as defined in Section 3.2.5. If successful, the user or group ID allocated for this new entry is returned in id.

Creation of a group entry by an unauthenticated caller is allowed only if the owner (oid) is specified as a non-zero value, or if the Protection Server is running in an unauthenticated mode. Creation of a user entry is allowed only if the caller is a member of the system:administrators group, or if the Protection Server is running in an unauthenticated mode. Members of the system:administrators group may create an unlimited number of groups, while other users are restricted by a group quota, as described in Section 2.1.1.

The underlying ubik-based PDB is manipulated under a write transaction, and is writelocked for the duration of the operation.

Error Codes

PRPERM The caller’s identity could not be established, or is not authorized to perform the operation.

PRBADNAM An Illegal name was provided for the new entry.

PREXIST The named user or group already exists.

PRDBFAIL Space for a new PDB entry could not be allocated, or the entry could not be successfully filled in.

PRNOMORE The caller’s creation quota has been exceeded.

PRDBBAD An error was found relating to the PDB.

3.6.4 PR INewEntry — Create a PDB entry for the given name and ID

int PR INewEntry(IN struct rx connection *z conn,
                      IN char *name,
                      IN long id,
                      IN long oid)

Description

This routine is similar to the PR NewEntry() function described in Section 3.6.3 in that it creates a new user or group entry in the PDB. However, PR INewEntry() is used when the numerical AFS ID must be set to a given value, namely id. Thus, there are no output parameters here. This function is not normally used in every-day operation. Rather, it is particularly useful for conversion operations, where AFS identities are being created in the PDB based on an existing set of unix ids.

Please refer to the description of the PR NewEntry() interface function for more details.

Error Codes

PRPERM The caller’s identity could not be established, or is not authorized to perform the operation.

PRBADNAM An illegal name was provided for the new entry.

PREXIST The named user or group already exists.

PRDBFAIL Space for a new PDB entry could not be allocated, or the entry could not be successfully filled in.

PRNOMORE The caller’s creation quota has been exceeded.

PRDBBAD An error was found relating to the PDB.

3.6.5 PR ListEntry — Get the contents of a PDB entry based on its ID

int PR ListEntry(IN struct rx connection *z conn,
                    IN long id,
                    OUT struct prcheckentry *entry)

Description

This function looks up the PDB entry associated with the numerical identifier id and writes the associated information into the entry parameter. As described in Section 3.3.5, a variable of type struct prcheckentry houses the entry’s externally-visible fields for the casual inquirer.

The underlying ubik-based PDB is manipulated under a read transaction, and is readlocked for the duration of the operation.

Error Codes

PRPERM The caller’s identity could not be established, or is not authorized to perform the operation.

PRNOENT A PDB entry matching id was not found.

PRDBBAD An error was found relating to the PDB.

3.6.6 PR DumpEntry — Get the contents of a PDB entry based on its offset (for debugging)

int PR DumpEntry(IN struct rx connection *z conn,
                       IN long pos,
                       OUT struct prdebugentry *entry)

Description

This routine returns the contents of the PDB entry located at byte offset pos within the replicated database, and is intended to be used only for debugging. The text of the entry is deposited into the buffer pointed to by entry. Note that the struct debugentry used for the entry argument is identical to the struct prentry which is used directory by the PDB (See Sections 3.3.2 and 3.3.4). Since the given offset may point in fact to a continuation entry instead of a main PDB entry, the caller must be prepared to interpret the contents of the entry argument, of type struct prdebugentry, as an object of type struct contentry, as described in Section 3.3.3.

The underlying ubik-based PDB is manipulated under a read transaction, and is readlocked for the duration of the operation.

Error Codes

PRDBBAD An error was found relating to the PDB.

3.6.7 PR ChangeEntry — Change an existing PDB entry’s ID, name, and/or owner

int PR ChangeEntry(IN struct rx connection *z conn,
                        IN long id,
                        IN char *name,
                        IN long oid,
                        IN long newid)

Description

This routine allows the caller to change one or more aspects of the user or group entry in the PDB whose numerical ID is id. An attempt to change the entry for any of

the reserved AFS IDs (ANYUSERID, AUTHUSERID, ANONYMOUSID, or SYSADMINID) will be

rejected. The new name, if any, to assign to the entry is held in name. If no name change is to be made, then the name argument may be set to the null string. In any case, the specified name may be no longer than PR MAXNAMELEN (64) characters long, including the trailing null. Similarly, the numerical ID of the entry’s (possibly new) owner is listed in the oid parameter. If no owner change is desired, oid is set to zero. Finally, a new numerical ID may be specified for the given entry in newid. If this is set to zero, then the entry’s ID will not be altered.

The caller will be allowed to make changes to a PDB entry under the following general conditions:

• They are the entry’s owner.

• They are a member of the system:administrators group.

• They are a member of the group which is the owner of the given entry.

• The Protection Server is running in its unauthenticated mode.

There are other specific conditions governing altering specific fields within the entry:

• The numerical ID may only be changed if the caller is a member of the built-in AFS administration group, system:administrators.

• The name and owner ID must be consistent with group naming rules following the requested changes unless the caller is a system administrator. Otherwise, PRBADNAM is returned.

• The entry’s owner may only be changed if the entry is for a group, not for an individual user.

The underlying ubik-based PDB is manipulated under a write transaction, and is writelocked for the duration of the operation.

Error Codes

PRPERM The caller’s identity could not be established, or is not authorized to perform the operation, or an attempt was made to change a group entry to a user entry (or vice versa), or an attempt was made to change a user entry’s owner, or an attempt was made to change a reserved ID.

PRNOENT A PDB entry matching id was not found.

PRIDEXIST The new ID specified by newid is already in use.

PRBADNAM An illegal name was provided for the new entry.

PRDBFAIL Reading or writing the given PDB entry failed.

PRDBBAD An error was found relating to the PDB.

3.6.8 PR SetFieldsEntry — Change miscellaneous fields in an existing PDB entry

int PR SetFieldsEntry(IN struct rx connection *z conn,
                          IN long id,
                          IN long mask,
                          IN long flags,
                          IN long ngroups,
                          IN long nusers,
                          IN long spare1,
                          IN long spare2)

Description

This function allows a caller to change one or more fields within the PDB entry matching the given user id. The mask argument is used to select which fields are to be changed. Legal values for this mask parameter are provided in Section 3.2.3. Depending on what has been selected, the values placed in the flags (setting the flag bits), ngroups (setting the group creation limit), and/or nusers (setting the foreign user limit) are inserted into the PDB entry. The remaining two arguments, spare1 and spare2, are not referenced, and are reserved for future expansion.

Attempting to alter the Protection Database entries for certain AFS IDs, namely ANYUSERID,

AUTHUSERID, ANONYMOUSID, and SYSADMIN are rejected.

The underlying ubik-based PDB is manipulated under a write transaction, and is writelocked for the duration of the operation.

Error Codes

PRPERM The caller’s identity could not be established, or is not authorized to perform the operation.

PRBADARG One or more of the values provided as arguments are illegal.

PRDBBAD An error was found relating to the PDB.

3.6.9 PR Delete — Delete an existing PDB entry

int PR Delete(IN struct rx connection *z conn,
                 IN long id)

Description

This operation is used to delete the PDB entry for the user or group whose ID is id. The caller must be either the entry’s owner, a member of the system:administrators group, or a member of the group listed as the entry’s owner for this function to succeed. Alternatively, the Protection Server will allow the operation if it is running in its unauthenticated mode.

Since this is a potentially long-lived operation, it may be split up into several ubik write transactions, with each one holding a write lock on the PDB. The processing of each continuation block (if any) for the entry is handled in a separate transaction. Similarly, a new transaction is generated for every 50 entries handled in the entry’s owned list. In addition, the lightweight Protection Server thread executing this call offers itself for rescheduling after handling each continuation block and after handling each group of 4 items in the owned list.

Error Codes

PRDBBAD An error was found relating to the PDB.

PRPERM The caller’s identity could not be established, or is not authorized to perform the operation, or tried to delete a reserved AFS ID.

PRNOENT A PDB entry matching id was not found.

PRDBFAIL The PDB could not be read from or written to successfully.

3.6.10 PR WhereIsIt — Get the PDB byte offset of the entry for a given ID

int PR WhereIsIt(IN struct rx connection *z conn,
                     IN long id,
                     OUT long *ps);

Description

This interface function will look up the PDB entry associated with the given numerical AFS id and return the byte offset into the replicated PDB file where the entry is located. This may be used in conjunction with the PR DumpEntry() call to examine the contents of the PDB at the given offset.

The underlying ubik-based PDB is manipulated under a read transaction, and is readlocked for the duration of the operation.

Error Codes

PRNOENT A PDB entry matching id was not found.

PRDBBAD An error was found relating to the PDB.

3.6.11 PR AddToGroup — Add a user to the chosen group

int PR AddToGroup(IN struct rx connection *z conn,
                        IN long uid,
                        IN long gid)

Description

This routine is used to add the given AFS uid to the group whose numerical identifier is gid. Note that group identifiers may not appear within a group.

The underlying ubik-based PDB is manipulated under a write transaction, and is writelocked for the duration of the operation.

Error Codes

PRPERM The caller’s identity could not be established, or is not authorized to perform the operation, or tried to add a member to one of the two special AFS built-in

        groups, system:anyuser and system:authuser, or tried to add ANONYMOUSID

to the group.

PRNOENT A PDB entry matching uid or gid was not found.

PRNOTUSER An attempt was made to add a group identifier to a group.

PRNOTGROUP The specified gid is not a group.

PRDBBAD An error was found relating to the PDB.

3.6.12 PR RemoveFromGroup — Remove a user from the chosen group

int PR RemoveFromGroup(IN struct rx connection *z conn,
                                IN long id,
                                IN long gid)

Description

This function allows the caller to remove the given AFS numerical id from the group identified by gid.

The underlying ubik-based PDB is manipulated under a write transaction, and is writelocked for the duration of the operation.

Error Codes

PRPERM The caller’s identity could not be established, or is not authorized to perform the operation, or tried to remove a member to one of the two special AFS built-in groups, system:anyuser and system:authuser, or tried to add

        ANONYMOUSID to the group.

PRNOENT A PDB entry matching id or gid was not found.

PRNOTUSER An attempt was made to remove a group identifier from the given group.

PRNOTGROUP An attempt was modify a PDB entry that does not describe a group.

PRDBBAD An error was found relating to the PDB.

3.6.13 PR ListMax — Get the largest allocated user/group ID

int PR ListMax(IN struct rx connection *z conn,
                   OUT long *uid,
                   OUT long *gid)

Description

This Protection Server interface routine places into its uid and gid arguments the largest allocated AFS numerical user and group IDs respectively.

The underlying ubik-based PDB is manipulated under a read transaction, and is readlocked for the duration of the operation.

Error Codes

PRDBBAD An error was found relating to the PDB.

3.6.14 PR SetMax — Set the largest allocated user/group ID

int PR SetMax(IN struct rx connection *z conn,
                  IN long id,
                  IN long gflag)

Description

This routine is used to set the value of either the highest-allocated AFS user or group to id. The gflag argument is set to a non-zero value if the given id is for a group, and to zero for an individual user. After successful completion of the call, the next invocation of PR NewEntry() will result in an ID of either (id+1) if the high watermark user ID was just set, or id-1) if the highest group ID was just set.

The underlying ubik-based PDB is manipulated under a write transaction, and is writelocked for the duration of the operation.

Error Codes

PRPERM The caller’s identity could not be established, or they are not authorized to perform the operation.

PRDBBAD An error was found relating to the PDB.

3.6.15 PR ListElements — List all IDs describign user/group membership

int PR ListElements(IN struct rx connection *z conn,
                        IN long id,
                        OUT prlist *elist,
                        OUT long *over)

Description

This interface function returns all of the IDs associated with the PDB entry whose ID is specified in the id argument. Basically, it returns the meaningful contents of the entries array in the associated struct prentry, along with the meaningful contents of the entries array from each chained continuation block (of type struct contentry). For a user id, the entries on this list represent the set of groups of which the user is a member. For a group id, the entries signify the list of users belonging to that group.

The IDs that appear in the elist list are sorted. If the size of the generated list has overflowed the maximum list size, PR MAXGROUPS (5,000), then the over argument is set to a non-zero value.

The underlying ubik-based PDB is manipulated under a read transaction, and is readlocked for the duration of the operation.

Error Codes

PRPERM The caller’s identity could not be established, or is not authorized to perform the operation.

PRNOENT A PDB entry matching id was not found.

PRDBBAD An error was found relating to the PDB.

This interface function is closely related to the PR GetCPS() routine. See Section 3.6.16 for a comparison of the two.

3.6.16 PR GetCPS — Get the CPS for the given ID

int PR GetCPS(IN struct rx connection *z conn,
                   IN long id,
                   OUT prlist *elist,
                   OUT long *over)

Description

Generate the Current Protection Subdomain, or CPS, for the AFS user with the given numerical id. Basically, the CPS is the closure of all identities that the given id can use. This list of groups and special AFS identities (e.g. ANYUSERID and AUTHUSERID) to which the specified user belongs is placed in the elist structure passed in as an argument to this routine. The user’s own ID also appears on this list.

The IDs that appear in the elist list are sorted. If the size of the list generated for the CPS has overflowed the maximum list size, PR MAXGROUPS (5,000), then the over argument is set to a non-zero value.

The underlying ubik-based PDB is manipulated under a read transaction, and is readlocked for the duration of the operation. As generating the CPS is a potentially lengthy operation, the lightweight Protection Server thread executing this call offers itself for rescheduling periodically. After processing the main PDB entry, the thread allows other active threads to run after handling every group of 50 IDs in a continuation block. This threading activity is completely invisible to the caller.

Error Codes

PRNOENT A PDB entry matching id was not found.

PRPERM The caller’s identity could not be established, or is not authorized to perform the operation.

PRDBBAD An error was found relating to the PDB.

3.6.17 PR ListOwned — List all IDs owned by the given ID

int PR ListOwned(IN struct rx connection *z conn,
                      IN long id,
                      OUT prlist *elist,
                      OUT long *over)

Description

This function lists the set of AFS IDs owned by the user or group entity whose ID is id. Basically, all IDs appearing in the linked list hanging from the owned field in the entity’s associated PDB entry are included. If the id parameter is set to zero, then the PDB orphan list is constructed. In this case, the IDs are taken from the list hanging from the orphan field from the PDB’s header. In either case, the resulting list is placed in the variable-length elist array.

The IDs that appear in the elist list are sorted. If the size of the generated list has overflowed the maximum list size, PR MAXGROUPS (5,000), then the over argument is set to a non-zero value.

The underlying ubik-based PDB is manipulated under a read transaction, and is readlocked for the duration of the operation.

Error Codes

PRPERM The caller’s identity could not be established, or is not authorized to perform the operation.

PRNOENT A PDB entry matching id was not found.

PRDBBAD An error was found relating to the PDB.

3.6.18 PR IsAMemberOf — Is a given user ID a member of a specified group?

int PR IsAMemberOf(IN struct rx connection *z conn,
                          IN long uid,
                          IN long gid,
                          OUT long *flag)

Description

This function sets its flag argument to a non-zero value if the user whose numerical ID is uid is a member of the gid group.

The underlying ubik-based PDB is manipulated under a read transaction, and is readlocked for the duration of the operation.

Error Codes

PRPERM The caller’s identity could not be established, or is not authorized to perform the operation.

PRNOENT A PDB entry matching uid or gid was not found.

PRBADARG The given uid is not an identifier for a user, or the given gid is not an identifier for a group.

PRDBBAD An error was found relating to the PDB.

Bibliography

[1] Transarc Corporation, AFS-3 Programmer’s Reference: BOS Server Interface, FS-00-D161, Pittsburgh, PA, June 1991

[2] CMU Information Technology Center. Synchronization and Caching Issues in the Andrew File System, USENIX Proceedings, Dallas, TX, Winter 1988.

[3] Transarc Corporation. AFS 3.0 Command Reference Manual, F-30-0-D103, Pittsburgh, PA, April 1990.

[4] Zayas, Edward R., Transarc Corporation. AFS-3 Programmer’s Reference: Specification for the Rx Remote Procedure Call Facility, FS-00-D164, Pittsburgh, PA, April 1991.

[5] Transarc Corporation. AFS 3.0 System Administrator’s Guide, F-30-0-D102, Pittsburgh, PA, April 1990.

[6] Kazar, Michael L., Information Technology Center, Carnegie Mellon University. Ubik - A Library For Managing Ubiquitous Data, ITCID, Pittsburgh, PA, Month, 1988.

[7] Kazar, Michael L., Information Technology Center, Carnegie Mellon University. Quorum Completion, ITCID, Pittsburgh, PA, Month, 1988.

Index

const ANONYMOUSID, 17, 31, 37, 39, 42, 43 const ANYUSERID, 17, 37, 39, 47 const AUTHUSERID, 17, 37, 39, 47 const COSIZE, 10, 16, 23, 24 const ENTRYSIZE, 16, 22, 23

const HASHSIZE, 16

const HIGHEST, 15 const LOWEST, 15 const PR MAXGROUPS, 16, 27, 46–48 const PR MAXLIST, 16, 26, 27, 31, 32 const PR MAXNAMELEN, 16, 23, 25, 26, 33,

37 const PR REMEMBER TIMES, 20, 22–24, 26

const PR SF ALLBITS, 16
const PR SF NGROUPS, 16
const PR SF NUSERS, 8, 16

const PRACCESS, 18, 19

const PRADDTOGROUP, 15
const PRBADARG, 28

const PRBADID, 17

const PRBADNAM, 28

const PRCELL, 8, 18

const PRCHANGEENTRY, 15

const PRCONT, 18

const PRDBADDR, 28

const PRDBBAD, 28

const PRDBFAIL, 28
const PRDBVERSION, 16
const PRDELETE, 15
const PRDUMPENTRY, 15

const PREXIST, 28 const PRFOREIGN, 8, 18 const PRFREE, 18

const PRGETCPS, 15

const PRGROUPEMPTY, 28

const PRGRP, 18

const PRIDEXIST, 28
const PRIDTONAME, 15
const PRINCONSISTENT, 28
const PRINEWUSER, 15

const PRINST, 18

const PRISAMEMBEROF, 15
const PRIVATE SHIFT, 18, 19
const PRLISTELEMENTS, 15
const PRLISTENTRY, 15
const PRLISTMAX, 15
const PRLISTOWNED, 15
const PRNAMETOID, 15
const PRNEWENTRY, 15

const PRNOENT, 28 const PRNOIDS, 28

const PRNOMORE, 28
const PRNOTGROUP, 28
const PRNOTUSER, 28
const PRP ADD ANY, 19
const PRP ADD MEM, 19
const PRP GROUP DEFAULT, 19
const PRP MEMBER ANY, 19
const PRP MEMBER MEM, 19
const PRP OWNED ANY, 19
const PRP REMOVE MEM, 19
const PRP STATUS ANY, 19
const PRP STATUS MEM, 19
const PRP USER DEFAULT, 19

const PRPERM, 28 const PRQUOTA, 18

const PRREMOVEFROMGROUP, 15
const PRSETFIELDSENTRY, 15

const PRSETMAX, 15

const PRSIZE, 10, 16, 21, 22, 24 const PRSRV, 16

const PRSUCCESS, 20
const PRTOOMANY, 28

const PRTYPE, 18 const PRUSER, 18

const PRWHEREISIT, 15

const SYSADMINID, 17, 37

const SYSADMIN, 39

CPS, 2, 7

file ptint.h, 14 file ptint.xg, 12, 14, 29 file ptopcodes.h, 15 file ptserver.h, 14, 28 function PR AddToGroup(), 15, 30, 42 function PR ChangeEntry(), 15, 30, 37 function PR Delete(), 15, 30, 40 function PR DumpEntry(), 15, 22, 24,

30, 36, 41 function PR GetCPS(), 15, 27, 30, 46, 47 function PR IDToName(), 15, 26, 27, 30,

32 function PR INewEntry(), 30, 34 function PR IsAMemberOf(), 15, 30, 49 function PR List(), 15 function PR ListElements(), 15, 27, 30,

46 function PR ListEntry(), 25, 30, 35 function PR ListMax(), 15, 20, 30, 44 function PR ListOwned(), 15, 20, 27, 30,

48 function PR NameToID(), 15, 26, 27, 30,

31 function PR NewEntry(), 15, 30, 33, 34 function PR NewUser(), 15 function PR RemoveFromGroup(), 15, 30,

43 function PR SetFieldsEntry(), 8, 15, 16,

18, 30, 39 function PR SetMax(), 15, 20, 30, 45 function PR WhereIsIt(), 15, 30, 41

group, 1, 2, 4

macro inc header word(), 29 macro set header word(), 28

orphan, 9 orphan list, 9

PDB, 1, 2, 4, 5, 8–12, 16–21, 23–25 privacy bits, 10

struct contentry, 23, 46

                                      struct prcheckentry, 25

struct prdebugentry, 8, 9, 24

struct prentry, 8, 9, 16, 18, 20, 21, 23–

25, 36, 46 struct prheader, 8–10, 20 switch, Protection Server -database, 12 switch, Protection Server -db, 12 switch, Protection Server -rebuild, 12 system:administrators group, 6, 8, 10, 11,

17, 19, 37, 40 system:anyuser group, 5–7, 11, 17, 42, 43 system:authuser group, 6, 17, 42, 43

typedef idlist, 27 typedef namelist, 26 typedef prlist, 27 typedef prname, 26

user, 1, 2, 4

Index  ii  August 28, 1991 12:16