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 ~ { 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; CedarCredentials: TYPE ~ ClearinghouseP2V2.Authenticator; cedarDummy: ROPE ~ "CedarDummy"; defaultName: Name _ ["Xerox", "Parc", NIL]; domainsFound: LIST OF DomainNameSequence _ NIL; localCHS: Address _ XNS.unknownAddress; Error: PUBLIC ERROR [msg: ROPE] ~ CODE; 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: BOOL _ FALSE] ~ { agent: CedarCredentials ~ PickUpCedarCredentials[]; h: Handle; GetCARDINAL: PUBLIC PROC [in: IO.STREAM] RETURNS [c: CARDINAL] ~ { c1: CHAR _ IO.GetChar[in]; c2: CHAR _ IO.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 ~ { 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: BOOL _ FALSE] ~ { 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; }; }... CHLookUpImpl.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Bill Jackson (bj) October 9, 1986 4:59:39 am PDT Copied Types Private Types Global State Errors Procs semantics here are StreamOfDomainName per XSIS 078404 Appendix F. Κ \˜codešœ™Kšœ Οmœ1™Kš žœžœ žœžœžœ˜;Kšœ1žœ˜8Kšœ˜K˜—Kšžœžœžœžœ˜*Kšœ(˜(Kšœžœ˜Kšœ: ˜@Kšœ˜K˜š žœžœžœ.žœ žœž˜Tšžœžœžœž˜'Kšžœ!žœžœžœ˜6Kšžœ˜—Kšžœ˜—Kšœ˜K˜——K˜K˜K˜—…—$φ2T