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.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.derivedKey.ConversationConstants;
33  import org.apache.wss4j.common.ext.WSPasswordCallback;
34  import org.apache.wss4j.common.ext.WSSecurityException;
35  import org.apache.wss4j.common.util.KeyUtils;
36  import org.apache.wss4j.dom.WSConstants;
37  import org.apache.wss4j.dom.handler.RequestData;
38  import org.apache.wss4j.dom.handler.WSHandler;
39  import org.apache.wss4j.dom.message.WSSecDKEncrypt;
40  import org.apache.wss4j.dom.util.WSSecurityUtil;
41  import org.w3c.dom.Document;
42  import org.w3c.dom.Element;
43  import org.w3c.dom.Node;
44  
45  public class EncryptionDerivedAction extends AbstractDerivedAction implements Action {
46  
47      public void execute(WSHandler handler, SecurityActionToken actionToken, RequestData reqData)
48              throws WSSecurityException {
49          CallbackHandler callbackHandler = reqData.getCallbackHandler();
50          if (callbackHandler == null) {
51              callbackHandler = handler.getPasswordCallbackHandler(reqData);
52          }
53  
54          EncryptionActionToken encryptionToken = null;
55          if (actionToken instanceof EncryptionActionToken) {
56              encryptionToken = (EncryptionActionToken)actionToken;
57          }
58          if (encryptionToken == null) {
59              encryptionToken = reqData.getEncryptionToken();
60          }
61  
62          WSPasswordCallback passwordCallback =
63              handler.getPasswordCB(encryptionToken.getUser(), WSConstants.DKT_ENCR, callbackHandler, reqData);
64          WSSecDKEncrypt wsEncrypt = new WSSecDKEncrypt(reqData.getSecHeader());
65          wsEncrypt.setIdAllocator(reqData.getWssConfig().getIdAllocator());
66          wsEncrypt.setWsDocInfo(reqData.getWsDocInfo());
67          wsEncrypt.setExpandXopInclude(reqData.isExpandXopInclude());
68  
69          if (encryptionToken.getKeyIdentifierId() != 0) {
70              wsEncrypt.setKeyIdentifierType(encryptionToken.getKeyIdentifierId());
71          }
72  
73          if (encryptionToken.getSymmetricAlgorithm() != null) {
74              wsEncrypt.setSymmetricEncAlgorithm(encryptionToken.getSymmetricAlgorithm());
75          }
76          wsEncrypt.setUserInfo(encryptionToken.getUser(), passwordCallback.getPassword());
77  
78          if (reqData.isUse200512Namespace()) {
79              wsEncrypt.setWscVersion(ConversationConstants.VERSION_05_12);
80          } else {
81              wsEncrypt.setWscVersion(ConversationConstants.VERSION_05_02);
82          }
83  
84          if (encryptionToken.getDerivedKeyLength() > 0) {
85              wsEncrypt.setDerivedKeyLength(encryptionToken.getDerivedKeyLength());
86          }
87  
88          Document doc = reqData.getSecHeader().getSecurityHeaderElement().getOwnerDocument();
89          String derivedKeyTokenReference = encryptionToken.getDerivedKeyTokenReference();
90          Element tokenElement = null;
91          SecretKey symmetricKey = null;
92          if ("EncryptedKey".equals(derivedKeyTokenReference)) {
93              if (reqData.getSignatureToken() == null || reqData.getSignatureToken().getKey() == null
94                  || reqData.getSignatureToken().getKeyIdentifier() == null) {
95                  String symmetricKeyAlgorithm = encryptionToken.getSymmetricAlgorithm();
96                  if (symmetricKeyAlgorithm == null) {
97                      symmetricKeyAlgorithm = WSConstants.AES_128;
98                  }
99                  KeyGenerator keyGen = KeyUtils.getKeyGenerator(symmetricKeyAlgorithm);
100                 symmetricKey = keyGen.generateKey();
101             }
102 
103             tokenElement = setupEncryptedKeyTokenReference(reqData, encryptionToken, wsEncrypt, symmetricKey);
104         } else if ("SecurityContextToken".equals(derivedKeyTokenReference)) {
105             tokenElement = setupSCTTokenReference(reqData, encryptionToken, wsEncrypt, passwordCallback, doc);
106         }
107 
108         wsEncrypt.setAttachmentCallbackHandler(reqData.getAttachmentCallbackHandler());
109         wsEncrypt.setStoreBytesInAttachment(reqData.isStoreBytesInAttachment());
110 
111         try {
112             List<WSEncryptionPart> parts = encryptionToken.getParts();
113             if (parts != null && !parts.isEmpty()) {
114                 wsEncrypt.getParts().addAll(parts);
115             } else {
116                 wsEncrypt.getParts().add(WSSecurityUtil.getDefaultEncryptionPart(doc));
117             }
118 
119             byte[] key = getKey(reqData.getSignatureToken(), passwordCallback, symmetricKey);
120             wsEncrypt.prepare(key);
121 
122             Element externRefList = wsEncrypt.encrypt();
123 
124             // Put the DerivedKeyToken Element in the right place in the security header
125             Node nextSibling = null;
126             if (tokenElement == null
127                 && "EncryptedKey".equals(encryptionToken.getDerivedKeyTokenReference())) {
128                 nextSibling = findEncryptedKeySibling(reqData);
129             } else if (tokenElement == null
130                 && "SecurityContextToken".equals(encryptionToken.getDerivedKeyTokenReference())) {
131                 nextSibling = findSCTSibling(reqData);
132             }
133             if (nextSibling == null) {
134                 wsEncrypt.prependDKElementToHeader();
135             } else {
136                 reqData.getSecHeader().getSecurityHeaderElement().insertBefore(
137                     wsEncrypt.getdktElement(), nextSibling);
138             }
139 
140             // Add the ReferenceList to the security header
141             wsEncrypt.addExternalRefElement(externRefList);
142 
143             if (tokenElement != null) {
144                 WSSecurityUtil.prependChildElement(reqData.getSecHeader().getSecurityHeaderElement(), tokenElement);
145             }
146 
147             wsEncrypt.clean();
148         } catch (WSSecurityException e) {
149             throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e,
150                                           "empty", new Object[] {"Error during Encryption: "});
151         }
152     }
153 
154     private Element setupSCTTokenReference(
155                                         RequestData reqData, EncryptionActionToken encryptionToken,
156                                         WSSecDKEncrypt wsEncrypt, WSPasswordCallback passwordCallback,
157                                         Document doc
158         ) throws WSSecurityException {
159         if (reqData.getSignatureToken() != null && reqData.getSignatureToken().getKey() != null
160             && reqData.getSignatureToken().getKeyIdentifier() != null) {
161             setupSCTReference(wsEncrypt, reqData.getSignatureToken(), reqData.isUse200512Namespace());
162             return null;
163         } else {
164             return setupSCTReference(wsEncrypt, passwordCallback, encryptionToken, reqData.isUse200512Namespace(), doc);
165         }
166     }
167 
168     private Element setupEncryptedKeyTokenReference(
169         RequestData reqData, EncryptionActionToken encryptionToken,
170         WSSecDKEncrypt wsEncrypt, SecretKey symmetricKey
171     ) throws WSSecurityException {
172         if (symmetricKey == null) {
173             setupEKReference(wsEncrypt, reqData.getSignatureToken());
174             return null;
175         } else {
176             return setupEKReference(wsEncrypt, reqData.getSecHeader(), encryptionToken, null, null, symmetricKey);
177         }
178     }
179 
180     private byte[] getKey(SignatureActionToken encryptionToken,
181                           WSPasswordCallback passwordCallback,
182                           SecretKey symmetricKey) throws WSSecurityException {
183         if (symmetricKey != null) {
184             return symmetricKey.getEncoded();
185         } else if (encryptionToken != null && encryptionToken.getKey() != null
186             && encryptionToken.getKeyIdentifier() != null) {
187             return encryptionToken.getKey();
188         } else {
189             return passwordCallback.getKey();
190         }
191     }
192 }