View Javadoc
1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements. See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership. The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License. You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied. See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.wss4j.dom.saml;
21  
22  import java.security.Principal;
23  import java.util.List;
24  
25  import javax.xml.namespace.QName;
26  
27  import org.w3c.dom.Element;
28  import org.w3c.dom.Node;
29  import org.w3c.dom.Text;
30  import org.apache.wss4j.common.crypto.AlgorithmSuite;
31  import org.apache.wss4j.common.crypto.AlgorithmSuiteValidator;
32  import org.apache.wss4j.common.ext.WSSecurityException;
33  import org.apache.wss4j.common.principal.WSDerivedKeyTokenPrincipal;
34  import org.apache.wss4j.common.saml.SAMLKeyInfo;
35  import org.apache.wss4j.common.saml.SAMLKeyInfoProcessor;
36  import org.apache.wss4j.common.token.SecurityTokenReference;
37  import org.apache.wss4j.dom.WSConstants;
38  import org.apache.wss4j.dom.engine.WSSecurityEngineResult;
39  import org.apache.wss4j.dom.handler.RequestData;
40  import org.apache.wss4j.dom.processor.EncryptedKeyProcessor;
41  import org.apache.wss4j.dom.str.STRParser;
42  import org.apache.wss4j.dom.str.STRParserParameters;
43  import org.apache.wss4j.dom.str.STRParserResult;
44  import org.apache.wss4j.dom.str.SignatureSTRParser;
45  import org.apache.xml.security.utils.XMLUtils;
46  
47  /**
48   * This interface allows the user to plug in custom ways of processing a SAML KeyInfo.
49   */
50  public class WSSSAMLKeyInfoProcessor implements SAMLKeyInfoProcessor {
51  
52      private static final String WST_NS = "http://schemas.xmlsoap.org/ws/2005/02/trust";
53      private static final String WST_NS_05_12 =
54          "http://docs.oasis-open.org/ws-sx/ws-trust/200512";
55  
56      private static final QName BINARY_SECRET =
57          new QName(WST_NS, "BinarySecret");
58      private static final QName BINARY_SECRET_05_12 =
59          new QName(WST_NS_05_12, "BinarySecret");
60  
61      private RequestData data;
62  
63      public WSSSAMLKeyInfoProcessor(RequestData data) {
64          this.data = data;
65      }
66  
67      public SAMLKeyInfo processSAMLKeyInfo(Element keyInfoElement) throws WSSecurityException {
68          //
69          // First try to find an EncryptedKey, BinarySecret or a SecurityTokenReference via DOM
70          //
71          if (keyInfoElement == null) {
72              return null;
73          }
74  
75          Node node = keyInfoElement.getFirstChild();
76          while (node != null) {
77              if (Node.ELEMENT_NODE == node.getNodeType()) {
78                  QName el = new QName(node.getNamespaceURI(), node.getLocalName());
79                  if (el.equals(WSConstants.ENCRYPTED_KEY)) {
80                      EncryptedKeyProcessor proc = new EncryptedKeyProcessor();
81                      List<WSSecurityEngineResult> result =
82                          proc.handleToken((Element)node, data, data.getSamlAlgorithmSuite());
83                      byte[] secret =
84                          (byte[])result.get(0).get(
85                              WSSecurityEngineResult.TAG_SECRET
86                          );
87                      return new SAMLKeyInfo(secret);
88                  } else if (el.equals(BINARY_SECRET) || el.equals(BINARY_SECRET_05_12)) {
89                      Text txt = (Text)node.getFirstChild();
90                      return new SAMLKeyInfo(XMLUtils.decode(txt.getData()));
91                  } else if (SecurityTokenReference.STR_QNAME.equals(el)) {
92                      STRParserParameters parameters = new STRParserParameters();
93                      parameters.setData(data);
94                      parameters.setStrElement((Element)node);
95  
96                      STRParser strParser = new SignatureSTRParser();
97                      STRParserResult parserResult = strParser.parseSecurityTokenReference(parameters);
98                      SAMLKeyInfo samlKeyInfo = new SAMLKeyInfo(parserResult.getCertificates());
99                      samlKeyInfo.setPublicKey(parserResult.getPublicKey());
100                     samlKeyInfo.setSecret(parserResult.getSecretKey());
101 
102                     Principal principal = parserResult.getPrincipal();
103 
104                     // Check for compliance against the defined AlgorithmSuite
105                     AlgorithmSuite algorithmSuite = data.getSamlAlgorithmSuite();
106                     if (algorithmSuite != null && principal instanceof WSDerivedKeyTokenPrincipal) {
107                         AlgorithmSuiteValidator algorithmSuiteValidator = new
108                             AlgorithmSuiteValidator(algorithmSuite);
109 
110                         algorithmSuiteValidator.checkDerivedKeyAlgorithm(
111                             ((WSDerivedKeyTokenPrincipal)principal).getAlgorithm()
112                         );
113                         algorithmSuiteValidator.checkSignatureDerivedKeyLength(
114                             ((WSDerivedKeyTokenPrincipal)principal).getLength()
115                         );
116                     }
117 
118                     return samlKeyInfo;
119                 }
120             }
121             node = node.getNextSibling();
122         }
123 
124         return null;
125     }
126 }