1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 package org.eclipse.jgit.internal.transport.sshd;
44
45 import java.io.IOException;
46 import java.net.URISyntaxException;
47 import java.security.GeneralSecurityException;
48 import java.util.Arrays;
49 import java.util.Map;
50 import java.util.concurrent.ConcurrentHashMap;
51 import java.util.concurrent.atomic.AtomicInteger;
52
53 import org.apache.sshd.common.NamedResource;
54 import org.apache.sshd.common.session.SessionContext;
55 import org.eclipse.jgit.annotations.NonNull;
56 import org.eclipse.jgit.transport.CredentialsProvider;
57 import org.eclipse.jgit.transport.URIish;
58 import org.eclipse.jgit.transport.sshd.KeyPasswordProvider;
59
60
61
62
63
64 public class PasswordProviderWrapper implements RepeatingFilePasswordProvider {
65
66 private final KeyPasswordProvider delegate;
67
68 private Map<String, AtomicInteger> counts = new ConcurrentHashMap<>();
69
70
71
72
73 public PasswordProviderWrapper(@NonNull KeyPasswordProvider delegate) {
74 this.delegate = delegate;
75 }
76
77 @Override
78 public void setAttempts(int numberOfPasswordPrompts) {
79 delegate.setAttempts(numberOfPasswordPrompts);
80 }
81
82 @Override
83 public int getAttempts() {
84 return delegate.getAttempts();
85 }
86
87 @Override
88 public String getPassword(SessionContext session, NamedResource resource,
89 int attemptIndex) throws IOException {
90 String key = resource.getName();
91 int attempt = counts
92 .computeIfAbsent(key, k -> new AtomicInteger()).get();
93 char[] passphrase = delegate.getPassphrase(toUri(key), attempt);
94 if (passphrase == null) {
95 return null;
96 }
97 try {
98 return new String(passphrase);
99 } finally {
100 Arrays.fill(passphrase, '\000');
101 }
102 }
103
104 @Override
105 public ResourceDecodeResult handleDecodeAttemptResult(
106 SessionContext session, NamedResource resource, int retryIndex,
107 String password, Exception err)
108 throws IOException, GeneralSecurityException {
109 String key = resource.getName();
110 AtomicInteger count = counts.get(key);
111 int numberOfAttempts = count == null ? 0 : count.incrementAndGet();
112 ResourceDecodeResult result = null;
113 try {
114 if (delegate.keyLoaded(toUri(key), numberOfAttempts, err)) {
115 result = ResourceDecodeResult.RETRY;
116 } else {
117 result = ResourceDecodeResult.TERMINATE;
118 }
119 } finally {
120 if (result != ResourceDecodeResult.RETRY) {
121 counts.remove(key);
122 }
123 }
124 return result;
125 }
126
127
128
129
130
131
132
133
134
135 private URIish toUri(String resourceKey) {
136 try {
137 return new URIish(resourceKey);
138 } catch (URISyntaxException e) {
139 return new URIish().setPath(resourceKey);
140 }
141 }
142
143 }