Tuesday, 19 July 2011

The server committed a protocol violation. Section=ResponseStatusLine

Recently while I was working with an IP camera from my C# application and trying to get the image, I come to this problem:
The server committed a protocol violation. Section=ResponseStatusLine
According to http://blog.webmastersam.net/post/Solution-for-The-server-committed-a-protocol-violation.aspx, the problem is caused by:

Unsafe header parsing is an option you can turn on on your ASP.Net website (in the web.config) to allow the framework to parse responses. But what is an unsafe header ? It is a header in which the keys contains one or more spaces (that is not allowed in the HTTP 1.1 specifications).
The common case is having a space in the "content-length" header key. The server actually returns a "content length" key, which, assuming no spaces are allowed, is considered as an attack vector (HTTP response split attack), thus, triggering a "HTTP protocol violation error" exception.
In most weblogs, the solution to this problem is just a simple change in web.config file for ASP .NET projects:
Just add the following code to the web.config file:
<system.net>
   <settings>
      <httpWebRequest useUnsafeHeaderParsing="true" />
   settings>
system.net>


BTW, my solution is a desktop application, not a web application, so I do not have any web.config file. An alternative way to solve this problem is:

public static bool SetUseUnsafeHeaderParsing(bool b)
{
    Assembly a = Assembly.GetAssembly(typeof(System.Net.Configuration.SettingsSection));
    if (a == null) return false;

    Type t = a.GetType("System.Net.Configuration.SettingsSectionInternal");
    if (t == null) return false;
           
    object o = t.InvokeMember("Section",
        BindingFlags.Static | BindingFlags.GetProperty | BindingFlags.NonPublic, null, null, new object[] { });
    if (o == null) return false;
    FieldInfo f = t.GetField("useUnsafeHeaderParsing", BindingFlags.NonPublic | BindingFlags.Instance);
    if (f == null) return false;

    f.SetValue(o, b);
    return true;
}

You just need to add this function and call it passing true to it. That's all, it is done!