Mercurial > jhg
diff src/org/tmatesoft/hg/internal/remote/SshAuthMethod.java @ 699:a483b2b68a2e
Provisional APIs and respective implementation for http, https and ssh remote repositories
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Thu, 08 Aug 2013 19:18:50 +0200 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/tmatesoft/hg/internal/remote/SshAuthMethod.java Thu Aug 08 19:18:50 2013 +0200 @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2013 TMate Software Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * For information on how to redistribute this software under + * the terms of a license other than GNU General Public License + * contact TMate Software at support@hg4j.com + */ +package org.tmatesoft.hg.internal.remote; + +import java.io.CharArrayWriter; +import java.io.IOException; +import java.io.InputStream; +import java.security.cert.X509Certificate; +import java.util.Arrays; + +import org.tmatesoft.hg.auth.HgAuthFailedException; +import org.tmatesoft.hg.auth.HgAuthMethod; + +import com.trilead.ssh2.Connection; + +/** + * + * @author Artem Tikhomirov + * @author TMate Software Ltd. + */ +public final class SshAuthMethod implements HgAuthMethod { + + private final Connection conn; + + public SshAuthMethod(Connection connection) { + conn = connection; + } + + public void tryWithUserInfo(String uriUserInfo) throws HgAuthFailedException { + assert uriUserInfo != null && uriUserInfo.trim().length() > 0; + int colon = uriUserInfo.indexOf(':'); + if (colon == -1) { + String username = uriUserInfo; + withPassword(username, null); + } else { + String username = uriUserInfo.substring(0, colon); + String password = uriUserInfo.substring(colon+1); + withPassword(username, password); + } + return; + } + + public void noCredentials() throws HgAuthFailedException { + try { + String username = System.getProperty("user.name"); + if (!conn.authenticateWithNone(username)) { + throw authFailed(username); + } + } catch (IOException ex) { + throw commFailed(ex); + } + } + + public void withPublicKey(String username, InputStream privateKey, String passphrase) throws HgAuthFailedException { + if (username == null) { + // FIXME AuthFailure and AuthFailed or similar distinct exceptions to tell true authentication issues from + // failures around it. + throw new HgAuthFailedException("Need username", null); + } + if (privateKey == null) { + throw new HgAuthFailedException("Need private key", null); + } + CharArrayWriter a = new CharArrayWriter(2048); + int r; + try { + while((r = privateKey.read()) != -1) { + a.append((char) r); + } + } catch (IOException ex) { + throw new HgAuthFailedException("Failed to read private key", ex); + } + try { + boolean success = conn.authenticateWithPublicKey(username, a.toCharArray(), passphrase); + if (!success) { + throw authFailed(username); + } + } catch (IOException ex) { + throw commFailed(ex); + } + } + + public void withPassword(String username, String password) throws HgAuthFailedException { + if (username == null) { + throw new HgAuthFailedException("Need username", null); + } + try { + boolean success; + if (password == null) { + success = conn.authenticateWithNone(username); + } else { + success = conn.authenticateWithPassword(username, password); + } + if (!success) { + throw authFailed(username); + } + } catch (IOException ex) { + throw commFailed(ex); + } + } + + public void withCertificate(X509Certificate[] clientCert) throws HgAuthFailedException { + } + + public boolean supportsPublicKey() { + return true; + } + + public boolean supportsPassword() { + return true; + } + + public boolean supportsCertificate() { + return true; + } + + private HgAuthFailedException commFailed(IOException ex) { + return new HgAuthFailedException("Communication failure while authenticating", ex); + } + + private HgAuthFailedException authFailed(String username) throws IOException { + final String[] authMethodsLeft = conn.getRemainingAuthMethods(username); + return new HgAuthFailedException(String.format("Failed to authenticate, other methods to try: %s", Arrays.toString(authMethodsLeft)), null); + } +} \ No newline at end of file