Пример #1
0
  private HTTPSSLKeyManager createKeyManager() {
    if (!myIsSecured) {
      return null;
    }

    SVNURL location = myRepository.getLocation();
    ISVNAuthenticationManager authManager = myRepository.getAuthenticationManager();
    String sslRealm =
        "<" + location.getProtocol() + "://" + location.getHost() + ":" + location.getPort() + ">";
    return new HTTPSSLKeyManager(authManager, sslRealm, location);
  }
Пример #2
0
 public DefaultSVNSSLTrustManager(
     File authDir,
     SVNURL url,
     File[] serverCertFiles,
     boolean useKeyStore,
     DefaultSVNAuthenticationManager authManager) {
   myURL = url;
   myAuthDirectory = authDir;
   myRealm = "https://" + url.getHost() + ":" + url.getPort();
   myAuthManager = authManager;
   myIsUseKeyStore = useKeyStore;
   myServerCertFiles = serverCertFiles;
 }
Пример #3
0
  private void connect(HTTPSSLKeyManager keyManager, TrustManager trustManager)
      throws IOException, SVNException {
    SVNURL location = myRepository.getLocation();

    if (mySocket == null || SVNSocketFactory.isSocketStale(mySocket)) {
      close();
      String host = location.getHost();
      int port = location.getPort();

      ISVNAuthenticationManager authManager = myRepository.getAuthenticationManager();
      ISVNProxyManager proxyAuth =
          authManager != null ? authManager.getProxyManager(location) : null;
      int connectTimeout = authManager != null ? authManager.getConnectTimeout(myRepository) : 0;
      int readTimeout =
          authManager != null ? authManager.getReadTimeout(myRepository) : DEFAULT_HTTP_TIMEOUT;
      if (readTimeout < 0) {
        readTimeout = DEFAULT_HTTP_TIMEOUT;
      }
      if (proxyAuth != null && proxyAuth.getProxyHost() != null) {
        myRepository
            .getDebugLog()
            .logFine(
                SVNLogType.NETWORK,
                "Using proxy " + proxyAuth.getProxyHost() + " (secured=" + myIsSecured + ")");
        mySocket =
            SVNSocketFactory.createPlainSocket(
                proxyAuth.getProxyHost(), proxyAuth.getProxyPort(), connectTimeout, readTimeout);
        if (myProxyAuthentication == null) {
          myProxyAuthentication =
              new HTTPBasicAuthentication(
                  proxyAuth.getProxyUserName(), proxyAuth.getProxyPassword(), myCharset);
        }
        myIsProxied = true;
        if (myIsSecured) {
          HTTPRequest connectRequest = new HTTPRequest(myCharset);
          connectRequest.setConnection(this);
          connectRequest.initCredentials(myProxyAuthentication, "CONNECT", host + ":" + port);
          connectRequest.setProxyAuthentication(myProxyAuthentication.authenticate());
          connectRequest.setForceProxyAuth(true);
          connectRequest.dispatch("CONNECT", host + ":" + port, null, 0, 0, null);
          HTTPStatus status = connectRequest.getStatus();
          if (status.getCode() == HttpURLConnection.HTTP_OK) {
            myInputStream = null;
            myOutputStream = null;
            mySocket =
                SVNSocketFactory.createSSLSocket(
                    keyManager != null ? new KeyManager[] {keyManager} : new KeyManager[0],
                    trustManager,
                    host,
                    port,
                    mySocket,
                    readTimeout);
            proxyAuth.acknowledgeProxyContext(true, null);
            return;
          }
          SVNURL proxyURL =
              SVNURL.parseURIEncoded(
                  "http://" + proxyAuth.getProxyHost() + ":" + proxyAuth.getProxyPort());
          SVNErrorMessage err =
              SVNErrorMessage.create(
                  SVNErrorCode.RA_DAV_REQUEST_FAILED,
                  "{0} request failed on ''{1}''",
                  new Object[] {"CONNECT", proxyURL});
          proxyAuth.acknowledgeProxyContext(false, err);
          SVNErrorManager.error(err, connectRequest.getErrorMessage(), SVNLogType.NETWORK);
        }
      } else {
        myIsProxied = false;
        myProxyAuthentication = null;
        mySocket =
            myIsSecured
                ? SVNSocketFactory.createSSLSocket(
                    keyManager != null ? new KeyManager[] {keyManager} : new KeyManager[0],
                    trustManager,
                    host,
                    port,
                    connectTimeout,
                    readTimeout)
                : SVNSocketFactory.createPlainSocket(host, port, connectTimeout, readTimeout);
      }
    }
  }
Пример #4
0
  public HTTPStatus request(
      String method,
      String path,
      HTTPHeader header,
      InputStream body,
      int ok1,
      int ok2,
      OutputStream dst,
      DefaultHandler handler,
      SVNErrorMessage context)
      throws SVNException {
    if ("".equals(path) || path == null) {
      path = "/";
    }

    // 1. prompt for ssl client cert if needed, if cancelled - throw cancellation exception.
    HTTPSSLKeyManager keyManager =
        myKeyManager == null && myRepository.getAuthenticationManager() != null
            ? createKeyManager()
            : myKeyManager;
    TrustManager trustManager =
        myTrustManager == null && myRepository.getAuthenticationManager() != null
            ? myRepository.getAuthenticationManager().getTrustManager(myRepository.getLocation())
            : myTrustManager;

    String sslRealm =
        "<" + myHost.getProtocol() + "://" + myHost.getHost() + ":" + myHost.getPort() + ">";
    SVNAuthentication httpAuth = myLastValidAuth;
    boolean isAuthForced =
        myRepository.getAuthenticationManager() != null
            ? myRepository.getAuthenticationManager().isAuthenticationForced()
            : false;
    if (httpAuth == null && isAuthForced) {
      httpAuth =
          myRepository
              .getAuthenticationManager()
              .getFirstAuthentication(ISVNAuthenticationManager.PASSWORD, sslRealm, null);
      myChallengeCredentials =
          new HTTPBasicAuthentication((SVNPasswordAuthentication) httpAuth, myCharset);
    }
    String realm = null;

    // 2. create request instance.
    HTTPRequest request = new HTTPRequest(myCharset);
    request.setConnection(this);
    request.setKeepAlive(true);
    request.setRequestBody(body);
    request.setResponseHandler(handler);
    request.setResponseStream(dst);

    SVNErrorMessage err = null;
    boolean ntlmAuthIsRequired = false;
    boolean ntlmProxyAuthIsRequired = false;
    boolean negoAuthIsRequired = false;
    int authAttempts = 0;
    while (true) {
      HTTPStatus status = null;
      if (System.currentTimeMillis() >= myNextRequestTimeout) {
        SVNDebugLog.getDefaultLog().logFine(SVNLogType.NETWORK, "Keep-Alive timeout detected");
        close();
      }
      int retryCount = 1;
      try {
        err = null;
        String httpAuthResponse = null;
        String proxyAuthResponse = null;
        while (retryCount >= 0) {
          connect(keyManager, trustManager);
          request.reset();
          request.setProxied(myIsProxied);
          request.setSecured(myIsSecured);
          if (myProxyAuthentication != null
              && (ntlmProxyAuthIsRequired
                  || !"NTLM".equals(myProxyAuthentication.getAuthenticationScheme()))) {
            if (proxyAuthResponse == null) {
              request.initCredentials(myProxyAuthentication, method, path);
              proxyAuthResponse = myProxyAuthentication.authenticate();
            }
            request.setProxyAuthentication(proxyAuthResponse);
          }

          if (myChallengeCredentials != null
              && (ntlmAuthIsRequired
                  || negoAuthIsRequired
                  || ((!"NTLM".equals(myChallengeCredentials.getAuthenticationScheme()))
                          && !"Negotiate".equals(myChallengeCredentials.getAuthenticationScheme()))
                      && httpAuth != null)) {
            if (httpAuthResponse == null) {
              request.initCredentials(myChallengeCredentials, method, path);
              httpAuthResponse = myChallengeCredentials.authenticate();
            }
            request.setAuthentication(httpAuthResponse);
          }

          try {
            request.dispatch(method, path, header, ok1, ok2, context);
            break;
          } catch (EOFException pe) {
            // retry, EOF always means closed connection.
            if (retryCount > 0) {
              close();
              continue;
            }
            throw (IOException) new IOException(pe.getMessage()).initCause(pe);
          } finally {
            retryCount--;
          }
        }
        myNextRequestTimeout = request.getNextRequestTimeout();
        status = request.getStatus();
      } catch (SSLHandshakeException ssl) {
        myRepository.getDebugLog().logFine(SVNLogType.NETWORK, ssl);
        close();
        if (ssl.getCause() instanceof SVNSSLUtil.CertificateNotTrustedException) {
          SVNErrorManager.cancel(ssl.getCause().getMessage(), SVNLogType.NETWORK);
        }
        SVNErrorMessage sslErr =
            SVNErrorMessage.create(
                SVNErrorCode.RA_NOT_AUTHORIZED,
                "SSL handshake failed: ''{0}''",
                new Object[] {ssl.getMessage()},
                SVNErrorMessage.TYPE_ERROR,
                ssl);
        if (keyManager != null) {
          keyManager.acknowledgeAndClearAuthentication(sslErr);
        }
        err = SVNErrorMessage.create(SVNErrorCode.RA_DAV_REQUEST_FAILED, ssl);
        // continue; http://svnkit.com/tracker/view.php?id=301 - Kohsuke
      } catch (IOException e) {
        myRepository.getDebugLog().logFine(SVNLogType.NETWORK, e);
        if (e instanceof SocketTimeoutException) {
          err =
              SVNErrorMessage.create(
                  SVNErrorCode.RA_DAV_REQUEST_FAILED,
                  "timed out waiting for server",
                  null,
                  SVNErrorMessage.TYPE_ERROR,
                  e);
        } else if (e instanceof UnknownHostException) {
          err =
              SVNErrorMessage.create(
                  SVNErrorCode.RA_DAV_REQUEST_FAILED,
                  "unknown host",
                  null,
                  SVNErrorMessage.TYPE_ERROR,
                  e);
        } else if (e instanceof ConnectException) {
          err =
              SVNErrorMessage.create(
                  SVNErrorCode.RA_DAV_REQUEST_FAILED,
                  "connection refused by the server",
                  null,
                  SVNErrorMessage.TYPE_ERROR,
                  e);
        } else if (e instanceof SVNCancellableOutputStream.IOCancelException) {
          SVNErrorManager.cancel(e.getMessage(), SVNLogType.NETWORK);
        } else if (e instanceof SSLException) {
          err = SVNErrorMessage.create(SVNErrorCode.RA_DAV_REQUEST_FAILED, e);
        } else {
          err = SVNErrorMessage.create(SVNErrorCode.RA_DAV_REQUEST_FAILED, e);
        }
      } catch (SVNException e) {
        myRepository.getDebugLog().logFine(SVNLogType.NETWORK, e);
        // force connection close on SVNException
        // (could be thrown by user's auth manager methods).
        close();
        throw e;
      } finally {
        finishResponse(request);
      }

      if (err != null) {
        close();
        break;
      }

      if (keyManager != null) {
        myKeyManager = keyManager;
        myTrustManager = trustManager;
        keyManager.acknowledgeAndClearAuthentication(null);
      }

      if (status.getCode() == HttpURLConnection.HTTP_FORBIDDEN) {
        myLastValidAuth = null;
        close();
        err = request.getErrorMessage();
      } else if (myIsProxied && status.getCode() == HttpURLConnection.HTTP_PROXY_AUTH) {
        Collection proxyAuthHeaders =
            request.getResponseHeader().getHeaderValues(HTTPHeader.PROXY_AUTHENTICATE_HEADER);
        try {
          myProxyAuthentication =
              HTTPAuthentication.parseAuthParameters(
                  proxyAuthHeaders, myProxyAuthentication, myCharset);
        } catch (SVNException svne) {
          myRepository.getDebugLog().logFine(SVNLogType.NETWORK, svne);
          err = svne.getErrorMessage();
          break;
        }

        if (myProxyAuthentication instanceof HTTPNTLMAuthentication) {
          ntlmProxyAuthIsRequired = true;
          HTTPNTLMAuthentication ntlmProxyAuth = (HTTPNTLMAuthentication) myProxyAuthentication;
          if (ntlmProxyAuth.isInType3State()) {
            continue;
          }
        }

        err =
            SVNErrorMessage.create(
                SVNErrorCode.RA_NOT_AUTHORIZED, "HTTP proxy authorization failed");
        SVNURL location = myRepository.getLocation();
        ISVNAuthenticationManager authManager = myRepository.getAuthenticationManager();
        ISVNProxyManager proxyManager =
            authManager != null ? authManager.getProxyManager(location) : null;
        if (proxyManager != null) {
          proxyManager.acknowledgeProxyContext(false, err);
        }
        close();

        break;
      } else if (status.getCode() == HttpURLConnection.HTTP_UNAUTHORIZED) {
        authAttempts++; // how many times did we try?

        Collection authHeaderValues =
            request.getResponseHeader().getHeaderValues(HTTPHeader.AUTHENTICATE_HEADER);
        if (authHeaderValues == null || authHeaderValues.size() == 0) {
          err = request.getErrorMessage();
          status.setError(
              SVNErrorMessage.create(
                  SVNErrorCode.RA_DAV_REQUEST_FAILED,
                  err.getMessageTemplate(),
                  err.getRelatedObjects()));
          if ("LOCK".equalsIgnoreCase(method)) {
            status
                .getError()
                .setChildErrorMessage(
                    SVNErrorMessage.create(
                        SVNErrorCode.UNSUPPORTED_FEATURE,
                        "Probably you are trying to lock file in repository that only allows anonymous access"));
          }
          SVNErrorManager.error(status.getError(), SVNLogType.NETWORK);
          return status;
        }

        // we should work around a situation when a server
        // does not support Basic authentication while we're
        // forcing it, credentials should not be immediately
        // thrown away
        boolean skip = false;
        isAuthForced =
            myRepository.getAuthenticationManager() != null
                ? myRepository.getAuthenticationManager().isAuthenticationForced()
                : false;
        if (isAuthForced) {
          if (httpAuth != null
              && myChallengeCredentials != null
              && !HTTPAuthentication.isSchemeSupportedByServer(
                  myChallengeCredentials.getAuthenticationScheme(), authHeaderValues)) {
            skip = true;
          }
        }

        try {
          myChallengeCredentials =
              HTTPAuthentication.parseAuthParameters(
                  authHeaderValues, myChallengeCredentials, myCharset);
        } catch (SVNException svne) {
          err = svne.getErrorMessage();
          break;
        }

        myChallengeCredentials.setChallengeParameter("methodname", method);
        myChallengeCredentials.setChallengeParameter("uri", path);

        if (skip) {
          close();
          continue;
        }

        HTTPNTLMAuthentication ntlmAuth = null;
        HTTPNegotiateAuthentication negoAuth = null;
        if (myChallengeCredentials instanceof HTTPNTLMAuthentication) {
          ntlmAuthIsRequired = true;
          ntlmAuth = (HTTPNTLMAuthentication) myChallengeCredentials;
          if (ntlmAuth.isInType3State()) {
            continue;
          }
        } else if (myChallengeCredentials instanceof HTTPDigestAuthentication) {
          // continue (retry once) if previous request was acceppted?
          if (myLastValidAuth != null) {
            myLastValidAuth = null;
            continue;
          }
        } else if (myChallengeCredentials instanceof HTTPNegotiateAuthentication) {
          negoAuthIsRequired = true;
          negoAuth = (HTTPNegotiateAuthentication) myChallengeCredentials;
          if (negoAuth.isStarted()) {
            continue;
          }
        }

        myLastValidAuth = null;

        if (ntlmAuth != null && ntlmAuth.isNative() && authAttempts == 1) {
          /*
           * if this is the first time we get HTTP_UNAUTHORIZED, NTLM is the target auth scheme
           * and JNA is available, we should try a native auth mechanism first without calling
           * auth providers.
           */
          continue;
        }

        if (negoAuth != null) {
          continue;
        }

        ISVNAuthenticationManager authManager = myRepository.getAuthenticationManager();
        if (authManager == null) {
          err = request.getErrorMessage();
          break;
        }

        realm = myChallengeCredentials.getChallengeParameter("realm");
        realm = realm == null ? "" : " " + realm;
        realm =
            "<"
                + myHost.getProtocol()
                + "://"
                + myHost.getHost()
                + ":"
                + myHost.getPort()
                + ">"
                + realm;

        if (httpAuth == null) {
          httpAuth =
              authManager.getFirstAuthentication(
                  ISVNAuthenticationManager.PASSWORD, realm, myRepository.getLocation());
        } else {
          authManager.acknowledgeAuthentication(
              false,
              ISVNAuthenticationManager.PASSWORD,
              realm,
              request.getErrorMessage(),
              httpAuth);
          httpAuth =
              authManager.getNextAuthentication(
                  ISVNAuthenticationManager.PASSWORD, realm, myRepository.getLocation());
        }

        if (httpAuth == null) {
          err = SVNErrorMessage.create(SVNErrorCode.CANCELLED, "HTTP authorization cancelled");
          break;
        }
        if (httpAuth != null) {
          myChallengeCredentials.setCredentials((SVNPasswordAuthentication) httpAuth);
        }
        continue;
      } else if (status.getCode() == HttpURLConnection.HTTP_MOVED_PERM
          || status.getCode() == HttpURLConnection.HTTP_MOVED_TEMP) {
        close();
        String newLocation =
            request.getResponseHeader().getFirstHeaderValue(HTTPHeader.LOCATION_HEADER);
        if (newLocation == null) {
          err = request.getErrorMessage();
          break;
        }
        int hostIndex = newLocation.indexOf("://");
        if (hostIndex > 0) {
          hostIndex += 3;
          hostIndex = newLocation.indexOf("/", hostIndex);
        }
        if (hostIndex > 0 && hostIndex < newLocation.length()) {
          String newPath = newLocation.substring(hostIndex);
          if (newPath.endsWith("/")
              && !newPath.endsWith("//")
              && !path.endsWith("/")
              && newPath.substring(0, newPath.length() - 1).equals(path)) {
            path += "//";
            continue;
          }
        }
        err = request.getErrorMessage();
      } else if (request.getErrorMessage() != null) {
        err = request.getErrorMessage();
      } else {
        ntlmProxyAuthIsRequired = false;
        ntlmAuthIsRequired = false;
        negoAuthIsRequired = false;
      }

      if (err != null) {
        break;
      }

      if (myIsProxied) {
        SVNURL location = myRepository.getLocation();
        ISVNAuthenticationManager authManager = myRepository.getAuthenticationManager();
        ISVNProxyManager proxyManager =
            authManager != null ? authManager.getProxyManager(location) : null;
        if (proxyManager != null) {
          proxyManager.acknowledgeProxyContext(true, null);
        }
      }

      if (httpAuth != null && realm != null && myRepository.getAuthenticationManager() != null) {
        myRepository
            .getAuthenticationManager()
            .acknowledgeAuthentication(
                true, ISVNAuthenticationManager.PASSWORD, realm, null, httpAuth);
      }
      if (trustManager != null && myRepository.getAuthenticationManager() != null) {
        myRepository.getAuthenticationManager().acknowledgeTrustManager(trustManager);
      }

      if (httpAuth != null) {
        myLastValidAuth = httpAuth;
      }

      status.setHeader(request.getResponseHeader());
      return status;
    }
    // force close on error that was not processed before.
    // these are errors that has no relation to http status (processing error or cancellation).
    close();
    if (err != null
        && err.getErrorCode().getCategory() != SVNErrorCode.RA_DAV_CATEGORY
        && err.getErrorCode() != SVNErrorCode.UNSUPPORTED_FEATURE) {
      SVNErrorManager.error(err, SVNLogType.NETWORK);
    }
    // err2 is another default context...
    //        myRepository.getDebugLog().info(err.getMessage());
    myRepository.getDebugLog().logFine(SVNLogType.NETWORK, new Exception(err.getMessage()));
    SVNErrorMessage err2 =
        SVNErrorMessage.create(
            SVNErrorCode.RA_DAV_REQUEST_FAILED,
            "{0} request failed on ''{1}''",
            new Object[] {method, path},
            err.getType(),
            err.getCause());
    SVNErrorManager.error(err, err2, SVNLogType.NETWORK);
    return null;
  }
 public SVNAuthentication requestClientAuthentication(
     String kind,
     SVNURL url,
     String realm,
     SVNErrorMessage errorMessage,
     SVNAuthentication previousAuth,
     boolean authMayBeStored) {
   // get from key-ring, use realm.
   realm = realm == null ? DEFAULT_URL.toString() : realm;
   Map info = Platform.getAuthorizationInfo(DEFAULT_URL, realm, kind);
   // convert info to SVNAuthentication.
   if (info != null && ISVNAuthenticationManager.SSL.equals(kind)) {
     String sslKind = (String) info.get("ssl-kind");
     if (sslKind != null && SVNSSLAuthentication.MSCAPI.equals(sslKind)) {
       String alias = (String) info.get("alias");
       return new SVNSSLAuthentication(sslKind, alias, authMayBeStored, url, false);
     }
     String password = (String) info.get("password");
     if (SVNSSLAuthentication.isCertificatePath(realm)) {
       if (password != null) {
         return new SVNPasswordAuthentication("", password, authMayBeStored, url, false);
       }
     } else {
       String path = (String) info.get("cert");
       if (path != null) {
         SVNSSLAuthentication auth =
             new SVNSSLAuthentication(new File(path), password, authMayBeStored, url, false);
         auth.setCertificatePath(path);
         return auth;
       }
     }
   } else if (info != null && !info.isEmpty() && info.get("username") != null) {
     if (ISVNAuthenticationManager.PASSWORD.equals(kind)) {
       return new SVNPasswordAuthentication(
           (String) info.get("username"),
           (String) info.get("password"),
           authMayBeStored,
           url,
           false);
     } else if (ISVNAuthenticationManager.SSH.equals(kind)) {
       int port = url.hasPort() ? url.getPort() : -1;
       if (port < 0 && info.get("port") != null) {
         port = Integer.parseInt((String) info.get("port"));
       }
       if (port < 0) {
         // will give us default port.
         port = url.getPort();
       }
       if (info.get("key") != null) {
         File keyPath = new File((String) info.get("key"));
         return new SVNSSHAuthentication(
             (String) info.get("username"),
             keyPath,
             (String) info.get("passphrase"),
             port,
             authMayBeStored,
             url,
             false);
       } else if (info.get("password") != null) {
         return new SVNSSHAuthentication(
             (String) info.get("username"),
             (String) info.get("password"),
             port,
             authMayBeStored,
             url,
             false);
       }
     } else if (ISVNAuthenticationManager.USERNAME.equals(kind)) {
       return new SVNUserNameAuthentication(
           (String) info.get("username"), authMayBeStored, url, false);
     }
   }
   return null;
 }