Loading projects/cadcCDP/build.xml +14 −4 Original line number Diff line number Diff line Loading @@ -90,20 +90,30 @@ <!-- JAR files to be included in classpath and war file --> <property name="lib.cadcUtil" value="${lib}/cadcUtil.jar" /> <property name="lib.cadcRegistryClient" value="${lib}/cadcRegistryClient.jar" /> <property name="ext.log4j" value="${ext.lib}/log4j.jar" /> <property name="ext.bouncy" value="${ext.lib}/bcprov.jar" /> <!-- end of project properties --> <!-- JAR files to be included in classpath for compilation --> <property name="jars" value="${lib.cadcUtil}:${ext.log4j}" /> <property name="jars" value="${lib.cadcUtil}:${lib.cadcRegistryClient}:${ext.log4j}:${ext.bouncy}" /> <property name="manifest.jars" value="${lib.cadcUtil} ${lib.cadcRegistryClient} ${ext.log4j} ${ext.bouncy}" /> <target name="build" depends="compile"> <target name="build" depends="compile,manifest"> <jar jarfile="${build}/lib/${project}.jar" basedir="${build}/class" update="no"> update="no" manifest="${build}/tmp/${project}.mf"> </jar> </target> <target name="manifest"> <manifest file="${build}/tmp/${project}.mf" mode="replace"> <attribute name="Main-Class" value="ca.nrc.cadc.cred.client.Main"/> <attribute name="Class-Path" value="${manifest.jars}" /> </manifest> </target> <target name="test"> <echo message="WARNING: no tests implemented" /> </target> Loading projects/cadcCDP/src/ca/nrc/cadc/cred/client/CertUtil.java 0 → 100644 +230 −0 Original line number Diff line number Diff line package ca.nrc.cadc.cred.client; import java.io.IOException; import java.io.Writer; import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.PrivateKey; import java.security.Security; import java.security.SignatureException; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateNotYetValidException; import java.security.cert.CertificateParsingException; import java.security.cert.X509Certificate; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.Random; import java.util.TimeZone; import javax.security.auth.x500.X500Principal; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.x509.BasicConstraints; import org.bouncycastle.asn1.x509.KeyUsage; import org.bouncycastle.asn1.x509.X509Extensions; import org.bouncycastle.jce.PKCS10CertificationRequest; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.openssl.PEMWriter; import org.bouncycastle.x509.X509V3CertificateGenerator; import org.bouncycastle.x509.extension.AuthorityKeyIdentifierStructure; import org.bouncycastle.x509.extension.SubjectKeyIdentifierStructure; import ca.nrc.cadc.auth.X509CertificateChain; /** * Utilities for certificate operations */ public class CertUtil { /** * Method that generates an X509 proxy certificate * * @param csr * CSR for the certificate * @param lifetime * lifetime of the certificate in SECONDS * @param chain * certificate used to sign the proxy certificate * @return generated proxy certificate * @throws NoSuchAlgorithmException * @throws NoSuchProviderException * @throws InvalidKeyException * @throws CertificateParsingException * @throws CertificateEncodingException * @throws SignatureException * @throws CertificateNotYetValidException * @throws CertificateExpiredException */ public static X509Certificate generateCertificate( PKCS10CertificationRequest csr, int lifetime, X509CertificateChain chain) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, CertificateParsingException, CertificateEncodingException, SignatureException, CertificateExpiredException, CertificateNotYetValidException { X509Certificate issuerCert = chain.getChain()[0]; PrivateKey issuerKey = chain.getPrivateKey(); Security.addProvider(new BouncyCastleProvider()); X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); certGen.setSerialNumber(BigInteger.valueOf(System .currentTimeMillis())); certGen.setIssuerDN(issuerCert.getSubjectX500Principal()); // generate the proxy DN as the issuerDN + CN=random number Random rand = new Random(); String issuerDN = issuerCert.getSubjectX500Principal().getName( X500Principal.RFC2253); String delegDN = String.valueOf(Math.abs(rand.nextInt())); String proxyDn = "CN=" + delegDN + "," + issuerDN; certGen.setSubjectDN(new X500Principal(proxyDn)); // set validity GregorianCalendar date = new GregorianCalendar(TimeZone .getTimeZone("GMT")); // Start date. Allow for a sixty five minute clock skew here. date.add(Calendar.MINUTE, -65); Date beforeDate = date.getTime(); for (X509Certificate currentCert : chain.getChain()) { if (beforeDate.before(currentCert.getNotBefore())) { beforeDate = currentCert.getNotBefore(); } } certGen.setNotBefore(beforeDate); // End date. // If hours = 0, then cert lifetime is set to that of user cert if (lifetime <= 0) { // set the validity of certificates as the minimum // of the certificates in the chain Date afterDate = issuerCert.getNotAfter(); for (X509Certificate currentCert : chain.getChain()) { if (afterDate.after(currentCert.getNotAfter())) { afterDate = currentCert.getNotAfter(); } } certGen.setNotAfter(afterDate); } else { // check the validity of the signing certificate date.add(Calendar.MINUTE, 5); date.add(Calendar.SECOND, lifetime); for (X509Certificate currentCert : chain.getChain()) { currentCert.checkValidity(date.getTime()); } certGen.setNotAfter(date.getTime()); } certGen.setPublicKey(csr.getPublicKey()); certGen.setSignatureAlgorithm(issuerCert.getSigAlgName()); // extensions // add ProxyCertInfo extension to the new cert certGen.addExtension(X509Extensions.KeyUsage, true, new KeyUsage( KeyUsage.digitalSignature | KeyUsage.keyEncipherment)); certGen.addExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(issuerCert)); certGen.addExtension(X509Extensions.SubjectKeyIdentifier, false, new SubjectKeyIdentifierStructure(csr.getPublicKey("BC"))); certGen.addExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(false)); // add the Proxy Certificate Information // I expect this code to be removed once support to proxy // certificates is provided in Bouncy Castle. // create a proxy policy // types of proxy certificate policies - see RFC3820 // impersonates the user final DERObjectIdentifier IMPERSONATION = new DERObjectIdentifier( "1.3.6.1.5.5.7.21.1"); // independent // final DERObjectIdentifier INDEPENDENT = new // DERObjectIdentifier( // "1.3.6.1.5.5.7.21.2"); // defined by a policy language // final DERObjectIdentifier LIMITED = new DERObjectIdentifier( // "1.3.6.1.4.1.3536.1.1.1.9"); ASN1EncodableVector policy = new ASN1EncodableVector(); policy.add(IMPERSONATION); // pathLengthConstr (RFC3820) // The pCPathLenConstraint field, if present, specifies the // maximum // depth of the path of Proxy Certificates that can be signed by // this // Proxy Certificate. A pCPathLenConstraint of 0 means that this // certificate MUST NOT be used to sign a Proxy Certificate. If // the // pCPathLenConstraint field is not present then the maximum proxy // path // length is unlimited. End entity certificates have unlimited // maximum // proxy path lengths. // DERInteger pathLengthConstr = new DERInteger(100); // create the proxy certificate information ASN1EncodableVector vec = new ASN1EncodableVector(); // policy.add(pathLengthConstr); vec.add(new DERSequence(policy)); // OID final DERObjectIdentifier OID = new DERObjectIdentifier( "1.3.6.1.5.5.7.1.14"); certGen.addExtension(OID, true, new DERSequence(vec)); return certGen.generate(issuerKey, "BC"); } /** * @param chain certificate * @param writer writer use to write the generated PEM certificate * @throws IOException */ public static void writePEMCertificateAndKey( X509CertificateChain chain, Writer writer) throws IOException { if (chain == null) throw new IllegalArgumentException("Null certificate chain"); if (writer == null) throw new IllegalArgumentException("Null writer"); PEMWriter pemWriter = new PEMWriter(writer); // write the first certificate first pemWriter.writeObject(chain.getChain()[0]); // then the key pemWriter.writeObject(chain.getPrivateKey()); // and finally the rest of the certificates in the chain for (int i = 1; i < chain.getChain().length; i++) { pemWriter.writeObject(chain.getChain()[i]); } pemWriter.flush(); } } projects/cadcCDP/src/ca/nrc/cadc/cred/client/CredPublicClient.java 0 → 100644 +753 −0 File added.Preview size limit exceeded, changes collapsed. Show changes projects/cadcCDP/src/ca/nrc/cadc/cred/client/Main.java 0 → 100644 +311 −0 Original line number Diff line number Diff line package ca.nrc.cadc.cred.client; import java.net.URI; import java.net.URL; import java.security.PrivilegedAction; import java.security.cert.X509Certificate; import javax.security.auth.Subject; import org.apache.log4j.Level; import org.apache.log4j.Logger; import ca.nrc.cadc.auth.CertCmdArgUtil; import ca.nrc.cadc.reg.client.RegistryClient; import ca.nrc.cadc.util.ArgumentMap; import ca.nrc.cadc.util.Log4jInit; public class Main implements PrivilegedAction<Boolean> { private static Logger logger = Logger.getLogger(Main.class); public static final String ARG_HELP = "help"; public static final String ARG_VERBOSE = "verbose"; public static final String ARG_DEBUG = "debug"; public static final String ARG_H = "h"; public static final String ARG_V = "v"; public static final String ARG_D = "d"; public static final String ARG_VIEW_CMD = "view"; public static final String ARG_DELEGATE_CMD = "delegate"; public static final String ARG_VALID_DAYS = "daysvalid"; // authenticated subject private static Subject subject; private String baseURL; private RegistryClient registryClient = new RegistryClient(); private CredPublicClient client; private int daysValid; private static final int INIT_STATUS = 1; // exit code for // initialisation failure private static final int NET_STATUS = 2; // exit code for // client-server failures // Operations on Cred client public enum Operation { DELEGATE, VIEW }; private Operation operation; // current operation on Cred client public static final String SERVICE_ID = "ivo://cadc.nrc.ca/cred"; /** * Main class for accessing CDP * * @param args */ public static void main(String[] args) { ArgumentMap argMap = new ArgumentMap(args); if (argMap.isSet(ARG_HELP) || argMap.isSet(ARG_H)) { usage(); System.exit(0); } // Set debug mode if (argMap.isSet(ARG_DEBUG) || argMap.isSet(ARG_D)) { Log4jInit.setLevel("ca.nrc.cadc.cred.client", Level.DEBUG); } else if (argMap.isSet(ARG_VERBOSE) || argMap.isSet(ARG_V)) { Log4jInit.setLevel("ca.nrc.cadc.cred.client", Level.INFO); } else Log4jInit.setLevel("ca", Level.WARN); Main command = new Main(); try { command.validateCommand(argMap); } catch (IllegalArgumentException ex) { msg("illegal argument(s): " + ex.getMessage()); msg(""); usage(); System.exit(INIT_STATUS); } try { command.init(argMap); Subject.doAs(subject, command); } catch (Throwable t) { logger.error("unexpected failure", t); System.exit(NET_STATUS); } System.exit(0); } /** * Runs the task in Subject's context. Needed by the PrivilegedAction * interface * * @return true if successfull, false otherwise */ public Boolean run() { logger.info("run - START"); if (this.operation.equals(Operation.DELEGATE)) { doDelegate(); } if (this.operation.equals(Operation.VIEW)) { doView(); } logger.info("run - DONE"); return new Boolean(true); } /** * Executes delegate command */ private void doDelegate() { try { client.delegate(null, daysValid); msg("Certificate updated"); } catch (Exception e) { e.printStackTrace(); logger.error("failed to delegate"); logger.error("reason: " + e.getMessage()); System.exit(NET_STATUS); } } /** * Executes view command */ private void doView() { try { X509Certificate[] certs = client.getCertificate(null); certs[0].checkValidity(); msg("Found valid certificate"); msg("Certificate Subject DN: " + certs[0].getSubjectX500Principal().getName()); msg("Certificate Expiry Date: " + certs[0].getNotAfter()); msg("Certificate Details: " + certs[0].toString()); } catch (Exception e) { logger.error("failed to delegate"); logger.error("reason: " + e.getMessage()); System.exit(NET_STATUS); } } /** * Validates the command line operations * * @param argMap */ private void validateCommand(ArgumentMap argMap) throws IllegalArgumentException { int numOp = 0; if (argMap.isSet(ARG_VIEW_CMD)) { operation = Operation.VIEW; numOp++; } if (argMap.isSet(ARG_DELEGATE_CMD)) { operation = Operation.DELEGATE; numOp++; String validDaysStr = argMap.getValue(ARG_VALID_DAYS); if (validDaysStr != null) { boolean valid = true; try { daysValid = Integer.parseInt(validDaysStr); if (daysValid < 1) { valid = false; } } catch (NumberFormatException ex) { valid = false; } if (valid == false) { logger.error(ARG_VALID_DAYS + " must be a positive integer value"); usage(); System.exit(INIT_STATUS); } } else { logger.error(ARG_VALID_DAYS + " argument missing"); usage(); System.exit(INIT_STATUS); } } if (numOp != 1) { logger.error("Must specify one operation"); usage(); System.exit(INIT_STATUS); } return; } /** * Initializes of the base URL for the service * * @param argMap */ private void init(ArgumentMap argMap) { try { subject = CertCmdArgUtil.initSubject(argMap); } catch (Exception ex) { logger.error("failed to initialise SSL from certificates: " + ex.getMessage()); if (logger.getLevel() == Level.DEBUG) { ex.printStackTrace(); } if (ex instanceof IllegalArgumentException) { usage(); } System.exit(INIT_STATUS); } try { URL baseURL = registryClient.getServiceURL( new URI(SERVICE_ID), "https"); if (baseURL == null) { logger.error("failed to find service URL for " + SERVICE_ID); System.exit(INIT_STATUS); } this.baseURL = baseURL.toString(); this.client = new CredPublicClient(new URL(this.baseURL)); } catch (Exception e) { logger.error("failed to find service URL for " + SERVICE_ID); logger.error("reason: " + e.getMessage()); System.exit(INIT_STATUS); } logger.info("server uri: " + SERVICE_ID); logger.info("base url: " + this.baseURL); } /** * Formats the usage message. */ public static void usage() { String[] um = { "Usage: java -jar cadcCDP.jar --view|(--delegate --daysvalid=<days>) [-v|--verbose|-d|--debug]", CertCmdArgUtil.getCertArgUsage(), " ", "Help: ", "java -jar cadcCDP.jar <-h | --help> ", " " }; for (String line : um) msg(line); } // encapsulate all messages to console here private static void msg(String s) { System.out.println(s); } } Loading
projects/cadcCDP/build.xml +14 −4 Original line number Diff line number Diff line Loading @@ -90,20 +90,30 @@ <!-- JAR files to be included in classpath and war file --> <property name="lib.cadcUtil" value="${lib}/cadcUtil.jar" /> <property name="lib.cadcRegistryClient" value="${lib}/cadcRegistryClient.jar" /> <property name="ext.log4j" value="${ext.lib}/log4j.jar" /> <property name="ext.bouncy" value="${ext.lib}/bcprov.jar" /> <!-- end of project properties --> <!-- JAR files to be included in classpath for compilation --> <property name="jars" value="${lib.cadcUtil}:${ext.log4j}" /> <property name="jars" value="${lib.cadcUtil}:${lib.cadcRegistryClient}:${ext.log4j}:${ext.bouncy}" /> <property name="manifest.jars" value="${lib.cadcUtil} ${lib.cadcRegistryClient} ${ext.log4j} ${ext.bouncy}" /> <target name="build" depends="compile"> <target name="build" depends="compile,manifest"> <jar jarfile="${build}/lib/${project}.jar" basedir="${build}/class" update="no"> update="no" manifest="${build}/tmp/${project}.mf"> </jar> </target> <target name="manifest"> <manifest file="${build}/tmp/${project}.mf" mode="replace"> <attribute name="Main-Class" value="ca.nrc.cadc.cred.client.Main"/> <attribute name="Class-Path" value="${manifest.jars}" /> </manifest> </target> <target name="test"> <echo message="WARNING: no tests implemented" /> </target> Loading
projects/cadcCDP/src/ca/nrc/cadc/cred/client/CertUtil.java 0 → 100644 +230 −0 Original line number Diff line number Diff line package ca.nrc.cadc.cred.client; import java.io.IOException; import java.io.Writer; import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.PrivateKey; import java.security.Security; import java.security.SignatureException; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateNotYetValidException; import java.security.cert.CertificateParsingException; import java.security.cert.X509Certificate; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.Random; import java.util.TimeZone; import javax.security.auth.x500.X500Principal; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.x509.BasicConstraints; import org.bouncycastle.asn1.x509.KeyUsage; import org.bouncycastle.asn1.x509.X509Extensions; import org.bouncycastle.jce.PKCS10CertificationRequest; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.openssl.PEMWriter; import org.bouncycastle.x509.X509V3CertificateGenerator; import org.bouncycastle.x509.extension.AuthorityKeyIdentifierStructure; import org.bouncycastle.x509.extension.SubjectKeyIdentifierStructure; import ca.nrc.cadc.auth.X509CertificateChain; /** * Utilities for certificate operations */ public class CertUtil { /** * Method that generates an X509 proxy certificate * * @param csr * CSR for the certificate * @param lifetime * lifetime of the certificate in SECONDS * @param chain * certificate used to sign the proxy certificate * @return generated proxy certificate * @throws NoSuchAlgorithmException * @throws NoSuchProviderException * @throws InvalidKeyException * @throws CertificateParsingException * @throws CertificateEncodingException * @throws SignatureException * @throws CertificateNotYetValidException * @throws CertificateExpiredException */ public static X509Certificate generateCertificate( PKCS10CertificationRequest csr, int lifetime, X509CertificateChain chain) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, CertificateParsingException, CertificateEncodingException, SignatureException, CertificateExpiredException, CertificateNotYetValidException { X509Certificate issuerCert = chain.getChain()[0]; PrivateKey issuerKey = chain.getPrivateKey(); Security.addProvider(new BouncyCastleProvider()); X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); certGen.setSerialNumber(BigInteger.valueOf(System .currentTimeMillis())); certGen.setIssuerDN(issuerCert.getSubjectX500Principal()); // generate the proxy DN as the issuerDN + CN=random number Random rand = new Random(); String issuerDN = issuerCert.getSubjectX500Principal().getName( X500Principal.RFC2253); String delegDN = String.valueOf(Math.abs(rand.nextInt())); String proxyDn = "CN=" + delegDN + "," + issuerDN; certGen.setSubjectDN(new X500Principal(proxyDn)); // set validity GregorianCalendar date = new GregorianCalendar(TimeZone .getTimeZone("GMT")); // Start date. Allow for a sixty five minute clock skew here. date.add(Calendar.MINUTE, -65); Date beforeDate = date.getTime(); for (X509Certificate currentCert : chain.getChain()) { if (beforeDate.before(currentCert.getNotBefore())) { beforeDate = currentCert.getNotBefore(); } } certGen.setNotBefore(beforeDate); // End date. // If hours = 0, then cert lifetime is set to that of user cert if (lifetime <= 0) { // set the validity of certificates as the minimum // of the certificates in the chain Date afterDate = issuerCert.getNotAfter(); for (X509Certificate currentCert : chain.getChain()) { if (afterDate.after(currentCert.getNotAfter())) { afterDate = currentCert.getNotAfter(); } } certGen.setNotAfter(afterDate); } else { // check the validity of the signing certificate date.add(Calendar.MINUTE, 5); date.add(Calendar.SECOND, lifetime); for (X509Certificate currentCert : chain.getChain()) { currentCert.checkValidity(date.getTime()); } certGen.setNotAfter(date.getTime()); } certGen.setPublicKey(csr.getPublicKey()); certGen.setSignatureAlgorithm(issuerCert.getSigAlgName()); // extensions // add ProxyCertInfo extension to the new cert certGen.addExtension(X509Extensions.KeyUsage, true, new KeyUsage( KeyUsage.digitalSignature | KeyUsage.keyEncipherment)); certGen.addExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(issuerCert)); certGen.addExtension(X509Extensions.SubjectKeyIdentifier, false, new SubjectKeyIdentifierStructure(csr.getPublicKey("BC"))); certGen.addExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(false)); // add the Proxy Certificate Information // I expect this code to be removed once support to proxy // certificates is provided in Bouncy Castle. // create a proxy policy // types of proxy certificate policies - see RFC3820 // impersonates the user final DERObjectIdentifier IMPERSONATION = new DERObjectIdentifier( "1.3.6.1.5.5.7.21.1"); // independent // final DERObjectIdentifier INDEPENDENT = new // DERObjectIdentifier( // "1.3.6.1.5.5.7.21.2"); // defined by a policy language // final DERObjectIdentifier LIMITED = new DERObjectIdentifier( // "1.3.6.1.4.1.3536.1.1.1.9"); ASN1EncodableVector policy = new ASN1EncodableVector(); policy.add(IMPERSONATION); // pathLengthConstr (RFC3820) // The pCPathLenConstraint field, if present, specifies the // maximum // depth of the path of Proxy Certificates that can be signed by // this // Proxy Certificate. A pCPathLenConstraint of 0 means that this // certificate MUST NOT be used to sign a Proxy Certificate. If // the // pCPathLenConstraint field is not present then the maximum proxy // path // length is unlimited. End entity certificates have unlimited // maximum // proxy path lengths. // DERInteger pathLengthConstr = new DERInteger(100); // create the proxy certificate information ASN1EncodableVector vec = new ASN1EncodableVector(); // policy.add(pathLengthConstr); vec.add(new DERSequence(policy)); // OID final DERObjectIdentifier OID = new DERObjectIdentifier( "1.3.6.1.5.5.7.1.14"); certGen.addExtension(OID, true, new DERSequence(vec)); return certGen.generate(issuerKey, "BC"); } /** * @param chain certificate * @param writer writer use to write the generated PEM certificate * @throws IOException */ public static void writePEMCertificateAndKey( X509CertificateChain chain, Writer writer) throws IOException { if (chain == null) throw new IllegalArgumentException("Null certificate chain"); if (writer == null) throw new IllegalArgumentException("Null writer"); PEMWriter pemWriter = new PEMWriter(writer); // write the first certificate first pemWriter.writeObject(chain.getChain()[0]); // then the key pemWriter.writeObject(chain.getPrivateKey()); // and finally the rest of the certificates in the chain for (int i = 1; i < chain.getChain().length; i++) { pemWriter.writeObject(chain.getChain()[i]); } pemWriter.flush(); } }
projects/cadcCDP/src/ca/nrc/cadc/cred/client/CredPublicClient.java 0 → 100644 +753 −0 File added.Preview size limit exceeded, changes collapsed. Show changes
projects/cadcCDP/src/ca/nrc/cadc/cred/client/Main.java 0 → 100644 +311 −0 Original line number Diff line number Diff line package ca.nrc.cadc.cred.client; import java.net.URI; import java.net.URL; import java.security.PrivilegedAction; import java.security.cert.X509Certificate; import javax.security.auth.Subject; import org.apache.log4j.Level; import org.apache.log4j.Logger; import ca.nrc.cadc.auth.CertCmdArgUtil; import ca.nrc.cadc.reg.client.RegistryClient; import ca.nrc.cadc.util.ArgumentMap; import ca.nrc.cadc.util.Log4jInit; public class Main implements PrivilegedAction<Boolean> { private static Logger logger = Logger.getLogger(Main.class); public static final String ARG_HELP = "help"; public static final String ARG_VERBOSE = "verbose"; public static final String ARG_DEBUG = "debug"; public static final String ARG_H = "h"; public static final String ARG_V = "v"; public static final String ARG_D = "d"; public static final String ARG_VIEW_CMD = "view"; public static final String ARG_DELEGATE_CMD = "delegate"; public static final String ARG_VALID_DAYS = "daysvalid"; // authenticated subject private static Subject subject; private String baseURL; private RegistryClient registryClient = new RegistryClient(); private CredPublicClient client; private int daysValid; private static final int INIT_STATUS = 1; // exit code for // initialisation failure private static final int NET_STATUS = 2; // exit code for // client-server failures // Operations on Cred client public enum Operation { DELEGATE, VIEW }; private Operation operation; // current operation on Cred client public static final String SERVICE_ID = "ivo://cadc.nrc.ca/cred"; /** * Main class for accessing CDP * * @param args */ public static void main(String[] args) { ArgumentMap argMap = new ArgumentMap(args); if (argMap.isSet(ARG_HELP) || argMap.isSet(ARG_H)) { usage(); System.exit(0); } // Set debug mode if (argMap.isSet(ARG_DEBUG) || argMap.isSet(ARG_D)) { Log4jInit.setLevel("ca.nrc.cadc.cred.client", Level.DEBUG); } else if (argMap.isSet(ARG_VERBOSE) || argMap.isSet(ARG_V)) { Log4jInit.setLevel("ca.nrc.cadc.cred.client", Level.INFO); } else Log4jInit.setLevel("ca", Level.WARN); Main command = new Main(); try { command.validateCommand(argMap); } catch (IllegalArgumentException ex) { msg("illegal argument(s): " + ex.getMessage()); msg(""); usage(); System.exit(INIT_STATUS); } try { command.init(argMap); Subject.doAs(subject, command); } catch (Throwable t) { logger.error("unexpected failure", t); System.exit(NET_STATUS); } System.exit(0); } /** * Runs the task in Subject's context. Needed by the PrivilegedAction * interface * * @return true if successfull, false otherwise */ public Boolean run() { logger.info("run - START"); if (this.operation.equals(Operation.DELEGATE)) { doDelegate(); } if (this.operation.equals(Operation.VIEW)) { doView(); } logger.info("run - DONE"); return new Boolean(true); } /** * Executes delegate command */ private void doDelegate() { try { client.delegate(null, daysValid); msg("Certificate updated"); } catch (Exception e) { e.printStackTrace(); logger.error("failed to delegate"); logger.error("reason: " + e.getMessage()); System.exit(NET_STATUS); } } /** * Executes view command */ private void doView() { try { X509Certificate[] certs = client.getCertificate(null); certs[0].checkValidity(); msg("Found valid certificate"); msg("Certificate Subject DN: " + certs[0].getSubjectX500Principal().getName()); msg("Certificate Expiry Date: " + certs[0].getNotAfter()); msg("Certificate Details: " + certs[0].toString()); } catch (Exception e) { logger.error("failed to delegate"); logger.error("reason: " + e.getMessage()); System.exit(NET_STATUS); } } /** * Validates the command line operations * * @param argMap */ private void validateCommand(ArgumentMap argMap) throws IllegalArgumentException { int numOp = 0; if (argMap.isSet(ARG_VIEW_CMD)) { operation = Operation.VIEW; numOp++; } if (argMap.isSet(ARG_DELEGATE_CMD)) { operation = Operation.DELEGATE; numOp++; String validDaysStr = argMap.getValue(ARG_VALID_DAYS); if (validDaysStr != null) { boolean valid = true; try { daysValid = Integer.parseInt(validDaysStr); if (daysValid < 1) { valid = false; } } catch (NumberFormatException ex) { valid = false; } if (valid == false) { logger.error(ARG_VALID_DAYS + " must be a positive integer value"); usage(); System.exit(INIT_STATUS); } } else { logger.error(ARG_VALID_DAYS + " argument missing"); usage(); System.exit(INIT_STATUS); } } if (numOp != 1) { logger.error("Must specify one operation"); usage(); System.exit(INIT_STATUS); } return; } /** * Initializes of the base URL for the service * * @param argMap */ private void init(ArgumentMap argMap) { try { subject = CertCmdArgUtil.initSubject(argMap); } catch (Exception ex) { logger.error("failed to initialise SSL from certificates: " + ex.getMessage()); if (logger.getLevel() == Level.DEBUG) { ex.printStackTrace(); } if (ex instanceof IllegalArgumentException) { usage(); } System.exit(INIT_STATUS); } try { URL baseURL = registryClient.getServiceURL( new URI(SERVICE_ID), "https"); if (baseURL == null) { logger.error("failed to find service URL for " + SERVICE_ID); System.exit(INIT_STATUS); } this.baseURL = baseURL.toString(); this.client = new CredPublicClient(new URL(this.baseURL)); } catch (Exception e) { logger.error("failed to find service URL for " + SERVICE_ID); logger.error("reason: " + e.getMessage()); System.exit(INIT_STATUS); } logger.info("server uri: " + SERVICE_ID); logger.info("base url: " + this.baseURL); } /** * Formats the usage message. */ public static void usage() { String[] um = { "Usage: java -jar cadcCDP.jar --view|(--delegate --daysvalid=<days>) [-v|--verbose|-d|--debug]", CertCmdArgUtil.getCertArgUsage(), " ", "Help: ", "java -jar cadcCDP.jar <-h | --help> ", " " }; for (String line : um) msg(line); } // encapsulate all messages to console here private static void msg(String s) { System.out.println(s); } }