-->

Odd Wildcard Behavior in java.net.SocketPermission

2019-09-02 05:39发布

问题:

I'm trying to get a Java security policy right. My code needs to resolve and connect to both login.salesforce.com and xx99.salesforce.com where xx99 can take any of about 100 different values.

It works if I hardcode specific hosts - e.g.

permission java.net.SocketPermission "login.salesforce.com:443", "connect, resolve";
permission java.net.SocketPermission "na30.salesforce.com:443", "connect, resolve";

But this would lead to me adding about 100 entries to my security policy file to cover all the possibilities, and Salesforce add new instances all the time, making maintenance a nightmare.

It works if I wildcard any host/port:

permission java.net.SocketPermission "*", "connect, resolve";

But the obvious answer fails - this

permission java.net.SocketPermission "*.salesforce.com:443", "connect, resolve";

gives me

2016-03-20 22:19:56,024 [user:*admin] [pipeline:Pipeline1] [thread:preview-pool-1-thread-1] WARN  Pipeline - Stage 'com_streamsets_stage_destination_waveanalytics_WaveAnalyticsDTarget_1' initialization error: java.security.AccessControlException: access denied ("java.net.SocketPermission" "login.salesforce.com:443" "connect,resolve")
java.security.AccessControlException: access denied ("java.net.SocketPermission" "login.salesforce.com:443" "connect,resolve")
    at java.security.AccessControlContext.checkPermission(AccessControlContext.java:472)
    at java.security.AccessController.checkPermission(AccessController.java:884)
    at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
    at java.lang.SecurityManager.checkConnect(SecurityManager.java:1051)
    at sun.net.www.http.HttpClient.openServer(HttpClient.java:510)
    ...etc...

Been staring at this for some time now - I just don't get it!

回答1:

So this question led me in the right direction. Stepping through the JDK source code, it resolves the hostname, then does a reverse lookup, and does a bunch of checks to prevent spoofing. The problem is login.salesforce.com...

Let's resolve login.salesforce.com:

$ dig login.salesforce.com

; <<>> DiG 9.8.3-P1 <<>> login.salesforce.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 28719
;; flags: qr rd ra; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;login.salesforce.com.      IN  A

;; ANSWER SECTION:
login.salesforce.com.   2288    IN  CNAME   login.gslb2.salesforce.com.
login.gslb2.salesforce.com. 57  IN  A   136.147.59.44
login.gslb2.salesforce.com. 57  IN  A   136.147.57.172
login.gslb2.salesforce.com. 57  IN  A   136.147.58.44
login.gslb2.salesforce.com. 57  IN  A   136.147.58.172

OK - let's do a reverse lookup on that first IP address:

$ nslookup 136.147.59.44
Server:     192.168.69.1
Address:    192.168.69.1#53

Non-authoritative answer:
44.59.147.136.in-addr.arpa  name = dcl7-dfw.login-dfw.salesforce.com.

Authoritative answers can be found from:

Huh - ok, let's resolve that hostname:

$ dig dcl7-dfw.login-dfw.salesforce.com

; <<>> DiG 9.8.3-P1 <<>> dcl7-dfw.login-dfw.salesforce.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 26165
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;dcl7-dfw.login-dfw.salesforce.com. IN  A

;; Query time: 35 msec
;; SERVER: 192.168.69.1#53(192.168.69.1)
;; WHEN: Thu Apr 28 13:25:56 2016
;; MSG SIZE  rcvd: 51

At this point, the JDK tries to compare the IP address it's holding (136.147.59.44) against the wildcard policy (*.salesforce.com) and, unsurprisingly, determines that they don't match.

So, I'm stuck with "*" in the policy.