001/* 002 * Copyright 2008-2017 UnboundID Corp. 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2008-2017 UnboundID Corp. 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 public final synchronized String[] getClientAliases(final String keyType, 131 final Principal[] issuers) 132 { 133 final LinkedHashSet<String> clientAliases = new LinkedHashSet<String>(); 134 135 for (final X509KeyManager m : keyManagers) 136 { 137 final String[] aliases = m.getClientAliases(keyType, issuers); 138 if (aliases != null) 139 { 140 clientAliases.addAll(Arrays.asList(aliases)); 141 } 142 } 143 144 if (clientAliases.isEmpty()) 145 { 146 return null; 147 } 148 else 149 { 150 final String[] aliases = new String[clientAliases.size()]; 151 return clientAliases.toArray(aliases); 152 } 153 } 154 155 156 157 /** 158 * Retrieves the nickname of the certificate that a client should use to 159 * authenticate to a server. 160 * 161 * @param keyType The list of key algorithm names that may be used. 162 * @param issuers The list of acceptable issuer certificate subjects. It 163 * may be {@code null} if any issuer may be used. 164 * @param socket The socket to be used. It may be {@code null} if the 165 * certificate may be for any socket. 166 * 167 * @return The nickname of the certificate to use, or {@code null} if no 168 * appropriate certificate is found. 169 */ 170 public final synchronized String chooseClientAlias(final String[] keyType, 171 final Principal[] issuers, 172 final Socket socket) 173 { 174 if (certificateAlias == null) 175 { 176 for (final X509KeyManager m : keyManagers) 177 { 178 final String alias = m.chooseClientAlias(keyType, issuers, socket); 179 if (alias != null) 180 { 181 return alias; 182 } 183 } 184 185 return null; 186 } 187 else 188 { 189 for (final String s : keyType) 190 { 191 for (final X509KeyManager m : keyManagers) 192 { 193 final String[] aliases = m.getClientAliases(s, issuers); 194 if (aliases != null) 195 { 196 for (final String alias : aliases) 197 { 198 if (alias.equals(certificateAlias)) 199 { 200 return certificateAlias; 201 } 202 } 203 } 204 } 205 } 206 207 return null; 208 } 209 } 210 211 212 213 /** 214 * Retrieves the nickname of the certificate that a client should use to 215 * authenticate to a server. 216 * 217 * @param keyType The list of key algorithm names that may be used. 218 * @param issuers The list of acceptable issuer certificate subjects. It 219 * may be {@code null} if any issuer may be used. 220 * @param engine The SSL engine to be used. It may be {@code null} if the 221 * certificate may be for any engine. 222 * 223 * @return The nickname of the certificate to use, or {@code null} if no 224 * appropriate certificate is found. 225 */ 226 @Override() 227 public final synchronized String chooseEngineClientAlias( 228 final String[] keyType, 229 final Principal[] issuers, 230 final SSLEngine engine) 231 { 232 if (certificateAlias == null) 233 { 234 for (final X509KeyManager m : keyManagers) 235 { 236 if (m instanceof X509ExtendedKeyManager) 237 { 238 final X509ExtendedKeyManager em = (X509ExtendedKeyManager) m; 239 final String alias = 240 em.chooseEngineClientAlias(keyType, issuers, engine); 241 if (alias != null) 242 { 243 return alias; 244 } 245 } 246 else 247 { 248 final String alias = m.chooseClientAlias(keyType, issuers, null); 249 if (alias != null) 250 { 251 return alias; 252 } 253 } 254 } 255 256 return null; 257 } 258 else 259 { 260 for (final String s : keyType) 261 { 262 for (final X509KeyManager m : keyManagers) 263 { 264 final String[] aliases = m.getClientAliases(s, issuers); 265 if (aliases != null) 266 { 267 for (final String alias : aliases) 268 { 269 if (alias.equals(certificateAlias)) 270 { 271 return certificateAlias; 272 } 273 } 274 } 275 } 276 } 277 278 return null; 279 } 280 } 281 282 283 284 /** 285 * Retrieves the nicknames of the server certificates of the specified type 286 * contained in the key store. 287 * 288 * @param keyType The key algorithm name for which to retrieve the available 289 * certificate nicknames. 290 * @param issuers The list of acceptable issuer certificate subjects. It 291 * may be {@code null} if any issuer may be used. 292 * 293 * @return The nicknames of the server certificates, or {@code null} if none 294 * were found in the key store. 295 */ 296 public final synchronized String[] getServerAliases(final String keyType, 297 final Principal[] issuers) 298 { 299 final LinkedHashSet<String> serverAliases = new LinkedHashSet<String>(); 300 301 for (final X509KeyManager m : keyManagers) 302 { 303 final String[] aliases = m.getServerAliases(keyType, issuers); 304 if (aliases != null) 305 { 306 serverAliases.addAll(Arrays.asList(aliases)); 307 } 308 } 309 310 if (serverAliases.isEmpty()) 311 { 312 return null; 313 } 314 else 315 { 316 final String[] aliases = new String[serverAliases.size()]; 317 return serverAliases.toArray(aliases); 318 } 319 } 320 321 322 323 /** 324 * Retrieves the nickname of the certificate that a server should use to 325 * authenticate to a client. 326 * 327 * @param keyType The key algorithm name that may be used. 328 * @param issuers The list of acceptable issuer certificate subjects. It 329 * may be {@code null} if any issuer may be used. 330 * @param socket The socket to be used. It may be {@code null} if the 331 * certificate may be for any socket. 332 * 333 * @return The nickname of the certificate to use, or {@code null} if no 334 * appropriate certificate is found. 335 */ 336 public final synchronized String chooseServerAlias(final String keyType, 337 final Principal[] issuers, 338 final Socket socket) 339 { 340 if (certificateAlias == null) 341 { 342 for (final X509KeyManager m : keyManagers) 343 { 344 final String alias = m.chooseServerAlias(keyType, issuers, socket); 345 if (alias != null) 346 { 347 return alias; 348 } 349 } 350 351 return null; 352 } 353 else 354 { 355 for (final X509KeyManager m : keyManagers) 356 { 357 final String[] aliases = m.getServerAliases(keyType, issuers); 358 if (aliases != null) 359 { 360 for (final String alias : aliases) 361 { 362 if (alias.equals(certificateAlias)) 363 { 364 return certificateAlias; 365 } 366 } 367 } 368 } 369 370 return null; 371 } 372 } 373 374 375 376 /** 377 * Retrieves the nickname of the certificate that a server should use to 378 * authenticate to a client. 379 * 380 * @param keyType The key algorithm name that may be used. 381 * @param issuers The list of acceptable issuer certificate subjects. It 382 * may be {@code null} if any issuer may be used. 383 * @param engine The SSL engine to be used. It may be {@code null} if the 384 * certificate may be for any engine. 385 * 386 * @return The nickname of the certificate to use, or {@code null} if no 387 * appropriate certificate is found. 388 */ 389 @Override() 390 public final synchronized String chooseEngineServerAlias(final String keyType, 391 final Principal[] issuers, 392 final SSLEngine engine) 393 { 394 if (certificateAlias == null) 395 { 396 for (final X509KeyManager m : keyManagers) 397 { 398 if (m instanceof X509ExtendedKeyManager) 399 { 400 final X509ExtendedKeyManager em = (X509ExtendedKeyManager) m; 401 final String alias = 402 em.chooseEngineServerAlias(keyType, issuers, engine); 403 if (alias != null) 404 { 405 return alias; 406 } 407 } 408 else 409 { 410 final String alias = m.chooseServerAlias(keyType, issuers, null); 411 if (alias != null) 412 { 413 return alias; 414 } 415 } 416 } 417 418 return null; 419 } 420 else 421 { 422 for (final X509KeyManager m : keyManagers) 423 { 424 final String[] aliases = m.getServerAliases(keyType, issuers); 425 if (aliases != null) 426 { 427 for (final String alias : aliases) 428 { 429 if (alias.equals(certificateAlias)) 430 { 431 return certificateAlias; 432 } 433 } 434 } 435 } 436 437 return null; 438 } 439 } 440 441 442 443 /** 444 * Retrieves the certificate chain for the certificate with the given 445 * nickname. 446 * 447 * @param alias The nickname of the certificate for which to retrieve the 448 * certificate chain. 449 * 450 * @return The certificate chain for the certificate with the given nickname, 451 * or {@code null} if the requested certificate cannot be found. 452 */ 453 public final synchronized X509Certificate[] getCertificateChain( 454 final String alias) 455 { 456 for (final X509KeyManager m : keyManagers) 457 { 458 final X509Certificate[] chain = m.getCertificateChain(alias); 459 if (chain != null) 460 { 461 return chain; 462 } 463 } 464 465 return null; 466 } 467 468 469 470 /** 471 * Retrieves the private key for the specified certificate. 472 * 473 * @param alias The nickname of the certificate for which to retrieve the 474 * private key. 475 * 476 * @return The private key for the requested certificate, or {@code null} if 477 * the requested certificate cannot be found. 478 */ 479 public final synchronized PrivateKey getPrivateKey(final String alias) 480 { 481 for (final X509KeyManager m : keyManagers) 482 { 483 final PrivateKey key = m.getPrivateKey(alias); 484 if (key != null) 485 { 486 return key; 487 } 488 } 489 490 return null; 491 } 492}