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.action;
21  
22  import javax.security.auth.callback.CallbackHandler;
23  
24  import org.apache.wss4j.common.SecurityActionToken;
25  import org.apache.wss4j.common.SignatureActionToken;
26  import org.apache.wss4j.common.crypto.Crypto;
27  import org.apache.wss4j.common.ext.WSPasswordCallback;
28  import org.apache.wss4j.common.ext.WSSecurityException;
29  import org.apache.wss4j.common.saml.SamlAssertionWrapper;
30  import org.apache.wss4j.common.saml.SAMLCallback;
31  import org.apache.wss4j.common.saml.SAMLUtil;
32  import org.apache.wss4j.dom.WSConstants;
33  import org.apache.wss4j.dom.handler.RequestData;
34  import org.apache.wss4j.dom.handler.WSHandler;
35  import org.apache.wss4j.dom.handler.WSHandlerConstants;
36  import org.apache.wss4j.dom.saml.WSSecSignatureSAML;
37  
38  public class SAMLTokenSignedAction implements Action {
39  
40      private static final org.slf4j.Logger LOG =
41          org.slf4j.LoggerFactory.getLogger(SAMLTokenSignedAction.class);
42  
43      public void execute(WSHandler handler, SecurityActionToken actionToken, RequestData reqData)
44              throws WSSecurityException {
45          Crypto crypto = null;
46  
47          // it is possible and legal that we do not have a signature crypto here - thus ignore the exception.
48          // This is usually the case for the SAML option "sender vouches". In this case no user crypto is
49          // required.
50          try {
51              crypto = handler.loadSignatureCrypto(reqData);
52          } catch (Exception ex) {
53              LOG.debug(ex.getMessage(), ex);
54          }
55  
56          CallbackHandler samlCallbackHandler =
57                  handler.getCallbackHandler(
58                      WSHandlerConstants.SAML_CALLBACK_CLASS,
59                      WSHandlerConstants.SAML_CALLBACK_REF,
60                      reqData
61                  );
62          if (samlCallbackHandler == null) {
63              throw new WSSecurityException(
64                  WSSecurityException.ErrorCode.FAILURE,
65                  "noSAMLCallbackHandler"
66              );
67          }
68          SAMLCallback samlCallback = new SAMLCallback();
69          SAMLUtil.doSAMLCallback(samlCallbackHandler, samlCallback);
70  
71          SamlAssertionWrapper samlAssertion = new SamlAssertionWrapper(samlCallback);
72          if (samlCallback.isSignAssertion()) {
73              samlAssertion.signAssertion(
74                  samlCallback.getIssuerKeyName(),
75                  samlCallback.getIssuerKeyPassword(),
76                  samlCallback.getIssuerCrypto(),
77                  samlCallback.isSendKeyValue(),
78                  samlCallback.getCanonicalizationAlgorithm(),
79                  samlCallback.getSignatureAlgorithm(),
80                  samlCallback.getSignatureDigestAlgorithm()
81              );
82          }
83          WSSecSignatureSAML wsSign = new WSSecSignatureSAML(reqData.getSecHeader());
84          wsSign.setIdAllocator(reqData.getWssConfig().getIdAllocator());
85          wsSign.setAddInclusivePrefixes(reqData.isAddInclusivePrefixes());
86          wsSign.setWsDocInfo(reqData.getWsDocInfo());
87          wsSign.setExpandXopInclude(reqData.isExpandXopInclude());
88          wsSign.setSignatureProvider(reqData.getSignatureProvider());
89  
90          CallbackHandler callbackHandler =
91              handler.getPasswordCallbackHandler(reqData);
92  
93          SignatureActionToken signatureToken = null;
94          if (actionToken instanceof SignatureActionToken) {
95              signatureToken = (SignatureActionToken)actionToken;
96          }
97          if (signatureToken == null) {
98              signatureToken = reqData.getSignatureToken();
99          }
100 
101         WSPasswordCallback passwordCallback =
102             handler.getPasswordCB(signatureToken.getUser(), WSConstants.ST_SIGNED, callbackHandler, reqData);
103         wsSign.setUserInfo(signatureToken.getUser(), passwordCallback.getPassword());
104 
105         if (signatureToken.getKeyIdentifierId() != 0) {
106             wsSign.setKeyIdentifierType(signatureToken.getKeyIdentifierId());
107         }
108         if (signatureToken.getSignatureAlgorithm() != null) {
109             wsSign.setSignatureAlgorithm(signatureToken.getSignatureAlgorithm());
110         }
111         if (signatureToken.getDigestAlgorithm() != null) {
112             wsSign.setDigestAlgo(signatureToken.getDigestAlgorithm());
113         }
114         if (signatureToken.getC14nAlgorithm() != null) {
115             wsSign.setSigCanonicalization(signatureToken.getC14nAlgorithm());
116         }
117         if (signatureToken.getKeyInfoElement() != null) {
118             wsSign.setCustomKeyInfoElement(signatureToken.getKeyInfoElement());
119         }
120 
121         if (!signatureToken.getParts().isEmpty()) {
122             wsSign.getParts().addAll(signatureToken.getParts());
123         }
124 
125         try {
126             wsSign.build(
127                     crypto,
128                     samlAssertion,
129                     samlCallback.getIssuerCrypto(),
130                     samlCallback.getIssuerKeyName(),
131                     samlCallback.getIssuerKeyPassword());
132 
133             reqData.getSignatureValues().add(wsSign.getSignatureValue());
134             byte[] signatureValue = samlAssertion.getSignatureValue();
135             if (signatureValue != null) {
136                 reqData.getSignatureValues().add(signatureValue);
137             }
138         } catch (WSSecurityException e) {
139             throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e, "empty",
140                                           new Object[] {"Error when signing the SAML token: "});
141         }
142     }
143 
144 }