DIRECTORY Agent USING [ Authentication, AuthenticationRecord, Authenticator, AuthenticatorLayout, Frob, FrobRecord, Machine, Principal ], AgentRpcControl USING [ ExportInterface, UnexportInterface ], Commander USING [ CommandProc, Register ], DESFace USING [ Block, Blocks, CBCCheckEncrypt, CorrectParity, EncryptBlock, GetRandomKey, Key, nullKey ], IO, LupineRuntime USING [ BindingError ], NamesGV USING [ AttributeSeq, GVGetAttribute, GVGetAttributeSeq, GVIsAuthenticated ], Pup USING [ Host, nullHost, nullNet ], PupHop USING [ GetRouting, RoutingTableEntry, unreachable ], Rope USING [ Concat, Equal, Length, Flatten, ROPE ], RPC USING [ EncryptionKey, ExportFailed, matchAllVersions, ShortROPE, VersionRange ], RPCInternal USING [ CopyPrincipal ], UserProfile USING [ Token ], VoiceUtils USING [ CmdOrToken, CurrentPasskey, InstanceFromNetAddress, MakeRName, NetAddress, NetAddressFromRope, nullNetAddress, Report, Problem ] ; AgentImpl: CEDAR PROGRAM IMPORTS AgentRpcControl, Commander, DESFace, IO, LupineRuntime, NamesGV, PupHop, Rope, RPC, RPCInternal, UserProfile, VoiceUtils EXPORTS Agent = { OPEN IO; blockSize: NAT = SIZE[DESFace.Block]; larkRegistry: Rope.ROPE _ ".Lark"; defaultServerInstance: Rope.ROPE _ UserProfile.Token[key: "ThrushServerInstance", default: "Morley.Lark"]; Authenticate: PUBLIC PROC [ nonceId: LONG INTEGER, a, b: Agent.Principal ] RETURNS [ an: Agent.Frob, ar: Agent.Frob ] = TRUSTED { ka, kb: DESFace.Key _ DESFace.nullKey -- !!! --; kx, ky, ck: DESFace.Key; aLen: NAT=a.Length[]; bLen: NAT=b.Length[]; authenticator: Agent.Authenticator; authentication: Agent.Authentication; nBlks: NAT _ DESBlocks[SIZE[Agent.AuthenticatorLayout[aLen]]]; IF a=NIL OR b=NIL OR aLen=0 OR bLen=0 THEN { VoiceUtils.Problem["Authenticate: Null arguments", $System]; RETURN[NIL, NIL]; }; ar _ NEW[Agent.FrobRecord[nBlks*blockSize]]; authenticator _ LOOPHOLE[@ar[0]]; a _ a.Flatten[]; b _ b.Flatten[]; DESFace.CorrectParity[@ka]; DESFace.CorrectParity[@kb]; kx _ DESFace.GetRandomKey[]; ky _ DESFace.GetRandomKey[]; ck _ DESFace.GetRandomKey[]; -- Build and encrypt Authenticator -- DESFace.EncryptBlock[key: kb, from: Blk[LONG[@ky]], to: Blk[@authenticator.ky ]]; DESFace.EncryptBlock[key: kb, from: Blk[LONG[@ck]], to: Blk[@authenticator.ck ]]; authenticator.time _ 0; RPCInternal.CopyPrincipal[from: a, to: @(authenticator.a)]; DESFace.CBCCheckEncrypt[key: ky, nBlks: nBlks-2, from: Blks[@authenticator.ck], to: Blks[@authenticator.ck], seed: [0,0,0,0] ]; DESFace.CBCCheckEncrypt[key: kx, nBlks: nBlks, from: Blks[@authenticator.ky], to: Blks[@authenticator.ky], seed: [0,0,0,0] ]; nBlks _ DESBlocks[SIZE[Agent.AuthenticationRecord[bLen]]]; an _ NEW[Agent.FrobRecord[nBlks*blockSize]]; authentication _ LOOPHOLE[@an[0]]; authentication.nonceId _ nonceId; DESFace.EncryptBlock[key: ka, from: Blk[LONG[@kx]],to: Blk[@authentication.kx] ]; DESFace.EncryptBlock[key: ka, from: Blk[LONG[@ck]], to: Blk[@authentication.ck ]]; RPCInternal.CopyPrincipal[from: b, to: @authentication.b]; DESFace.CBCCheckEncrypt[key: kx, nBlks: nBlks-2, from: Blks[@authentication.ck], to: Blks[@authentication.ck], seed: [0,0,0,0] ]; VoiceUtils.Report[IO.PutFR["Authenticate[%s, to; %s]", rope[a], rope[b]], $System]; }; DESBlocks: PROC[len: NAT] RETURNS [nBlks: NAT] = { RETURN [ (len + blockSize - 1) / blockSize ]; }; Blk: PROC[p: LONG POINTER] RETURNS [LONG POINTER TO DESFace.Block] = TRUSTED INLINE { RETURN [LOOPHOLE[p]]; }; Blks: PROC[p: LONG POINTER] RETURNS [DESFace.Blocks] = TRUSTED INLINE { RETURN [LOOPHOLE[p]]; }; Vitae: PUBLIC PROC[ clientMachine: Agent.Machine, range: RPC.VersionRange_RPC.matchAllVersions, interfaceType: RPC.ShortROPE ] RETURNS [ serverMachine: Agent.Machine_[[0],[0]], clientRname: Agent.Principal, clientInstance: RPC.ShortROPE_NIL, serverInstance: RPC.ShortROPE_NIL ] = TRUSTED { serverMachineRope: RPC.ShortROPE; clientMachineRName: RPC.ShortROPE; pa: VoiceUtils.NetAddress; interfaceSeq: NamesGV.AttributeSeq; comment: Rope.ROPE _ NIL; pa _ VoiceUtils.nullNetAddress; pa.net _ clientMachine.net; pa.host _ clientMachine.host; clientInstance _ VoiceUtils.InstanceFromNetAddress[pa, "0"]; clientMachineRName _ VoiceUtils.InstanceFromNetAddress[pa, larkRegistry]; SELECT NamesGV.GVIsAuthenticated[clientMachineRName] FROM bogus, nonexistent, unknown => comment _ "RName is unknown or invalid. "; authentic, perhaps => { clientRname _ NamesGV.GVGetAttribute[clientMachineRName, $owner, NIL]; interfaceSeq _ NamesGV.GVGetAttributeSeq[clientMachineRName, $interface]; IF interfaceSeq#NIL THEN { IF ~interfaceType.Equal[interfaceSeq[0].attributeValue, FALSE] THEN comment _ comment.Concat[IO.PutFR["GV interface type is %s. ", rope[interfaceSeq[0].attributeValue]]]; serverInstance _ interfaceSeq[1].attributeValue; }; IF serverInstance=NIL THEN serverInstance _ defaultServerInstance; serverMachineRope _ NamesGV.GVGetAttribute[ serverInstance, $connect, NIL ]; IF serverMachineRope#NIL THEN { pa _ VoiceUtils.NetAddressFromRope[serverMachineRope]; serverMachine _ [net: pa.net, host: pa.host]; } ELSE comment _ comment.Concat["Instance has not been exported. "]; }; ENDCASE=>ERROR; VoiceUtils.Report[ IO.PutFR["Vitae[lark: %b, type: %s] -> [ rName: %s, client: %s, server: %s]", card[clientMachine.host], rope[interfaceType], rope[clientRname], rope[clientInstance], rope[serverInstance]], $System]; IF comment#NIL THEN VoiceUtils.Report[IO.PutFR[" (%s)", rope[comment]], $System]; }; RoutingHostForHost: PUBLIC PROC[ clientMachine: Agent.Machine, -- Address of the requester. targetMachine: Agent.Machine -- Address of the destination ] RETURNS [routingMachine: Agent.Machine _ [Pup.nullNet, Pup.nullHost]] = { routingTableEntry: PupHop.RoutingTableEntry; IF clientMachine.net = targetMachine.net THEN RETURN[targetMachine]; -- why did you ask? routingTableEntry _ PupHop.GetRouting[targetMachine.net]; IF routingTableEntry.hop >= PupHop.unreachable THEN RETURN; routingMachine _ [routingTableEntry.immediate.net, routingTableEntry.immediate.host]; VoiceUtils.Report[ IO.PutFR["RoutingHostForHost[targetnet: %b] -> [ net: %b, host: %b]", card[clientMachine.net], card[routingMachine.net], card[routingMachine.host]], $System]; }; AgentInit: Commander.CommandProc = { ENABLE RPC.ExportFailed => { VoiceUtils.Problem["Agent export failed", $System]; GOTO Failed; }; instance: Rope.ROPE = VoiceUtils.MakeRName[ VoiceUtils.CmdOrToken[cmd: cmd, key: "AgentInstance", default: "Michaelson.Lark"], rName]; serverPassword: RPC.EncryptionKey = VoiceUtils.CurrentPasskey[ VoiceUtils.CmdOrToken[cmd: cmd, key: "AgentPassword", default: "MFLFLX"]]; AgentRpcControl.UnexportInterface[!LupineRuntime.BindingError=>CONTINUE]; AgentRpcControl.ExportInterface[ interfaceName: [ "Agent.Lark", instance], user: instance, password: serverPassword]; VoiceUtils.Report[IO.PutFR["Agent exported as %s", rope[instance]], $System]; EXITS Failed => NULL; }; Commander.Register["Agent", AgentInit, "Agent \nExport Registration/Authentication Agent"]; }. ΘProtocol agent services for Larks and other lightweights AgentImpl.mesa Dan Swinehart May 23, 1986 5:14:04 pm PDT Authentication Encrypt the whole thing for a's benefit Build and encrypt Authentication Binding Implements everything but range check An interface is "type, instance, versionStart, versionEnd" Routing Information From the client, what's the right host value to use in order to reach targetMachine. At present, this code assumes that clientMachine.net = localNet, which makes it possible to use the standard routing code in the Pup package. Initialization Swinehart, May 23, 1986 3:26:05 pm PDT Add RoutingHostForHost changes to: DIRECTORY , AgentImpl , Vitae , RoutingHostForHost  Κ ˜Jšœ8™8Jšœ™Jšœ)™)J˜šΟk ˜ šœœ(˜3J˜K—Jšœœ(˜=Jšœ œ˜*šœœ1˜>J˜+—Jšœ˜Jšœœ˜%JšœœH˜UJšœœ˜&Jšœœ0˜šœœœœœœœ˜,Jšœ=œœœ˜Q—Jšœœ$˜,Jšœœ ˜!J˜J˜J˜J˜J˜J˜J˜JšŸ%˜%Jšœ(œ%˜QJšœ(œ%˜QJ˜Jšœ;˜;˜PJ˜0—Jšœ'™'˜NJ˜0—Jšœ ™ Jšœœ$˜:Jšœœ$˜,Jšœœ ˜"˜!Jšœ(œ%˜QJšœ(œ&˜RJšœ:˜:J˜QJ˜2—J˜S˜J˜—š ž œœœœ œœ˜;J˜(—šžœœœœœœœœ˜EJšœœœ˜)—š žœœœœœ˜7Jšœœœ˜)J˜——šœ™J˜—šžœœœ˜Jšœ˜Jšœœœ˜-Jšœœ ˜šœ˜ Jšœ'˜'Jšœ˜Jšœœ œ˜"Jšœœ ˜!Jšœœ˜ J™%Jšœœ ˜!Jšœœ ˜"J˜J˜#Jšœœœ˜J˜J˜J˜Jšœ<˜JšœJ˜J—Jšœ?œ˜I˜ J˜)J˜J˜—J˜MJšœ œ˜J˜——˜Jšœ˜—J˜™&K™Kš œ Οr œ  œ  œ œ ™G—K™—…—p$X