author | redestad |
Tue, 03 May 2016 15:50:54 +0200 | |
changeset 37781 | 71ed5645f17c |
parent 37593 | 824750ada3d6 |
child 41579 | c0fe2e6364d9 |
permissions | -rw-r--r-- |
2 | 1 |
/* |
23010
6dadb192ad81
8029235: Update copyright year to match last edit in jdk8 jdk repository for 2013
lana
parents:
15000
diff
changeset
|
2 |
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. |
2 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
5506 | 7 |
* published by the Free Software Foundation. Oracle designates this |
2 | 8 |
* particular file as subject to the "Classpath" exception as provided |
5506 | 9 |
* by Oracle in the LICENSE file that accompanied this code. |
2 | 10 |
* |
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
5506 | 21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
2 | 24 |
*/ |
25 |
||
26 |
package sun.net.www.protocol.http; |
|
27 |
||
28 |
import java.util.Iterator; |
|
29 |
import java.util.HashMap; |
|
37593
824750ada3d6
8154231: Simplify access to System properties from JDK code
redestad
parents:
29986
diff
changeset
|
30 |
import sun.net.www.*; |
824750ada3d6
8154231: Simplify access to System properties from JDK code
redestad
parents:
29986
diff
changeset
|
31 |
import sun.security.action.GetPropertyAction; |
2 | 32 |
|
33 |
/** |
|
34 |
* This class is used to parse the information in WWW-Authenticate: and Proxy-Authenticate: |
|
35 |
* headers. It searches among multiple header lines and within each header line |
|
36 |
* for the best currently supported scheme. It can also return a HeaderParser |
|
37 |
* containing the challenge data for that particular scheme. |
|
38 |
* |
|
39 |
* Some examples: |
|
40 |
* |
|
41 |
* WWW-Authenticate: Basic realm="foo" Digest realm="bar" NTLM |
|
42 |
* Note the realm parameter must be associated with the particular scheme. |
|
43 |
* |
|
44 |
* or |
|
45 |
* |
|
46 |
* WWW-Authenticate: Basic realm="foo" |
|
47 |
* WWW-Authenticate: Digest realm="foo",qop="auth",nonce="thisisanunlikelynonce" |
|
48 |
* WWW-Authenticate: NTLM |
|
49 |
* |
|
50 |
* or |
|
51 |
* |
|
52 |
* WWW-Authenticate: Basic realm="foo" |
|
53 |
* WWW-Authenticate: NTLM ASKAJK9893289889QWQIOIONMNMN |
|
54 |
* |
|
55 |
* The last example shows how NTLM breaks the rules of rfc2617 for the structure of |
|
56 |
* the authentication header. This is the reason why the raw header field is used for ntlm. |
|
57 |
* |
|
58 |
* At present, the class chooses schemes in following order : |
|
59 |
* 1. Negotiate (if supported) |
|
60 |
* 2. Kerberos (if supported) |
|
61 |
* 3. Digest |
|
62 |
* 4. NTLM (if supported) |
|
63 |
* 5. Basic |
|
64 |
* |
|
65 |
* This choice can be modified by setting a system property: |
|
66 |
* |
|
67 |
* -Dhttp.auth.preference="scheme" |
|
68 |
* |
|
69 |
* which in this case, specifies that "scheme" should be used as the auth scheme when offered |
|
70 |
* disregarding the default prioritisation. If scheme is not offered then the default priority |
|
71 |
* is used. |
|
72 |
* |
|
73 |
* Attention: when http.auth.preference is set as SPNEGO or Kerberos, it's actually "Negotiate |
|
74 |
* with SPNEGO" or "Negotiate with Kerberos", which means the user will prefer the Negotiate |
|
75 |
* scheme with GSS/SPNEGO or GSS/Kerberos mechanism. |
|
76 |
* |
|
77 |
* This also means that the real "Kerberos" scheme can never be set as a preference. |
|
78 |
*/ |
|
79 |
||
80 |
public class AuthenticationHeader { |
|
81 |
||
82 |
MessageHeader rsp; // the response to be parsed |
|
83 |
HeaderParser preferred; |
|
84 |
String preferred_r; // raw Strings |
|
2942
37d9baeb7518
6578647: Undefined requesting URL in java.net.Authenticator.getPasswordAuthentication()
weijun
parents:
2
diff
changeset
|
85 |
private final HttpCallerInfo hci; // un-schemed, need check |
2 | 86 |
|
87 |
// When set true, do not use Negotiate even if the response |
|
88 |
// headers suggest so. |
|
89 |
boolean dontUseNegotiate = false; |
|
90 |
static String authPref=null; |
|
91 |
||
92 |
public String toString() { |
|
93 |
return "AuthenticationHeader: prefer " + preferred_r; |
|
94 |
} |
|
95 |
||
96 |
static { |
|
37781
71ed5645f17c
8155775: Re-examine naming of privileged methods to access System properties
redestad
parents:
37593
diff
changeset
|
97 |
authPref = GetPropertyAction.privilegedGetProperty("http.auth.preference"); |
2 | 98 |
|
99 |
// http.auth.preference can be set to SPNEGO or Kerberos. |
|
100 |
// In fact they means "Negotiate with SPNEGO" and "Negotiate with |
|
101 |
// Kerberos" separately, so here they are all translated into |
|
102 |
// Negotiate. Read NegotiateAuthentication.java to see how they |
|
103 |
// were used later. |
|
104 |
||
105 |
if (authPref != null) { |
|
106 |
authPref = authPref.toLowerCase(); |
|
107 |
if(authPref.equals("spnego") || authPref.equals("kerberos")) { |
|
108 |
authPref = "negotiate"; |
|
109 |
} |
|
110 |
} |
|
111 |
} |
|
112 |
||
113 |
String hdrname; // Name of the header to look for |
|
114 |
||
115 |
/** |
|
116 |
* parse a set of authentication headers and choose the preferred scheme |
|
117 |
* that we support for a given host |
|
118 |
*/ |
|
119 |
public AuthenticationHeader (String hdrname, MessageHeader response, |
|
2942
37d9baeb7518
6578647: Undefined requesting URL in java.net.Authenticator.getPasswordAuthentication()
weijun
parents:
2
diff
changeset
|
120 |
HttpCallerInfo hci, boolean dontUseNegotiate) { |
37d9baeb7518
6578647: Undefined requesting URL in java.net.Authenticator.getPasswordAuthentication()
weijun
parents:
2
diff
changeset
|
121 |
this.hci = hci; |
2 | 122 |
this.dontUseNegotiate = dontUseNegotiate; |
123 |
rsp = response; |
|
124 |
this.hdrname = hdrname; |
|
29986
97167d851fc4
8078467: Update core libraries to use diamond with anonymous classes
darcy
parents:
25859
diff
changeset
|
125 |
schemes = new HashMap<>(); |
2 | 126 |
parse(); |
127 |
} |
|
128 |
||
2942
37d9baeb7518
6578647: Undefined requesting URL in java.net.Authenticator.getPasswordAuthentication()
weijun
parents:
2
diff
changeset
|
129 |
public HttpCallerInfo getHttpCallerInfo() { |
37d9baeb7518
6578647: Undefined requesting URL in java.net.Authenticator.getPasswordAuthentication()
weijun
parents:
2
diff
changeset
|
130 |
return hci; |
37d9baeb7518
6578647: Undefined requesting URL in java.net.Authenticator.getPasswordAuthentication()
weijun
parents:
2
diff
changeset
|
131 |
} |
2 | 132 |
/* we build up a map of scheme names mapped to SchemeMapValue objects */ |
133 |
static class SchemeMapValue { |
|
134 |
SchemeMapValue (HeaderParser h, String r) {raw=r; parser=h;} |
|
135 |
String raw; |
|
136 |
HeaderParser parser; |
|
137 |
} |
|
138 |
||
10596
39b3a979e600
7090158: Networking Libraries don't build with javac -Werror
chegar
parents:
5506
diff
changeset
|
139 |
HashMap<String, SchemeMapValue> schemes; |
2 | 140 |
|
141 |
/* Iterate through each header line, and then within each line. |
|
142 |
* If multiple entries exist for a particular scheme (unlikely) |
|
143 |
* then the last one will be used. The |
|
144 |
* preferred scheme that we support will be used. |
|
145 |
*/ |
|
146 |
private void parse () { |
|
10596
39b3a979e600
7090158: Networking Libraries don't build with javac -Werror
chegar
parents:
5506
diff
changeset
|
147 |
Iterator<String> iter = rsp.multiValueIterator(hdrname); |
2 | 148 |
while (iter.hasNext()) { |
10596
39b3a979e600
7090158: Networking Libraries don't build with javac -Werror
chegar
parents:
5506
diff
changeset
|
149 |
String raw = iter.next(); |
39b3a979e600
7090158: Networking Libraries don't build with javac -Werror
chegar
parents:
5506
diff
changeset
|
150 |
HeaderParser hp = new HeaderParser(raw); |
39b3a979e600
7090158: Networking Libraries don't build with javac -Werror
chegar
parents:
5506
diff
changeset
|
151 |
Iterator<String> keys = hp.keys(); |
2 | 152 |
int i, lastSchemeIndex; |
153 |
for (i=0, lastSchemeIndex = -1; keys.hasNext(); i++) { |
|
154 |
keys.next(); |
|
155 |
if (hp.findValue(i) == null) { /* found a scheme name */ |
|
156 |
if (lastSchemeIndex != -1) { |
|
157 |
HeaderParser hpn = hp.subsequence (lastSchemeIndex, i); |
|
158 |
String scheme = hpn.findKey(0); |
|
159 |
schemes.put (scheme, new SchemeMapValue (hpn, raw)); |
|
160 |
} |
|
161 |
lastSchemeIndex = i; |
|
162 |
} |
|
163 |
} |
|
164 |
if (i > lastSchemeIndex) { |
|
165 |
HeaderParser hpn = hp.subsequence (lastSchemeIndex, i); |
|
166 |
String scheme = hpn.findKey(0); |
|
10596
39b3a979e600
7090158: Networking Libraries don't build with javac -Werror
chegar
parents:
5506
diff
changeset
|
167 |
schemes.put(scheme, new SchemeMapValue (hpn, raw)); |
2 | 168 |
} |
169 |
} |
|
170 |
||
171 |
/* choose the best of them, the order is |
|
172 |
* negotiate -> kerberos -> digest -> ntlm -> basic |
|
173 |
*/ |
|
174 |
SchemeMapValue v = null; |
|
10596
39b3a979e600
7090158: Networking Libraries don't build with javac -Werror
chegar
parents:
5506
diff
changeset
|
175 |
if (authPref == null || (v=schemes.get (authPref)) == null) { |
2 | 176 |
|
177 |
if(v == null && !dontUseNegotiate) { |
|
10596
39b3a979e600
7090158: Networking Libraries don't build with javac -Werror
chegar
parents:
5506
diff
changeset
|
178 |
SchemeMapValue tmp = schemes.get("negotiate"); |
2 | 179 |
if(tmp != null) { |
2942
37d9baeb7518
6578647: Undefined requesting URL in java.net.Authenticator.getPasswordAuthentication()
weijun
parents:
2
diff
changeset
|
180 |
if(hci == null || !NegotiateAuthentication.isSupported(new HttpCallerInfo(hci, "Negotiate"))) { |
2 | 181 |
tmp = null; |
182 |
} |
|
183 |
v = tmp; |
|
184 |
} |
|
185 |
} |
|
186 |
||
187 |
if(v == null && !dontUseNegotiate) { |
|
10596
39b3a979e600
7090158: Networking Libraries don't build with javac -Werror
chegar
parents:
5506
diff
changeset
|
188 |
SchemeMapValue tmp = schemes.get("kerberos"); |
2 | 189 |
if(tmp != null) { |
190 |
// the Kerberos scheme is only observed in MS ISA Server. In |
|
191 |
// fact i think it's a Kerberos-mechnism-only Negotiate. |
|
192 |
// Since the Kerberos scheme is always accompanied with the |
|
193 |
// Negotiate scheme, so it seems impossible to reach this |
|
194 |
// line. Even if the user explicitly set http.auth.preference |
|
195 |
// as Kerberos, it means Negotiate with Kerberos, and the code |
|
196 |
// will still tried to use Negotiate at first. |
|
197 |
// |
|
198 |
// The only chance this line get executed is that the server |
|
199 |
// only suggest the Kerberos scheme. |
|
2942
37d9baeb7518
6578647: Undefined requesting URL in java.net.Authenticator.getPasswordAuthentication()
weijun
parents:
2
diff
changeset
|
200 |
if(hci == null || !NegotiateAuthentication.isSupported(new HttpCallerInfo(hci, "Kerberos"))) { |
2 | 201 |
tmp = null; |
202 |
} |
|
203 |
v = tmp; |
|
204 |
} |
|
205 |
} |
|
206 |
||
207 |
if(v == null) { |
|
10596
39b3a979e600
7090158: Networking Libraries don't build with javac -Werror
chegar
parents:
5506
diff
changeset
|
208 |
if ((v=schemes.get ("digest")) == null) { |
15000
8a1bb7eb6307
8005638: Less secure Authentication schemes should work when more secure schemes are not available
chegar
parents:
10596
diff
changeset
|
209 |
if (!NTLMAuthenticationProxy.supported |
8a1bb7eb6307
8005638: Less secure Authentication schemes should work when more secure schemes are not available
chegar
parents:
10596
diff
changeset
|
210 |
|| ((v=schemes.get("ntlm"))==null)) { |
10596
39b3a979e600
7090158: Networking Libraries don't build with javac -Werror
chegar
parents:
5506
diff
changeset
|
211 |
v = schemes.get ("basic"); |
2 | 212 |
} |
213 |
} |
|
214 |
} |
|
215 |
} else { // authPref != null && it's found in reponses' |
|
216 |
if (dontUseNegotiate && authPref.equals("negotiate")) { |
|
217 |
v = null; |
|
218 |
} |
|
219 |
} |
|
220 |
||
221 |
if (v != null) { |
|
222 |
preferred = v.parser; |
|
223 |
preferred_r = v.raw; |
|
224 |
} |
|
225 |
} |
|
226 |
||
227 |
/** |
|
228 |
* return a header parser containing the preferred authentication scheme (only). |
|
229 |
* The preferred scheme is the strongest of the schemes proposed by the server. |
|
230 |
* The returned HeaderParser will contain the relevant parameters for that scheme |
|
231 |
*/ |
|
232 |
public HeaderParser headerParser() { |
|
233 |
return preferred; |
|
234 |
} |
|
235 |
||
236 |
/** |
|
237 |
* return the name of the preferred scheme |
|
238 |
*/ |
|
239 |
public String scheme() { |
|
240 |
if (preferred != null) { |
|
241 |
return preferred.findKey(0); |
|
242 |
} else { |
|
243 |
return null; |
|
244 |
} |
|
245 |
} |
|
246 |
||
247 |
/* return the raw header field for the preferred/chosen scheme */ |
|
248 |
||
249 |
public String raw () { |
|
250 |
return preferred_r; |
|
251 |
} |
|
252 |
||
253 |
/** |
|
254 |
* returns true is the header exists and contains a recognised scheme |
|
255 |
*/ |
|
256 |
public boolean isPresent () { |
|
257 |
return preferred != null; |
|
258 |
} |
|
259 |
} |