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.message;
21  
22  import java.io.IOException;
23  import java.security.spec.AlgorithmParameterSpec;
24  import java.util.ArrayList;
25  import java.util.HashMap;
26  import java.util.List;
27  import java.util.Map;
28  
29  import javax.crypto.BadPaddingException;
30  import javax.crypto.Cipher;
31  import javax.crypto.IllegalBlockSizeException;
32  import javax.crypto.SecretKey;
33  import javax.security.auth.callback.Callback;
34  import javax.security.auth.callback.CallbackHandler;
35  import javax.security.auth.callback.UnsupportedCallbackException;
36  
37  import org.apache.wss4j.common.WSEncryptionPart;
38  import org.apache.wss4j.common.ext.Attachment;
39  import org.apache.wss4j.common.ext.AttachmentRequestCallback;
40  import org.apache.wss4j.common.ext.AttachmentResultCallback;
41  import org.apache.wss4j.common.ext.WSSecurityException;
42  import org.apache.wss4j.common.util.AttachmentUtils;
43  import org.apache.wss4j.common.util.XMLUtils;
44  import org.apache.wss4j.dom.WSConstants;
45  import org.apache.wss4j.dom.WSDocInfo;
46  import org.apache.wss4j.dom.WsuIdAllocator;
47  import org.apache.wss4j.dom.callback.CallbackLookup;
48  import org.apache.wss4j.dom.callback.DOMCallbackLookup;
49  import org.apache.wss4j.dom.util.WSSecurityUtil;
50  import org.apache.xml.security.algorithms.JCEMapper;
51  import org.apache.xml.security.encryption.AbstractSerializer;
52  import org.apache.xml.security.encryption.EncryptedData;
53  import org.apache.xml.security.encryption.Serializer;
54  import org.apache.xml.security.encryption.TransformSerializer;
55  import org.apache.xml.security.encryption.XMLCipher;
56  import org.apache.xml.security.encryption.XMLCipherUtil;
57  import org.apache.xml.security.encryption.XMLEncryptionException;
58  import org.apache.xml.security.keys.KeyInfo;
59  import org.apache.xml.security.stax.ext.XMLSecurityConstants;
60  import org.apache.xml.security.utils.EncryptionConstants;
61  import org.w3c.dom.Attr;
62  import org.w3c.dom.Document;
63  import org.w3c.dom.Element;
64  import org.w3c.dom.NamedNodeMap;
65  import org.w3c.dom.Node;
66  import org.w3c.dom.NodeList;
67  
68  /**
69   * A class to encrypt references.
70   */
71  public class Encryptor {
72  
73      private Document doc;
74      private WSSecHeader securityHeader;
75      private WsuIdAllocator idAllocator;
76      private CallbackLookup callbackLookup;
77      private CallbackHandler attachmentCallbackHandler;
78      private boolean storeBytesInAttachment;
79      private Serializer encryptionSerializer;
80      private boolean expandXopInclude;
81      private WSDocInfo wsDocInfo;
82  
83      public List<String> doEncryption(
84          KeyInfo keyInfo,
85          SecretKey secretKey,
86          String encryptionAlgorithm,
87          List<WSEncryptionPart> references,
88          List<Element> attachmentEncryptedDataElements
89      ) throws WSSecurityException {
90  
91          XMLCipher xmlCipher = null;
92          try {
93              if (encryptionSerializer != null) {
94                  xmlCipher = XMLCipher.getInstance(encryptionSerializer, encryptionAlgorithm);
95              } else {
96                  xmlCipher = XMLCipher.getInstance(encryptionAlgorithm);
97              }
98          } catch (XMLEncryptionException ex) {
99              throw new WSSecurityException(
100                 WSSecurityException.ErrorCode.UNSUPPORTED_ALGORITHM, ex
101             );
102         }
103 
104         List<String> encDataRef = new ArrayList<>();
105         WSEncryptionPart attachmentEncryptionPart = null;
106         for (WSEncryptionPart encPart : references) {
107             if (encPart.getId() != null && encPart.getId().startsWith("cid:")) {
108                 attachmentEncryptionPart = encPart;
109                 continue;
110             }
111 
112             //
113             // Get the data to encrypt.
114             //
115             if (callbackLookup == null) {
116                 callbackLookup = new DOMCallbackLookup(doc);
117             }
118             List<Element> elementsToEncrypt =
119                 WSSecurityUtil.findElements(encPart, callbackLookup);
120             if (elementsToEncrypt == null || elementsToEncrypt.isEmpty()) {
121                 if (!encPart.isRequired()) {
122                     continue;
123                 }
124                 throw new WSSecurityException(
125                     WSSecurityException.ErrorCode.FAILURE,
126                     "noEncElement",
127                     new Object[] {"{" + encPart.getNamespace() + "}" + encPart.getName()});
128             }
129 
130             if (expandXopInclude) {
131                 for (Element elementToEncrypt : elementsToEncrypt) {
132                     Element encrElement = elementToEncrypt;
133 
134                     // Look for xop:Include Nodes
135                     List<Element> includeElements =
136                         XMLUtils.findElements(elementToEncrypt.getFirstChild(), "Include", WSConstants.XOP_NS);
137                     if (includeElements != null && !includeElements.isEmpty()) {
138                         // See if we already have an expanded Element available (from Signature) that matches the current Element
139                         Element matchingElement = findMatchingExpandedElement(encrElement);
140                         if (matchingElement != null && matchingElement != encrElement) {
141                             // If so then replace the existing Element to encrypt in the SOAP Envelope
142                             encrElement.getParentNode().replaceChild(matchingElement, encrElement);
143                             encrElement = matchingElement;
144 
145                             // We already have an expanded Element, but might need to delete the attachments
146                             for (Element includeElement : includeElements) {
147                                 String xopURI = includeElement.getAttributeNS(null, "href");
148                                 if (xopURI != null) {
149                                     // Delete the attachment
150 
151                                     AttachmentRequestCallback attachmentRequestCallback = new AttachmentRequestCallback();
152                                     attachmentRequestCallback.setAttachmentId(WSSecurityUtil.getAttachmentId(xopURI));
153 
154                                     try {
155                                         attachmentCallbackHandler.handle(new Callback[]{attachmentRequestCallback});
156                                     } catch (UnsupportedCallbackException | IOException e) {
157                                         throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK, e);
158                                     }
159                                 }
160                             }
161                         } else {
162                             // Here we didn't find an already expanded Element, so inline the attachment bytes
163                             WSSecurityUtil.inlineAttachments(includeElements, attachmentCallbackHandler, true);
164                         }
165                     }
166 
167                     if (storeBytesInAttachment) {
168                         try {
169                             String id =
170                                 encryptElementInAttachment(keyInfo, secretKey, encryptionAlgorithm, encPart, encrElement);
171                             encPart.setEncId(id);
172                             encDataRef.add("#" + id);
173                         } catch (Exception ex) {
174                             throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, ex);
175                         }
176                     } else {
177                         String id =
178                             encryptElement(encrElement, encPart.getEncModifier(), xmlCipher, secretKey, keyInfo);
179                         encPart.setEncId(id);
180                         encDataRef.add("#" + id);
181                     }
182                 }
183             } else if (storeBytesInAttachment) {
184                 for (Element elementToEncrypt : elementsToEncrypt) {
185                     try {
186                         String id =
187                             encryptElementInAttachment(keyInfo, secretKey, encryptionAlgorithm, encPart, elementToEncrypt);
188                         encPart.setEncId(id);
189                         encDataRef.add("#" + id);
190                     } catch (Exception ex) {
191                         throw new WSSecurityException(
192                             WSSecurityException.ErrorCode.FAILED_ENCRYPTION, ex
193                         );
194                     }
195                 }
196             } else {
197                 for (Element elementToEncrypt : elementsToEncrypt) {
198                     String id =
199                         encryptElement(elementToEncrypt, encPart.getEncModifier(), xmlCipher, secretKey, keyInfo);
200                     encPart.setEncId(id);
201                     encDataRef.add("#" + id);
202                 }
203             }
204         }
205 
206         if (attachmentEncryptionPart != null) {
207             encryptAttachment(keyInfo, secretKey, encryptionAlgorithm, attachmentEncryptionPart, encDataRef,
208                               attachmentEncryptedDataElements);
209         }
210 
211         return encDataRef;
212     }
213 
214     private Element findMatchingExpandedElement(Element element) {
215         Element matchingElement = null;
216 
217         if (element.hasAttributeNS(WSConstants.WSU_NS, "Id")) {
218             String id = element.getAttributeNS(WSConstants.WSU_NS, "Id");
219             matchingElement = wsDocInfo.getTokenElement(id);
220         }
221 
222         if (matchingElement == null && element.hasAttributeNS(null, "Id")) {
223             String id = element.getAttributeNS(null, "Id");
224             matchingElement = wsDocInfo.getTokenElement(id);
225         }
226 
227         // Check the Elements are the same
228         if (matchingElement != null && matchingElement.getNamespaceURI().equals(element.getNamespaceURI())
229             && matchingElement.getLocalName().equals(element.getLocalName())) {
230             return matchingElement;
231         }
232 
233         return null;
234     }
235 
236     private String encryptElementInAttachment(
237         KeyInfo keyInfo,
238         SecretKey secretKey,
239         String encryptionAlgorithm,
240         WSEncryptionPart encryptionPart,
241         Element elementToEncrypt
242    ) throws Exception {
243 
244         String type = EncryptionConstants.TYPE_ELEMENT;
245         if ("Content".equals(encryptionPart.getEncModifier())) {
246             type = EncryptionConstants.TYPE_CONTENT;
247         }
248 
249         final String attachmentId = idAllocator.createId("", doc);
250         String encEncryptedDataId = idAllocator.createId("ED-", attachmentId);
251 
252         if ("Header".equals(encryptionPart.getEncModifier())
253             && elementToEncrypt.getParentNode().equals(WSSecurityUtil.getSOAPHeader(doc))) {
254             createEncryptedHeaderElement(securityHeader, elementToEncrypt, idAllocator);
255         }
256 
257         Element encryptedData =
258             doc.createElementNS(WSConstants.ENC_NS, WSConstants.ENC_PREFIX + ":EncryptedData");
259         encryptedData.setAttributeNS(null, "Id", encEncryptedDataId);
260         encryptedData.setAttributeNS(null, "Type", type);
261 
262         Element encryptionMethod =
263             doc.createElementNS(WSConstants.ENC_NS, WSConstants.ENC_PREFIX + ":EncryptionMethod");
264         encryptionMethod.setAttributeNS(null, "Algorithm", encryptionAlgorithm);
265 
266         encryptedData.appendChild(encryptionMethod);
267         encryptedData.appendChild(WSSecurityUtil.cloneElement(doc, keyInfo.getElement()));
268 
269         Element cipherData =
270             doc.createElementNS(WSConstants.ENC_NS, WSConstants.ENC_PREFIX + ":CipherData");
271         Element cipherValue =
272             doc.createElementNS(WSConstants.ENC_NS, WSConstants.ENC_PREFIX + ":CipherValue");
273         cipherData.appendChild(cipherValue);
274         encryptedData.appendChild(cipherData);
275 
276         Cipher cipher = createCipher(encryptionAlgorithm, secretKey);
277 
278         // Serialize and encrypt the element
279         AbstractSerializer serializer = new TransformSerializer(true);
280 
281         byte[] serializedOctets = null;
282         if (type.equals(EncryptionConstants.TYPE_CONTENT)) {
283             NodeList children = elementToEncrypt.getChildNodes();
284             if (null != children) {
285                 serializedOctets = serializer.serializeToByteArray(children);
286             } else {
287                 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION,
288                                               "Element has no content.");
289             }
290         } else {
291             serializedOctets = serializer.serializeToByteArray(elementToEncrypt);
292         }
293 
294         byte[] encryptedBytes = null;
295         try {
296             encryptedBytes = cipher.doFinal(serializedOctets);
297         } catch (IllegalBlockSizeException ibse) {
298             throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, ibse);
299         } catch (BadPaddingException bpe) {
300             throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, bpe);
301         }
302 
303         // Now build up to a properly XML Encryption encoded octet stream
304         byte[] iv = cipher.getIV();
305         byte[] finalEncryptedBytes = new byte[iv.length + encryptedBytes.length];
306         System.arraycopy(iv, 0, finalEncryptedBytes, 0, iv.length);
307         System.arraycopy(encryptedBytes, 0, finalEncryptedBytes, iv.length, encryptedBytes.length);
308 
309         if ("Content".equals(encryptionPart.getEncModifier())) {
310             Node child = elementToEncrypt.getFirstChild();
311             while (child != null) {
312                 Node sibling = child.getNextSibling();
313                 elementToEncrypt.removeChild(child);
314                 child = sibling;
315             }
316             elementToEncrypt.appendChild(encryptedData);
317         } else {
318             elementToEncrypt.getParentNode().replaceChild(encryptedData, elementToEncrypt);
319         }
320 
321         AttachmentUtils.storeBytesInAttachment(cipherValue, doc, attachmentId,
322                                               finalEncryptedBytes, attachmentCallbackHandler);
323 
324         return encEncryptedDataId;
325     }
326 
327     private void encryptAttachment(
328         KeyInfo keyInfo,
329         SecretKey secretKey,
330         String encryptionAlgorithm,
331         WSEncryptionPart attachmentEncryptionPart,
332         List<String> encDataRef,
333         List<Element> attachmentEncryptedDataElements
334     ) throws WSSecurityException {
335         if (attachmentCallbackHandler == null) {
336             throw new WSSecurityException(
337                 WSSecurityException.ErrorCode.FAILURE,
338                 "empty", new Object[] {"no attachment callbackhandler supplied"}
339             );
340         }
341 
342         AttachmentRequestCallback attachmentRequestCallback = new AttachmentRequestCallback();
343         String id = AttachmentUtils.getAttachmentId(attachmentEncryptionPart.getId());
344         attachmentRequestCallback.setAttachmentId(id);
345         try {
346             attachmentCallbackHandler.handle(new Callback[]{attachmentRequestCallback});
347         } catch (Exception e) {
348             throw new WSSecurityException(
349                 WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e
350             );
351         }
352         String attachmentEncryptedDataType = WSConstants.SWA_ATTACHMENT_ENCRYPTED_DATA_TYPE_CONTENT_ONLY;
353         if ("Element".equals(attachmentEncryptionPart.getEncModifier())) {
354             attachmentEncryptedDataType = WSConstants.SWA_ATTACHMENT_ENCRYPTED_DATA_TYPE_COMPLETE;
355         }
356 
357         for (Attachment attachment : attachmentRequestCallback.getAttachments()) {
358 
359             final String attachmentId = attachment.getId();
360             String encEncryptedDataId = idAllocator.createId("ED-", attachmentId);
361             encDataRef.add("#" + encEncryptedDataId);
362 
363             Element encryptedData =
364                 doc.createElementNS(WSConstants.ENC_NS, WSConstants.ENC_PREFIX + ":EncryptedData");
365             encryptedData.setAttributeNS(null, "Id", encEncryptedDataId);
366             encryptedData.setAttributeNS(null, "MimeType", attachment.getMimeType());
367             encryptedData.setAttributeNS(null, "Type", attachmentEncryptedDataType);
368 
369             Element encryptionMethod =
370                 doc.createElementNS(WSConstants.ENC_NS, WSConstants.ENC_PREFIX + ":EncryptionMethod");
371             encryptionMethod.setAttributeNS(null, "Algorithm", encryptionAlgorithm);
372 
373             encryptedData.appendChild(encryptionMethod);
374             encryptedData.appendChild(WSSecurityUtil.cloneElement(doc, keyInfo.getElement()));
375 
376             Element cipherData =
377                 doc.createElementNS(WSConstants.ENC_NS, WSConstants.ENC_PREFIX + ":CipherData");
378             Element cipherReference =
379                 doc.createElementNS(WSConstants.ENC_NS, WSConstants.ENC_PREFIX + ":CipherReference");
380             cipherReference.setAttributeNS(null, "URI", "cid:" + attachmentId);
381 
382             Element transforms = doc.createElementNS(WSConstants.ENC_NS, WSConstants.ENC_PREFIX + ":Transforms");
383             Element transform = doc.createElementNS(WSConstants.SIG_NS, WSConstants.SIG_PREFIX + ":Transform");
384             transform.setAttributeNS(null, "Algorithm", WSConstants.SWA_ATTACHMENT_CIPHERTEXT_TRANS);
385             transforms.appendChild(transform);
386 
387             cipherReference.appendChild(transforms);
388             cipherData.appendChild(cipherReference);
389             encryptedData.appendChild(cipherData);
390 
391             attachmentEncryptedDataElements.add(encryptedData);
392 
393             Attachment resultAttachment = new Attachment();
394             resultAttachment.setId(attachmentId);
395             resultAttachment.setMimeType("application/octet-stream");
396 
397             Cipher cipher = createCipher(encryptionAlgorithm, secretKey);
398 
399             Map<String, String> headers = new HashMap<>(attachment.getHeaders());
400             resultAttachment.setSourceStream(
401                 AttachmentUtils.setupAttachmentEncryptionStream(
402                     cipher, "Element".equals(attachmentEncryptionPart.getEncModifier()),
403                     attachment, headers
404                 )
405             );
406             resultAttachment.addHeaders(headers);
407 
408             AttachmentResultCallback attachmentResultCallback = new AttachmentResultCallback();
409             attachmentResultCallback.setAttachmentId(attachmentId);
410             attachmentResultCallback.setAttachment(resultAttachment);
411             try {
412                 attachmentCallbackHandler.handle(new Callback[]{attachmentResultCallback});
413             } catch (Exception e) {
414                 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e);
415             }
416         }
417     }
418 
419     private Cipher createCipher(String encryptionAlgorithm, SecretKey secretKey)
420         throws WSSecurityException {
421         String jceAlgorithm = JCEMapper.translateURItoJCEID(encryptionAlgorithm);
422         try {
423             Cipher cipher = Cipher.getInstance(jceAlgorithm);
424 
425             int ivLen = JCEMapper.getIVLengthFromURI(encryptionAlgorithm) / 8;
426             byte[] iv = XMLSecurityConstants.generateBytes(ivLen);
427             AlgorithmParameterSpec paramSpec =
428                 XMLCipherUtil.constructBlockCipherParameters(encryptionAlgorithm, iv);
429             cipher.init(Cipher.ENCRYPT_MODE, secretKey, paramSpec);
430 
431             return cipher;
432         } catch (Exception e) {
433             throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e);
434         }
435     }
436 
437     /**
438      * Encrypt an element.
439      */
440     private String encryptElement(
441         Element elementToEncrypt,
442         String modifier,
443         XMLCipher xmlCipher,
444         SecretKey secretKey,
445         KeyInfo keyInfo
446     ) throws WSSecurityException {
447 
448         boolean content = "Content".equals(modifier);
449         //
450         // Encrypt data, and set necessary attributes in xenc:EncryptedData
451         //
452         String xencEncryptedDataId = idAllocator.createId("ED-", elementToEncrypt);
453         try {
454             if ("Header".equals(modifier)) {
455                 String soapNamespace = WSSecurityUtil.getSOAPNamespace(doc.getDocumentElement());
456                 if (elementToEncrypt.getParentNode().getNamespaceURI().equals(soapNamespace)
457                     && WSConstants.ELEM_HEADER.equals(elementToEncrypt.getParentNode().getLocalName())) {
458                     createEncryptedHeaderElement(securityHeader, elementToEncrypt, idAllocator);
459                 }
460             }
461 
462             xmlCipher.init(XMLCipher.ENCRYPT_MODE, secretKey);
463             EncryptedData encData = xmlCipher.getEncryptedData();
464             encData.setId(xencEncryptedDataId);
465             encData.setKeyInfo(keyInfo);
466             xmlCipher.doFinal(doc, elementToEncrypt, content);
467             return xencEncryptedDataId;
468         } catch (Exception ex) {
469             throw new WSSecurityException(
470                 WSSecurityException.ErrorCode.FAILED_ENCRYPTION, ex
471             );
472         }
473     }
474 
475     private static void createEncryptedHeaderElement(
476         WSSecHeader securityHeader,
477         Element elementToEncrypt,
478         WsuIdAllocator idAllocator
479     ) {
480         Element elem =
481             elementToEncrypt.getOwnerDocument().createElementNS(
482                 WSConstants.WSSE11_NS, "wsse11:" + WSConstants.ENCRYPTED_HEADER
483             );
484         XMLUtils.setNamespace(elem, WSConstants.WSSE11_NS, WSConstants.WSSE11_PREFIX);
485         String wsuPrefix =
486             XMLUtils.setNamespace(elem, WSConstants.WSU_NS, WSConstants.WSU_PREFIX);
487         String headerId = idAllocator.createId("EH-", elementToEncrypt);
488         elem.setAttributeNS(
489             WSConstants.WSU_NS, wsuPrefix + ":Id", headerId
490         );
491 
492         //
493         // Add the EncryptedHeader node to the element to be encrypted's parent
494         // (i.e. the SOAP header). Add the element to be encrypted to the Encrypted
495         // Header node as well
496         //
497         Node parent = elementToEncrypt.getParentNode();
498         elementToEncrypt = (Element)parent.replaceChild(elem, elementToEncrypt);
499         elem.appendChild(elementToEncrypt);
500 
501         if (securityHeader != null) {
502             NamedNodeMap map = securityHeader.getSecurityHeaderElement().getAttributes();
503             for (int i = 0; i < map.getLength(); i++) {
504                 Attr attr = (Attr)map.item(i);
505                 if (WSConstants.URI_SOAP11_ENV.equals(attr.getNamespaceURI())
506                     || WSConstants.URI_SOAP12_ENV.equals(attr.getNamespaceURI())) {
507                     String soapEnvPrefix =
508                         XMLUtils.setNamespace(
509                             elem, attr.getNamespaceURI(), WSConstants.DEFAULT_SOAP_PREFIX
510                         );
511                     elem.setAttributeNS(
512                         attr.getNamespaceURI(),
513                         soapEnvPrefix + ":" + attr.getLocalName(),
514                         attr.getValue()
515                     );
516                 }
517             }
518         }
519 
520     }
521 
522     public Document getDoc() {
523         return doc;
524     }
525 
526     public void setDoc(Document doc) {
527         this.doc = doc;
528     }
529 
530     public WSSecHeader getSecurityHeader() {
531         return securityHeader;
532     }
533 
534     public void setSecurityHeader(WSSecHeader securityHeader) {
535         this.securityHeader = securityHeader;
536     }
537 
538     public WsuIdAllocator getIdAllocator() {
539         return idAllocator;
540     }
541 
542     public void setIdAllocator(WsuIdAllocator idAllocator) {
543         this.idAllocator = idAllocator;
544     }
545 
546     public CallbackLookup getCallbackLookup() {
547         return callbackLookup;
548     }
549 
550     public void setCallbackLookup(CallbackLookup callbackLookup) {
551         this.callbackLookup = callbackLookup;
552     }
553 
554     public CallbackHandler getAttachmentCallbackHandler() {
555         return attachmentCallbackHandler;
556     }
557 
558     public void setAttachmentCallbackHandler(CallbackHandler attachmentCallbackHandler) {
559         this.attachmentCallbackHandler = attachmentCallbackHandler;
560     }
561 
562     public boolean isStoreBytesInAttachment() {
563         return storeBytesInAttachment;
564     }
565 
566     public void setStoreBytesInAttachment(boolean storeBytesInAttachment) {
567         this.storeBytesInAttachment = storeBytesInAttachment;
568     }
569 
570     public Serializer getEncryptionSerializer() {
571         return encryptionSerializer;
572     }
573 
574     public void setEncryptionSerializer(Serializer encryptionSerializer) {
575         this.encryptionSerializer = encryptionSerializer;
576     }
577 
578     public boolean isExpandXopInclude() {
579         return expandXopInclude;
580     }
581 
582     public void setExpandXopInclude(boolean expandXopInclude) {
583         this.expandXopInclude = expandXopInclude;
584     }
585 
586     public WSDocInfo getWsDocInfo() {
587         return wsDocInfo;
588     }
589 
590     public void setWsDocInfo(WSDocInfo wsDocInfo) {
591         this.wsDocInfo = wsDocInfo;
592     }
593 
594 }