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