UserCredentials.mesa
last edited by Levin on September 22, 1983 12:02 pm
DIRECTORY
IO: TYPE USING [STREAM],
Rope: TYPE USING [ROPE];
UserCredentials: CEDAR DEFINITIONS =
BEGIN
This interface manages the credentials (Grapevine RName and password) of the human sitting at the terminal. It provides facilities for authentication of the individual and protection of the contents of the local disk against unauthorized access.
The individual must supply his credentials once per power-on of his machine. The credentials are retained by the system across world-swaps, rollbacks, and boots. The credentials are discarded only under the following circumstances: (1) the user leaves the Cedar world entirely (e.g., by returning to the Alto world), (2) the machine is powered off, (3) the user deliberately instructs the system to forget his credentials (e.g., by pressing the Idle button). These events delimit sessions, at least from the standpoint of credentials lifetime. Once the credentials have been discarded, the system will normally require that they be supplied and authenticated before any access to the disk is permitted.
State: TYPE = MACHINE DEPENDENT {
noCredentials(0), name(1), nameHint(2), nameAndPassword(3)};
The credentials are stored on disk in a private location that is not part of any logical volume. The information stored there may be in one of the forms indicated by "State".
"noCredentials" means that the disk area has never been initialized or that it holds credentials in an obsolete format from a previous, incompatible Cedar release.
"name" means that the user's name is stored on the disk and that Login (see below) will accept only the named individual. Furthermore, the password supplied at Login time must be acceptable to Grapevine. (If Grapevine is unavailable, the password must match the last password for this individual that Grapevine acknowledged as correct.)
"nameHint" means that any individual registered with Grapevine may successfully log in, but the system retains the credentials of the individual who did so most recently on this machine.
"nameAndPassword" is functionally similar to "name" except that both name and password are stored on the disk in unencrypted form and that Login will prompt for credentials only if Grapevine rejects the ones stored on disk.
GetState: PROC RETURNS [State];
This procedure returns the present form of the credentials stored on the disk.
ChangeState: PROC [new: State] RETURNS [old: State];
This procedure permits the form of the credentials stored on the disk to be changed. If "new" is other than State[noCredentials], the name and/or password stored on the disk will be obtained from Get (see below), which may not produce the same values as are on the disk at the time ChangeState is called.
LoginOptions: TYPE = RECORD [
confirmCredentialsOverwrite: BOOLFALSE,
'confirmCredentialsOverwrite' is interrogated by Login only if it finds missing or obsolete credentials information on the disk. If 'confirmCredentialsOverwrite' is TRUE, Login will give the user the opportunity to retain the disk state untouched. Otherwise, Login will force the state to be either 'name' or 'nameHint', asking the user which he wants.
prohibitDiskProtection: BOOLFALSE,
If 'prohibitDiskProtection' is TRUE, Login will not to offer the user the opportunity to set the disk credentials state to 'name'.
ignoreDiskEntirely: BOOLFALSE,
If 'ignoreDiskEntirely' is TRUE, Login will bypass any attempt to access or rewrite the disk credentials ('confirmCredentialsOverwrite' is therefore ignored in this case).
alwaysInteract: BOOLFALSE,
If 'alwaysInteract' is TRUE, Login will interact with the user to acquire the credentials, even if the user was already satisfactorily logged in.
reserved: [0..7777B] ← 0
];
defaultOptions: LoginOptions = [];
Login: PROC [
startInteraction: PROC RETURNS [in, out: IO.STREAM],
endInteraction: PROC [in, out: IO.STREAM],
options: LoginOptions ← defaultOptions];
The detailed behavior of this procedure depends on the present state of the private disk area used to store credentials (see description of "State", above). Login is prepared to find the credentials area in any of the four states.
If the initial state is "noCredentials", Login will prompt the user for a Grapevine RName and password, which it then presents to Grapevine for authentication. (The details of prompting are described below.) Once a valid set of credentials is supplied, Login asks if the desired final state is "name" or "nameHint" and rewrites the credentials area accordingly. (See the descriptions of the LoginOptions "confirmCredentialsOverwrite" and "prohibitDiskProtection" for exceptions to this behavior.)
If the initial state is "nameHint", Login prompts as for "noCredentials", then (unless options.ignoreDiskEntirely is TRUE) rewrites the credentials area in State[nameHint] using the name and password supplied.
If the initial state is "name", Login prompts for the password only, obtaining the user name from the disk. This combination of name and password must be acceptable to Grapevine.
If the initial state is "nameAndPassword", Login obtains both name and password from the disk and presents them to Grapevine. If they are rejected as invalid, Login acts as though the initial state were "name".
At the completion of Login, the successfully authenticated credentials are available through the Get procedure (see below).
If, when Login is invoked, Get[].name.Length[] = 0, it behaves exactly as just described. If, however, it finds Get[].name.Length[] > 0 (and options.alwaysInteract is FALSE), Login bypasses all of the above processing and returns without inspecting the disk credentials area. Thus, once credentials have been established using Login, they remain in effect until discarded by one of the circumstances described earlier. If every Cedar environment sharing the disk on this machine calls Login before it permits the user access to any information stored on the disk, a strong guarantee of disk privacy can be made (assuming GetState[] = name).
If Login needs to interact with the user, it first calls "startInteraction" to obtain two stream for character I/O. When interaction has completed, Login calls "endInteraction", enabling the initial supplier of the streams to clean up. Login never retains the streams across calls. "endInteraction" is called if and only if "startInteraction" is. The "in" stream is assumed to deliver characters one-at-a-time and without echoing anywhere. The "in" stream is expected to provide GetChar; the "out" stream is expected to provide PutChar and EraseChar.
If Login needed to interact with the user, it invokes the registered CredentialsChangeProcs (see RegisterForChange) upon completion of the Login sequence.
Get: PROC RETURNS [name, password: Rope.ROPE];
This procedure returns the current values of the user name and password. If Login has not yet been called, both name and password will be NIL. The same values will be returned in all Cedar environments on this machine, independent of boot, rollback, or world-swap. These credentials will remain in effect until the next call of Login.
CredentialsChangeProc: TYPE = PROC [clientData: REF ANY];
RegisterForChange: PROC [proc: CredentialsChangeProc, clientData: REF ANYNIL];
This procedure registers a client-supplied procedure to be invoked when the credentials maintained by the implementation of this interface change. See the description of Login for the circumstances under which this occurs.
UnRegisterForChange: PROC [proc: CredentialsChangeProc, clientData: REF ANYNIL];
This procedure undoes the effect of a previous RegisterForChange.
END.