SoapExtension Problem

L

lissbpp

I’ve got a problem with a custom SoapExtension that uses encryption. I am
encrypting the <soap:Body> element using this library:
http://www.obviex.com/samples/EncryptionWithSalt.aspx. The error that I am
getting is intermittent for users (if a user tries the service again many
times it will work). The webservice gets around 50K requests per day and I
get around 100-200 of these errors, which is a fairly low occurrence but it’s
driving me nuts trying to figure out the problem.
This is a smart client application that shares an assembly both on the agent
and server that deals with the SoapExtension. The SoapExtension is
configured in app.config and web.config respectively.
My problem:
For some reason I am getting SoapMessages that do not have a closing
</soap:Body> & </soap:Envelope> on both the client and server. Exception
reads: “Unexpected end of file has occurred. The following elements are not
closed: soap:Body, soap:Envelope.â€
Example soap message:
<?xml version="1.0" encoding="utf-8"?><soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Header><EncryptionHeader
xmlns="http://mystuff.com " /></soap:Header><soap:Body>Gv/RcjUTg8ctp…[END]
The SoapExtension:
using System;
using System.Text;
using System.Web.Services.Protocols;
using System.IO;
using System.Web.Services;
using System.Net;
using System.Xml;
using System.Text.RegularExpressions;

namespace MyStuff
{
public class SoapExtension : SoapExtension
{
Stream _wireStream;
Stream _applicationStream;

public override Stream ChainStream(Stream stream)
{
_wireStream = stream;
_applicationStream = new MemoryStream();
return _applicationStream;
}

public override object GetInitializer(LogicalMethodInfo methodInfo,
SoapExtensionAttribute attribute)
{
return null;
}

public override object GetInitializer(Type WebServiceType)
{
return null;
}

public override void Initialize(object initializer)
{
return;
}

void Copy(Stream from, Stream to)
{
TextReader reader = new StreamReader(from);
TextWriter writer = new StreamWriter(to);
writer.WriteLine(reader.ReadToEnd());
writer.Flush();
}

private void WriteInput()
{
string soapMessage = string.Empty;
try
{
XmlDocument soapXML = new XmlDocument();

string passPhrase = "XXX"; // can be any string
string initVector = "XXX†// must be 16 bytes

// Before encrypting data, we will append plain text to a
random
// salt value, which will be between 4 and 8 bytes long
(implicitly
// used defaults).
Crypto crypto = new Crypto(passPhrase, initVector);

TextReader streamReader = new StreamReader(_wireStream);
TextWriter streamWriter = new
StreamWriter(_applicationStream);

soapMessage = streamReader.ReadToEnd();

soapXML.LoadXml(soapMessage);

XmlNamespaceManager xmlnsSoap = new
XmlNamespaceManager(soapXML.NameTable);
xmlnsSoap.AddNamespace("soap",
"http://schemas.xmlsoap.org/soap/envelope/");

//NOTE: If we have an encryption header lets decrypt the
packet <soap:Body> only
XmlNode soapHeader =
soapXML.SelectSingleNode("soap:Envelope/soap:Header", xmlnsSoap);
if (soapHeader != null)
{
if (soapHeader["EncryptionHeader"] != null)
{
XmlNode bodyNode =
soapXML.SelectSingleNode("soap:Envelope/soap:Body", xmlnsSoap);

bodyNode.InnerXml = crypto.Decrypt(bodyNode.InnerXml);
}
}

streamWriter.Write(soapXML.OuterXml);
streamWriter.Flush();

Copy(_wireStream, _applicationStream);
//NOTE: Rewind stream to the begining
_applicationStream.Position = 0;
}
catch (Exception ex)
{
ex.Data.Add("SoapMessage", soapMessage);
ExceptionProvider.HandleException(ex, "Client");
}
}

private void WriteOutput()
{
string soapMessage = string.Empty;
try
{
_applicationStream.Position = 0;

XmlDocument soapXML = new XmlDocument();

string passPhrase = "XXX"; // can be any string
string initVector = "XXX"; // must be 16 bytes

// Before encrypting data, we will append plain text to a
random
// salt value, which will be between 4 and 8 bytes long
(implicitly
// used defaults).
Crypto crypto = new Crypto(passPhrase, initVector);

TextReader streamReader = new
StreamReader(_applicationStream);
TextWriter streamWriter = new StreamWriter(_wireStream);

soapMessage = streamReader.ReadToEnd();

soapXML.LoadXml(soapMessage);

XmlNamespaceManager xmlnsSoap = new
XmlNamespaceManager(soapXML.NameTable);
xmlnsSoap.AddNamespace("soap",
"http://schemas.xmlsoap.org/soap/envelope/");

//NOTE: If we have an encryption header lets encrypt the
packet <soap:Body> only
XmlNode soapHeader =
soapXML.SelectSingleNode("soap:Envelope/soap:Header", xmlnsSoap);

if (soapHeader != null)
{
if (soapHeader["EncryptionHeader"] != null)
{
bodyNode.InnerText =
crypto.Encrypt(bodyNode.InnerXml);
}
}

streamWriter.Write(soapXML.OuterXml);
streamWriter.Flush();

//NOTE: Rewind stream to the begining
Copy(_applicationStream, _wireStream);
}
catch (Exception ex)
{
ex.Data.Add("SoapMessage", soapMessage);
ExceptionProvider.HandleException(ex, "Client");
}
}



public override void ProcessMessage(SoapMessage message)
{
switch (message.Stage)
{
case SoapMessageStage.BeforeDeserialize:
WriteInput();
break;
case SoapMessageStage.AfterDeserialize:
break;
case SoapMessageStage.BeforeSerialize:
break;
case SoapMessageStage.AfterSerialize:
WriteOutput();
break;
default:
throw new Exception("invalid stage");
}
}
}
}

Any help would be greatly appreciated.
 
J

John Saunders [MVP]

lissbpp said:
I’ve got a problem with a custom SoapExtension that uses encryption. I
am
encrypting the <soap:Body> element using this library:
http://www.obviex.com/samples/EncryptionWithSalt.aspx. The error that I
am
getting is intermittent for users (if a user tries the service again many
times it will work). The webservice gets around 50K requests per day and
I
get around 100-200 of these errors, which is a fairly low occurrence but
it’s
driving me nuts trying to figure out the problem.

....

I don't have time now to read all of your code. However, I note that you
have a number of objects that implement IDisposable, but which you are not
using inside of a using block. For instance, in WriteInput, I believe I
would have:

using (TextReader streamReader = new StreamReader(_wireStream))
{
using (TextWriter streamWriter = new StreamWriter(_applicationStream))
{
// ...
}
}
 
L

lissbpp

I'm getting a "Stream was not readable" exception when I wrap the streams up
in using blocks. The exception is not coming from my SoapExtension but from
deep within the framework:

<stackTrace> at System.IO.StreamReader..ctor(Stream stream, Encoding
encoding, Boolean detectEncodingFromByteOrderMarks, Int32 bufferSize)
at
System.Web.Services.Protocols.SoapHttpClientProtocol.GetReaderForMessage(SoapClientMessage message, Int32 bufferSize)
at
System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall)
at
System.Web.Services.Protocols.SoapHttpClientProtocol.InvokeAsyncCallback(IAsyncResult result)</stackTrace>
 
J

John Saunders [MVP]

lissbpp said:
I'm getting a "Stream was not readable" exception when I wrap the streams
up
in using blocks. The exception is not coming from my SoapExtension but
from
deep within the framework:

<stackTrace> at System.IO.StreamReader..ctor(Stream stream, Encoding
encoding, Boolean detectEncodingFromByteOrderMarks, Int32 bufferSize)
at
System.Web.Services.Protocols.SoapHttpClientProtocol.GetReaderForMessage(SoapClientMessage
message, Int32 bufferSize)
at
System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage
message, WebResponse response, Stream responseStream, Boolean asyncCall)
at
System.Web.Services.Protocols.SoapHttpClientProtocol.InvokeAsyncCallback(IAsyncResult
result)</stackTrace>

Did you get that error when wrapping the StreamReader/StreamWriter? I can
imagine that StreamReader.Dispose might close the corresponding stream,
which would be a problem for .NET.
 
L

lissbpp

Indeed that's what I did and that's probably why the runtime is blowing
chunks when disposing the stream.
 
L

lissbpp

Any other suggestions?

John Saunders said:
Did you get that error when wrapping the StreamReader/StreamWriter? I can
imagine that StreamReader.Dispose might close the corresponding stream,
which would be a problem for .NET.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,154
Members
46,702
Latest member
LukasConde

Latest Threads

Top