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