Hi all,
just a bit of a wrap up in case someone could use it in the future ...

The usecase:
Connect to an Identitiy provider through HTTPS based on TLSv1.2 with client authentication required (a password protected PKCS12 file "clientCERTKEY.p12" with client certificate and key was provided together with a CA certificate for trusting the server certificate "serverCA.crt"). Extract a chunk of XML from the response which represents a SAML assertion and and use it to call another service again over TLSv1.2 with the same client certificate/key pair. TLSv1.2 with mutual authentication requires a longer SSL handshake during which both Server and Client are authenticated and trusted.

Objective:
Do as much as possible in XQuery without descending into the Java dungeon.

Solution:

1) import the serverCA.crt int a dedicated Java keystore (localtruststore.jks) that will act as truststore. This works probably also if the cert is imported in the global truststore but we did not want to pollute the global store while testing. Note that you have to set a password to protect the truststore during importing.

/keytool -v -importcert -keystore localtruststore.jks -file serverCA.crt

/2) instruct basex to use the newly created truststore plus the clientCERTKEY.p12 file as keystore for the client. This has been resolved by modifying the BaseX startup line to look like:
/
//java -Djavax.net.ssl.keyStore=path/to/clientCERTKEY.p12 -Djavax.net.ssl.keyStorePassword=THEGIVENPASSFORP12 -Djavax.net.ssl.keyStoreType=PKCS12 -Djavax.net.ssl.trustStore=path/to/localtruststore.jks -Djavax.net.ssl.trustStorePassword=THEPASSWORDFORTRUSTSTORE -jar BaseX.jar
/
3) Up to this point it worked fine. I just used http:send-request to send my request from a basexgui for instance and I was easily able to migrate the SAML assertion from the response to the request for the second service.

4) The second call failed because of an annoying (but rather common) issue with the server certificate whose DN entries did not match correctly the requiremnts for the second service url. So I had to write a Custom HostnameVerifier in Java (plenty of examples on the web). And unfortunately I had to pollute my xquery workflow (put the jar in library folder and link it up in the code like below).

/Java code for the verifier://
//package com.nw.tls;//
//
//import javax.net.ssl.HostnameVerifier;//
//import javax.net.ssl.HttpsURLConnection;//
//import javax.net.ssl.SSLSession;//
//
//public class LaxHostNameVerifier implements HostnameVerifier{//
//
//    public LaxHostNameVerifier() {//
//HttpsURLConnection.setDefaultHostnameVerifier(this);//
//    }//
////
//    @Override//
//    public boolean verify(String hostname, SSLSession session) {//
//        return true//;
//    }//
//}/

Code for including it into XQuery
/declare namespace Verifier = "java:com.nw.tls.LaxHostNameVerifier";//
//let $init := Verifier:new()/

5) In a last effort we've found out a way to link extra jars by declaring them as java agents on the startup line. So I was finally able to use my pure XQuery flow by just enriching the startup line like below:

/java -Djavax.net.ssl.keyStore=path/to/clientCERTKEY.p12 -Djavax.net.ssl.keyStorePassword=THGIVENPASSFORP12 -Djavax.net.ssl.keyStoreType=PKCS12 -Djavax.net.ssl.trustStore=path/to/localtruststore.jks -Djavax.net.ssl.trustStorePassword=THEPASSWORDFORTRUSTSTORE -javaagent:LaxHostnameVerifierAgent.jar -jar BaseX.jar/

Thats'all folks.
Final question to Christian ... instead of ignoring certificates altogether could you plan for a less risky option IGNORE_HOSTNAME_VERIFICATION which just ignores the verification of the host name of a certificate? I think this is such a common case that it might deserve a dedicated flag. Isn't it?

Thanks for the support.
Kind regards and Seaon Greetings to wveryone!
Marco.

On 11/12/2017 21:41, Christian Grün wrote:
That’s good news, Marco!

All I remember was that I updated the Java keystore with certificates
in the part in order to be able to use the https protocol. The
IGNORECERT option can be disabled to ignore certificates.

Looking forward to your »success story«,
Christian


On Mon, Dec 11, 2017 at 9:37 PM, Marco Lettere <m.lett...@gmail.com> wrote:
Hi again,
your words put me on the right way. My doubt was how to pass the information
to the http module send-request functon.
After some investigation I've found out that it may be done by setting some
env variables through -D in the startup scripts pointing to server and
client certificates put in proper keystore and truststore.
At this point http:send-request will transparently use the mutual
certificate exchange without any fiddling with Java code!
That's absolutely great!

Now I'm very close to the final solution and just need to relax the default
hostname verifier. Anyone already did this with basex?

Thanks again for everything.
Marco.

[1] java -cp "$CP" -Djavax.net.ssl.keyStore=/path/to/keystore.p12
-Djavax.net.ssl.keyStorePassword=thepass -Djavax.net.ssl.keyStoreType=PKCS12
-Djavax.net.ssl.trustStore=/path/to/trustsotre.jks
-Djavax.net.ssl.trustStorePassword=thepass $BASEX_JVM org.basex.BaseXGUI
"$@"

On 07/12/2017 22:02, Christian Grün wrote:
Ciao Marco.

Just wanted to be sure that there isn't a way to do everything in XQuery.
Is
it?
I think the HTTP Module could be used for that. What have you tried so
far?

Saluti
Christian



Reply via email to