1
2
3
4
5
6
7
8
9
10 package org.eclipse.jgit.internal.transport.sshd;
11
12 import static java.nio.charset.StandardCharsets.UTF_8;
13 import static java.text.MessageFormat.format;
14 import static org.apache.sshd.client.config.hosts.HostPatternsHolder.NON_STANDARD_PORT_PATTERN_ENCLOSURE_END_DELIM;
15 import static org.apache.sshd.client.config.hosts.HostPatternsHolder.NON_STANDARD_PORT_PATTERN_ENCLOSURE_START_DELIM;
16
17 import java.io.BufferedReader;
18 import java.io.IOException;
19 import java.nio.file.Files;
20 import java.nio.file.Path;
21 import java.util.Arrays;
22 import java.util.Collection;
23 import java.util.LinkedList;
24 import java.util.List;
25 import java.util.stream.Collectors;
26
27 import org.apache.sshd.client.config.hosts.HostPatternValue;
28 import org.apache.sshd.client.config.hosts.HostPatternsHolder;
29 import org.apache.sshd.client.config.hosts.KnownHostEntry;
30 import org.apache.sshd.client.config.hosts.KnownHostHashValue;
31 import org.apache.sshd.common.config.keys.AuthorizedKeyEntry;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35
36
37
38
39
40
41
42
43
44
45
46
47 public class KnownHostEntryReader {
48
49 private static final Logger LOG = LoggerFactory
50 .getLogger(KnownHostEntryReader.class);
51
52 private KnownHostEntryReader() {
53
54 }
55
56
57
58
59
60
61
62
63
64
65
66 public static List<KnownHostEntry> readFromFile(Path path)
67 throws IOException {
68 List<KnownHostEntry> result = new LinkedList<>();
69 try (BufferedReader r = Files.newBufferedReader(path, UTF_8)) {
70 r.lines().forEachOrdered(l -> {
71 if (l == null) {
72 return;
73 }
74 String line = clean(l);
75 if (line.isEmpty()) {
76 return;
77 }
78 try {
79 KnownHostEntry entry = parseHostEntry(line);
80 if (entry != null) {
81 result.add(entry);
82 } else {
83 LOG.warn(format(SshdText.get().knownHostsInvalidLine,
84 path, line));
85 }
86 } catch (RuntimeException e) {
87 LOG.warn(format(SshdText.get().knownHostsInvalidLine, path,
88 line), e);
89 }
90 });
91 }
92 return result;
93 }
94
95 private static String clean(String line) {
96 int i = line.indexOf('#');
97 return i < 0 ? line.trim() : line.substring(0, i).trim();
98 }
99
100 private static KnownHostEntry parseHostEntry(String line) {
101 KnownHostEntry entry = new KnownHostEntry();
102 entry.setConfigLine(line);
103 String tmp = line;
104 int i = 0;
105 if (tmp.charAt(0) == KnownHostEntry.MARKER_INDICATOR) {
106
107 i = tmp.indexOf(' ', 1);
108 if (i < 0) {
109 return null;
110 }
111 entry.setMarker(tmp.substring(1, i));
112 tmp = tmp.substring(i + 1).trim();
113 }
114 i = tmp.indexOf(' ');
115 if (i < 0) {
116 return null;
117 }
118
119 if (tmp.charAt(0) == KnownHostHashValue.HASHED_HOST_DELIMITER) {
120
121 KnownHostHashValue hash = KnownHostHashValue
122 .parse(tmp.substring(0, i));
123 if (hash == null) {
124 return null;
125 }
126 entry.setHashedEntry(hash);
127 entry.setPatterns(null);
128 } else {
129 Collection<HostPatternValue> patterns = parsePatterns(
130 tmp.substring(0, i));
131 if (patterns == null || patterns.isEmpty()) {
132 return null;
133 }
134 entry.setHashedEntry(null);
135 entry.setPatterns(patterns);
136 }
137 tmp = tmp.substring(i + 1).trim();
138 AuthorizedKeyEntry key = AuthorizedKeyEntry
139 .parseAuthorizedKeyEntry(tmp);
140 if (key == null) {
141 return null;
142 }
143 entry.setKeyEntry(key);
144 return entry;
145 }
146
147 private static Collection<HostPatternValue> parsePatterns(String text) {
148 if (text.isEmpty()) {
149 return null;
150 }
151 List<String> items = Arrays.stream(text.split(","))
152 .filter(item -> item != null && !item.isEmpty()).map(item -> {
153 if (NON_STANDARD_PORT_PATTERN_ENCLOSURE_START_DELIM == item
154 .charAt(0)) {
155 return item;
156 }
157 int firstColon = item.indexOf(':');
158 if (firstColon < 0) {
159 return item;
160 }
161 int secondColon = item.indexOf(':', firstColon + 1);
162 if (secondColon > 0) {
163
164 return item;
165 }
166
167 return NON_STANDARD_PORT_PATTERN_ENCLOSURE_START_DELIM
168 + item.substring(0, firstColon)
169 + NON_STANDARD_PORT_PATTERN_ENCLOSURE_END_DELIM
170 + item.substring(firstColon);
171 }).collect(Collectors.toList());
172 return items.isEmpty() ? null : HostPatternsHolder.parsePatterns(items);
173 }
174 }