001/* 002 * Copyright 2008-2019 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2008-2019 Ping Identity Corporation 007 * 008 * This program is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU General Public License (GPLv2 only) 010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 011 * as published by the Free Software Foundation. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Public License for more details. 017 * 018 * You should have received a copy of the GNU General Public License 019 * along with this program; if not, see <http://www.gnu.org/licenses>. 020 */ 021package com.unboundid.util.ssl; 022 023 024 025import java.net.Socket; 026import java.security.Principal; 027import java.security.PrivateKey; 028import java.security.cert.X509Certificate; 029import java.util.Arrays; 030import java.util.LinkedHashSet; 031import javax.net.ssl.KeyManager; 032import javax.net.ssl.SSLEngine; 033import javax.net.ssl.X509ExtendedKeyManager; 034import javax.net.ssl.X509KeyManager; 035 036import com.unboundid.util.NotExtensible; 037import com.unboundid.util.StaticUtils; 038import com.unboundid.util.ThreadSafety; 039import com.unboundid.util.ThreadSafetyLevel; 040 041 042 043/** 044 * This class provides an SSL key manager that may be used to wrap a provided 045 * set of key managers. It provides the ability to select the desired 046 * certificate based on a given nickname. 047 */ 048@NotExtensible() 049@ThreadSafety(level=ThreadSafetyLevel.INTERFACE_THREADSAFE) 050public abstract class WrapperKeyManager 051 extends X509ExtendedKeyManager 052{ 053 // The nickname of the certificate that should be selected. 054 private final String certificateAlias; 055 056 // The set of key managers that will be used to perform the processing. 057 private final X509KeyManager[] keyManagers; 058 059 060 061 /** 062 * Creates a new instance of this wrapper key manager with the provided 063 * information. 064 * 065 * @param keyManagers The set of key managers to be wrapped. It must 066 * not be {@code null} or empty, and it must contain 067 * only X509KeyManager instances. 068 * @param certificateAlias The nickname of the certificate that should be 069 * selected. It may be {@code null} if any 070 * acceptable certificate found may be used. 071 */ 072 protected WrapperKeyManager(final KeyManager[] keyManagers, 073 final String certificateAlias) 074 { 075 this.certificateAlias = certificateAlias; 076 077 this.keyManagers = new X509KeyManager[keyManagers.length]; 078 for (int i=0; i < keyManagers.length; i++) 079 { 080 this.keyManagers[i] = (X509KeyManager) keyManagers[i]; 081 } 082 } 083 084 085 086 /** 087 * Creates a new instance of this wrapper key manager with the provided 088 * information. 089 * 090 * @param keyManagers The set of key managers to be wrapped. It must 091 * not be {@code null} or empty. 092 * @param certificateAlias The nickname of the certificate that should be 093 * selected. It may be {@code null} if any 094 * acceptable certificate found may be used. 095 */ 096 protected WrapperKeyManager(final X509KeyManager[] keyManagers, 097 final String certificateAlias) 098 { 099 this.keyManagers = keyManagers; 100 this.certificateAlias = certificateAlias; 101 } 102 103 104 105 /** 106 * Retrieves the nickname of the certificate that should be selected. 107 * 108 * @return The nickname of the certificate that should be selected, or 109 * {@code null} if any acceptable certificate found in the key store 110 * may be used. 111 */ 112 public String getCertificateAlias() 113 { 114 return certificateAlias; 115 } 116 117 118 119 /** 120 * Retrieves the nicknames of the client certificates of the specified type 121 * contained in the key store. 122 * 123 * @param keyType The key algorithm name for which to retrieve the available 124 * certificate nicknames. 125 * @param issuers The list of acceptable issuer certificate subjects. It 126 * may be {@code null} if any issuer may be used. 127 * 128 * @return The nicknames of the client certificates, or {@code null} if none 129 * were found in the key store. 130 */ 131 @Override() 132 public final synchronized String[] getClientAliases(final String keyType, 133 final Principal[] issuers) 134 { 135 final LinkedHashSet<String> clientAliases = 136 new LinkedHashSet<>(StaticUtils.computeMapCapacity(10)); 137 138 for (final X509KeyManager m : keyManagers) 139 { 140 final String[] aliases = m.getClientAliases(keyType, issuers); 141 if (aliases != null) 142 { 143 clientAliases.addAll(Arrays.asList(aliases)); 144 } 145 } 146 147 if (clientAliases.isEmpty()) 148 { 149 return null; 150 } 151 else 152 { 153 final String[] aliases = new String[clientAliases.size()]; 154 return clientAliases.toArray(aliases); 155 } 156 } 157 158 159 160 /** 161 * Retrieves the nickname of the certificate that a client should use to 162 * authenticate to a server. 163 * 164 * @param keyType The list of key algorithm names that may be used. 165 * @param issuers The list of acceptable issuer certificate subjects. It 166 * may be {@code null} if any issuer may be used. 167 * @param socket The socket to be used. It may be {@code null} if the 168 * certificate may be for any socket. 169 * 170 * @return The nickname of the certificate to use, or {@code null} if no 171 * appropriate certificate is found. 172 */ 173 @Override() 174 public final synchronized String chooseClientAlias(final String[] keyType, 175 final Principal[] issuers, 176 final Socket socket) 177 { 178 if (certificateAlias == null) 179 { 180 for (final X509KeyManager m : keyManagers) 181 { 182 final String alias = m.chooseClientAlias(keyType, issuers, socket); 183 if (alias != null) 184 { 185 return alias; 186 } 187 } 188 189 return null; 190 } 191 else 192 { 193 for (final String s : keyType) 194 { 195 for (final X509KeyManager m : keyManagers) 196 { 197 final String[] aliases = m.getClientAliases(s, issuers); 198 if (aliases != null) 199 { 200 for (final String alias : aliases) 201 { 202 if (alias.equals(certificateAlias)) 203 { 204 return certificateAlias; 205 } 206 } 207 } 208 } 209 } 210 211 return null; 212 } 213 } 214 215 216 217 /** 218 * Retrieves the nickname of the certificate that a client should use to 219 * authenticate to a server. 220 * 221 * @param keyType The list of key algorithm names that may be used. 222 * @param issuers The list of acceptable issuer certificate subjects. It 223 * may be {@code null} if any issuer may be used. 224 * @param engine The SSL engine to be used. It may be {@code null} if the 225 * certificate may be for any engine. 226 * 227 * @return The nickname of the certificate to use, or {@code null} if no 228 * appropriate certificate is found. 229 */ 230 @Override() 231 public final synchronized String chooseEngineClientAlias( 232 final String[] keyType, 233 final Principal[] issuers, 234 final SSLEngine engine) 235 { 236 if (certificateAlias == null) 237 { 238 for (final X509KeyManager m : keyManagers) 239 { 240 if (m instanceof X509ExtendedKeyManager) 241 { 242 final X509ExtendedKeyManager em = (X509ExtendedKeyManager) m; 243 final String alias = 244 em.chooseEngineClientAlias(keyType, issuers, engine); 245 if (alias != null) 246 { 247 return alias; 248 } 249 } 250 else 251 { 252 final String alias = m.chooseClientAlias(keyType, issuers, null); 253 if (alias != null) 254 { 255 return alias; 256 } 257 } 258 } 259 260 return null; 261 } 262 else 263 { 264 for (final String s : keyType) 265 { 266 for (final X509KeyManager m : keyManagers) 267 { 268 final String[] aliases = m.getClientAliases(s, issuers); 269 if (aliases != null) 270 { 271 for (final String alias : aliases) 272 { 273 if (alias.equals(certificateAlias)) 274 { 275 return certificateAlias; 276 } 277 } 278 } 279 } 280 } 281 282 return null; 283 } 284 } 285 286 287 288 /** 289 * Retrieves the nicknames of the server certificates of the specified type 290 * contained in the key store. 291 * 292 * @param keyType The key algorithm name for which to retrieve the available 293 * certificate nicknames. 294 * @param issuers The list of acceptable issuer certificate subjects. It 295 * may be {@code null} if any issuer may be used. 296 * 297 * @return The nicknames of the server certificates, or {@code null} if none 298 * were found in the key store. 299 */ 300 @Override() 301 public final synchronized String[] getServerAliases(final String keyType, 302 final Principal[] issuers) 303 { 304 final LinkedHashSet<String> serverAliases = 305 new LinkedHashSet<>(StaticUtils.computeMapCapacity(10)); 306 307 for (final X509KeyManager m : keyManagers) 308 { 309 final String[] aliases = m.getServerAliases(keyType, issuers); 310 if (aliases != null) 311 { 312 serverAliases.addAll(Arrays.asList(aliases)); 313 } 314 } 315 316 if (serverAliases.isEmpty()) 317 { 318 return null; 319 } 320 else 321 { 322 final String[] aliases = new String[serverAliases.size()]; 323 return serverAliases.toArray(aliases); 324 } 325 } 326 327 328 329 /** 330 * Retrieves the nickname of the certificate that a server should use to 331 * authenticate to a client. 332 * 333 * @param keyType The key algorithm name that may be used. 334 * @param issuers The list of acceptable issuer certificate subjects. It 335 * may be {@code null} if any issuer may be used. 336 * @param socket The socket to be used. It may be {@code null} if the 337 * certificate may be for any socket. 338 * 339 * @return The nickname of the certificate to use, or {@code null} if no 340 * appropriate certificate is found. 341 */ 342 @Override() 343 public final synchronized String chooseServerAlias(final String keyType, 344 final Principal[] issuers, 345 final Socket socket) 346 { 347 if (certificateAlias == null) 348 { 349 for (final X509KeyManager m : keyManagers) 350 { 351 final String alias = m.chooseServerAlias(keyType, issuers, socket); 352 if (alias != null) 353 { 354 return alias; 355 } 356 } 357 358 return null; 359 } 360 else 361 { 362 for (final X509KeyManager m : keyManagers) 363 { 364 final String[] aliases = m.getServerAliases(keyType, issuers); 365 if (aliases != null) 366 { 367 for (final String alias : aliases) 368 { 369 if (alias.equals(certificateAlias)) 370 { 371 return certificateAlias; 372 } 373 } 374 } 375 } 376 377 return null; 378 } 379 } 380 381 382 383 /** 384 * Retrieves the nickname of the certificate that a server should use to 385 * authenticate to a client. 386 * 387 * @param keyType The key algorithm name that may be used. 388 * @param issuers The list of acceptable issuer certificate subjects. It 389 * may be {@code null} if any issuer may be used. 390 * @param engine The SSL engine to be used. It may be {@code null} if the 391 * certificate may be for any engine. 392 * 393 * @return The nickname of the certificate to use, or {@code null} if no 394 * appropriate certificate is found. 395 */ 396 @Override() 397 public final synchronized String chooseEngineServerAlias(final String keyType, 398 final Principal[] issuers, 399 final SSLEngine engine) 400 { 401 if (certificateAlias == null) 402 { 403 for (final X509KeyManager m : keyManagers) 404 { 405 if (m instanceof X509ExtendedKeyManager) 406 { 407 final X509ExtendedKeyManager em = (X509ExtendedKeyManager) m; 408 final String alias = 409 em.chooseEngineServerAlias(keyType, issuers, engine); 410 if (alias != null) 411 { 412 return alias; 413 } 414 } 415 else 416 { 417 final String alias = m.chooseServerAlias(keyType, issuers, null); 418 if (alias != null) 419 { 420 return alias; 421 } 422 } 423 } 424 425 return null; 426 } 427 else 428 { 429 for (final X509KeyManager m : keyManagers) 430 { 431 final String[] aliases = m.getServerAliases(keyType, issuers); 432 if (aliases != null) 433 { 434 for (final String alias : aliases) 435 { 436 if (alias.equals(certificateAlias)) 437 { 438 return certificateAlias; 439 } 440 } 441 } 442 } 443 444 return null; 445 } 446 } 447 448 449 450 /** 451 * Retrieves the certificate chain for the certificate with the given 452 * nickname. 453 * 454 * @param alias The nickname of the certificate for which to retrieve the 455 * certificate chain. 456 * 457 * @return The certificate chain for the certificate with the given nickname, 458 * or {@code null} if the requested certificate cannot be found. 459 */ 460 @Override() 461 public final synchronized X509Certificate[] getCertificateChain( 462 final String alias) 463 { 464 for (final X509KeyManager m : keyManagers) 465 { 466 final X509Certificate[] chain = m.getCertificateChain(alias); 467 if (chain != null) 468 { 469 return chain; 470 } 471 } 472 473 return null; 474 } 475 476 477 478 /** 479 * Retrieves the private key for the specified certificate. 480 * 481 * @param alias The nickname of the certificate for which to retrieve the 482 * private key. 483 * 484 * @return The private key for the requested certificate, or {@code null} if 485 * the requested certificate cannot be found. 486 */ 487 @Override() 488 public final synchronized PrivateKey getPrivateKey(final String alias) 489 { 490 for (final X509KeyManager m : keyManagers) 491 { 492 final PrivateKey key = m.getPrivateKey(alias); 493 if (key != null) 494 { 495 return key; 496 } 497 } 498 499 return null; 500 } 501}