1 package org.ejbca.core.protocol.xkms.client; 2 3 import java.io.BufferedInputStream ; 4 import java.io.BufferedReader ; 5 import java.io.FileInputStream ; 6 import java.io.FileNotFoundException ; 7 import java.io.FileOutputStream ; 8 import java.io.IOException ; 9 import java.io.InputStreamReader ; 10 import java.io.PrintStream ; 11 import java.math.BigInteger ; 12 import java.security.Key ; 13 import java.security.KeyStore ; 14 import java.security.KeyStoreException ; 15 import java.security.NoSuchAlgorithmException ; 16 import java.security.NoSuchProviderException ; 17 import java.security.SecureRandom ; 18 import java.security.UnrecoverableKeyException ; 19 import java.security.cert.Certificate ; 20 import java.security.cert.CertificateException ; 21 import java.security.cert.X509Certificate ; 22 import java.util.ArrayList ; 23 import java.util.Collection ; 24 import java.util.Date ; 25 import java.util.Iterator ; 26 import java.util.List ; 27 import java.util.Properties ; 28 import java.util.Random ; 29 30 import org.ejbca.core.model.ca.crl.RevokedCertInfo; 31 import org.ejbca.core.protocol.xkms.common.XKMSConstants; 32 import org.ejbca.util.CertTools; 33 import org.ejbca.util.P12toPEM; 34 import org.w3._2002._03.xkms_.KeyBindingType; 35 import org.w3._2002._03.xkms_.StatusType; 36 import org.w3._2002._03.xkms_.UnverifiedKeyBindingType; 37 import org.w3._2002._03.xkms_.UseKeyWithType; 38 39 46 47 public abstract class XKMSCLIBaseCommand { 48 49 protected String [] args = null; 50 private XKMSInvoker xkms = null; 51 private Properties props = null; 52 private String password = null; 53 54 protected X509Certificate clientCert = null; 55 protected Key privateKey = null; 56 private Collection catrustlist = null; 57 58 59 protected static final String [] REASON_TEXTS ={"NOT REVOKED","UNSPECIFIED","KEYCOMPROMISE","CACOMPROMISE", 60 "AFFILIATIONCHANGED","SUPERSEDED","CESSATIONOFOPERATION", 61 "CERTIFICATEHOLD","REMOVEFROMCRL","PRIVILEGESWITHDRAWN", 62 "AACOMPROMISE"}; 63 64 protected static final String RESPONDWITH_X509CERT = "X509CERT"; 65 protected static final String RESPONDWITH_X509CHAIN = "X509CHAIN"; 66 protected static final String RESPONDWITH_X509CHAINANDCRL = "X509CHAINANDCRL"; 67 68 protected static final String ENCODING_PEM = "pem"; 69 protected static final String ENCODING_DER = "der"; 70 protected static final String ENCODING_P12 = "p12"; 71 protected static final String ENCODING_JKS = "jks"; 72 73 protected static final String KEYUSAGE_ALL = "ALL"; 74 protected static final String KEYUSAGE_SIGNATURE = "SIGNATURE"; 75 protected static final String KEYUSAGE_ENCRYPTION = "ENCRYPTION"; 76 protected static final String KEYUSAGE_EXCHANGE = "EXCHANGE"; 77 78 protected static final String QUERYTYPE_CERT = "CERT"; 79 protected static final String QUERYTYPE_SMIME = "SMIME"; 80 protected static final String QUERYTYPE_TLS = "TLS"; 81 protected static final String QUERYTYPE_TLSHTTP = "TLSHTTP"; 82 protected static final String QUERYTYPE_TLSSMTP = "TLSSMTP"; 83 protected static final String QUERYTYPE_IPSEC = "IPSEC"; 84 protected static final String QUERYTYPE_PKIX = "PKIX"; 85 86 public static final int NOT_REVOKED = RevokedCertInfo.NOT_REVOKED; 87 public static final int REVOKATION_REASON_UNSPECIFIED = RevokedCertInfo.REVOKATION_REASON_UNSPECIFIED; 88 public static final int REVOKATION_REASON_KEYCOMPROMISE = RevokedCertInfo.REVOKATION_REASON_KEYCOMPROMISE; 89 public static final int REVOKATION_REASON_CACOMPROMISE = RevokedCertInfo.REVOKATION_REASON_CACOMPROMISE; 90 public static final int REVOKATION_REASON_AFFILIATIONCHANGED = RevokedCertInfo.REVOKATION_REASON_AFFILIATIONCHANGED; 91 public static final int REVOKATION_REASON_SUPERSEDED = RevokedCertInfo.REVOKATION_REASON_SUPERSEDED; 92 public static final int REVOKATION_REASON_CESSATIONOFOPERATION = RevokedCertInfo.REVOKATION_REASON_CESSATIONOFOPERATION; 93 public static final int REVOKATION_REASON_CERTIFICATEHOLD = RevokedCertInfo.REVOKATION_REASON_CERTIFICATEHOLD; 94 public static final int REVOKATION_REASON_REMOVEFROMCRL = RevokedCertInfo.REVOKATION_REASON_REMOVEFROMCRL; 95 public static final int REVOKATION_REASON_PRIVILEGESWITHDRAWN = RevokedCertInfo.REVOKATION_REASON_PRIVILEGESWITHDRAWN; 96 public static final int REVOKATION_REASON_AACOMPROMISE = RevokedCertInfo.REVOKATION_REASON_AACOMPROMISE; 97 98 protected static final int[] REASON_VALUES = {NOT_REVOKED,REVOKATION_REASON_UNSPECIFIED, 99 REVOKATION_REASON_KEYCOMPROMISE, REVOKATION_REASON_CACOMPROMISE, 100 REVOKATION_REASON_AFFILIATIONCHANGED, REVOKATION_REASON_SUPERSEDED, 101 REVOKATION_REASON_CESSATIONOFOPERATION, REVOKATION_REASON_CERTIFICATEHOLD, 102 REVOKATION_REASON_REMOVEFROMCRL, REVOKATION_REASON_PRIVILEGESWITHDRAWN, 103 REVOKATION_REASON_AACOMPROMISE}; 104 105 XKMSCLIBaseCommand(String [] args){ 106 CertTools.installBCProvider(); 107 this.args = args; 108 109 } 110 111 117 protected XKMSInvoker getXKMSInvoker() throws FileNotFoundException , IOException { 118 if(xkms == null){ 119 120 if(getKeyStorePath()!=null){ 121 try{ 122 KeyStore clientKeyStore = KeyStore.getInstance("JKS"); 123 clientKeyStore.load(new FileInputStream (getKeyStorePath()), getKeyStorePassword().toCharArray()); 124 if(getKeyStoreAlias() == null){ 125 throw new IOException ("Error no alias specified in the property file"); 126 } 127 String alias = getKeyStoreAlias(); 128 clientCert = (java.security.cert.X509Certificate )clientKeyStore.getCertificate(alias); 129 privateKey = clientKeyStore.getKey(alias,"foo123".toCharArray()); 130 Certificate [] trustedcerts = clientKeyStore.getCertificateChain(alias); 131 catrustlist = new ArrayList (); 132 for(int i=0;i<trustedcerts.length;i++ ){ 133 if(((X509Certificate )trustedcerts[i]).getBasicConstraints() != -1){ 134 catrustlist.add(trustedcerts[i]); 135 } 136 } 137 }catch(Exception e){ 138 throw new IOException ("Error reading client keystore " + e.getMessage()); 139 } 140 } 141 142 xkms = new XKMSInvoker(getWebServiceURL(),catrustlist); 143 144 } 145 146 return xkms; 147 148 } 149 150 private String getKeyStorePassword() throws FileNotFoundException , IOException { 151 if(password == null){ 152 if(getProperties().getProperty("xkmscli.keystore.password") == null){ 153 BufferedReader reader = new BufferedReader (new InputStreamReader (System.in)); 154 System.out.print("Enter keystore password :"); 155 password = reader.readLine(); 156 }else{ 157 password = getProperties().getProperty("xkmscli.keystore.password"); 158 } 159 } 160 return password; 161 } 162 163 private String getKeyStorePath() throws FileNotFoundException , IOException { 164 return getProperties().getProperty("xkmscli.keystore.path"); 165 } 166 167 private String getKeyStoreAlias() throws FileNotFoundException , IOException { 168 return getProperties().getProperty("xkmscli.keystore.alias"); 169 } 170 171 private String getWebServiceURL() throws FileNotFoundException , IOException { 172 return getProperties().getProperty("xkmscli.url", "http://localhost:8080/ejbca/xkms/xkms"); 173 } 174 175 private Properties getProperties() throws FileNotFoundException , IOException { 176 if(props == null){ 177 props = new Properties (); 178 try { 179 props.load(new FileInputStream ("xkmscli.properties")); 180 } catch (FileNotFoundException e) { 181 props.load(new FileInputStream ("../xkmscli.properties")); 183 } 184 } 185 return props; 186 } 187 188 protected PrintStream getPrintStream(){ 189 return System.out; 190 } 191 192 protected int getRevokeReason(String reason) throws Exception { 193 for(int i=0;i<REASON_TEXTS.length;i++){ 194 if(REASON_TEXTS[i].equalsIgnoreCase(reason)){ 195 return REASON_VALUES[i]; 196 } 197 } 198 getPrintStream().println("Error : Unsupported reason " + reason); 199 usage(); 200 System.exit(-1); 201 return 0; 202 } 203 204 protected String genId() throws NoSuchAlgorithmException { 205 BigInteger serno = null; 206 Random random = SecureRandom.getInstance("SHA1PRNG"); 207 208 long seed = Math.abs((new Date ().getTime()) + this.hashCode()); 209 random.setSeed(seed); 210 try { 211 byte[] sernobytes = new byte[8]; 212 213 random.nextBytes(sernobytes); 214 serno = (new java.math.BigInteger (sernobytes)).abs(); 215 216 } catch (Exception e) { 217 getPrintStream().println("Error generating response ID " ); 218 } 219 return "_" + serno.toString(); 220 } 221 222 228 protected Collection getResponseWith(String arg) { 229 ArrayList retval = new ArrayList (); 230 231 if(arg.equalsIgnoreCase(RESPONDWITH_X509CERT)){ 232 retval.add(XKMSConstants.RESPONDWITH_X509CERT); 233 return retval; 234 } 235 236 if(arg.equalsIgnoreCase(RESPONDWITH_X509CHAIN)){ 237 retval.add(XKMSConstants.RESPONDWITH_X509CHAIN); 238 return retval; 239 } 240 241 if(arg.equalsIgnoreCase(RESPONDWITH_X509CHAINANDCRL)){ 242 retval.add(XKMSConstants.RESPONDWITH_X509CHAIN); 243 retval.add(XKMSConstants.RESPONDWITH_X509CRL); 244 return retval; 245 } 246 247 getPrintStream().println("Illegal response with " + arg); 248 usage(); 249 System.exit(-1); 250 return null; 251 } 252 253 258 protected byte[] loadCert(String arg) { 259 try { 260 BufferedInputStream bis = new BufferedInputStream (new FileInputStream (arg)); 261 byte[] retval = new byte[bis.available()]; 262 bis.read(retval); 263 return retval; 264 265 } catch (FileNotFoundException e) { 266 getPrintStream().println("Couldn't find file with name " + arg); 267 usage(); 268 System.exit(-1); 269 } catch (IOException e) { 270 getPrintStream().println("Couldn't read file with name " + arg); 271 usage(); 272 System.exit(-1); 273 } 274 return null; 275 } 276 277 protected String getRevokeReason(int reason) { 278 for(int i=0;i<REASON_VALUES.length;i++){ 279 if(REASON_VALUES[i]==reason){ 280 return REASON_TEXTS[i]; 281 } 282 } 283 getPrintStream().println("Error : Unsupported reason " + reason); 284 usage(); 285 System.exit(-1); 286 return null; 287 } 288 289 protected void displayKeyUsage(UnverifiedKeyBindingType next) { 290 Iterator <String > iter = next.getKeyUsage().iterator(); 291 getPrintStream().println(" Certificate have the following key usage:"); 292 if(next.getKeyUsage().size() == 0){ 293 getPrintStream().println(" " + KEYUSAGE_ALL ); 294 } 295 while(iter.hasNext()){ 296 String keyUsage = iter.next(); 297 if(keyUsage.equals(XKMSConstants.KEYUSAGE_SIGNATURE)){ 298 getPrintStream().println(" " + KEYUSAGE_SIGNATURE ); 299 } 300 if(keyUsage.equals(XKMSConstants.KEYUSAGE_ENCRYPTION)){ 301 getPrintStream().println(" " + KEYUSAGE_ENCRYPTION); 302 } 303 if(keyUsage.equals(XKMSConstants.KEYUSAGE_EXCHANGE)){ 304 getPrintStream().println(" " + KEYUSAGE_EXCHANGE); 305 } 306 } 307 308 } 309 310 311 312 protected void displayUseKeyWith(UnverifiedKeyBindingType next) { 313 Iterator <UseKeyWithType> iter = next.getUseKeyWith().iterator(); 314 if(next.getKeyUsage().size() != 0){ 315 getPrintStream().println(" Certificate can be used with applications:"); 316 while(iter.hasNext()){ 317 UseKeyWithType useKeyWith = iter.next(); 318 if(useKeyWith.getApplication().equals(XKMSConstants.USEKEYWITH_IPSEC)){ 319 getPrintStream().println(" " + QUERYTYPE_IPSEC + " = " + useKeyWith.getIdentifier()); 320 } 321 if(useKeyWith.getApplication().equals(XKMSConstants.USEKEYWITH_PKIX)){ 322 getPrintStream().println(" " + QUERYTYPE_PKIX + " = " + useKeyWith.getIdentifier()); 323 } 324 if(useKeyWith.getApplication().equals(XKMSConstants.USEKEYWITH_SMIME)){ 325 getPrintStream().println(" " + QUERYTYPE_SMIME + " = " + useKeyWith.getIdentifier()); 326 } 327 if(useKeyWith.getApplication().equals(XKMSConstants.USEKEYWITH_TLS)){ 328 getPrintStream().println(" " + QUERYTYPE_TLS + " = " + useKeyWith.getIdentifier()); 329 } 330 if(useKeyWith.getApplication().equals(XKMSConstants.USEKEYWITH_TLSHTTP)){ 331 getPrintStream().println(" " + QUERYTYPE_TLSHTTP + " = " + useKeyWith.getIdentifier()); 332 } 333 if(useKeyWith.getApplication().equals(XKMSConstants.USEKEYWITH_TLSSMTP)){ 334 getPrintStream().println(" " + QUERYTYPE_TLSSMTP + " = " + useKeyWith.getIdentifier()); 335 } 336 } 337 } 338 } 339 340 350 protected void storeKeyStore(KeyStore ks, String username, String kspassword, boolean createJKS, 351 boolean createPEM, String mainStoreDir) 352 throws IOException , KeyStoreException , UnrecoverableKeyException , NoSuchAlgorithmException , 353 NoSuchProviderException , CertificateException { 354 355 if (mainStoreDir == null) { 357 throw new IOException ("Can't find directory to store keystore in."); 358 } 359 360 String keyStoreFilename = mainStoreDir + username; 361 362 if (createJKS) { 363 keyStoreFilename += ".jks"; 364 } else { 365 keyStoreFilename += ".p12"; 366 } 367 368 if (createPEM) { 370 String PEMfilename = mainStoreDir + "pem"; 371 P12toPEM p12topem = new P12toPEM(ks, kspassword, true); 372 p12topem.setExportPath(PEMfilename); 373 p12topem.createPEM(); 374 getPrintStream().println("Keystore written successfully to the directory " + PEMfilename); 375 } else { 376 FileOutputStream os = new FileOutputStream (keyStoreFilename); 377 ks.store(os, kspassword.toCharArray()); 378 getPrintStream().println("Keystore written successfully to " + keyStoreFilename); 379 } 380 381 382 383 } 385 protected void displayStatus(KeyBindingType type) { 386 StatusType status = type.getStatus(); 387 getPrintStream().println(" The certificate had the following status"); 388 getPrintStream().println(" Valid:"); 389 displayStatusReasons(status.getValidReason()); 390 getPrintStream().println(" Indeterminable:"); 391 displayStatusReasons(status.getIndeterminateReason()); 392 getPrintStream().println(" Invalid:"); 393 displayStatusReasons(status.getInvalidReason()); 394 395 } 396 397 private void displayStatusReasons(List <String > reasons) { 398 if(reasons.size() == 0){ 399 getPrintStream().println(" NONE"); 400 }else{ 401 Iterator <String > iter = reasons.iterator(); 402 while(iter.hasNext()){ 403 String next = iter.next(); 404 if(next.equals(XKMSConstants.STATUSREASON_ISSUERTRUST)){ 405 getPrintStream().println(" ISSUERTRUST"); 406 } 407 if(next.equals(XKMSConstants.STATUSREASON_REVOCATIONSTATUS)){ 408 getPrintStream().println(" REVOCATIONSTATUS"); 409 } 410 if(next.equals(XKMSConstants.STATUSREASON_SIGNATURE)){ 411 getPrintStream().println(" SIGNATURE"); 412 } 413 if(next.equals(XKMSConstants.STATUSREASON_VALIDITYINTERVAL)){ 414 getPrintStream().println(" VALIDITYINTERVAL"); 415 } 416 } 417 } 418 } 419 420 421 protected abstract void usage(); 422 423 } 424 | Popular Tags |