<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Matt Mitchell &#187; Technical</title>
	<atom:link href="http://mattmitchell.com.au/topics/technical/feed/" rel="self" type="application/rss+xml" />
	<link>http://mattmitchell.com.au</link>
	<description></description>
	<lastBuildDate>Thu, 23 Feb 2017 06:48:03 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5</generator>
		<item>
		<title>Birthday Problems, Friendly Identifiers, and MongoDB</title>
		<link>http://mattmitchell.com.au/birthday-problems-friendly-identifiers-and-mongodb/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=birthday-problems-friendly-identifiers-and-mongodb</link>
		<comments>http://mattmitchell.com.au/birthday-problems-friendly-identifiers-and-mongodb/#comments</comments>
		<pubDate>Fri, 26 Jun 2015 08:38:44 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://mattmitchell.com.au/?p=238</guid>
		<description><![CDATA[<p>Recently I came across a bit of an interesting problem. An application I was working with had functionality that required the generation of user-friendly identifiers (e.g. 8 or less numbers). This seemed to be working pretty well the first day &#8230; <a href="http://mattmitchell.com.au/birthday-problems-friendly-identifiers-and-mongodb/">Continue reading <span class="meta-nav">&#8594;</span></a></p><p>Posted as <a href="http://mattmitchell.com.au/birthday-problems-friendly-identifiers-and-mongodb/">Birthday Problems, Friendly Identifiers, and MongoDB</a> at <a href="http://mattmitchell.com.au">Matt Mitchell</a></p>]]></description>
				<content:encoded><![CDATA[<p>Recently I came across a bit of an interesting problem.</p>
<p>An application I was working with had functionality that required the generation of user-friendly identifiers (e.g. 8 or less numbers). This seemed to be working pretty well the first day we looked at it: each new user was getting an incremental ID and things were smooth.</p>
<p><a href="http://mattmitchell.com.au/wp-content/uploads/2015/06/Counters1.png"><img src="http://mattmitchell.com.au/wp-content/uploads/2015/06/Counters1.png" alt="Counters1" width="287" height="39" class="alignnone size-full wp-image-253" /></a></p>
<p>The second day there was a reasonable gap overnight in the ID range and as far as I could tell the bank account wasn&#8217;t overflowing with new business, so that was a bit odd. Still, I let it go as it didn&#8217;t seem to be doing any major harm yet.</p>
<p><a href="http://mattmitchell.com.au/wp-content/uploads/2015/06/Counters2.png"><img src="http://mattmitchell.com.au/wp-content/uploads/2015/06/Counters2.png" alt="Counters2" width="318" height="71" class="alignnone size-full wp-image-254" /></a></p>
<p>Third day there was a gap overnight again, and this time it had wrapped around and started generating lower identifiers!</p>
<p><a href="http://mattmitchell.com.au/wp-content/uploads/2015/06/Counters3.png"><img src="http://mattmitchell.com.au/wp-content/uploads/2015/06/Counters3.png" alt="Counters3" width="341" height="106" class="alignnone size-full wp-image-255" /></a></p>
<p>While not a major issue in terms of sequencing or overflow (we just needed unique IDs), I was immediately concerned about whether the identifiers were really unique: why were we getting nightly &#8220;jumps&#8221; and how quick until we got unlucky enough to start overlapping?</p>
<p>It was time to look under the hood.</p>
<h2>MongoDB ObjectIds and UUIDs</h2>
<p>The application was using <a href="https://www.mongodb.org/">MongoDB</a> for storage. Though I&#8217;d come across the NoSQL concept since around 2009 through <a href="http://avc.com/2009/07/hacker-news-and-the-nosql-movement/">the usual channels</a>, I was admittedly fairly late to putting it into much practice. So it came as a bit of a surprise that MongoDB did not have out-of-the-box functionality to generate incremental identity values, but instead relies on a <a href="http://docs.mongodb.org/manual/tutorial/create-an-auto-incrementing-field/">bit of scripting</a> to achieve a similar approach.</p>
<p>Of course pausing for a moment and thinking about high-performance distributed environments I realised it made some sense to have an independent process to reliably generate unique identifiers (e.g. <a href="http://stackoverflow.com/questions/1705008/simple-proof-that-guid-is-not-unique">UUID Generation</a>) that did not depend on insert locking and allowed nodes to act independently.</p>
<p>In fact, the MongoDB BSON ObjectId values look and feel pretty much like a custom UUID along the lines of <a href="https://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>.</p>
<p>Contrast <a href="http://blogs.msdn.com/b/oldnewthing/archive/2008/06/27/8659071.aspx">UUIDs/GUIDs</a>:</p>
<ul>
<li>60 bits of timestamp</li>
<li>48 bits of computer identifier</li>
<li>14 bits of uniquifier</li>
<li>6 bits are fixed</li>
<li>128 bits total (16 bytes)</li>
</ul>
<p>With the <a href="http://docs.mongodb.org/manual/reference/object-id/">BSON ObjectId</a></p>
<ul>
<li>32 bits representing the seconds since the Unix epoch</li>
<li>24 bits of machine identifier</li>
<li>16 bits of process id</li>
<li>24 bits for an increment counter, starting with a random value</li>
<li>96 bits total (12 bytes)</li>
</ul>
<p>Importantly, as with GUID&#8217;s a <a href="http://blogs.msdn.com/b/oldnewthing/archive/2008/06/27/8659071.aspx">substring of the full identifier is not unique</a>. This is pretty natural when you consider that your substring might just be the timestamp (and two PCs could have the same timestamp, you might generate two IDs at the same time, clocks can change, <a href="http://derickrethans.nl/leap-seconds-and-what-to-do-with-them.html">leap seconds</a> etc.).</p>
<h2>The MongoDB Increment Counter</h2>
<p>With this in mind, returning to my recent MongoDB experience I noticed that while the standard full BSON ObjectId values were being used for object identifiers (good), it was clear that the user identifiers were being generated elsewhere to ensure they had something more user-friendly than 24 alphanumeric characters.</p>
<p>To this end someone had decided to use the <strong>increment counter</strong> value of the BSON ObjectId, which made some sense given <a href="http://docs.mongodb.org/manual/reference/object-id/">the description</a> of &#8220;a counter, starting with a random value&#8221;.</p>
<p>Indeed this incremental behaviour is what you would see during a test run, with wrapping should the counter be exceeded (say due to a high initial random value). Furthermore, at 3 bytes the value was effectively an unsigned mediumint as well, which meant a maximum of 16777215 or 8 digits or less for users to recite, and plenty of space for our expected number of lifetime identifiers. Perfect right?</p>
<p>Clearly something wasn&#8217;t lining up, so I dove in with Reflector and had a look at the <a href="http://docs.mongodb.org/ecosystem/drivers/csharp/">MongoDB driver code</a>, specifically <code>GenerateNewId</code> in <code>MongoDB.Bson.ObjectId</code>.</p>
<p>As described, at first glance it was a counter just incrementing away:</p>
<p><a href="http://mattmitchell.com.au/wp-content/uploads/2015/06/MongoDBGenerateNewId.png"><img src="http://mattmitchell.com.au/wp-content/uploads/2015/06/MongoDBGenerateNewId.png" alt="MongoDBGenerateNewId" width="685" height="228" class="alignnone size-full wp-image-258" /></a></p>
<p>But incrementing what?</p>
<p><a href="http://mattmitchell.com.au/wp-content/uploads/2015/06/MongoDBCounter.png"><img src="http://mattmitchell.com.au/wp-content/uploads/2015/06/MongoDBCounter.png" alt="MongoDBCounter" width="431" height="18" class="alignnone size-full wp-image-257" /></a></p>
<p>Ah, a static variable initialised with <code>new Random().Next()</code> &#8211; that would explain it. Each time the application was starting, or restarting, which was at least <a href="http://weblogs.asp.net/owscott/why-is-the-iis-default-app-pool-recycle-set-to-1740-minutes">every 29 hours</a>, this variable was being reset with a chance each time of landing on or near to a previously generated &#8220;increment value&#8221;. What&#8217;s more, if we had multiple application domains in the production environment we would have an even greater risk of overlapping.</p>
<p>Now of course for the purposes of an ObjectId the random seed is just one part of the puzzle so it presents fairly minimal issues unless <a href="http://stackoverflow.com/a/5694803/364">there are more than 1677715 (2^24) ObjectId&#8217;s generated in the same second</a>. The minimal risk of multiple AppDomains on the same machine generating the same increment counter within the same second is addressed by the inclusion of the Application Domain ID as part of the machine identifier component of the ObjectId. However, by taking just the increment counter in isolation we didn&#8217;t have these safeguards.</p>
<p>Then again, there were still nearly <strong>17 million</strong> possible counter spots: surely intuition would say the chances of getting the same counter again on an AppDomain restart was pretty low&#8230;</p>
<h2>The Birthday Problem</h2>
<p>So interesting trivia:</p>
<blockquote><p>
  What are the chances of two people in an average small office (say 23 people) having the same birthday?</p>
<p>  Something like 23/365? Maybe a bit lower or a bit higher?</p>
<p>  What about a larger office of say 70 people?</p>
</blockquote>
<p>Turns out (and you&#8217;ve probably heard this one before) that the small office has a 50% chance of two people sharing the same birthday, and the larger office has a 99.9% chance. Why does this matter? Well it turns out our counter regeneration was just an example of the <a href="https://en.wikipedia.org/wiki/Birthday_problem">Birthday Problem</a>, albeit with less funny hats than we&#8217;d usually hope for, and a disappointing absence of cake.</p>
<p>Running the numbers (via <a href="http://stackoverflow.com/a/22019172/364">a convenient bit of JS</a> ran through Chrome Dev Tools), it turned out after 4000 AppDomain restarts there was a 37% chance of overlapping, this was 52% by 5000 restarts, and 94.9% by 10000 restarts. While that <em>might</em> buy us a few months or even years, I didn&#8217;t want to be rolling the dice on uniqueness.</p>
<p><a href="http://mattmitchell.com.au/wp-content/uploads/2015/06/CalculatingBirthdayProblem.png"><img src="http://mattmitchell.com.au/wp-content/uploads/2015/06/CalculatingBirthdayProblem.png" alt="CalculatingBirthdayProblem" width="224" height="268" class="alignnone size-full wp-image-259" /></a></p>
<p>Just to be sure, I decided I&#8217;d also write up a quick simulator of the experience, factoring for the number of AppDomain restarts and the average number of generated identifiers each AppDomain. It became clear that there were some trade-offs depending on the generation rate vs the AppDomain restart rate, but the general principle held.</p>
<p>Indeed from just a couple of quick anecdotal runs (I&#8217;m sure it could be run and graphed properly):</p>
<ul>
<li>1 ID generation per AppDomain restart meant between 3,000 and 10,000 AppDomain restarts before a collision (equating to about as many days).</li>
<li>10 ID generations per AppDomain restart meant between 750 and 1,500 AppDomain restarts (meaning less days) before a collision, but between 7,500 and 15,000 generated IDs (an increased number of IDs). </li>
<li>100 ID generations per AppDomain restart meant only 250 to 500 AppDomain restarts but 25,000 to 50,000 generated IDs.</li>
<li>1000 ID generations per AppDomain restart meant 100 to 150 AppDomain restarts and 50,000 to 150,000 generated IDs.</li>
</ul>
<p><a href="http://mattmitchell.com.au/wp-content/uploads/2015/06/GraphingSimulation.png"><img src="http://mattmitchell.com.au/wp-content/uploads/2015/06/GraphingSimulation.png" alt="GraphingSimulation" width="742" height="225" class="alignnone size-full wp-image-256" /></a></p>
<p>While some of these rates were low enough that you could potentially last a couple of years, others were not, and it was ultimately a dangerous and unnecessary game of luck to be playing when there were good incremental alternatives.</p>
<p>Ultimately it meant we should either:</p>
<ol>
<li>Change the generation method to have a concept of already generated identifiers</li>
<li>Or, change the generation method to be unique without randomness or high collision risk (quite a challenge to keep short)</li>
<li>Or, accept the non-unique IDs, and request supporting info (e.g. as airlines do) when using the identifier.</li>
</ol>
<p>However, the overall takeaway was: <strong>Don&#8217;t use the MongoDB Increment value as a Unique Identifier.</strong></p>
<p>For reference here is the simulation code I whipped up and ran in <a href="https://www.linqpad.net/">LINQPad</a></p>
<pre><code>void Main()
{
     List&lt;int&gt; generatedIds = new List&lt;int&gt;();
     var r = new Random();

     for (int restart=0; restart&lt;100000; restart++)
     {
        int __staticIncrement = r.Next();

        for (int generated=0; generated&lt;1000; generated++)
        {
            int generatedId = __staticIncrement++ &amp; 16777215;
            generatedIds.Add(generatedId);

            if (generatedIds.Count(d =&gt; d == generatedId) &gt; 1)
            {
                //generatedId.Dump();
                (restart + " " + generated).Dump();
            }
        }
     }
}
</code></pre>
<p>Posted as <a href="http://mattmitchell.com.au/birthday-problems-friendly-identifiers-and-mongodb/">Birthday Problems, Friendly Identifiers, and MongoDB</a> at <a href="http://mattmitchell.com.au">Matt Mitchell</a></p>]]></content:encoded>
			<wfw:commentRss>http://mattmitchell.com.au/birthday-problems-friendly-identifiers-and-mongodb/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Preventing SQL Injection in BizTalk</title>
		<link>http://mattmitchell.com.au/preventing-sql-injection-in-biztalk/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=preventing-sql-injection-in-biztalk</link>
		<comments>http://mattmitchell.com.au/preventing-sql-injection-in-biztalk/#comments</comments>
		<pubDate>Mon, 22 Jul 2013 10:06:04 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Technical]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[BizTalk]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://mattmitchell.com.au/?p=8</guid>
		<description><![CDATA[<p>I was reviewing a solution recently using the BizTalk WCF-OracleDB Adapter and detected an interesting security vulnerability. Before you dismiss this as &#8220;I&#8217;m using SQL Server, I&#8217;ll be right mate&#8221;, this issue probably also affects the BizTalk WCF-SQL Adapter and &#8230; <a href="http://mattmitchell.com.au/preventing-sql-injection-in-biztalk/">Continue reading <span class="meta-nav">&#8594;</span></a></p><p>Posted as <a href="http://mattmitchell.com.au/preventing-sql-injection-in-biztalk/">Preventing SQL Injection in BizTalk</a> at <a href="http://mattmitchell.com.au">Matt Mitchell</a></p>]]></description>
				<content:encoded><![CDATA[<p>I was reviewing a solution recently using the <a href="http://social.technet.microsoft.com/wiki/contents/articles/6782.biztalk-adapter-pack-2010-wcf-oracledb-adapter-en-us.aspx">BizTalk WCF-OracleDB Adapter</a> and detected an interesting security vulnerability.</p>
<p>Before you dismiss this as <em>&#8220;I&#8217;m using SQL Server, I&#8217;ll be right mate&#8221;</em>, <strong>this issue probably also affects the <a href="http://social.technet.microsoft.com/wiki/contents/articles/6781.biztalk-adapter-pack-2010-wcf-sql-adapter-en-us.aspx">BizTalk WCF-SQL Adapter</a></strong> and while I haven&#8217;t addressed fixes for WCF-SQL specifically in this article, there may be helpful overlap.</p>
<p>In our case we were using plenty of code in <a href="http://msdn.microsoft.com/en-us/library/ee253554%28v=bts.10%29.aspx">Construct</a>/<a href="http://msdn.microsoft.com/en-us/library/ee253499%28v=bts.10%29.aspx">Assign</a> shapes to create new Oracle <code>Select</code> message instances. Something like this:</p>
<pre><code>// Create message
InvSelectMsg = Utility.CreateMessage("OurSchemas.InvoiceSelect"); 
InvSelectMsg.COLUMN_NAMES = "INVOICE_ID"; // SELECT
InvSelectMsg.FILTER = System.String.Format("REFERENCE = '{0}'", reference); // WHERE
</code></pre>
<p>This looks innocuous enough, but for anyone who&#8217;s worked on web apps without an <a href="http://en.wikipedia.org/wiki/Object-relational_mapping">ORM</a> (including the <a href="http://samsaffron.com/archive/2011/03/30/How+I+learned+to+stop+worrying+and+write+my+own+ORM">performance-constrained</a> or those simply <a href="http://staff.newtelligence.net/clemensv/PermaLink.aspx?guid=8a119c62-2fc1-4409-9ae4-0b250fdb785b">caught</a> <a href="http://www.tonymarston.net/php-mysql/object-relational-mappers-are-evil.html">in</a> <a href="http://en.wikipedia.org/wiki/Object-relational_impedance_mismatch">the</a> <a href="http://database-programmer.blogspot.com.au/2010/12/historical-perspective-of-orm-and.html">crossfire</a> <a href="http://www.agiledata.org/essays/impedanceMismatch.html">of</a> <a href="http://www.codinghorror.com/blog/2006/06/object-relational-mapping-is-the-vietnam-of-computer-science.html">an</a> <a href="http://www.codinghorror.com/blog/2004/07/why-objects-suck.html">ORM</a> <a href="http://blogs.tedneward.com/2006/06/26/The+Vietnam+Of+Computer+Science.aspx">battleground</a>) this stands out as a clear-cut <a href="http://en.wikipedia.org/wiki/SQL_injection">SQL Injection</a> <a href="http://en.wikipedia.org/wiki/SQL_injection#Examples">nightmare</a>.</p>
<p>Sure enough, testing confirmed there was a vulnerability, which so far I&#8217;ve seen when:</p>
<ul>
<li>Using a <a href="http://msdn.microsoft.com/en-us/library/ee253499%28v=bts.10%29.aspx">BizTalk Message Assignment Shape</a> to set the <code>FILTER</code> property of an <a href="http://msdn.microsoft.com/en-us/library/cc185500%28v=bts.10%29.aspx">Oracle Select message</a>.</li>
<li>Using <a href="http://msdn.microsoft.com/en-us/library/aa547076.aspx">BizTalk Maps</a> to set the <code>FILTER</code> property of an <a href="http://msdn.microsoft.com/en-us/library/cc185500%28v=bts.10%29.aspx">Oracle Select message</a>.</li>
<li>Building the <code>SQLSTATEMENT</code> property of an Oracle <a href="http://msdn.microsoft.com/en-US/library/cc185266%28v=bts.10%29"><code>SQLEXECUTE</code></a> message using user inputs other than those referenced via the <code>PARAMETERSET</code></li>
</ul>
<p>Counter-intuitively, <a href="http://msdn.microsoft.com/en-US/library/cc185266%28v=bts.10%29">SQLEXECUTE messages</a> are <strong><em>less</em></strong> likely to be affected by this issue than the <a href="http://msdn.microsoft.com/en-us/library/cc185500%28v=bts.10%29.aspx">&#8220;strongly-typed&#8221; message schemas</a>.</p>
<p>As a side note, one of the more concerning things for me is that I&#8217;ve regularly heard lines such as &#8220;Oracle prevents SQL Injection&#8221; by people who when pushed don&#8217;t seem to know what SQL injection is. What I <em>think</em> they mean is that Oracle prevents multiple statement execution, which while preventing a section of SQL Injection attacks, does not make Oracle immune.</p>
<h2>SQL Injection?</h2>
<p>The above sample renders to some SQL like this:</p>
<pre><code>SELECT INVOICE_ID FROM OracleInvoiceView WHERE REFERENCE = 'Some Invoice Ref'
</code></pre>
<p>But consider the case where <code>REFERENCE</code> includes a single quote character (e.g. <code>Invoice for Joey's Pianos</code>). The query is now:</p>
<pre><code>SELECT INVOICE_ID FROM OracleInvoiceView WHERE REFERENCE = 'Invoice for Joey's Pianos'
</code></pre>
<p>You can probably see from the syntax highlighting that the query ends at <code>Joey'</code> and then has the random extra text <code>Pianos'</code> sitting after the complete query which simply causes a parse error (the best-case in a SQL Injection scenario).</p>
<p>But what if that query was less innocuous? What if, Joey decided to send his <code>REFERENCE</code> as <code>Joey' OR 1=1 --</code>? The query would now return every <code>INVOICE_ID</code> in the system, letting Joey see his competitor&#8217;s data:</p>
<pre><code>--// This query shows Joey all invoices. 
--// Note the end -- to comment out the end single-quote and avoid an error 
SELECT INVOICE_ID FROM OracleInvoiceView WHERE REFERENCE = 'Joey' OR 1=1 --' 
</code></pre>
<p>Even worse, Joey might send <code>'; DELETE FROM BillsOutstanding; --</code> which could (depending on configuration as Oracle will usually prevent multiple statement execution preventing this particular extreme case) lead to both a <code>SELECT</code> and <code>DELETE</code> being executed against the database and all of your outstanding bills being wiped from the database.</p>
<pre><code>SELECT INVOICE_ID FROM OracleInvoiceView WHERE REFERENCE = ''; 
DELETE FROM BillsOutstanding; --'
</code></pre>
<p>If Joey was subtle enough in what was modified or deleted you might never discover there was an issue.</p>
<p><img src="http://imgs.xkcd.com/comics/exploits_of_a_mom.png" alt="Exploits of a Mom" /></p>
<p>[Source: <a href="http://xkcd.com/327/">xkcd</a>]</p>
<h2>Why hasn&#8217;t everyone noticed this already?</h2>
<p>I&#8217;m not sure, I have a couple of theories:</p>
<ul>
<li>Everyone else was smart enough to fix this issue and thought it too obvious to mention.</li>
<li>There&#8217;s a really good article out there already that I haven&#8217;t come across yet.</li>
<li>Everyone else is using the <code>SQLEXECUTE</code> schemas, and only using user-input via the <code>PARAMETERSET</code>.</li>
<li>BizTalk is often used for integration of controlled systems where this issue might not arise. (I&#8217;d still expect it to cause errors with standard non-malicious data though).</li>
</ul>
<h2>Why doesn&#8217;t this (usually) affect SQLEXECUTE messages?</h2>
<p>It appears that <code>SQLEXECUTE</code> schemas circumvent this issue by using <a href="http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/dynamic.htm#BJEDAHEE">Oracle Bind Arguments</a>, so the filter clause sent to Oracle looks like this <code>WHERE REFERENCE = :variable</code>, where the <code>:variable</code> value is set from the <code>PARAMETERSET</code> of the <code>SQLEXECUTE</code> message. For this reason <code>SQLEXECUTE</code> messages are most easily created in a map:</p>
<p><img src="http://mattmitchell.com.au/wp-content/uploads/2012/07/sql-execute-map.png" alt="SQLEXCEUTE BizTalk Map" /></p>
<p>These <code>PARAMETERSET</code> values are treated specially by Oracle to prevent injection (you&#8217;ve created <a href="http://en.wikipedia.org/wiki/Prepared_statement">a parametrised query</a>, so the values are never executed as <a href="http://en.wikipedia.org/wiki/PL/SQL">PL/SQL</a>). Of course, if you generate the actual <code>SQLSTATEMENT</code> section of your <code>SQLEXECUTE</code> message using user input (for example, <code>System.String.Format("SELECT Id FROM SomeView WHERE Column='{1}'", filterValue)</code>) then you&#8217;re back to square-one and facing SQL Injection issues. One interesting case I haven&#8217;t tested yet is <code>SQLEXECUTE</code> messages built using the <code>PARAMETERSET</code> using wildcard/<code>LIKE</code> filters.</p>
<h2>So what do I do?</h2>
<p>There&#8217;s a range of advice out there on how to address SQL Injection in your language of choice, including:</p>
<ul>
<li><a href="http://www.unixwiz.net/techtips/sql-injection.html">SQL Injection Attacks by Example</a> by Steve Friedl from Unixwiz.net</li>
<li><a href="http://ferruh.mavituna.com/sql-injection-cheatsheet-oku/">SQL Injection Cheat Sheet</a> by Ferruh Mavituna</li>
<li><a href="http://bobby-tables.com/">Bobby Tables &#8211; A guide to preventing SQL Injection</a></li>
<li><a href="http://msdn.microsoft.com/en-us/library/ff648339.aspx">How to Protect From SQL Injection in ASP.NET</a> from Microsoft Patterns &amp; Practices</li>
<li><a href="https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet">SQL Injection Prevention Cheat Sheet</a> from The Open Web Application Security Project</li>
</ul>
<p>Usually this boils down to making sure that user-input characters are always treated as user-input and not part of the actual SQL query syntax. This is usually achieved by:</p>
<ul>
<li>Parametrising the query.</li>
<li>Escaping non-parametrised special characters (e.g. single quotes)</li>
<li>Ensuring non-string values match their expected data type</li>
<li>Implementation specific details (depending on the specific SQL database and client used)</li>
</ul>
<p>For Oracle in particular some resources I came across included:</p>
<ul>
<li><a href="http://www.petefinnigan.com/orasec.htm">Oracle Security Papers</a> by Pete Finnigan (including SQL Injection and Oracle <a href="http://www.symantec.com/connect/articles/sql-injection-and-oracle-part-one">Part One</a> and <a href="http://www.symantec.com/connect/articles/sql-injection-and-oracle-part-two">Two</a>)</li>
<li><a href="http://www.oracle.com/technetwork/database/features/plsql/overview/how-to-write-injection-proof-plsql-1-129572.pdf">How to write SQL injection proof PL/SQL</a> from Oracle</li>
<li><a href="http://docs.oracle.com/cd/E14072_01/appdev.112/e10472/dynamic.htm#CHDFCHHJ">SQL Injection</a> and the linked topics on techniques and guarding from the Oracle Database PL/SQL Language Reference</li>
<li><a href="http://www.slaviks-blog.com/2009/10/13/blind-sql-injection-in-oracle/">Blind SQL Injection in Oracle</a> by Slavik Markovich (CTO for Database Security for McAfee)</li>
<li><a href="http://www.red-database-security.com/whitepaper/oracle_security_whitepaper.html">Oracle Security Whitepapers</a> from Red Database Security</li>
<li><a href="http://ferruh.mavituna.com/oracle-sql-injection-cheat-sheet-oku/">Oracle SQL Injection Cheat Sheet</a> by Ferruh Mavituna</li>
</ul>
<h2>Specifically?</h2>
<p>My solution for resolving Oracle SQL Injection in BizTalk, <strong>which is by no means fool-proof or applicable to every scenario</strong>, relies upon:</p>
<ol>
<li>Calling a utility function (to be detailed below) when setting <code>FILTER</code> values</li>
<li>Ensuring that the format string provided to the utility function places single-quotes around string parameters (<code>WHERE val = '{0}'</code> rather than <code>WHERE val = {0}</code>)</li>
</ol>
<p>Some of the known shortcomings of this method, which could be addressed with some further thought are:</p>
<ol>
<li>Does not ensure that numerics (or other non-string values?) match their expected data type (relies on the calling developer to enforce this)</li>
<li>Relies on developers to ensure their query format-string has quotes around string parameters</li>
<li>Relies on the <code>ToString</code> method of your provided parameters to return the desired representation for your query value (can&#8217;t see this being an issue, but it bears noting)</li>
</ol>
<p>At least one other alternative to my method is enforcing developers to create <code>FILTER</code>s with a fully parametrised class &#8211; something similar in usage to <a href="http://msdn.microsoft.com/en-us/library/z4956bkc"><code>System.Data.SqlClient.SqlCommand</code></a> &#8211; although you would need to ensure the implementation fully supports your target database and usage (in our case Oracle).</p>
<h2>Out with the code already!</h2>
<p>The most primitive bit of code is a simple string escape for single-quotes. Something like:</p>
<pre><code>static string EscapeParameter(object unescapedParameter)
{
    if (unescapedParameter == null)
        return String.Empty;

     // Escape quotes
     return unescapedParameter.ToString().Replace("'", "''"); 
}
</code></pre>
<p>You can then wrap this up with something like:</p>
<pre><code>static string EscapeWhere(string format, params object[] unescapedParameters) 
{ 
    /* Escape parameters */
    object[] escapedParameters = unescapedParameters
      .Select((param, index) =&gt; EscapeParameter(param))
      .ToArray();

    /* Return filter string with escaped parameters */
    return String.Format(format, escapedParameters);
}
</code></pre>
<p>This allows simple usage like this:</p>
<pre><code>SelectMsg = Utility.CreateMessage("OurSchemas.InvoiceSelect"); // Create message
SelectMsg.COLUMN_NAMES = "INVOICE_ID"; // SELECT
SelectMsg.FILTER = Utility.EscapeWhere("REFERENCE = '{0}'", reference); // WHERE
</code></pre>
<p><strong>However</strong>, this only supports your standard equivalence-style filters. What about wildcard filtering (<code>WHERE val LIKE '%input%'</code>)?</p>
<h2>Why is LIKE special?</h2>
<p>Wildcards/<code>LIKE</code> statements in your <code>WHERE</code> clause are a special case for SQL Injection, at least in Oracle.</p>
<p>Imagine the case where you want to search for products starting with <code>20% Off</code>:</p>
<pre><code>WHERE Title LIKE '20% Off%' --// This doesn't give us what we want!
</code></pre>
<p>Because percent (<code>%</code>) is a special wildcard character when using <code>LIKE</code>, we won&#8217;t get the results we are after (it will match <code>20 Special Things About Falling Off a Horse</code> for instance).</p>
<p>To address this, Oracle (like many languages) allows you to escape special characters like <code>%</code> with another special character. This escape character is usually a backlash (<code>\</code>) although in Oracle you can define your escape character by following your <code>LIKE</code> statement with an <code>ESCAPE '\'</code> statement.</p>
<blockquote><p>
  You can include the actual characters % or _ in the pattern by using the ESCAPE clause, which identifies the escape character. If the escape character precedes the character % or _ in the pattern, then Oracle interprets this character literally in the pattern rather than as a special pattern-matching character. You can also search for the escape character itself by repeating it. For example, if @ is the escape character, then you can use @@ to search for @.</p>
<p>  Source: <a href="http://docs.oracle.com/cd/B19306_01/server.102/b14200/conditions007.htm">Pattern-matching Conditions</a>, Oracle Database SQL Reference</p>
</blockquote>
<p>This means we can get what we were after like this:</p>
<pre><code>WHERE Title LIKE '20\% Off%' ESCAPE '\' --// What we were after!
</code></pre>
<p>This is great, except now our customers have a whole new set of special characters they can provide that change the behaviour of our queries to Oracle. While this probably doesn&#8217;t leave your database open to all of the SQL Injection attacks we&#8217;ve discussed, it probably still allows your customers access to data they probably shouldn&#8217;t have.</p>
<p>This means <em>if</em> we have a parameter used in a <code>LIKE</code> filter we need to:</p>
<ol>
<li>Escape all special Oracle wildcard characters</li>
<li>Escape whichever <code>ESCAPE</code> character we&#8217;re using</li>
<li>Ensure all <code>LIKE</code> statements have a corresponding <code>ESCAPE</code> clause (<strong><em>this has to be applied per-<code>LIKE</code></em></strong> which is something that I didn&#8217;t find clear from the docs)</li>
</ol>
<p>The <a href="http://docs.oracle.com/cd/B19306_01/server.102/b14200/conditions007.htm">Oracle documentation</a> lists the special wildcard characters as:</p>
<blockquote><p>
  An underscore (_) in the pattern matches exactly one character (as opposed to one byte in a multibyte character set) in the value.</p>
<p>  A percent sign (%) in the pattern can match zero or more characters (as opposed to bytes in a multibyte character set) in the value. The pattern &#8216;%&#8217; cannot match a null.</p>
</blockquote>
<p>This meant I needed to update my <code>EscapeParameter</code> function to:</p>
<ol>
<li>Escape existing <code>ESCAPE</code> characters (e.g. <code>\</code>)</li>
<li>Escape <code>LIKE</code> wildcard characters (<code>%</code> and <code>_</code>)</li>
<li>Only do this when the parameter was being used in a <code>LIKE</code> clause</li>
</ol>
<p>I also needed to make sure the <code>EscapeWhere</code> function was:</p>
<ol>
<li>Smart enough to work out which parameters need wildcard escaping or not. </li>
<li>Adding in an <code>ESCAPE</code> clause for every <code>LIKE</code> clause (or rely on calling developers to remember this, and be consistent in their selection of an <code>ESCAPE</code> character).</li>
</ol>
<h2>Final Code</h2>
<p>Incorporating these new requirements led to the code below.</p>
<p>Before you jump in remember <strong>THIS CODE PROBABLY HAS ISSUES, TEST THOROUGHLY!</strong> (this is true for any code you find online).</p>
<p><strong>Updated <code>EscapeWhere</code> method</strong></p>
<pre><code>/// String parameters should be enclosed in single-quotes
/// Parameters of other data types (e.g. numerics) should be validated 
/// by the caller before calling this method.
/// USE WITH CAUTION AND EXTENSIVE TESTING
static string EscapeWhere(string format, params object[] unescapedParameters) 
{ 
    /* Regex for LIKE clauses
      * LIKE (Whitespace) 
      * (Single Quote) (Optional Anything But Single Quote)
      * (Start Brace) (Number) (End Brace)
      * (Optional Anything But Single Quote) (Single Quote) */ 
    string likeRegex = @"LIKE\s+'[^']?{(\d+)}[^']?'";

    /* Extract indices of parameters that need wildcard escaping */
    List&lt;int&gt; wildcardParameterIndices = Regex.Matches(format, likeRegex)
      .Cast&lt;Match&gt;()
      .Select(m =&gt; m.Groups[1]) // Select the "Decimal" group of each Match
      .Select(g =&gt; int.Parse(g.Value)) // Extract the parameter number
      .ToList();

    /* Append ESCAPES to LIKE statements. */
    format = Regex.Replace(format, likeRegex, @"$0 ESCAPE '\'");

   /* Escape parameters, including wildcard escaping where applicable */
   object[] escapedParameters = unescapedParameters
     .Select((param, index) 
        =&gt; EscapeParameter(param, wildcardParameterIndices.Contains(index)))
     .ToArray();

   /* Return WHERE filter string with escaped parameters */
   return String.Format(format, escapedParameters);
}
</code></pre>
<p><strong>Updated <code>EscapeParameter</code> method</strong></p>
<p>(Which <a href="http://code.google.com/p/google-code-prettify/">Prettify</a> struggles with due to <a href="http://msdn.microsoft.com/en-us/library/aa691090%28v=vs.71%29.aspx">C# String Literals</a>)</p>
<pre><code>/// If escapeWildcards is true, assumes parameter used in a LIKE clause
/// and also assumes an "ESCAPE '\'" statement will follow the parameter.
/// USE WITH CAUTION AND EXTENSIVE TESTING
static string EscapeParameter(object unescapedParameter, bool escapeWildcards)
{
    if (unescapedParameter == null)
        return String.Empty;

    // Escape quotes
    string escapedParameter = unescapedParameter.ToString().Replace("'", "''"); 

    // Escape wildcards when used in a `LIKE` clause
    if (escapeWildcards)
    {
        escapedParameter = escapedParameter
          .Replace(@"\", @"\\") // Escape escaping slashes (before adding more)
          .Replace("_", @"\_") // Escape underscore for LIKE statements
          .Replace("%", @"\%"); // Escape percentage for LIKE statements
    }

    return escapedParameter;
}
</code></pre>
<p>This allows the following usage</p>
<pre><code>SelectMsg = Utility.CreateMessage("OurSchemas.InvoiceSelect"); // Create message
SelectMsg.COLUMN_NAMES = "INVOICE_ID"; // SELECT
SelectMsg.FILTER = Utility.EscapeWhere("NAME LIKE '%{0}%' AND REFERENCE = '{1}'", 
    name, reference); // WHERE
</code></pre>
<p>Now as I&#8217;ve mentioned, this isn&#8217;t tested for every possible scenario. Ideally I&#8217;d upload a <a href="http://msdn.microsoft.com/en-us/library/ms182470.aspx">Visual Studio Test Project</a> with some sample tests, but for the purposes of this blog post I have instead thrown a quick script through <a href="http://www.linqpad.net/">LINQPad</a> as <s><a href="http://www.albahari.com/">Joseph Albahari</a> has promised me an island</s> I really like LINQPad and it&#8217;s amazing.</p>
<pre><code>EscapeWhere("WHERE Col = {0}", 1).Dump(); // Test non-string
EscapeWhere("WHERE Col = '{0}'", "Test").Dump(); // Test string
EscapeWhere("WHERE Col = '{0}'", "Test'").Dump(); // Test single-quote
EscapeWhere("WHERE Col = '{0}'", "Test''").Dump(); // Test 2x single-quote
EscapeWhere("WHERE Col LIKE '{0}'", "Test").Dump(); // Test LIKE
EscapeWhere("WHERE Col LIKE '%{0}%'", "Test").Dump(); // Test LIKE %
EscapeWhere("WHERE Col LIKE '%{0}_'", "Test").Dump(); // Test LIKE _
EscapeWhere("WHERE Col LIKE '%{0}%'", "Test%").Dump(); // Test Escapes %
EscapeWhere("WHERE Col LIKE '%{0}%'", "Test_").Dump(); // Test Escapes _
EscapeWhere("WHERE Col LIKE '%{0}%'", @"Test\%").Dump(); // Test Escapes \
// Test 2x LIKE
EscapeWhere("WHERE Col LIKE '%{0}%' AND Col2 LIKE '%{1}%'", "Test", "Test2").Dump(); 
// Test LIKE + non-LIKE
EscapeWhere("WHERE Col LIKE '%{0}%' AND Col2 = '{1}'", "Test", "Test2").Dump(); 
</code></pre>
<p>Which prints the following output:</p>
<pre><code>/*
WHERE Col = 1
WHERE Col = 'Test'
WHERE Col = 'Test'''
WHERE Col = 'Test'''''
WHERE Col LIKE 'Test' ESCAPE '\'
WHERE Col LIKE '%Test%' ESCAPE '\'
WHERE Col LIKE '%Test_' ESCAPE '\'
WHERE Col LIKE '%Test\%%' ESCAPE '\'
WHERE Col LIKE '%Test\_%' ESCAPE '\'
WHERE Col LIKE '%Test\\\%%' ESCAPE '\'
WHERE Col LIKE '%Test%' ESCAPE '\' AND Col2 LIKE '%Test2%' ESCAPE '\'
WHERE Col LIKE '%Test%' ESCAPE '\' AND Col2 = 'Test2'
*/
</code></pre>
<p>For peace of mind I&#8217;d like someone to point me to a reliable and well-tested alternative I can leverage in a similar manner. In the meantime if you do happen to find any issues, or have some feedback, please make sure to let me know either in the comments or <a href="mailto:matt@mattmitchell.com.au">via email</a>.</p>
<p>Posted as <a href="http://mattmitchell.com.au/preventing-sql-injection-in-biztalk/">Preventing SQL Injection in BizTalk</a> at <a href="http://mattmitchell.com.au">Matt Mitchell</a></p>]]></content:encoded>
			<wfw:commentRss>http://mattmitchell.com.au/preventing-sql-injection-in-biztalk/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>What&#8217;s your IDE look like?</title>
		<link>http://mattmitchell.com.au/whats-your-ide-look-like/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=whats-your-ide-look-like</link>
		<comments>http://mattmitchell.com.au/whats-your-ide-look-like/#comments</comments>
		<pubDate>Tue, 09 Oct 2012 20:08:45 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://mattmitchell.com.au/?p=201</guid>
		<description><![CDATA[<p>A couple of recent releases have prompted me to spend a little time trying a new style for my IDE. Specifically: The Tomorrow Theme (and associated Hacker News thread) Adobe Source Code Pro font (and associated Hacker News thread) The &#8230; <a href="http://mattmitchell.com.au/whats-your-ide-look-like/">Continue reading <span class="meta-nav">&#8594;</span></a></p><p>Posted as <a href="http://mattmitchell.com.au/whats-your-ide-look-like/">What&#8217;s your IDE look like?</a> at <a href="http://mattmitchell.com.au">Matt Mitchell</a></p>]]></description>
				<content:encoded><![CDATA[<p>A couple of recent releases have prompted me to spend a little time trying a new style for my IDE.</p>
<p>Specifically:</p>
<ul>
<li><a href="https://github.com/chriskempson/tomorrow-theme">The Tomorrow Theme</a> (and associated <a href="http://news.ycombinator.com/item?id=4476359">Hacker News thread</a>)</li>
<li><a href="http://blogs.adobe.com/typblography/2012/09/source-code-pro.html">Adobe Source Code Pro</a> font (and associated <a href="http://news.ycombinator.com/item?id=4623482">Hacker News thread</a>) </li>
</ul>
<p><strong>The Tomorrow Theme</strong></p>
<p><img src="http://mattmitchell.com.au/wp-content/uploads/2012/10/Tomorrow-Palette.png" alt="" title="Tomorrow-Palette" width="285" height="75" class="alignnone size-full wp-image-208" /></p>
<p>The <a href="https://github.com/chriskempson/tomorrow-theme">Tomorrow Theme</a> is a colour palette (actually series of colour palettes) from <a href="http://chriskempson.com/">Chris Kempson</a> that emerged out of 5 years of personal use and revision.</p>
<p>I&#8217;ve chosen to go with the <a href="https://github.com/chriskempson/tomorrow-theme#tomorrow-night">Tomorrow Night</a> palette:</p>
<p><img src="http://mattmitchell.com.au/wp-content/uploads/2012/10/Tomorrow-Night-223x300.png" alt="" title="Tomorrow-Night" width="223" height="300" class="alignnone size-medium wp-image-205" /></p>
<p>For my use in Visual Studio I downloaded and begun adapting the <a href="https://github.com/chriskempson/tomorrow-theme/blob/master/Visual%20Studio/tomorrow-night.vssettings">Tomorrow Night Visual Studio Theme</a> from Chris&#8217;s GitHib repository.</p>
<p>I think the VS theme can use some work, but the palette itself is pretty cool and any issues are to be expected as this wasn&#8217;t designed for Visual Studio.</p>
<p>You can <a href="https://github.com/chriskempson/tomorrow-theme/downloads">download the theme</a> as a compressed repository from GitHub.</p>
<p><strong>Adobe Source Code Pro</strong></p>
<p><img src="http://mattmitchell.com.au/wp-content/uploads/2012/10/Meta_Chars-300x36.png" alt="" title="Meta_Chars" width="300" height="36" class="alignnone size-medium wp-image-209" /></p>
<p><a href="http://blogs.adobe.com/typblography/2012/09/source-code-pro.html">Source Code Pro</a> is a new font designed by <a href="https://twitter.com/pauldhunt">Paul D. Hunt</a>, a typeface designer and developer at Adobe.</p>
<p><img src="http://mattmitchell.com.au/wp-content/uploads/2012/10/SourceCodeSplash-300x185.png" alt="" title="SourceCodeSplash" width="300" height="185" class="alignnone size-medium wp-image-204" /></p>
<p>It&#8217;s the eagerly awaited monospace companion to the recently released <a href="http://blogs.adobe.com/typblography/2012/08/source-sans-pro.html">Source Sans Pro</a>.</p>
<p>You can <a href="http://sourceforge.net/projects/sourcecodepro.adobe/">download the font from SourceForge</a> or grab the <a href="https://github.com/adobe/Source-Code-Pro">source/unbuilt files on GitHub</a>.</p>
<p><strong>The Outcome So Far</strong></p>
<p>After putting these two together this is what I have so far:</p>
<p><img src="http://mattmitchell.com.au/wp-content/uploads/2012/10/codeide2.png" alt="" title="codeide" width="598" height="647" class="alignnone size-full wp-image-210" /></p>
<p><img src="http://mattmitchell.com.au/wp-content/uploads/2012/10/csscode1.png" alt="" title="csscode" width="305" height="268" class="alignnone size-full wp-image-211" /></p>
<p>So far I&#8217;m liking the new theme, but it&#8217;s still very much a work in progress and I&#8217;m already spotting things I want to change:</p>
<ul>
<li>Consider a bolding font weight as per the <a href="https://raw.github.com/ChrisKempson/Tomorrow-Theme/master/Images/Tomorrow-Night.png">Tomorrow Night TextMate sample</a>.</li>
<li>Distinguish between keywords (e.g. <code>class</code>, <code>public</code>) and type aliases (e.g. lowercase <code>string</code> and <code>object</code>). This will probably required a plugin such as <a href="http://www.jetbrains.com/resharper/documentation/help20/Options/syntaxhighlighting.html">ReSharper&#8217;s enhanced Syntax Highlighting</a></li>
<li>Distinguish between objects/methods/properties</li>
<li>Revise the highlighting in more advanced cases (e.g. selection, debugging, breakpoints)</li>
<li>Extend the colouring consistency throughout the UI (e.g. already had to change the line number colouring to be consistent just so I wouldn&#8217;t go crazy)</li>
<li>Review Razor, HTML, and JavaScript colouring</li>
<li>Check out <a href="https://github.com/chriskempson/base16">Base16</a> colours (described as the &#8220;next evolution of Tomorrow Theme&#8221;)</li>
</ul>
<p>In the meantime I&#8217;m keen to hear feedback and see what everyone else is using.</p>
<p>Posted as <a href="http://mattmitchell.com.au/whats-your-ide-look-like/">What&#8217;s your IDE look like?</a> at <a href="http://mattmitchell.com.au">Matt Mitchell</a></p>]]></content:encoded>
			<wfw:commentRss>http://mattmitchell.com.au/whats-your-ide-look-like/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to Change the Commands FtpWebRequest Sends</title>
		<link>http://mattmitchell.com.au/how-to-change-the-commands-ftpwebrequest-sends/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=how-to-change-the-commands-ftpwebrequest-sends</link>
		<comments>http://mattmitchell.com.au/how-to-change-the-commands-ftpwebrequest-sends/#comments</comments>
		<pubDate>Sun, 29 Jul 2012 16:48:14 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Technical]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[FTP]]></category>

		<guid isPermaLink="false">http://mattmitchell.com.au/?p=165</guid>
		<description><![CDATA[<p>Below I discuss how I&#8217;ve worked around some limitations of the System.Net.FtpWebRequest to allow low-level customisation of the actual commands sent by the FtpWebRequest class. This allows resolution of a couple of issues, including: Customising the logon sequence (allowing support &#8230; <a href="http://mattmitchell.com.au/how-to-change-the-commands-ftpwebrequest-sends/">Continue reading <span class="meta-nav">&#8594;</span></a></p><p>Posted as <a href="http://mattmitchell.com.au/how-to-change-the-commands-ftpwebrequest-sends/">How to Change the Commands FtpWebRequest Sends</a> at <a href="http://mattmitchell.com.au">Matt Mitchell</a></p>]]></description>
				<content:encoded><![CDATA[<p>Below I discuss how I&#8217;ve worked around some limitations of the <code>System.Net.FtpWebRequest</code> to allow low-level customisation of the actual commands sent by the <code>FtpWebRequest</code> class.</p>
<p>This allows resolution of a couple of issues, including:</p>
<ul>
<li>Customising the logon sequence (allowing support for an FTP Proxy <a href="https://kb.bluecoat.com/index?page=content&amp;id=KB3438">such as the Bluecoat ProxySG</a>)</li>
<li>Removing the hard-coded <code>OPTS</code> command <a href="http://stackoverflow.com/questions/1545793/opts-command-on-ftpwebrequest-ftpwebresponse/1551880#comment15513820_1551880">for servers that do not support the command</a>.</li>
</ul>
<p>If you&#8217;re here for the workaround <a href="#fix">click here to see the solution</a>, and for everyone else I&#8217;m going to be as self-indulgent as usual and detail the background of my workaround.</p>
<h2>Background and security exploit in FtpWebRequest</h2>
<p>My particular discovery of this workaround was unintentional &#8211; I was looking to change the <code>USER</code>/<code>PASS</code> sequence sent by <code>FtpWebRequest</code> (including sending an <code>ACCT</code> command after the <code>USER</code> and <code>PASS</code>). To achieve this I tried sending an embedded command as my <code>PASS</code> by setting the password of my <code>FtpWebRequest</code>&#8216;s <code>NetworkCredential</code>.</p>
<pre><code>NetworkCredential n = new NetworkCredential("SomeUser", "SomePass\nACCT SomeAcct");
</code></pre>
<p>Surprisingly, <strong>this actually (almost) worked</strong>! It actually sent <code>ACCT SomeAcct</code> as an FTP command (<strong>and this is a whole new space for a security vulnerability</strong>).</p>
<p>Unfortunately I was then (seemingly) getting errors on the <code>OPTS</code> command, which led me down the path below. What I found out later was that injecting the command caused internal miscounts on command processing, which meant the responses from the server were out of alignment with the commands sent and couldn&#8217;t be properly correlated.</p>
<h2>How FtpWebRequest Sends Commands</h2>
<p>It was time to <a href="http://www.jetbrains.com/decompiler/">decompile</a> <a href="http://msdn.microsoft.com/en-us/library/system.net.ftpwebrequest.aspx"><code>System.Net.FtpWebRequest</code></a> and I decided to start at the <a href="http://msdn.microsoft.com/en-us/library/system.net.ftpwebrequest.getresponse.aspx"><code>GetResponse</code></a> method, which seemed to be the method where actual commands were sent to the server.</p>
<p>Looking through the method, it seemed that the basic structure was:</p>
<ol>
<li>If using a HTTP Proxy, delegate to <code>HttpWebRequest</code> / <code>HttpWebResponse</code></li>
<li>If using asynchronous methods &#8220;do some stuff I didn&#8217;t understand at the time&#8221;</li>
<li>If using synchronous methods call the private method <code>SubmitRequest</code></li>
</ol>
<p>Checking out <code>SubmitRequest</code>, it seemed that that there was some stuff happening with a <code>System.Net.FtpControlStream</code> &#8211; an internal class which apparently was the actual type of the <code>m_connection</code> variable being used throughout <code>FtpWebRequest</code>.</p>
<pre><code> FtpControlStream ftpControlStream = this.m_Connection;
</code></pre>
<p>I jumped into <code>FtpControlStream</code> and decided to do a quick search for &#8220;OPTS&#8221;. Sure enough there were a couple of references:</p>
<p>The first reference was in a <code>PipelineCallback</code> method, which seemed to be doing some pretty hacky stuff using string evaluation after each command to work out what to do. This didn&#8217;t look good.</p>
<pre><code>if (entry.Command == "OPTS utf8 on\r\n")
{
  if (response.PositiveCompletion)
    this.Encoding = Encoding.UTF8;
  else
    this.Encoding = Encoding.Default;
  return CommandStream.PipelineInstruction.Advance;
}
</code></pre>
<p>The second reference was in a <code>BuildCommandsList</code> method, which looked to be building the list of commands run as part of an FTP request. This looked much more promising, and sure enough there was a line adding the <code>OPTS</code> command to the queue:</p>
<pre><code>  arrayList.Add((object) new CommandStream.PipelineEntry(this.FormatFtpCommand("OPTS", "utf8 on")));
</code></pre>
<p>This explained why <a href="http://stackoverflow.com/a/1551880/364">Thomas Levesque&#8217;s answer on StackOverflow</a> was that <code>OPTS</code> is hardcoded.</p>
<h2>Changing the Commands FtpWebRequest Sends</h2>
<p>I was starting to get a bit of a picture of how this worked:</p>
<ol>
<li>A queue of commands (a <code>CommandStream</code>) is built (<code>BuildCommandsList</code>)</li>
<li>Each command is processed in sequence</li>
<li>A callback (<code>PipelineCallback</code>) is fired as each command is processed allowing actual functionality</li>
</ol>
<p>The next question was &#8211; how could I modify this commands list before it was sent to the server?</p>
<p>Unfortunately <a href="http://www.codinghorror.com/blog/2008/07/monkeypatching-for-humans.html">Monkeypatching</a> (rewriting existing code) isn&#8217;t currently possible in C#, but maybe I could make my own <code>CommandStream</code> / <code>FtpControlStream</code> and replace (using reflection) the <code>m_Connection</code> variable in <code>FtpWebRequest</code> with my new class?</p>
<p>Unfortunately <a href="http://blogs.msdn.com/b/ericlippert/archive/2008/09/26/preventing-third-party-derivation-part-one.aspx">Eric Lippert says this is impossible</a> and <a href="http://stackoverflow.com/a/8498341/364">Jon Hanna&#8217;s attempts on StackOverflow</a> were stopped by <code>TypeLoadExceptions</code>. My own quick attempts ran into the same issues so this seemed a no-go.</p>
<p>I read through the code of <code>CommandStream</code>, <code>FtpControlStream</code>, and <code>FtpWebRequest</code> a bit more, and realised there were quite a few callbacks around the place &#8211; if just one of these happened to fire at the right time (after the command list was built, but before a given command was sent to the server) I might be able to hook in my own callback!</p>
<p>Unfortunately most of the callbacks were implemented as direct method references, and thanks to &#8220;no monkeypatching&#8221; I wouldn&#8217;t be able to change these. However, a couple of callbacks used member <code>AsyncCallback</code> variables, and these <em>I could</em> repoint to my own code!</p>
<p>After running a few <a href="http://www.linqpad.net/">LINQPad</a> tests (injecting a basic &#8220;Hello World&#8221; callback of my own into these various callback options) to work out when these different callbacks fired, I&#8217;d narrowed down my target: <code>m_WriteCallbackDelegate</code> in <code>System.Net.CommandStream</code>.</p>
<p><code>m_WriteCallbackDelegate</code> seemed to fire after each command was sent to the server &#8211; as long as I didn&#8217;t want to have a command other than <code>USER</code> sent first (or <code>AUTH TLS</code> if SSL was enabled) this was the callback I was after.</p>
<p>My basic strategy would be to inject a callback that would:</p>
<ol>
<li>Check if the position in the command list is at the position expected to make a change (so that modifications are not applied twice, as the callback fires for every command)</li>
<li>If so, modify the built command list (for instance, remove the command if I don&#8217;t want it sent)</li>
<li>Hand back to the original callback (so everything can continue as normal)</li>
</ol>
<p>With some reflection this part was actually surprisingly easy once I worked out what was happening.</p>
<h2>Gotchas</h2>
<p>Unfortunately there were two gotchas:</p>
<ol>
<li>The callback was only fired when the asynchronous methods of <code>FtpWebRequest</code> were used (<a href="http://msdn.microsoft.com/en-us/library/system.net.ftpwebrequest.begingetresponse.aspx"><code>BeginGetResponse</code></a> / <a href="http://msdn.microsoft.com/en-us/library/system.net.ftpwebrequest.endgetresponse.aspx"><code>EndGetResponse</code></a>).</li>
<li>The callback variable (<code>m_WriteCallbackDelegate</code>) was <code>static</code> &#8211; this would affect every <code>FtpWebRequest</code> in the current AppDomain!</li>
</ol>
<p>Resolving the first point wasn&#8217;t the end of the world &#8211; I could rewrite my code a little (and deal with the terrible asynchronous <code>FtpWebRequest</code> interface) to call the asynchronous methods but still work synchronously (or asynchronously if I so chose).</p>
<p>The second point was however a little trickier. What I was after was to only apply the callback on specific <code>FtpWebRequest</code> instances (those that I needed my modifications to apply to).</p>
<p>My first thought was to store a thread-safe list of IDs for the requests that I wanted to apply the special callback for. I could then add the ID of new requests to this list on demand, and when the callback fired it would check the current request&#8217;s instance ID against that list.</p>
<p>Unfortunately something like <code>GetHashCode</code> collides really quickly (my quick <a href="http://www.linqpad.net/">LINQPad</a> tests showed collisions after around 10,000 objects), and there was no way for me to add a new variable to an <code>internal</code> class (I could add an <a href="http://msdn.microsoft.com/en-us/library/bb383977.aspx">Extension Method</a> but these wouldn&#8217;t allow me to add a member-level property). If only there were some way to dynamically attach data to an object instance.. <a href="http://stackoverflow.com/a/5204458/364">oh wow there is</a>!</p>
<blockquote>
<p>The ConditionalWeakTable&lt;TKey, TValue> class enables language compilers to attach arbitrary properties to managed objects at run time.</p>
<p>Source: <a href="http://msdn.microsoft.com/en-us/library/dd287757.aspx">http://msdn.microsoft.com/en-us/library/dd287757.aspx</a></p>
</blockquote>
<p>The <a href="http://msdn.microsoft.com/en-us/library/dd287757.aspx"><code>ConditionalWeakTable</code></a> meant that I could keep a thread-safe dynamic collection (with weak references removing GC issues!) of the <code>FtpWebRequest</code> instances that should use my new callback, and the callback could at run-time check if the current instance should apply the new rules (or simply hand back to the original callback).</p>
<p><a name="fix"></a></p>
<h2>The Final Workaround</h2>
<p>So what I had worked out at this point was:</p>
<ol>
<li><code>FtpWebRequest</code> uses a <code>FtpCommandStream</code> to store a queue of commands (each represented by a <code>PipelineEntry</code>) to send to the FTP server.</li>
<li>This command stream generates a series of commands to execute <em>per request</em>.</li>
<li>This means if the command stream is modified for each request, the commands sent by <code>FtpCommandStream</code> can be modified.</li>
<li>Facilitating this, when using the asynchronous methods of <code>FtpWebRequest</code>, a callback method is fired (by <code>FtpCommandStream</code>&#8216;s parent class <code>ControlStream</code>) after each command is sent to the server.</li>
<li>This allows us to inject/remove/change a command in the stream then hand back to the standard callback.</li>
<li>This callback is <code>static</code> so any replacement will need to happen once per AppDomain and ensure that changes are only applied to the desired instances of `FtpWebRequest</li>
</ol>
<p>Wrapping this all up gave me an injected custom write callback which I chose to setup with a <a href="http://msdn.microsoft.com/en-us/library/aa645612%28v=vs.71%29.aspx">static initializer</a>, and I&#8217;m hoping you can adapt to your own needs. It also required a couple of extension methods which I&#8217;ve included below for changing an array generically (without design-time declaration of its type, as we cannot declare the internal <code>PipelineEntry</code> type).</p>
<p>In my particular case I wanted to inject additional FTP commands, so my callback when fired would run through a <code>Queue</code> of commands to inject. Each item in this queue had a condition to check against the &#8220;last run command&#8221; (stored as <code>Func&lt;string, bool&gt;</code>) and if this condition was true, a &#8220;command&#8221; to inject as the next command. However my example below shows how to perform both a command removal and insertion.</p>
<p>Remember this relies on leveraging internal behaviour of the framework, which could (though I doubt it for minor releases) change without warning at any time.</p>
<p>If you have any questions or trouble adapting this to your particular needs feel free to leave a comment or <a href="mailto:matt@mattmitchell.com.au">get in touch</a>.</p>
<pre><code>// In custom class FtpCallbackInjector
// NB: Requires usage of the asynchronous FtpWebRequest methods (Begin/End)
// NB: In this sample, your request must be added to MarkedRequests

// Could strong-type "object" here - it's the associated per-request "state"
private readonly static ConditionalWeakTable&lt;FtpWebRequest, object&gt; MarkedRequests = new ConditionalWeakTable&lt;FtpWebRequest, object&gt;();

// Static Initializer
static FtpCallbackInjector()
{
    // Get access to (post)-write callback delegate
    Type commandStreamType = typeof(FtpWebRequest).Assembly.GetType("System.Net.CommandStream");
    FieldInfo commandStreamWriteCallbackField = commandStreamType.GetField("m_WriteCallbackDelegate", BindingFlags.NonPublic | BindingFlags.Static);

    // Store original delegate for chaining
    AsyncCallback originalDelegate = (AsyncCallback)commandStreamWriteCallbackField.GetValue(null); 

    // Inject our own delegate (which in turn calls the original delegate)
    commandStreamWriteCallbackField.SetValue(null, new AsyncCallback((asyncResult) =&gt;
    {
      /* Get field/method references via reflection */
      Type commandStreamPipelineEntryType = typeof(FtpWebRequest).Assembly.GetType("System.Net.CommandStream+PipelineEntry");
      FieldInfo commandStreamCommandsField = commandStreamType.GetField("m_Commands", BindingFlags.NonPublic | BindingFlags.Instance);
      FieldInfo commandStreamIndexField = commandStreamType.GetField("m_Index", BindingFlags.NonPublic | BindingFlags.Instance);
      FieldInfo commandStreamRequestField = commandStreamType.GetField("m_Request", BindingFlags.NonPublic | BindingFlags.Instance);
      FieldInfo pipelineEntryCommandField = commandStreamPipelineEntryType.GetField("Command", BindingFlags.NonPublic | BindingFlags.Instance);
      MethodInfo formatFtpCommandMethod = typeof(FtpWebRequest).Assembly.GetType("System.Net.FtpControlStream").GetMethod("FormatFtpCommand", BindingFlags.NonPublic | BindingFlags.Instance);

      // asyncResult.AsyncState is the System.Net.CommandStream
      object commandStream = asyncResult.AsyncState; 

      // Reference to executing request
      FtpWebRequest request = (FtpWebRequest)commandStreamRequestField.GetValue(commandStream); 

      /* Check if executing request is marked */
      // Associate anything you like here with the request
      object markedState = null; 
      if (!MarkedRequests.TryGetValue(request, out markedState))
      {
        // If not marked simply chain and return
        originalDelegate(asyncResult);
        return;
      }

      // Array of PipelineEntry
      Array commands = (Array)commandStreamCommandsField.GetValue(commandStream); 
      // Current (just-executed) index in CommandStream
      int commandStreamIndex = (int)commandStreamIndexField.GetValue(commandStream); 
      // Current (just-executed) command of type System.Net.CommandStream+PipelineEntry
      object currentPipelineEntry = commands.GetValue(commandStreamIndex); 
      // Current (just-written) command string
      string currentCommand = (string)pipelineEntryCommandField.GetValue(currentPipelineEntry); 

      // If the just executed command passes some kind of filter
      // Example removing "OPTS" after "PASS"
      // (Could have also got "next command" and checked it was "OPTS")
      if (currentCommand.StartsWith("PASS")
      {
          // Remove next "OPTS" command
          commands = RemoveAt(commands, commandStreamIndex + 1);

          // Update CommandStream's command (PipelineEntry) array with the new array 
          commandStreamCommandsField.SetValue(commandStream, commands);
      }

      // Example adding "ACCT" after "PASS"
      if (currentCommand.StartsWith("PASS"))
      {
        // Create "ACCT" command
        // Get the Pipeline Entry constructor which takes a string parameter (the command)
        ConstructorInfo pipelineEntryConstructor = commandStreamPipelineEntryType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(string) }, null);

        // Call the FormatFtpCommand method, which takes a command and parameter and formats them for FTP submission
        string formattedCommand = (string)formatFtpCommandMethod.Invoke(commandStream, new[] { "ACCT", "someAcct" });

        // Create new Pipeline Entry using formatted command as parameter
        // Of type System.Net.CommandStream+PipelineEntry
        object newPipelineEntry = pipelineEntryConstructor.Invoke(new [] { formattedCommand }); 

        // Create new merged command stream array including injected command
        commands = InsertAt(commands, commandStreamIndex + 1, newPipelineEntry);

        // Update CommandStream's command (PipelineEntry) array with the new array
        commandStreamCommandsField.SetValue(commandStream, commands);
      }
    }

    // Chain back to original delegate
    originalDelegate(asyncResult);
  }));
}

public static Array RemoveAt(Array source, int index)
{
    if (source == null) 
        throw new ArgumentNullException("source"); 

    if (0 &gt; index || index &gt;= source.Length) 
    throw new ArgumentOutOfRangeException("index", index, "index is outside the bounds of source array"); 

    Array dest = Array.CreateInstance(source.GetType().GetElementType(), source.Length - 1); 
    Array.Copy(source, 0, dest, 0, index); 
    Array.Copy(source, index+1, dest, index, source.Length - index - 1); 

    return dest;
 }

 public static Array InsertAt(Array source, int index, object o) 
 {  
    if (source == null) 
        throw new ArgumentNullException("source"); 

    if (0 &gt; index || index &gt; source.Length) 
        throw new ArgumentOutOfRangeException("index", index, "index is outside the bounds of source array"); 

    Array dest = Array.CreateInstance(source.GetType().GetElementType(), source.Length + 1); 
    Array.Copy(source, 0, dest, 0, index); 
    dest.SetValue(o, index);
    Array.Copy(source, index, dest, index+1, source.Length - index); 

    return dest;
 }
</code></pre>
<p>Posted as <a href="http://mattmitchell.com.au/how-to-change-the-commands-ftpwebrequest-sends/">How to Change the Commands FtpWebRequest Sends</a> at <a href="http://mattmitchell.com.au">Matt Mitchell</a></p>]]></content:encoded>
			<wfw:commentRss>http://mattmitchell.com.au/how-to-change-the-commands-ftpwebrequest-sends/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>FtpWebRequest is Broken</title>
		<link>http://mattmitchell.com.au/ftpwebrequest-is-broken/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=ftpwebrequest-is-broken</link>
		<comments>http://mattmitchell.com.au/ftpwebrequest-is-broken/#comments</comments>
		<pubDate>Sun, 29 Jul 2012 13:25:39 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Technical]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[FTP]]></category>

		<guid isPermaLink="false">http://mattmitchell.com.au/?p=12</guid>
		<description><![CDATA[<p>I&#8217;m going to take a brief break from helpful solutions to have a bit of a rant about FTP support in the .NET Framework. When all you have is hammers.. FTP as a protocol is pretty lousy, but its support &#8230; <a href="http://mattmitchell.com.au/ftpwebrequest-is-broken/">Continue reading <span class="meta-nav">&#8594;</span></a></p><p>Posted as <a href="http://mattmitchell.com.au/ftpwebrequest-is-broken/">FtpWebRequest is Broken</a> at <a href="http://mattmitchell.com.au">Matt Mitchell</a></p>]]></description>
				<content:encoded><![CDATA[<p>I&#8217;m going to take a brief break from helpful solutions to have a bit of a rant about FTP support in the .NET Framework.</p>
<h2>When all you have is hammers..</h2>
<p>FTP as a protocol is pretty lousy, but its support in .NET (see <a href="http://msdn.microsoft.com/en-us/library/system.net.ftpwebrequest.aspx"><code>System.Net.FtpWebRequest</code></a>) is especially terrible. If you <em>can</em> use an alternative, I suggest you do.</p>
<p>Here&#8217;s just a small list of alternatives (evaluate each based on community feedback, release/update activity, user support, and your own testing):</p>
<ul>
<li><a href="http://ftps.codeplex.com/">Alex FTPS Client</a> &#8211; Seems active, well-rated, and gets lots of <a href="http://stackoverflow.com/a/2301528/364">positive community reviews</a> on places like StackOverflow. </li>
<li><a href="http://code.google.com/p/starksoft-component-libraries/">Starksoft FTP and FTPS C# Client Library</a> &#8211; Seems decent, and is written by a guy called <a href="http://www.starksoft.com/blog/">Benton Stark</a> which is <a href="http://awoiaf.westeros.org/index.php/House_Stark">a pretty awesome name</a>. Check out <a href="http://code.google.com/p/starksoft-component-libraries/">the Google Code repository</a> for the latest code (the <a href="http://starksoftftps.codeplex.com/">CodePlex project</a> is out of date, and I believe the <a href="http://starksoft.com/prod_ftp.html">binaries on the Starksoft site</a> are also out of date as of <a href="http://code.google.com/p/starksoft-component-libraries/source/detail?r=63">Revision 63</a>).</li>
<li><a href="http://ftplib.codeplex.com/">C# FTP Library</a> &#8211; A C# wrapper for <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa384180%28v=vs.85%29.aspx">WinINet FTP functionality</a>. There&#8217;s a couple of other WinINet/FTP articles, including an <a href="http://techsupt.winbatch.com/TS/T000002003F2.html">article on WinINet FTP limitations</a>, <a href="http://www.teksoftco.com/articles/ftp%20client.htm">a C++ sample</a>, a <a href="http://www.pablosoftwaresolutions.com/html/ftp_wanderer_3_0.html">full WinINet-based FTP client</a> with C++ source that originated from <a href="http://www.codeproject.com/Articles/2665/FTP-Wanderer-FTP-Client-using-WININET">a well-rated The Code Project article</a></li>
<li>There are other projects in various states (<a href="http://libftp.codeplex.com/">libftp</a>, <a href="http://ftp.codeplex.com/">OpenNETCF FTP Library</a>, <a href="http://netftp.codeplex.com/">System.Net.FtpClient</a>).</li>
<li>There are some fairly excellent-looking commercial libraries (<a href="http://www.limilabs.com/ftp">Limiblabs Ftp.dll</a>, <a href="http://www.rebex.net/ftp-ssl.net/">Rebex FTP/SSL for .NET/.NET CF</a>, <a href="http://www.enterprisedt.com/products/edtftpnetpro/overview.html">edtFTPnet/PRO</a>) which take <a href="http://stackoverflow.com/questions/1842186/does-net-ftpwebrequest-support-both-implicit-ftps-and-explicit-ftpes">every opportunity</a> to post how <s>they can&#8217;t help you solve your problem with the standard libraries but if you feel like forking out some cash your problem is solved</s> great they are (<a href="http://stackoverflow.com/search?q=rebex">Rebex being the most notorious I&#8217;ve seen for this</a>). The benefit of these of course being you&#8217;re in good company (look at some of the clients for the more popular libraries) and have someone to <s>blame</s> fix any issues you have.</li>
</ul>
<h2>Why not just use FtpWebRequest?</h2>
<p>Why not <code>System.Net.FtpWebRequest</code> you say?</p>
<p>I&#8217;ve talked before about <a href="http://mattmitchell.com.au/zebras-in-system-net-networkcredential/">a small framework issue</a> when using <code>FtpWebRequest</code> (and have others still to post) but I&#8217;ll let that one slide in my criticism here (it&#8217;s <em>probably</em> <code>System.Net.NetworkCredential</code>&#8216;s fault that another framework class called its <code>internal</code> methods).</p>
<p>So let&#8217;s focus on a few of my other criticisms (most of which apply equally to both <code>FtpWebRequest</code> and <code>HttpWebRequest</code>):</p>
<ul>
<li><strong>The interface is not high-level enough to adequately wrap FTP functionality</strong>. This leads to a fair bit of <a href="http://en.wikipedia.org/wiki/Boilerplate_%28text%29">boilerplate</a> (<a href="http://technoyoga.blogspot.com.au/2007/10/microsoft-net-20-ftp-support-still.html">as noted years ago</a>, compare the Ruby code in that article). It also leads to inadequacy on basic tasks. For instance, there&#8217;s no real standard on directory listings, so you&#8217;re forced to try and write your own server-specific directory listing parser (I&#8217;ve previously adapted <a href="http://ftps.codeplex.com/SourceControl/changeset/view/75876#53963"><code>DirectoryListParser</code></a> from <a href="http://ftps.codeplex.com/">Alex FTPS Client</a>, itself adapted from <a href="http://blogs.msdn.com/b/adarshk/archive/2004/09/15/230177.aspx">Adarsh&#8217;s post</a>). Likewise, server behaviour seems to vary on &#8220;FileExists&#8221; meaning <a href="http://stackoverflow.com/questions/347897/how-to-check-if-file-exists-on-ftp-before-ftpwebrequest">the &#8220;best&#8221; solution is to wait for an exception</a>.</li>
<li><strong>The interface does not expose adequate control of important behaviors</strong>. For instance, connection pooling is implicit and handled fairly obscurely &#8211; see <a href="http://blogs.msdn.com/b/adarshk/archive/2005/01/02/345411.aspx">Adarsh&#8217;s post</a>, <a href="http://blogs.msdn.com/b/jpsanders/archive/2009/05/20/understanding-maxservicepointidletime-and-defaultconnectionlimit.aspx">jpsander&#8217;s post</a>, and <a href="http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.aspx"><code>System.Net.ServicePointManager</code></a>. Don&#8217;t even <a href="http://stackoverflow.com/questions/4586049/get-underlying-tcp-connection-from-httpwebrequest-response">try and get hold of the <em>actual</em> connection</a>. FTP servers being so inconsistently implemented, the ability to manually modify even seemingly inconsequential behaviours becomes essential.</li>
<li><strong>The actual implementation is less than adequate</strong> (and largely intermittently so) and relying on MSDN documentation is likely to mislead you on best practice usage. For some example issues see <a href="http://www.dzhang.com/blog/2010/03/31/httpwebrequest-abort-in-net-cf-2-broken-when-m_connection-null">David Zhang&#8217;s issue with HttpWebRequest in CF</a>, <a href="http://abi.exdream.com/Blog/post/2009/04/07/HttpWebRequest-is-very-slow-and-taking-forever-on-Windows-7.aspx">Benjamin Nitschke&#8217;s issues with HttpWebRequest performance</a>, and the <a href="http://stackoverflow.com/search?q=underlying%20connection%20is%20closed">numerous threads</a> on (frequently intermittent and hard to reproduce when testing) &#8220;underlying connection was closed&#8221; issues.</li>
</ul>
<p>I&#8217;ve personally dealt with these &#8220;underlying connection was closed&#8221; issues in rare circumstances where a connection is lost and therefore &#8220;breaks&#8221; protocol without properly closing the connection, which:</p>
<ol>
<li>Leads to a series of connections stuck in <code>TIME_WAIT</code> just in case there&#8217;s more traffic to come.</li>
<li>Which leads to an exhaustion of the <a href="http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.aspx"><code>ServicePointManager</code></a> connection pool count</li>
<li>Which means all new connections encounter the &#8220;underlying connection was closed&#8221; issue</li>
<li>Which, requires a restart of the AppDomain (i.e. your application)</li>
</ol>
<p><a href="http://stackoverflow.com/questions/1559232/net-ftpwebrequest-fails-sometimes">Usually</a> someone will suggest the largely hit-and-miss idea of changing <code>KeepAlive</code> to <code>false</code> (or <code>true</code> if you&#8217;ve already tried that). The more effective but hacky solution seems to be <a href="http://stackoverflow.com/questions/1390780/httpwebrequest-how-to-handle-premature-closure-of-underlying-tcp-connection">trying to subvert .NET connection handling and leveraging reflection hacks</a>.</p>
<p>Should a mature framework really have such a <a href="http://www.joelonsoftware.com/articles/LeakyAbstractions.html">leaky abstraction</a>?</p>
<h2>It can&#8217;t be that bad?</h2>
<p>The sheer fact that there are so many successful commercial libraries for something as seemingly fundamental as FTP connectivity confirms to me that the standard libraries are simply inadequate.</p>
<p>The cherry on top of this rather unappetising cake is that Microsoft is not only well-aware of the library&#8217;s inadequacies, but has given up on its own FTP library:</p>
<ul>
<li><a href="http://blog.rebex.net/news/archive/2010/07/19/microsoft-uses-rebex-ftp-ssl-and-sftp-in-visual-studio-2010-and-expression-web.aspx">Microsoft is using Rebex FTP/SSL and SFTP in Microsoft Visual Studio 2010</a></li>
<li>Microsoft uses the same Rebex component in place of <code>FtpWebRequest</code> in the <a href="http://msdn.microsoft.com/en-us/library/ee253291%28v=bts.10%29.aspx">BizTalk FTP Adapter</a> (<a href="http://www.jetbrains.com/decompiler/">decompile</a> the adapter if you&#8217;re curious)</li>
</ul>
<p>Hopefully we can see Microsoft either buy (and integrate, particularly as many of the commercial libraries are fairly low-level) or build an adequate FTP library in a future version of the framework. I&#8217;m not holding my breath.</p>
<p>Posted as <a href="http://mattmitchell.com.au/ftpwebrequest-is-broken/">FtpWebRequest is Broken</a> at <a href="http://mattmitchell.com.au">Matt Mitchell</a></p>]]></content:encoded>
			<wfw:commentRss>http://mattmitchell.com.au/ftpwebrequest-is-broken/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Detecting Duplicate XML data in SQL Server</title>
		<link>http://mattmitchell.com.au/detecting-duplicate-xml-data-in-sql-server/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=detecting-duplicate-xml-data-in-sql-server</link>
		<comments>http://mattmitchell.com.au/detecting-duplicate-xml-data-in-sql-server/#comments</comments>
		<pubDate>Thu, 19 Jul 2012 16:00:35 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Technical]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://mattmitchell.com.au/?p=57</guid>
		<description><![CDATA[<p>Had the interesting problem today of trying to detect duplicate XML values in a SQL Server table (stored in a column of field type XML). I&#8217;m not the first to cover this issue: Matt Woodward has covered the simplest case &#8230; <a href="http://mattmitchell.com.au/detecting-duplicate-xml-data-in-sql-server/">Continue reading <span class="meta-nav">&#8594;</span></a></p><p>Posted as <a href="http://mattmitchell.com.au/detecting-duplicate-xml-data-in-sql-server/">Detecting Duplicate XML data in SQL Server</a> at <a href="http://mattmitchell.com.au">Matt Mitchell</a></p>]]></description>
				<content:encoded><![CDATA[<p>Had the interesting problem today of trying to detect duplicate XML values in a SQL Server table (stored in a column of field type <code>XML</code>).</p>
<p>I&#8217;m not the first to cover this issue:</p>
<ul>
<li><a href="http://blog.mattwoodward.com/2008/02/detecting-duplicate-xml-data-in-sql.html">Matt Woodward has covered the simplest case of duplicate checks</a></li>
<li><a href="http://stackoverflow.com/questions/2411401/sql-server-xml-type-column-duplicate-entry-detection">There&#8217;s a StackOverflow question covering it</a></li>
</ul>
<p>However, my &#8220;requirements&#8221; as they were differed a little from the existing solutions:</p>
<ol>
<li>Only compare a subset of the XML value (a timestamp header would still differ on XML values we considered duplicates)</li>
<li>Only apply the duplicate checking to some of the rows</li>
<li>Keep the first row of a set of duplicates</li>
<li>Support large XML values</li>
<li>Develop this solution ASAP (this was needed in a critical support situation)</li>
</ol>
<p>A single application had populated the table, so fortunately I could assume all XML was equally processed.</p>
<h2>My Solution</h2>
<p>Now in the heat of the moment I went with a hashed solution <a href="http://stackoverflow.com/questions/2411401/sql-server-xml-type-column-duplicate-entry-detection">as StackOverflow proposed</a>. Upon reflection however I don&#8217;t see a real reason (beyond perhaps performance) I couldn&#8217;t have followed <a href="http://blog.mattwoodward.com/2008/02/detecting-duplicate-xml-data-in-sql.html">Matt Woodward&#8217;s method</a> and performed a simple string conversion and comparison (well a comparison of substrings given the requirement to ignore the header). Indeed it&#8217;s the <a href="#improved-solution">improved solution</a> I list below.</p>
<p>However, given the hashing direction the <a href="http://msdn.microsoft.com/en-us/library/ms174415.aspx"><code>HASHBYTES</code></a> function seemed a good start.</p>
<blockquote>
<p>HASHBYTES (Transact-SQL)</p>
<p>Returns the MD2, MD4, MD5, SHA, SHA1, or SHA2 hash of its input.</p>
</blockquote>
<p>Unfortunately, while this <em>is</em> a decent enough function for hashing, it led me on a bit of a <a href="http://stackoverflow.com/questions/11517288/how-do-i-convert-an-xml-field-with-more-than-8000-characters-into-a-string/11527424#11527424">wild goose chase</a> as I tried to work out why I couldn&#8217;t seem to cast my <code>XML</code> field to <code>varchar</code> without getting an error. It turned out that this was because I was passing my cast value straight to <code>HASHBYTES</code> which was in turn throwing an error.</p>
<p>See much like <a href="http://mattmitchell.com.au/zebras-in-system-net-networkcredential/">a past post</a> I had missed something pretty crucial on <a href="http://msdn.microsoft.com/en-us/library/ms174415.aspx">the MSDN page</a> &#8211; <code>HASHBYTES</code> has an 8000 character limit!</p>
<p><img src="http://mattmitchell.com.au/wp-content/uploads/2012/07/hashbytesremarks.png" alt="HASHBYTES Remarks" /></p>
<p>At least this time the implications were glaringly obvious, and I had noone else to blame but myself. In the process at least I learned a bit more about <code>XML</code> support in <code>SQL</code>, and found some pretty cool resources including this <a href="http://beyondrelational.com/modules/2/blogs/28/posts/10292/xml-workshops.aspx">series of SQL XML Workshops from Jacob Sebastian</a> found while <a href="http://stackoverflow.com/questions/966441/xml-query-in-sql-server-2008">searching on StackOverflow</a>.</p>
<p>It turned out that conversion to <code>XML</code> was as easy as I&#8217;d first tried:</p>
<pre><code>CONVERT(varchar(max), XmlColumn)
</code></pre>
<p>Once I got past this problem the query I ran with was pretty easy to put together.</p>
<p>First, I would only hash content from after the header, which I could identify by the character index of either the header closing tag or content start tag (found using <a href="http://msdn.microsoft.com/en-us/library/ms186323.aspx"><code>CHARINDEX</code></a>). I could have also used <a href="http://www.codeguru.com/csharp/.net/net_data/article.php/c19491/SQL-Server-2005-XQuery-and-XMLDML--Part-1.htm">SQL Server&#8217;s XML query functions</a>, but I was short on time and this seemed suitable for a throwaway task.</p>
<pre><code>CHARINDEX('&lt;Content&gt;', CONVERT(varchar(max), XmlColumn))
</code></pre>
<p>Then I could use a <a href="http://msdn.microsoft.com/en-us/library/ms187748.aspx"><code>SUBSTRING</code></a> to grab the next 8000 characters (to support <code>HASHBYTES</code>) from this point:</p>
<pre><code>SUBSTRING(
 CONVERT(varchar(max), XmlColumn), --// Data
 CHARINDEX('&lt;Content&gt;', CONVERT(varchar(max), XmlColumn)), --// Start Index
 8000) --// Length
</code></pre>
<p>This ultimately gave me the following query, which suited our purposes:</p>
<pre><code>--// WARNING: THIS CODE HAS A MAJOR ISSUE (SEE BELOW)
UPDATE OurTable 
SET IsDuplicate = 1
WHERE 
  OtherFilters = 'SomeValue' --// Other filters, so only checking certain rows
  AND Id NOT IN ( --// ID is either unique or matches the first 'duplicate'
    SELECT MIN(Id) FROM OurTable --// Pick the lowest ID for a given hash
    WHERE OtherFilters = 'SomeValue' --// Same as the OtherFilters above!
    GROUP BY --// Group by hash (i.e. duplicates grouped)
      HASHBYTES('md5', --// Hash Function 
       SUBSTRING( --// Hash Data (the substring of 8000 chars after the header)
         CONVERT(varchar(max), XmlColumn), --// Substring Data
         CHARINDEX('&lt;Content&gt;', CONVERT(varchar(max), XmlColumn)), --// Index
         8000))) --// Length
</code></pre>
<h2>Review</h2>
<p><strong>There is a major issue with this query</strong>! Can you spot it?</p>
<p>The problem is that it assumes the first 8000 characters of the XML (well, after the trimmed header) are enough for unique identification. While this may be a valid assumption (as it was in my case), if it&#8217;s wrong you run the risk of falsely labeling some XML a duplicate, which could be disastrous.</p>
<p>At the time I considered resolving this by appending the hashes of the next 8000 characters, possibly repeating if necessary to increase the character coverage (one of my less bright ideas).</p>
<p>In retrospect simple string comparison was not only sufficient, but a better (if not as performant) solution (<a href="http://stackoverflow.com/questions/11517288/how-do-i-convert-an-xml-field-with-more-than-8000-characters-into-a-string/11527424#11527424">the goose chase</a> of believing that conversion of large <code>XML</code> to <code>varchar</code> had issues put this idea out of my mind). It also has the added benefit of avoiding admittedly unlikely <a href="http://en.wikipedia.org/wiki/MD5#Collision_vulnerabilities">MD5 collisions</a>.</p>
<p>However, if performance is a concern (or depending on the number of rows and size of XML values involved) hashing may still be a good fallback option (perhaps even with my terrible &#8216;concatenated hashes&#8217; approach). Alternatively I would probably look to point <a href="http://www.linqpad.net/">LINQPad</a> at the database and write some pretty basic code to perform duplicate detection (which would have additional advantages if the XML was processed in different ways with regard to whitespace and self-closing tags).<a name="improved-solution"></a></p>
<h2>Improved Solution</h2>
<p>Assuming performance isn&#8217;t a serious bottleneck, something like the following works (and is what I&#8217;ve used subsequently):</p>
<pre><code>UPDATE OurTable 
SET IsDuplicate = 1 
WHERE 
  OtherFilters = 'SomeValue' --// Other filters, so only checking certain rows
  AND Id NOT IN ( --// ID is either unique or matches the first 'duplicate' 
    SELECT MIN(Id) FROM OurTable --// Pick the lowest ID for a given hash 
    WHERE OtherFilters = 'SomeValue' --// Same as the OtherFilters above!
    GROUP BY --// Group by content (i.e. duplicates grouped) 
      SUBSTRING( 
        CONVERT(varchar(max), XmlColumn), --// Substring Data 
        CHARINDEX('&lt;Content&gt;', CONVERT(varchar(max), XmlColumn)), --// Start Index 
        LEN(CONVERT(varchar(max), XmlColumn)))) --// Length, excess is handled
</code></pre>
<p>Since originally publishing this I did a little more research on the issues with hashing, and should you go down this direction there&#8217;s <a href="http://blog.kejser.org/2011/11/06/exploring-hash-functions-in-sql-server/">a great article by Thomas Kejser on SQL hash functions and performance</a>. For one, it makes sense to use something like <code>SHA1</code> instead of the <code>MD5</code> in my example as it reduces the likelihood of collision issues without a noticeable performance difference.</p>
<p>I have the feeling there&#8217;s much room for others optimisations and approaches here, so if anyone has run into this problem before or has some ideas on what to do next time I&#8217;m curious to hear more!</p>
<p>Posted as <a href="http://mattmitchell.com.au/detecting-duplicate-xml-data-in-sql-server/">Detecting Duplicate XML data in SQL Server</a> at <a href="http://mattmitchell.com.au">Matt Mitchell</a></p>]]></content:encoded>
			<wfw:commentRss>http://mattmitchell.com.au/detecting-duplicate-xml-data-in-sql-server/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Zebras in System.Net.NetworkCredential</title>
		<link>http://mattmitchell.com.au/zebras-in-system-net-networkcredential/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=zebras-in-system-net-networkcredential</link>
		<comments>http://mattmitchell.com.au/zebras-in-system-net-networkcredential/#comments</comments>
		<pubDate>Mon, 09 Jul 2012 20:19:04 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Technical]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[FTP]]></category>

		<guid isPermaLink="false">http://mattmitchell.com.au/?p=5</guid>
		<description><![CDATA[<p>Ran into an interesting problem recently where some pretty straightforward FTP code was throwing a WebException on GetResponse when using correct server details. Looking a little further, the error indicated there was an Object reference not set to an instance &#8230; <a href="http://mattmitchell.com.au/zebras-in-system-net-networkcredential/">Continue reading <span class="meta-nav">&#8594;</span></a></p><p>Posted as <a href="http://mattmitchell.com.au/zebras-in-system-net-networkcredential/">Zebras in System.Net.NetworkCredential</a> at <a href="http://mattmitchell.com.au">Matt Mitchell</a></p>]]></description>
				<content:encoded><![CDATA[<p>Ran into an interesting problem recently where some pretty straightforward FTP code was throwing a <code>WebException</code> on <code>GetResponse</code> when using correct server details.</p>
<p>Looking a little further, the error indicated there was an <em>Object reference not set to an instance of an object</em> (<code>NullReferenceException</code>).</p>
<p>If you&#8217;re here for the fix, feel free to jump to <a href="#workaround">Workaround</a>.</p>
<h2>Diagnosis</h2>
<p>Normally a <code>WebException</code> is pretty informative (usually credential or connectivity issues) but in this case I was getting something unusual:</p>
<ul>
<li><strong>Status:</strong> UnknownError</li>
<li><strong>Message:</strong> Object reference not set to an instance of an object. </li>
</ul>
<p>Well that&#8217;s <code>NullReferenceException</code> text, but this was thrown from framework code and there&#8217;s no way the .NET Framework is throwing <code>NullReferenceExceptions</code> on relatively straightforward code right?</p>
<p><a href="http://en.wikipedia.org/wiki/Zebra_%28medicine%29">Think Horses not Zebras</a> (or its development equivalent <a href="http://www.codinghorror.com/blog/2008/03/the-first-rule-of-programming-its-always-your-fault.html">Select Isn&#8217;t Broken</a>) told me there was something wrong with my code.</p>
<blockquote>
<p>We worked on a project where a senior engineer was convinced that the select system call was broken on Solaris. No amount of persuasion or logic could change his mind (the fact that every other networking application on the box worked fine was irrelevant). He spent weeks writing workarounds, which, for some odd reason, didn&#8217;t seem to fix the problem. When finally forced to sit down and read the documentation on select, he discovered the problem and corrected it in a matter of minutes. <strong>We now use the phrase &#8220;select is broken&#8221; as a gentle reminder whenever one of us starts blaming the system for a fault that is likely to be our own</strong>.</p>
<p><strong>Source:</strong> <a href="http://pragprog.com/the-pragmatic-programmer/">The Pragamtic Programmer</a> via <a href="http://www.codinghorror.com/blog/2008/03/the-first-rule-of-programming-its-always-your-fault.html">Coding Horror</a></p>
</blockquote>
<p>I reduced my code to the simple test-case below and ran it through <a href="http://www.linqpad.net/">LINQPad</a>.</p>
<pre><code>NetworkCredential credentials = new NetworkCredential();
credentials.UserName = "user";
credentials.Password = "pass";
FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create("ftp://localhost");
request.Credentials = credentials;
request.Method = WebRequestMethods.Ftp.ListDirectoryDetails;

// Throws error
using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
{
}
</code></pre>
<p>But I continued to get the <code>WebException</code>, and noticed that sure enough it <em>was</em> wrapping an inner <code>NullReferenceException</code></p>
<pre><code>Object reference not set to an instance of an object.  
   at System.Net.NetworkCredential.InternalGetDomainUserName()
   at System.Net.FtpControlStream.BuildCommandsList(WebRequest req)
   at System.Net.CommandStream.SubmitRequest(WebRequest request, Boolean async, Boolean readInitalResponseOnConnect)
   at System.Net.FtpWebRequest.TimedSubmitRequestHelper(Boolean async)
   at System.Net.FtpWebRequest.SubmitRequest(Boolean async)
</code></pre>
<p>Checking my code for <code>null</code> values revealed no obvious cause and all signs pointed to a framework bug, but surely someone else would have noticed? I did a search and &#8230; <a href="http://social.msdn.microsoft.com/Forums/pl-PL/netfxnetcom/thread/32aa3ff6-06f7-415f-8936-ceae30d4c412">found I wasn&#8217;t alone</a>!</p>
<p>Unfortunately (at the time) there was no clear explanation for what was happening, so it was time to open the hood with my favourite decompiler and check out <code>System.Net.NetworkCredential.InternalGetDomainUserName</code></p>
<pre><code>internal string InternalGetDomainUserName()
{
  string str = this.InternalGetDomain();
  if (str.Length != 0)
    str = str + "\\";
  return str + this.InternalGetUserName();
}
</code></pre>
<p>Hmm, clearly <code>str</code> must be <code>null</code> to cause the exception I was seeing. What didn&#8217;t make sense was why framework code was leaving a potentially <code>null</code> parameter unguarded.</p>
<p>Looking deeper, <code>str</code> was set to <code>InternalGetDomain()</code> which simply returned the local <code>m_domain</code> member.</p>
<pre><code>internal string InternalGetDomain()
{
  return this.m_domain;
}
</code></pre>
<p>This meant that <code>m_domain</code> must be <code>null</code>, but checking the property setter for <code>Domain</code> (the public interface to <code>m_domain</code>) I discovered it guards against <code>null</code> values (using <code>string.Empty</code> instead).</p>
<pre><code>public string Domain
{
    set
    {
      if (value == null)
        this.m_domain = string.Empty;
      else
        this.m_domain = value;
    }
}
</code></pre>
<p>This explained why the framework code wasn&#8217;t guarding (it assumed that the setter property would prevent <code>null</code> values!) but it didn&#8217;t explain why <code>m_domain</code> was <code>null</code>.</p>
<p>Hmm, given it was impossible for me to set <code>Domain</code> to <code>null</code> (through the public interface), it was time to see where <code>Domain / m_Domain</code> was initialised (I hadn&#8217;t changed it from its default after all).</p>
<p><code>System.Net.NetworkCredential</code> has a few constructors, most of which chain to a constructor that initialises the username, password, and domain.</p>
<pre><code>public NetworkCredential()
{
}

public NetworkCredential(string userName, string password)
  : this(userName, password, string.Empty)
{
}

public NetworkCredential(string userName, SecureString password)
  : this(userName, password, string.Empty)
{
}

public NetworkCredential(string userName, string password, string domain)
{
  this.UserName = userName;
  this.Password = password;
  this.Domain = domain;
}

public NetworkCredential(string userName, SecureString password, string domain)
{
  this.UserName = userName;
  this.SecurePassword = password;
  this.Domain = domain;
}
</code></pre>
<p>However, the default (parameterless) constructor does not chain, and sure enough that&#8217;s the one we&#8217;re using!</p>
<p>Actually, the default constructor does nothing at all, leaving private members such as <code>Domain</code> uninitialised (and therefore <code>null</code>) &#8211; a state that we&#8217;ve established for <code>Domain</code> at least is otherwise unachievable through the public interface.</p>
<p>This leads to the following weird behaviours:</p>
<pre><code>// Unaffected: Non-default constructor
new NetworkCredential(
"user", "pass"
); // Domain == String.Empty

// Unaffected: Non-default constructor with named parameters
new NetworkCredential(
userName: "user", password: "pass"
); // Domain == String.Empty

// Impacted: Default constructor with object initializer
new NetworkCredential()
{
Username = "user",
Password = "pass"
}; // Domain == null

// Impacted: Default constructor then property assignment
var creds = new NetworkCredential();
creds.Username = "user";
creds.Password = "pass";
// Domain == null 
</code></pre>
<p>Interestingly enough, this doesn&#8217;t just impact <code>Domain</code> (<code>UserName</code> and <code>Password</code> are also <code>null</code>). For instance, if you were to use the default constructor and not set a <code>Password</code>, a call to <code>credentials.SecurePassword</code> will throw a <code>NullReferenceException</code>.</p>
<pre><code>NetworkCredential credentials = new NetworkCredential();
// Throws NullReferenceException
object password = credentials.SecurePassword; 
</code></pre>
<p><a name="workaround"></a></p>
<h2>Workaround</h2>
<p>Our workaround is therefore:</p>
<ul>
<li>Use another constructor (<code>NetworkCredential credentials = new NetworkCredential("user", "pass");</code>)</li>
<li>Or, set <code>Domain</code> to a value (<code>credentials.Domain = null;</code> would do)</li>
</ul>
<h2>Reflections</h2>
<p>Now to be fair, <a href="http://msdn.microsoft.com/en-us/library/1xabb1hw.aspx">the MSDN documentation</a> <em>does</em> remark that the default constructor does not initialise properties.</p>
<p><img src="http://mattmitchell.com.au/wp-content/uploads/2012/07/networkcredential-remarks.png" alt="System.Net.NetworkCredential Default Constructor MSDN Remarks" /></p>
<p>This being the case though, the framework is not excused from throwing unhandled exceptions and should handle the <code>null</code> properties internally rather than make invalid assumptions.</p>
<p>On Microsoft&#8217;s part, this could be fixed by either:</p>
<ul>
<li>Chaining the default constructor </li>
<li>Or, initialising members in the default constructor</li>
<li>Or, having internal methods such as <code>InternalGetDomainUserName</code> checking members are not <code>null</code> before dereferencing</li>
</ul>
<h2>Outcomes</h2>
<p>I lodged a <a href="http://connect.microsoft.com/VisualStudio/feedback/details/695227/networkcredential-default-constructor-leaves-domain-null-leading-to-null-object-reference-exceptions-in-framework-code">Microsoft Connect ticket</a> for this one and the team was able to verify the issue pretty quickly before advising a fix would be planned in a future release.</p>
<p>I also updated the <a href="http://social.msdn.microsoft.com/Forums/pl-PL/netfxnetcom/thread/32aa3ff6-06f7-415f-8936-ceae30d4c412">MSDN Forums question I came across</a> with the solution (the OP had fortunately already arrived at the workaround by accident).</p>
<p>Posted as <a href="http://mattmitchell.com.au/zebras-in-system-net-networkcredential/">Zebras in System.Net.NetworkCredential</a> at <a href="http://mattmitchell.com.au">Matt Mitchell</a></p>]]></content:encoded>
			<wfw:commentRss>http://mattmitchell.com.au/zebras-in-system-net-networkcredential/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
