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.KeyException;
20 import java.security.PrivateKey;
21 import java.util.ArrayList;
22 import java.util.List;
23 import java.util.Map;
24
25 import javax.xml.namespace.QName;
26
27 import org.opensaml.xml.security.SecurityHelper;
28 import org.opensaml.xml.security.credential.UsageType;
29 import org.opensaml.xml.util.DatatypeHelper;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32 import org.springframework.beans.FatalBeanException;
33 import org.springframework.beans.factory.support.AbstractBeanDefinition;
34 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
35 import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
36 import org.springframework.beans.factory.xml.ParserContext;
37 import org.w3c.dom.Element;
38
39
40
41
42
43 public abstract class AbstractCredentialBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
44
45
46 private final Logger log = LoggerFactory.getLogger(AbstractCredentialBeanDefinitionParser.class);
47
48
49 protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext) {
50 return element.getAttributeNS(null, "id");
51 }
52
53
54
55
56
57
58
59 protected void parseAttributes(Element element, BeanDefinitionBuilder builder) {
60 String usage = DatatypeHelper.safeTrimOrNullString(element.getAttributeNS(null, "usage"));
61 if (usage != null) {
62 builder.addPropertyValue("usageType", UsageType.valueOf(usage.toUpperCase()));
63 } else {
64 builder.addPropertyValue("usageType", UsageType.UNSPECIFIED);
65 }
66
67 String entityID = DatatypeHelper.safeTrimOrNullString(element.getAttributeNS(null, "entityID"));
68 if (entityID != null) {
69 builder.addPropertyValue("entityID", entityID);
70 }
71 }
72
73
74
75
76
77
78
79 protected void parseCommon(Map<QName, List<Element>> configChildren, BeanDefinitionBuilder builder) {
80 parseKeyNames(configChildren, builder);
81 }
82
83
84
85
86
87
88
89 protected void parseKeyNames(Map<QName, List<Element>> configChildren, BeanDefinitionBuilder builder) {
90 log.debug("Parsing credential key names");
91 List<Element> keyNameElems = configChildren.get(new QName(SecurityNamespaceHandler.NAMESPACE, "KeyName"));
92 if (keyNameElems == null || keyNameElems.isEmpty()) {
93 return;
94 }
95
96 String keyName;
97 ArrayList<String> keyNames = new ArrayList<String>();
98 for (Element keyNameElem : keyNameElems) {
99 keyName = DatatypeHelper.safeTrimOrNullString(keyNameElem.getTextContent());
100 if (keyName != null) {
101 keyNames.add(keyName);
102 }
103 }
104
105 builder.addPropertyValue("keyNames", keyNames);
106 }
107
108
109
110
111
112
113
114 protected void parsePrivateKey(Map<QName, List<Element>> configChildren, BeanDefinitionBuilder builder) {
115 List<Element> keyElems = configChildren.get(new QName(SecurityNamespaceHandler.NAMESPACE, "PrivateKey"));
116 if (keyElems == null || keyElems.isEmpty()) {
117 return;
118 }
119
120 log.debug("Parsing credential private key");
121 Element privKeyElem = keyElems.get(0);
122 byte[] encodedKey = getEncodedPrivateKey(DatatypeHelper.safeTrimOrNullString(privKeyElem.getTextContent()));
123 String keyPassword = DatatypeHelper.safeTrimOrNullString(privKeyElem.getAttributeNS(null, "password"));
124 char[] keyPasswordCharArray = null;
125 if (keyPassword != null) {
126 keyPasswordCharArray = keyPassword.toCharArray();
127 }
128 try {
129 PrivateKey privKey = SecurityHelper.decodePrivateKey(encodedKey, keyPasswordCharArray);
130 builder.addPropertyValue("privateKey", privKey);
131 } catch (KeyException e) {
132 throw new FatalBeanException("Unable to create credential, unable to parse private key", e);
133 }
134 }
135
136
137
138
139
140
141
142
143 protected abstract byte[] getEncodedPrivateKey(String keyConfigContent);
144
145 }