summaryrefslogtreecommitdiffstats
path: root/java/com/google/gerrit/sshd/SshUtil.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/com/google/gerrit/sshd/SshUtil.java')
-rw-r--r--java/com/google/gerrit/sshd/SshUtil.java162
1 files changed, 162 insertions, 0 deletions
diff --git a/java/com/google/gerrit/sshd/SshUtil.java b/java/com/google/gerrit/sshd/SshUtil.java
new file mode 100644
index 0000000000..ce354224b5
--- /dev/null
+++ b/java/com/google/gerrit/sshd/SshUtil.java
@@ -0,0 +1,162 @@
+// Copyright (C) 2008 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.sshd;
+
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.server.CurrentUser;
+import com.google.gerrit.server.IdentifiedUser;
+import com.google.gerrit.server.account.AccountSshKey;
+import com.google.gerrit.sshd.SshScope.Context;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.StringReader;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.PublicKey;
+import java.security.interfaces.DSAPublicKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.InvalidKeySpecException;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.sshd.common.SshException;
+import org.apache.sshd.common.future.CloseFuture;
+import org.apache.sshd.common.future.SshFutureListener;
+import org.apache.sshd.common.keyprovider.KeyPairProvider;
+import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
+import org.apache.sshd.server.session.ServerSession;
+import org.eclipse.jgit.lib.Constants;
+
+/** Utilities to support SSH operations. */
+public class SshUtil {
+ /**
+ * Parse a public key into its Java type.
+ *
+ * @param key the account key to parse.
+ * @return the valid public key object.
+ * @throws InvalidKeySpecException the key supplied is not a valid SSH key.
+ * @throws NoSuchAlgorithmException the JVM is missing the key algorithm.
+ * @throws NoSuchProviderException the JVM is missing the provider.
+ */
+ public static PublicKey parse(AccountSshKey key)
+ throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchProviderException {
+ try {
+ final String s = key.encodedKey();
+ if (s == null) {
+ throw new InvalidKeySpecException("No key string");
+ }
+ final byte[] bin = Base64.decodeBase64(Constants.encodeASCII(s));
+ return new ByteArrayBuffer(bin).getRawPublicKey();
+ } catch (RuntimeException | SshException e) {
+ throw new InvalidKeySpecException("Cannot parse key", e);
+ }
+ }
+
+ /**
+ * Convert an RFC 4716 style key to an OpenSSH style key.
+ *
+ * @param keyStr the key string to convert.
+ * @return {@code keyStr} if conversion failed; otherwise the converted key, in OpenSSH key
+ * format.
+ */
+ public static String toOpenSshPublicKey(String keyStr) {
+ try {
+ final StringBuilder strBuf = new StringBuilder();
+ final BufferedReader br = new BufferedReader(new StringReader(keyStr));
+ String line = br.readLine(); // BEGIN SSH2 line...
+ if (line == null || !line.equals("---- BEGIN SSH2 PUBLIC KEY ----")) {
+ return keyStr;
+ }
+
+ while ((line = br.readLine()) != null) {
+ if (line.indexOf(':') == -1) {
+ strBuf.append(line);
+ break;
+ }
+ }
+
+ while ((line = br.readLine()) != null) {
+ if (line.startsWith("---- ")) {
+ break;
+ }
+ strBuf.append(line);
+ }
+
+ final PublicKey key =
+ new ByteArrayBuffer(Base64.decodeBase64(Constants.encodeASCII(strBuf.toString())))
+ .getRawPublicKey();
+ if (key instanceof RSAPublicKey) {
+ strBuf.insert(0, KeyPairProvider.SSH_RSA + " ");
+
+ } else if (key instanceof DSAPublicKey) {
+ strBuf.insert(0, KeyPairProvider.SSH_DSS + " ");
+
+ } else {
+ return keyStr;
+ }
+
+ strBuf.append(' ');
+ strBuf.append("converted-key");
+ return strBuf.toString();
+ } catch (IOException | RuntimeException e) {
+ return keyStr;
+ }
+ }
+
+ public static boolean success(
+ final String username,
+ final ServerSession session,
+ final SshScope sshScope,
+ final SshLog sshLog,
+ final SshSession sd,
+ final CurrentUser user) {
+ if (sd.getUser() == null) {
+ sd.authenticationSuccess(username, user);
+
+ // If this is the first time we've authenticated this
+ // session, record a login event in the log and add
+ // a close listener to record a logout event.
+ //
+ Context ctx = sshScope.newContext(null, sd, null);
+ Context old = sshScope.set(ctx);
+ try {
+ sshLog.onLogin();
+ } finally {
+ sshScope.set(old);
+ }
+
+ session.addCloseFutureListener(
+ new SshFutureListener<CloseFuture>() {
+ @Override
+ public void operationComplete(CloseFuture future) {
+ final Context ctx = sshScope.newContext(null, sd, null);
+ final Context old = sshScope.set(ctx);
+ try {
+ sshLog.onLogout();
+ } finally {
+ sshScope.set(old);
+ }
+ }
+ });
+ }
+
+ return true;
+ }
+
+ public static IdentifiedUser createUser(
+ final SshSession sd,
+ final IdentifiedUser.GenericFactory userFactory,
+ final Account.Id account) {
+ return userFactory.create(sd.getRemoteAddress(), account);
+ }
+}