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 ], NameDB USING [ GetAttribute ], 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, NameDB, PupHop, Rope, RPC, RPCInternal, UserProfile, VoiceUtils EXPORTS Agent = { OPEN IO; blockSize: NAT = SIZE[DESFace.Block]; 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; clientLarkHost: RPC.ShortROPE; pa: VoiceUtils.NetAddress; comment: Rope.ROPE _ NIL; dbInterfaceName: ROPE; pa _ VoiceUtils.nullNetAddress; pa.net _ clientMachine.net; pa.host _ clientMachine.host; clientInstance _ VoiceUtils.InstanceFromNetAddress[pa, "0"]; clientLarkHost _ VoiceUtils.InstanceFromNetAddress[pa, NIL]; clientRname _ NameDB.GetAttribute[clientLarkHost, $rname, NIL, $larkhost]; IF clientRname#NIL THEN { dbInterfaceName _ NameDB.GetAttribute[clientRname, $interface]; IF ~interfaceType.Equal[dbInterfaceName, FALSE] THEN comment _ comment.Concat[IO.PutFR["GV interface type is %s. ", rope[dbInterfaceName]]]; serverInstance _ NameDB.GetAttribute[clientRname, $instance] }; IF serverInstance=NIL THEN serverInstance _ defaultServerInstance; serverMachineRope _ NameDB.GetAttribute[serverInstance, $connect ]; IF serverMachineRope#NIL THEN { pa _ VoiceUtils.NetAddressFromRope[serverMachineRope]; serverMachine _ [net: pa.net, host: pa.host]; } ELSE comment _ comment.Concat["Instance has not been exported. "]; 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"]; }. AgentImpl.mesa Copyright Σ 1987 by Xerox Corporation. All rights reserved. Dan Swinehart April 2, 1987 6:23:27 pm PST Authentication Encrypt the whole thing for a's benefit Build and encrypt Authentication Binding Implements everything but range check 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 Swinehart, April 2, 1987 6:12:37 pm PST Adapt to new NameDB interface changes to: DIRECTORY, AgentImpl, Vitae, blockSize Κά˜™Icode™J˜+—Jšœ˜Jšœœ˜%Jšœœ˜Jšœœ˜&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šœ<˜˜B˜šœK˜MJšœW˜WJšœ ˜ ——Jšœ œœœ)˜QJšœ˜J˜——™J˜šžœ œ˜ JšœŸ˜:šœŸ˜:Jšœ˜—JšœB˜IJ™γJ˜,Jšœ'œœŸ˜XJ˜9Jšœ-œœ˜;J˜U˜šœC˜EJšœX˜X——J˜J˜——šœ™J˜šž œ˜$š˜JšœGœ ˜Y—šœœ˜+JšœZ˜Z—šœœ+˜>JšœJ˜J—Jšœ?œ˜I˜ J˜)J˜J˜—J˜MJšœ œ˜J˜——˜Jšœ˜—J˜™&K™Kšœ Οr/™;—™'K™Kšœ  &™2—K™K™—…—$#