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