 |
A question about SocketPermissions
Posted by joshy on September 20, 2007 at 10:44 AM | Comments (5)
I'm going to abuse my celebrity and world renowned fame today (world renowned means the 5 mile radius around my house, right?). I have a technical question to ask my wonderful audience of readers (who are all beautiful, smart, and above average). I've looked through the Javadocs and some tutorials without understanding a few details, so here goes.
How do SocketPermissions imply each other?
Some background. I have code which opens a connection to a URL. When the connection is opened I am using security managers to catch it and approve certain URLs and deny others. The user should be able to specify at init or on the fly what URLs they want to approve using a dialog box. The security manager is getting requests for SocketPermissions like this: www.yahoo.com connect,resolve. So far so good.
The problem is that opening the URL actually produces multiple requests. For example yahoo.com will request yahoo.com, www.yahoo.com, yahoo.com:80, www.yahoo.com:80, 192.168.1.1 and 192.168.1.1:80. (or whatever the ip address for yahoo really is). That's all fine and dandy, except that I don't want to have to ask the user multiple times for permission. They should be able to say: Allow yahoo.com and all other requests should be allowed from that. So how can I do this?
I have looked at the docs for SocketPermission.implies() and run a few tests. It seems that foo.com implies foo.com:80, but not the reverse. And the ip address does not imply the domain and vice versa. So how can I do approve a full URL connection to foo.com without bombarding the user with requests?
Thanks guys. I know my readership is smart and talented enough to answer this question with one hand tied behind their backs, hanging upside down, over a lake of fire, and with a mouth full of peanut butter. :)
Bookmark blog post: del.icio.us Digg DZone Furl Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment
-
You disencourage people, who do not have an answer to your question, to leave a comment. I will post anyway, I hope it does not bring your hopes up. I don't have an answer, but would like to know it myself. :)
Posted by: fatihc on September 20, 2007 at 11:24 AM
-
I think I may have an idea...
Before activating the URL, call url.openConnection().getPermission().
Place the Permission in a collection and only prompt the user for Permission's that are in that collection.
Example:
URL url = new URL("http://yahoo.com");
URLConnection conn = url.openConnection();
sm.perms.add(conn.getPermission());
conn.getContent();
Posted by: locust on September 20, 2007 at 05:20 PM
-
grant {
permission java.net.SocketPermission "*.yahoo.com:80", "connect";
};
works for me.
So I think what you need to do, is:
get the host using url.getHost()
if the host is a DNS name, then extract from it a 2nd level domain, that is from java.sun.com you get sun.com
Then ask the user to allow either the full DNS name or all names based on the extracted 2nd level domain
if the user allows the full name, then grant SocketPermission(hostname+":"+url.getPort(),"connect")
if the user allows all hosts based on this 2nd level domain, then grant SocketPermission("*." +secondLvlDomain+":"+url.getPort(),"connect")
open the URL
HTH
Posted by: rullrich on September 20, 2007 at 06:17 PM
-
Thank you for your help. I have *.foo.com:80 matching www.foo.com and www.foo.com:80. However, I can't figure out how to match the ip address from the domain. Any thoughts on that?
Posted by: joshy on September 21, 2007 at 10:06 AM
-
Yeah matching the IP can be a problem. For a real world example check out http://heise.de/ and try to use a SocketPermission for *.heise.de. You will then see that my proposal doesn't work all the time. It depends on the (reverse) DNS setup for IPs in question. Run the following code, and you will see what I'm talking about:
public static void main(String[] args) throws Exception {
nslookup( "heise.de");
nslookup( "yahoo.com");
}
private static void nslookup(String host) throws UnknownHostException {
InetAddress[] ia =
new InetAddress[]{InetAddress.getAllByName(host)[0]};
String cname =
InetAddress.getByName(ia[0].getHostAddress()).getHostName().
toLowerCase();
System.out.printf("host=[%s] ia=[%s] cname=[%s]%n", host, ia[0].getHostAddress(), cname);
}You should see something like this:host=[heise.de] ia=[193.99.144.80] cname=[193.99.144.80]
host=[yahoo.com] ia=[216.109.112.135] cname=[w2.rc.vip.dcn.yahoo.com]So as you can see in the case of heise.de the SocketPermission will not be able to match the wildcarded host name expression with a cname from a reverse lookup and hence the Permission will fail. (It would even fail, if the reverse lookup would return a cname of "heise.de"). The solution in the case of heise.de simply is to add an additional SocketPermission for "heise.de", which will allow resolving heise.de and due to a direct IP address comparison also to connect to 193.99.144.80.This will however not help in all cases. You might find servers out there which have an IP with a reverse name that has no resembling to the name for which it was delivered as result of a DNS lookup. Such addresses will never match a wildcard expression.However, there is a solution, but that is to complicated to completely describe it in this crappy comment field. It works something like this: Write a Policy-Implementation that decorates the existing Policy. This Policy should then intercept all permission checks for SocketPermission. Every time a check for a SocketPermission with a DNS name as target succeeds, this policy should use InetAddress#getAllByName to lookup the addresses for the requested host and then dynamically grant those adresses with the same actions as requested. I have some code which is halfway there, if you're interested I will complete it and post it somewhere.
Posted by: rullrich on September 21, 2007 at 02:59 PM
|