Update CM to us Local Intermediate Certs 33/55633/1
authorInstrumental <jonathan.gathman@att.com>
Mon, 2 Jul 2018 14:40:49 +0000 (09:40 -0500)
committerInstrumental <jonathan.gathman@att.com>
Mon, 2 Jul 2018 14:41:03 +0000 (09:41 -0500)
Issue-ID: AAF-384
Change-Id: Iefd36c5b9ab8011ac696cb85e74c54edb63cb40a
Signed-off-by: Instrumental <jonathan.gathman@att.com>
45 files changed:
auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/CA.java
auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/JscepCA.java
auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/LocalCA.java
auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/X509ChainWithIssuer.java
auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/X509andChain.java
auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/cert/BCFactory.java
auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/cert/CSRMeta.java
auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/cert/RDN.java
auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/data/CertReq.java
auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/data/CertResp.java
auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/facade/FacadeImpl.java
auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/mapper/Mapper1_0.java
auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/mapper/Mapper2_0.java
auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/service/CMService.java
auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/ca/JU_AppCA.java
auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/cert/JU_BCFactory.java
auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/test/CertmanTest.java
auth/auth-core/src/main/java/org/onap/aaf/auth/env/AuthzTransFilter.java
auth/auth-core/src/main/java/org/onap/aaf/auth/rserv/TransFilter.java
auth/auth-core/src/main/java/org/onap/aaf/auth/server/JettyServiceStarter.java
auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/CMArtifactShow.java
cadi/aaf/src/main/java/org/onap/aaf/cadi/aaf/v2_0/AAFConHttp.java
cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/Agent.java [moved from cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/CmAgent.java with 82% similarity]
cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/ArtifactDir.java [moved from cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/ArtifactDir.java with 95% similarity]
cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/CertException.java [moved from cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/CertException.java with 97% similarity]
cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/Factory.java [moved from cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/Factory.java with 94% similarity]
cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/PlaceArtifact.java [moved from cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/PlaceArtifact.java with 97% similarity]
cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/PlaceArtifactInFiles.java [moved from cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/PlaceArtifactInFiles.java with 95% similarity]
cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/PlaceArtifactInKeystore.java [moved from cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/PlaceArtifactInKeystore.java with 81% similarity]
cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/PlaceArtifactOnStream.java [moved from cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/PlaceArtifactOnStream.java with 97% similarity]
cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/PlaceArtifactScripts.java [moved from cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/PlaceArtifactScripts.java with 98% similarity]
cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_ArtifactDir.java
cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_CertException.java
cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_CmAgent.java
cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_Factory.java
cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_PlaceArtifactInFiles.java
cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_PlaceArtifactInKeystore.java
cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_PlaceArtifactOnStream.java
cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_PlaceArtifactScripts.java
cadi/core/src/main/java/org/onap/aaf/cadi/Symm.java
cadi/core/src/main/java/org/onap/aaf/cadi/config/Config.java
cadi/core/src/main/java/org/onap/aaf/cadi/config/SecurityInfoC.java
cadi/core/src/main/java/org/onap/aaf/cadi/filter/CadiFilter.java
cadi/core/src/main/java/org/onap/aaf/cadi/filter/CadiHTTPManip.java
misc/env/src/main/java/org/onap/aaf/misc/env/util/Split.java

index ea72648..ac3e1a5 100644 (file)
@@ -36,7 +36,8 @@ import org.onap.aaf.auth.cm.cert.CSRMeta;
 import org.onap.aaf.auth.cm.cert.RDN;
 import org.onap.aaf.cadi.Access;
 import org.onap.aaf.cadi.Access.Level;
-import org.onap.aaf.cadi.cm.CertException;
+import org.onap.aaf.cadi.config.Config;
+import org.onap.aaf.cadi.configure.CertException;
 import org.onap.aaf.misc.env.Trans;
 import org.onap.aaf.misc.env.util.Split;
 
@@ -57,9 +58,9 @@ public abstract class CA {
        private final String env;
        private MessageDigest messageDigest;
        private final String permType;
-       private Set<String> caIssuerDNs;
        private final ArrayList<String> idDomains;
        private String[] trustedCAs;
+       private String[] caIssuerDNs;
        private List<RDN> rdns; 
 
 
@@ -71,7 +72,7 @@ public abstract class CA {
                if(permType==null) {
                        throw new CertException(CM_CA_PREFIX + name + ".perm_type" + MUST_EXIST_TO_CREATE_CSRS_FOR + caName);
                }
-               caIssuerDNs = new HashSet<>();
+               caIssuerDNs = Split.splitTrim(':', access.getProperty(Config.CADI_X509_ISSUERS, null));
                
                String tag = CA.CM_CA_PREFIX+caName+CA.CM_CA_BASE_SUBJECT;
                
@@ -112,7 +113,12 @@ public abstract class CA {
                                String trustCas = access.getProperty(CM_TRUST_CAS,null);
                                if(trustCas!=null) {
                                        for(String fname : Split.splitTrim(',', trustCas)) {
-                                               File crt = new File(data,fname);
+                                               File crt;
+                                               if(fname.contains("/")) {
+                                                       crt = new File(fname);
+                                               } else {
+                                                       crt = new File(data,fname);
+                                               }
                                                if(crt.exists()) {
                                                        access.printf(Level.INIT, "Loading CA Cert from %s", crt.getAbsolutePath());
                                                        bytes = new byte[(int)crt.length()];
@@ -139,7 +145,19 @@ public abstract class CA {
        }
 
        protected void addCaIssuerDN(String issuerDN) {
-               caIssuerDNs.add(issuerDN);
+               boolean changed = true;
+               for(String id : caIssuerDNs) {
+                       if(id.equals(issuerDN)) {
+                               changed = false;
+                               break;
+                       }
+               }
+               if(changed) {
+                       String[] newsa = new String[caIssuerDNs.length+1];
+                       newsa[0]=issuerDN;
+                       System.arraycopy(caIssuerDNs, 0, newsa, 1, caIssuerDNs.length);
+                       caIssuerDNs = newsa;
+               }
        }
        
        protected synchronized void addTrustedCA(final String crtString) {
@@ -161,7 +179,7 @@ public abstract class CA {
                trustedCAs = temp;
        }
        
-       public Set<String> getCaIssuerDNs() {
+       public String[] getCaIssuerDNs() {
                return caIssuerDNs;
        }
        
@@ -211,4 +229,5 @@ public abstract class CA {
        public CSRMeta newCSRMeta() {
                return new CSRMeta(rdns);
        }
+
 }
index ee73dbd..3f39838 100644 (file)
@@ -48,7 +48,7 @@ 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.configure.CertException;
 import org.onap.aaf.cadi.locator.HotPeerLocator;
 import org.onap.aaf.misc.env.Env;
 import org.onap.aaf.misc.env.TimeTaken;
index e2287c3..af2d2f6 100644 (file)
@@ -39,6 +39,7 @@ import java.security.cert.CertificateException;
 import java.security.cert.X509Certificate;
 import java.security.interfaces.RSAPublicKey;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Date;
 import java.util.GregorianCalendar;
 import java.util.List;
@@ -64,28 +65,33 @@ import org.onap.aaf.auth.cm.cert.RDN;
 import org.onap.aaf.auth.env.NullTrans;
 import org.onap.aaf.cadi.Access;
 import org.onap.aaf.cadi.Access.Level;
-import org.onap.aaf.cadi.cm.CertException;
-import org.onap.aaf.cadi.cm.Factory;
+import org.onap.aaf.cadi.configure.CertException;
+import org.onap.aaf.cadi.configure.Factory;
 import org.onap.aaf.misc.env.Env;
 import org.onap.aaf.misc.env.TimeTaken;
 import org.onap.aaf.misc.env.Trans;
 
 public class LocalCA extends CA {
 
+       private final static BigInteger ONE = new BigInteger("1");
        // Extensions
        private static final KeyPurposeId[] ASN_WebUsage = new KeyPurposeId[] {
                                KeyPurposeId.id_kp_serverAuth, // WebServer
-                               KeyPurposeId.id_kp_clientAuth};// WebClient
-                               
+                               KeyPurposeId.id_kp_clientAuth // WebClient
+                               };
+       
        private final PrivateKey caKey;
        private final X500Name issuer;
        private final SecureRandom random = new SecureRandom();
-       private byte[] serialish;
+       private BigInteger serial;
        private final X509ChainWithIssuer x509cwi; // "Cert" is CACert
-
+       
+       
        public LocalCA(Access access, final String name, final String env, final String[][] params) throws IOException, CertException {
                super(access, name, env);
-               serialish = new byte[24];
+       
+               serial = new BigInteger(64,random);
+
                if(params.length<1 || params[0].length<2) {
                        throw new IOException("LocalCA expects cm_ca.<ca name>=org.onap.aaf.auth.cm.ca.LocalCA,<full path to key file>[;<Full Path to Trust Chain, ending with actual CA>]+");
                }
@@ -180,7 +186,9 @@ public class LocalCA extends CA {
                }
                
                X500NameBuilder xnb = new X500NameBuilder();
-               for(RDN rnd : RDN.parse(',', x509cwi.getIssuerDN())) {
+               List<RDN> rp = RDN.parse(',', x509cwi.getIssuerDN());
+               Collections.reverse(rp);
+               for(RDN rnd : rp) {
                        xnb.addRDN(rnd.aoi,rnd.value);
                }
                issuer = xnb.build();
@@ -201,9 +209,10 @@ public class LocalCA extends CA {
                TimeTaken tt = trans.start("Create/Sign Cert",Env.SUB);
                try {
                        BigInteger bi;
-                       synchronized(serialish) {
-                               random.nextBytes(serialish);
-                               bi = new BigInteger(serialish);
+                       
+                       synchronized(ONE) {
+                               bi = serial;
+                               serial = serial.add(ONE);
                        }
                                
                        RSAPublicKey rpk = (RSAPublicKey)csrmeta.keypair(trans).getPublic();
@@ -225,20 +234,23 @@ public class LocalCA extends CA {
 
                    JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils();
                        xcb.addExtension(Extension.basicConstraints,
-                       false, new BasicConstraints(false))
+                       false, new BasicConstraints(false
+                                       ))
                            .addExtension(Extension.keyUsage,
                                true, new KeyUsage(KeyUsage.digitalSignature
-                                                | KeyUsage.keyEncipherment))
+                                                | KeyUsage.keyEncipherment 
+                                                | KeyUsage.nonRepudiation))
                            .addExtension(Extension.extendedKeyUsage,
                                          true, new ExtendedKeyUsage(ASN_WebUsage))
-
                     .addExtension(Extension.authorityKeyIdentifier,
-                                         false, extUtils.createAuthorityKeyIdentifier(x509cwi.cert))
-                           .addExtension(Extension.subjectKeyIdentifier,
-                                         false, extUtils.createSubjectKeyIdentifier(x509cwi.cert.getPublicKey()))
+                                 false, extUtils.createAuthorityKeyIdentifier(x509cwi.cert))
+                    .addExtension(Extension.subjectKeyIdentifier,
+                                 false, extUtils.createSubjectKeyIdentifier(rpk))
                            .addExtension(Extension.subjectAlternativeName,
                                        false, new GeneralNames(sans))
-                                                          ;
+//                         .addExtension(MiscObjectIdentifiers.netscape, true, new NetscapeCertType(
+//                                     NetscapeCertType.sslClient|NetscapeCertType.sslClient))
+                           ;                       
        
                        x509 = new JcaX509CertificateConverter().getCertificate(
                                        xcb.build(BCFactory.contentSigner(caKey)));
@@ -248,7 +260,7 @@ public class LocalCA extends CA {
                        tt.done();
                }
                
-               return new X509ChainWithIssuer(x509cwi,x509);
+               return new X509andChain(x509,x509cwi.trustChain);
        }
 
 }
index 6ba5a37..e31b998 100644 (file)
@@ -29,13 +29,14 @@ import java.security.cert.X509Certificate;
 import java.util.Collection;
 import java.util.List;
 
-import org.onap.aaf.cadi.cm.CertException;
-import org.onap.aaf.cadi.cm.Factory;
+import org.onap.aaf.cadi.configure.CertException;
+import org.onap.aaf.cadi.configure.Factory;
 
 public class X509ChainWithIssuer extends X509andChain {
        private String issuerDN;
+       public X509Certificate caX509;
 
-       public X509ChainWithIssuer(X509ChainWithIssuer orig, X509Certificate x509) {
+       public X509ChainWithIssuer(X509ChainWithIssuer orig, X509Certificate x509) throws IOException, CertException {
                super(x509,orig.trustChain);
                issuerDN=orig.issuerDN;         
        }
@@ -48,7 +49,8 @@ public class X509ChainWithIssuer extends X509andChain {
                        if(rdr==null) { // cover for badly formed array
                                continue;
                        }
-                       byte[] bytes = Factory.decode(rdr);
+                       
+                       byte[] bytes = Factory.decode(rdr,null);
                        try {
                                certs = Factory.toX509Certificate(bytes);
                        } catch (CertificateException e) {
@@ -62,24 +64,24 @@ public class X509ChainWithIssuer extends X509andChain {
                                }
                                if(cert==null) { // first in Trust Chain
                                        issuerDN = subject.toString();
+                                       cert=x509; // adding each time makes sure last one is signer.
                                }
                                addTrustChainEntry(x509);
-                               cert=x509; // adding each time makes sure last one is signer.
                        }
                }
        }
        
        public X509ChainWithIssuer(Certificate[] certs) throws IOException, CertException {
                X509Certificate x509;
-               for(Certificate c : certs) {
-                       x509=(X509Certificate)c;
+               for(int i=certs.length-1; i>=0; --i) {
+                       x509=(X509Certificate)certs[i];
                        Principal subject = x509.getSubjectDN();
                        if(subject!=null) {
-                               if(cert==null) { // first in Trust Chain
-                                       issuerDN= subject.toString();
-                               }
                                addTrustChainEntry(x509);
-                               cert=x509; // adding each time makes sure last one is signer.
+                               if(i==0) { // last one is signer
+                                       cert=x509; 
+                                       issuerDN= subject.toString(); 
+                               }
                        }
                }
        }
index 46a6393..5141cc6 100644 (file)
@@ -25,8 +25,8 @@ import java.security.cert.X509Certificate;
 import java.util.List;
 
 import org.onap.aaf.auth.env.NullTrans;
-import org.onap.aaf.cadi.cm.CertException;
-import org.onap.aaf.cadi.cm.Factory;
+import org.onap.aaf.cadi.configure.CertException;
+import org.onap.aaf.cadi.configure.Factory;
 
 
 /**
@@ -45,14 +45,14 @@ public class X509andChain {
                trustChain = null;
        }
        
-       public X509andChain(X509Certificate cert, String[] trustChain) {
+       public X509andChain(X509Certificate cert, String[] tc) throws IOException, CertException {
                this.cert = cert;
-               this.trustChain = trustChain;
+               trustChain=tc;
        }
 
-       public X509andChain(X509Certificate cert, List<String> chain) {
+       public X509andChain(X509Certificate cert, List<String> chain) throws IOException, CertException {
                this.cert = cert;
-               trustChain = new String[chain.size()];
+               trustChain = new String[chain.size()+1];
                chain.toArray(trustChain);
        }
        
@@ -67,6 +67,7 @@ public class X509andChain {
                        trustChain=temp;
                }
        }
+       
 
        public X509Certificate getX509() {
                return cert;
index 7f4590f..70ddd43 100644 (file)
@@ -37,8 +37,8 @@ import org.bouncycastle.pkcs.PKCS10CertificationRequest;
 import org.onap.aaf.auth.cm.ca.CA;
 import org.onap.aaf.auth.cm.validation.CertmanValidator;
 import org.onap.aaf.cadi.Symm;
-import org.onap.aaf.cadi.cm.CertException;
-import org.onap.aaf.cadi.cm.Factory;
+import org.onap.aaf.cadi.configure.CertException;
+import org.onap.aaf.cadi.configure.Factory;
 import org.onap.aaf.misc.env.Env;
 import org.onap.aaf.misc.env.TimeTaken;
 import org.onap.aaf.misc.env.Trans;
index 2b763f7..7d417d5 100644 (file)
@@ -49,8 +49,8 @@ import org.bouncycastle.operator.OperatorCreationException;
 import org.bouncycastle.pkcs.PKCS10CertificationRequest;
 import org.bouncycastle.pkcs.PKCS10CertificationRequestBuilder;
 import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder;
-import org.onap.aaf.cadi.cm.CertException;
-import org.onap.aaf.cadi.cm.Factory;
+import org.onap.aaf.cadi.configure.CertException;
+import org.onap.aaf.cadi.configure.Factory;
 import org.onap.aaf.misc.env.Trans;
 
 public class CSRMeta {
index 5b55f1c..564a4b5 100644 (file)
@@ -25,7 +25,7 @@ import java.util.List;
 
 import org.bouncycastle.asn1.ASN1ObjectIdentifier;
 import org.bouncycastle.asn1.x500.style.BCStyle;
-import org.onap.aaf.cadi.cm.CertException;
+import org.onap.aaf.cadi.configure.CertException;
 import org.onap.aaf.cadi.util.Split;
 
 public class RDN {
index aa0b9c2..d960945 100644 (file)
@@ -28,7 +28,7 @@ import javax.xml.datatype.XMLGregorianCalendar;
 import org.onap.aaf.auth.cm.ca.CA;
 import org.onap.aaf.auth.cm.cert.BCFactory;
 import org.onap.aaf.auth.cm.cert.CSRMeta;
-import org.onap.aaf.cadi.cm.CertException;
+import org.onap.aaf.cadi.configure.CertException;
 
 public class CertReq {
        // These cannot be null
index 595025e..970bfb8 100644 (file)
@@ -25,12 +25,11 @@ import java.io.IOException;
 import java.security.GeneralSecurityException;
 import java.security.KeyPair;
 import java.security.cert.X509Certificate;
-import java.util.Set;
 
 import org.onap.aaf.auth.cm.ca.CA;
 import org.onap.aaf.auth.cm.cert.CSRMeta;
-import org.onap.aaf.cadi.cm.CertException;
-import org.onap.aaf.cadi.cm.Factory;
+import org.onap.aaf.cadi.configure.CertException;
+import org.onap.aaf.cadi.configure.Factory;
 import org.onap.aaf.misc.env.Trans;
 
 public class CertResp {
@@ -40,17 +39,15 @@ public class CertResp {
        
        private String privateKey, certString;
        private String[] trustChain;
-       private String[] trustCAs;
        private String[] notes;
        
-       public CertResp(Trans trans, CA ca, X509Certificate x509, CSRMeta csrMeta, String[] trustChain, String[] trustCAs, String[] notes) throws IOException, GeneralSecurityException, CertException {
+       public CertResp(Trans trans, CA ca, X509Certificate x509, CSRMeta csrMeta, String[] trustChain, String[] notes) throws IOException, GeneralSecurityException, CertException {
                keyPair = csrMeta.keypair(trans);
                privateKey = Factory.toString(trans, keyPair.getPrivate());
                certString = Factory.toString(trans,x509);
                challenge=csrMeta.challenge();
                this.ca = ca;
                this.trustChain = trustChain;
-               this.trustCAs = trustCAs;
                this.notes = notes;
        }
 
@@ -76,7 +73,7 @@ public class CertResp {
                return notes;
        }
        
-       public Set<String> caIssuerDNs() {
+       public String[] caIssuerDNs() {
                return ca.getCaIssuerDNs();
        }
        
@@ -89,6 +86,6 @@ public class CertResp {
        }
        
        public String[] trustCAs() {
-               return trustCAs;
+               return ca.getTrustedCAs();
        }
 }
index 0598ee6..51a905a 100644 (file)
@@ -58,8 +58,8 @@ import org.onap.aaf.auth.env.AuthzEnv;
 import org.onap.aaf.auth.env.AuthzTrans;
 import org.onap.aaf.auth.layer.Result;
 import org.onap.aaf.cadi.aaf.AAFPermission;
-import org.onap.aaf.cadi.cm.CertException;
-import org.onap.aaf.cadi.cm.Factory;
+import org.onap.aaf.cadi.configure.CertException;
+import org.onap.aaf.cadi.configure.Factory;
 import org.onap.aaf.misc.env.APIException;
 import org.onap.aaf.misc.env.Data;
 import org.onap.aaf.misc.env.Env;
index 16517c9..c06734f 100644 (file)
@@ -31,8 +31,8 @@ import org.onap.aaf.auth.cm.data.CertReq;
 import org.onap.aaf.auth.cm.data.CertResp;
 import org.onap.aaf.auth.cm.validation.CertmanValidator;
 import org.onap.aaf.auth.dao.cass.ArtiDAO;
-import org.onap.aaf.auth.dao.cass.CertDAO;
 import org.onap.aaf.auth.dao.cass.ArtiDAO.Data;
+import org.onap.aaf.auth.dao.cass.CertDAO;
 import org.onap.aaf.auth.env.AuthzTrans;
 import org.onap.aaf.auth.layer.Result;
 import org.onap.aaf.cadi.util.FQI;
@@ -108,7 +108,9 @@ public class Mapper1_0 implements Mapper<BaseRequest,CertInfo,Artifacts,Error> {
                if((value=cin.challenge())!=null) {
                        cout.setChallenge(value);
                }
+               // In Version 1, Cert is always first
                cout.getCerts().add(cin.asCertString());
+               // Follow with Trust Chain
                if(cin.trustChain()!=null) {
                        for(String c : cin.trustChain()) {
                                if(c!=null) {
@@ -116,12 +118,15 @@ public class Mapper1_0 implements Mapper<BaseRequest,CertInfo,Artifacts,Error> {
                                }
                        }
                }
+
                // Adding all the Certs in one response is a mistake.  Makes it very hard for Agent to setup
                // Certs in keystore versus Truststore.  Separate in Version 2_0
                if(cin.trustCAs()!=null) {
                        for(String c : cin.trustCAs()) {
                                if(c!=null) {
-                                       cout.getCerts().add(c);
+                                       if(!cout.getCerts().contains(c)) {
+                                               cout.getCerts().add(c);
+                                       }
                                }
                        }
                }
@@ -138,7 +143,10 @@ public class Mapper1_0 implements Mapper<BaseRequest,CertInfo,Artifacts,Error> {
                        }
                        cout.setNotes(sb.toString());
                }
-               cout.getCaIssuerDNs().addAll(cin.caIssuerDNs());
+               List<String> caIssuerDNs = cout.getCaIssuerDNs();
+               for(String s : cin.caIssuerDNs()) {
+                       caIssuerDNs.add(s);
+               }
                cout.setEnv(cin.env());
                return Result.ok(cout);
 
index 13123bd..76f7d9b 100644 (file)
@@ -127,7 +127,12 @@ public class Mapper2_0 implements Mapper<BaseRequest,CertInfo,Artifacts,Error> {
                                }
                                cout.setNotes(sb.toString());
                        }
-                       cout.getCaIssuerDNs().addAll(cin.caIssuerDNs());
+                       
+                       List<String> caIssuerDNs = cout.getCaIssuerDNs();
+                       for(String s : cin.caIssuerDNs()) {
+                               caIssuerDNs.add(s);
+                       }
+
                        cout.setEnv(cin.env());
                        return Result.ok(cout);
                } else {
index 4ef5472..8d39f54 100644 (file)
@@ -59,7 +59,7 @@ import org.onap.aaf.auth.org.Organization.Identity;
 import org.onap.aaf.auth.org.OrganizationException;
 import org.onap.aaf.cadi.Hash;
 import org.onap.aaf.cadi.aaf.AAFPermission;
-import org.onap.aaf.cadi.cm.Factory;
+import org.onap.aaf.cadi.configure.Factory;
 import org.onap.aaf.cadi.util.FQI;
 import org.onap.aaf.misc.env.APIException;
 import org.onap.aaf.misc.env.util.Chrono;
@@ -317,7 +317,7 @@ public class CMService {
                                crdd.type = CredDAO.CERT_SHA256_RSA;
                                credDAO.create(trans, crdd);
                                
-                               CertResp cr = new CertResp(trans, ca, x509, csrMeta, x509ac.getTrustChain(), ca.getTrustedCAs(), compileNotes(notes));
+                               CertResp cr = new CertResp(trans, ca, x509, csrMeta, x509ac.getTrustChain(),compileNotes(notes));
                                return Result.ok(cr);
                        } catch (Exception e) {
                                trans.error().log(e);
@@ -398,7 +398,7 @@ public class CMService {
                                cdd.x509=Factory.toString(trans, x509);
                                certDAO.create(trans, cdd);
                                
-                               CertResp cr = new CertResp(trans, ca, x509, csrMeta, x509ac.getTrustChain(), ca.getTrustedCAs(), compileNotes(null));
+                               CertResp cr = new CertResp(trans, ca, x509, csrMeta, x509ac.getTrustChain(), compileNotes(null));
                                return Result.ok(cr);
                        } catch (Exception e) {
                                trans.error().log(e);
index f6d5cab..d81ea9b 100644 (file)
@@ -52,10 +52,9 @@ import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.runners.MockitoJUnitRunner;
-import org.onap.aaf.auth.cm.ca.CA;
 import org.onap.aaf.auth.cm.cert.CSRMeta;
 import org.onap.aaf.auth.dao.cached.CachedCertDAO;
-import org.onap.aaf.cadi.cm.CertException;
+import org.onap.aaf.cadi.configure.CertException;
 import org.onap.aaf.misc.env.Trans;
 
 //TODO: Gabe [JUnit] Import does not exist
index 856d09c..337bc9e 100644 (file)
@@ -41,7 +41,7 @@ import org.junit.rules.ExpectedException;
 import org.junit.runner.RunWith;
 import org.mockito.Mockito;
 import org.mockito.runners.MockitoJUnitRunner;
-import org.onap.aaf.cadi.cm.CertException;
+import org.onap.aaf.cadi.configure.CertException;
 import org.onap.aaf.misc.env.TimeTaken;
 import org.onap.aaf.misc.env.Trans;
 
index 7d3f25c..5ec96f2 100644 (file)
@@ -41,8 +41,8 @@ import org.onap.aaf.cadi.Locator.Item;
 import org.onap.aaf.cadi.client.Future;
 import org.onap.aaf.cadi.client.Rcli;
 import org.onap.aaf.cadi.client.Retryable;
-import org.onap.aaf.cadi.cm.Factory;
 import org.onap.aaf.cadi.config.SecurityInfoC;
+import org.onap.aaf.cadi.configure.Factory;
 import org.onap.aaf.cadi.http.HBasicAuthSS;
 import org.onap.aaf.cadi.http.HMangr;
 import org.onap.aaf.cadi.locator.DNSLocator;
index cbc0737..531e40a 100644 (file)
@@ -29,6 +29,7 @@ import javax.servlet.http.HttpServletRequest;
 import org.onap.aaf.auth.rserv.TransFilter;
 import org.onap.aaf.cadi.CadiException;
 import org.onap.aaf.cadi.Connector;
+import org.onap.aaf.cadi.LocatorException;
 import org.onap.aaf.cadi.TrustChecker;
 import org.onap.aaf.cadi.principal.TaggedPrincipal;
 import org.onap.aaf.cadi.principal.TrustPrincipal;
@@ -48,7 +49,7 @@ public class AuthzTransFilter extends TransFilter<AuthzTrans> {
 
        public static final int BUCKETSIZE = 2;
        
-       public AuthzTransFilter(AuthzEnv env, Connector con, TrustChecker tc, Object ... additionalTafLurs) throws CadiException {
+       public AuthzTransFilter(AuthzEnv env, Connector con, TrustChecker tc, Object ... additionalTafLurs) throws CadiException, LocatorException {
                super(env.access(),con, tc, additionalTafLurs);
                this.env = env;
                serviceMetric = new Metric();
index 400c539..c286e50 100644 (file)
@@ -37,6 +37,7 @@ import org.onap.aaf.cadi.Access;
 import org.onap.aaf.cadi.CadiException;
 import org.onap.aaf.cadi.CadiWrap;
 import org.onap.aaf.cadi.Connector;
+import org.onap.aaf.cadi.LocatorException;
 import org.onap.aaf.cadi.Lur;
 import org.onap.aaf.cadi.TrustChecker;
 import org.onap.aaf.cadi.config.Config;
@@ -66,7 +67,7 @@ public abstract class TransFilter<TRANS extends TransStore> implements Filter {
 
        private final String[] no_authn;
        
-       public TransFilter(Access access, Connector con, TrustChecker tc, Object ... additionalTafLurs) throws CadiException {
+       public TransFilter(Access access, Connector con, TrustChecker tc, Object ... additionalTafLurs) throws CadiException, LocatorException {
                cadi = new CadiHTTPManip(access, con, tc, additionalTafLurs);
                String no = access.getProperty(Config.CADI_NOAUTHN, null);
                if(no!=null) {
index 4b2ca32..cefc7a2 100644 (file)
@@ -231,11 +231,16 @@ public class JettyServiceStarter<ENV extends RosettaEnv, TRANS extends Trans> ex
                try {
                        register(service.registrants(port));
                        access().printf(Level.INIT, "Starting Jetty Service for %s, version %s, on %s://%s:%d", service.app_name,service.app_version,protocol,hostname,port);
+                       server.join();
                } catch(Exception e) {
                        access().log(e,"Error registering " + service.app_name);
-                       // Question: Should Registered Services terminate?
+                       String doExit = access().getProperty("cadi_exitOnFailure", "true");
+                       if (doExit == "true") {
+                               System.exit(1);
+                       } else {
+                               throw e;
+                       }
                }
-               server.join();
        }
 
        private FilterChain buildFilterChain(final AbsService<?,?> as, final FilterChain doLast) throws CadiException, LocatorException {
index 0ad7364..296e41e 100644 (file)
@@ -47,7 +47,7 @@ import org.onap.aaf.cadi.CadiException;
 import org.onap.aaf.cadi.client.Future;
 import org.onap.aaf.cadi.client.Rcli;
 import org.onap.aaf.cadi.client.Retryable;
-import org.onap.aaf.cadi.cm.Factory;
+import org.onap.aaf.cadi.configure.Factory;
 import org.onap.aaf.cadi.util.FQI;
 import org.onap.aaf.misc.env.APIException;
 import org.onap.aaf.misc.env.Env;
index 7237cb5..9fc38d9 100644 (file)
@@ -70,8 +70,9 @@ public class AAFConHttp extends AAFCon<HttpURLConnection> {
                        } catch (IOException /*| GeneralSecurityException*/ e) {
                                throw new CadiException(e);
                        }
+               } else {
+                       throw new CadiException("No IDs (" + Config.CADI_ALIAS + " or " + Config.AAF_APPID + ") have been identified.");
                }
-               return null;
        }
 
        public AAFConHttp(Access access, String tag) throws APIException, CadiException, LocatorException {
  *
  */
 
-package org.onap.aaf.cadi.cm;
+package org.onap.aaf.cadi.configure;
 
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.PrintStream;
 import java.net.ConnectException;
+import java.net.HttpURLConnection;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.nio.file.Files;
@@ -53,6 +54,7 @@ import org.onap.aaf.cadi.client.Future;
 import org.onap.aaf.cadi.client.Rcli;
 import org.onap.aaf.cadi.client.Retryable;
 import org.onap.aaf.cadi.config.Config;
+import org.onap.aaf.cadi.config.SecurityInfoC;
 import org.onap.aaf.cadi.http.HBasicAuthSS;
 import org.onap.aaf.cadi.locator.SingleEndpointLocator;
 import org.onap.aaf.cadi.sso.AAFSSO;
@@ -76,8 +78,8 @@ import certman.v1_0.CertificateRequest;
 import locate.v1_1.Configuration;
 import locate.v1_1.Configuration.Props;
 
-public class CmAgent {
-       private static final String HASHES = "######################";
+public class Agent {
+       private static final String HASHES = "################################################################";
        private static final String PRINT = "print";
        private static final String FILE = "file";
        private static final String PKCS12 = "pkcs12";
@@ -103,25 +105,36 @@ public class CmAgent {
                int exitCode = 0;
                doExit = true;
                try {
-                       AAFSSO aafsso = new AAFSSO(args, new AAFSSO.ProcessArgs() {
-                               @Override
-                               public Properties process(String[] args, Properties props) {
-                                       if(args.length>1) {
-                                               if(args[0].equals("validate")) {
-                                                       props.put(Config.CADI_PROP_FILES, args[1]);
-                                               } else if (!args[0].equals("genkeypair")) {
-                                                       props.put("aaf_id", args[1]);
-                                               }       
+                       AAFSSO aafsso;
+                       PropAccess access;
+                       
+                       if(args.length>0 && args[0].equals("validate")) {
+                               int idx = args[1].indexOf('=');
+                               aafsso = null;
+                               access = new PropAccess(
+                                                       (idx<0?Config.CADI_PROP_FILES:args[1].substring(0, idx))+
+                                                       '='+
+                                                   (idx<0?args[1]:args[1].substring(idx+1)));
+                       } else {
+                               aafsso= new AAFSSO(args, new AAFSSO.ProcessArgs() {
+                                       @Override
+                                       public Properties process(String[] args, Properties props) {
+                                               if(args.length>1) {
+                                                       if (!args[0].equals("genkeypair")) {
+                                                               props.put("aaf_id", args[1]);
+                                                       }       
+                                               }
+                                               return props;
                                        }
-                                       return props;
-                               }
-                       });
-                       if(aafsso.loginOnly()) {
+                               });
+                               access = aafsso.access();
+                       }
+                               
+                       if(aafsso!=null && aafsso.loginOnly()) {
                                aafsso.setLogDefault();
                                aafsso.writeFiles();
                                System.out.println("AAF SSO information created in ~/.aaf");
                        } else {
-                               PropAccess access = aafsso.access();
                                env = new RosettaEnv(access.getProperties());
                                Deque<String> cmds = new ArrayDeque<String>();
                                for(String p : args) {
@@ -145,7 +158,7 @@ public class CmAgent {
                                        System.out.println("   showpass <FQI> [<machine>]");
                                        System.out.println("   check    <FQI> [<machine>]");
                                        System.out.println("   config   <FQI>");
-                                       System.out.println("   validate <cadi.props>");
+                                       System.out.println("   validate <FQI>.props>");
                                        System.out.println("   genkeypair");
                                        if (doExit) {
                                                System.exit(1);
@@ -174,16 +187,18 @@ public class CmAgent {
                                        trans.setProperty("oauth_token", token);
                                }
                                try {
+                                       if(aafsso!=null) {
                                        // show Std out again
-                                       aafsso.setLogDefault();
-                                       aafsso.setStdErrDefault();
-                                       
-                                       // if CM_URL can be obtained, add to sso.props, if written
-                                       String cm_url = getProperty(access,env,false, Config.CM_URL,Config.CM_URL+": ");
-                                       if(cm_url!=null) {
-                                               aafsso.addProp(Config.CM_URL, cm_url);
+                                               aafsso.setLogDefault();
+                                               aafsso.setStdErrDefault();
+                                               
+                                               // if CM_URL can be obtained, add to sso.props, if written
+                                               String cm_url = getProperty(access,env,false, Config.CM_URL,Config.CM_URL+": ");
+                                               if(cm_url!=null) {
+                                                       aafsso.addProp(Config.CM_URL, cm_url);
+                                               }
+                                               aafsso.writeFiles();
                                        }
-                                       aafsso.writeFiles();
 
                                        AAFCon<?> aafcon = new AAFConHttp(access,Config.CM_URL);
 
@@ -214,7 +229,7 @@ public class CmAgent {
                                                        initConfig(trans,access,aafcon,cmds);
                                                        break;
                                                case "validate":
-                                                       validate(aafsso,aafcon);
+                                                       validate(access);
                                                        break;
                                                case "check":
                                                        try {
@@ -234,7 +249,9 @@ public class CmAgent {
                                trans.info().log("Trans Info\n",sb);
                        }
                                }
-                               aafsso.close();
+                               if(aafsso!=null) {
+                                       aafsso.close();
+                               }
                        }
                } catch (Exception e) {
                        e.printStackTrace();
@@ -610,7 +627,7 @@ public class CmAgent {
                                                if(allowed) {
                                                        File dir = new File(a.getDir());
                                                        Properties props = new Properties();
-                                                       FileInputStream fis = new FileInputStream(new File(dir,a.getNs()+".props"));
+                                                       FileInputStream fis = new FileInputStream(new File(dir,a.getNs()+".cred.props"));
                                                        try {
                                                                props.load(fis);
                                                                fis.close();
@@ -664,88 +681,135 @@ public class CmAgent {
                TimeTaken tt = trans.start("Get Configuration", Env.REMOTE);
                try {
                        boolean ok=false;
-                       File fprops = File.createTempFile(rootFile, ".tmp",dir);
-                       PrintStream out = new PrintStream(new FileOutputStream(fprops));
-                       out.println(HASHES);
-                       out.print("# Configuration File generated on ");
-                       out.println(new Date().toString());
-                       out.println(HASHES);
-                       
-                       File fkf = new File(dir,rootFile+".keyfile");
-                       if(!fkf.exists()) {
-                               CmdLine.main(new String[] {"keygen",fkf.toString()});
-                       }
-                       out.print("cadi_keyfile=");
-                       out.println(fkf.getCanonicalPath());
-                       
-                       out.print(Config.AAF_APPID);
-                       out.print('=');
-                       out.println(fqi);
-                       
-                       Symm filesymm = Symm.obtain(fkf);
-                       out.print(Config.AAF_APPPASS);
-                       out.print("=enc:");
-                       String ps = pa.decrypt(pa.getProperty(Config.AAF_APPPASS), false);
-                       ps = filesymm.enpass(ps);
-                       out.println(ps);
-                       
-                       out.print(Config.CADI_TRUSTSTORE);
-                       out.print("=");
-                       File origTruststore = new File(pa.getProperty(Config.CADI_TRUSTSTORE));
-                       File newTruststore = new File(dir,origTruststore.getName());
-                       if(!newTruststore.exists()) {
-                               Files.copy(origTruststore.toPath(), newTruststore.toPath());
+                       File fProps = File.createTempFile(rootFile, ".tmp",dir);
+                       File fSecureTempProps = File.createTempFile(rootFile, ".cred.tmp",dir);
+                       File fSecureProps = new File(dir,rootFile+".cred.props");
+                       PrintStream psProps;
+
+                       File fLocProps = new File(dir,rootFile + ".location.props");
+                       if(!fLocProps.exists()) {
+                               psProps = new PrintStream(new FileOutputStream(fLocProps));
+                               try {
+                                       psProps.println(HASHES);
+                                       psProps.print("# Configuration File generated on ");
+                                       psProps.println(new Date().toString());
+                                       psProps.println(HASHES);
+                                       for(String tag : new String[] {Config.CADI_LATITUDE,Config.CADI_LONGITUDE}) {
+                                               psProps.print(tag);
+                                               psProps.print('=');
+                                               psProps.println(getProperty(pa, trans, false, tag, "%s: ",tag));
+                                       }
+                               } finally {
+                                       psProps.close();
+                               }
                        }
-                       out.println(newTruststore.getCanonicalPath());
-
-                       out.print(Config.CADI_TRUSTSTORE_PASSWORD);
-                       out.print("=enc:");
-                       ps = pa.decrypt(pa.getProperty(Config.CADI_TRUSTSTORE_PASSWORD), false);
-                       ps = filesymm.enpass(ps);
-                       out.println(ps);
 
-                       
+                       psProps = new PrintStream(new FileOutputStream(fProps));
                        try {
-                               Future<Configuration> acf = aafcon.client(new SingleEndpointLocator(locator))
-                                               .read("/configure/"+fqi+"/aaf", configDF);
-                               if(acf.get(TIMEOUT)) {
-//                                     out.println(acf.value.getName());
-                                       for(Props props : acf.value.getProps()) {
-                                               out.println(props.getTag() + '=' + props.getValue());                                   
+                               PrintStream psCredProps = new PrintStream(new FileOutputStream(fSecureTempProps));
+                               try {
+                                       psCredProps.println(HASHES);
+                                       psCredProps.print("# Configuration File generated on ");
+                                       psCredProps.println(new Date().toString());
+                                       psCredProps.println(HASHES);
+
+                                       psProps.println(HASHES);
+                                       psProps.print("# Configuration File generated on ");
+                                       psProps.println(new Date().toString());
+                                       psProps.println(HASHES);
+                                       
+                                       psProps.print(Config.CADI_PROP_FILES);
+                                       psProps.print('=');
+                                       psProps.print(fSecureProps.getCanonicalPath());
+                                       psProps.print(File.pathSeparatorChar);
+                                       psProps.println(fLocProps.getCanonicalPath());
+                                       
+                                       File fkf = new File(dir,rootFile+".keyfile");
+                                       if(!fkf.exists()) {
+                                               CmdLine.main(new String[] {"keygen",fkf.toString()});
                                        }
-                                       ok = true;
-                               } else if(acf.code()==401){
-                                       trans.error().log("Bad Password sent to AAF");
-                               } else {
-                                       trans.error().log(errMsg.toMsg(acf));
+                                       psCredProps.print("cadi_keyfile=");
+                                       psCredProps.println(fkf.getCanonicalPath());
+                                       
+                                       psCredProps.print(Config.AAF_APPID);
+                                       psCredProps.print('=');
+                                       psCredProps.println(fqi);
+                                       
+                                       Symm filesymm = Symm.obtain(fkf);
+                                       psCredProps.print(Config.AAF_APPPASS);
+                                       psCredProps.print("=enc:");
+                                       String ps = pa.decrypt(pa.getProperty(Config.AAF_APPPASS), false);
+                                       ps = filesymm.enpass(ps);
+                                       psCredProps.println(ps);
+                                       
+                                       psCredProps.print(Config.CADI_TRUSTSTORE);
+                                       psCredProps.print("=");
+                                       File origTruststore = new File(pa.getProperty(Config.CADI_TRUSTSTORE));
+                                       File newTruststore = new File(dir,origTruststore.getName());
+                                       if(!newTruststore.exists()) {
+                                               Files.copy(origTruststore.toPath(), newTruststore.toPath());
+                                       }
+                                       psCredProps.println(newTruststore.getCanonicalPath());
+               
+                                       psCredProps.print(Config.CADI_TRUSTSTORE_PASSWORD);
+                                       psCredProps.print("=enc:");
+                                       ps = pa.decrypt(pa.getProperty(Config.CADI_TRUSTSTORE_PASSWORD), false);
+                                       ps = filesymm.enpass(ps);
+                                       psCredProps.println(ps);
+                                       
+                                       try {
+                                               Future<Configuration> acf = aafcon.client(new SingleEndpointLocator(locator))
+                                                               .read("/configure/"+fqi+"/aaf", configDF);
+                                               if(acf.get(TIMEOUT)) {
+               //                                      out.println(acf.value.getName());
+                                                       for(Props props : acf.value.getProps()) {
+                                                               psProps.println(props.getTag() + '=' + props.getValue());                                       
+                                                       }
+                                                       ok = true;
+                                               } else if(acf.code()==401){
+                                                       trans.error().log("Bad Password sent to AAF");
+                                               } else {
+                                                       trans.error().log(errMsg.toMsg(acf));
+                                               }
+                                       } finally {
+                                               psProps.close();
+                                       }
+                                       if(ok) {
+                                               File newFile = new File(dir,rootFile+".props");
+                                               fProps.renameTo(newFile);
+                                               System.out.println("Created " + newFile.getCanonicalPath());
+                                               fProps = newFile;
+                                               
+                                               fSecureTempProps.renameTo(fSecureProps);
+                                               System.out.println("Created " + fSecureProps.getCanonicalPath());
+                                               fProps = newFile;
+                                       } else {
+                                               fProps.delete();
+                                               fSecureTempProps.delete();
+                                       }
+                               } finally {
+                                       psCredProps.close();
                                }
                        } finally {
-                               out.close();
-                       }
-                       if(ok) {
-                               File newFile = new File(dir,rootFile+".common.props");
-                               fprops.renameTo(newFile);
-                               System.out.println("Created " + newFile.getCanonicalPath());
-                               fprops = newFile;
-                       } else {
-                               fprops.delete();
+                               psProps.close();
                        }
                } finally {
                        tt.done();
                }
        }
        
-       private static void validate(final AAFSSO aafsso, final AAFCon<?> aafcon) throws LocatorException, CadiException, APIException {
+       private static void validate(final PropAccess pa) throws LocatorException, CadiException, APIException {
                System.out.println("Validating Configuration...");
-               aafcon.clone(aafsso.access().getProperty(Config.AAF_URL)).best(new Retryable<Void>() {
+               final AAFCon<?> aafcon = new AAFConHttp(pa,Config.AAF_URL,new SecurityInfoC<HttpURLConnection>(pa));
+               aafcon.best(new Retryable<Void>() {
                        @Override
                        public Void code(Rcli<?> client) throws CadiException, ConnectException, APIException {
-                               Future<Perms> fc = client.read("/authz/perms/user/"+aafsso.user(),permDF);
+                               Future<Perms> fc = client.read("/authz/perms/user/"+aafcon.defID(),permDF);
                                if(fc.get(aafcon.timeout)) {
                                        System.out.print("Success connecting to ");
                                        System.out.println(client.getURI());
                                        System.out.print("   Permissions for ");
-                                       System.out.println(aafsso.user());
+                                       System.out.println(aafcon.defID());
                                        for(Perm p : fc.value.getPerm()) {
                                                System.out.print('\t');
                                                System.out.print(p.getType());
@@ -19,7 +19,7 @@
  *
  */
 
-package org.onap.aaf.cadi.cm;
+package org.onap.aaf.cadi.configure;
 
 import java.io.File;
 import java.io.FileOutputStream;
@@ -29,6 +29,7 @@ import java.io.PrintStream;
 import java.io.PrintWriter;
 import java.security.KeyStore;
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -75,8 +76,8 @@ public abstract class ArtifactDir implements PlaceArtifact {
                                
                                // Also place cm_url and Host Name
                                addProperty(Config.CM_URL,trans.getProperty(Config.CM_URL));
-                               addProperty(Config.HOSTNAME,machine);
-                               addProperty(Config.AAF_ENV,certInfo.getEnv());
+//                             addProperty(Config.HOSTNAME,machine);
+//                             addProperty(Config.AAF_ENV,certInfo.getEnv());
                                // Obtain Issuers
                                boolean first = true;
                                StringBuilder issuers = new StringBuilder();
@@ -208,10 +209,11 @@ public abstract class ArtifactDir implements PlaceArtifact {
                }
                boolean first=processed.get("dir")==null;
                try {
-                       File f = new File(dir,arti.getNs()+".props");
+                       File f = new File(dir,arti.getNs()+".cred.props");
                        if(f.exists()) {
                                if(first) {
-                                       f.delete();
+                                       File backup = File.createTempFile(f.getName()+'.', ".backup",dir);
+                                       f.renameTo(backup);
                                } else {
                                        f.setWritable(true);
                                }
@@ -19,7 +19,7 @@
  *
  */
 
-package org.onap.aaf.cadi.cm;
+package org.onap.aaf.cadi.configure;
 
 import java.io.BufferedReader;
 import java.io.ByteArrayInputStream;
@@ -64,6 +64,7 @@ import javax.crypto.Cipher;
 import javax.crypto.NoSuchPaddingException;
 
 import org.onap.aaf.cadi.Symm;
+import org.onap.aaf.cadi.client.Holder;
 import org.onap.aaf.misc.env.Env;
 import org.onap.aaf.misc.env.TimeTaken;
 import org.onap.aaf.misc.env.Trans;
@@ -155,10 +156,10 @@ public class Factory {
        }
        
        public static PrivateKey toPrivateKey(Trans trans, String pk) throws IOException, CertException {
-               byte[] bytes = decode(new StringReader(pk));
+               byte[] bytes = decode(new StringReader(pk), null);
                return toPrivateKey(trans, bytes);
        }
-       
+
        public static PrivateKey toPrivateKey(Trans trans, byte[] bytes) throws IOException, CertException {
                TimeTaken tt=trans.start("Reconstitute Private Key", Env.SUB);
                try {
@@ -169,11 +170,12 @@ public class Factory {
                        tt.done();
                }
        }
-       
+
        public static PrivateKey toPrivateKey(Trans trans, File file) throws IOException, CertException {
                TimeTaken tt = trans.start("Decode Private Key File", Env.SUB);
                try {
-                       return toPrivateKey(trans,decode(file));
+                       Holder<String> firstLine = new Holder<String>(null);
+                       return toPrivateKey(trans,decode(file,firstLine));
                }finally {
                        tt.done();
                }
@@ -190,7 +192,7 @@ public class Factory {
                try {
                        ByteArrayInputStream bais = new ByteArrayInputStream(pk.getBytes());
                        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-                       Symm.base64noSplit.decode(bais, baos);
+                       Symm.base64noSplit.decode(new StripperInputStream(bais), baos);
 
                        return keyFactory.generatePublic(new X509EncodedKeySpec(baos.toByteArray()));
                } catch (InvalidKeySpecException e) {
@@ -273,10 +275,25 @@ public class Factory {
        }
 
        public static byte[] strip(Reader rdr) throws IOException {
+               return strip(rdr,null);
+       }
+       
+       public static byte[] strip(Reader rdr, Holder<String> hs) throws IOException {
                BufferedReader br = new BufferedReader(rdr);
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                String line;
+               boolean notStarted = true;
                while((line=br.readLine())!=null) {
+                       if(notStarted) {
+                               if(line.startsWith("-----")) {
+                                       notStarted = false;
+                                       if(hs!=null) {
+                                               hs.set(line);
+                                       }
+                               } else {
+                                       continue;
+                               }
+                       }
                        if(line.length()>0 &&
                           !line.startsWith("-----") &&
                           line.indexOf(':')<0) {  // Header elements
@@ -285,7 +302,7 @@ public class Factory {
                }
                return baos.toByteArray();
        }
-       
+
        public static class StripperInputStream extends InputStream {
                private Reader created;
                private BufferedReader br;
@@ -395,17 +412,18 @@ public class Factory {
                return baos.toByteArray();
        }
        
-       public static byte[] decode(File f) throws IOException {
+       public static byte[] decode(File f, Holder<String> hs) throws IOException {
                FileReader fr = new FileReader(f);
                try {
-                       return Factory.decode(fr);
+                       return Factory.decode(fr,hs);
                } finally {
                        fr.close();
                }
-
        }
-       public static byte[] decode(Reader rdr) throws IOException {
-               return decode(strip(rdr));
+
+
+       public static byte[] decode(Reader rdr,Holder<String> hs) throws IOException {
+               return decode(strip(rdr,hs));
        }
 
 
@@ -19,7 +19,7 @@
  *
  */
 
-package org.onap.aaf.cadi.cm;
+package org.onap.aaf.cadi.configure;
 
 import java.io.File;
 
@@ -36,6 +36,7 @@ public class PlaceArtifactInFiles extends ArtifactDir {
                try {
                        // Setup Public Cert
                        File f = new File(dir,arti.getNs()+".crt");
+                       // In Version 1.0, App Cert is first
                        write(f,Chmod.to644,certInfo.getCerts().get(0),C_R);
                        
                        // Setup Private Key
@@ -19,7 +19,7 @@
  *
  */
 
-package org.onap.aaf.cadi.cm;
+package org.onap.aaf.cadi.configure;
 
 import java.io.File;
 import java.security.KeyStore;
@@ -28,7 +28,10 @@ import java.security.cert.Certificate;
 import java.security.cert.X509Certificate;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 import org.onap.aaf.cadi.CadiException;
 import org.onap.aaf.cadi.Symm;
@@ -52,7 +55,8 @@ public class PlaceArtifactInKeystore extends ArtifactDir {
                try {
                        KeyStore jks = KeyStore.getInstance(kst);
                        if(fks.exists()) {
-                               fks.delete();
+                               File backup = File.createTempFile(fks.getName()+'.', ".backup",dir);
+                               fks.renameTo(backup);
                        }       
 
                        // Get the Cert(s)... Might include Trust store
@@ -60,29 +64,26 @@ public class PlaceArtifactInKeystore extends ArtifactDir {
                        // find where the trusts end in 1.0 API
                
                        X509Certificate x509;
-                       List<X509Certificate> certList = new ArrayList<X509Certificate>();
-                       Certificate[] trustChain = null;
-                       Certificate[] trustCAs;
+                       List<X509Certificate> chainList = new ArrayList<X509Certificate>();
+                       Set<X509Certificate> caSet = new HashSet<X509Certificate>();
                        for(Certificate c : certColl) {
                                x509 = (X509Certificate)c;
-                               if(trustChain==null && x509.getSubjectDN().equals(x509.getIssuerDN())) {
-                                       trustChain = new Certificate[certList.size()];
-                                       certList.toArray(trustChain);
-                                       certList.clear(); // reuse
+                               // Is a Root (self-signed, anyway)
+                               if(x509.getSubjectDN().equals(x509.getIssuerDN())) {
+                                       caSet.add(x509);
+                               } else {
+                                       chainList.add(x509);
                                }
-                               certList.add(x509);
                        }
-                       
-                       // remainder should be Trust CAs
-                       trustCAs = new Certificate[certList.size()];
-                       certList.toArray(trustCAs);
+//                     chainList.addAll(caSet);
+                       //Collections.reverse(chainList);
 
                        // Properties, etc
                        // Add CADI Keyfile Entry to Properties
                        addProperty(Config.CADI_KEYFILE,arti.getDir()+'/'+arti.getNs() + ".keyfile");
                        // Set Keystore Password
                        addProperty(Config.CADI_KEYSTORE,fks.getAbsolutePath());
-                       String keystorePass = Symm.randomGen(CmAgent.PASS_SIZE);
+                       String keystorePass = Symm.randomGen(Agent.PASS_SIZE);
                        addEncProperty(Config.CADI_KEYSTORE_PASSWORD,keystorePass);
                        char[] keystorePassArray = keystorePass.toCharArray();
                        jks.load(null,keystorePassArray); // load in
@@ -106,6 +107,8 @@ public class PlaceArtifactInKeystore extends ArtifactDir {
                        KeyStore.ProtectionParameter protParam = 
                                        new KeyStore.PasswordProtection(keyPass.toCharArray());
                        
+                       Certificate[] trustChain = new Certificate[chainList.size()];
+                       chainList.toArray(trustChain);
                        KeyStore.PrivateKeyEntry pkEntry = 
                                new KeyStore.PrivateKeyEntry(pk, trustChain);
                        jks.setEntry(arti.getMechid(), 
@@ -116,16 +119,23 @@ public class PlaceArtifactInKeystore extends ArtifactDir {
                        
                        // Change out to TrustStore
                        fks = new File(dir,arti.getNs()+".trust."+kst);
+                       if(fks.exists()) {
+                               File backup = File.createTempFile(fks.getName()+'.', ".backup",dir);
+                               fks.renameTo(backup);
+                       }       
+
                        jks = KeyStore.getInstance(kst);
                        
                        // Set Truststore Password
                        addProperty(Config.CADI_TRUSTSTORE,fks.getAbsolutePath());
-                       String trustStorePass = Symm.randomGen(CmAgent.PASS_SIZE);
+                       String trustStorePass = Symm.randomGen(Agent.PASS_SIZE);
                        addEncProperty(Config.CADI_TRUSTSTORE_PASSWORD,trustStorePass);
                        char[] truststorePassArray = trustStorePass.toCharArray();
                        jks.load(null,truststorePassArray); // load in
                        
                        // Add Trusted Certificates, but PKCS12 doesn't support
+                       Certificate[] trustCAs = new Certificate[caSet.size()];
+                       caSet.toArray(trustCAs);
                        for(int i=0; i<trustCAs.length;++i) {
                                jks.setCertificateEntry("ca_" + arti.getCa() + '_' + i, trustCAs[i]);
                        }
@@ -19,7 +19,7 @@
  *
  */
 
-package org.onap.aaf.cadi.cm;
+package org.onap.aaf.cadi.configure;
 
 import java.io.File;
 
@@ -116,7 +116,7 @@ public class PlaceArtifactScripts extends ArtifactDir {
                        " fi\n" +
                        "}\n\n" +
                        javaHome() + "/bin/" +"java -cp $CP " +
-                               CmAgent.class.getName() + 
+                               Agent.class.getName() + 
                                " cadi_prop_files=$DIR/$APP.props check 2>  $DIR/$APP.STDERR > $DIR/$APP.STDOUT\n" +
                        "case \"$?\" in\n" +
                        "  0)\n" +
index d0d67e2..ed23179 100644 (file)
@@ -42,7 +42,7 @@ import org.junit.Test;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.onap.aaf.cadi.CadiException;
-import org.onap.aaf.cadi.cm.ArtifactDir;
+import org.onap.aaf.cadi.configure.ArtifactDir;
 import org.onap.aaf.cadi.util.Chmod;
 import org.onap.aaf.misc.env.Trans;
 
index aa12d7c..a973bc2 100644 (file)
@@ -24,8 +24,7 @@ package org.onap.aaf.cadi.cm.test;
 import static org.junit.Assert.*;
 import static org.hamcrest.CoreMatchers.*;
 import org.junit.*;
-
-import org.onap.aaf.cadi.cm.CertException;
+import org.onap.aaf.cadi.configure.CertException;
 
 public class JU_CertException {
 
index fbeb360..b50c5a5 100644 (file)
@@ -28,7 +28,7 @@ import java.io.File;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
-import org.onap.aaf.cadi.cm.CmAgent;
+import org.onap.aaf.cadi.configure.Agent;
 
 public class JU_CmAgent {
 
@@ -58,62 +58,62 @@ public class JU_CmAgent {
                                "-login",
                                "-noExit",
                };
-               CmAgent.main(args);
+               Agent.main(args);
 
                inStream.reset();
                args = new String[] {
                                "-noExit",
                };
-               CmAgent.main(args);
+               Agent.main(args);
 
                inStream.reset();
                args = new String[] {
                                "place",
                                "-noExit",
                };
-               CmAgent.main(args);
+               Agent.main(args);
 
                inStream.reset();
                args = new String[] {
                                "-noExit",
                                "create"
                };
-               CmAgent.main(args);
+               Agent.main(args);
 
                inStream.reset();
                args = new String[] {
                                "-noExit",
                                "read"
                };
-               CmAgent.main(args);
+               Agent.main(args);
 
                inStream.reset();
                args = new String[] {
                                "-noExit",
                                "copy"
                };
-               CmAgent.main(args);
+               Agent.main(args);
 
                inStream.reset();
                args = new String[] {
                                "-noExit",
                                "update"
                };
-               CmAgent.main(args);
+               Agent.main(args);
 
                inStream.reset();
                args = new String[] {
                                "-noExit",
                                "delete"
                };
-               CmAgent.main(args);
+               Agent.main(args);
 
                inStream.reset();
                args = new String[] {
                                "-noExit",
                                "showpass"
                };
-               CmAgent.main(args);
+               Agent.main(args);
 
        }
 
index fb186b8..b47abe2 100644 (file)
@@ -57,11 +57,10 @@ import java.util.List;
 
 import javax.crypto.Cipher;
 
-import org.onap.aaf.cadi.cm.CertException;
-import org.onap.aaf.cadi.cm.Factory;
-import org.onap.aaf.cadi.cm.Factory.Base64InputStream;
-import org.onap.aaf.cadi.cm.Factory.StripperInputStream;
-
+import org.onap.aaf.cadi.configure.CertException;
+import org.onap.aaf.cadi.configure.Factory;
+import org.onap.aaf.cadi.configure.Factory.Base64InputStream;
+import org.onap.aaf.cadi.configure.Factory.StripperInputStream;
 import org.onap.aaf.misc.env.Env;
 import org.onap.aaf.misc.env.LogTarget;
 import org.onap.aaf.misc.env.TimeTaken;
@@ -162,8 +161,8 @@ public class JU_Factory {
                assertThat(privateKeyString.startsWith("-----BEGIN PRIVATE KEY-----"), is(true));
                assertThat(privateKeyString.endsWith("-----END PRIVATE KEY-----\n"), is(true));
 
-               PublicKey publicKey = Factory.toPublicKey(transMock, cleanupString(publicKeyString));
-               PrivateKey privateKey = Factory.toPrivateKey(transMock, cleanupString(privateKeyString));
+               PublicKey publicKey = Factory.toPublicKey(transMock, publicKeyString);
+               PrivateKey privateKey = Factory.toPrivateKey(transMock, privateKeyString);
 
                Cipher encryptor = Factory.pkCipher(publicKey, true);
                Cipher decryptor = Factory.pkCipher(privateKey, false);
index 3c83112..7afb4cf 100644 (file)
@@ -32,7 +32,7 @@ import java.util.List;
 import org.junit.*;
 import org.mockito.*;
 import org.onap.aaf.cadi.CadiException;
-import org.onap.aaf.cadi.cm.PlaceArtifactInFiles;
+import org.onap.aaf.cadi.configure.PlaceArtifactInFiles;
 import org.onap.aaf.misc.env.Trans;
 
 import certman.v1_0.Artifacts.Artifact;
index d146f63..0b086f1 100644 (file)
@@ -39,7 +39,7 @@ import java.security.cert.CertificateException;
 import org.junit.*;
 import org.mockito.*;
 import org.onap.aaf.cadi.CadiException;
-import org.onap.aaf.cadi.cm.PlaceArtifactInKeystore;
+import org.onap.aaf.cadi.configure.PlaceArtifactInKeystore;
 import org.onap.aaf.misc.env.Env;
 import org.onap.aaf.misc.env.TimeTaken;
 import org.onap.aaf.misc.env.Trans;
@@ -102,8 +102,9 @@ public class JU_PlaceArtifactInKeystore {
                certs.add(x509String);
                certs.add(x509Chain);
                assertThat(placer.place(transMock, certInfoMock, artiMock, "machine"), is(true));
-               for (String ext : new String[] {"chal", "keyfile", "jks", "props", "trust.jks"}) {
-                       assertThat(new File(dirName + '/' + nsName + '.' + ext).exists(), is(true));
+               for (String ext : new String[] {"chal", "keyfile", "jks", "trust.jks", "cred.props"}) {
+                       File f = new File(dirName + '/' + nsName + '.' + ext);
+                       assertThat(f.exists(), is(true));
                }
 
                // coverage
index 6e390be..3d8f41c 100644 (file)
@@ -32,8 +32,7 @@ import java.util.List;
 
 import org.junit.*;
 import org.mockito.*;
-
-import org.onap.aaf.cadi.cm.PlaceArtifactOnStream;
+import org.onap.aaf.cadi.configure.PlaceArtifactOnStream;
 import org.onap.aaf.misc.env.LogTarget;
 import org.onap.aaf.misc.env.Trans;
 
index 0ed29e1..682606c 100644 (file)
@@ -30,7 +30,7 @@ import java.io.File;
 import org.junit.*;
 import org.mockito.*;
 import org.onap.aaf.cadi.CadiException;
-import org.onap.aaf.cadi.cm.PlaceArtifactScripts;
+import org.onap.aaf.cadi.configure.PlaceArtifactScripts;
 import org.onap.aaf.misc.env.Trans;
 
 import certman.v1_0.Artifacts.Artifact;
index ea3891f..5a3fe82 100644 (file)
@@ -450,9 +450,11 @@ public class Symm {
                   this.range = range;
           }
           public int convert(int read) throws IOException {
+                  // System.out.print((char)read);
                   switch(read) {
                           case -1: 
                           case '=':
+                          case ' ':
                           case '\n':
                           case '\r':
                                   return -1;
index c79c5cc..9a0a53c 100644 (file)
@@ -43,6 +43,7 @@ import org.onap.aaf.cadi.CadiException;
 import org.onap.aaf.cadi.Connector;
 import org.onap.aaf.cadi.CredVal;
 import org.onap.aaf.cadi.Locator;
+import org.onap.aaf.cadi.LocatorException;
 import org.onap.aaf.cadi.Lur;
 import org.onap.aaf.cadi.PropAccess;
 import org.onap.aaf.cadi.Symm;
@@ -225,7 +226,7 @@ public class Config {
                }
        }
 
-       public static HttpTaf configHttpTaf(Connector con, SecurityInfoC<HttpURLConnection> si, TrustChecker tc, CredVal up, Lur lur, Object ... additionalTafLurs) throws CadiException {
+       public static HttpTaf configHttpTaf(Connector con, SecurityInfoC<HttpURLConnection> si, TrustChecker tc, CredVal up, Lur lur, Object ... additionalTafLurs) throws CadiException, LocatorException {
                Access access = si.access;
                /////////////////////////////////////////////////////
                // Setup AAFCon for any following
@@ -712,7 +713,7 @@ public class Config {
 
 
        @SuppressWarnings("unchecked")
-       public static Locator<URI> loadLocator(SecurityInfoC<HttpURLConnection> si, final String _url) {
+       public static Locator<URI> loadLocator(SecurityInfoC<HttpURLConnection> si, final String _url) throws LocatorException {
                Access access = si.access;
                Locator<URI> locator = null;
                if(_url==null) {
@@ -753,6 +754,9 @@ public class Config {
                                        access.log(Level.INFO, "AAFLocator enabled using preloaded " + locator.getClass().getSimpleName());
                                }
                        } catch (InvocationTargetException e) {
+                               if(e.getTargetException() instanceof LocatorException) {
+                                       throw (LocatorException)e.getTargetException();
+                               }
                                access.log(Level.INIT,e.getTargetException().getMessage(),"AAFLocator for",url,"could not be created.",e);
                        } catch (Exception e) {
                                access.log(Level.INIT,"AAFLocator for",url,"could not be created.",e);
index 33aef6c..cc366c2 100644 (file)
@@ -34,7 +34,7 @@ public class SecurityInfoC<CLIENT> extends SecurityInfo {
        private static Map<Class<?>,SecurityInfoC<?>> sicMap = new HashMap<Class<?>,SecurityInfoC<?>>();
        public SecuritySetter<CLIENT> defSS;
 
-       private SecurityInfoC(Access access) throws CadiException {
+       public SecurityInfoC(Access access) throws CadiException {
                super(access);
                defSS = new SecuritySetter<CLIENT>() {
                                @Override
@@ -54,14 +54,14 @@ public class SecurityInfoC<CLIENT> extends SecurityInfo {
                        };
        }
        
-       @SuppressWarnings("unchecked")
        public static synchronized <CLIENT> SecurityInfoC<CLIENT> instance(Access access, Class<CLIENT> cls) throws CadiException {
-               SecurityInfoC<?> sic = sicMap.get(cls);
+               @SuppressWarnings("unchecked")
+               SecurityInfoC<CLIENT> sic = (SecurityInfoC<CLIENT>) sicMap.get(cls);
                if(sic==null) {
                        sic = new SecurityInfoC<CLIENT>(access); 
                        sicMap.put(cls, sic);
                }
-               return (SecurityInfoC<CLIENT>)sic;
+               return sic;
        }
 
        public SecurityInfoC<CLIENT> set(SecuritySetter<CLIENT> defSS) {
index 8577d55..1f302c6 100644 (file)
@@ -38,6 +38,7 @@ import javax.servlet.http.HttpServletResponse;
 import org.onap.aaf.cadi.Access;
 import org.onap.aaf.cadi.CadiException;
 import org.onap.aaf.cadi.CadiWrap;
+import org.onap.aaf.cadi.LocatorException;
 import org.onap.aaf.cadi.Lur;
 import org.onap.aaf.cadi.PropAccess;
 import org.onap.aaf.cadi.ServletContextAccess;
@@ -188,7 +189,7 @@ public class CadiFilter implements Filter {
                                }
                                try {
                                        httpChecker = new CadiHTTPManip(access,null /*reuseable Con*/,tc, additionalTafLurs);
-                               } catch (CadiException e1) {
+                               } catch (CadiException | LocatorException e1) {
                                        throw new ServletException(e1);
                                }
                        } else if(access==null) {
index 006d6b4..0cc5220 100644 (file)
@@ -32,6 +32,7 @@ import org.onap.aaf.cadi.CadiException;
 import org.onap.aaf.cadi.CadiWrap;
 import org.onap.aaf.cadi.Connector;
 import org.onap.aaf.cadi.CredVal;
+import org.onap.aaf.cadi.LocatorException;
 import org.onap.aaf.cadi.Lur;
 import org.onap.aaf.cadi.Taf;
 import org.onap.aaf.cadi.TrustChecker;
@@ -70,7 +71,7 @@ public class CadiHTTPManip {
        public static final Object[] noAdditional = new Object[0]; // CadiFilter can be created each call in some systems
 
 
-       public CadiHTTPManip(Access access, Connector con, TrustChecker tc, Object ... additionalTafLurs) throws CadiException {
+       public CadiHTTPManip(Access access, Connector con, TrustChecker tc, Object ... additionalTafLurs) throws CadiException, LocatorException {
                synchronized(LOCK) {
                        this.access = access;
 //                     Get getter = new AccessGetter(access);
index 57e6009..efb6812 100644 (file)
@@ -30,7 +30,13 @@ package org.onap.aaf.misc.env.util;
  */\r
 \r
 public class Split {\r
+         private static final String[] BLANK = new String[0];\r
+         \r
          public static String[] split(char c, String value) {\r
+                 if(value==null) {\r
+                         return BLANK;\r
+                 }\r
+\r
                  // Count items to preallocate Array (memory alloc is more expensive than counting twice)\r
                  int count,idx;\r
                  for(count=1,idx=value.indexOf(c);idx>=0;idx=value.indexOf(c,++idx),++count);\r
@@ -50,6 +56,9 @@ public class Split {
          }\r
 \r
          public static String[] splitTrim(char c, String value) {\r
+                 if(value==null) {\r
+                         return BLANK;\r
+                 }\r
                  // Count items to preallocate Array (memory alloc is more expensive than counting twice)\r
                  int count,idx;\r
                  for(count=1,idx=value.indexOf(c);idx>=0;idx=value.indexOf(c,++idx),++count);\r
@@ -69,6 +78,10 @@ public class Split {
          }\r
 \r
          public static String[] splitTrim(char c, String value, int size) {\r
+                 if(value==null) {\r
+                         return BLANK;\r
+                 }\r
+\r
                  int idx;\r
                  String[] rv = new String[size];\r
                  if(size==1) {\r