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