1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.wss4j.dom.action;
21
22 import java.util.List;
23
24 import javax.crypto.KeyGenerator;
25 import javax.crypto.SecretKey;
26 import javax.security.auth.callback.CallbackHandler;
27
28 import org.apache.wss4j.common.EncryptionActionToken;
29 import org.apache.wss4j.common.SecurityActionToken;
30 import org.apache.wss4j.common.SignatureActionToken;
31 import org.apache.wss4j.common.WSEncryptionPart;
32 import org.apache.wss4j.common.crypto.Crypto;
33 import org.apache.wss4j.common.derivedKey.ConversationConstants;
34 import org.apache.wss4j.common.ext.WSPasswordCallback;
35 import org.apache.wss4j.common.ext.WSSecurityException;
36 import org.apache.wss4j.common.util.KeyUtils;
37 import org.apache.wss4j.dom.WSConstants;
38 import org.apache.wss4j.dom.handler.RequestData;
39 import org.apache.wss4j.dom.handler.WSHandler;
40 import org.apache.wss4j.dom.message.WSSecDKSign;
41 import org.apache.wss4j.dom.util.WSSecurityUtil;
42 import org.w3c.dom.Document;
43 import org.w3c.dom.Element;
44 import org.w3c.dom.Node;
45
46 public class SignatureDerivedAction extends AbstractDerivedAction implements Action {
47
48 public void execute(WSHandler handler, SecurityActionToken actionToken, RequestData reqData)
49 throws WSSecurityException {
50 CallbackHandler callbackHandler = reqData.getCallbackHandler();
51 if (callbackHandler == null) {
52 callbackHandler = handler.getPasswordCallbackHandler(reqData);
53 }
54
55 SignatureActionToken signatureToken = null;
56 if (actionToken instanceof SignatureActionToken) {
57 signatureToken = (SignatureActionToken)actionToken;
58 }
59 if (signatureToken == null) {
60 signatureToken = reqData.getSignatureToken();
61 }
62
63 WSPasswordCallback passwordCallback =
64 handler.getPasswordCB(signatureToken.getUser(), WSConstants.DKT_SIGN, callbackHandler, reqData);
65 WSSecDKSign wsSign = new WSSecDKSign(reqData.getSecHeader());
66 wsSign.setIdAllocator(reqData.getWssConfig().getIdAllocator());
67 wsSign.setAddInclusivePrefixes(reqData.isAddInclusivePrefixes());
68 wsSign.setWsDocInfo(reqData.getWsDocInfo());
69 wsSign.setExpandXopInclude(reqData.isExpandXopInclude());
70
71 if (signatureToken.getSignatureAlgorithm() != null) {
72 wsSign.setSignatureAlgorithm(signatureToken.getSignatureAlgorithm());
73 }
74 if (signatureToken.getDigestAlgorithm() != null) {
75 wsSign.setDigestAlgorithm(signatureToken.getDigestAlgorithm());
76 }
77 if (signatureToken.getC14nAlgorithm() != null) {
78 wsSign.setSigCanonicalization(signatureToken.getC14nAlgorithm());
79 }
80 wsSign.setUserInfo(signatureToken.getUser(), passwordCallback.getPassword());
81
82 if (reqData.isUse200512Namespace()) {
83 wsSign.setWscVersion(ConversationConstants.VERSION_05_12);
84 } else {
85 wsSign.setWscVersion(ConversationConstants.VERSION_05_02);
86 }
87
88 if (signatureToken.getDerivedKeyLength() > 0) {
89 wsSign.setDerivedKeyLength(signatureToken.getDerivedKeyLength());
90 }
91
92 Document doc = reqData.getSecHeader().getSecurityHeaderElement().getOwnerDocument();
93
94 String derivedKeyTokenReference = signatureToken.getDerivedKeyTokenReference();
95 Element tokenElement = null;
96 SecretKey symmetricKey = null;
97 if ("EncryptedKey".equals(derivedKeyTokenReference)) {
98 if (reqData.getEncryptionToken() == null || reqData.getEncryptionToken().getKey() == null
99 || reqData.getEncryptionToken().getKeyIdentifier() == null) {
100 String symmetricKeyAlgorithm = WSConstants.AES_128;
101 KeyGenerator keyGen = KeyUtils.getKeyGenerator(symmetricKeyAlgorithm);
102 symmetricKey = keyGen.generateKey();
103 }
104
105 tokenElement = setupEncryptedKeyTokenReference(reqData, signatureToken, wsSign, symmetricKey);
106 } else if ("SecurityContextToken".equals(derivedKeyTokenReference)) {
107 tokenElement = setupSCTTokenReference(reqData, signatureToken, wsSign, passwordCallback, doc);
108 } else {
109
110 if (signatureToken.getDerivedKeyIdentifier() != 0) {
111 wsSign.setKeyIdentifierType(signatureToken.getDerivedKeyIdentifier());
112 } else {
113 wsSign.setKeyIdentifierType(WSConstants.THUMBPRINT_IDENTIFIER);
114 }
115
116 wsSign.setCrypto(signatureToken.getCrypto());
117 }
118
119 wsSign.setAttachmentCallbackHandler(reqData.getAttachmentCallbackHandler());
120 wsSign.setStoreBytesInAttachment(reqData.isStoreBytesInAttachment());
121
122 try {
123 List<WSEncryptionPart> parts = signatureToken.getParts();
124 if (parts != null && !parts.isEmpty()) {
125 wsSign.getParts().addAll(parts);
126 } else {
127 wsSign.getParts().add(WSSecurityUtil.getDefaultEncryptionPart(doc));
128 }
129
130 byte[] key = getKey(signatureToken, reqData.getEncryptionToken(), passwordCallback, symmetricKey);
131 wsSign.prepare(key);
132
133 List<javax.xml.crypto.dsig.Reference> referenceList = wsSign.addReferencesToSign(wsSign.getParts());
134
135
136 Node nextSibling = null;
137 if (tokenElement == null
138 && "EncryptedKey".equals(signatureToken.getDerivedKeyTokenReference())) {
139 nextSibling = findEncryptedKeySibling(reqData);
140 } else if (tokenElement == null
141 && "SecurityContextToken".equals(signatureToken.getDerivedKeyTokenReference())) {
142 nextSibling = findSCTSibling(reqData);
143 }
144
145 if (nextSibling == null) {
146 wsSign.computeSignature(referenceList);
147 } else {
148 wsSign.computeSignature(referenceList, true, (Element)nextSibling);
149 }
150
151 if (nextSibling == null) {
152 wsSign.prependDKElementToHeader();
153 } else {
154 reqData.getSecHeader().getSecurityHeaderElement().insertBefore(
155 wsSign.getdktElement(), wsSign.getSignatureElement());
156 }
157
158 if (tokenElement != null) {
159 WSSecurityUtil.prependChildElement(reqData.getSecHeader().getSecurityHeaderElement(), tokenElement);
160 }
161
162 reqData.getSignatureValues().add(wsSign.getSignatureValue());
163
164 wsSign.clean();
165 } catch (WSSecurityException e) {
166 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e, "empty",
167 new Object[] {"Error during Signature: "});
168 }
169 }
170
171 private Element setupEncryptedKeyTokenReference(
172 RequestData reqData, SignatureActionToken signatureToken,
173 WSSecDKSign wsSign, SecretKey symmetricKey
174 ) throws WSSecurityException {
175
176 if (symmetricKey == null) {
177 setupEKReference(wsSign, reqData.getEncryptionToken());
178 return null;
179 } else {
180 return setupEKReference(wsSign, reqData.getSecHeader(), signatureToken, null, null, symmetricKey);
181 }
182 }
183
184 private Element setupSCTTokenReference(
185 RequestData reqData, SignatureActionToken signatureToken,
186 WSSecDKSign wsSign, WSPasswordCallback passwordCallback,
187 Document doc
188 ) throws WSSecurityException {
189 if (reqData.getEncryptionToken() != null && reqData.getEncryptionToken().getKey() != null
190 && reqData.getEncryptionToken().getKeyIdentifier() != null) {
191 setupSCTReference(wsSign, reqData.getEncryptionToken(), reqData.isUse200512Namespace());
192 return null;
193 } else {
194 return setupSCTReference(wsSign, passwordCallback, signatureToken, reqData.isUse200512Namespace(), doc);
195 }
196 }
197
198 private byte[] getKey(SignatureActionToken signatureToken,
199 EncryptionActionToken encryptionToken,
200 WSPasswordCallback passwordCallback,
201 SecretKey symmetricKey) throws WSSecurityException {
202 String derivedKeyTokenReference = signatureToken.getDerivedKeyTokenReference();
203 boolean directReference = !("EncryptedKey".equals(derivedKeyTokenReference)
204 || "SecurityContextToken".equals(derivedKeyTokenReference));
205
206 if (symmetricKey != null) {
207 return symmetricKey.getEncoded();
208 } else if (directReference) {
209 byte[] key = null;
210 if (passwordCallback.getKey() != null) {
211 key = passwordCallback.getKey();
212 } else if (signatureToken.getKey() != null) {
213 key = signatureToken.getKey();
214 } else if (signatureToken.getCrypto() != null) {
215 Crypto crypto = signatureToken.getCrypto();
216 key = crypto.getPrivateKey(signatureToken.getUser(), passwordCallback.getPassword()).getEncoded();
217 }
218 return key;
219 } else if (encryptionToken != null && encryptionToken.getKey() != null
220 && encryptionToken.getKeyIdentifier() != null) {
221 return encryptionToken.getKey();
222 } else {
223 return passwordCallback.getKey();
224 }
225 }
226 }