a resource access protocol, and an agent monitoring. service. Security is a major concern in the design. of each of these services. The paper describes .... itself free to listen for further requests. The. ATP handler thread thus implements the ac-.
Agent Server Architecture for the Ajanta Mobile-Agent System Neeran M. Karnik and Anand R. Tripathi Department of Computer Science, University of Minnesota Minneapolis, MN 55455
Abstract
This paper provides an overview of Ajanta, a Java-based mobile-agent system, and focuses in particular on the architecture of the agent server { the process which hosts agents and enables them to access resources, communicate, migrate etc. The agent server's main components include an agent execution environment, an agent transfer protocol, a resource access protocol, and an agent monitoring service. Security is a major concern in the design of each of these services. The paper describes how a security architecture is integrated into the agent server design, and informally argues about its correctness based upon Java's security model.
Keywords: Mobile agents, Distributed computing, Java, Security
1 Introduction Mobile agent-based programming is a new paradigm for distributed processing, especially in large-scale heterogeneous networks such as the Internet. A mobile agent is a program that represents a user in a network, which can autonomously migrate from node to node. Applications inject mobile agents into a network to perform tasks on the user's behalf, allowing them to roam the network either on a predetermined path, or one that the agents themselves determine based on dynamically gathered information. The mobile agent paradigm introduces a higher level of abstraction in network programming { the programmer can use agents as active application components that traverse the network, performing computations rele-
vant to their location. It also helps optimize network bandwidth, by moving client code to network resources when appropriate, and permits increased asynchrony in client-server interactions[1]. Agents can provide value addition to existing services by dynamically extending their functionality. They can be used for electronic commerce, information search and ltering, network maintenance, testing, fault diagnosis and for software installation and upgrades on remote machines. Security and robustness are the primary concerns in deploying mobile agent systems. Each participating host needs to provide a facility for executing agents. This can potentially expose the host to attacks by malicious agents. Unless countermeasures are taken, such agents could leak, destroy or alter sensitive data. Conversely, agents themselves may be tampered with by malicious hosts. Thus, security mechanisms are necessary. Robustness concerns also require that an agent application have full control over its roaming agents. It should be able to monitor them, issue control commands, or recall them at any time, irrespective of their current location. This paper describes Ajanta, a Java-based mobile agent system that we are developing. Section 2 provides an overview of the Ajanta system, its architecture and various agent programming primitives. Sections 3 and 4 describe its secure mechanisms for agent transfer, execution and communication. Some related work is brie y reviewed in Section 5. We conclude with a summary and plans for future work.
2 Overview of Ajanta A network host can supply resources or services to mobile agents by running an agent server. Ajanta's generic agent server provides con ned environments for executing mobile agents, and allows the host to control access to its resources. It also makes some basic primitives available to programmers, such as those that allow agents to migrate to other servers, communicate with each other, query their environment, etc. Agent servers can be specialized to provide application-speci c services or resources, such as interfaces to databases, or electronic store-fronts. A set of such agent servers cooperatively implements the agent programming environment. Application programs can then create and dispatch agents to these servers, in order to access their resources. Agents are implemented in Ajanta as Java[2] objects which are active and mobile. An agent is active in the sense that it is assigned a thread which executes its code. Object mobility is implemented using Java's serialization facility, which allows us to capture an object's state, transmit it to some host, and recreate the object on that host. However the execution state of the agent's thread is not captured, since this would require modi cations to the Java virtual machine, rendering it incompatible with standard Java installations. Instead, when an agent migrates to a remote host, a new thread is assigned to execute it. An agent performs actions on behalf of a principal { an entity which has a unique identity in the system. Agents, hosts, agent servers and users are examples of principals in Ajanta. Each agent has an owner { the user whom the agent represents. An agent's credentials include its identity, owner, home site, code base, and any restrictions imposed on its rights. The home site may be used to report status information or to return a malfunctioning agent. The code base is a server responsible for providing any code that the agent needs, which is unavailable at its current host. These credentials are protected cryptographically, and are used by agent servers for access control. Each
principal in Ajanta needs a globally unique name which allows location-independent access. We have adopted the Uniform Resource Name (URN) framework[3] for object naming and we are developing a name resolution service to suit our needs.
2.1 Agent Server Structure AGENT Current
Itinerary
Resource
Proxy1
Proxy2
Code
State
(Methods)
(Internal Data)
M1
M2
M3
AccessProtocol
host
Credentials
Agent Environment Resource
Domain
Registry
Database
Agent Transfer
ATP
AGENT SERVER
Figure 1: The Ajanta Server Structure Figure 1 shows an agent server along with an agent currently resident on it. Each agent server has an agent environment object, which acts as the interface between visiting agents and the server. The server's domain database keeps track of agents currently executing on it, and responds to status queries from their owners. The agent transfer component implements a protocol that allows agents to migrate from host to host. A server may also provide application-speci c resources. A resource is an object that acts as an interface to some service or information available at the host. The server maintains a resource registry which is used in setting up safe bindings between resources and agents.
2.2 Agent Programming Primitives
An agent is written as a subclass of the systemde ned class Agent. Conceptually, it is a composite of its code and state. Its state includes
its credentials and a reference to the agent environment (called host in the gure). When an agent arrives at a server, its host reference is appropriately initialized before it starts executing. The agent environment provides services to agents in the form of primitives. These are described below. Agent creation simply involves instantiating a subclass of Agent. Typically, the creator provides it with a set of credentials, an itinerary of servers to visit, and other application-speci c data. A newly created agent is a passive object. It is activated by dispatching it to some agent server for execution, using the launch primitive. The programmer optionally speci es the method to be invoked and can pass parameters to it. If the method speci cation is omitted, the server executes a (parameterless) run method by default. An agent can request migration using the go primitive. It speci es the URN of the desired destination server, along with the method to be executed there. As before, the method speci cation is optional. The protocol followed by the agent server for performing the actual migration is described in Section 3. If it completes successfully, the go method never returns and the thread executing it is terminated. If however an error occurs during the transfer, an exception is thrown, allowing the agent to handle the error. In some situations, the agent may prefer to co-locate itself with another agent or resource that it needs to access. It can use the go primitive, specifying the URN of the co-location target. The go method invokes the name service to nd the current host server of the speci ed agent or resource, and sends the caller agent to that server. Ajanta provides a generic Resource interface, which must be extended to de ne application-speci c resources. An agent can access resources installed on its current server using the getResource primitive. The agent speci es the URN of the desired resource, which is then made available (using a proxybased access mechanism described in Section. 4.2), assuming that the resource's security
policy allows it. Agent communication can be implemented either using this resource access mechanism, or by installing a remotely callable proxy using the createRMIProxy primitive. This is elaborated on in Section 4.3.
3 Secure Agent Transfer Ajanta's agent transfer protocol (ATP) is cooperatively implemented by the sending and receiving agent servers. The sender serializes the agent and transmits it to the receiver, which must recreate the agent and execute it within a protection domain of its own. When an agent server is created, it starts up an ATP Listener thread, which listens for connections on a particular port. Given an agent server's URN, its host and ATP port can be determined by consulting the name service. The ATP listener creates an ATP Handler thread to handle each incoming connection, leaving itself free to listen for further requests. The ATP handler thread thus implements the actual agent transfer protocol. An agent's migration request contains a destination and a method speci cation. The sending server's transfer request contains the agent's credentials and this method speci cation, together with some parameters controlling the transfer itself { such as ags indicating whether the transfer should be encrypted or signed, the algorithms to be used for that purpose, etc. After executing a mutual authentication protocol which establishes the identities of the sending and receiving servers, the transfer request message is transmitted to the receiver's ATP listener. The credentials identify the agent requesting a transfer, thus allowing the destination server to decide whether to permit the transfer. If the transfer is permissible, the ATP handler sets up an execution environment for the incoming agent. The sending server then serializes the agent object and transmits it. It is received, deserialized and activated by the ATP handler. Note that the agent's code is not
transferred at this stage, but is loaded if necessary from its code base as explained in Section 4.1. Once the agent has been transferred, the receiving server sends an acknowledgment message back to the sender, which can then update the agent's location with the name service, and clean up its internal data structures to indicate that the agent is no longer hosted by it. If an error occurs before the agent can be activated, a negative acknowledgment is returned instead. The original server then informs the agent that its transfer request failed, by raising an exception.
4 Secure Agent Execution The two primary challenges in executing an agent securely are: the creation of a protection domain in which to isolate the agent, and the provision of a secure resource access protocol.
4.1 Protection Domains for Agents
We use two Java mechanisms for implementing protection domains: thread groups and class loading. A thread group in Java is a simple collection of threads. When an agent arrives, a new thread group is created for it. A single thread is created in this group, and is assigned the task of executing the method requested by the agent. During its execution, the agent may create other threads, but it is constrained to create them within its own thread group. Thus, any thread executing that agent's code can be identi ed by its thread group id. The agent server maintains a domain database indexed by thread group ids, in which it stores the agent's URN and credentials, as well as a reference to the agent object itself. This entry is used by the server's code whenever it needs access to the agent or its identity { e.g. when an agent attempts to acquire a resource, its credentials are needed to determine the level of access permitted. We use Java's class loader mechanism to protect agents from each other. The Java virtual machine associates with each class, the class loader instance that loaded it. Two
classes loaded by dierent loaders may have the same name, but are considered dierent types. This implies that objects of the two classes are not type-compatible, even if the classes are in fact identical. In eect, a class loader de nes its own namespace. Each agent is assigned a unique class loader instance. Whenever the agent's code encounters an object reference whose class is not currently loaded, the Java virtual machine invokes the agent's class loader, and provides it the name of the required class. The class loader rst searches the server's classpath { a set of directories on the local le system which contain classes trusted by the server. If the required class is found on the classpath, it is loaded into the virtual machine. Otherwise, the agent's code base is contacted and asked to supply the missing class. This communication may be encrypted and digitally signed to ensure the integrity of the downloaded code. Since each agent has its own class loader, a malicious agent cannot replace any other agent's classes with its own impostor versions.
Agent Activation: When an agent trans-
fer connection is initiated, the ATP handler thread rst reads the transfer request message from the sender. This contains the credentials of the agent being transferred. The handler consults the server's security policy to determine whether to allow the transfer to continue. If the agent is not permitted to execute on the server, the connection is aborted. Otherwise, the ATP handler creates a thread group, a new thread in that group, and a new class loader for the agent. An entry for the agent is made into the domain database. The newly created thread uses a bootstrap mechanism to transfer control into the new class loader's namespace. It then deserializes the agent object from the incoming connection, and sets the agent's host reference to the local server's agent environment (see Fig. 1). Finally, it transfers control to the agent, by invoking the method in the transfer request.
4.2 Secure Resource Access Agents need access to both system-level and application-de ned resources as they execute. The server must grant access only to authorized agents, and then only to the extent permitted by their privileges. System-level resources are protected in Java using the security manager which encodes security policy. All Java library calls which access system resources rst invoke the security manager to screen the access. For application-level resources however, we avoid burdening the security manager further, since every new resource added to the system would necessitate extending the security manager, making it a large, uncohesive module prone to errors (and thereby, security loopholes). Therefore, we need a mechanism which allows the agent server to provide a secure language-level binding between agents and resources. Each resource must be allowed to de ne its own security policy, and control its implementation.
its propagation from one agent to another by checking each invocation of the proxy to verify the protection domain to which it was originally granted. Thus, a proxy can act as an identity-based capability[6]. public interface Resource { // generic methods, common to all resources } public class ResourceImpl implements Resource { // implementations of the generic methods } public interface AccessProtocol { public Resource getProxy (Credentials cred); }
Figure 2: Generic Resource Interface Resource
AccessProtocol
Proxy-based Resource Access: In Ajanta,
agents are not provided with direct references to resources { we interpose a proxy[4] between a resource and its clients (i.e., agents). When an agent makes a request to access a resource, the server returns a proxy object, which contains a private reference to the actual resource. The proxy implements the same interface as the resource it represents; however during proxy construction, some of the interface methods may be disabled, based on its security policy and the client's credentials. For permitted methods, the proxy simply passes the invocation through to the embedded resource. Since the agent only has a reference to the proxy, its restricted interface ensures that the agent can only access the resource through the permitted methods. A separate proxy is created for each agent, although the embedded resource may be shared if appropriate. This approach oers other advantages. One can embed usage-metering and accounting mechanisms[5] in a proxy. Also, even though the proxy is like a capability, we can limit
ResourceImpl
BufferImpl
KEY:
class interface
Buffer
BufferProxy
implementation inheritance interface inheritance
Figure 3: Class Hierarchy for Buer Resource
Resource Access Protocol: Ajanta de-
nes a
Resource interface, and provides a ResourceImpl class which implements it (see
Fig. 2). This class provides generic functionality common to all resources, such as resource naming and ownership. Application-de ned resources implement the Resource interface, usually by simply inheriting the ResourceImpl class. For example, Fig. 3 shows the class hierarchy for a Buffer resource interface and its implementation. The resource binding protocol is de ned in terms of generic Resource objects so as to make it application-independent. In order to make itself securely available to agents, a resource class must also implement
the system-de ned AccessProtocol interface, i.e., a getProxy method. When an agent requests a resource, the getProxy method of that resource is executed, which returns an instance of its proxy class. Thus, for each applicationde ned resource class, a corresponding proxy class must be available (e.g. the BufferProxy class in Fig. 3). It may be automatically generated from the resource interface using a simple lexical processing tool. The getProxy method creates a new instance of the proxy class customized for the caller agent, by initializing access control information embedded in the proxy, based on the caller's credentials and the resource's security policy. In order to allow dynamic modi cation of access control, a proxy class provides additional operations to enable or disable resource interface methods. These operations are privileged, i.e. only a thread in the agent server's protection domain is allowed to execute them; thus, agents cannot tamper with the proxy objects allocated to them.
Resource Request Protocol: Each agent
server maintains a resource registry to facilitate binding between its resources and agents. For each resource, the registry contains the URN and a reference to the resource object, besides other information such as resource ownership. To obtain access to any resource, an agent invokes the getResource method on its host object supplying the URN of the desired resource. The server nds the corresponding object in the resource registry and makes an \upcall" to its getProxy method, providing the calling agent's credentials as a parameter. The resource object then creates an appropriately restricted proxy, and passes it back. This interposition of the proxy between the agent and the resource remains transparent to the agent.
4.3 Agent Communication
Two agents located on the same server can utilize this proxy-based resource access mechanism to communicate among themselves. An agent class can implement the Resource and
interfaces and register itself with the server as a resource. Co-located agents may also communicate via shared access to a resource on their server. However, in many applications, agents residing on dierent servers need to communicate or synchronize with each other. Thus a remotely invocable communication mechanism is necessary. Java provides the RMI mechanism for remote communication. However, if an agent is allowed to present an RMI interface, it opens up a security loophole. The agent itself may be granted access to certain resources, but the RMI interface provides a conduit to leak information to unauthorized principals. We need to authenticate incoming and outgoing connections, so as to control the set of principals which have indirect access to a resource. The proxy interposition concept is used to control incoming connections; outgoing connections are monitored by the security manager. An agent wishing to make itself available for remote invocation uses the createRMIProxy primitive, to request its server to install an RMI proxy for a speci ed interface. If the server can nd a proxy class appropriate for that interface, it creates a proxy instance (containing an embedded reference to the agent) and registers it with the local RMI registry under the agent's name. If the appropriate proxy is not available locally, the request would fail { the agent's code base is not trusted to provide a safe proxy class. The trusted proxy ensures that information will not be leaked to unauthorized callers. Incoming RMI invocations are intercepted by the proxy, which passes the call to the agent and relays the results back to the caller. If authentication of the caller is necessary, the proxy delivers an exception to the caller, which is expected to make another RMI call supplying its identity. Authentication then proceeds using a challenge-response mechanism using a random nonce [7]. AccessProtocol
4.4 Potential Threats The scheme presented above is now examined against potential threats of various kinds
of attacks. We introduce some additional rules, based on Java's security model, to guard against these threats and ensure the integrity of the scheme. A proxy contains an embedded reference to the resource object. The agent may attempt to directly (or via re ection) invoke the methods of this object, bypassing the proxy's access control checks. To prevent this, we rely on Java's encapsulation mechanism, by declaring the embedded resource reference as private. If the proxy object could be typecast to another type which bypassed the access control checks for each method, the agent could gain unauthorized access to the resource. In our scheme however, we enforce the rule that a proxy class has no ancestors apart from the base Object class. Thus, Java will not allow the agent to typecast the proxy instance to any other class. When the agent arrives across the network, it typically also provides its own code base. In doing so, it may attempt to install its own version of the proxy class, which bypasses access control checks or makes the embedded resource publicly available. However, Ajanta's class loader makes sure that the proxy class is only loaded from the classpath. A malicious agent could serialize a proxy, transmit the byte stream to a cooperative agent server and deserialize it using a fake proxy class, thus exposing the underlying resource. We prevent this by enforcing the rule that the resource reference within a proxy class must be declared as transient. Java does not include transient references in the byte stream generated by object serialization. The agent, having followed the proper protocol to obtain a proxy, may attempt to clone it. While this does not result in the cloning of the underlying resource, it can aect accounting and revocation mechanisms built into the proxy. To avoid this, we enforce the rule that the proxy class does not implement the Cloneable interface. Java does not allow the cloning of any object which does not implement this interface.
5 Related Work Most existing mobile-agent systems do not pay particular attention to security and robustness in their designs. Telescript[8] however has language-level mechanisms for security. It uses dierent types of permits for access control and for imposing quotas on resource use. Security mix-in classes can be used to protect objects from unauthorized modi cation, copying or migration. The Aglets Workbench[9] has only primitive security functionality. However a security architecture for this system has recently been proposed[9]. Agent Tcl[10] supports access control lists based on host names and uses PGP for encryption and authentication. In Ara[11], agent servers use access control lists (called \allowances") to impose restrictions on visiting agents. For protecting access to resources, our approach is based on the concept of proxies, which was rst developed by Shapiro[4]. We use proxies to act as capabilities. A proxy may include the identity of the client, and thus act as an identity-based capability[6]. One of the contributions of our work lies in supporting proxy-based capabilities whose integrity can be assured based on Java's security model. The protection scheme described in [12] has some conceptual similarities to our approach. Both schemes use proxy objects acting as capabilities, instead of direct access to resources. In [12], the restricted interfaces of such proxy classes (called lters) are statically de ned, independently by clients and servers. These lters are integrated with the resource interface de nitions; this allows the system to automatically create and interpose appropriate lter objects in client-server interactions. In contrast, our scheme supports dynamic de nition and modi cation of the access privileges assigned to an agent through a proxy. Moreover, we can argue about the integrity of our scheme based on Java's security model and present a speci c set of design rules to guard against potential attacks.
6 Conclusions In Ajanta, a Java-based mobile agent system, we build upon Java's security model and provide a con ned execution environment for each agent, protecting it from tampering by other agents. We have also built a ne-grained access control mechanism for resources based on proxy interposition. A similar mechanism is used to enable remote invocation of an agent, thus allowing the agent's creator to control it remotely. Applications can de ne their own security policies for agent transfer, resource access as well as agent-to-agent communication. An area for future work is auditability, i.e., we need to provide a mechanism to reliably determine the migration history of an agent. This is required by the agent application to determine the level of trust that can be placed in the agent's results. We also plan to implement some real-world applications which can exercise Ajanta's security and robustness features, and demonstrate the utility of the agent paradigm.
References [1] C. Harrison, D. Chess, and A. Kershenbaum. Mobile Agents: Are they a good idea? Technical report, IBM Research Division, T.J.Watson Research Center, March 1995. [2] J. Gosling, W. Joy, and G. Steele. The Java Language Speci cation. AddisonWesley, August 1996. [3] K. Sollins and L. Masinter. RFC 1737: Functional Requirements for Uniform Resource Names. http://www.cis.ohiostate.edu/htbin/rfc/rfc1737.html, December 1994. [4] M. Shapiro. Structure and Encapsulation in Distributed Systems: The Proxy Principle. In Proceedings of the 6th International Conference on Distributed Computing Systems, pages 198{204, 1986.
[5] B.C. Neuman. Proxy-based authorization and accounting for distributed systems. In Proceedings of the Thirteenth International Conference on Distributed Computing Systems, pages 283{291, May 1993. [6] Li Gong. A Secure Identity-Based Capability System. In IEEE Symposium on Security and Privacy, pages 56{63, May 1989. [7] R. Needham and M. Schroeder. Using Encryption for Authentication in Large Networks of Computers. Communications of the ACM, 21(12):993{999, December 1978. [8] J. Tardo and L. Valente. Mobile Agent Security and Telescript. In Proceedings of COMPCON Spring '96, pages 58{63, 1996. [9] G. Karjoth, D. Lange, and M. Oshima. A Security Model for Aglets. IEEE Internet Computing, pages 68{77, July-August 1997. [10] R. Gray. Agent Tcl: A exible and secure mobile-agent system. In Proceedings of the 4th Tcl/Tk Workshop, July 1996. [11] H. Peine and T. Stolpmann. The Architecture of the Ara Platform for Mobile Agents. In Proceedings of the 1st International Workshop on Mobile Agents. Springer Verlag, LNCS #1219, April 1997. [12] D. Hagimont and L. Ismail. A Protection Scheme for Mobile Agents on Java. In Proceedings of the 3rd International Conference on Mobile Computing and Networking, September 1997.