/* * ==================================================================== * Copyright (c) 2004-2012 TMate Software Ltd. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://svnkit.com/license.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * ==================================================================== */ package org.tmatesoft.svn.core.internal.io.svn; import java.io.IOException; import java.util.List; import org.tmatesoft.svn.core.SVNErrorCode; import org.tmatesoft.svn.core.SVNErrorMessage; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.auth.BasicAuthenticationManager; import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager; import org.tmatesoft.svn.core.auth.SVNAuthentication; import org.tmatesoft.svn.core.auth.SVNPasswordAuthentication; import org.tmatesoft.svn.core.internal.wc.SVNErrorManager; import org.tmatesoft.svn.util.SVNLogType; /** * @version 1.3 * @author TMate Software Ltd. */ public class SVNPlainAuthenticator extends SVNAuthenticator { public SVNPlainAuthenticator(SVNConnection connection) throws SVNException { super(connection); } public SVNAuthentication authenticate(List mechs, String realm, SVNRepositoryImpl repos) throws SVNException { SVNErrorMessage failureReason = null; if (mechs == null || mechs.size() == 0) { return null; } ISVNAuthenticationManager authManager = repos.getAuthenticationManager(); if (authManager != null && authManager.isAuthenticationForced() && mechs.contains("ANONYMOUS") && mechs.contains("CRAM-MD5")) { mechs.remove("ANONYMOUS"); } SVNURL location = repos.getLocation(); SVNPasswordAuthentication auth = null; if (repos.getExternalUserName() != null && mechs.contains("EXTERNAL")) { getConnection().write("(w(s))", new Object[]{"EXTERNAL", ""}); failureReason = readAuthResponse(); } else if (mechs.contains("ANONYMOUS")) { getConnection().write("(w(s))", new Object[]{"ANONYMOUS", ""}); failureReason = readAuthResponse(); } else if (mechs.contains("CRAM-MD5")) { while (true) { CramMD5 authenticator = new CramMD5(); if (location != null) { realm = "<" + location.getProtocol() + "://" + location.getHost() + ":" + location.getPort() + "> " + realm; } try { if (auth == null && authManager != null) { auth = (SVNPasswordAuthentication) authManager.getFirstAuthentication(ISVNAuthenticationManager.PASSWORD, realm, location); } else if (authManager != null) { BasicAuthenticationManager.acknowledgeAuthentication(false, ISVNAuthenticationManager.PASSWORD, realm, failureReason, auth, location, authManager); auth = (SVNPasswordAuthentication) authManager.getNextAuthentication(ISVNAuthenticationManager.PASSWORD, realm, location); } } catch (SVNException e) { if (e.getErrorMessage().getErrorCode() == SVNErrorCode.CANCELLED) { throw e; } else if (getLastError() != null) { SVNErrorManager.error(getLastError(), SVNLogType.NETWORK); } throw e; } if (auth == null) { failureReason = SVNErrorMessage.create(SVNErrorCode.CANCELLED, "Authentication cancelled"); setLastError(failureReason); break; } if (auth.getUserName() == null || auth.getPasswordValue() == null) { failureReason = SVNErrorMessage.create(SVNErrorCode.RA_NOT_AUTHORIZED, "Can''t get password. Authentication is required for ''{0}''", realm); break; } getConnection().write("(w())", new Object[]{"CRAM-MD5"}); while (true) { authenticator.setUserCredentials(auth); List items = getConnection().readTuple("w(?s)", true); String status = SVNReader.getString(items, 0); if (SVNAuthenticator.SUCCESS.equals(status)) { BasicAuthenticationManager.acknowledgeAuthentication(true, ISVNAuthenticationManager.PASSWORD, realm, null, auth, location, authManager); return auth; } else if (SVNAuthenticator.FAILURE.equals(status)) { failureReason = SVNErrorMessage.create(SVNErrorCode.RA_NOT_AUTHORIZED, "Authentication error from server: {0}", SVNReader.getString(items, 1)); String message = SVNReader.getString(items, 1); if (message != null) { setLastError(SVNErrorMessage.create(SVNErrorCode.RA_NOT_AUTHORIZED, message)); } break; } else if (SVNAuthenticator.STEP.equals(status)) { try { byte[] response = authenticator.buildChallengeResponse(SVNReader.getBytes(items, 1)); getConnectionOutputStream().write(response); getConnectionOutputStream().flush(); } catch (IOException e) { SVNErrorManager.error(SVNErrorMessage.create(SVNErrorCode.RA_SVN_IO_ERROR, e.getMessage()), e, SVNLogType.NETWORK); } } } } } else { SVNErrorManager.error(SVNErrorMessage.create(SVNErrorCode.RA_NOT_AUTHORIZED, "Cannot negotiate authentication mechanism"), SVNLogType.NETWORK); } if (failureReason != null) { if (getLastError() != null) { SVNErrorManager.error(getLastError(), SVNLogType.NETWORK); } SVNErrorManager.error(failureReason, SVNLogType.NETWORK); } return auth; } protected SVNErrorMessage readAuthResponse() throws SVNException { List items = getConnection().readTuple("w(?s)", true); if (SVNAuthenticator.SUCCESS.equals(SVNReader.getString(items, 0))) { return null; } else if (SVNAuthenticator.FAILURE.equals(SVNReader.getString(items, 0))) { return SVNErrorMessage.create(SVNErrorCode.RA_NOT_AUTHORIZED, "Authentication error from server: {0}", SVNReader.getString(items, 1)); } return SVNErrorMessage.create(SVNErrorCode.RA_NOT_AUTHORIZED, "Unexpected server response to authentication"); } }