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