[prev in list] [next in list] [prev in thread] [next in thread] 

List:       xmlrpc-user
Subject:    Re: possible bug in the class "WSSecEncrypt"
From:       Colm O hEigeartaigh <coheigea () apache ! org>
Date:       2010-11-24 14:16:50
Message-ID: AANLkTin3YqmGQMtiB_wEFvq_-DtcrPCWKwuqVWaKFFPJ () mail ! gmail ! com
[Download RAW message or body]

Hi Marcin,

1) Yes that looks like a bug. Please create a JIRA
(https://issues.apache.org/jira/browse/WSS) and attach a patch for
this issue. Please note that NodeLists are not thread-safe, and are to
be avoided in WSS4J.

2) XPath is only used on the inbound side to refer to an element that
has been processed. I agree that it would be useful to support this
feature on the outbound side. The current API's used in
WSEncryptionPart cannot be changed for backwards compatibility
reasons. Another constructor could be added to support setting the
XPath. Some functionality would then have to be added to
WSSecurityUtil to
find a set of elements matching the XPath expression. You could add a
new JIRA for this as well if you want.

Thanks,

Colm.

On Wed, Nov 24, 2010 at 12:39 PM,  <Marcin.Markiewicz@fiducia.de> wrote:
> Hallo team,
> 
> it's my first post for this project, and the first one for an open source
> project as well. Thus i kindly pleas to excuse my mistakes, should i have
> done some.
> 
> I'm currently developing an web service framework for the Fiducia, germany
> (huge Java banking project). My current task is to encrypt some parts of the
> SOAP-Headers, containing attachments.
> 
> The structure of the SOAP-Message is like this:
> ---
> <xml...>
> <soapenv:Envelope>
> <soapenv:Header>
> <myNS:Header1>
> <!-- XML data-->
> </myNS:Header1>
> <myNS:Header2>
> <!-- XML data-->
> </myNS:Header2>
> ...
> <myNS:Attachments>
> <myNS:attachment>
> <!-- binary data base64 encoded -->
> </myNS:attachment>
> <myNS:attachment>
> <!-- binary data base64 encoded -->
> </myNS:attachment>
> <myNS:attachment>
> <!-- binary data base64 encoded -->
> </myNS:attachment>
> ...
> </myNS:Attachments>
> ...
> <myNS:HeaderX>
> <!-- XML data-->
> </myNS:HeaderX>
> </soapenv:Header>
> <soapenv:Body>
> <!-- XML data-->
> </soapenv:Body>
> </soapenv:Envelope>
> ---
> 
> The attachments will be extracted later in their own MIME multipart parts,
> using MTOM.
> My problem is now, that i cannot encrypt the attachments separately from
> each other. I can encrypt the whole Attachments-header using:
> ---
> WSEncryptionPartencryptionPart = new WSEncryptionPart("Attachments",
> "myNS-URI", "Content");
> encryptionParts.add(encryptionPart);
> ---
> But if I want to encrypt the attachment-elements separately using:
> ---
> WSEncryptionPartencryptionPart = new WSEncryptionPart("attachment",
> "myNS-URI", "Content");
> encryptionParts.add(encryptionPart);
> ---
> then only the firs one will be encrypted. The others will not.
> 
> I have quickly analysed the class
> org.apache.ws.security.message.WSSecEncrypt, an found the code lines 495 and
> following, especially the one with:
> ---
> body = (Element) WSSecurityUtil.findElement(document, elemName, nmSpace);
> ---
> Well, this line finds only one (the first one) element with the given name,
> and not all of them. Then I implemented some work aound - not pretty, but
> working - and now this class canencrypt all the elements with the given
> name.
> here is the modified method:
> ---
> private Vector doEncryption(
> Document doc,
> SecretKey secretKey,
> KeyInfo keyInfo,
> Vector references
> ) throws WSSecurityException {
> 
> XMLCipher xmlCipher = null;
> try {
> xmlCipher = XMLCipher.getInstance(symEncAlgo);
> } catch (XMLEncryptionException e3) {
> throw new WSSecurityException(
> WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, e3
> );
> }
> 
> Vector encDataRef = new Vector();
> 
> boolean cloneKeyInfo = false;
> for (int part = 0; part < references.size(); part++) {
> WSEncryptionPart encPart = (WSEncryptionPart) references.get(part);
> 
> String idToEnc = encPart.getId();
> String elemName = encPart.getName();
> String nmSpace = encPart.getNamespace();
> String modifier = encPart.getEncModifier();
> //
> // Third step: get the data to encrypt.
> //
> //Element body = null;
> if (idToEnc != null) {
> Element element =
> WSSecurityUtil.findElementById(
> document.getDocumentElement(), idToEnc, WSConstants.WSU_NS
> );
> if (element == null) {
> element =
> WSSecurityUtil.findElementById(document.getDocumentElement(), idToEnc,
> null);
> }
> if (element == null) {
> throw new WSSecurityException(
> WSSecurityException.FAILURE,
> "noEncElement",
> new Object[] {"{" + nmSpace + "}" + elemName}
> );
> }
> String encRef = encryptPart(document, encPart, element, keyInfo, xmlCipher,
> secretKey);
> encDataRef.add(encRef);
> } else {
> NodeList elements = document.getElementsByTagNameNS(nmSpace, elemName);
> if(elements == null || elements.getLength() <= 0) {
> throw new WSSecurityException(
> WSSecurityException.FAILURE,
> "noEncElement",
> new Object[] {"{" + nmSpace + "}" + elemName}
> );
> }
> for(int i = 0; i < elements.getLength(); i++) {
> Element element = (Element)elements.item(i);
> String encRef = encryptPart(document, encPart, element, keyInfo, xmlCipher,
> secretKey);
> encDataRef.add(encRef);
> }
> }
> }
> return encDataRef;
> }
> ---
> 
> and here is the ne private method used by the modified one:
> ---
> private String encryptPart(Document doc, WSEncryptionPart encPart, Element
> element, KeyInfo keyInfo, XMLCipher xmlCipher, SecretKey secretKey ) throws
> WSSecurityException
> {
> Vector encDataRef = new Vector();
> 
> String modifier = encPart.getEncModifier();
> 
> boolean content = modifier.equals("Content") ? true : false;
> String xencEncryptedDataId =
> wssConfig.getIdAllocator().createId("EncDataId-", element);
> encPart.setEncId(xencEncryptedDataId);
> 
> boolean cloneKeyInfo = true;
> 
> if (keyInfo == null) {
> keyInfo = new KeyInfo(document);
> SecurityTokenReference secToken = new SecurityTokenReference(document);
> Reference ref = new Reference(document);
> if (encKeyIdDirectId) {
> ref.setURI(encKeyId);
> } else {
> ref.setURI("#" + encKeyId);
> }
> if (encKeyValueType != null) {
> ref.setValueType(encKeyValueType);
> }
> secToken.setReference(ref);
> keyInfo.addUnknownElement(secToken.getElement());
> Element keyInfoElement = keyInfo.getElement();
> keyInfoElement.setAttributeNS(
> WSConstants.XMLNS_NS, "xmlns:" + WSConstants.SIG_PREFIX, WSConstants.SIG_NS
> );
> }
> //
> // Fourth step: encrypt data, and set necessary attributes in
> // xenc:EncryptedData
> //
> try {
> if (modifier.equals("Header")) {
> 
> Element elem =
> doc.createElementNS(
> WSConstants.WSSE11_NS, "wsse11:" + WSConstants.ENCRYPTED_HEADER
> );
> WSSecurityUtil.setNamespace(elem, WSConstants.WSSE11_NS,
> WSConstants.WSSE11_PREFIX);
> String wsuPrefix =
> WSSecurityUtil.setNamespace(elem, WSConstants.WSU_NS,
> WSConstants.WSU_PREFIX);
> elem.setAttributeNS(
> WSConstants.WSU_NS, wsuPrefix + ":Id",
> wssConfig.getIdAllocator().createId("EncHeader-", element)
> );
> 
> NamedNodeMap map = element.getAttributes();
> 
> for (int i = 0 ; i < map.getLength() ; i++) {
> Attr attr = (Attr)map.item(i);
> if (attr.getNamespaceURI().equals(WSConstants.URI_SOAP11_ENV)
> > > attr.getNamespaceURI().equals(WSConstants.URI_SOAP12_ENV)) {
> String soapEnvPrefix =
> WSSecurityUtil.setNamespace(
> elem, attr.getNamespaceURI(), WSConstants.DEFAULT_SOAP_PREFIX
> );
> elem.setAttributeNS(
> attr.getNamespaceURI(),
> soapEnvPrefix + ":" + attr.getLocalName(),
> attr.getValue()
> );
> }
> }
> 
> xmlCipher.init(XMLCipher.ENCRYPT_MODE, secretKey);
> EncryptedData encData = xmlCipher.getEncryptedData();
> encData.setId(xencEncryptedDataId);
> encData.setKeyInfo(keyInfo);
> xmlCipher.doFinal(doc, element, content);
> 
> Element encDataElem =
> WSSecurityUtil.findElementById(
> document.getDocumentElement(), xencEncryptedDataId, null
> );
> Node clone = encDataElem.cloneNode(true);
> elem.appendChild(clone);
> encDataElem.getParentNode().appendChild(elem);
> encDataElem.getParentNode().removeChild(encDataElem);
> } else {
> xmlCipher.init(XMLCipher.ENCRYPT_MODE, secretKey);
> EncryptedData encData = xmlCipher.getEncryptedData();
> encData.setId(xencEncryptedDataId);
> encData.setKeyInfo(keyInfo);
> xmlCipher.doFinal(doc, element, content);
> }
> if (cloneKeyInfo) {
> keyInfo = new KeyInfo((Element) keyInfo.getElement().cloneNode(true), null);
> }
> } catch (Exception e2) {
> throw new WSSecurityException(
> WSSecurityException.FAILED_ENCRYPTION, null, null, e2
> );
> }
> return xencEncryptedDataId;
> 
> }
> ---
> 
> 
> I've just extraced the part of the old method responsible for the
> encryption/marking of one Element and I call it for all found parts.
> Perheadps you can discuss this modification and biuld it in one of the next
> version - should it be approved.
> 
> And there is one more suggestion - the class "WSEncryptionPart"... Since
> wss4j-1.5.8, or 1.5.9 you can set an XPath. But it is never used! The lookup
> is done only by the namespaceURI and local name. Perheaps it will be used in
> one of the future versions. But - what if the namespace/local name does not
> correspond to the XPath? And if we have the XPath then we can use only it,
> and forget the namespace/local name.
> So it would be nice, if the class WSEncryptionPart would have all the
> currently used constructors, and beside this new one with the XPath.
> Something like this:
> ---
> //old ones:
> WSEncryptionPart(String id)
> WSEncryptionPart(String id, String encMod)
> WSEncryptionPart(String id, String encMod,int type)
> WSEncryptionPart(String nm, String nmspace, String encMod)
> WSEncryptionPart(String nm, String nmspace, String encMod, int type)
> 
> //new ones:
> WSEncryptionPart(String xPath, String encMod)
> WSEncryptionPart(String xPath, String encMod, int type)
> ---
> and the newly added methods for setting and getting the xpath can be
> deleted.
> The search for the given element in the document can be then done by xpath
> _or_ the old way, depending on the parameter set.
> 
> 
> 
> Greetings,
> 
> Marcin Markiewicz
> 
> 
> 
> ----------------------------------------------------------------------------------------------------------------------------------------------
>  
> Fiducia IT AG
> Fiduciastraße 20
> 76227 Karlsruhe
> 
> Sitz der Gesellschaft: Karlsruhe
> AG Mannheim HRB 100059
> 
> Vorsitzender des Aufsichtsrats: Gregor Scheller
> Vorsitzender des Vorstands: Michael Krings
> Stellv. Vorsitzender des Vorstands: Klaus-Peter Bruns
> Vorstand: Jens-Olaf Bartels, Hans-Peter Straberger
> 
> Umsatzsteuer-ID.Nr. DE143582320, http://www.fiducia.de
> ----------------------------------------------------------------------------------------------------------------------------------------------
>  

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@ws.apache.org
For additional commands, e-mail: dev-help@ws.apache.org


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic