CHLookUpImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Bill Jackson (bj) October 9, 1986 4:59:39 am PDT
DIRECTORY
AuthenticationP14V2,
Basics USING [LongNumber],
CHEntriesP0V0 USING [addressList],
CHNameP2V0,
ClearinghouseP2V2,
CrRPC,
IO,
RefText,
Rope USING [Equal, FromRefText, InlineFetch, Length, ROPE, SkipTo, Substr],
UserCredentials USING [Get],
XNS USING [Address, broadcastHost, broadcastNet, unknownAddress],
XNSWKS USING [clearinghouse],
CHLookUp;
CHLookUpImpl: CEDAR MONITOR
IMPORTS ClearinghouseP2V2, CrRPC, IO, RefText, Rope, UserCredentials
EXPORTS CHLookUp ~ {
Copied Types
Address: TYPE ~ XNS.Address;
Credentials: TYPE ~ AuthenticationP14V2.Credentials;
DomainName: TYPE ~ CHNameP2V0.DomainName;
DomainNameSequence: TYPE ~ ClearinghouseP2V2.DomainNameSequence;
DomainNameSequenceObject: TYPE ~ ClearinghouseP2V2.DomainNameSequenceObject;
Handle: TYPE ~ CrRPC.Handle;
Item: TYPE ~ ClearinghouseP2V2.Item;
Name: TYPE ~ CHNameP2V0.Name;
NetworkAddress: TYPE ~ ClearinghouseP2V2.NetworkAddress;
NetworkAddressList: TYPE ~ ClearinghouseP2V2.NetworkAddressList;
NetworkAddressListObject: TYPE ~ ClearinghouseP2V2.NetworkAddressListObject;
ROPE: TYPE ~ Rope.ROPE;
SimpleVerifier: TYPE ~ AuthenticationP14V2.SimpleVerifier;
Private Types
CedarCredentials: TYPE ~ ClearinghouseP2V2.Authenticator;
Global State
cedarDummy: ROPE ~ "CedarDummy";
defaultName: Name ← ["Xerox", "Parc", NIL];
domainsFound: LIST OF DomainNameSequence ← NIL;
localCHS: Address ← XNS.unknownAddress;
Errors
Error: PUBLIC ERROR [msg: ROPE] ~ CODE;
Procs
AddressFromRope: PUBLIC PROC [pattern: ROPE] RETURNS [address: Address, distinguishedObject: Name] ~ {
user: CedarCredentials ← PickUpCedarCredentials[];
h: Handle;
name: Name ← NameFromRope[pattern, defaultName];
domain: DomainName ← [organization~name.organization, domain~name.domain];
IF (NOT ValidCHS[localCHS, domain]) THEN localCHS ← LocateCHS[domain];
h ← CrRPC.CreateClientHandle[$SPP, localCHS];
[address, distinguishedObject] ← RetrieveAddress[h, name, user];
CrRPC.DestroyClientHandle[h];
};
AddressListValue: PUBLIC PROC [item: Item] RETURNS [list: NetworkAddressList ← NIL] ~ {
len: NAT ~ (item.length / SIZE[NetworkAddress]);
reportedLength: NAT ← 0;
word: NAT ← 0;
GetNetworkAddress: PROC RETURNS [addr: NetworkAddress] ~ {
addr.network[0] ← item[word+0];
addr.network[1] ← item[word+1];
addr.host[0] ← item[word+2];
addr.host[1] ← item[word+3];
addr.host[2] ← item[word+4];
addr.socket ← item[word+5];
word ← word + SIZE[NetworkAddress]; -- 6
};
reportedLength ← item[word];
word ← word+1;
IF (len # reportedLength) THEN ERROR;
IF (len < 1) THEN RETURN;
list ← NEW [NetworkAddressListObject[len]];
FOR i: NAT IN [0..len) DO
list[i] ← GetNetworkAddress[];
ENDLOOP;
};
AuthCredentials: PUBLIC PROC [c: Name] RETURNS [a: Credentials] ~ TRUSTED {
lenOrg: NAT ~ MIN [Rope.Length[c.organization], ClearinghouseP2V2.maxOrganizationLength];
lenDom: NAT ~ MIN [Rope.Length[c.domain], ClearinghouseP2V2.maxDomainLength];
lenObj: NAT ~ MIN [Rope.Length[c.object], ClearinghouseP2V2.maxObjectLength];
size: NAT ~ HWords[lenOrg] + HWords[lenDom] + HWords[lenOrg] + 3;
finger: NAT ← 4; -- skip size & lenOrg
wordfinger: NAT ← 0;
b: LONG POINTER TO PACKED ARRAY [0..200) OF CHAR; -- 200 >> (20+20+40)*2 + 6>> (2*size)
a.type ← simple;
a.value ← NEW [AuthenticationP14V2.SeqWordsObject[size]];
b ← LOOPHOLE[a.value];
a.value[wordfinger] ← lenOrg;
FOR i: NAT IN [0..lenOrg) DO
b[(i+finger)] ← Rope.InlineFetch[c.organization, i];
ENDLOOP;
b[(lenOrg+finger)] ← 0C; -- IF (lenOrg MOD 2 = 1) THEN
wordfinger ← wordfinger + HWords[lenOrg];
a.value[wordfinger] ← lenDom;
finger ← finger + (HWords[lenOrg] * 2);
FOR i: NAT IN [0..lenDom) DO
b[(i+finger)] ← Rope.InlineFetch[c.domain, i];
ENDLOOP;
b[(lenDom+finger)] ← 0C; -- IF (lenDom MOD 2 = 1) THEN
wordfinger ← wordfinger + HWords[lenDom];
a.value[wordfinger] ← lenObj;
finger ← finger + (HWords[lenDom] * 2);
FOR i: NAT IN [0..lenObj) DO
b[(i+finger)] ← Rope.InlineFetch[c.object, i];
ENDLOOP;
IF (lenObj MOD 2 = 1) THEN b[(lenObj+finger)] ← 0C;
};
CHAddressToXNSAddress: PUBLIC PROC [in: NetworkAddress] RETURNS [address: Address] ~ {
address.net ← LOOPHOLE [in.network];
address.host ← LOOPHOLE [in.host];
address.socket ← LOOPHOLE [in.socket];
};
FindCHServer: PROC [h: Handle] RETURNS [answer: Address ← XNS.unknownAddress] ~ {
PutArgs: CrRPC.PutArgsProc ~ { NULL };
GetResults: CrRPC.GetResultsProc ~ {
n: CARDINAL ← CrRPC.GetCARDINAL[h];
IF ( (n > 0) AND (answer = XNS.unknownAddress) ) THEN {
addr: NetworkAddress;
addr.network[0] ← CrRPC.GetCARDINAL[h];
addr.network[1] ← CrRPC.GetCARDINAL[h];
addr.host[0] ← CrRPC.GetCARDINAL[h];
addr.host[1] ← CrRPC.GetCARDINAL[h];
addr.host[2] ← CrRPC.GetCARDINAL[h];
addr.socket ← CrRPC.GetCARDINAL[h];
answer ← CHAddressToXNSAddress[addr];
};
};
CrRPC.Call[h, 2, 2, 0, PutArgs, GetResults
! CrRPC.Error => CONTINUE];
};
FindServer: PROC RETURNS [answer: XNS.Address ← XNS.unknownAddress] ~ {
h: Handle;
h ← CrRPC.CreateClientHandle[$EXCHANGE, [XNS.broadcastNet, XNS.broadcastHost, XNSWKS.clearinghouse]];
{
FOR hops: CARDINAL IN [0..4) DO
h ← CrRPC.SetHops[h, hops, hops];
h ← CrRPC.SetTimeout[h, (200 + (300*hops))];
THROUGH [0..4) DO
IF ( (answer ← FindCHServer[h]) # XNS.unknownAddress ) THEN GOTO Found;
ENDLOOP;
ENDLOOP;
EXITS
Found => NULL;
};
CrRPC.DestroyClientHandle[h];
};
HashPassword: PUBLIC PROC [password: ROPE] RETURNS [hashVal: SimpleVerifier ← 0] ~ {
len: NAT ~ Rope.Length[password];
FOR i: NAT IN [0..len) DO
acc: Basics.LongNumber;
c: CHAR ← Rope.InlineFetch[password, i];
SELECT c FROM
IN ['A .. 'Z] => c ← c + ('a - 'A);
ENDCASE;
acc.hi ← hashVal;
acc.lo ← ORD[c];
hashVal ← (acc.lc MOD 65357);
ENDLOOP;
};
HWords: PROC [bytes: NAT] RETURNS [hWords: NAT] ~ INLINE {
hWords ← (bytes + 3) / 2;
};
LocateCHS: PUBLIC PROC [context: DomainName] RETURNS [chs: Address ← XNS.unknownAddress] ~ {
IF (chs = XNS.unknownAddress) THEN {
chs ← FindServer[];
};
IF (NOT ValidCHS[chs, context]) THEN {
Error["I'm not that smart!"];
};
};
PickUpCedarCredentials: PUBLIC PROC RETURNS [user: CedarCredentials] ~ {
name: ROPE;
passwd: ROPE;
username: Name ← defaultName;
[name, passwd] ← UserCredentials.Get[];
username.object ← Rope.Substr[name, 0, Rope.SkipTo[name, 0, "."]];
user.credentials ← AuthCredentials[username];
user.verifier ← NEW [AuthenticationP14V2.SeqWordsObject[1]];
user.verifier.body[0] ← HashPassword[passwd];
};
RetrieveAddress: PUBLIC PROC [h: Handle, object: Name, user: CedarCredentials] RETURNS [address: XNS.Address ← XNS.unknownAddress, distinguishedObject: Name] ~ {
ENABLE {
ClearinghouseP2V2.ArgumentError => {
SELECT TRUE FROM
(problem = noSuchObject) => Error["Name not found!"];
ENDCASE => Error["Unknown Argument Error!"];
};
ClearinghouseP2V2.PropertyError => {
SELECT TRUE FROM
(problem = missing) => Error["No Address for this object!"];
(problem = wrongType) => Error["Wrong type!"];
ENDCASE => Error["Unknown Property Error!"];
};
};
value: Item;
addresses: NetworkAddressList;
[distinguishedObject, value] ← ClearinghouseP2V2.RetrieveItem[h, object, CHEntriesP0V0.addressList, user];
addresses ← AddressListValue[value];
IF (addresses # NIL) THEN address ← CHAddressToXNSAddress[addresses[0]];
};
NameFromRope: PUBLIC PROC [rope: ROPE, defaultName: Name] RETURNS [result: Name] ~ {
len: NAT ~ Rope.Length[rope];
pos: NAT ← 0;
GetField: PROC [default: ROPE] RETURNS [field: ROPE] ~ {
startPos: NAT ← pos;
field ← default;
IF (startPos >= len) THEN RETURN;
pos ← Rope.SkipTo[rope, startPos, ":"];
IF (pos = startPos) THEN RETURN;
field ← Rope.Substr[rope, startPos, (pos-startPos)];
pos ← pos + 1;
};
result.object ← GetField[defaultName.object];
result.domain ← GetField[defaultName.domain];
result.organization ← GetField[defaultName.organization];
};
ValidCHS: PUBLIC PROC [chs: Address, context: DomainName] RETURNS [yes: BOOLFALSE] ~ {
agent: CedarCredentials ~ PickUpCedarCredentials[];
h: Handle;
GetCARDINAL: PUBLIC PROC [in: IO.STREAM] RETURNS [c: CARDINAL] ~ {
c1: CHARIO.GetChar[in];
c2: CHARIO.GetChar[in];
c ← (c1.ORD*256) + c2.ORD;
};
GetROPE: PUBLIC PROC [in: IO.STREAM] RETURNS [rope: ROPE] ~ {
text: REF TEXT;
len: CARDINAL;
len ← GetCARDINAL[in];
text ← RefText.ObtainScratch[len];
FOR i: INT IN [0 .. len) DO
text ← RefText.AppendChar[text, IO.GetChar[in]]
ENDLOOP;
IF ( (len MOD 2) = 1) THEN [] ← IO.GetChar[in]; -- zero byte
rope ← Rope.FromRefText[text];
RefText.ReleaseScratch[text];
};
GetDomainNameSequence: PROC [in: IO.STREAM] RETURNS [dns: DomainNameSequence] ~ {
length1: CARDINAL ~ GetCARDINAL[in];
dns ← NEW [DomainNameSequenceObject[length1]];
FOR i0: CARDINAL IN [0..length1) DO
dns.body[i0].organization ← GetROPE[in];
dns.body[i0].domain ← GetROPE[in];
ENDLOOP;
};
DomainSink: CrRPC.BulkDataSink ~ {
semantics here are StreamOfDomainName per XSIS 078404 Appendix F.
domainNameSequence: DomainNameSequence;
kind: NAT ← 0;
WHILE (kind = 0) DO
IF (checkAbort[h]) THEN RETURN;
kind ← GetCARDINAL[stream];
domainNameSequence ← GetDomainNameSequence[stream];
domainsFound ← CONS [domainNameSequence, domainsFound];
ENDLOOP;
abort ← FALSE;
};
Equiv: PROC [l, r: DomainName] RETURNS [yup: BOOLFALSE] ~ {
IF (NOT Rope.Equal[l.domain, r.domain, FALSE]) THEN RETURN;
yup ← Rope.Equal[l.organization, r.organization, FALSE];
};
IF (chs = XNS.unknownAddress) THEN RETURN;
h ← CrRPC.CreateClientHandle[$SPP, chs];
domainsFound ← NIL;
ClearinghouseP2V2.ListDomainServed[h, DomainSink, agent]; -- sic
CrRPC.DestroyClientHandle[h];
FOR each: LIST OF DomainNameSequence ← domainsFound, each.rest WHILE (each # NIL) DO
FOR i: NAT IN [0..each.first.length) DO
IF (Equiv[each.first[i], context]) THEN RETURN [TRUE];
ENDLOOP;
ENDLOOP;
};
}...