View Javadoc

1   /*
2    * Licensed to the University Corporation for Advanced Internet Development, 
3    * Inc. (UCAID) under one or more contributor license agreements.  See the 
4    * NOTICE file distributed with this work for additional information regarding
5    * copyright ownership. The UCAID licenses this file to You under the Apache 
6    * License, Version 2.0 (the "License"); you may not use this file except in 
7    * compliance with the License.  You may obtain a copy of the License at
8    *
9    *    http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
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   * Base class for credential beans.
43   */
44  public abstract class AbstractCredentialBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
45      
46      /** Class logger. */
47      private final Logger log = LoggerFactory.getLogger(AbstractCredentialBeanDefinitionParser.class);
48  
49      /** {@inheritDoc} */
50      protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext) {
51          return element.getAttributeNS(null, "id");
52      }
53      
54      /**
55       * Parse the credential element attributes.
56       * 
57       * @param element credential element
58       * @param builder bean definition builder
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       * Parses the common elements from the credential configuration.
76       * 
77       * @param configChildren children of the credential element
78       * @param builder credential build
79       */
80      protected void parseCommon(Map<QName, List<Element>> configChildren, BeanDefinitionBuilder builder) {
81          parseKeyNames(configChildren, builder);
82      }
83  
84      /**
85       * Parses the key names from the credential configuration.
86       * 
87       * @param configChildren children of the credential element
88       * @param builder credential build
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      * Parses the private key from the credential configuration.
111      * 
112      * @param configChildren children of the credential element
113      * @param builder credential build
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      * Extracts the private key bytes from the content of the PrivateKey configuration element.
139      * 
140      * @param keyConfigContent content of the Private configuration element
141      * 
142      * @return private key bytes
143      */
144     protected abstract byte[] getEncodedPrivateKey(String keyConfigContent);
145 
146 }