1 package org.bouncycastle.jsse.provider;
2 
3 import java.security.cert.CertPathBuilder;
4 import java.security.cert.PKIXBuilderParameters;
5 import java.security.cert.PKIXCertPathChecker;
6 import java.security.cert.PKIXRevocationChecker;
7 import java.security.cert.X509Certificate;
8 import java.util.ArrayList;
9 import java.util.Collection;
10 import java.util.Collections;
11 import java.util.List;
12 import java.util.Map;
13 import java.util.function.BiFunction;
14 
15 import javax.net.ssl.SNIHostName;
16 import javax.net.ssl.SNIMatcher;
17 import javax.net.ssl.SNIServerName;
18 import javax.net.ssl.StandardConstants;
19 
20 import org.bouncycastle.jsse.BCApplicationProtocolSelector;
21 import org.bouncycastle.jsse.BCSNIHostName;
22 import org.bouncycastle.jsse.BCSNIMatcher;
23 import org.bouncycastle.jsse.BCSNIServerName;
24 import org.bouncycastle.jsse.BCStandardConstants;
25 
26 abstract class JsseUtils_8
27     extends JsseUtils_7
28 {
29     static class ExportAPSelector<T> implements BiFunction<T, List<String>, String>
30     {
31         private final BCApplicationProtocolSelector<T> selector;
32 
ExportAPSelector(BCApplicationProtocolSelector<T> selector)33         ExportAPSelector(BCApplicationProtocolSelector<T> selector)
34         {
35             this.selector = selector;
36         }
37 
38         @Override
apply(T t, List<String> u)39         public String apply(T t, List<String> u)
40         {
41             return selector.select(t, u);
42         }
43 
unwrap()44         BCApplicationProtocolSelector<T> unwrap()
45         {
46             return selector;
47         }
48     }
49 
50     static class ExportSNIMatcher extends SNIMatcher
51     {
52         private final BCSNIMatcher matcher;
53 
ExportSNIMatcher(BCSNIMatcher matcher)54         ExportSNIMatcher(BCSNIMatcher matcher)
55         {
56             super(matcher.getType());
57 
58             this.matcher = matcher;
59         }
60 
61         @Override
matches(SNIServerName serverName)62         public boolean matches(SNIServerName serverName)
63         {
64             return matcher.matches(importSNIServerName(serverName));
65         }
66 
unwrap()67         BCSNIMatcher unwrap()
68         {
69             return matcher;
70         }
71     }
72 
73     static class ImportAPSelector<T> implements BCApplicationProtocolSelector<T>
74     {
75         private final BiFunction<T, List<String>, String> selector;
76 
ImportAPSelector(BiFunction<T, List<String>, String> selector)77         ImportAPSelector(BiFunction<T, List<String>, String> selector)
78         {
79             this.selector = selector;
80         }
81 
82         @Override
select(T transport, List<String> protocols)83         public String select(T transport, List<String> protocols)
84         {
85             return selector.apply(transport, protocols);
86         }
87 
unwrap()88         BiFunction<T, List<String>, String> unwrap()
89         {
90             return selector;
91         }
92     }
93 
94     static class ImportSNIMatcher extends BCSNIMatcher
95     {
96         private final SNIMatcher matcher;
97 
ImportSNIMatcher(SNIMatcher matcher)98         ImportSNIMatcher(SNIMatcher matcher)
99         {
100             super(matcher.getType());
101 
102             this.matcher = matcher;
103         }
104 
105         @Override
matches(BCSNIServerName serverName)106         public boolean matches(BCSNIServerName serverName)
107         {
108             return matcher.matches(exportSNIServerName(serverName));
109         }
110 
unwrap()111         SNIMatcher unwrap()
112         {
113             return matcher;
114         }
115     }
116 
117     static class UnknownServerName extends SNIServerName
118     {
UnknownServerName(int type, byte[] encoded)119         UnknownServerName(int type, byte[] encoded)
120         {
121             super(type, encoded);
122         }
123     }
124 
addStatusResponses(CertPathBuilder pkixBuilder, PKIXBuilderParameters pkixParameters, Map<X509Certificate, byte[]> statusResponseMap)125     static void addStatusResponses(CertPathBuilder pkixBuilder, PKIXBuilderParameters pkixParameters,
126         Map<X509Certificate, byte[]> statusResponseMap)
127     {
128         if (statusResponseMap.isEmpty())
129         {
130             return;
131         }
132 
133         List<PKIXCertPathChecker> certPathCheckers = pkixParameters.getCertPathCheckers();
134         PKIXRevocationChecker existingChecker = getFirstRevocationChecker(certPathCheckers);
135 
136         if (null != existingChecker)
137         {
138             // NOTE: Existing checker will be used irrespective of pkixParameters.isRevocationEnabled
139             Map<X509Certificate, byte[]> ocspResponses = existingChecker.getOcspResponses();
140             if (putAnyAbsent(ocspResponses, statusResponseMap) > 0)
141             {
142                 existingChecker.setOcspResponses(ocspResponses);
143                 pkixParameters.setCertPathCheckers(certPathCheckers);
144             }
145         }
146         else
147         {
148             if (pkixParameters.isRevocationEnabled())
149             {
150                 PKIXRevocationChecker checker = (PKIXRevocationChecker)pkixBuilder.getRevocationChecker();
151                 checker.setOcspResponses(statusResponseMap);
152                 pkixParameters.addCertPathChecker(checker);
153             }
154         }
155     }
156 
exportAPSelector(BCApplicationProtocolSelector<T> selector)157     static <T> BiFunction<T, List<String>, String> exportAPSelector(BCApplicationProtocolSelector<T> selector)
158     {
159         if (null == selector)
160         {
161             return null;
162         }
163 
164         if (selector instanceof ImportAPSelector)
165         {
166             return ((ImportAPSelector<T>)selector).unwrap();
167         }
168 
169         return new ExportAPSelector<T>(selector);
170     }
171 
exportSNIMatcher(BCSNIMatcher matcher)172     static SNIMatcher exportSNIMatcher(BCSNIMatcher matcher)
173     {
174         if (null == matcher)
175         {
176             return null;
177         }
178 
179         if (matcher instanceof ImportSNIMatcher)
180         {
181             return ((ImportSNIMatcher)matcher).unwrap();
182         }
183 
184         return new ExportSNIMatcher(matcher);
185     }
186 
exportSNIMatchers(Collection<BCSNIMatcher> matchers)187     static List<SNIMatcher> exportSNIMatchers(Collection<BCSNIMatcher> matchers)
188     {
189         if (null == matchers || matchers.isEmpty())
190         {
191             return Collections.<SNIMatcher>emptyList();
192         }
193 
194         ArrayList<SNIMatcher> result = new ArrayList<SNIMatcher>(matchers.size());
195         for (BCSNIMatcher matcher : matchers)
196         {
197             result.add(exportSNIMatcher(matcher));
198         }
199         return Collections.unmodifiableList(result);
200     }
201 
202     /*
203      * NOTE: Return type is Object to isolate callers from JDK 8 type
204      */
exportSNIMatchersDynamic(Collection<BCSNIMatcher> matchers)205     static Object exportSNIMatchersDynamic(Collection<BCSNIMatcher> matchers)
206     {
207         return exportSNIMatchers(matchers);
208     }
209 
exportSNIServerName(BCSNIServerName serverName)210     static SNIServerName exportSNIServerName(BCSNIServerName serverName)
211     {
212         if (null == serverName)
213         {
214             return null;
215         }
216 
217         int type = serverName.getType();
218         byte[] encoded = serverName.getEncoded();
219 
220         switch (type)
221         {
222         case BCStandardConstants.SNI_HOST_NAME:
223             return new SNIHostName(encoded);
224         default:
225             return new UnknownServerName(type, encoded);
226         }
227     }
228 
exportSNIServerNames(Collection<BCSNIServerName> serverNames)229     static List<SNIServerName> exportSNIServerNames(Collection<BCSNIServerName> serverNames)
230     {
231         if (null == serverNames || serverNames.isEmpty())
232         {
233             return Collections.<SNIServerName>emptyList();
234         }
235 
236         ArrayList<SNIServerName> result = new ArrayList<SNIServerName>(serverNames.size());
237         for (BCSNIServerName serverName : serverNames)
238         {
239             result.add(exportSNIServerName(serverName));
240         }
241         return Collections.unmodifiableList(result);
242     }
243 
244     /*
245      * NOTE: Return type is Object to isolate callers from JDK 8 type
246      */
exportSNIServerNamesDynamic(Collection<BCSNIServerName> serverNames)247     static Object exportSNIServerNamesDynamic(Collection<BCSNIServerName> serverNames)
248     {
249         return exportSNIServerNames(serverNames);
250     }
251 
getFirstRevocationChecker(List<PKIXCertPathChecker> certPathCheckers)252     static PKIXRevocationChecker getFirstRevocationChecker(List<PKIXCertPathChecker> certPathCheckers)
253     {
254         for (PKIXCertPathChecker certPathChecker : certPathCheckers)
255         {
256             if (certPathChecker instanceof PKIXRevocationChecker)
257             {
258                 return (PKIXRevocationChecker)certPathChecker;
259             }
260         }
261         return null;
262     }
263 
importAPSelector(BiFunction<T, List<String>, String> selector)264     static <T> BCApplicationProtocolSelector<T> importAPSelector(BiFunction<T, List<String>, String> selector)
265     {
266         if (null == selector)
267         {
268             return null;
269         }
270 
271         if (selector instanceof ExportAPSelector)
272         {
273             return ((ExportAPSelector<T>)selector).unwrap();
274         }
275 
276         return new ImportAPSelector<T>(selector);
277     }
278 
importSNIMatcher(SNIMatcher matcher)279     static BCSNIMatcher importSNIMatcher(SNIMatcher matcher)
280     {
281         if (null == matcher)
282         {
283             return null;
284         }
285 
286         if (matcher instanceof ExportSNIMatcher)
287         {
288             return ((ExportSNIMatcher)matcher).unwrap();
289         }
290 
291         return new ImportSNIMatcher(matcher);
292     }
293 
importSNIMatchers(Collection<SNIMatcher> matchers)294     static List<BCSNIMatcher> importSNIMatchers(Collection<SNIMatcher> matchers)
295     {
296         if (null == matchers || matchers.isEmpty())
297         {
298             return Collections.emptyList();
299         }
300 
301         ArrayList<BCSNIMatcher> result = new ArrayList<BCSNIMatcher>(matchers.size());
302         for (SNIMatcher matcher : matchers)
303         {
304             result.add(importSNIMatcher(matcher));
305         }
306         return Collections.unmodifiableList(result);
307     }
308 
309     /*
310      * NOTE: Argument type is Object to isolate callers from JDK 8 type
311      */
312     @SuppressWarnings("unchecked")
importSNIMatchersDynamic(Object matchers)313     static List<BCSNIMatcher> importSNIMatchersDynamic(Object matchers)
314     {
315         return importSNIMatchers((Collection<SNIMatcher>)matchers);
316     }
317 
importSNIServerName(SNIServerName serverName)318     static BCSNIServerName importSNIServerName(SNIServerName serverName)
319     {
320         if (null == serverName)
321         {
322             return null;
323         }
324 
325         int type = serverName.getType();
326         byte[] encoded = serverName.getEncoded();
327 
328         switch (type)
329         {
330         case StandardConstants.SNI_HOST_NAME:
331             return new BCSNIHostName(encoded);
332         default:
333             return new BCUnknownServerName(type, encoded);
334         }
335     }
336 
importSNIServerNames(Collection<SNIServerName> serverNames)337     static List<BCSNIServerName> importSNIServerNames(Collection<SNIServerName> serverNames)
338     {
339         if (null == serverNames || serverNames.isEmpty())
340         {
341             return Collections.emptyList();
342         }
343 
344         ArrayList<BCSNIServerName> result = new ArrayList<BCSNIServerName>(serverNames.size());
345         for (SNIServerName serverName : serverNames)
346         {
347             result.add(importSNIServerName(serverName));
348         }
349         return Collections.unmodifiableList(result);
350     }
351 
352     /*
353      * NOTE: Argument type is Object to isolate callers from JDK 8 type
354      */
355     @SuppressWarnings("unchecked")
importSNIServerNamesDynamic(Object serverNames)356     static List<BCSNIServerName> importSNIServerNamesDynamic(Object serverNames)
357     {
358         return importSNIServerNames((Collection<SNIServerName>)serverNames);
359     }
360 
putAnyAbsent(Map<K, V> to, Map<K, V> from)361     static <K, V> int putAnyAbsent(Map<K, V> to, Map<K, V> from)
362     {
363         int count = 0;
364         for (Map.Entry<K, V> entry : from.entrySet())
365         {
366             if (null == to.putIfAbsent(entry.getKey(), entry.getValue()))
367             {
368                 ++count;
369             }
370         }
371         return count;
372     }
373 }
374