1 13 14 package org.ejbca.core.protocol.xkms.client; 15 16 import java.io.FileOutputStream ; 17 import java.io.IOException ; 18 import java.security.cert.CRLException ; 19 import java.security.cert.CertificateException ; 20 import java.security.cert.X509CRL ; 21 import java.security.cert.X509Certificate ; 22 import java.util.ArrayList ; 23 import java.util.Collection ; 24 import java.util.Iterator ; 25 import java.util.List ; 26 27 import javax.xml.bind.JAXBElement; 28 29 import org.ejbca.core.protocol.xkms.common.XKMSConstants; 30 import org.ejbca.ui.cli.ErrorAdminCommandException; 31 import org.ejbca.ui.cli.IAdminCommand; 32 import org.ejbca.ui.cli.IllegalAdminCommandException; 33 import org.ejbca.util.Base64; 34 import org.ejbca.util.CertTools; 35 import org.w3._2000._09.xmldsig_.KeyInfoType; 36 import org.w3._2000._09.xmldsig_.X509DataType; 37 import org.w3._2002._03.xkms_.KeyBindingType; 38 import org.w3._2002._03.xkms_.LocateRequestType; 39 import org.w3._2002._03.xkms_.LocateResultType; 40 import org.w3._2002._03.xkms_.ObjectFactory; 41 import org.w3._2002._03.xkms_.QueryKeyBindingType; 42 import org.w3._2002._03.xkms_.UnverifiedKeyBindingType; 43 import org.w3._2002._03.xkms_.UseKeyWithType; 44 import org.w3._2002._03.xkms_.ValidateRequestType; 45 import org.w3._2002._03.xkms_.ValidateResultType; 46 47 48 49 50 51 57 public class LocateCommand extends XKMSCLIBaseCommand implements IAdminCommand{ 58 59 private ObjectFactory xKMSObjectFactory = new ObjectFactory(); 60 private org.w3._2000._09.xmldsig_.ObjectFactory sigFactory = new org.w3._2000._09.xmldsig_.ObjectFactory(); 61 62 private static final int ARG_QUERYTYPE = 1; 63 private static final int ARG_QUERYVALUE = 2; 64 private static final int ARG_KEYUSAGE = 3; 65 private static final int ARG_RESPONDWITH = 4; 66 private static final int ARG_VALIDATEFLAG = 5; 67 private static final int ARG_ENCODING = 6; 68 private static final int ARG_OUTPUTPATH = 7; 69 70 71 72 73 74 private static final String VALIDATION_VALIDATE = "validate"; 75 private static final String VALIDATION_NOVALIDATION = "novalidation"; 76 77 78 79 84 public LocateCommand(String [] args) { 85 super(args); 86 } 87 88 94 public void execute() throws IllegalAdminCommandException, ErrorAdminCommandException { 95 96 try { 97 98 if(args.length < 7 || args.length > 8){ 99 usage(); 100 System.exit(-1); 101 } 102 103 boolean isCertQuery = args[ARG_QUERYTYPE].equalsIgnoreCase(QUERYTYPE_CERT); 104 105 String queryType = getQueryType(args[ARG_QUERYTYPE]); 106 107 byte[] queryCert = null; 108 String queryVal = null; 109 if(isCertQuery){ 110 queryCert = loadCert(args[ARG_QUERYVALUE]); 111 }else{ 112 queryVal = args[ARG_QUERYVALUE]; 113 } 114 115 boolean validate = getValidate(args[ARG_VALIDATEFLAG]); 116 boolean pEMEncoding = usePEMEncoding(args[ARG_ENCODING]); 117 String keyUsage = getKeyUsage(args[ARG_KEYUSAGE]); 118 Collection respondWith = getResponseWith(args[ARG_RESPONDWITH]); 119 String outputPath = ""; 120 if(args.length >= ARG_OUTPUTPATH +1){ 121 if(args[ARG_OUTPUTPATH] != null){ 122 outputPath = args[ARG_OUTPUTPATH] + "/"; 123 } 124 } 125 126 127 QueryKeyBindingType queryKeyBindingType = xKMSObjectFactory.createQueryKeyBindingType(); 128 if(isCertQuery){ 129 X509DataType x509DataType = sigFactory.createX509DataType(); 130 x509DataType.getX509IssuerSerialOrX509SKIOrX509SubjectName().add(sigFactory.createX509DataTypeX509Certificate(queryCert)); 131 KeyInfoType keyInfoType = sigFactory.createKeyInfoType(); 132 keyInfoType.getContent().add(sigFactory.createX509Data(x509DataType)); 133 queryKeyBindingType.setKeyInfo(keyInfoType); 134 }else{ 135 UseKeyWithType useKeyWithType = xKMSObjectFactory.createUseKeyWithType(); 136 useKeyWithType.setApplication(queryType); 137 useKeyWithType.setIdentifier(queryVal); 138 queryKeyBindingType.getUseKeyWith().add(useKeyWithType); 139 } 140 if(keyUsage != null){ 141 queryKeyBindingType.getKeyUsage().add(keyUsage); 142 } 143 144 String reqId = genId(); 145 146 List keyBindings = new ArrayList (); 147 if(validate){ 148 ValidateRequestType validationRequestType = xKMSObjectFactory.createValidateRequestType(); 149 validationRequestType.setId(reqId); 150 Iterator iter = respondWith.iterator(); 151 while(iter.hasNext()){ 152 validationRequestType.getRespondWith().add((String ) iter.next()); 153 } 154 validationRequestType.setQueryKeyBinding(queryKeyBindingType); 155 getPrintStream().println("Sending validation request with id " + reqId + " to XKMS Service"); 156 157 ValidateResultType validateResult = getXKMSInvoker().validate(validationRequestType, clientCert, privateKey); 158 keyBindings = validateResult.getKeyBinding(); 159 160 }else{ 161 LocateRequestType locateRequestType = xKMSObjectFactory.createLocateRequestType(); 162 locateRequestType.setId(reqId); 163 Iterator iter = respondWith.iterator(); 164 while(iter.hasNext()){ 165 locateRequestType.getRespondWith().add((String ) iter.next()); 166 } 167 locateRequestType.setQueryKeyBinding(queryKeyBindingType); 168 169 getPrintStream().println("Sending locate request with id " + reqId + " to XKMS Service"); 170 LocateResultType locateResult = getXKMSInvoker().locate(locateRequestType, clientCert, privateKey); 171 keyBindings = locateResult.getUnverifiedKeyBinding(); 172 } 173 174 if(keyBindings.size() > 0){ 175 getPrintStream().println("\n The query matched " + keyBindings.size() + " certificates :"); 176 Iterator iter = keyBindings.iterator(); 177 while(iter.hasNext()){ 178 UnverifiedKeyBindingType next = (UnverifiedKeyBindingType) iter.next(); 179 displayAndOutputCert(next, outputPath, pEMEncoding); 180 if(next instanceof KeyBindingType){ 181 displayStatus((KeyBindingType) next); 182 } 183 getPrintStream().println("\n\n\n"); 184 } 185 }else{ 186 getPrintStream().println("\n The query didn't match any certificates"); 187 } 188 189 } catch (Exception e) { 190 throw new ErrorAdminCommandException(e); 191 } 192 } 193 194 195 196 private void displayAndOutputCert(UnverifiedKeyBindingType next, String outputPath, boolean pEMEncoding) throws CertificateException , CRLException , IOException { 197 List keyInfos = next.getKeyInfo().getContent(); 198 199 Iterator iter = keyInfos.iterator(); 200 while(iter.hasNext()){ 201 Object obj = iter.next(); 202 if(obj instanceof JAXBElement){ 203 JAXBElement<X509DataType> jAXBX509Data = (JAXBElement<X509DataType>) obj; 204 Iterator iter2 = jAXBX509Data.getValue().getX509IssuerSerialOrX509SKIOrX509SubjectName().iterator(); 205 while(iter2.hasNext()){ 206 JAXBElement next2 = (JAXBElement) iter2.next(); 207 String filename = ""; 208 if(next2.getName().getLocalPart().equals("X509Certificate")){ 209 byte[] encoded = (byte[]) next2.getValue(); 210 X509Certificate nextCert = CertTools.getCertfromByteArray(encoded); 211 getPrintStream().println(" Found certificate with DN " + CertTools.getSubjectDN(nextCert) + " issued by " + CertTools.getIssuerDN(nextCert)); 212 213 if(pEMEncoding){ 214 filename = outputPath + CertTools.getPartFromDN(CertTools.getSubjectDN(nextCert), "CN") + ".pem"; 215 FileOutputStream fos = new FileOutputStream (filename); 216 ArrayList certs = new ArrayList (); 217 certs.add(nextCert); 218 byte[] pemData = CertTools.getPEMFromCerts(certs); 219 fos.write(pemData); 220 fos.close(); 221 }else{ 222 filename = outputPath + CertTools.getPartFromDN(CertTools.getSubjectDN(nextCert), "CN") + ".cer"; 223 FileOutputStream fos = new FileOutputStream (filename); 224 fos.write(nextCert.getEncoded()); 225 fos.close(); 226 } 227 } 228 if(next2.getName().getLocalPart().equals("X509CRL")){ 229 byte[] encoded = (byte[]) next2.getValue(); 230 X509CRL nextCRL = CertTools.getCRLfromByteArray(encoded); 231 232 getPrintStream().println(" Found CRLissued by " + CertTools.getIssuerDN(nextCRL)); 233 if(pEMEncoding){ 234 filename = outputPath + CertTools.getPartFromDN(CertTools.getIssuerDN(nextCRL), "CN") + "-crl.pem"; 235 FileOutputStream fos = new FileOutputStream (filename); 236 fos.write("-----BEGIN X509 CRL-----\n".getBytes()); 237 fos.write(Base64.encode(nextCRL.getEncoded(), true)); 238 fos.write("\n-----END X509 CRL-----\n".getBytes()); 239 fos.close(); 240 }else{ 241 filename = outputPath + CertTools.getPartFromDN(CertTools.getIssuerDN(nextCRL), "CN") + ".crl"; 242 FileOutputStream fos = new FileOutputStream (filename); 243 fos.write(nextCRL.getEncoded()); 244 fos.close(); 245 } 246 } 247 getPrintStream().println(" Written to : " + filename + "\n"); 248 } 249 250 displayUseKeyWith(next); 252 253 displayKeyUsage(next); 255 } 256 } 257 } 258 259 260 261 265 private boolean getValidate(String arg) { 266 if(arg.equalsIgnoreCase(VALIDATION_VALIDATE)){ 267 return true; 268 } 269 270 if(arg.equalsIgnoreCase(VALIDATION_NOVALIDATION)){ 271 return false; 272 } 273 274 getPrintStream().println("Illegal validation flag " + arg); 275 usage(); 276 System.exit(-1); 277 return false; 278 } 279 280 285 private String getQueryType(String arg) { 286 if(arg.equalsIgnoreCase(QUERYTYPE_CERT)){ 287 return null; 288 } 289 290 if(arg.equalsIgnoreCase(QUERYTYPE_IPSEC)){ 291 return XKMSConstants.USEKEYWITH_IPSEC; 292 } 293 294 if(arg.equalsIgnoreCase(QUERYTYPE_PKIX)){ 295 return XKMSConstants.USEKEYWITH_PKIX; 296 } 297 298 if(arg.equalsIgnoreCase(QUERYTYPE_SMIME)){ 299 return XKMSConstants.USEKEYWITH_SMIME; 300 } 301 302 if(arg.equalsIgnoreCase(QUERYTYPE_TLS)){ 303 return XKMSConstants.USEKEYWITH_TLS; 304 } 305 306 if(arg.equalsIgnoreCase(QUERYTYPE_TLSHTTP)){ 307 return XKMSConstants.USEKEYWITH_TLSHTTP; 308 } 309 310 if(arg.equalsIgnoreCase(QUERYTYPE_TLSSMTP)){ 311 return XKMSConstants.USEKEYWITH_TLSSMTP; 312 } 313 314 getPrintStream().println("Illegal query type " + arg); 315 usage(); 316 System.exit(-1); 317 return null; 318 } 319 320 325 private String getKeyUsage(String arg) { 326 if(arg.equalsIgnoreCase(KEYUSAGE_ALL)){ 327 return null; 328 } 329 if(arg.equalsIgnoreCase(KEYUSAGE_SIGNATURE)){ 330 return XKMSConstants.KEYUSAGE_SIGNATURE; 331 } 332 if(arg.equalsIgnoreCase(KEYUSAGE_ENCRYPTION)){ 333 return XKMSConstants.KEYUSAGE_ENCRYPTION; 334 } 335 if(arg.equalsIgnoreCase(KEYUSAGE_EXCHANGE)){ 336 return XKMSConstants.KEYUSAGE_EXCHANGE; 337 } 338 339 getPrintStream().println("Illegal key usage " + arg); 340 usage(); 341 System.exit(-1); 342 return null; 343 } 344 345 346 350 private boolean usePEMEncoding(String arg){ 351 if(arg.equalsIgnoreCase(ENCODING_PEM)){ 352 return true; 353 } 354 355 if(arg.equalsIgnoreCase(ENCODING_DER)){ 356 return false; 357 } 358 359 getPrintStream().println("Illegal encoding (should be pem or der) : " + arg); 360 usage(); 361 System.exit(-1); 362 return false; 363 } 364 365 366 protected void usage() { 367 getPrintStream().println("Command used to locate and optionaly validate a certificate"); 368 getPrintStream().println("Usage : locate <querytype> <queryvalue> <keyusage> <respondwith> <"+VALIDATION_VALIDATE+"|"+VALIDATION_NOVALIDATION+"> <der|pem> <outputpath (optional)> \n\n"); 369 getPrintStream().println("Querytypes are:"); 370 getPrintStream().println(" CERT : Use a existing certificate from file, queryvalue should be path to certificate.\n" 371 +" SMIME : Lookup by the RFC882 Name of certificate\n" 372 +" TLS : Lookup by the URI in the certificate\n" 373 +" TLSHTTP : Lookup by the CN in the certificate\n" 374 +" TSLSMTP : Lookup by the DNS Name of the certificate\n" 375 +" IPSEC : Lookup by the IP address of the certificate\n" 376 +" PKIX : Lookup by the SubjectDN of the certificate\n"); 377 getPrintStream().println("Available Keyusages are:"); 378 getPrintStream().println(" ALL : Any key usage will do\n" 379 +" SIGNATURE : Return certificate that can be used for signing\n" 380 +" ENCRYPTION : Return certificate that can be used for encryption\n" 381 +" EXCHANGE : Return certificate that can be used for exchange\n"); 382 getPrintStream().println("Available Respond With values are:"); 383 getPrintStream().println(" X509CERT : Respond with the certificate.\n" 384 +" X509CHAIN : Respond with the entire certificate chain\n" 385 +" X509CHAINANDCRL : Respond with the chain and CRL\n"); 386 getPrintStream().println("Use 'validate' if you want the status of the certificate, othervise use 'novalidation'.\n"); 387 getPrintStream().println("Use 'pem' or 'der' depending on prefered encoding.\n"); 388 getPrintStream().println("Outputpath specifies to which directory to write certificate and CRLs, current directory is used if omitted\n\n"); 389 getPrintStream().println("Example: locate TLSHTTP \"John Doe\" SIGNATURE X509CERT "+VALIDATION_VALIDATE+" pem"); 390 getPrintStream().println("Returns the signing certificate belonging to CN=John Doe and specifies if it is valid to the current directory"); 391 392 393 } 394 395 396 } 397 | Popular Tags |