Thursday, December 11, 2014

Datapower XQuery replace


One of the clients that I’m working for discovered a problem with a SOAP web service querying an LDAP. The service could contain a ‘*’ in plain text in possibly different fields in the message. When the service is called it uses the ‘*’ as a wildcard. The system should handle the ‘*’ as plain text so we need to escape the character with ‘\2a’ (escape for a LDAP filter query). So they looked in complete web service chain where the least impact was. They decided that an update in the DataPower configuration was the best option.

This is a small message example, but the ‘*’ can occur in couple different WSDL operations and in different fields.
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
               xmlns:tem="http://tempuri.org/">
   <soap:Header/>
   <soap:Body>
      <tem:FindUser>
        <tem:UserName>KMe_*</tem:UserName>
      </tem:FindUser>
   </soap:Body>
</soap:Envelope>

I immediately thought to use the function str:replace(). But unfortunately it is not supported in Datapower, which brought me to XQuery, as an alternative for XSLT. So this is the solution that I developed.

Because the replacement is only necessary for 3 operations from the WSDL I defined the policy-rule on WSDL operation level.


Below the XQuery code used to replace the ‘*’ into ‘\2’a. The XQuery can be extended to handle other values that need to be escaped for example:  ( ) \ / NUL

xquery version "1.0";
declare namespace local = "http://example.org";
declare function local:copy-replace($element as element()) {
  element {node-name($element)}
               {$element/@*,
                for $child in $element/node()
                return if ($child instance of element())
                       then local:copy-replace($child)
                       else replace($child,'\*','\\2a')
               }
};
local:copy-replace(/*)

The total number of requests that have a ‘*’ or other wildcards in the username is limited. To improve the performance I adapted the standard SQL-injection filter to search for ‘*’ and output the number of hits. This way when the hit count is 0 I can skip the XQuery transform action.

Author: Kim

No comments:

Post a Comment