You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by Guillaume Castagnino <gc...@vulnit.com> on 2012/06/15 10:50:00 UTC

Using (JaxWS)DynamicClient with SOAP 1.2 webservices.

Hi,

I'm new to CXF (2.6.1 with openjdk7), and I have a problem when dealing with 
SOAP 1.2 webservices with the DynamicClient.

First a little context. I'm programming a web vulnerability scanner. So during 
web crawling, I get some WSDL definitions that I do not know anything about. 
My goal with CXF is to:
- enumerate endpoints and operations with in/out parameters
- build SOAP HTTP requests (but not send the requests, I will do that with 
other tools such as sqlmap, xml injection testers...)
So all is done programmatically, I have absolutely no precompiled classes that 
would have been generated with wsdl2java or something, I do not know the 
service name, etc..., since I do not know anything about the webservice priori 
to lauching my scanner ! This is important, because if I correclty understand 
CXF, not knowing anything about the service forbids me to use many CXF ways to 
do.



My first approach was to only use the WSDL parser. This was working for both 
SOAP 1.1 and SOAP 1.2 descriptions:
  // Create the CXF bus
  Bus bus = BusFactory.getThreadDefaultBus();
  // grab the WSDL extension
  WSDLManager wsdlManager = bus.getExtension(WSDLManager.class);
  // Parse the WSDL
  Definition def = wsdlManager.getDefinition(wsdlURL);
  WSDLServiceBuilder builder = new WSDLServiceBuilder(bus);
  List<ServiceInfo> services = builder.buildServices(def);

Then iterate over the ServiceInfo list to discover endpoints, namespaces, SOAP 
version and operations. With this approach, I have to manually build my SOAP 
requests (HTTP header and SOAP XML), dealing with the 2 SOAP version... This 
is working, but this means manually dealing with all SOAP specificity to 
ensure maximum compatibility (I do not know what the SOAP server is : axis, 
.net, php nuSOAP...)



The second approach is to use CXF to generate the SOAP request instead of 
building it manually. So I switched to using a (JaxWS)DynamicClient to build 
classes on the fly. With this, I can still enumerate the ServiceInfo, and I 
can invoke services, and use an interceptor to get the SOAP request content:
  // Create the CXF bus
  Bus bus = BusFactory.getThreadDefaultBus();
  JaxWsDynamicClientFactory cf = JaxWsDynamicClientFactory.newInstance(bus);
  Client wsClient = cf.createClient(wsdlURL);
  List<ServiceInfo> services =
                      wsClient.getEndpoint().getService().getServiceInfos();

Then I simply use the wsClient.invoke(BOI, params...) method, using an 
interceptor coupled with the SAAJOutInterceptor to gather the SOAP request and 
the associated HTTP headers and abort before it's sent to the network.
This is working fine and I'm happy with this for SOAP 1.1 services.

But when I test this against a SOAP 1.2 WSDL such as the one attached (wich 
describes 2 SOAP 1.2 endpoints), the JaxWsDynamicClientFactory throw me an 
exception: "Only document-style SOAP 1.1 http are supported for auto-selection 
of endpoint; none were found. !!"
So I cannot build the SOAP requests, and moreover I cannot even iterate over 
the ServiceInfos, whereas I was able to do it using the with my first approach 
with the WSDLManager/WSDLServiceBuilder.



The question is:
- Is there a way to build a DynamicClient for such SOAP 1.2 WSDL ?
- Or is there an other way to do this (always 100% programmatically and 
dynamically, since I do not know anything about the service before executing 
my crawler !)


Thank you very much for any help !!

-- 
Guillaume Castagnino
    gcastagnino@vulnit.com

Re: Using (JaxWS)DynamicClient with SOAP 1.2 webservices.

Posted by Daniel Kulp <dk...@apache.org>.
On Monday, June 18, 2012 10:17:27 AM Guillaume Castagnino wrote:
> Thanks !!
> 
> This seems to be working like this !

...... 

> But one more question: doing like this, the WSDL is parsed twice, isn't it
> ? The first time to build the Definition, and the second time when
> building the Client ? Is there a way I missed to pass the Definition
> directly to the Client to avoid this double WSDL parsing ?

Likely not.   The WSDLManager mantains a WeakHashMap type of cache for the 
WSDL's.   As long as you strongly  hold onto the key you pass into the 
getDefinition call and you use the same key for the call to create the 
dynamic client, it should use the cached copy and not reparse it.

Dan


> 
> 
> Now I get some issues with the XSD complex types such as "undefined simple
> or complex type 'enc11:Array'", but this is an other story, thanks !
> 
> Guillaume

Daniel Kulp
dkulp@apache.org - http://dankulp.com/blog
Talend Community Coder - http://coders.talend.com

Re: Using (JaxWS)DynamicClient with SOAP 1.2 webservices.

Posted by Guillaume Castagnino <gc...@vulnit.com>.
Thanks !!

This seems to be working like this !

Bus bus = BusFactory.getThreadDefaultBus();
WSDLManager wsdlManager = bus.getExtension(WSDLManager.class);
Definition def = wsdlManager.getDefinition(output.getAbsolutePath());
WSDLServiceBuilder builder = new WSDLServiceBuilder(bus);
List<ServiceInfo> services = builder.buildServices(def);
JaxWsDynamicClientFactory cf = 
                      JaxWsDynamicClientFactory.newInstance(bus);

for (ServiceInfo service : services) {
 for (EndpointInfo endpoint : service.getEndpoints()) {
  Client wsClient = cf.createClient(output.getAbsolutePath(), 
                              service.getName(), endpoint.getName());
  BindingInfo bi = wsClient.getEndpoint().getBinding().getBindingInfo();
  for (BindingOperationInfo operation : bi.getOperations()) {
   SoapRequest soapRequest = new SoapRequest(request, wsClient, operation);
   feedback.addSoapRequest(soapRequest);
  }
 }
}


But one more question: doing like this, the WSDL is parsed twice, isn't it ?
The first time to build the Definition, and the second time when building the 
Client ? Is there a way I missed to pass the Definition directly to the Client 
to avoid this double WSDL parsing ?


Now I get some issues with the XSD complex types such as "undefined simple or 
complex type 'enc11:Array'", but this is an other story, thanks !

Guillaume

Le vendredi 15 juin 2012 16:29:59, Daniel Kulp a écrit :
> You may need to use a combined approach.  Use your original code to load the
> wsdl and iterate over the services, mostly to get the service names and
> endpoint names.   That's really it.  Then use DynamicClient factory, but
> pass in the appropriate servicename and endpoint name that you want to use.
> 
> Dan
> 
> On Friday, June 15, 2012 10:50:00 AM Guillaume Castagnino wrote:
> > Hi,
> > 
> > I'm new to CXF (2.6.1 with openjdk7), and I have a problem when dealing
> > with SOAP 1.2 webservices with the DynamicClient.
> > 
> > First a little context. I'm programming a web vulnerability scanner. So
> > during web crawling, I get some WSDL definitions that I do not know
> > anything about. My goal with CXF is to:
> > - enumerate endpoints and operations with in/out parameters
> > - build SOAP HTTP requests (but not send the requests, I will do that
> > with other tools such as sqlmap, xml injection testers...)
> > So all is done programmatically, I have absolutely no precompiled
> > classes
> > that would have been generated with wsdl2java or something, I do not
> > know
> > the service name, etc..., since I do not know anything about the
> > webservice priori to lauching my scanner ! This is important, because if
> > I correclty understand CXF, not knowing anything about the service
> > forbids me to use many CXF ways to do.
> > 
> > 
> > 
> > My first approach was to only use the WSDL parser. This was working for
> > 
> > both SOAP 1.1 and SOAP 1.2 descriptions:
> >   // Create the CXF bus
> >   Bus bus = BusFactory.getThreadDefaultBus();
> >   // grab the WSDL extension
> >   WSDLManager wsdlManager = bus.getExtension(WSDLManager.class);
> >   // Parse the WSDL
> >   Definition def = wsdlManager.getDefinition(wsdlURL);
> >   WSDLServiceBuilder builder = new WSDLServiceBuilder(bus);
> >   List<ServiceInfo> services = builder.buildServices(def);
> > 
> > Then iterate over the ServiceInfo list to discover endpoints,
> > namespaces,
> > SOAP version and operations. With this approach, I have to manually
> > build
> > my SOAP requests (HTTP header and SOAP XML), dealing with the 2 SOAP
> > version... This is working, but this means manually dealing with all
> > SOAP
> > specificity to ensure maximum compatibility (I do not know what the SOAP
> > server is : axis, .net, php nuSOAP...)
> > 
> > 
> > 
> > The second approach is to use CXF to generate the SOAP request instead
> > of
> > building it manually. So I switched to using a (JaxWS)DynamicClient to
> > build classes on the fly. With this, I can still enumerate the
> > ServiceInfo, and I can invoke services, and use an interceptor to get
> > the
> > SOAP request content: // Create the CXF bus
> > 
> >   Bus bus = BusFactory.getThreadDefaultBus();
> >   JaxWsDynamicClientFactory cf =
> > 
> > JaxWsDynamicClientFactory.newInstance(bus); Client wsClient =
> > cf.createClient(wsdlURL);
> > 
> >   List<ServiceInfo> services =
> > 
> > wsClient.getEndpoint().getService().getServiceInfos();
> > 
> > Then I simply use the wsClient.invoke(BOI, params...) method, using an
> > interceptor coupled with the SAAJOutInterceptor to gather the SOAP
> > request and the associated HTTP headers and abort before it's sent to
> > the network. This is working fine and I'm happy with this for SOAP 1.1
> > services.
> > 
> > But when I test this against a SOAP 1.2 WSDL such as the one attached
> > (wich describes 2 SOAP 1.2 endpoints), the JaxWsDynamicClientFactory
> > throw me an exception: "Only document-style SOAP 1.1 http are supported
> > for auto-selection of endpoint; none were found. !!"
> > So I cannot build the SOAP requests, and moreover I cannot even iterate
> > over the ServiceInfos, whereas I was able to do it using the with my
> > first approach with the WSDLManager/WSDLServiceBuilder.
> > 
> > 
> > 
> > The question is:
> > - Is there a way to build a DynamicClient for such SOAP 1.2 WSDL ?
> > - Or is there an other way to do this (always 100% programmatically and
> > dynamically, since I do not know anything about the service before
> > executing my crawler !)
> > 
> > 
> > Thank you very much for any help !!
-- 
Guillaume Castagnino
    gcastagnino@vulnit.com


Re: Using (JaxWS)DynamicClient with SOAP 1.2 webservices.

Posted by Daniel Kulp <dk...@apache.org>.
You may need to use a combined approach.  Use your original code to load the 
wsdl and iterate over the services, mostly to get the service names and 
endpoint names.   That's really it.  Then use DynamicClient factory, but 
pass in the appropriate servicename and endpoint name that you want to use.

Dan


On Friday, June 15, 2012 10:50:00 AM Guillaume Castagnino wrote:
> Hi,
> 
> I'm new to CXF (2.6.1 with openjdk7), and I have a problem when dealing
> with SOAP 1.2 webservices with the DynamicClient.
> 
> First a little context. I'm programming a web vulnerability scanner. So
> during web crawling, I get some WSDL definitions that I do not know
> anything about. My goal with CXF is to:
> - enumerate endpoints and operations with in/out parameters
> - build SOAP HTTP requests (but not send the requests, I will do that with
> other tools such as sqlmap, xml injection testers...)
> So all is done programmatically, I have absolutely no precompiled classes
> that would have been generated with wsdl2java or something, I do not know
> the service name, etc..., since I do not know anything about the
> webservice priori to lauching my scanner ! This is important, because if
> I correclty understand CXF, not knowing anything about the service
> forbids me to use many CXF ways to do.
> 
> 
> 
> My first approach was to only use the WSDL parser. This was working for
> both SOAP 1.1 and SOAP 1.2 descriptions:
>   // Create the CXF bus
>   Bus bus = BusFactory.getThreadDefaultBus();
>   // grab the WSDL extension
>   WSDLManager wsdlManager = bus.getExtension(WSDLManager.class);
>   // Parse the WSDL
>   Definition def = wsdlManager.getDefinition(wsdlURL);
>   WSDLServiceBuilder builder = new WSDLServiceBuilder(bus);
>   List<ServiceInfo> services = builder.buildServices(def);
> 
> Then iterate over the ServiceInfo list to discover endpoints, namespaces,
> SOAP version and operations. With this approach, I have to manually build
> my SOAP requests (HTTP header and SOAP XML), dealing with the 2 SOAP
> version... This is working, but this means manually dealing with all SOAP
> specificity to ensure maximum compatibility (I do not know what the SOAP
> server is : axis, .net, php nuSOAP...)
> 
> 
> 
> The second approach is to use CXF to generate the SOAP request instead of
> building it manually. So I switched to using a (JaxWS)DynamicClient to
> build classes on the fly. With this, I can still enumerate the
> ServiceInfo, and I can invoke services, and use an interceptor to get the
> SOAP request content: // Create the CXF bus
>   Bus bus = BusFactory.getThreadDefaultBus();
>   JaxWsDynamicClientFactory cf =
> JaxWsDynamicClientFactory.newInstance(bus); Client wsClient =
> cf.createClient(wsdlURL);
>   List<ServiceInfo> services =
>                      
> wsClient.getEndpoint().getService().getServiceInfos();
> 
> Then I simply use the wsClient.invoke(BOI, params...) method, using an
> interceptor coupled with the SAAJOutInterceptor to gather the SOAP request
> and the associated HTTP headers and abort before it's sent to the
> network. This is working fine and I'm happy with this for SOAP 1.1
> services.
> 
> But when I test this against a SOAP 1.2 WSDL such as the one attached
> (wich describes 2 SOAP 1.2 endpoints), the JaxWsDynamicClientFactory
> throw me an exception: "Only document-style SOAP 1.1 http are supported
> for auto-selection of endpoint; none were found. !!"
> So I cannot build the SOAP requests, and moreover I cannot even iterate
> over the ServiceInfos, whereas I was able to do it using the with my
> first approach with the WSDLManager/WSDLServiceBuilder.
> 
> 
> 
> The question is:
> - Is there a way to build a DynamicClient for such SOAP 1.2 WSDL ?
> - Or is there an other way to do this (always 100% programmatically and
> dynamically, since I do not know anything about the service before
> executing my crawler !)
> 
> 
> Thank you very much for any help !!
-- 
Daniel Kulp
dkulp@apache.org - http://dankulp.com/blog
Talend Community Coder - http://coders.talend.com