123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- /*
- * Copyright (C) 2018, 2021 Thomas Wolf <thomas.wolf@paranor.ch> and others
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Distribution License v. 1.0 which is available at
- * https://www.eclipse.org/org/documents/edl-v10.php.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
- package org.eclipse.jgit.internal.transport.sshd;
-
- import java.io.IOException;
- import java.security.PublicKey;
- import java.util.HashSet;
- import java.util.LinkedList;
- import java.util.List;
- import java.util.Set;
-
- import org.apache.sshd.client.auth.pubkey.UserAuthPublicKey;
- import org.apache.sshd.client.session.ClientSession;
- import org.apache.sshd.common.NamedFactory;
- import org.apache.sshd.common.RuntimeSshException;
- import org.apache.sshd.common.SshConstants;
- import org.apache.sshd.common.config.keys.KeyUtils;
- import org.apache.sshd.common.signature.Signature;
- import org.apache.sshd.common.signature.SignatureFactoriesHolder;
- import org.apache.sshd.common.util.buffer.Buffer;
-
- /**
- * Custom {@link UserAuthPublicKey} implementation fixing SSHD-1105: if there
- * are several signature algorithms applicable for a public key type, we must
- * try them all, in the correct order.
- *
- * @see <a href="https://issues.apache.org/jira/browse/SSHD-1105">SSHD-1105</a>
- * @see <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=572056">Bug
- * 572056</a>
- */
- public class JGitPublicKeyAuthentication extends UserAuthPublicKey {
-
- private final List<String> algorithms = new LinkedList<>();
-
- JGitPublicKeyAuthentication(List<NamedFactory<Signature>> factories) {
- super(factories);
- }
-
- @Override
- protected boolean sendAuthDataRequest(ClientSession session, String service)
- throws Exception {
- if (current == null) {
- algorithms.clear();
- }
- String currentAlgorithm = null;
- if (current != null && !algorithms.isEmpty()) {
- currentAlgorithm = algorithms.remove(0);
- }
- if (currentAlgorithm == null) {
- try {
- if (keys == null || !keys.hasNext()) {
- if (log.isDebugEnabled()) {
- log.debug(
- "sendAuthDataRequest({})[{}] no more keys to send", //$NON-NLS-1$
- session, service);
- }
- return false;
- }
- current = keys.next();
- algorithms.clear();
- } catch (Error e) { // Copied from superclass
- warn("sendAuthDataRequest({})[{}] failed ({}) to get next key: {}", //$NON-NLS-1$
- session, service, e.getClass().getSimpleName(),
- e.getMessage(), e);
- throw new RuntimeSshException(e);
- }
- }
- PublicKey key;
- try {
- key = current.getPublicKey();
- } catch (Error e) { // Copied from superclass
- warn("sendAuthDataRequest({})[{}] failed ({}) to retrieve public key: {}", //$NON-NLS-1$
- session, service, e.getClass().getSimpleName(),
- e.getMessage(), e);
- throw new RuntimeSshException(e);
- }
- if (currentAlgorithm == null) {
- String keyType = KeyUtils.getKeyType(key);
- Set<String> aliases = new HashSet<>(
- KeyUtils.getAllEquivalentKeyTypes(keyType));
- aliases.add(keyType);
- List<NamedFactory<Signature>> existingFactories;
- if (current instanceof SignatureFactoriesHolder) {
- existingFactories = ((SignatureFactoriesHolder) current)
- .getSignatureFactories();
- } else {
- existingFactories = getSignatureFactories();
- }
- if (existingFactories != null) {
- // Select the factories by name and in order
- existingFactories.forEach(f -> {
- if (aliases.contains(f.getName())) {
- algorithms.add(f.getName());
- }
- });
- }
- currentAlgorithm = algorithms.isEmpty() ? keyType
- : algorithms.remove(0);
- }
- String name = getName();
- if (log.isDebugEnabled()) {
- log.debug(
- "sendAuthDataRequest({})[{}] send SSH_MSG_USERAUTH_REQUEST request {} type={} - fingerprint={}", //$NON-NLS-1$
- session, service, name, currentAlgorithm,
- KeyUtils.getFingerPrint(key));
- }
-
- Buffer buffer = session
- .createBuffer(SshConstants.SSH_MSG_USERAUTH_REQUEST);
- buffer.putString(session.getUsername());
- buffer.putString(service);
- buffer.putString(name);
- buffer.putBoolean(false);
- buffer.putString(currentAlgorithm);
- buffer.putPublicKey(key);
- session.writePacket(buffer);
- return true;
- }
-
- @Override
- protected void releaseKeys() throws IOException {
- algorithms.clear();
- current = null;
- super.releaseKeys();
- }
- }
|