Case sensitivity in namespace prefix affects XML Signature Operation

We were diagnosing an exception thrown in XML signature validation.


<Cannot check signature - Current Node: [#document: null]>



After digging around, we noticed that the XML in process is referencing an element with the name space value in different letter case.

The name space is declared as follows,


<SOAP-ENV:Envelope xmlns:SOAP-ENV=" ... >



But in the transform, we reference the element like this and turns out to be failed


<ds:Transform Algorithm="http://www.w3.org/...>

  <ds:XPath>
    not(ancestor-or-self::node()[@soap-env:actor=\"urn:oasis:names:tc:ebxml- ...

  </ds:XPath>

</ds:Transform>



Did you spot the difference? Yes, it's the case of "SOAP-ENV" declared in the Envelope to be upper case but the one referenced in the transform is in lower case.

Once it is fixed, all works.

H2O - Essential for your life

H2O

A couple of my entries are related to Hermes 2, the product that my team develops. Originally, two versions are provided, one as open source and one as closed source for commercial usage.

But on June 1, 2007, it's come to the end of the 2 products. Cause they will be merged into one - the H2O (pronounce as H-two-oh), which carries all the functions in the closed source, plus more.

H2O is a java application, that handles electronic messages, following the specification of ebMS and AS2. A web frontend is provided for configuration and status tracking. If you are looking for messaging solution, I sincerely recomment you to give H2O a try.

You can head to this location in getting the program, as well as related documentation. Additional information will be added to the website soon.

A Web Service Client in PEAR SOAP

In the preparation of my next episode on Hermes 2, I have been struggling on how to develop a web service client in technology other than Java. My primary candidate is definitely ruby, but I have to give up on it after playing it for a while. I just don't know how to construct a MIME message in Soap4r.

So, I headed to my second lover, PHP. From there, I have a couple of choices, NuSOAP, Pear SOAP and PHP Extension. I have decided to use Pear SOAP cause NuSOAP seems to be stopped from developing and PHP Extension is not something I am familiar with. With that said, let's move forward and see how it works.

Installation, embrace beta packages


I am not drilling into the details on how to compile PHP with Pear support, google on this topic and you should get loads of responses. There are 2 things that I feel worth mentioning.


  1. Change the preferred_state to beta so that you can install the latest version of PEAR::SOAP.


  2. pear config-set preferred_state beta



  3. After that, install all the dependency for SOAP, including Mail_MIME and Mail_DIME, if NOT, you will not be able to send multipart message.

    pear install -alldeps SOAP





Hurray! Now show me some code ...


OK ok ... First of all, create a new soap client and define the endpoint that it will be connecting to.


$url='http://images.vsmile.com:8080/corvus/httpd/ebms/sender';
$soapclient = new SOAP_Client($url);



After that, prepare the parameter which you will be sending over in the SOAP message, this parameter should be those required by the web service server for program execution. You should encapsulate all the value in the class SOAP::Value and put them into an array. Notice on the last value that I am packaging, I am using the SOAP_Attachment object which is a child of the SOAP_VALUE.


$params =
array (
new SOAP_VALUE('cpaId', 'nonEmptyToken', 'cecid'),
......
new SOAP_Attachment('SWA','text/xml','./dbhelper.xml')
)
;



Along with the program parameter, you will also need to define on how the SOAP message should be delivered. This include the document type of the message, how the file should be sent over as, etc. All these settings will again be encapsulated in an array.

From the code below, notice that I am defining the attachment will be sent over as a MIME message, i.e. a multipart message.


$options=array(
'namespace' => "http://service.ebms.edi.cecid.hku.hk/",
'soapaction' => '',
'style' => 'document',
'use' => 'literal',
'trace' => 1,
'timeout' => 30000,
'Attachments'=>'Mime'
);



With these, we can initiate the call!


$resp = $soapclient->call('query', $params, $options);



Damn it! It doesn't work!


Yes, it doesn't work to me either, until I read this.

I modified my SOAP_Base::_makeMimeMessage as instructed. Notice about the double quote surrounding "text/xml"? Axis reject the SOAP request if it is un-quoted.


$params = array('content_type' => 'multipart/related;
type=text/xml');


to


$params = array('content_type' => 'multipart/related;
type="text/xml"');


Ta-da, it works ok now!

The “Partnership” in Hermes

Let's talk about "Partnership", one of the term you should know well in using Hermes.

After finishing this episode, you will know on how to create a partnership and can deliver messages to my testing server.

A large Hawaii pizza with extra cheese, please!


So, what is partnership?

Take an analogy, when you go to order a pizza, the waiter will ask you a couple of questions. What is your favorite topping? What size do you want? Do you want extra cheese?

Right, partnership is your decision on how the messages should be transmitted.

Partnership is an "agreement", in between you and the people who gonna receive your message (let's call them a "partner"). This "agreement" defines on how the message will be sent, e.g. should the partner reply with a note upon receiving a message.

Ok, how could I place my order?


In the Hermes 2 packages, you can find execution script called "partnership.sh" (or partnership.bat), the script will invoke a java class that helps to create the partnership. The program gather the partnership values from the xml file, which can be found from the "data" directory.

The XML file contains all the major configuration that you can find from the message specification, and the default value are configured to create partnership for loopback test. You should be able to spot the meaning of each of them by the name of each element and configure the partnership as desired.

Thus, to create the partnership, all you need to do is,


  1. Modify the xml file, e.g. if you want to create a partnership to send ebms message, you should edit the file "ebms.xml"
  2. Execute the batch script "sh partnership.sh ebms -a data/ebms.xml"


One thing to note is, the script will assume the username and password for the database to be those defined in the installation guide. If not, you will need to change the value in the file "conf/partnership.module.core.xml"

Who else can take my order?


So, you might want to talk to someone else other than yourself. Don't worry, I have setup a testing server. But PLEASE be gentle, don't try to stress test my server. :D


  1. Open "data/ebms.xml"
  2. Modify the following line from


    <transportEndpoint>
      http://127.0.0.1:8080/corvus/httpd/ebms/inbound
    </transportEndpoint>



    to


    <transportEndpoint>
      http://images.vsmile.com:8080/corvus/httpd/ebms/inbound
    </transportEndpoint>

  3. Execute the shell script,



    sh loopback.sh ebms



  4. All should goes well like in the loopback test, mark down the message id for the next step.


How would I know if my order has been placed?


Visit this page and look for the message id you get in the previous step.

Found it? Congratulation, you have sent your first ebms message over the internet.

What you can do next is to play around with the rest of the setting, like enabling the receive of acknowledgement, setup your own pair of server and try to exchange messages (make sure the partnership setting aligns between the server).

Once you are familiar with this, you can go live to exchange electronic messages with your business partner. Have fun!

Setting up of the Hermes2 Messaging Gateway

Introduction



Hermes 2 (or Corvus, the codename we used to call in the office) is a messaging gateway that enables the handling of electronic messages in the format of AS2 or ebMS. For details, you can refer to our product web page.

I have noticed different questions in the mailing list, and as one of the developer behind the product, I hope my contribution can help those people who is interested in using it.

First off, let's start our installation.

The procedures are basically the same as indicated in the installation guide but I will include a small section in answering some commonly asked question. Also, I want to bring up some interesting finding as I am going to deploy Hermes in a little bit different environment.

Prerequisite


Apart from the binary of Hermes 2, you will need to prepare some other supporting applications, note that I have replaced Postgres with Mysql cause my web host only provides the later one. :D

NOTE : I don't have time to test out everything on this platform so if you want full compliance, stick with Postgres. ;)



Configuration - Mysql


I will highlight the steps nvolved in using Mysql in place of Postgres, but for the rest of the installation, please check out the details from the installation guide.


  1. Create two databases, named as "as2" and "ebms" respectively
  2. Create an user "corvus", grant the right to "CREATE", "DELETE", "DROP", "SELECT", "INSERT", "UPDATE". Or you can simply grant ALL if you are as lazy as me.
  3. Modify the table schemas, replace "VARCHAR" with "VARCHAR(255)" and "BYTEA" with "BLOB". Or you can download my copy from here.
  4. Create the tables accordingly.


Configuration - Hermes


The configuration files in the binary is having Postgres configured as the database of choice. You will need to change the setting in using Mysql instead.



  1. Get yourself a nice editor, search for the string

    "org.postgresql.Driver"


    and replace it with

    "com.mysql.jdbc.Driver"



    Also, locate this as well,

    "jdbc:postgresql://localhost:5432/ebms"


    and replace it with,

    "jdbc:mysql://127.0.0.1:3306/ebms"



    Repeat the procedure for AS2.

  2. Put the jdbc driver of Mysql into the "lib" folder of the Corvus webapps

You can now startup the tomcat and check the various log files (catalina.out, corvus.log, ebms.log and as2.log) that no errors are thrown.

Configuration - Loopback test


Congratulation! Now you are just one step away from completion.

It doesn't mean all is set even if no error is thrown during startup, let's try out our installation with the loopback test. BUT since the program is developed with Postgres in mind so some changes has to be made.


  1. Copy the JDBC driver of Mysql into the lib folder and modify the execution batch files to include it in the classpath.
  2. Modify the file "partnership.module.corel.xml" in the "conf" folder. Do the same thing as in Step 1 in Hermes 2 configuration.

Ta-da, now you are all set and done. Run the loopback test as usual and you should get the following results,



- Module 'Corvus Partnership' initialized successfully.
Start sending AS2 loopback test case.
Sent AS2 loopback test case with returned message ID 20061117-170806-45901@210.245.164.9.
Start checking the received list.
Download the message from the list with ID 20061117-170806-45901@210.245.164.9.
Downloaded successfully.
End checking the received list.
============================
AS2 loop back test finished.
============================



Note



There's something funny upon executing the loopback test ...

I have encountered several DAO issues and turns out it is the case sensitivity in the SQL query. The DB tables are all created with a big cap for the first letter and somehow, in the SQL query, some of the statement is using lower cap and the mismatch leads to the DAO issue. I have changed the table name accordingly in all the DAO XML files and everything is working fine.

What if ...


You are lucky if everything can go in one pass. I will put up pointer to questions which I have seen many times in the google group.


  1. When I boot up Hermes 2, I saw this message in the corvus.log,

    Unsupported keysize or algorithm parameters



    This error will raise if you forgot to deploy the JCE patch. Make sure you are copying to the right location. Also, I found that I have to set the "JAVA_HOME" in my user profile in order to have the patch loaded properly.

  2. Why is the JDK version so specific? Can I use some other version like JDK 1.5?
    Trust me, you will save yourself a lot of time in using the version we request. We find that a method we rely on, has somehow been changed to a private method since 1.4.2_04, so you might experience issues like

    java.lang.IllegalAccessError: tried to access field
    org.apache.xpath.compiler.FunctionTable.m_functions from class org.apache.xml.security.Init



    For JDK 1.5, we have identified some code changes that need to be done before it can operate properly.
  3. Is the "wildcard" feature that was introduced in Hermes 1 still valid in Hermes 2?
    No, this feature has been taken away from Hermes 2, due to the change in principle from push mode to polling mode. You need to specify precisely on what are the messages you want to send or receive.
  4. OK, now everything is working, what if I want to write a client?
    To keep things simple, let's focus on ebms message delivery first. First of all, you need to create a "partnership" for sending out messages. You can do so by using the program in the loopback test, the program will read a "data" file which define the details of the partnership (think partnership to CPA in ebMS).
    After that, you develop your program and make a web service call to Corvus for message delivery. The web service call will include some of the key information you defined in the partnership, so that Corvus can pick up the rest (like where to send it to) from the database.
    The "end point" on Corvus that responsible for picking up the request is
    "http://127.0.0.1:8080/corvus/httpd/ebms/sender" and you need to supply the following information in the web service call,

    • cpaId
    • service
    • action
    • conversation id
    • from party id
    • from party id type
    • to party id
    • to party id type
    • ref to message id

    Also, you will want to create an "AttachmentPart" which carries the "payload" you want to send over to the recipient.
    Upon making the request, you should get a soap response. The body inside should contain an element called "message_id" and the value of this is a string. This is the "token" that Corvus generated for you. You can use this "token" to perform query.


I hope this episode can help you a bit in kicking start the installation. When you are busying in setting up the environment, I will prepare my next episode, focusing on the partnership thing and hope to bring you something more interesting. Stay tuned.