2 * Copyright (C) 2018, 2021 Thomas Wolf <thomas.wolf@paranor.ch> and others
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Distribution License v. 1.0 which is available at
6 * https://www.eclipse.org/org/documents/edl-v10.php.
8 * SPDX-License-Identifier: BSD-3-Clause
10 package org.eclipse.jgit.internal.transport.sshd;
12 import static java.text.MessageFormat.format;
13 import static org.eclipse.jgit.transport.SshConstants.PUBKEY_ACCEPTED_ALGORITHMS;
15 import java.util.Iterator;
16 import java.util.List;
17 import java.util.NoSuchElementException;
19 import org.apache.sshd.client.auth.pubkey.KeyAgentIdentity;
20 import org.apache.sshd.client.auth.pubkey.PublicKeyIdentity;
21 import org.apache.sshd.client.auth.pubkey.UserAuthPublicKey;
22 import org.apache.sshd.client.config.hosts.HostConfigEntry;
23 import org.apache.sshd.client.session.ClientSession;
24 import org.apache.sshd.common.NamedFactory;
25 import org.apache.sshd.common.signature.Signature;
26 import org.eclipse.jgit.util.StringUtils;
29 * Custom {@link UserAuthPublicKey} implementation for handling SSH config
30 * PubkeyAcceptedAlgorithms.
32 public class JGitPublicKeyAuthentication extends UserAuthPublicKey {
34 JGitPublicKeyAuthentication(List<NamedFactory<Signature>> factories) {
39 public void init(ClientSession rawSession, String service)
41 if (!(rawSession instanceof JGitClientSession)) {
42 throw new IllegalStateException("Wrong session type: " //$NON-NLS-1$
43 + rawSession.getClass().getCanonicalName());
45 JGitClientSession session = (JGitClientSession) rawSession;
46 HostConfigEntry hostConfig = session.getHostConfigEntry();
47 // Set signature algorithms for public key authentication
48 String pubkeyAlgos = hostConfig.getProperty(PUBKEY_ACCEPTED_ALGORITHMS);
49 if (!StringUtils.isEmptyOrNull(pubkeyAlgos)) {
50 List<String> signatures = session.getSignatureFactoriesNames();
51 signatures = session.modifyAlgorithmList(signatures,
52 session.getAllAvailableSignatureAlgorithms(), pubkeyAlgos,
53 PUBKEY_ACCEPTED_ALGORITHMS);
54 if (!signatures.isEmpty()) {
55 if (log.isDebugEnabled()) {
56 log.debug(PUBKEY_ACCEPTED_ALGORITHMS + ' ' + signatures);
58 setSignatureFactoriesNames(signatures);
60 log.warn(format(SshdText.get().configNoKnownAlgorithms,
61 PUBKEY_ACCEPTED_ALGORITHMS, pubkeyAlgos));
64 // If we don't set signature factories here, the default ones from the
65 // session will be used.
66 super.init(session, service);
67 // In sshd 2.7.0, we end up now with a key iterator that uses keys
68 // provided by an ssh-agent even if IdentitiesOnly is true. So if
69 // needed, filter out any KeyAgentIdentity.
70 if (hostConfig.isIdentitiesOnly()) {
71 Iterator<PublicKeyIdentity> original = keys;
72 // The original iterator will already have gotten the identities
73 // from the agent. Unfortunately there's nothing we can do about
74 // that; it'll have to be fixed upstream. (As will, ultimately,
75 // respecting isIdentitiesOnly().) At least we can simply not
76 // use the keys the agent provided.
78 // See https://issues.apache.org/jira/browse/SSHD-1218
79 keys = new Iterator<>() {
81 private PublicKeyIdentity value;
84 public boolean hasNext() {
88 PublicKeyIdentity next = null;
89 while (original.hasNext()) {
90 next = original.next();
91 if (!(next instanceof KeyAgentIdentity)) {
100 public PublicKeyIdentity next() {
102 PublicKeyIdentity result = value;
106 throw new NoSuchElementException();
113 protected PublicKeyIdentity resolveAttemptedPublicKeyIdentity(
114 ClientSession session, String service) throws Exception {
115 PublicKeyIdentity result = super.resolveAttemptedPublicKeyIdentity(
117 // This fixes SSHD-1231. Can be removed once we're using Apache MINA
120 // See https://issues.apache.org/jira/browse/SSHD-1231
121 currentAlgorithms.clear();