001 /* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at 010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE 011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE. 012 * See the License for the specific language governing permissions 013 * and limitations under the License. 014 * 015 * When distributing Covered Code, include this CDDL HEADER in each 016 * file and include the License file at 017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, 018 * add the following below this CDDL HEADER, with the fields enclosed 019 * by brackets "[]" replaced with your own identifying information: 020 * Portions Copyright [yyyy] [name of copyright owner] 021 * 022 * CDDL HEADER END 023 * 024 * 025 * Copyright 2008 Sun Microsystems, Inc. 026 */ 027 package org.opends.server.util; 028 029 030 031 import java.net.Socket; 032 import java.security.Principal; 033 import java.security.PrivateKey; 034 import java.security.cert.X509Certificate; 035 import javax.net.ssl.KeyManager; 036 import javax.net.ssl.SSLEngine; 037 import javax.net.ssl.X509ExtendedKeyManager; 038 import javax.net.ssl.X509KeyManager; 039 040 041 042 /** 043 * This class implements an X.509 key manager that will be used to wrap an 044 * existing key manager and makes it possible to configure which certificate(s) 045 * should be used for client and/or server operations. The certificate 046 * selection will be based on the alias (also called the nickname) of the 047 * certificate. 048 */ 049 @org.opends.server.types.PublicAPI( 050 stability=org.opends.server.types.StabilityLevel.UNCOMMITTED, 051 mayInstantiate=true, 052 mayExtend=false, 053 mayInvoke=true) 054 public final class SelectableCertificateKeyManager 055 extends X509ExtendedKeyManager 056 { 057 // The alias of the certificate that should be selected from the key manager. 058 private String alias; 059 060 // The key manager that is wrapped by this key manager. 061 private X509KeyManager keyManager; 062 063 064 065 /** 066 * Creates a new instance of this key manager that will wrap the provided key 067 * manager and use the certificate with the specified alias. 068 * 069 * @param keyManager The key manager to be wrapped by this key manager. 070 * @param alias The nickname of the certificate that should be 071 * selected for operations involving this key manager. 072 */ 073 public SelectableCertificateKeyManager(X509KeyManager keyManager, 074 String alias) 075 { 076 super(); 077 078 this.keyManager = keyManager; 079 this.alias = alias; 080 } 081 082 083 084 /** 085 * Chooses the alias of the client certificate that should be used based on 086 * the provided critieria. This will either return the preferred alias 087 * configured for this key manager, or {@code null} if no client certificate 088 * with that alias is configured in the underlying key manager. 089 * 090 * @param keyType The set of key algorithm names, ordered with the most 091 * preferred key type first. 092 * @param issuers The list of acceptable issuer subject names, or 093 * {@code null} if any issuer may be used. 094 * @param socket The socket to be used for this connection. 095 * 096 * @return The alias configured for this key manager, or {@code null} if no 097 * such client certificate is available with that alias. 098 */ 099 public String chooseClientAlias(String[] keyType, Principal[] issuers, 100 Socket socket) 101 { 102 for (String type : keyType) 103 { 104 String[] clientAliases = keyManager.getClientAliases(type, issuers); 105 if (clientAliases != null) 106 { 107 for (String clientAlias : clientAliases) 108 { 109 if (clientAlias.equals(alias)) 110 { 111 return alias; 112 } 113 } 114 } 115 } 116 117 return null; 118 } 119 120 121 122 /** 123 * Chooses the alias of the client certificate that should be used based on 124 * the provided critieria. This will either return the preferred alias 125 * configured for this key manager, or {@code null} if no client certificate 126 * with that alias is configured in the underlying key manager. 127 * 128 * @param keyType The set of key algorithm names, ordered with the most 129 * preferred key type first. 130 * @param issuers The list of acceptable issuer subject names, or 131 * {@code null} if any issuer may be used. 132 * @param engine The SSL engine to be used for this connection. 133 * 134 * @return The alias configured for this key manager, or {@code null} if no 135 * such client certificate is available with that alias. 136 */ 137 public String chooseEngineClientAlias(String[] keyType, Principal[] issuers, 138 SSLEngine engine) 139 { 140 for (String type : keyType) 141 { 142 String[] clientAliases = keyManager.getClientAliases(type, issuers); 143 if (clientAliases != null) 144 { 145 for (String clientAlias : clientAliases) 146 { 147 if (clientAlias.equals(alias)) 148 { 149 return alias; 150 } 151 } 152 } 153 } 154 155 return null; 156 } 157 158 159 160 /** 161 * Chooses the alias of the server certificate that should be used based on 162 * the provided critieria. This will either return the preferred alias 163 * configured for this key manager, or {@code null} if no server certificate 164 * with that alias is configured in the underlying key manager. 165 * 166 * @param keyType The public key type for the certificate. 167 * @param issuers The list of acceptable issuer subject names, or 168 * {@code null} if any issuer may be used. 169 * @param socket The socket to be used for this connection. 170 * 171 * @return The alias configured for this key manager, or {@code null} if no 172 * such server certificate is available with that alias. 173 */ 174 public String chooseServerAlias(String keyType, Principal[] issuers, 175 Socket socket) 176 { 177 String[] serverAliases = keyManager.getServerAliases(keyType, issuers); 178 if (serverAliases != null) 179 { 180 for (String serverAlias : serverAliases) 181 { 182 if (serverAlias.equals(alias)) 183 { 184 return alias; 185 } 186 } 187 } 188 189 return null; 190 } 191 192 193 194 /** 195 * Chooses the alias of the server certificate that should be used based on 196 * the provided critieria. This will either return the preferred alias 197 * configured for this key manager, or {@code null} if no server certificate 198 * with that alias is configured in the underlying key manager. 199 * 200 * @param keyType The public key type for the certificate. 201 * @param issuers The list of acceptable issuer subject names, or 202 * {@code null} if any issuer may be used. 203 * @param engine The SSL engine to be used for this connection. 204 * 205 * @return The alias configured for this key manager, or {@code null} if no 206 * such server certificate is available with that alias. 207 */ 208 public String chooseEngineServerAlias(String keyType, Principal[] issuers, 209 SSLEngine engine) 210 { 211 String[] serverAliases = keyManager.getServerAliases(keyType, issuers); 212 if (serverAliases != null) 213 { 214 for (String serverAlias : serverAliases) 215 { 216 if (serverAlias.equals(alias)) 217 { 218 return alias; 219 } 220 } 221 } 222 223 return null; 224 } 225 226 227 228 /** 229 * Retrieves the certificate chain for the provided alias. 230 * 231 * @param alias The alias for the certificate chain to retrieve. 232 * 233 * @return The certificate chain for the provided alias, or {@code null} if 234 * no certificate is associated with the provided alias. 235 */ 236 public X509Certificate[] getCertificateChain(String alias) 237 { 238 return keyManager.getCertificateChain(alias); 239 } 240 241 242 243 /** 244 * Retrieves the set of certificate aliases that may be used for client 245 * authentication with the given public key type and set of issuers. 246 * 247 * @param keyType The public key type for the aliases to retrieve. 248 * @param issuers The list of acceptable issuer subject names, or 249 * {@code null} if any issuer may be used. 250 * 251 * @return The set of certificate aliases that may be used for client 252 * authentication with the given public key type and set of issuers, 253 * or {@code null} if there were none. 254 */ 255 public String[] getClientAliases(String keyType, Principal[] issuers) 256 { 257 return keyManager.getClientAliases(keyType, issuers); 258 } 259 260 261 262 /** 263 * Retrieves the private key for the provided alias. 264 * 265 * @param alias The alias for the private key to return. 266 * 267 * @return The private key for the provided alias, or {@code null} if no 268 * private key is available for the provided alias. 269 */ 270 public PrivateKey getPrivateKey(String alias) 271 { 272 return keyManager.getPrivateKey(alias); 273 } 274 275 276 277 /** 278 * Retrieves the set of certificate aliases that may be used for server 279 * authentication with the given public key type and set of issuers. 280 * 281 * @param keyType The public key type for the aliases to retrieve. 282 * @param issuers The list of acceptable issuer subject names, or 283 * {@code null} if any issuer may be used. 284 * 285 * @return The set of certificate aliases that may be used for server 286 * authentication with the given public key type and set of issuers, 287 * or {@code null} if there were none. 288 */ 289 public String[] getServerAliases(String keyType, Principal[] issuers) 290 { 291 return keyManager.getServerAliases(keyType, issuers); 292 } 293 294 295 296 /** 297 * Wraps the provided set of key managers in selectable certificate key 298 * managers using the provided alias. 299 * 300 * @param keyManagers The set of key managers to be wrapped. 301 * @param alias The alias to use for selecting the desired 302 * certificate. 303 * 304 * @return A key manager array 305 */ 306 public static X509ExtendedKeyManager[] wrap(KeyManager[] keyManagers, 307 String alias) 308 { 309 X509ExtendedKeyManager[] newKeyManagers = 310 new X509ExtendedKeyManager[keyManagers.length]; 311 for (int i=0; i < keyManagers.length; i++) 312 { 313 newKeyManagers[i] = new SelectableCertificateKeyManager( 314 (X509KeyManager) keyManagers[i], alias); 315 } 316 317 return newKeyManagers; 318 } 319 } 320