AT&T 2.0.19 Code drop, stage 3
[aaf/authz.git] / auth / auth-certman / src / main / java / org / onap / aaf / auth / cm / ca / CA.java
1 /**
2  * ============LICENSE_START====================================================
3  * org.onap.aaf
4  * ===========================================================================
5  * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
6  * ===========================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END====================================================
19  *
20  */
21 package org.onap.aaf.auth.cm.ca;
22
23 import java.io.File;
24 import java.io.FileInputStream;
25 import java.io.IOException;
26 import java.security.MessageDigest;
27 import java.security.Principal;
28 import java.util.ArrayList;
29 import java.util.Collections;
30 import java.util.HashSet;
31 import java.util.List;
32 import java.util.Set;
33
34 import org.bouncycastle.asn1.x500.style.BCStyle;
35 import org.onap.aaf.auth.cm.cert.CSRMeta;
36 import org.onap.aaf.auth.cm.cert.RDN;
37 import org.onap.aaf.cadi.Access;
38 import org.onap.aaf.cadi.Access.Level;
39 import org.onap.aaf.cadi.cm.CertException;
40 import org.onap.aaf.misc.env.Trans;
41 import org.onap.aaf.misc.env.util.Split;
42
43 public abstract class CA {
44         private static final String MUST_EXIST_TO_CREATE_CSRS_FOR = " must exist to create CSRs for ";
45         //TODO figuring out what is an Issuing CA is a matter of convention.  Consider SubClassing for Open Source
46         public static final String ISSUING_CA = "Issuing CA";
47         public static final String CM_CA_PREFIX = "cm_ca.";
48         public static final String CM_CA_BASE_SUBJECT = ".baseSubject";
49         protected static final String CM_PUBLIC_DIR = "cm_public_dir";
50         private static final String CM_TRUST_CAS = "cm_trust_cas";
51         protected static final String CM_BACKUP_CAS = "cm_backup_cas";
52
53         public static final Set<String> EMPTY = Collections.unmodifiableSet(new HashSet<String>());
54
55         
56         private final String name,env;
57         private MessageDigest messageDigest;
58         private final String permType;
59         private Set<String> caIssuerDNs;
60         private final ArrayList<String> idDomains;
61         private String[] trustedCAs;
62         private List<RDN> rdns; 
63
64
65         protected CA(Access access, String caName, String env) throws IOException, CertException {
66                 trustedCAs = new String[4]; // starting array
67                 this.name = caName;
68                 this.env = env;
69                 permType = access.getProperty(CM_CA_PREFIX + name + ".perm_type",null);
70                 if(permType==null) {
71                         throw new CertException(CM_CA_PREFIX + name + ".perm_type" + MUST_EXIST_TO_CREATE_CSRS_FOR + caName);
72                 }
73                 caIssuerDNs = new HashSet<String>();
74                 
75                 String tag = CA.CM_CA_PREFIX+caName+CA.CM_CA_BASE_SUBJECT;
76                 
77                 String fields = access.getProperty(tag, null);
78                 if(fields==null) {
79                         throw new CertException(tag + MUST_EXIST_TO_CREATE_CSRS_FOR + caName);
80                 }
81                 for(RDN rdn : rdns = RDN.parse('/',fields)) {
82                         if(rdn.aoi==BCStyle.EmailAddress) { // Cert Specs say Emails belong in Subject
83                                 throw new CertException("email address is not allowed in " + CM_CA_BASE_SUBJECT);
84                         }
85                 }
86                 
87                 idDomains = new ArrayList<String>();
88                 StringBuilder sb = null;
89                 for(String s : Split.splitTrim(',', access.getProperty(CA.CM_CA_PREFIX+caName+".idDomains", ""))) {
90                         if(s.length()>0) {
91                                 if(sb==null) {
92                                         sb = new StringBuilder();
93                                 } else {
94                                         sb.append(", ");
95                                 }
96                                 idDomains.add(s);
97                                 sb.append(s);
98                         }
99                 }
100                 if(sb!=null) {
101                         access.printf(Level.INIT, "CA '%s' supports Personal Certificates for %s", caName, sb);
102                 }
103                 
104                 String data_dir = access.getProperty(CM_PUBLIC_DIR,null);
105                 if(data_dir!=null) {
106                         File data = new File(data_dir);
107                         byte[] bytes;
108                         if(data.exists()) {
109                                 String trust_cas = access.getProperty(CM_TRUST_CAS,null);
110                                 if(trust_cas!=null) {
111                                         for(String fname : Split.splitTrim(',', trust_cas)) {
112                                                 File crt = new File(data,fname);
113                                                 if(crt.exists()) {
114                                                         access.printf(Level.INIT, "Loading CA Cert from %s", crt.getAbsolutePath());
115                                                         bytes = new byte[(int)crt.length()];
116                                                         FileInputStream fis = new FileInputStream(crt);
117                                                         try {
118                                                                 fis.read(bytes);
119                                                                 addTrustedCA(new String(bytes));
120                                                         } finally {
121                                                                 fis.close();
122                                                         }
123                                                 } else {
124                                                         access.printf(Level.INIT, "FAILED to Load CA Cert from %s", crt.getAbsolutePath());
125                                                 }
126                                         }
127                                 } else {
128                                         access.printf(Level.INIT, "Cannot load external TRUST CAs: No property %s",CM_TRUST_CAS);
129                                 }
130                         } else {
131                                 access.printf(Level.INIT, "Cannot load external TRUST CAs: %s doesn't exist, or is not accessible",data.getAbsolutePath());
132                         }
133                 }
134         }
135
136         protected void addCaIssuerDN(String issuerDN) {
137                 caIssuerDNs.add(issuerDN);
138         }
139         
140         protected synchronized void addTrustedCA(final String crtString) {
141                 String crt;
142                 if(crtString.endsWith("\n")) {
143                         crt = crtString;
144                 } else {
145                         crt = crtString + '\n';
146                 }
147                 for(int i=0;i<trustedCAs.length;++i) {
148                         if(trustedCAs[i]==null) {
149                                 trustedCAs[i]=crt;
150                                 return;
151                         }
152                 }
153                 String[] temp = new String[trustedCAs.length+5];
154                 System.arraycopy(trustedCAs,0,temp, 0, trustedCAs.length);
155                 temp[trustedCAs.length]=crt;
156                 trustedCAs = temp;
157         }
158         
159         public Set<String> getCaIssuerDNs() {
160                 return caIssuerDNs;
161         }
162         
163         public String[] getTrustedCAs() {
164                 return trustedCAs;
165         }
166         
167         public String getEnv() {
168                 return env;
169         }
170
171         protected void setMessageDigest(MessageDigest md) {
172                 messageDigest = md;
173         }
174
175         /*
176          * End Required Constructor calls
177          */
178
179         public String getName() {
180                 return name;
181         }
182         
183         
184         public String getPermType() {
185                 return permType;
186         }
187         
188         public abstract X509andChain sign(Trans trans, CSRMeta csrmeta) throws IOException, CertException;
189
190         /* (non-Javadoc)
191          * @see org.onap.aaf.auth.cm.ca.CA#inPersonalDomains(java.security.Principal)
192          */
193         public boolean inPersonalDomains(Principal p) {
194                 int at = p.getName().indexOf('@');
195                 if(at>=0) {
196                         return idDomains.contains(p.getName().substring(at+1));
197                 } else {
198                         return false;
199                 }
200         }
201
202         public MessageDigest messageDigest() {
203                 return messageDigest;
204         }
205
206         public CSRMeta newCSRMeta() {
207                 return new CSRMeta(rdns);
208         }
209 }