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