]> source.dussan.org Git - jgit.git/blob
2996a221cea7c6b47e78f70e5818b714f4224a55
[jgit.git] /
1 /*
2  * Copyright (C) 2018, 2021 Thomas Wolf <thomas.wolf@paranor.ch> and others
3  *
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.
7  *
8  * SPDX-License-Identifier: BSD-3-Clause
9  */
10 package org.eclipse.jgit.internal.transport.sshd;
11
12 import static java.text.MessageFormat.format;
13 import static org.eclipse.jgit.transport.SshConstants.PUBKEY_ACCEPTED_ALGORITHMS;
14
15 import java.util.Iterator;
16 import java.util.List;
17 import java.util.NoSuchElementException;
18
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;
27
28 /**
29  * Custom {@link UserAuthPublicKey} implementation for handling SSH config
30  * PubkeyAcceptedAlgorithms.
31  */
32 public class JGitPublicKeyAuthentication extends UserAuthPublicKey {
33
34         JGitPublicKeyAuthentication(List<NamedFactory<Signature>> factories) {
35                 super(factories);
36         }
37
38         @Override
39         public void init(ClientSession rawSession, String service)
40                         throws Exception {
41                 if (!(rawSession instanceof JGitClientSession)) {
42                         throw new IllegalStateException("Wrong session type: " //$NON-NLS-1$
43                                         + rawSession.getClass().getCanonicalName());
44                 }
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);
57                                 }
58                                 setSignatureFactoriesNames(signatures);
59                         } else {
60                                 log.warn(format(SshdText.get().configNoKnownAlgorithms,
61                                                 PUBKEY_ACCEPTED_ALGORITHMS, pubkeyAlgos));
62                         }
63                 }
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.
77                         //
78                         // See https://issues.apache.org/jira/browse/SSHD-1218
79                         keys = new Iterator<>() {
80
81                                 private PublicKeyIdentity value;
82
83                                 @Override
84                                 public boolean hasNext() {
85                                         if (value != null) {
86                                                 return true;
87                                         }
88                                         PublicKeyIdentity next = null;
89                                         while (original.hasNext()) {
90                                                 next = original.next();
91                                                 if (!(next instanceof KeyAgentIdentity)) {
92                                                         value = next;
93                                                         return true;
94                                                 }
95                                         }
96                                         return false;
97                                 }
98
99                                 @Override
100                                 public PublicKeyIdentity next() {
101                                         if (hasNext()) {
102                                                 PublicKeyIdentity result = value;
103                                                 value = null;
104                                                 return result;
105                                         }
106                                         throw new NoSuchElementException();
107                                 }
108                         };
109                 }
110         }
111
112         @Override
113         protected PublicKeyIdentity resolveAttemptedPublicKeyIdentity(
114                         ClientSession session, String service) throws Exception {
115                 PublicKeyIdentity result = super.resolveAttemptedPublicKeyIdentity(
116                                 session, service);
117                 // This fixes SSHD-1231. Can be removed once we're using Apache MINA
118                 // sshd > 2.8.0.
119                 //
120                 // See https://issues.apache.org/jira/browse/SSHD-1231
121                 currentAlgorithms.clear();
122                 return result;
123         }
124
125 }