src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java

Print this page




 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);