1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package edu.internet2.middleware.shibboleth.common.config.security;
18
19 import java.security.cert.CRLException;
20 import java.security.cert.CertificateException;
21 import java.security.cert.X509CRL;
22 import java.security.cert.X509Certificate;
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.List;
26 import java.util.Map;
27
28 import javax.xml.namespace.QName;
29
30 import org.opensaml.xml.security.x509.X509Util;
31 import org.opensaml.xml.util.DatatypeHelper;
32 import org.opensaml.xml.util.XMLHelper;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35 import org.springframework.beans.FatalBeanException;
36 import org.springframework.beans.factory.support.AbstractBeanDefinition;
37 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
38 import org.springframework.beans.factory.xml.ParserContext;
39 import org.w3c.dom.Attr;
40 import org.w3c.dom.Element;
41
42
43
44
45 public abstract class AbstractX509CredentialBeanDefinitionParser extends AbstractCredentialBeanDefinitionParser {
46
47
48 private final Logger log = LoggerFactory.getLogger(AbstractX509CredentialBeanDefinitionParser.class);
49
50
51 protected Class getBeanClass(Element element) {
52 return X509CredentialFactoryBean.class;
53 }
54
55
56 protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext) {
57 return element.getAttributeNS(null, "id");
58 }
59
60
61 protected void doParse(Element element, BeanDefinitionBuilder builder) {
62 log.info("Parsing configuration for {} credential with id: {}", XMLHelper.getXSIType(element)
63 .getLocalPart(), element.getAttributeNS(null, "id"));
64
65 parseAttributes(element, builder);
66
67 Map<QName, List<Element>> configChildren = XMLHelper.getChildElements(element);
68
69 parseCommon(configChildren, builder);
70
71 parsePrivateKey(configChildren, builder);
72 parseCertificates(configChildren, builder);
73 parseCRLs(configChildren, builder);
74 }
75
76
77
78
79
80
81
82 protected void parseCertificates(Map<QName, List<Element>> configChildren, BeanDefinitionBuilder builder) {
83 List<Element> certElems = configChildren.get(new QName(SecurityNamespaceHandler.NAMESPACE, "Certificate"));
84 if (certElems == null || certElems.isEmpty()) {
85 return;
86 }
87
88 log.debug("Parsing x509 credential certificates");
89 ArrayList<X509Certificate> certs = new ArrayList<X509Certificate>();
90 byte[] encodedCert;
91 Collection<X509Certificate> decodedCerts;
92 for (Element certElem : certElems) {
93 encodedCert = getEncodedCertificate(DatatypeHelper.safeTrimOrNullString(certElem.getTextContent()));
94 if (encodedCert == null) {
95 continue;
96 }
97
98 boolean isEntityCert = false;
99 Attr entityCertAttr = certElem.getAttributeNodeNS(null, "entityCertificate");
100 if (entityCertAttr != null) {
101 isEntityCert = XMLHelper.getAttributeValueAsBoolean(entityCertAttr);
102 }
103 if (isEntityCert) {
104 log.debug("Element config flag found indicating entity certificate");
105 }
106
107 try {
108 decodedCerts = X509Util.decodeCertificate(encodedCert);
109 certs.addAll(decodedCerts);
110 if (isEntityCert) {
111 if (decodedCerts.size() == 1) {
112 builder.addPropertyValue("entityCertificate", decodedCerts.iterator().next());
113 } else {
114 throw new FatalBeanException(
115 "Config element indicated an entityCertificate, but multiple certs where decoded");
116 }
117 }
118 } catch (CertificateException e) {
119 throw new FatalBeanException("Unable to create X509 credential, unable to parse certificates", e);
120 }
121 }
122
123 builder.addPropertyValue("certificates", certs);
124 }
125
126
127
128
129
130
131
132
133 protected abstract byte[] getEncodedCertificate(String certConfigContent);
134
135
136
137
138
139
140
141 protected void parseCRLs(Map<QName, List<Element>> configChildren, BeanDefinitionBuilder builder) {
142 List<Element> crlElems = configChildren.get(new QName(SecurityNamespaceHandler.NAMESPACE, "CRL"));
143 if (crlElems == null || crlElems.isEmpty()) {
144 return;
145 }
146
147 log.debug("Parsing x509 credential CRLs");
148 ArrayList<X509CRL> crls = new ArrayList<X509CRL>();
149 byte[] encodedCRL;
150 Collection<X509CRL> decodedCRLs;
151 for (Element crlElem : crlElems) {
152 encodedCRL = getEncodedCRL(DatatypeHelper.safeTrimOrNullString(crlElem.getTextContent()));
153 if (encodedCRL == null) {
154 continue;
155 }
156
157 try {
158 decodedCRLs = X509Util.decodeCRLs(encodedCRL);
159 crls.addAll(decodedCRLs);
160 } catch (CRLException e) {
161 throw new FatalBeanException("Unable to create X509 credential, unable to parse CRLs", e);
162 }
163 }
164
165 builder.addPropertyValue("crls", crls);
166 }
167
168
169
170
171
172
173
174
175 protected abstract byte[] getEncodedCRL(String certCRLContent);
176 }