396 private static final PlatformLogger logger =
397 PlatformLogger.getLogger("sun.net.www.protocol.http.HttpURLConnection");
398
399 /*
400 * privileged request password authentication
401 *
402 */
403 private static PasswordAuthentication
404 privilegedRequestPasswordAuthentication(
405 final String host,
406 final InetAddress addr,
407 final int port,
408 final String protocol,
409 final String prompt,
410 final String scheme,
411 final URL url,
412 final RequestorType authType) {
413 return java.security.AccessController.doPrivileged(
414 new java.security.PrivilegedAction<PasswordAuthentication>() {
415 public PasswordAuthentication run() {
416 if (logger.isLoggable(PlatformLogger.FINEST)) {
417 logger.finest("Requesting Authentication: host =" + host + " url = " + url);
418 }
419 PasswordAuthentication pass = Authenticator.requestPasswordAuthentication(
420 host, addr, port, protocol,
421 prompt, scheme, url, authType);
422 if (logger.isLoggable(PlatformLogger.FINEST)) {
423 logger.finest("Authentication returned: " + (pass != null ? pass.toString() : "null"));
424 }
425 return pass;
426 }
427 });
428 }
429
430 private boolean isRestrictedHeader(String key, String value) {
431 if (allowRestrictedHeaders) {
432 return false;
433 }
434
435 key = key.toLowerCase();
436 if (restrictedHeaderSet.contains(key)) {
437 /*
438 * Exceptions to restricted headers:
439 *
440 * Allow "Connection: close".
441 */
442 if (key.equals("connection") && value.equalsIgnoreCase("close")) {
615 requests.set ("Content-Length",
616 String.valueOf(fixedContentLengthLong));
617 } else if (fixedContentLength != -1) {
618 requests.set ("Content-Length",
619 String.valueOf(fixedContentLength));
620 }
621 }
622 } else if (poster != null) {
623 /* add Content-Length & POST/PUT data */
624 synchronized (poster) {
625 /* close it, so no more data can be added */
626 poster.close();
627 requests.set("Content-Length",
628 String.valueOf(poster.size()));
629 }
630 }
631
632 if (!chunked) {
633 if (requests.findValue("Transfer-Encoding") != null) {
634 requests.remove("Transfer-Encoding");
635 if (logger.isLoggable(PlatformLogger.WARNING)) {
636 logger.warning(
637 "use streaming mode for chunked encoding");
638 }
639 }
640 }
641
642 // get applicable cookies based on the uri and request headers
643 // add them to the existing request headers
644 setCookieHeader();
645
646 setRequests=true;
647 }
648 if (logger.isLoggable(PlatformLogger.FINE)) {
649 logger.fine(requests.toString());
650 }
651 http.writeRequests(requests, poster, streaming());
652 if (ps.checkError()) {
653 String proxyHost = http.getProxyHostUsed();
654 int proxyPort = http.getProxyPortUsed();
655 disconnectInternal();
656 if (failedOnce) {
657 throw new IOException("Error writing to server");
658 } else { // try once more
659 failedOnce=true;
660 if (proxyHost != null) {
661 setProxiedClient(url, proxyHost, proxyPort);
662 } else {
663 setNewClient (url);
664 }
665 ps = (PrintStream) http.getOutputStream();
666 connected=true;
667 responses = new MessageHeader();
668 setRequests=false;
974 sm.checkPermission(p);
975 socketPermission = newPerm;
976 return socketPermission;
977 } catch (SecurityException e) {
978 // fall thru
979 }
980 return null;
981 }
982
983 protected void plainConnect0() throws IOException {
984 // try to see if request can be served from local cache
985 if (cacheHandler != null && getUseCaches()) {
986 try {
987 URI uri = ParseUtil.toURI(url);
988 if (uri != null) {
989 cachedResponse = cacheHandler.get(uri, getRequestMethod(), requests.getHeaders(EXCLUDE_HEADERS));
990 if ("https".equalsIgnoreCase(uri.getScheme())
991 && !(cachedResponse instanceof SecureCacheResponse)) {
992 cachedResponse = null;
993 }
994 if (logger.isLoggable(PlatformLogger.FINEST)) {
995 logger.finest("Cache Request for " + uri + " / " + getRequestMethod());
996 logger.finest("From cache: " + (cachedResponse != null ? cachedResponse.toString() : "null"));
997 }
998 if (cachedResponse != null) {
999 cachedHeaders = mapToMessageHeader(cachedResponse.getHeaders());
1000 cachedInputStream = cachedResponse.getBody();
1001 }
1002 }
1003 } catch (IOException ioex) {
1004 // ignore and commence normal connection
1005 }
1006 if (cachedHeaders != null && cachedInputStream != null) {
1007 connected = true;
1008 return;
1009 } else {
1010 cachedResponse = null;
1011 }
1012 }
1013 try {
1014 /* Try to open connections using the following scheme,
1015 * return on the first one that's successful:
1016 * 1) if (instProxy != null)
1017 * connect to instProxy; raise exception if failed
1018 * 2) else use system default ProxySelector
1019 * 3) is 2) fails, make direct connection
1020 */
1021
1022 if (instProxy == null) { // no instance Proxy is set
1023 /**
1024 * Do we have to use a proxy?
1025 */
1026 ProxySelector sel =
1027 java.security.AccessController.doPrivileged(
1028 new java.security.PrivilegedAction<ProxySelector>() {
1029 public ProxySelector run() {
1030 return ProxySelector.getDefault();
1031 }
1032 });
1033 if (sel != null) {
1034 URI uri = sun.net.www.ParseUtil.toURI(url);
1035 if (logger.isLoggable(PlatformLogger.FINEST)) {
1036 logger.finest("ProxySelector Request for " + uri);
1037 }
1038 Iterator<Proxy> it = sel.select(uri).iterator();
1039 Proxy p;
1040 while (it.hasNext()) {
1041 p = it.next();
1042 try {
1043 if (!failedOnce) {
1044 http = getNewHttpClient(url, p, connectTimeout);
1045 http.setReadTimeout(readTimeout);
1046 } else {
1047 // make sure to construct new connection if first
1048 // attempt failed
1049 http = getNewHttpClient(url, p, connectTimeout, false);
1050 http.setReadTimeout(readTimeout);
1051 }
1052 if (logger.isLoggable(PlatformLogger.FINEST)) {
1053 if (p != null) {
1054 logger.finest("Proxy used: " + p.toString());
1055 }
1056 }
1057 break;
1058 } catch (IOException ioex) {
1059 if (p != Proxy.NO_PROXY) {
1060 sel.connectFailed(uri, p.address(), ioex);
1061 if (!it.hasNext()) {
1062 // fallback to direct connection
1063 http = getNewHttpClient(url, null, connectTimeout, false);
1064 http.setReadTimeout(readTimeout);
1065 break;
1066 }
1067 } else {
1068 throw ioex;
1069 }
1070 continue;
1071 }
1072 }
1291 // they cannot be changed by user code after we are connected,
1292 // only internally.
1293 synchronized (this) {
1294 if (setUserCookies) {
1295 int k = requests.getKey("Cookie");
1296 if (k != -1)
1297 userCookies = requests.getValue(k);
1298 k = requests.getKey("Cookie2");
1299 if (k != -1)
1300 userCookies2 = requests.getValue(k);
1301 setUserCookies = false;
1302 }
1303 }
1304
1305 // remove old Cookie header before setting new one.
1306 requests.remove("Cookie");
1307 requests.remove("Cookie2");
1308
1309 URI uri = ParseUtil.toURI(url);
1310 if (uri != null) {
1311 if (logger.isLoggable(PlatformLogger.FINEST)) {
1312 logger.finest("CookieHandler request for " + uri);
1313 }
1314 Map<String, List<String>> cookies
1315 = cookieHandler.get(
1316 uri, requests.getHeaders(EXCLUDE_HEADERS));
1317 if (!cookies.isEmpty()) {
1318 if (logger.isLoggable(PlatformLogger.FINEST)) {
1319 logger.finest("Cookies retrieved: " + cookies.toString());
1320 }
1321 for (Map.Entry<String, List<String>> entry :
1322 cookies.entrySet()) {
1323 String key = entry.getKey();
1324 // ignore all entries that don't have "Cookie"
1325 // or "Cookie2" as keys
1326 if (!"Cookie".equalsIgnoreCase(key) &&
1327 !"Cookie2".equalsIgnoreCase(key)) {
1328 continue;
1329 }
1330 List<String> l = entry.getValue();
1331 if (l != null && !l.isEmpty()) {
1332 StringBuilder cookieValue = new StringBuilder();
1333 for (String value : l) {
1334 cookieValue.append(value).append("; ");
1335 }
1336 // strip off the trailing '; '
1337 try {
1338 requests.add(key, cookieValue.substring(0, cookieValue.length() - 2));
1459 }
1460
1461 // Check if URL should be metered
1462 boolean meteredInput = ProgressMonitor.getDefault().shouldMeterInput(url, method);
1463
1464 if (meteredInput) {
1465 pi = new ProgressSource(url, method);
1466 pi.beginTracking();
1467 }
1468
1469 /* REMIND: This exists to fix the HttpsURLConnection subclass.
1470 * Hotjava needs to run on JDK1.1FCS. Do proper fix once a
1471 * proper solution for SSL can be found.
1472 */
1473 ps = (PrintStream)http.getOutputStream();
1474
1475 if (!streaming()) {
1476 writeRequests();
1477 }
1478 http.parseHTTP(responses, pi, this);
1479 if (logger.isLoggable(PlatformLogger.FINE)) {
1480 logger.fine(responses.toString());
1481 }
1482
1483 boolean b1 = responses.filterNTLMResponses("WWW-Authenticate");
1484 boolean b2 = responses.filterNTLMResponses("Proxy-Authenticate");
1485 if (b1 || b2) {
1486 if (logger.isLoggable(PlatformLogger.FINE)) {
1487 logger.fine(">>>> Headers are filtered");
1488 logger.fine(responses.toString());
1489 }
1490 }
1491
1492 inputStream = http.getInputStream();
1493
1494 respCode = getResponseCode();
1495 if (respCode == -1) {
1496 disconnectInternal();
1497 throw new IOException ("Invalid Http response");
1498 }
1499 if (respCode == HTTP_PROXY_AUTH) {
1500 if (streaming()) {
1501 disconnectInternal();
1502 throw new HttpRetryException (
1503 RETRY_MSG1, HTTP_PROXY_AUTH);
1504 }
1505
1506 // Read comments labeled "Failed Negotiate" for details.
1926 boolean inNegotiateProxy = false;
1927
1928 try {
1929 /* Actively setting up a tunnel */
1930 setTunnelState(TunnelState.SETUP);
1931
1932 do {
1933 if (!checkReuseConnection()) {
1934 proxiedConnect(url, proxyHost, proxyPort, false);
1935 }
1936 // send the "CONNECT" request to establish a tunnel
1937 // through proxy server
1938 sendCONNECTRequest();
1939 responses.reset();
1940
1941 // There is no need to track progress in HTTP Tunneling,
1942 // so ProgressSource is null.
1943 http.parseHTTP(responses, null, this);
1944
1945 /* Log the response to the CONNECT */
1946 if (logger.isLoggable(PlatformLogger.FINE)) {
1947 logger.fine(responses.toString());
1948 }
1949
1950 if (responses.filterNTLMResponses("Proxy-Authenticate")) {
1951 if (logger.isLoggable(PlatformLogger.FINE)) {
1952 logger.fine(">>>> Headers are filtered");
1953 logger.fine(responses.toString());
1954 }
1955 }
1956
1957 statusLine = responses.getValue(0);
1958 StringTokenizer st = new StringTokenizer(statusLine);
1959 st.nextToken();
1960 respCode = Integer.parseInt(st.nextToken().trim());
1961 if (respCode == HTTP_PROXY_AUTH) {
1962 // Read comments labeled "Failed Negotiate" for details.
1963 boolean dontUseNegotiate = false;
1964 Iterator<String> iter = responses.multiValueIterator("Proxy-Authenticate");
1965 while (iter.hasNext()) {
1966 String value = iter.next().trim();
1967 if (value.equalsIgnoreCase("Negotiate") ||
1968 value.equalsIgnoreCase("Kerberos")) {
1969 if (!inNegotiateProxy) {
1970 inNegotiateProxy = true;
1971 } else {
2058 requests.set(0, HTTP_CONNECT + " " + connectRequestURI(url)
2059 + " " + httpVersion, null);
2060 requests.setIfNotSet("User-Agent", userAgent);
2061
2062 String host = url.getHost();
2063 if (port != -1 && port != url.getDefaultPort()) {
2064 host += ":" + String.valueOf(port);
2065 }
2066 requests.setIfNotSet("Host", host);
2067
2068 // Not really necessary for a tunnel, but can't hurt
2069 requests.setIfNotSet("Accept", acceptString);
2070
2071 if (http.getHttpKeepAliveSet()) {
2072 requests.setIfNotSet("Proxy-Connection", "keep-alive");
2073 }
2074
2075 setPreemptiveProxyAuthentication(requests);
2076
2077 /* Log the CONNECT request */
2078 if (logger.isLoggable(PlatformLogger.FINE)) {
2079 logger.fine(requests.toString());
2080 }
2081
2082 http.writeRequests(requests, null);
2083 }
2084
2085 /**
2086 * Sets pre-emptive proxy authentication in header
2087 */
2088 private void setPreemptiveProxyAuthentication(MessageHeader requests) throws IOException {
2089 AuthenticationInfo pauth
2090 = AuthenticationInfo.getProxyAuth(http.getProxyHostUsed(),
2091 http.getProxyPortUsed());
2092 if (pauth != null && pauth.supportsPreemptiveAuthorization()) {
2093 String value;
2094 if (pauth instanceof DigestAuthentication) {
2095 DigestAuthentication digestProxy = (DigestAuthentication) pauth;
2096 if (tunnelState() == TunnelState.SETUP) {
2097 value = digestProxy
2098 .getHeaderValue(connectRequestURI(url), HTTP_CONNECT);
2201 * transparent authentication (Windows only) the username
2202 * and password will be picked up from the current logged
2203 * on users credentials.
2204 */
2205 if (tryTransparentNTLMProxy ||
2206 (!tryTransparentNTLMProxy && a != null)) {
2207 ret = NTLMAuthenticationProxy.proxy.create(true, host, port, a);
2208 }
2209
2210 /* set to false so that we do not try again */
2211 tryTransparentNTLMProxy = false;
2212 }
2213 break;
2214 case NEGOTIATE:
2215 ret = new NegotiateAuthentication(new HttpCallerInfo(authhdr.getHttpCallerInfo(), "Negotiate"));
2216 break;
2217 case KERBEROS:
2218 ret = new NegotiateAuthentication(new HttpCallerInfo(authhdr.getHttpCallerInfo(), "Kerberos"));
2219 break;
2220 case UNKNOWN:
2221 if (logger.isLoggable(PlatformLogger.FINEST)) {
2222 logger.finest("Unknown/Unsupported authentication scheme: " + scheme);
2223 }
2224 /*fall through*/
2225 default:
2226 throw new AssertionError("should not reach here");
2227 }
2228 }
2229 // For backwards compatibility, we also try defaultAuth
2230 // REMIND: Get rid of this for JDK2.0.
2231
2232 if (ret == null && defaultAuth != null
2233 && defaultAuth.schemeSupported(scheme)) {
2234 try {
2235 URL u = new URL("http", host, port, "/");
2236 String a = defaultAuth.authString(u, scheme, realm);
2237 if (a != null) {
2238 ret = new BasicAuthentication (true, host, port, realm, a);
2239 // not in cache by default - cache on success
2240 }
2241 } catch (java.net.MalformedURLException ignored) {
2242 }
2243 }
2244 if (ret != null) {
2245 if (!ret.setHeaders(this, p, raw)) {
2246 ret = null;
2247 }
2248 }
2249 }
2250 if (logger.isLoggable(PlatformLogger.FINER)) {
2251 logger.finer("Proxy Authentication for " + authhdr.toString() +" returned " + (ret != null ? ret.toString() : "null"));
2252 }
2253 return ret;
2254 }
2255
2256 /**
2257 * Gets the authentication for an HTTP server, and applies it to
2258 * the connection.
2259 * @param authHdr the AuthenticationHeader which tells what auth scheme is
2260 * prefered.
2261 */
2262 @SuppressWarnings("fallthrough")
2263 private AuthenticationInfo getServerAuthentication (AuthenticationHeader authhdr) {
2264 /* get authorization from authenticator */
2265 AuthenticationInfo ret = null;
2266 String raw = authhdr.raw();
2267 /* When we get an NTLM auth from cache, don't set any special headers */
2268 if (authhdr.isPresent()) {
2269 HeaderParser p = authhdr.headerParser();
2270 String realm = p.findValue("realm");
2360 url.getHost(), addr, port, url.getProtocol(),
2361 "", scheme, url, RequestorType.SERVER);
2362 }
2363
2364 /* If we are not trying transparent authentication then
2365 * we need to have a PasswordAuthentication instance. For
2366 * transparent authentication (Windows only) the username
2367 * and password will be picked up from the current logged
2368 * on users credentials.
2369 */
2370 if (tryTransparentNTLMServer ||
2371 (!tryTransparentNTLMServer && a != null)) {
2372 ret = NTLMAuthenticationProxy.proxy.create(false, url1, a);
2373 }
2374
2375 /* set to false so that we do not try again */
2376 tryTransparentNTLMServer = false;
2377 }
2378 break;
2379 case UNKNOWN:
2380 if (logger.isLoggable(PlatformLogger.FINEST)) {
2381 logger.finest("Unknown/Unsupported authentication scheme: " + scheme);
2382 }
2383 /*fall through*/
2384 default:
2385 throw new AssertionError("should not reach here");
2386 }
2387 }
2388
2389 // For backwards compatibility, we also try defaultAuth
2390 // REMIND: Get rid of this for JDK2.0.
2391
2392 if (ret == null && defaultAuth != null
2393 && defaultAuth.schemeSupported(scheme)) {
2394 String a = defaultAuth.authString(url, scheme, realm);
2395 if (a != null) {
2396 ret = new BasicAuthentication (false, url, realm, a);
2397 // not in cache by default - cache on success
2398 }
2399 }
2400
2401 if (ret != null ) {
2402 if (!ret.setHeaders(this, p, raw)) {
2403 ret = null;
2404 }
2405 }
2406 }
2407 if (logger.isLoggable(PlatformLogger.FINER)) {
2408 logger.finer("Server Authentication for " + authhdr.toString() +" returned " + (ret != null ? ret.toString() : "null"));
2409 }
2410 return ret;
2411 }
2412
2413 /* inclose will be true if called from close(), in which case we
2414 * force the call to check because this is the last chance to do so.
2415 * If not in close(), then the authentication info could arrive in a trailer
2416 * field, which we have not read yet.
2417 */
2418 private void checkResponseCredentials (boolean inClose) throws IOException {
2419 try {
2420 if (!needToCheck)
2421 return;
2422 if ((validateProxy && currentProxyCredentials != null) &&
2423 (currentProxyCredentials instanceof DigestAuthentication)) {
2424 String raw = responses.findValue ("Proxy-Authentication-Info");
2425 if (inClose || (raw != null)) {
2426 DigestAuthentication da = (DigestAuthentication)
2427 currentProxyCredentials;
2515 throw (IOException) e.getException();
2516 }
2517 } else {
2518 // run without additional permission
2519 return followRedirect0(loc, stat, locUrl);
2520 }
2521 }
2522
2523 /* Tells us whether to follow a redirect. If so, it
2524 * closes the connection (break any keep-alive) and
2525 * resets the url, re-connects, and resets the request
2526 * property.
2527 */
2528 private boolean followRedirect0(String loc, int stat, URL locUrl)
2529 throws IOException
2530 {
2531 disconnectInternal();
2532 if (streaming()) {
2533 throw new HttpRetryException (RETRY_MSG3, stat, loc);
2534 }
2535 if (logger.isLoggable(PlatformLogger.FINE)) {
2536 logger.fine("Redirected from " + url + " to " + locUrl);
2537 }
2538
2539 // clear out old response headers!!!!
2540 responses = new MessageHeader();
2541 if (stat == HTTP_USE_PROXY) {
2542 /* This means we must re-request the resource through the
2543 * proxy denoted in the "Location:" field of the response.
2544 * Judging by the spec, the string in the Location header
2545 * _should_ denote a URL - let's hope for "http://my.proxy.org"
2546 * Make a new HttpClient to the proxy, using HttpClient's
2547 * Instance-specific proxy fields, but note we're still fetching
2548 * the same URL.
2549 */
2550 String proxyHost = locUrl.getHost();
2551 int proxyPort = locUrl.getPort();
2552
2553 SecurityManager security = System.getSecurityManager();
2554 if (security != null) {
2555 security.checkConnect(proxyHost, proxyPort);
|
396 private static final PlatformLogger logger =
397 PlatformLogger.getLogger("sun.net.www.protocol.http.HttpURLConnection");
398
399 /*
400 * privileged request password authentication
401 *
402 */
403 private static PasswordAuthentication
404 privilegedRequestPasswordAuthentication(
405 final String host,
406 final InetAddress addr,
407 final int port,
408 final String protocol,
409 final String prompt,
410 final String scheme,
411 final URL url,
412 final RequestorType authType) {
413 return java.security.AccessController.doPrivileged(
414 new java.security.PrivilegedAction<PasswordAuthentication>() {
415 public PasswordAuthentication run() {
416 if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
417 logger.finest("Requesting Authentication: host =" + host + " url = " + url);
418 }
419 PasswordAuthentication pass = Authenticator.requestPasswordAuthentication(
420 host, addr, port, protocol,
421 prompt, scheme, url, authType);
422 if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
423 logger.finest("Authentication returned: " + (pass != null ? pass.toString() : "null"));
424 }
425 return pass;
426 }
427 });
428 }
429
430 private boolean isRestrictedHeader(String key, String value) {
431 if (allowRestrictedHeaders) {
432 return false;
433 }
434
435 key = key.toLowerCase();
436 if (restrictedHeaderSet.contains(key)) {
437 /*
438 * Exceptions to restricted headers:
439 *
440 * Allow "Connection: close".
441 */
442 if (key.equals("connection") && value.equalsIgnoreCase("close")) {
615 requests.set ("Content-Length",
616 String.valueOf(fixedContentLengthLong));
617 } else if (fixedContentLength != -1) {
618 requests.set ("Content-Length",
619 String.valueOf(fixedContentLength));
620 }
621 }
622 } else if (poster != null) {
623 /* add Content-Length & POST/PUT data */
624 synchronized (poster) {
625 /* close it, so no more data can be added */
626 poster.close();
627 requests.set("Content-Length",
628 String.valueOf(poster.size()));
629 }
630 }
631
632 if (!chunked) {
633 if (requests.findValue("Transfer-Encoding") != null) {
634 requests.remove("Transfer-Encoding");
635 if (logger.isLoggable(PlatformLogger.Level.WARNING)) {
636 logger.warning(
637 "use streaming mode for chunked encoding");
638 }
639 }
640 }
641
642 // get applicable cookies based on the uri and request headers
643 // add them to the existing request headers
644 setCookieHeader();
645
646 setRequests=true;
647 }
648 if (logger.isLoggable(PlatformLogger.Level.FINE)) {
649 logger.fine(requests.toString());
650 }
651 http.writeRequests(requests, poster, streaming());
652 if (ps.checkError()) {
653 String proxyHost = http.getProxyHostUsed();
654 int proxyPort = http.getProxyPortUsed();
655 disconnectInternal();
656 if (failedOnce) {
657 throw new IOException("Error writing to server");
658 } else { // try once more
659 failedOnce=true;
660 if (proxyHost != null) {
661 setProxiedClient(url, proxyHost, proxyPort);
662 } else {
663 setNewClient (url);
664 }
665 ps = (PrintStream) http.getOutputStream();
666 connected=true;
667 responses = new MessageHeader();
668 setRequests=false;
974 sm.checkPermission(p);
975 socketPermission = newPerm;
976 return socketPermission;
977 } catch (SecurityException e) {
978 // fall thru
979 }
980 return null;
981 }
982
983 protected void plainConnect0() throws IOException {
984 // try to see if request can be served from local cache
985 if (cacheHandler != null && getUseCaches()) {
986 try {
987 URI uri = ParseUtil.toURI(url);
988 if (uri != null) {
989 cachedResponse = cacheHandler.get(uri, getRequestMethod(), requests.getHeaders(EXCLUDE_HEADERS));
990 if ("https".equalsIgnoreCase(uri.getScheme())
991 && !(cachedResponse instanceof SecureCacheResponse)) {
992 cachedResponse = null;
993 }
994 if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
995 logger.finest("Cache Request for " + uri + " / " + getRequestMethod());
996 logger.finest("From cache: " + (cachedResponse != null ? cachedResponse.toString() : "null"));
997 }
998 if (cachedResponse != null) {
999 cachedHeaders = mapToMessageHeader(cachedResponse.getHeaders());
1000 cachedInputStream = cachedResponse.getBody();
1001 }
1002 }
1003 } catch (IOException ioex) {
1004 // ignore and commence normal connection
1005 }
1006 if (cachedHeaders != null && cachedInputStream != null) {
1007 connected = true;
1008 return;
1009 } else {
1010 cachedResponse = null;
1011 }
1012 }
1013 try {
1014 /* Try to open connections using the following scheme,
1015 * return on the first one that's successful:
1016 * 1) if (instProxy != null)
1017 * connect to instProxy; raise exception if failed
1018 * 2) else use system default ProxySelector
1019 * 3) is 2) fails, make direct connection
1020 */
1021
1022 if (instProxy == null) { // no instance Proxy is set
1023 /**
1024 * Do we have to use a proxy?
1025 */
1026 ProxySelector sel =
1027 java.security.AccessController.doPrivileged(
1028 new java.security.PrivilegedAction<ProxySelector>() {
1029 public ProxySelector run() {
1030 return ProxySelector.getDefault();
1031 }
1032 });
1033 if (sel != null) {
1034 URI uri = sun.net.www.ParseUtil.toURI(url);
1035 if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
1036 logger.finest("ProxySelector Request for " + uri);
1037 }
1038 Iterator<Proxy> it = sel.select(uri).iterator();
1039 Proxy p;
1040 while (it.hasNext()) {
1041 p = it.next();
1042 try {
1043 if (!failedOnce) {
1044 http = getNewHttpClient(url, p, connectTimeout);
1045 http.setReadTimeout(readTimeout);
1046 } else {
1047 // make sure to construct new connection if first
1048 // attempt failed
1049 http = getNewHttpClient(url, p, connectTimeout, false);
1050 http.setReadTimeout(readTimeout);
1051 }
1052 if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
1053 if (p != null) {
1054 logger.finest("Proxy used: " + p.toString());
1055 }
1056 }
1057 break;
1058 } catch (IOException ioex) {
1059 if (p != Proxy.NO_PROXY) {
1060 sel.connectFailed(uri, p.address(), ioex);
1061 if (!it.hasNext()) {
1062 // fallback to direct connection
1063 http = getNewHttpClient(url, null, connectTimeout, false);
1064 http.setReadTimeout(readTimeout);
1065 break;
1066 }
1067 } else {
1068 throw ioex;
1069 }
1070 continue;
1071 }
1072 }
1291 // they cannot be changed by user code after we are connected,
1292 // only internally.
1293 synchronized (this) {
1294 if (setUserCookies) {
1295 int k = requests.getKey("Cookie");
1296 if (k != -1)
1297 userCookies = requests.getValue(k);
1298 k = requests.getKey("Cookie2");
1299 if (k != -1)
1300 userCookies2 = requests.getValue(k);
1301 setUserCookies = false;
1302 }
1303 }
1304
1305 // remove old Cookie header before setting new one.
1306 requests.remove("Cookie");
1307 requests.remove("Cookie2");
1308
1309 URI uri = ParseUtil.toURI(url);
1310 if (uri != null) {
1311 if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
1312 logger.finest("CookieHandler request for " + uri);
1313 }
1314 Map<String, List<String>> cookies
1315 = cookieHandler.get(
1316 uri, requests.getHeaders(EXCLUDE_HEADERS));
1317 if (!cookies.isEmpty()) {
1318 if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
1319 logger.finest("Cookies retrieved: " + cookies.toString());
1320 }
1321 for (Map.Entry<String, List<String>> entry :
1322 cookies.entrySet()) {
1323 String key = entry.getKey();
1324 // ignore all entries that don't have "Cookie"
1325 // or "Cookie2" as keys
1326 if (!"Cookie".equalsIgnoreCase(key) &&
1327 !"Cookie2".equalsIgnoreCase(key)) {
1328 continue;
1329 }
1330 List<String> l = entry.getValue();
1331 if (l != null && !l.isEmpty()) {
1332 StringBuilder cookieValue = new StringBuilder();
1333 for (String value : l) {
1334 cookieValue.append(value).append("; ");
1335 }
1336 // strip off the trailing '; '
1337 try {
1338 requests.add(key, cookieValue.substring(0, cookieValue.length() - 2));
1459 }
1460
1461 // Check if URL should be metered
1462 boolean meteredInput = ProgressMonitor.getDefault().shouldMeterInput(url, method);
1463
1464 if (meteredInput) {
1465 pi = new ProgressSource(url, method);
1466 pi.beginTracking();
1467 }
1468
1469 /* REMIND: This exists to fix the HttpsURLConnection subclass.
1470 * Hotjava needs to run on JDK1.1FCS. Do proper fix once a
1471 * proper solution for SSL can be found.
1472 */
1473 ps = (PrintStream)http.getOutputStream();
1474
1475 if (!streaming()) {
1476 writeRequests();
1477 }
1478 http.parseHTTP(responses, pi, this);
1479 if (logger.isLoggable(PlatformLogger.Level.FINE)) {
1480 logger.fine(responses.toString());
1481 }
1482
1483 boolean b1 = responses.filterNTLMResponses("WWW-Authenticate");
1484 boolean b2 = responses.filterNTLMResponses("Proxy-Authenticate");
1485 if (b1 || b2) {
1486 if (logger.isLoggable(PlatformLogger.Level.FINE)) {
1487 logger.fine(">>>> Headers are filtered");
1488 logger.fine(responses.toString());
1489 }
1490 }
1491
1492 inputStream = http.getInputStream();
1493
1494 respCode = getResponseCode();
1495 if (respCode == -1) {
1496 disconnectInternal();
1497 throw new IOException ("Invalid Http response");
1498 }
1499 if (respCode == HTTP_PROXY_AUTH) {
1500 if (streaming()) {
1501 disconnectInternal();
1502 throw new HttpRetryException (
1503 RETRY_MSG1, HTTP_PROXY_AUTH);
1504 }
1505
1506 // Read comments labeled "Failed Negotiate" for details.
1926 boolean inNegotiateProxy = false;
1927
1928 try {
1929 /* Actively setting up a tunnel */
1930 setTunnelState(TunnelState.SETUP);
1931
1932 do {
1933 if (!checkReuseConnection()) {
1934 proxiedConnect(url, proxyHost, proxyPort, false);
1935 }
1936 // send the "CONNECT" request to establish a tunnel
1937 // through proxy server
1938 sendCONNECTRequest();
1939 responses.reset();
1940
1941 // There is no need to track progress in HTTP Tunneling,
1942 // so ProgressSource is null.
1943 http.parseHTTP(responses, null, this);
1944
1945 /* Log the response to the CONNECT */
1946 if (logger.isLoggable(PlatformLogger.Level.FINE)) {
1947 logger.fine(responses.toString());
1948 }
1949
1950 if (responses.filterNTLMResponses("Proxy-Authenticate")) {
1951 if (logger.isLoggable(PlatformLogger.Level.FINE)) {
1952 logger.fine(">>>> Headers are filtered");
1953 logger.fine(responses.toString());
1954 }
1955 }
1956
1957 statusLine = responses.getValue(0);
1958 StringTokenizer st = new StringTokenizer(statusLine);
1959 st.nextToken();
1960 respCode = Integer.parseInt(st.nextToken().trim());
1961 if (respCode == HTTP_PROXY_AUTH) {
1962 // Read comments labeled "Failed Negotiate" for details.
1963 boolean dontUseNegotiate = false;
1964 Iterator<String> iter = responses.multiValueIterator("Proxy-Authenticate");
1965 while (iter.hasNext()) {
1966 String value = iter.next().trim();
1967 if (value.equalsIgnoreCase("Negotiate") ||
1968 value.equalsIgnoreCase("Kerberos")) {
1969 if (!inNegotiateProxy) {
1970 inNegotiateProxy = true;
1971 } else {
2058 requests.set(0, HTTP_CONNECT + " " + connectRequestURI(url)
2059 + " " + httpVersion, null);
2060 requests.setIfNotSet("User-Agent", userAgent);
2061
2062 String host = url.getHost();
2063 if (port != -1 && port != url.getDefaultPort()) {
2064 host += ":" + String.valueOf(port);
2065 }
2066 requests.setIfNotSet("Host", host);
2067
2068 // Not really necessary for a tunnel, but can't hurt
2069 requests.setIfNotSet("Accept", acceptString);
2070
2071 if (http.getHttpKeepAliveSet()) {
2072 requests.setIfNotSet("Proxy-Connection", "keep-alive");
2073 }
2074
2075 setPreemptiveProxyAuthentication(requests);
2076
2077 /* Log the CONNECT request */
2078 if (logger.isLoggable(PlatformLogger.Level.FINE)) {
2079 logger.fine(requests.toString());
2080 }
2081
2082 http.writeRequests(requests, null);
2083 }
2084
2085 /**
2086 * Sets pre-emptive proxy authentication in header
2087 */
2088 private void setPreemptiveProxyAuthentication(MessageHeader requests) throws IOException {
2089 AuthenticationInfo pauth
2090 = AuthenticationInfo.getProxyAuth(http.getProxyHostUsed(),
2091 http.getProxyPortUsed());
2092 if (pauth != null && pauth.supportsPreemptiveAuthorization()) {
2093 String value;
2094 if (pauth instanceof DigestAuthentication) {
2095 DigestAuthentication digestProxy = (DigestAuthentication) pauth;
2096 if (tunnelState() == TunnelState.SETUP) {
2097 value = digestProxy
2098 .getHeaderValue(connectRequestURI(url), HTTP_CONNECT);
2201 * transparent authentication (Windows only) the username
2202 * and password will be picked up from the current logged
2203 * on users credentials.
2204 */
2205 if (tryTransparentNTLMProxy ||
2206 (!tryTransparentNTLMProxy && a != null)) {
2207 ret = NTLMAuthenticationProxy.proxy.create(true, host, port, a);
2208 }
2209
2210 /* set to false so that we do not try again */
2211 tryTransparentNTLMProxy = false;
2212 }
2213 break;
2214 case NEGOTIATE:
2215 ret = new NegotiateAuthentication(new HttpCallerInfo(authhdr.getHttpCallerInfo(), "Negotiate"));
2216 break;
2217 case KERBEROS:
2218 ret = new NegotiateAuthentication(new HttpCallerInfo(authhdr.getHttpCallerInfo(), "Kerberos"));
2219 break;
2220 case UNKNOWN:
2221 if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
2222 logger.finest("Unknown/Unsupported authentication scheme: " + scheme);
2223 }
2224 /*fall through*/
2225 default:
2226 throw new AssertionError("should not reach here");
2227 }
2228 }
2229 // For backwards compatibility, we also try defaultAuth
2230 // REMIND: Get rid of this for JDK2.0.
2231
2232 if (ret == null && defaultAuth != null
2233 && defaultAuth.schemeSupported(scheme)) {
2234 try {
2235 URL u = new URL("http", host, port, "/");
2236 String a = defaultAuth.authString(u, scheme, realm);
2237 if (a != null) {
2238 ret = new BasicAuthentication (true, host, port, realm, a);
2239 // not in cache by default - cache on success
2240 }
2241 } catch (java.net.MalformedURLException ignored) {
2242 }
2243 }
2244 if (ret != null) {
2245 if (!ret.setHeaders(this, p, raw)) {
2246 ret = null;
2247 }
2248 }
2249 }
2250 if (logger.isLoggable(PlatformLogger.Level.FINER)) {
2251 logger.finer("Proxy Authentication for " + authhdr.toString() +" returned " + (ret != null ? ret.toString() : "null"));
2252 }
2253 return ret;
2254 }
2255
2256 /**
2257 * Gets the authentication for an HTTP server, and applies it to
2258 * the connection.
2259 * @param authHdr the AuthenticationHeader which tells what auth scheme is
2260 * prefered.
2261 */
2262 @SuppressWarnings("fallthrough")
2263 private AuthenticationInfo getServerAuthentication (AuthenticationHeader authhdr) {
2264 /* get authorization from authenticator */
2265 AuthenticationInfo ret = null;
2266 String raw = authhdr.raw();
2267 /* When we get an NTLM auth from cache, don't set any special headers */
2268 if (authhdr.isPresent()) {
2269 HeaderParser p = authhdr.headerParser();
2270 String realm = p.findValue("realm");
2360 url.getHost(), addr, port, url.getProtocol(),
2361 "", scheme, url, RequestorType.SERVER);
2362 }
2363
2364 /* If we are not trying transparent authentication then
2365 * we need to have a PasswordAuthentication instance. For
2366 * transparent authentication (Windows only) the username
2367 * and password will be picked up from the current logged
2368 * on users credentials.
2369 */
2370 if (tryTransparentNTLMServer ||
2371 (!tryTransparentNTLMServer && a != null)) {
2372 ret = NTLMAuthenticationProxy.proxy.create(false, url1, a);
2373 }
2374
2375 /* set to false so that we do not try again */
2376 tryTransparentNTLMServer = false;
2377 }
2378 break;
2379 case UNKNOWN:
2380 if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
2381 logger.finest("Unknown/Unsupported authentication scheme: " + scheme);
2382 }
2383 /*fall through*/
2384 default:
2385 throw new AssertionError("should not reach here");
2386 }
2387 }
2388
2389 // For backwards compatibility, we also try defaultAuth
2390 // REMIND: Get rid of this for JDK2.0.
2391
2392 if (ret == null && defaultAuth != null
2393 && defaultAuth.schemeSupported(scheme)) {
2394 String a = defaultAuth.authString(url, scheme, realm);
2395 if (a != null) {
2396 ret = new BasicAuthentication (false, url, realm, a);
2397 // not in cache by default - cache on success
2398 }
2399 }
2400
2401 if (ret != null ) {
2402 if (!ret.setHeaders(this, p, raw)) {
2403 ret = null;
2404 }
2405 }
2406 }
2407 if (logger.isLoggable(PlatformLogger.Level.FINER)) {
2408 logger.finer("Server Authentication for " + authhdr.toString() +" returned " + (ret != null ? ret.toString() : "null"));
2409 }
2410 return ret;
2411 }
2412
2413 /* inclose will be true if called from close(), in which case we
2414 * force the call to check because this is the last chance to do so.
2415 * If not in close(), then the authentication info could arrive in a trailer
2416 * field, which we have not read yet.
2417 */
2418 private void checkResponseCredentials (boolean inClose) throws IOException {
2419 try {
2420 if (!needToCheck)
2421 return;
2422 if ((validateProxy && currentProxyCredentials != null) &&
2423 (currentProxyCredentials instanceof DigestAuthentication)) {
2424 String raw = responses.findValue ("Proxy-Authentication-Info");
2425 if (inClose || (raw != null)) {
2426 DigestAuthentication da = (DigestAuthentication)
2427 currentProxyCredentials;
2515 throw (IOException) e.getException();
2516 }
2517 } else {
2518 // run without additional permission
2519 return followRedirect0(loc, stat, locUrl);
2520 }
2521 }
2522
2523 /* Tells us whether to follow a redirect. If so, it
2524 * closes the connection (break any keep-alive) and
2525 * resets the url, re-connects, and resets the request
2526 * property.
2527 */
2528 private boolean followRedirect0(String loc, int stat, URL locUrl)
2529 throws IOException
2530 {
2531 disconnectInternal();
2532 if (streaming()) {
2533 throw new HttpRetryException (RETRY_MSG3, stat, loc);
2534 }
2535 if (logger.isLoggable(PlatformLogger.Level.FINE)) {
2536 logger.fine("Redirected from " + url + " to " + locUrl);
2537 }
2538
2539 // clear out old response headers!!!!
2540 responses = new MessageHeader();
2541 if (stat == HTTP_USE_PROXY) {
2542 /* This means we must re-request the resource through the
2543 * proxy denoted in the "Location:" field of the response.
2544 * Judging by the spec, the string in the Location header
2545 * _should_ denote a URL - let's hope for "http://my.proxy.org"
2546 * Make a new HttpClient to the proxy, using HttpClient's
2547 * Instance-specific proxy fields, but note we're still fetching
2548 * the same URL.
2549 */
2550 String proxyHost = locUrl.getHost();
2551 int proxyPort = locUrl.getPort();
2552
2553 SecurityManager security = System.getSecurityManager();
2554 if (security != null) {
2555 security.checkConnect(proxyHost, proxyPort);
|