summaryrefslogtreecommitdiffstats
path: root/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/JscepCA.java
diff options
context:
space:
mode:
Diffstat (limited to 'auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/JscepCA.java')
-rw-r--r--auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/JscepCA.java268
1 files changed, 268 insertions, 0 deletions
diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/JscepCA.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/JscepCA.java
new file mode 100644
index 00000000..ae4e21aa
--- /dev/null
+++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/JscepCA.java
@@ -0,0 +1,268 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+package org.onap.aaf.auth.cm.ca;
+
+import java.io.FileReader;
+import java.io.IOException;
+import java.net.Authenticator;
+import java.net.MalformedURLException;
+import java.net.PasswordAuthentication;
+import java.net.URL;
+import java.security.cert.CertStoreException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.pkcs.PKCS10CertificationRequest;
+import org.jscep.client.Client;
+import org.jscep.client.ClientException;
+import org.jscep.client.EnrollmentResponse;
+import org.jscep.client.verification.CertificateVerifier;
+import org.jscep.transaction.TransactionException;
+import org.onap.aaf.auth.cm.cert.BCFactory;
+import org.onap.aaf.auth.cm.cert.CSRMeta;
+import org.onap.aaf.cadi.Access;
+import org.onap.aaf.cadi.LocatorException;
+import org.onap.aaf.cadi.Access.Level;
+import org.onap.aaf.cadi.Locator.Item;
+import org.onap.aaf.cadi.cm.CertException;
+import org.onap.aaf.cadi.locator.HotPeerLocator;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.TimeTaken;
+import org.onap.aaf.misc.env.Trans;
+import org.onap.aaf.misc.env.util.Split;
+
+public class JscepCA extends CA {
+ static final String CA_PREFIX = "http://";
+ static final String CA_POSTFIX="/certsrv/mscep_admin/mscep.dll";
+
+ private final static String MS_PROFILE="1";
+ private final static int MAX_RETRY=3;
+ public static final long INVALIDATE_TIME = 1000*60*10; // 10 mins
+
+ // package on purpose
+ private Map<String,X509ChainWithIssuer> mxcwi_s;
+ private Map<Client,X509ChainWithIssuer> mxcwi_c;
+
+
+ private JscepClientLocator clients;
+
+ public JscepCA(final Access access, final String name, final String env, String [][] params) throws IOException, CertException, LocatorException {
+ super(access, name, env);
+ mxcwi_s = new ConcurrentHashMap<String,X509ChainWithIssuer>();
+ mxcwi_c = new ConcurrentHashMap<Client,X509ChainWithIssuer>();
+
+ if(params.length<2) {
+ throw new CertException("No Trust Chain parameters are included");
+ }
+ if(params[0].length<2) {
+ throw new CertException("User/Password required for JSCEP");
+ }
+ final String id = params[0][0];
+ final String pw = params[0][1];
+
+ // Set this for NTLM password Microsoft
+ Authenticator.setDefault(new Authenticator() {
+ public PasswordAuthentication getPasswordAuthentication () {
+ try {
+ return new PasswordAuthentication (id,access.decrypt(pw,true).toCharArray());
+ } catch (IOException e) {
+ access.log(e);
+ }
+ return null;
+ }
+ });
+
+ StringBuilder urlstr = new StringBuilder();
+
+ for(int i=1;i<params.length;++i) { // skip first section, which is user/pass
+ // Work
+ if(i>1) {
+ urlstr.append(','); // delimiter
+ }
+ urlstr.append(params[i][0]);
+
+ String dir = access.getProperty(CM_PUBLIC_DIR, "");
+ if(!"".equals(dir) && !dir.endsWith("/")) {
+ dir = dir + '/';
+ }
+ String path;
+ List<FileReader> frs = new ArrayList<FileReader>(params.length-1);
+ try {
+ for(int j=1; j<params[i].length; ++j) { // first 3 taken up, see above
+ path = !params[i][j].contains("/")?dir+params[i][j]:params[i][j];
+ access.printf(Level.INIT, "Loading a TrustChain Member for %s from %s",name, path);
+ frs.add(new FileReader(path));
+ }
+ X509ChainWithIssuer xcwi = new X509ChainWithIssuer(frs);
+ addCaIssuerDN(xcwi.getIssuerDN());
+ mxcwi_s.put(params[i][0],xcwi);
+ } finally {
+ for(FileReader fr : frs) {
+ if(fr!=null) {
+ fr.close();
+ }
+ }
+ }
+ }
+ clients = new JscepClientLocator(access,urlstr.toString());
+ }
+
+ // package on purpose
+
+ @Override
+ public X509ChainWithIssuer sign(Trans trans, CSRMeta csrmeta) throws IOException, CertException {
+ TimeTaken tt = trans.start("Generating CSR and Keys for New Certificate", Env.SUB);
+ PKCS10CertificationRequest csr;
+ try {
+ csr = csrmeta.generateCSR(trans);
+ if(trans.info().isLoggable()) {
+ trans.info().log(BCFactory.toString(csr));
+ }
+ if(trans.info().isLoggable()) {
+ trans.info().log(csr);
+ }
+ } finally {
+ tt.done();
+ }
+
+ tt = trans.start("Enroll CSR", Env.SUB);
+ Client client = null;
+ Item item = null;
+ for(int i=0; i<MAX_RETRY;++i) {
+ try {
+ item = clients.best();
+ client = clients.get(item);
+
+ EnrollmentResponse er = client.enrol(
+ csrmeta.initialConversationCert(trans),
+ csrmeta.keypair(trans).getPrivate(),
+ csr,
+ MS_PROFILE /* profile... MS can't deal with blanks*/);
+
+ while(true) {
+ if(er.isSuccess()) {
+ trans.checkpoint("Cert from " + clients.info(item));
+ X509Certificate x509 = null;
+ for( Certificate cert : er.getCertStore().getCertificates(null)) {
+ if(x509==null) {
+ x509 = (X509Certificate)cert;
+ break;
+ }
+ }
+ X509ChainWithIssuer mxcwi = mxcwi_c.get(client);
+ return new X509ChainWithIssuer(mxcwi,x509);
+// break;
+ } else if (er.isPending()) {
+ trans.checkpoint("Polling, waiting on CA to complete");
+ Thread.sleep(3000);
+ } else if (er.isFailure()) {
+// switch(er.getFailInfo()) {
+// case badMessageCheck:
+// throw new ClientException("Received BadMessageCheck from Jscep");
+// case badAlg:
+// case badCertId:
+// case badRequest:
+// case badTime:
+// default:
+// }
+ throw new CertException(clients.info(item)+':'+er.getFailInfo().toString());
+ }
+ }
+ //i=MAX_RETRY;
+ } catch(LocatorException e) {
+ trans.error().log(e);
+ i=MAX_RETRY;
+ } catch (ClientException e) {
+ trans.error().log(e,"SCEP Client Error, Temporarily Invalidating Client: " + clients.info(item));
+ try {
+ clients.invalidate(client);
+ if(!clients.hasItems()) {
+ clients.refresh();
+ }
+ } catch (LocatorException e1) {
+ trans.error().log(e,clients.info(item));
+ i=MAX_RETRY; // can't go any further
+ }
+ } catch (InterruptedException|TransactionException|CertificateException|OperatorCreationException | CertStoreException e) {
+ trans.error().log(e);
+ i=MAX_RETRY;
+ } finally {
+ tt.done();
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Locator specifically for Jscep Clients.
+ *
+ * Class based client for access to common Map
+ */
+ private class JscepClientLocator extends HotPeerLocator<Client> {
+
+ protected JscepClientLocator(Access access, String urlstr)throws LocatorException {
+ super(access, urlstr, JscepCA.INVALIDATE_TIME,
+ access.getProperty("cadi_latitude","39.833333"), //Note: Defaulting to GEO center of US
+ access.getProperty("cadi_longitude","-98.583333")
+ );
+ }
+
+ @Override
+ protected Client _newClient(String urlinfo) throws LocatorException {
+ try {
+ String[] info = Split.split('/', urlinfo);
+ Client c = new Client(new URL(JscepCA.CA_PREFIX + info[0] + JscepCA.CA_POSTFIX),
+ new CertificateVerifier() {
+ @Override
+ public boolean verify(X509Certificate cert) {
+ //TODO checkIssuer
+ return true;
+ }
+ }
+ );
+ // Map URL to Client, because Client doesn't expose Connection
+ mxcwi_c.put(c,mxcwi_s.get(urlinfo));
+ return c;
+ } catch (MalformedURLException e) {
+ throw new LocatorException(e);
+ }
+ }
+
+ @Override
+ protected Client _invalidate(Client client) {
+ return null;
+ }
+
+ @Override
+ protected void _destroy(Client client) {
+ mxcwi_c.remove(client);
+ }
+
+
+ }
+}