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 java.util.ArrayList;
23  import java.util.List;
24  
25  import javax.security.auth.callback.CallbackHandler;
26  
27  import org.apache.wss4j.common.SecurityActionToken;
28  import org.apache.wss4j.common.SignatureActionToken;
29  import org.apache.wss4j.common.WSEncryptionPart;
30  import org.apache.wss4j.common.ext.WSPasswordCallback;
31  import org.apache.wss4j.common.ext.WSSecurityException;
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.message.WSSecSignature;
36  import org.apache.wss4j.dom.util.WSSecurityUtil;
37  import org.w3c.dom.Document;
38  import org.w3c.dom.Element;
39  import org.w3c.dom.Node;
40  
41  public class SignatureAction implements Action {
42  
43      public void execute(WSHandler handler, SecurityActionToken actionToken, RequestData reqData)
44              throws WSSecurityException {
45          CallbackHandler callbackHandler = reqData.getCallbackHandler();
46          if (callbackHandler == null) {
47              callbackHandler = handler.getPasswordCallbackHandler(reqData);
48          }
49  
50          SignatureActionToken signatureToken = null;
51          if (actionToken instanceof SignatureActionToken) {
52              signatureToken = (SignatureActionToken)actionToken;
53          }
54          if (signatureToken == null) {
55              signatureToken = reqData.getSignatureToken();
56          }
57  
58          WSPasswordCallback passwordCallback =
59              handler.getPasswordCB(signatureToken.getUser(), WSConstants.SIGN, callbackHandler, reqData);
60          WSSecSignature wsSign = new WSSecSignature(reqData.getSecHeader());
61          wsSign.setIdAllocator(reqData.getWssConfig().getIdAllocator());
62          wsSign.setAddInclusivePrefixes(reqData.isAddInclusivePrefixes());
63          wsSign.setWsDocInfo(reqData.getWsDocInfo());
64          wsSign.setExpandXopInclude(reqData.isExpandXopInclude());
65          wsSign.setSignatureProvider(reqData.getSignatureProvider());
66  
67          if (signatureToken.getKeyIdentifierId() != 0) {
68              wsSign.setKeyIdentifierType(signatureToken.getKeyIdentifierId());
69          }
70          if (signatureToken.getSignatureAlgorithm() != null) {
71              wsSign.setSignatureAlgorithm(signatureToken.getSignatureAlgorithm());
72          }
73          if (signatureToken.getDigestAlgorithm() != null) {
74              wsSign.setDigestAlgo(signatureToken.getDigestAlgorithm());
75          }
76          if (signatureToken.getC14nAlgorithm() != null) {
77              wsSign.setSigCanonicalization(signatureToken.getC14nAlgorithm());
78          }
79  
80          wsSign.setIncludeSignatureToken(signatureToken.isIncludeToken());
81  
82          wsSign.setUserInfo(signatureToken.getUser(), passwordCallback.getPassword());
83          wsSign.setUseSingleCertificate(signatureToken.isUseSingleCert());
84  
85          if (passwordCallback.getKey() != null) {
86              wsSign.setSecretKey(passwordCallback.getKey());
87          } else if (signatureToken.getKey() != null) {
88              wsSign.setSecretKey(signatureToken.getKey());
89          } else if (signatureToken.getUser() == null) {
90              throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "noSignatureUser");
91          }
92  
93          if (signatureToken.getTokenId() != null) {
94              wsSign.setCustomTokenId(signatureToken.getTokenId());
95          }
96          if (signatureToken.getTokenType() != null) {
97              wsSign.setCustomTokenValueType(signatureToken.getTokenType());
98          }
99          if (signatureToken.getSha1Value() != null) {
100             wsSign.setEncrKeySha1value(signatureToken.getSha1Value());
101         }
102         if (signatureToken.getKeyInfoElement() != null) {
103             wsSign.setCustomKeyInfoElement(signatureToken.getKeyInfoElement());
104         }
105 
106         wsSign.setAttachmentCallbackHandler(reqData.getAttachmentCallbackHandler());
107         wsSign.setStoreBytesInAttachment(reqData.isStoreBytesInAttachment());
108 
109         try {
110             wsSign.prepare(signatureToken.getCrypto());
111 
112             Element siblingElementToPrepend = null;
113             boolean signBST = false;
114             for (WSEncryptionPart part : signatureToken.getParts()) {
115                 if ("STRTransform".equals(part.getName()) && part.getId() == null) {
116                     part.setId(wsSign.getSecurityTokenReferenceURI());
117                 } else if (reqData.isAppendSignatureAfterTimestamp()
118                         && WSConstants.WSU_NS.equals(part.getNamespace())
119                         && "Timestamp".equals(part.getName())) {
120                     int originalSignatureActionIndex =
121                         reqData.getOriginalSignatureActionPosition();
122                     // Need to figure out where to put the Signature Element in the header
123                     if (originalSignatureActionIndex > 0) {
124                         Element secHeader = reqData.getSecHeader().getSecurityHeaderElement();
125                         Node lastChild = secHeader.getLastChild();
126                         int count = 0;
127                         while (lastChild != null && count < originalSignatureActionIndex) {
128                             while (lastChild != null && lastChild.getNodeType() != Node.ELEMENT_NODE) {
129                                 lastChild = lastChild.getPreviousSibling();
130                             }
131                             count++;
132                         }
133                         if (lastChild instanceof Element) {
134                             siblingElementToPrepend = (Element)lastChild;
135                         }
136                     }
137                 } else if (WSConstants.WSSE_NS.equals(part.getNamespace())
138                     && WSConstants.BINARY_TOKEN_LN.equals(part.getName())) {
139                     signBST = true;
140                 }  else if ("KeyInfo".equals(part.getName()) && WSConstants.SIG_NS.equals(part.getNamespace())
141                     && part.getElement() == null) {
142                     // Special code to sign the KeyInfo
143                     part.setId(wsSign.getKeyInfoUri());
144                     break;
145                 }
146             }
147 
148             if (signBST) {
149                 wsSign.prependBSTElementToHeader();
150             }
151 
152             List<WSEncryptionPart> parts = signatureToken.getParts();
153             if (parts == null || parts.isEmpty()) {
154                 parts = new ArrayList<>(1);
155                 Document doc = reqData.getSecHeader().getSecurityHeaderElement().getOwnerDocument();
156                 parts.add(WSSecurityUtil.getDefaultEncryptionPart(doc));
157             }
158 
159             List<javax.xml.crypto.dsig.Reference> referenceList = wsSign.addReferencesToSign(parts);
160 
161             if (signBST
162                 || reqData.isAppendSignatureAfterTimestamp() && siblingElementToPrepend == null) {
163                 wsSign.computeSignature(referenceList, false, null);
164             } else {
165                 wsSign.computeSignature(referenceList, true, siblingElementToPrepend);
166             }
167 
168             if (!signBST) {
169                 wsSign.prependBSTElementToHeader();
170             }
171             reqData.getSignatureValues().add(wsSign.getSignatureValue());
172         } catch (WSSecurityException e) {
173             throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e, "empty",
174                                           new Object[] {"Error during Signature: "});
175         }
176     }
177 
178 }