Blog Home  Sign In RSS 2.0 Atom 1.0 CDF  

  def Softwaremaker() :
         return "William Tay", "<Challenging Conventions />"

  knownType_Serialize, about = Softwaremaker()
 

 Saturday, November 27, 2004
« WSE 2.0 SP2 is here | Main | Chinese Mandarin Language Semantics »
 
Had a good brief chat with Plumbers: John Bristowe and Steve Maine on this issue.
 
[Just added: Hervey Wilson [Dev Lead of WSE] has this to reply to this post.. Thanks Hervey for your thoughts on this issue.]
 

My confusion seems to come from reading the WS-Security specs on both MSDN and OASIS. The MSDN copy that wasnt the OASIS standard says and incidentally was implemeted through WSE 1.0 :
 
An intermediary on the message path MAY add one or more new sub-elements to an existing <Security> header block if they are targeted for the same SOAP node
 
However, the same specs on OASIS reads:
 
An active intermediary on the message path MAY add one or more new sub-elements to an existing <wsse:Security> header block if they are targeted for its SOAP node
 
IMHO, that IS a whole lot of difference. The first specs indicate that you can change the securityHeaders if they are going to the same soap node. In this case, if I am assuming that the same soap node = ulitmate receiver, I can basically access something NOT meant for me.
 
However, the meaning on the OASIS one is slightly different. It says that I can change the securityHeaders if it is meant for itself (its SOAP node). That changed the whole thing quite a bit. It doesnt say now that I can change or add additional elements into the securityHeaders for the ultimate receiver. To be honest, and I have read this line many times to make sure I got the context right, I dont see the point in adding any sub-elements to a security header block that is targetted at itself. It doesnt really make much sense, if any, at all.
 
John is definitely right in saying that I shouldnt be trying to use security headers targeted for the ultimate receiver inside the context of a SOAP intermediary. In most cases, the security element(s) targeted for the final destination will be signed. Therefore, providing access via the object model doesn't make sense because manipulating these headers would invalidate the digital signature.
 
I definitely agree with him on this. That is one of the reasons why WS-Routing was superseded by WS-Addressing.
 
And of course, WSE 2.0 implements the OASIS-standard WS-Security Specs.
 
However, I am looking at the idea of taking the securityHeaders meant for someone else that arent signed and sign it. The final SOAP actor can and will only accept a message that is signed by its adjacent node and NOT the initial actor, per se. Does this idea sound far-fetched ?

 
I have done some reading into the WS-Security Specs and also cracked open [aka Reflect()] WSE 2.0 to see how it implements and processes the Security Headers.
 
First of all, do take note of this very important specification block found in the OASIS-standard WS-Security Specs.
 
“The header block provides a mechanism for attaching security-related information targeted at a specific recipient in the form of a SOAP actor/role. This may be either the ultimate recipient of the message or an intermediary. Consequently, elements of this type may be present multiple times in a SOAP message. An active intermediary on the message path MAY add one or more new sub-elements to an existing header block if they are targeted for its SOAP node or it MAY add one or more new headers for additional targets. As stated, a message MAY have multiple header blocks if they are targeted for separate recipients. However, only one header block MAY omit the S11: actor or S12: role attributes. Two header blocks MUST NOT have the same value for S11: actor or S12: role. Message security information targeted for different recipients MUST appear in different header blocks. This is due to potential processing order issues (e.g. due to possible header re-ordering). The header block without a specified S11: actor or S12: role MAY be processed by anyone, but MUST NOT be removed prior to the final destination or endpoint..."
 
This boils down to another interesting fundamental concept of trust here which Steve Maine talks about here in which he asked if Trust is Point-to-Point or End-to-End ?
 
The intermediary is a very important concept of SOAP Routing extensibility and is pretty much explains the processing model of SOAP messages. An intermediary sits between the initial sender and the ultimate receiver and intercepts SOAP messages. An intermediary acts as both a SOAP sender and a SOAP receiver at the same time. Intermediary nodes make it possible to design some interesting and flexible networking architectures that can be influenced by message content.
 
While processing a message, a SOAP node assumes one or more roles that influence how SOAP headers are processed. SOAP 1.1 only defines a single role named http://schemas.xmlsoap.org/soap/actor/next (next, for short). Every SOAP node is required to assume the next role. Hence, when a SOAP message arrives at any given SOAP node, the node must process all mandatory headers targeted at the next role, and it may choose to process optional headers also targeted at the next role. In addition to next, SOAP 1.2 adds two new predefined roles to the existing "Next" role in SOAP 1.1 which is the "None" and the "Ultimate Receiver" role.

SOAP headers target specific roles through the global actor attribute (SOAP 1.1). When you send a SOAP message to a receiving service without specifying the actor value, the actor attribute will be absent from the header. In this case, the header is targeted at the ultimate receiver by default. If a SOAP node successfully processes a header, it MUST remove the header from the message. SOAP nodes are allowed to reinsert headers, but doing so changes the contract parties—it's now between the current node and the next node the header targets (Point-to-Point Node-to-Node Trust ?).

In WSE 2.0, security headers can be processed if any of the following conditions are true:
  • Actor is equal to ActorNext.
  • Actor matches this node.
  • Actor is empty and the IsIntermediary property of context is false .

From my understanding of the above, an endpoint (not an intermediary) should assume 3 roles --- Its own role, an actorless security header and also must process one that says next.

However, if I send 2 security headers (one for "http://schemas.xmlsoap.org/soap/actor/next" and the other doesnt have an actor attribute) to an endpoint.asmx, it fails with a "The <EncryptedData> element referenced by the <ReferenceList> in the Security header could not be found" exception. I did some tracing and found that the later security header with the next role is appended to the security header with the actorless attribute. I believe it should have been prepended instead.

Cracking open the IL on SecurityInputFilter further reveals this.
 
There is a CanProcessHeader method that looks for the actorless attribute first, once it finds it, it processes it and removes it. Then, it then look for the ActorNext URI role.
 
This will not work in my case as the intermediary which has inserted the later next role security header by encrypting the SOAP message a second time needs to be processed and decrypted first. The CanProcessHeader method will definitely fail as it cannot find the actorless security header referenced security token without decrypting it with the tokens found in the next role security header first. However, WSE looks for the actorless attribute header first.

protected ...
...
string text1 = header.GetAttribute("actor", "http://schemas.xmlsoap.org/soap/envelope/");
if (text1.Length == 0)
{
if (context.IsIntermediary)
{
return false;
}
return true;
}
Uri uri1 = new Uri(text1);
if (!uri1.Equals(Soap.ActorNextURI) && !uri1.Equals(context.Actor))
{
return false;
}
return true;
}

I suppose I can try to re-arrange the security headers to a proper sequence although I would hate to do that (Am I supposed to be even doing that ?).
 
The funny thing is that if I choose not to encrypt the body a second time and instead just add the next role attribute security header instead (which means this second security header does nothing), it still throws me an exception
 
Microsoft.Web.Services2.Security.SecurityFault: An error was discovered processing the <Security> header
 
Could someone shed some light on this issue. Is an endpoint supposed to take on the role of the next actor attribute ? If so, shouldn't the security headers with a SOAP next role attribute (which is very likely to be input from an intermediary) be prepended to the actorless security header instead or is this a bug in WSE ?
 
[Just added: Hervey Wilson [Dev Lead of WSE] has this to reply to this post.. Thanks Hervey for your thoughts on this issue.]
Saturday, November 27, 2004 10:18:35 AM (Malay Peninsula Standard Time, UTC+08:00)  #    Disclaimer  Comments [2]
  • Blog reactions