Entwickler-Ecke

Sonstiges (.NET) - Entschlüsseln einer xml response im WCF client


jahuer1 - Do 17.02.11 12:02
Titel: Entschlüsseln einer xml response im WCF client
Ich habe einen WCF client, der über eine sichere Verbindung einen Webservice aufruft. Die Meldungen sind signiert und verschlüsselt.

Frage:
Wenn ich nun die Response erhalte: Wie bekomme ich die SOAP-Message in dem Moment, in dem sie zwar noch signiert aber schon entschlüsselt ist?

Mit dem Zustand signiert und verschlüsselt habe ich kein Problem. Den habe ich.

Ziel:
Die hereinkommenden (Klartext)-SOAP-Messages sollen geloggt werden.


Ralf Jansen - Do 17.02.11 12:08

Du kennst das eingebaute Logging [http://msdn.microsoft.com/de-de/library/ms730064.aspx] von WCF?
Richtig konfiguriert gehe ich davon aus das sich dein Anforderung damit abdecken lässt.


jahuer1 - Do 17.02.11 15:21

Das wäre am Anfang beim Generieren des Clients alle Einstellungen machen. (?)

Wie könnte man das zur Laufzeit einschalten? (und auch wieder ausschalten)
Die Logs - wenn wir sie denn so bezeichnen wollen - sollten vom Programm (client) selber verwaltet/angeschaut/etc. werden können und nicht von einem zusätzlichen Programm.

Das müsste wohl irgendwie mit einem Intercepter funktionieren. Aber wie?


jahuer1 - Fr 18.02.11 12:55

Ich habe es mit einem Interceptor probiert. Das Resultat ist leider noch unbrauchbar! :evil:


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
internal class myInterceptor : ChannelMessageInterceptor

        public override void OnReceive(ref Message message)        
        {            
            SaveMessage(ref message, ResponseFilename);
            ModifySecurityTokenReference(ref message);

// *1* Hier würde ich gerne "message" vollständig auslesen können!

        }

        private void ModifySecurityTokenReference(ref Message message)
        {
            if (ClientCertificate!=null)
            {
                MemoryStream memoryStream = new MemoryStream();
                XmlTextWriter writer = new XmlTextWriter(memoryStream, Encoding.UTF8);
                message.WriteMessage(writer);
                writer.Flush();

                memoryStream.Position = 0;
                XmlDocument doc = new XmlDocument();
                doc.PreserveWhitespace = true;
                doc.Load(memoryStream);

                XmlNamespaceManager nsmanager = new XmlNamespaceManager(doc.NameTable);
                nsmanager.AddNamespace("wsse",myUtils.WsseNs);
                nsmanager.AddNamespace("soapenv", myUtils.SoapenvNs);
                nsmanager.AddNamespace("ds", myUtils.DsNs);
                nsmanager.AddNamespace("soapenc", myUtils.SoapencNs);
                nsmanager.AddNamespace("e", myUtils.XmlencNs);
                XmlNode keyInfoNode =
                    doc.SelectSingleNode("/soapenv:Envelope/soapenv:Header/wsse:Security/e:EncryptedKey/ds:KeyInfo",
                                         nsmanager);

                //Check if the response is encrypted 
                if (keyInfoNode != null)
                {
                    XmlNode securityTokenReferenceNode = keyInfoNode.SelectSingleNode("wsse:SecurityTokenReference", nsmanager);
                    XmlNode keyIdentifierNode = securityTokenReferenceNode.SelectSingleNode("wsse:KeyIdentifier", nsmanager);

                    XmlElement x509Data = doc.CreateElement("ds""X509Data", myUtils.DsNs);
                    XmlElement x509IssuerSerial = doc.CreateElement("ds""X509IssuerSerial", myUtils.DsNs);
                    XmlElement x509IssuerName = doc.CreateElement("ds""X509IssuerName", myUtils.DsNs);
                    x509IssuerName.InnerText = ClientCertificate.Issuer;
                    XmlElement x509SerialNumber = doc.CreateElement("ds""X509SerialNumber", myUtils.DsNs);
                    x509SerialNumber.InnerText = long.Parse(ClientCertificate.SerialNumber, NumberStyles.HexNumber).ToString();
                    x509Data.AppendChild(x509IssuerSerial);                    
                    x509IssuerSerial.AppendChild(x509IssuerName);
                    x509IssuerSerial.AppendChild(x509SerialNumber);

                    securityTokenReferenceNode.ReplaceChild(x509Data, keyIdentifierNode);

                }
                // Clone message                    
                XmlTextReader reader = new XmlTextReader(new StringReader(doc.OuterXml));
                Message replacedMessage = Message.CreateMessage(reader, int.MaxValue, message.Version);
                message = replacedMessage;
            }
        }


Wenn ich nun beim Punkt *1* "message" auslesen will, bekomme ich folgendes:


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
    <soap:Header>
        <wsse:Security soap:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
. . .  <!-- Hier ist alles okay -->
        </wsse:Security>
    </soap:Header>
    <soap:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="id-21630">... Datenstrom ...</soap:Body>
</soap:Envelope>


Aber "... Datenstrom ..." wäre ja gerade der Teil, den ich haben möchte! :cry:

Also: Wie bekomme ich meine SOAP-Message-Response in vollständigem Zustand?

@Ralf Jansen: Das WCF-logging hat auch nicht mehr geboten als diese Information. Eher sogar weniger!