Many potential applications of Jini require network security. Although various third parties have made proprietary security extensions to Jini, until now the only security available to users of the standard Jini release is the security infrastructure of the Java platform. The Jini Community's Davis project is about to change that. Bob Scheifler is leading the development of the next release of Jini, in which security is the central concern, as part of the Davis project.
On Friday, April 12, 2002 Bill Venners visited the Sun Microsystems campus in Burlington, Massachusettes and interviewed Bob Scheifler, Sun Distinguished Engineer and architect in the Jini Group. In Part I of this interview, Scheifler discusses the need for security in Jini and the special security considerations of dynamically downloaded code. In Part II, Scheifler describes the mechanisms used to determine whether a proxy should be trusted. In Part III, Scheifler covers the mechanisms used to achieve object integrity. In Part IV, Scheifler discusses security constraints and the RemoteSecurity
interface. In this fifth installment of the interview, Scheifler describes the dynamic granting of permissions to proxies.
Bill Venners: How do clients dynamically grant permissions to proxies at runtime?
Bob Scheifler: You have to decide if you trust the proxy, then you have to decide what you will allow the proxy to do. That is the process of authorization, where you grant permissions in the standard Java model. You authorize by granting permissions. Somehow we have to grant the proxy permissions dynamically.
We have to grant permissions dynamically for a couple of reasons. One is that in the standard Java security model you grant permissions to a code base or to URLs. But in the Jini world, you don't want to have to know where the code came from. That should be an implementation detail.
Say you are a service, and I have a proxy from you. I don't want to have to know what URL you serve code from. One reason I can't do a static grant is I generally don't know where your code comes from. I don't want to grant permissions to code from anywhere because that would be granting to untrusted code. And even if I know where your code is now, you might change your mind later about whether that is really the trusted code or not. What I really want to do is wait until after I have decided I trust the proxy before I grant it any permission. If I grant it permissions before I decide I trust it, then it may have already abused those permissions behind my back and already done damage.
From the time I unmarshal that object, if I have already granted it permissions, it can already exercise those permissions while it is being unmarshalled. So I want to make sure that I don't grant it any permissions until after I decide I trust it. That is where the dynamic granting comes into play. I don't want to characterize these permissions in a static security policy. At runtime I get a proxy from somewhere. I decide I trust it. And then I want to grant it permissions.
Bill Venners: How do I grant permissions dynamically?
Bob Scheifler: You might say I want to grant permissions to the proxy object. But the Java security model doesn't have a notion of granting permissions to objects. Its notion is that you grant permissions to protection domains. So now you have to look at how the Java security model defines a protection domain. In J2SE 1.4 the notion of a protection domain has been extended to include principals and class loaders. In part it was extended precisely for the Jini security model. A protection domain now has three components: principals, code source, and class loader. The principals indentify who is executing the code. The code source is the traditional notion of where the code came from, a URL, and who signed the code. The class loader is an actual class loader object that loaded the code.
Since we can't grant to the object, we grant to the class loader of the object's class. The class loader essentially equates to the code base. You don't have to know the actual code base because you can grant to the class loader.
Bill Venners: Is each JAR file loaded by one class loader?
Bob Scheifler: Each code base is loaded by one class loader. You have a code base with a whole bunch of URLs in it, or a JAR file with a bunch of class path URLs. There is one-to-one mapping between code base and class loader.
Bill Venners: If I have a JAR file that I load from some URL, and it has in it class path URLs to other JAR files, would those JAR files be loaded by the same class loader?
Bob Scheifler: That is still the same class loader. The basic assumption is that all of the subsidiary objects in your proxy will be objects from the same class loader or from a parent class loader. So I get this proxy object. I decide I trust it. Then I propagate some of my permissions to it by propagating to the combination of principals and class loader. We expect the normal case to be that every thread executes code on behalf of some subject.
Bill Venners: What's the difference between a subject and a principal?
Bob Scheifler: A subject is a container that has principals and their credentials. Credentials prove you are the principals. If I am a client that makes a remote call to you, I will authenticate to you. The basis of that authentication is the subject that the client's thread executes under. The set of potential principals that I might authenticate as are the principals in the subject. I will prove the identity of those principals with the credentials in the subject.
Bill Venners: Every thread operates on behalf of one subject.
Bob Scheifler: Typically, yes. It is actually a little more complicated than that. The leaf-most executed subject is the one you will use for authentication. There is essentially a notion of a current subject for a thread.
Bill Venners: What do you mean by leaf-most?
Bob Scheifler: There may be a cascade of subjects executing. I might say execute this code as Bob, but that code says execute this subsidiary code as Alice. Are you both Bob and Alice at that point? The answer is no. You are just Alice. But Bob is still there in the sense that when you finish executing as Alice, you start executing again as Bob. At the time we do a dynamic grant, we grant not just to the class loader, but also to the combination of the principals of the current subject and the class loader. If you have a simple application that you only execute as one identity, it doesn't matter that you grant to the subject. It only matters when you have a virtual machine in which different threads execute as different identities either because you have multiple services that share a VM or you have a service that executes code as client identity for the client.
You must make sure you don't step on each other toes. Both Bob and Alice run on the same VM. The fact that Bob decides to trust the proxy doesn't mean that Alice should trust the proxy.
Bill Venners: They may have the same proxy.
Bob Scheifler: They may have the same proxy, but they want to segregate who trusts whom for that purpose. Tying it to principals is the way that you can do that segregation. So the dynamic policy mechanism is to say in addition to the standard Java security policy object, we implemented an additional interface that allows us to do these dynamics grants.
Bill Venners: Are you assuming all these proxies will be stubs? One of the nice things about Jini is there's a choice as to how to implement service interfaces. They can be completely implemented locally, or partly locally, partly remotely, or maybe it's a remote object and the proxy is just a stub.
Bob Scheifler: Jini security is not just for stubs. It certainly includes smart proxies. Part of the trust mechanism goes back and asks the server if it trusts a potentially smart proxy where you have downloaded code. If you look JERI (Jini Extensible Remote Invocation) and secure JERI, in most cases we have gotten rid of stubs. We use java.lang.reflect.proxy
to do dynamically generated stubs. So in those cases, you might argue that you would not be actually downloading a stub. It will all be local code. But we are definitely catering to smart proxies.
Now the interesting case that you brought up is if my service proxy is a completely local object with no remote back end. How do I decide I trust it? The mechanism that I described doesn't give you a way because there is nobody at the other end to ask if it trusts the proxy.
Bill Venners: A proxy that's completely implemented locally could still give a bootstrap object that goes across and gets a verifier. Once the proxy is verified, the service could be fully implemented locally.
Bob Scheifler: There still has to be somebody at the other end whose identity I think I know in order to ask that question.
The Jini Community, the central site for signers of the Jini Sun Community Source Licence to interact:
http://www.jini.org
To get involved in the Davis project, in which Jini security is being defined, go to:
http://davis.jini.org/
Have an opinion? Be the first to post a comment about this article.
Bill Venners is president of Artima Software, Inc. and editor-in-chief of Artima.com. He is author of the book, Inside the Java Virtual Machine, a programmer-oriented survey of the Java platform's architecture and internals. His popular columns in JavaWorld magazine covered Java internals, object-oriented design, and Jini. Bill has been active in the Jini Community since its inception. He led the Jini Community's ServiceUI project that produced the ServiceUI API. The ServiceUI became the de facto standard way to associate user interfaces to Jini services, and was the first Jini community standard approved via the Jini Decision Process. Bill also serves as an elected member of the Jini Community's initial Technical Oversight Committee (TOC), and in this role helped to define the governance process for the community. He currently devotes most of his energy to building Artima.com into an ever more useful resource for developers.
Artima provides consulting and training services to help you make the most of Scala, reactive
and functional programming, enterprise systems, big data, and testing.