Print this page
Split |
Close |
Expand all |
Collapse all |
--- old/src/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java
+++ new/src/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java
1 1 /*
2 2 * Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved.
3 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 4 *
5 5 * This code is free software; you can redistribute it and/or modify it
6 6 * under the terms of the GNU General Public License version 2 only, as
7 7 * published by the Free Software Foundation. Sun designates this
8 8 * particular file as subject to the "Classpath" exception as provided
9 9 * by Sun in the LICENSE file that accompanied this code.
10 10 *
11 11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 14 * version 2 for more details (a copy is included in the LICENSE file that
15 15 * accompanied this code).
16 16 *
17 17 * You should have received a copy of the GNU General Public License version
↓ open down ↓ |
17 lines elided |
↑ open up ↑ |
18 18 * 2 along with this work; if not, write to the Free Software Foundation,
19 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 20 *
21 21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 23 * have any questions.
24 24 */
25 25
26 26 package sun.net.www.protocol.http;
27 27
28 +import java.net.URL;
29 +import java.io.IOException;
30 +import java.net.Authenticator.RequestorType;
28 31 import java.util.HashMap;
29 -
30 32 import sun.net.www.HeaderParser;
31 33 import sun.misc.BASE64Decoder;
32 34 import sun.misc.BASE64Encoder;
33 -import sun.util.logging.PlatformLogger;
34 -
35 -import java.net.URL;
36 -import java.io.IOException;
37 -import java.net.Authenticator.RequestorType;
38 -import java.lang.reflect.Constructor;
39 35 import static sun.net.www.protocol.http.AuthScheme.NEGOTIATE;
40 36 import static sun.net.www.protocol.http.AuthScheme.KERBEROS;
41 37
42 38 /**
43 39 * NegotiateAuthentication:
44 40 *
45 41 * @author weijun.wang@sun.com
46 42 * @since 1.6
47 43 */
48 44
49 45 class NegotiateAuthentication extends AuthenticationInfo {
50 46
51 47 private static final long serialVersionUID = 100L;
52 48
53 49 final private HttpCallerInfo hci;
54 50
55 51 // These maps are used to manage the GSS availability for diffrent
56 52 // hosts. The key for both maps is the host name.
57 53 // <code>supported</code> is set when isSupported is checked,
58 54 // if it's true, a cached Negotiator is put into <code>cache</code>.
59 55 // the cache can be used only once, so after the first use, it's cleaned.
60 56 static HashMap <String, Boolean> supported = null;
61 57 static HashMap <String, Negotiator> cache = null;
62 58
63 59 // The HTTP Negotiate Helper
64 60 private Negotiator negotiator = null;
65 61
66 62 /**
67 63 * Constructor used for both WWW and proxy entries.
68 64 * @param hci a schemed object.
69 65 */
70 66 public NegotiateAuthentication(HttpCallerInfo hci) {
↓ open down ↓ |
22 lines elided |
↑ open up ↑ |
71 67 super(RequestorType.PROXY==hci.authType ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
72 68 hci.scheme.equalsIgnoreCase("Negotiate") ? NEGOTIATE : KERBEROS,
73 69 hci.url,
74 70 "");
75 71 this.hci = hci;
76 72 }
77 73
78 74 /**
79 75 * @return true if this authentication supports preemptive authorization
80 76 */
81 - boolean supportsPreemptiveAuthorization() {
77 + @Override
78 + public boolean supportsPreemptiveAuthorization() {
82 79 return false;
83 80 }
84 81
85 82 /**
86 83 * Find out if the HttpCallerInfo supports Negotiate protocol. In order to
87 84 * find out yes or no, an initialization of a Negotiator object against it
88 85 * is tried. The generated object will be cached under the name of ths
89 86 * hostname at a success try.<br>
90 87 *
91 88 * If this method is called for the second time on an HttpCallerInfo with
92 89 * the same hostname, the answer is retrieved from cache.
93 90 *
94 91 * @return true if supported
95 92 */
96 93 synchronized public static boolean isSupported(HttpCallerInfo hci) {
97 94 if (supported == null) {
98 95 supported = new HashMap <String, Boolean>();
99 96 cache = new HashMap <String, Negotiator>();
100 97 }
101 98 String hostname = hci.host;
102 99 hostname = hostname.toLowerCase();
103 100 if (supported.containsKey(hostname)) {
104 101 return supported.get(hostname);
105 102 }
106 103
107 104 try {
108 105 Negotiator neg = Negotiator.getSupported(hci);
109 106 supported.put(hostname, true);
110 107 // the only place cache.put is called. here we can make sure
↓ open down ↓ |
19 lines elided |
↑ open up ↑ |
111 108 // the object is valid and the oneToken inside is not null
112 109 cache.put(hostname, neg);
113 110 return true;
114 111 } catch(Exception e) {
115 112 supported.put(hostname, false);
116 113 return false;
117 114 }
118 115 }
119 116
120 117 /**
121 - * @return the name of the HTTP header this authentication wants to set
122 - */
123 - String getHeaderName() {
124 - if (type == SERVER_AUTHENTICATION) {
125 - return "Authorization";
126 - } else {
127 - return "Proxy-Authorization";
128 - }
129 - }
130 -
131 - /**
132 118 * Not supported. Must use the setHeaders() method
133 119 */
134 - String getHeaderValue(URL url, String method) {
120 + @Override
121 + public String getHeaderValue(URL url, String method) {
135 122 throw new RuntimeException ("getHeaderValue not supported");
136 123 }
137 124
138 125 /**
139 126 * Check if the header indicates that the current auth. parameters are stale.
140 127 * If so, then replace the relevant field with the new value
141 128 * and return true. Otherwise return false.
142 129 * returning true means the request can be retried with the same userid/password
143 130 * returning false means we have to go back to the user to ask for a new
144 131 * username password.
145 132 */
146 - boolean isAuthorizationStale (String header) {
133 + @Override
134 + public boolean isAuthorizationStale (String header) {
147 135 return false; /* should not be called for Negotiate */
148 136 }
149 137
150 138 /**
151 139 * Set header(s) on the given connection.
152 140 * @param conn The connection to apply the header(s) to
153 141 * @param p A source of header values for this connection, not used because
154 142 * HeaderParser converts the fields to lower case, use raw instead
155 143 * @param raw The raw header field.
156 144 * @return true if all goes well, false if no headers were set.
157 145 */
158 - synchronized boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) {
146 + @Override
147 + public synchronized boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) {
159 148
160 149 try {
161 150 String response;
162 151 byte[] incoming = null;
163 152 String[] parts = raw.split("\\s+");
164 153 if (parts.length > 1) {
165 154 incoming = new BASE64Decoder().decodeBuffer(parts[1]);
166 155 }
167 156 response = hci.scheme + " " + new B64Encoder().encode(
168 157 incoming==null?firstToken():nextToken(incoming));
169 158
170 159 conn.setAuthenticationProperty(getHeaderName(), response);
171 160 return true;
172 161 } catch (IOException e) {
173 162 return false;
174 163 }
175 164 }
176 165
177 166 /**
178 167 * return the first token.
179 168 * @returns the token
180 169 * @throws IOException if <code>Negotiator.getSupported()</code> or
181 170 * <code>Negotiator.firstToken()</code> failed.
182 171 */
183 172 private byte[] firstToken() throws IOException {
184 173 negotiator = null;
185 174 if (cache != null) {
186 175 synchronized(cache) {
187 176 negotiator = cache.get(getHost());
188 177 if (negotiator != null) {
189 178 cache.remove(getHost()); // so that it is only used once
190 179 }
191 180 }
192 181 }
193 182 if (negotiator == null) {
194 183 try {
195 184 negotiator = Negotiator.getSupported(hci);
196 185 } catch(Exception e) {
197 186 IOException ioe = new IOException("Cannot initialize Negotiator");
198 187 ioe.initCause(e);
199 188 throw ioe;
200 189 }
201 190 }
202 191
203 192 return negotiator.firstToken();
204 193 }
205 194
206 195 /**
207 196 * return more tokens
208 197 * @param token the token to be fed into <code>negotiator.nextToken()</code>
209 198 * @returns the token
210 199 * @throws IOException if <code>negotiator.nextToken()</code> throws Exception.
211 200 * May happen if the input token is invalid.
212 201 */
213 202 private byte[] nextToken(byte[] token) throws IOException {
214 203 return negotiator.nextToken(token);
215 204 }
216 205
217 206 class B64Encoder extends BASE64Encoder {
218 207 protected int bytesPerLine () {
219 208 return 100000; // as big as it can be, maybe INT_MAX
↓ open down ↓ |
51 lines elided |
↑ open up ↑ |
220 209 }
221 210 }
222 211
223 212 // MS will send a final WWW-Authenticate even if the status is already
224 213 // 200 OK. The token can be fed into initSecContext() again to determine
225 214 // if the server can be trusted. This is not the same concept as Digest's
226 215 // Authentication-Info header.
227 216 //
228 217 // Currently we ignore this header.
229 218
230 -}
231 -
232 -/**
233 - * This abstract class is a bridge to connect NegotiteAuthentication and
234 - * NegotiatorImpl, so that JAAS and JGSS calls can be made
235 - */
236 -abstract class Negotiator {
237 - static Negotiator getSupported(HttpCallerInfo hci)
238 - throws Exception {
239 -
240 - // These lines are equivalent to
241 - // return new NegotiatorImpl(hci);
242 - // The current implementation will make sure NegotiatorImpl is not
243 - // directly referenced when compiling, thus smooth the way of building
244 - // the J2SE platform where HttpURLConnection is a bootstrap class.
245 - //
246 - // Makes NegotiatorImpl, and the security classes it references, a
247 - // runtime dependency rather than a static one.
248 -
249 - Class clazz;
250 - Constructor c;
251 - try {
252 - clazz = Class.forName("sun.net.www.protocol.http.NegotiatorImpl", true, null);
253 - c = clazz.getConstructor(HttpCallerInfo.class);
254 - } catch (ClassNotFoundException cnfe) {
255 - finest(cnfe);
256 - throw cnfe;
257 - } catch (ReflectiveOperationException roe) {
258 - // if the class is there then something seriously wrong if
259 - // the constructor is not.
260 - throw new AssertionError(roe);
261 - }
262 -
263 - try {
264 - return (Negotiator) (c.newInstance(hci));
265 - } catch (ReflectiveOperationException roe) {
266 - finest(roe);
267 - Throwable t = roe.getCause();
268 - if (t != null && t instanceof Exception)
269 - finest((Exception)t);
270 - throw roe;
271 - }
272 - }
273 -
274 - abstract byte[] firstToken() throws IOException;
275 -
276 - abstract byte[] nextToken(byte[] in) throws IOException;
277 -
278 - static void finest(Exception e) {
279 - PlatformLogger logger = HttpURLConnection.getHttpLogger();
280 - logger.finest("NegotiateAuthentication: " + e);
281 - }
282 219 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX