<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0">
  <channel>
    <title><![CDATA[[SecurityRatty] tag: override]]></title>
    <link>http://securityratty.com/tag/override</link>
    <description></description>
    <pubDate>Wed, 09 Jan 2008 03:10:54 +0000</pubDate>
    <generator>iRatty Engine</generator>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <item>
      <title><![CDATA[PasswordTextBox]]></title>
      <link>http://securityratty.com/article/4e1580792b56914339b6489792b99933</link>
      <guid>http://securityratty.com/article/4e1580792b56914339b6489792b99933</guid>
      <description><![CDATA[Chris Sells used to poke fun at me when we worked together in my former life . He used to call my security class, &quot;Essential Access Denied&quot;. His point was a good one: when they aren't applied...]]></description>
      <content:encoded><![CDATA[<p><a href="http://www.sellsbrothers.com/" target="_blank">Chris Sells</a> used to poke fun at me when we worked together in my <a href="http://www.flickr.com/photos/andyrs/240203382/" target="_blank">former life</a>. He used to call my security class, &quot;Essential Access Denied&quot;. His point was a good one: when they aren&#39;t applied carefully, security countermeasures often just get in the way of getting work done. I don&#39;t know about you, but password-mode text boxes in web forms have always been one of those annoyances.</p> <p>I&#39;m not complaining about the fact that I can&#39;t see what I&#39;m typing. I understand and laud that feature, because I don&#39;t want someone looking over my shoulder at the password I&#39;m typing, and this even applies when I&#39;m at home. I love my children, but I certainly don&#39;t want them knowing the password to my bank account!</p> <p>No, what I&#39;m bothered by is how a typical password text box behaves on a form that may incur multiple post-backs before it&#39;s finally submitted. If you use the built in ASP.NET TextBox control, it purposely does not repopulate the password text, which means if you press a button on the form that performs a post-back, or if you have a multi-page form that posts back on every step, that password disappears, and the user typically has to re-enter it. You could solve this with liberal use of ASP.NET Ajax UpdatePanels, but that adds its own complexities. I wanted a simpler solution.</p> <p>So I did a little research to see what others had discovered about this problem, and I ended up deriving my own custom control from TextBox to make a much more user-friendly (and developer-friendly) TextBox control. I called it PasswordTextBox, and it acts just like a TextBox in password mode, but it retains the password while still giving the user the same level of protection the standard TextBox supplies.</p> <p>My PasswordTextBox operates very simply: it stores the password in control state, and renders a series of fixed characters (with the same length as the actual password) into the text box so that it &quot;looks&quot; like the user&#39;s password has been rendered. Since control state is part of view state, and since view state is stored in a hidden field on the form, I encrypt the password before putting it into control state.</p> <p>The result is quite nice - the user can post your form back as many times as she needs to, perhaps moving back and forth across wizard steps or tabs, and when she finally presses the &quot;Finish&quot; button (or whatever you call the last step of your input form), your code will be able to read the password by simply accessing the Text property on the PasswordTextBox. The user will believe that her password is sitting there on the form while she&#39;s working, as the same number of obfuscated characters will show up in the field as she typed in originally (what she doesn&#39;t know is that those characters aren&#39;t her real password anymore, but what she doesn&#39;t know won&#39;t hurt her!)</p> <p>Note that to keep this simple, I used DPAPI to encrypt the password, which suited my purposes. But if you have a web farm, that won&#39;t work well at all if you don&#39;t know which machine the user&#39;s going to post back to, so you&#39;ll want to replace that with something more robust. I could see looking up the &lt;machineKey&gt; for entropy, as that tends to be sync&#39;d already across the farm, but I&#39;ve not yet spent the cycles to go down that road, since unfortunately all of the code for generating keys based on that config section are off limits in ASP.NET (most of the useful stuff is marked internal). I don&#39;t think it&#39;d be that hard to do though.</p> <p>Anyway, without further ado, here&#39;s the code, which you&#39;ll see is quite simple. I&#39;d love feedback, especially if you see any glaring problems with the idea or the implementation!</p><pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">class</span> PasswordTextBox : TextBox
{
    <span class="rem">// unlikely that a string of these would be used for a password</span>
    <span class="kwrd">const</span> <span class="kwrd">char</span> PasswordPlaceholderChar = <span class="str">&#39;}&#39;</span>;

    <span class="kwrd">string</span> password; <span class="rem">// stored encrypted in control state</span>

    <span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> OnInit(EventArgs e)
    {
        <span class="kwrd">base</span>.OnInit(e);
        Page.RegisterRequiresControlState(<span class="kwrd">this</span>);
    }

    <span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">object</span> SaveControlState()
    {
        <span class="kwrd">byte</span>[] encryptedPassword = ProtectPassword(password);

        <span class="kwrd">object</span> baseControlState = <span class="kwrd">base</span>.SaveControlState();
        <span class="kwrd">if</span> (<span class="kwrd">null</span> == baseControlState)
            <span class="kwrd">return</span> encryptedPassword;
        <span class="kwrd">else</span> <span class="kwrd">return</span> <span class="kwrd">new</span> Pair(baseControlState, encryptedPassword);
    }

    <span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> LoadControlState(<span class="kwrd">object</span> savedState)
    {
        <span class="kwrd">byte</span>[] encryptedPassword;

        Pair pair = savedState <span class="kwrd">as</span> Pair;
        <span class="kwrd">if</span> (<span class="kwrd">null</span> != pair)
        {
            <span class="kwrd">base</span>.LoadControlState(pair.First);
            encryptedPassword = pair.Second <span class="kwrd">as</span> <span class="kwrd">byte</span>[];
        }
        <span class="kwrd">else</span> encryptedPassword = savedState <span class="kwrd">as</span> <span class="kwrd">byte</span>[];

        password = UnprotectPassword(encryptedPassword);
    }

    <span class="rem">/// &lt;summary&gt;</span>
    <span class="rem">/// This control always uses TextMode=Password</span>
    <span class="rem">/// &lt;/summary&gt;</span>
    <span class="kwrd">public</span> <span class="kwrd">override</span> TextBoxMode TextMode
    {
        get
        {
            <span class="kwrd">return</span> TextBoxMode.Password;
        }
        set { }
    }

    <span class="rem">/// &lt;summary&gt;</span>
    <span class="rem">/// TextBox doesn&#39;t render value attribute for TextMode=Password</span>
    <span class="rem">/// So we add code that renders a placeholder text instead</span>
    <span class="rem">/// &lt;/summary&gt;</span>
    <span class="rem">/// &lt;param name=&quot;writer&quot;&gt;&lt;/param&gt;</span>
    <span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> AddAttributesToRender(HtmlTextWriter writer)
    {
        <span class="kwrd">base</span>.AddAttributesToRender(writer);

        <span class="kwrd">string</span> text = Text;
        <span class="kwrd">if</span> (text.Length &gt; 0)
            writer.AddAttribute(HtmlTextWriterAttribute.Value,
                GetPlaceholderPassword(text));
    }

    <span class="rem">/// &lt;summary&gt;</span>
    <span class="rem">/// TextBox doesn&#39;t save the &quot;Text&quot; viewstate in</span>
    <span class="rem">/// TextMode=Password and we don&#39;t want our behavior to break</span>
    <span class="rem">/// if ViewState is turned off so we store the password in</span>
    <span class="rem">/// Control State, encrypted with MachineKey</span>
    <span class="rem">/// &lt;/summary&gt;</span>
    <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">string</span> Text
    {
        get
        {
            <span class="kwrd">return</span> password ?? <span class="kwrd">string</span>.Empty;
        }
        set
        {
            <span class="rem">// this prevents us overwriting the actual</span>
            <span class="rem">// password with a placeholder</span>
            <span class="kwrd">if</span> (!<span class="kwrd">string</span>.IsNullOrEmpty(password) &amp;&amp;
                <span class="kwrd">value</span>.Equals(GetPlaceholderPassword(password)))
                <span class="kwrd">return</span>;

            password = <span class="kwrd">value</span>;
        }
    }

    <span class="kwrd">private</span> <span class="kwrd">string</span> GetPlaceholderPassword(<span class="kwrd">string</span> realPassword)
    {
        <span class="kwrd">int</span> length = 12;
        <span class="kwrd">if</span> (!<span class="kwrd">string</span>.IsNullOrEmpty(realPassword))
            length = realPassword.Length;

        StringBuilder sb = <span class="kwrd">new</span> StringBuilder();
        sb.Append(PasswordPlaceholderChar, length);

        <span class="kwrd">return</span> sb.ToString();
    }

    <span class="kwrd">public</span> <span class="kwrd">byte</span>[] ProtectPassword(<span class="kwrd">string</span> password)
    {
        <span class="kwrd">if</span> (<span class="kwrd">string</span>.IsNullOrEmpty(password))
            <span class="kwrd">return</span> <span class="kwrd">null</span>;
        <span class="kwrd">byte</span>[] cleartext = Encoding.UTF8.GetBytes(password);
        <span class="kwrd">return</span> ProtectedData.Protect(cleartext, <span class="kwrd">null</span>,
            DataProtectionScope.LocalMachine);
    }

    <span class="kwrd">public</span> <span class="kwrd">string</span> UnprotectPassword(<span class="kwrd">byte</span>[] ciphertext)
    {
        <span class="kwrd">if</span> (<span class="kwrd">null</span> == ciphertext)
            <span class="kwrd">return</span> <span class="kwrd">null</span>;
        <span class="kwrd">byte</span>[] cleartext = ProtectedData.Unprotect(ciphertext, <span class="kwrd">null</span>,
            DataProtectionScope.LocalMachine);
        <span class="kwrd">return</span> Encoding.UTF8.GetString(cleartext);
    }
}
</pre><div style="clear:both;"></div><img src="http://www.pluralsight.com/community/aggbug.aspx?PostID=54154" width="1" height="1">]]></content:encoded>
      <pubDate>Wed, 29 Oct 2008 16:49:54 +0000</pubDate>
      <category domain="http://securityratty.com/tag/password-mode text boxes">password-mode text boxes</category>
      <category domain="http://securityratty.com/tag/text">text</category>
      <category domain="http://securityratty.com/tag/return null">return null</category>
      <category domain="http://securityratty.com/tag/return">return</category>
      <category domain="http://securityratty.com/tag/net">net</category>
      <category domain="http://securityratty.com/tag/net ajax updatepanels">net ajax updatepanels</category>
      <category domain="http://securityratty.com/tag/net textbox control">net textbox control</category>
      <category domain="http://securityratty.com/tag/password">password</category>
      <category domain="http://securityratty.com/tag/textbox control">textbox control</category>
      <source url="http://www.pluralsight.com/community/blogs/keith/archive/2008/10/29/passwordtextbox.aspx">PasswordTextBox</source>
    </item>
    <item>
      <title><![CDATA[GPS Spoofing]]></title>
      <link>http://securityratty.com/article/301910a8390d678e528ed1556dd2bb4e</link>
      <guid>http://securityratty.com/article/301910a8390d678e528ed1556dd2bb4e</guid>
      <description><![CDATA[Interesting : Jon used a desktop computer attached to a GPS satellite simulator to create a fake GPS signal. Portable GPS satellite simulators can fit in the trunk of a car, and are often used for...]]></description>
      <content:encoded><![CDATA[<p><a href="http://philosecurity.org/2008/09/07/gps-spoofing">Interesting</a>:</p>

<blockquote>Jon used a desktop computer attached to a GPS satellite simulator to create a fake GPS signal. Portable GPS satellite simulators can fit in the trunk of a car, and are often used for testing. They are available as commercial off-the-shelf products. You can also rent them for less than $1K a week -- peanuts to anyone thinking of hijacking a cargo truck and selling stolen goods.

<p>In his first experiments, Jon placed his desktop computer and GPS satellite simulator in the cab of his small truck, and powered them off an inverter. The VAT used a second truck as the victim cargo truck. "With this setup," Jon said, "we were able to spoof the GPS receiver from about 30 feet away. If our equipment could broadcast a stronger signal, or if we had purchased stronger signal amplifiers, we certainly could have spoofed over a greater distance."</p>

<p>During later experiments, Jon and the VAT were able to easily achieve much greater GPS spoofing ranges. They spoofed GPS signals at ranges over three quarters of a mile. "The farthest distance we achieved was 4586 feet, at Los Alamos," said Jon. "When you radiate an RF signal, you ideally want line of sight, but in this case we were walking around buildings and near power lines. We really had a lot of obstruction in the way. It surprised us." An attacker could drive within a half mile of the victim truck, and still override the truck's GPS signals.</blockquote></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~f/schneier/fulltext?a=XoEIL"><img src="http://feeds.feedburner.com/~f/schneier/fulltext?i=XoEIL" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/schneier/fulltext?a=JZqYL"><img src="http://feeds.feedburner.com/~f/schneier/fulltext?i=JZqYL" border="0"></img></a>
</div>]]></content:encoded>
      <pubDate>Wed, 17 Sep 2008 03:03:53 +0000</pubDate>
      <category domain="http://securityratty.com/tag/gps">gps</category>
      <category domain="http://securityratty.com/tag/fake gps signal">fake gps signal</category>
      <category domain="http://securityratty.com/tag/signal">signal</category>
      <category domain="http://securityratty.com/tag/gps satellite simulator">gps satellite simulator</category>
      <category domain="http://securityratty.com/tag/truck">truck</category>
      <category domain="http://securityratty.com/tag/victim truck">victim truck</category>
      <category domain="http://securityratty.com/tag/victim cargo truck">victim cargo truck</category>
      <category domain="http://securityratty.com/tag/stronger signal amplifiers">stronger signal amplifiers</category>
      <category domain="http://securityratty.com/tag/cargo truck">cargo truck</category>
      <source url="http://www.schneier.com/blog/archives/2008/09/gps_spoofing.html">GPS Spoofing</source>
    </item>
    <item>
      <title><![CDATA[Better exception reporting in ASP.NET part 2]]></title>
      <link>http://securityratty.com/article/b878f7921917b371086606df6d043229</link>
      <guid>http://securityratty.com/article/b878f7921917b371086606df6d043229</guid>
      <description><![CDATA[This is the third post in a series
The first post described the problem: ASP.NET wasn't reporting inner exception stack traces
The second post described my solution
This post shows the code I used to...]]></description>
      <content:encoded><![CDATA[<p>This is the third post in a series.</p> <p>The <a href="http://www.pluralsight.com/community/blogs/keith/archive/2008/08/01/asp-net-health-monitoring-doesn-t-log-inner-exception-stack-trace.aspx" target="_blank">first post</a> described the problem: ASP.NET wasn&#39;t reporting inner exception stack traces.</p> <p>The <a href="http://www.pluralsight.com/community/blogs/keith/archive/2008/08/01/better-exception-reporting-in-asp-net.aspx" target="_blank">second post</a> described my solution.</p> <p>This post shows the code I used to solve the problem: a custom email provider for the Health Monitoring system in ASP.NET. Enjoy!</p> <p>Here&#39;s the provider. Note that I opted *not* to build a buffering provider to keep things simple:</p><pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">class</span> MyMailWebEventProvider : WebEventProvider
{
    <span class="kwrd">string</span> to;
    <span class="kwrd">string</span> from;
    <span class="kwrd">string</span> subjectPrefix;

    <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">void</span> Initialize(<span class="kwrd">string</span> name,
        NameValueCollection config)
    {
        <span class="kwrd">base</span>.Initialize(name, config);

        to = GetAndRemoveStringAttribute(config, <span class="str">&quot;to&quot;</span>, <span class="kwrd">true</span>);
        from = GetAndRemoveStringAttribute(config, <span class="str">&quot;from&quot;</span>, <span class="kwrd">true</span>);
        subjectPrefix = GetAndRemoveStringAttribute(config,
            <span class="str">&quot;subjectPrefix&quot;</span>, <span class="kwrd">false</span>);
    }
    <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">void</span> ProcessEvent(WebBaseEvent raisedEvent)
    {
        SendMail(raisedEvent);
    }

    <span class="kwrd">private</span> <span class="kwrd">void</span> SendMail(WebBaseEvent raisedEvent)
    {
        <span class="kwrd">string</span> subject = ComputeEmailSubject(raisedEvent);
        <span class="kwrd">string</span> body = ComputeEmailBody(raisedEvent);

        MailMessage msg = <span class="kwrd">new</span> MailMessage(from, to, subject, body);
        <span class="kwrd">new</span> SmtpClient().Send(msg);
    }

    <span class="kwrd">private</span> <span class="kwrd">string</span> ComputeEmailBody(WebBaseEvent raisedEvent)
    {
        WebRequestErrorEvent errorEvent =
            raisedEvent <span class="kwrd">as</span> WebRequestErrorEvent;
        <span class="kwrd">if</span> (<span class="kwrd">null</span> != errorEvent)
            <span class="kwrd">return</span> ErrorEventFormattingHelper.FormatRequestErrorEvent(errorEvent);
        <span class="kwrd">else</span> <span class="kwrd">return</span> raisedEvent.ToString();
    }

    <span class="kwrd">private</span> <span class="kwrd">string</span> ComputeEmailSubject(WebBaseEvent raisedEvent)
    {
        StringBuilder subjectBuilder = <span class="kwrd">new</span> StringBuilder();

        <span class="rem">// surface some details in subject about error events</span>
        WebBaseErrorEvent errorEvent = raisedEvent <span class="kwrd">as</span> WebBaseErrorEvent;
        <span class="kwrd">if</span> (<span class="kwrd">null</span> != errorEvent)
        {
            Exception unhandledException = errorEvent.ErrorException;

            <span class="rem">// drill through reflection exceptions to show the root cause</span>
            TargetInvocationException invocationException =
                unhandledException <span class="kwrd">as</span> TargetInvocationException;
            <span class="kwrd">if</span> (<span class="kwrd">null</span> != invocationException)
            {
                Exception innerException =
                    DrillIntoTargetInvocationException(invocationException);
                subjectBuilder.AppendFormat(<span class="str">&quot;{0}&quot;</span>,
                    (innerException ?? invocationException).GetType().Name);
                <span class="kwrd">if</span> (<span class="kwrd">null</span> != innerException)
                    subjectBuilder.Append(<span class="str">&quot; (via reflection)&quot;</span>);
            }
            <span class="kwrd">else</span> subjectBuilder.Append(unhandledException.GetType().Name);
        }

        <span class="rem">// if we&#39;ve not got anything better</span>
        <span class="rem">// just show the event type in the subject</span>
        <span class="kwrd">if</span> (0 == subjectBuilder.Length)
            subjectBuilder.AppendFormat(<span class="str">&quot;Event type: {0}&quot;</span>,
                raisedEvent.GetType().Name);

        <span class="kwrd">if</span> (!<span class="kwrd">string</span>.IsNullOrEmpty(subjectPrefix)) {
            subjectBuilder.Insert(0, <span class="str">&#39; &#39;</span>);
            subjectBuilder.Insert(0, subjectPrefix);
        }
        <span class="kwrd">return</span> subjectBuilder.ToString();
    }

    <span class="rem">/// &lt;summary&gt;</span>
    <span class="rem">/// Reflection often hides exception details, so we try to drill down</span>
    <span class="rem">/// through the plumbing exceptions to find a likely cause</span>
    <span class="rem">/// &lt;/summary&gt;</span>
    <span class="kwrd">private</span> Exception DrillIntoTargetInvocationException(
        TargetInvocationException outerException)
    {
        Exception innerException = outerException.InnerException;
        TargetInvocationException innerInvocationException =
            innerException <span class="kwrd">as</span> TargetInvocationException;
        <span class="kwrd">if</span> (<span class="kwrd">null</span> != innerInvocationException)
            <span class="kwrd">return</span> DrillIntoTargetInvocationException(innerInvocationException);
        <span class="kwrd">else</span> <span class="kwrd">if</span> (<span class="kwrd">null</span> != innerException)
            <span class="kwrd">return</span> innerException;
        <span class="kwrd">else</span> <span class="kwrd">return</span> <span class="kwrd">null</span>;
    }

    <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">string</span> GetAndRemoveStringAttribute(NameValueCollection config,
        <span class="kwrd">string</span> attributeName, <span class="kwrd">bool</span> required)
    {
        <span class="kwrd">string</span> <span class="kwrd">value</span> = config.Get(attributeName);
        <span class="kwrd">if</span> (required &amp;&amp; <span class="kwrd">string</span>.IsNullOrEmpty(<span class="kwrd">value</span>))
            <span class="kwrd">throw</span> <span class="kwrd">new</span> ConfigurationErrorsException(<span class="kwrd">string</span>.Format(
                <span class="str">&quot;Expected attribute {0}, which is missing or empty.&quot;</span>,
                attributeName));
        config.Remove(attributeName);
        <span class="kwrd">return</span> <span class="kwrd">value</span>;
    }

    <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">void</span> Flush()
    {
        <span class="rem">// nothing to do - this is not a buffering provider</span>
    }

    <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">void</span> Shutdown()
    {
        <span class="rem">// nothing to do here either</span>
    }
}</pre>
<p>Here&#39;s a helper class that formats the error messages the way I want to see them. Note that I&#39;ve omitted some fields that I personally didn&#39;t care about, and I&#39;ve reordered things a bit, so you might want to tweak this if you&#39;re going to use it in your own system.</p><pre class="csharpcode"><span class="kwrd">internal</span> <span class="kwrd">static</span> <span class="kwrd">class</span> ErrorEventFormattingHelper
{
    <span class="kwrd">internal</span> <span class="kwrd">static</span> <span class="kwrd">string</span> FormatRequestErrorEvent(
        WebRequestErrorEvent errorEvent)
    {
        CustomEventFormatter formatter = 
            <span class="kwrd">new</span> CustomEventFormatter();

        formatter.AppendLine(<span class="kwrd">string</span>.Format(
            <span class="str">&quot;Unhandled Exception in {0}:&quot;</span>,
            WebBaseEvent.ApplicationInformation
            .ApplicationVirtualPath));
        formatter.Indent();
        EmitExceptionAtAGlance(formatter, 
            errorEvent.ErrorException);
        formatter.RevertIndent();

        formatter.AppendLine();
        formatter.AppendLine(<span class="str">&quot;Exception stack trace(s):&quot;</span>);
        EmitExceptionStackTrace(formatter, 
            errorEvent.ErrorException);

        formatter.AppendLine();
        formatter.AppendLine(<span class="str">&quot;Event information:&quot;</span>);
        formatter.Indent();
        EmitEventInfo(formatter, errorEvent);
        formatter.RevertIndent();

        formatter.AppendLine();
        formatter.AppendLine(<span class="str">&quot;Application information:&quot;</span>);
        formatter.Indent();
        EmitApplicationInfo(formatter, 
            WebBaseEvent.ApplicationInformation);
        formatter.RevertIndent();

        formatter.AppendLine();
        formatter.AppendLine(<span class="str">&quot;Process/thread information:&quot;</span>);
        formatter.Indent();
        EmitProcessInfo(formatter, 
            errorEvent.ProcessInformation);
        formatter.RevertIndent();

        formatter.AppendLine();
        formatter.AppendLine(<span class="str">&quot;Request information:&quot;</span>);
        formatter.Indent();
        EmitRequestInfo(formatter, 
            errorEvent.RequestInformation);
        formatter.RevertIndent();

        <span class="kwrd">return</span> formatter.ToString();
    }

    <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> EmitEventInfo(
        CustomEventFormatter formatter,
        WebBaseEvent theEvent)
    {
        formatter.AppendLine(<span class="kwrd">string</span>.Format(
            <span class="str">&quot;Event code: {0}&quot;</span>,
            theEvent.EventCode.ToString(
            CultureInfo.InvariantCulture)));
        formatter.AppendLine(<span class="kwrd">string</span>.Format(
            <span class="str">&quot;Event message: {0}&quot;</span>, 
            theEvent.Message));
        formatter.AppendLine(<span class="kwrd">string</span>.Format(
            <span class="str">&quot;Event time: {0}&quot;</span>, 
            theEvent.EventTime.ToString(
            CultureInfo.InvariantCulture)));
        formatter.AppendLine(<span class="kwrd">string</span>.Format(
            <span class="str">&quot;Event ID: {0}&quot;</span>, 
            theEvent.EventID.ToString(<span class="str">&quot;N&quot;</span>, 
            CultureInfo.InvariantCulture)));
    }

    <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> EmitApplicationInfo(
        CustomEventFormatter formatter, 
        WebApplicationInformation appInfo)
    {
        formatter.AppendLine(<span class="kwrd">string</span>.Format(
            <span class="str">&quot;Application domain: {0}&quot;</span>, 
            appInfo.ApplicationDomain));
        formatter.AppendLine(<span class="kwrd">string</span>.Format(
            <span class="str">&quot;Application Virtual Path: {0}&quot;</span>, 
            appInfo.ApplicationVirtualPath));
        formatter.AppendLine(<span class="kwrd">string</span>.Format(
            <span class="str">&quot;Application Physical Path: {0}&quot;</span>, 
            appInfo.ApplicationPath));
    }

    <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> EmitProcessInfo(
        CustomEventFormatter formatter, 
        WebProcessInformation webProcessInfo)
    {
        formatter.AppendLine(<span class="kwrd">string</span>.Format(
            <span class="str">&quot;Process ID: {0}&quot;</span>, 
            webProcessInfo.ProcessID.ToString(
            CultureInfo.InvariantCulture)));
        formatter.AppendLine(<span class="kwrd">string</span>.Format(
            <span class="str">&quot;Process name: {0}&quot;</span>, 
            webProcessInfo.ProcessName));
        formatter.AppendLine(<span class="kwrd">string</span>.Format(
            <span class="str">&quot;Account name: {0}&quot;</span>, 
            webProcessInfo.AccountName));
    }

    <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> EmitRequestInfo(
        CustomEventFormatter formatter, 
        WebRequestInformation webRequestInfo)
    {
        <span class="kwrd">string</span> name = <span class="kwrd">null</span>;
        <span class="kwrd">if</span> (webRequestInfo.Principal != <span class="kwrd">null</span>)
            name = webRequestInfo.Principal.Identity.Name;

        formatter.AppendLine(<span class="kwrd">string</span>.Format(
            <span class="str">&quot;Request URL: {0}&quot;</span>, 
            webRequestInfo.RequestUrl));
        formatter.AppendLine(<span class="kwrd">string</span>.Format(
            <span class="str">&quot;Request path: {0}&quot;</span>, 
            webRequestInfo.RequestPath));
        formatter.AppendLine(<span class="kwrd">string</span>.Format(
            <span class="str">&quot;User name: {0}&quot;</span>, 
            name ?? <span class="str">&quot;[ANONYMOUS]&quot;</span>));
        formatter.AppendLine(<span class="kwrd">string</span>.Format(
            <span class="str">&quot;User host address: {0}&quot;</span>, 
            webRequestInfo.UserHostAddress));
    }

    <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> EmitExceptionAtAGlance(
        CustomEventFormatter formatter, 
        Exception exception)
    {
        formatter.AppendLine(<span class="kwrd">string</span>.Format(
            <span class="str">&quot;Type: {0}&quot;</span>, 
            exception.GetType().Name));
        formatter.AppendLine(<span class="kwrd">string</span>.Format(
            <span class="str">&quot;Message: {0}&quot;</span>, 
            exception.Message));
        <span class="kwrd">if</span> (<span class="kwrd">null</span> != exception.InnerException)
        {
            formatter.Indent();
            formatter.AppendLine(<span class="str">&quot;--&gt;Inner Exception&quot;</span>);
            EmitExceptionAtAGlance(formatter, 
                exception.InnerException);
            formatter.RevertIndent();
        }
    }

    <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> EmitExceptionStackTrace(
        CustomEventFormatter formatter, Exception exception)
    {
        formatter.AppendLine(exception.StackTrace);

        <span class="kwrd">if</span> (<span class="kwrd">null</span> != exception.InnerException)
        {
            <span class="rem">// no point indenting</span>
            <span class="rem">// since stack traces typically wrap like crazy</span>
            formatter.AppendLine();
            formatter.AppendLine(<span class="str">&quot;--&gt;Inner exception stack trace:&quot;</span>);
            EmitExceptionStackTrace(formatter, exception.InnerException);
        }
    }
}
</pre>
<p>And finally, here&#39;s a helper class that manages indentation levels for the output email message:</p><pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">class</span> CustomEventFormatter
{
    <span class="kwrd">const</span> <span class="kwrd">int</span> TabSpaces = 4;

    StringBuilder sb = <span class="kwrd">new</span> StringBuilder();
    <span class="kwrd">private</span> <span class="kwrd">int</span> indentLevel;
    <span class="kwrd">private</span> <span class="kwrd">bool</span> startingNewLine = <span class="kwrd">true</span>;

    <span class="kwrd">public</span> <span class="kwrd">void</span> Indent()
    {
        ++indentLevel;
    }

    <span class="kwrd">public</span> <span class="kwrd">void</span> RevertIndent()
    {
        <span class="kwrd">if</span> (indentLevel &gt; 0)
            --indentLevel;
    }

    <span class="kwrd">public</span> <span class="kwrd">void</span> Append(<span class="kwrd">string</span> text)
    {
        <span class="kwrd">if</span> (startingNewLine)
            EmitIndent();
        sb.Append(text);
        startingNewLine = <span class="kwrd">false</span>;
    }

    <span class="kwrd">public</span> <span class="kwrd">void</span> AppendLine(<span class="kwrd">string</span> lineOfText)
    {
        <span class="kwrd">if</span> (startingNewLine)
            EmitIndent();
        EmitIndent();
        sb.AppendLine(lineOfText);
        startingNewLine = <span class="kwrd">true</span>;
    }

    <span class="kwrd">private</span> <span class="kwrd">void</span> EmitIndent()
    {
        sb.Append(<span class="str">&#39; &#39;</span>, TabSpaces * indentLevel);
    }

    <span class="kwrd">public</span> <span class="kwrd">void</span> AppendLine()
    {
        AppendLine(<span class="kwrd">string</span>.Empty);
    }

    <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">string</span> ToString()
    {
        <span class="kwrd">return</span> sb.ToString();
    }
}
</pre>
<p>Build this into a library application and reference it in your config file. Here&#39;s an example:</p><pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">healthMonitoring</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">providers</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">add</span> <span class="attr">name</span><span class="kwrd">=&quot;mailWebEventProvider&quot;</span>
         <span class="attr">type</span><span class="kwrd">=&quot;MyMailWebEventProvider&quot;</span>
         <span class="attr">to</span><span class="kwrd">=&quot;web-fault@fabrikam.com&quot;</span>
         <span class="attr">from</span><span class="kwrd">=&quot;website@fabrikam.com&quot;</span>
         <span class="attr">buffer</span><span class="kwrd">=&quot;false&quot;</span>
         <span class="attr">subjectPrefix</span><span class="kwrd">=&quot;[WEB-ERROR]&quot;</span>
       <span class="kwrd">/&gt;</span>
  <span class="kwrd">&lt;/</span><span class="html">providers</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">rules</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">add</span> <span class="attr">name</span><span class="kwrd">=&quot;All Errors Email&quot;</span>
         <span class="attr">eventName</span><span class="kwrd">=&quot;All Errors&quot;</span>
         <span class="attr">provider</span><span class="kwrd">=&quot;mailWebEventProvider&quot;</span>
         <span class="attr">profile</span><span class="kwrd">=&quot;Default&quot;</span>
         <span class="attr">minInstances</span><span class="kwrd">=&quot;1&quot;</span>
         <span class="attr">maxLimit</span><span class="kwrd">=&quot;Infinite&quot;</span>
         <span class="attr">minInterval</span><span class="kwrd">=&quot;00:01:00&quot;</span>
         <span class="attr">custom</span><span class="kwrd">=&quot;&quot;</span><span class="kwrd">/&gt;</span>
  <span class="kwrd">&lt;/</span><span class="html">rules</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">healthMonitoring</span><span class="kwrd">&gt;</span>
</pre><div style="clear:both;"></div><img src="http://www.pluralsight.com/community/aggbug.aspx?PostID=52349" width="1" height="1">]]></content:encoded>
      <pubDate>Mon, 04 Aug 2008 10:11:14 +0000</pubDate>
      <category domain="http://securityratty.com/tag/return">return</category>
      <category domain="http://securityratty.com/tag/return subjectbuilder">return subjectbuilder</category>
      <category domain="http://securityratty.com/tag/return formatter">return formatter</category>
      <category domain="http://securityratty.com/tag/exception">exception</category>
      <category domain="http://securityratty.com/tag/formatter">formatter</category>
      <category domain="http://securityratty.com/tag/crazy formatter">crazy formatter</category>
      <category domain="http://securityratty.com/tag/static void">static void</category>
      <category domain="http://securityratty.com/tag/static void emitprocessinfo">static void emitprocessinfo</category>
      <category domain="http://securityratty.com/tag/return null">return null</category>
      <source url="http://www.pluralsight.com/community/blogs/keith/archive/2008/08/04/better-exception-reporting-in-asp-net-part-2.aspx">Better exception reporting in ASP.NET part 2</source>
    </item>
    <item>
      <title><![CDATA[Kill Switches and Remote Control]]></title>
      <link>http://securityratty.com/article/6faff6d8aced2811984a7463136f6b3a</link>
      <guid>http://securityratty.com/article/6faff6d8aced2811984a7463136f6b3a</guid>
      <description><![CDATA[It used to be that just the entertainment industries wanted to control your computers -- and televisions and iPods and everything else -- to ensure that you didn't violate any copyright rules. But now...]]></description>
      <content:encoded><![CDATA[It used to be that just the entertainment industries wanted to control your computers -- and televisions and iPods and everything else -- to ensure that you didn't violate any copyright rules. But now everyone else wants to get their hooks into your gear.

OnStar will soon include the <a href="http://www.informationweek.com/news/mobility/showArticle.jhtml?articleID=202400922">ability</a> for the police to shut off your engine remotely. Buses are getting the <a href="http://www.nypost.com/seven/06082008/news/regionalnews/busting_terror_114567.htm">same capability</a>, in case terrorists want to re-enact the movie <cite>Speed</cite>. The Pentagon wants a kill switch <a href="http://blog.wired.com/defense/2008/06/the-pentagons-n.html">installed</a> on airplanes, and is worried about potential enemies <a href="http://spectrum.ieee.org/may08/6171">installing</a> kill switches on their own equipment. 

Microsoft is doing some of the most creative thinking along these lines, with something it's calling "<a href="http://arstechnica.com/news.ars/post/20080611-microsoft-patent-brings-miss-manners-into-the-digital-age.html">Digital Manners Policies</a>." According to its <a href="http://appft1.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&Sect2=HITOFF&d=PG01&p=1&u=%2Fnetahtml%2FPTO%2Fsrchnum.html&r=1&f=G&l=50&s1=%2220080125102%22.PGNR.&OS=DN/20080125102&RS=DN/20080125102">patent application</a>, DMP-enabled devices would accept broadcast "orders" limiting capabilities. Cellphones could be remotely set to vibrate mode in restaurants and concert halls, and be turned off on airplanes and in hospitals. Cameras could be prohibited from taking pictures in locker rooms and museums, and recording equipment could be disabled in theaters. Professors finally could prevent students from texting one another during class. 

The possibilities are endless, and very dangerous. Making this work involves building a nearly flawless hierarchical system of authority. That's a difficult security problem even in its simplest form. Distributing that system among a variety of different devices -- computers, phones, PDAs, cameras, recorders -- with different firmware and manufacturers, is even more difficult. Not to mention delegating different levels of authority to various agencies, enterprises, industries and individuals, and then enforcing the necessary safeguards.

Once we go down this path -- giving one device authority over other devices -- the security problems start piling up. Who has the authority to limit functionality of my devices, and how do they get that authority? What prevents them from abusing that power? Do I get the ability to override their limitations? In what circumstances, and how? Can they override my override?

How do we prevent this from being abused? Can a burglar, for example, enforce a "no photography" rule and prevent security cameras from working? Can the police enforce the same rule to avoid another Rodney King incident? Do the police get "superuser" devices that cannot be limited, and do they get "supercontroller" devices that can limit anything? How do we ensure that only they get them, and what do we do when the devices inevitably fall into the wrong hands?

It's comparatively easy to make this work in closed specialized systems -- OnStar, airplane avionics, military hardware -- but much more difficult in open-ended systems. If you think Microsoft's vision could possibly be securely designed, all you have to do is look at the dismal effectiveness of the various copy-protection and digital-rights-management systems we've seen over the years. That's a similar capabilities-enforcement mechanism, albeit simpler than these more general systems.

And that's the key to understanding this system. Don't be fooled by the scare stories of wireless devices on airplanes and in hospitals, or visions of a world where no one is yammering loudly on their cellphones in posh restaurants. This is really about media companies wanting to exert their control further over your electronics. They not only want to prevent you from surreptitiously recording movies and concerts, they want your new television to enforce good "manners" on your computer, and not allow it to record any programs. They want your iPod to politely refuse to copy music to a computer other than your own. They want to enforce <em>their</em> legislated definition of manners: to control what you do and when you do it, and to charge you repeatedly for the privilege whenever possible. 

"Digital Manners Policies" is a marketing term. Let's call this what it really is: Selective Device Jamming. It's not polite, it's dangerous. It won't make anyone more secure -- or more polite.

This essay <a href="http://www.wired.com/politics/security/commentary/securitymatters/2008/06/securitymatters_0626">originally appeared</a> in Wired.com.<div class="feedflare">
<a href="http://feeds.feedburner.com/~f/schneier/fulltext?a=JiKwGJ"><img src="http://feeds.feedburner.com/~f/schneier/fulltext?i=JiKwGJ" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/schneier/fulltext?a=aXm5MJ"><img src="http://feeds.feedburner.com/~f/schneier/fulltext?i=aXm5MJ" border="0"></img></a>
</div>]]></content:encoded>
      <pubDate>Tue, 01 Jul 2008 02:48:37 +0000</pubDate>
      <category domain="http://securityratty.com/tag/wireless devices">wireless devices</category>
      <category domain="http://securityratty.com/tag/devices">devices</category>
      <category domain="http://securityratty.com/tag/devices inevitably">devices inevitably</category>
      <category domain="http://securityratty.com/tag/digital manners policies">digital manners policies</category>
      <category domain="http://securityratty.com/tag/prevent">prevent</category>
      <category domain="http://securityratty.com/tag/prevent security cameras">prevent security cameras</category>
      <category domain="http://securityratty.com/tag/difficult security">difficult security</category>
      <category domain="http://securityratty.com/tag/cameras">cameras</category>
      <category domain="http://securityratty.com/tag/prevent students">prevent students</category>
      <source url="http://www.schneier.com/blog/archives/2008/07/kill_switches_a.html">Kill Switches and Remote Control</source>
    </item>
    <item>
      <title><![CDATA[Security Matters: I've Seen the Future, and It Has a Kill Switch]]></title>
      <link>http://securityratty.com/article/b9aa8529e116abf92778a4755495e63d</link>
      <guid>http://securityratty.com/article/b9aa8529e116abf92778a4755495e63d</guid>
      <description><![CDATA[It used to be that just the entertainment industries wanted to control your computers -- and televisions and iPods and everything else -- to ensure that you didn't violate any copyright rules. But now...]]></description>
      <content:encoded><![CDATA[<p>It used to be that just the entertainment industries wanted to control your computers -- and televisions and iPods and everything else -- to ensure that you didn't violate any copyright rules. But now everyone else wants to get their hooks into your gear.
</p><p>
OnStar will soon include the <a href="http://www.informationweek.com/news/mobility/showArticle.jhtml?articleID=202400922">ability</a> for the police to shut off your engine remotely. Buses are getting the <a href="http://www.nypost.com/seven/06082008/news/regionalnews/busting_terror_114567.htm">same capability</a>, in case terrorists want to re-enact the movie <cite>Speed</cite>. The Pentagon wants a kill switch <a href="http://blog.wired.com/defense/2008/06/the-pentagons-n.html">installed</a> on airplanes, and is worried about potential enemies <a href="http://spectrum.ieee.org/may08/6171">installing</a> kill switches on their own equipment. 
</p><p>
Microsoft is doing some of the most creative thinking along these lines, with something it's calling "<a href="http://arstechnica.com/news.ars/post/20080611-microsoft-patent-brings-miss-manners-into-the-digital-age.html">Digital Manners Policies</a>." According to its <a href="http://appft1.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&Sect2=HITOFF&d=PG01&p=1&u=%2Fnetahtml%2FPTO%2Fsrchnum.html&r=1&f=G&l=50&s1=%2220080125102%22.PGNR.&OS=DN/20080125102&RS=DN/20080125102">patent application</a>, DMP-enabled devices would accept broadcast "orders" limiting capabilities. Cellphones could be remotely set to vibrate mode in restaurants and concert halls, and be turned off on airplanes and in hospitals. Cameras could be prohibited from taking pictures in locker rooms and museums, and recording equipment could be disabled in theaters. Professors finally could prevent students from texting one another during class. 
</p><p>
The possibilities are endless, and very dangerous. Making this work involves building a nearly flawless hierarchical system of authority. That's a difficult security problem even in its simplest form. Distributing that system among a variety of different devices -- computers, phones, PDAs, cameras, recorders -- with different firmware and manufacturers, is even more difficult. Not to mention delegating different levels of authority to various agencies, enterprises, industries and individuals, and then enforcing the necessary safeguards.
</p><p>
Once we go down this path -- giving one device authority over other devices -- the security problems start piling up. Who has the authority to limit functionality of my devices, and how do they get that authority? What prevents them from abusing that power? Do I get the ability to override their limitations? In what circumstances, and how? Can they override my override?
</p><p>
How do we prevent this from being abused? Can a burglar, for example, enforce a "no photography" rule and prevent security cameras from working? Can the police enforce the same rule to avoid another Rodney King incident? Do the police get "superuser" devices that cannot be limited, and do they get "supercontroller" devices that can limit anything? How do we ensure that only they get them, and what do we do when the devices inevitably fall into the wrong hands?
</p><p>
It's comparatively easy to make this work in closed specialized systems -- OnStar, airplane avionics, military hardware -- but much more difficult in open-ended systems. If you think Microsoft's vision could possibly be securely designed, all you have to do is look at the dismal effectiveness of the various copy-protection and digital-rights-management systems we've seen over the years. That's a similar capabilities-enforcement mechanism, albeit simpler than these more general systems.
</p><p>
And that's the key to understanding this system. Don't be fooled by the scare stories of wireless devices on airplanes and in hospitals, or visions of a world where no one is yammering loudly on their cellphones in posh restaurants. This is really about media companies wanting to exert their control further over your electronics. They not only want to prevent you from surreptitiously recording movies and concerts, they want your new television to enforce good "manners" on your computer, and not allow it to record any programs. They want your iPod to politely refuse to copy music a computer other than your own. They want to enforce <em>their</em> legislated definition of manners: to control what you do and when you do it, and to charge you repeatedly for the privilege whenever possible. 
</p><p>
"Digital Manners Policies" is a marketing term. Let's call this what it really is: Selective Device Jamming. It's not polite, it's dangerous. It won't make anyone more secure -- or more polite.
</p>
<p>
---
</p>
<p><em>Bruce Schneier is chief security technology officer of BT, and author of</em> Beyond Fear: Thinking Sensibly About Security in an Uncertain World<em>.</em>
</p><br style="clear: both;"/>
  <img alt="" style="border: 0; height:1px; width:1px;" border="0" src="http://www.pheedo.com/img.phdo?i=2e7004605a2cfdb2dff6647568035341" height="1" width="1"/>
<img src="http://www.pheedo.com/feeds/tracker.php?i=2e7004605a2cfdb2dff6647568035341" style="display: none;" border="0" height="1" width="1" alt=""/><div class="feedflare">
<a href="http://feeds.feedburner.com/~f/wired/politics/privacy?a=TdV5GI"><img src="http://feeds.feedburner.com/~f/wired/politics/privacy?i=TdV5GI" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/wired/politics/privacy?a=hCKWyi"><img src="http://feeds.feedburner.com/~f/wired/politics/privacy?i=hCKWyi" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/wired/politics/privacy?a=P6GE7i"><img src="http://feeds.feedburner.com/~f/wired/politics/privacy?i=P6GE7i" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/wired/politics/privacy?a=YY5ZlI"><img src="http://feeds.feedburner.com/~f/wired/politics/privacy?i=YY5ZlI" border="0"></img></a>
 <a href="http://feeds.wired.com/~f/wired/politics/security?a=rAla0I"><img src="http://feeds.wired.com/~f/wired/politics/security?i=rAla0I" border="0"></img></a> <a href="http://feeds.wired.com/~f/wired/politics/security?a=DKXIgi"><img src="http://feeds.wired.com/~f/wired/politics/security?i=DKXIgi" border="0"></img></a> <a href="http://feeds.wired.com/~f/wired/politics/security?a=IE7M8i"><img src="http://feeds.wired.com/~f/wired/politics/security?i=IE7M8i" border="0"></img></a> <a href="http://feeds.wired.com/~f/wired/politics/security?a=swX5hI"><img src="http://feeds.wired.com/~f/wired/politics/security?i=swX5hI" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/wired/politics/privacy/~4/320220918" height="1" width="1"/><img src="http://feeds.wired.com/~r/wired/politics/security/~4/320220920" height="1" width="1"/>]]></content:encoded>
      <pubDate>Thu, 26 Jun 2008 00:00:00 +0000</pubDate>
      <category domain="http://securityratty.com/tag/security">security</category>
      <category domain="http://securityratty.com/tag/wireless devices">wireless devices</category>
      <category domain="http://securityratty.com/tag/devices">devices</category>
      <category domain="http://securityratty.com/tag/prevent">prevent</category>
      <category domain="http://securityratty.com/tag/prevent security cameras">prevent security cameras</category>
      <category domain="http://securityratty.com/tag/difficult security">difficult security</category>
      <category domain="http://securityratty.com/tag/cameras">cameras</category>
      <category domain="http://securityratty.com/tag/prevent students">prevent students</category>
      <category domain="http://securityratty.com/tag/difficult">difficult</category>
      <source url="http://feeds.wired.com/~r/wired/politics/security/~3/320220920/securitymatters_0626">Security Matters: I've Seen the Future, and It Has a Kill Switch</source>
    </item>
    <item>
      <title><![CDATA[Enabling hierarchical nant builds]]></title>
      <link>http://securityratty.com/article/6d991aa98c59ab5248eca3f43819fd48</link>
      <guid>http://securityratty.com/article/6d991aa98c59ab5248eca3f43819fd48</guid>
      <description><![CDATA[In a recent post , I talked about my experience enabling continuous integration for the internal builds here at Pluralsight. I recently worked with Craig to restructure our nant build. As part of...]]></description>
      <content:encoded><![CDATA[<p>In a <a href="http://www.pluralsight.com/blogs/keith/archive/2008/01/18/49967.aspx" target="_blank">recent post</a>, I talked about my experience enabling continuous integration for the internal builds here at Pluralsight. I recently worked with Craig to restructure our nant build. As part of that, I wanted to ensure that I could run the build from anywhere in the source tree. We use a typical hierarchical build where each project has a build script that knows how to compile, test, deploy, etc. based on the specified target. Then at the top of the tree, there's a build script that runs all the other ones. That root build script is what gets run automatically by <a href="http://ccnet.thoughtworks.com/" target="_blank">Cruise Control</a>.</p>
<p>My root script defines a bunch of properties, like where the output directories for the overall build live, where the tools live, and so on. And that works fine when I run the build from the root. The properties get defined, all the child scripts are run with &lt;nant/&gt; tasks, and they see those properties. But if I want to drill down into the tree and run one of the build scripts lower down, suddenly there's problems because it depends on properties that are only defined in the root script. I really like being able to run builds from anywhere in the tree for perf - if I'm trying to fix a particular project, I don't necessarily want to wait for unit tests on the entire tree to run in order to see if mine passed.</p>
<p>Craig made a great suggestion. Put the properties into a separate script (we named it properties.nant) and &lt;include/&gt; that script. Then to enable hierarchical builds, we'd create a properties.nant file for each folder in the tree, which would &lt;include/&gt; its parent. That way I could define properties anywhere in the tree, and they would be "inherited" by anything below it.</p>
<p>I took that idea one step further, because I didn't want to maintain a bunch of property scripts with nothing in them but an &lt;include/&gt; for the parent. I wrote an &lt;includefromparent/&gt; nant task that walks up the directory tree looking for the target file. So now I can do this:</p>
<p><tt>&lt;includefromparent buildfile="properties.nant"/&gt;</tt></p>
<p>This worked great! But now I ran into a problem. Many of my properties are defined like so in the root properties.nant file:</p>
<p><tt>&lt;property name="libraryOutputDir" value="${project::get-base-directory()}\artifacts\libraries"/&gt;</tt></p>
<p>Do you see the issue? If I run the build with the root script, everything works fine, because it's the root nant project I'm building, and get-base-directory() refers to the root of the project, where the artifacts folder lives. But if I run from lower in the tree, it's a different project, and get-base-directory() refers to a subfolder, where the artifacts folder definitely should NOT be.</p>
<p>I needed a way to find the root of the project tree. So I build a second really simple nant task:</p>
<p><tt>&lt;findmarkeddir markerfile="filetolookfor.txt" property="root"/&gt;</tt></p>
<p>This task simply looks up the directory hierarchy until it finds the specified marker file, then puts the name of that directory (the "marked" directory) into a designated property (here I've called it root). With that in place, I rewrote my property definitions in terms of the base directory:</p>
<p><tt>&lt;property name="libraryOutputDir" value="${root}\artifacts\libraries"/&gt;</tt></p>
<p>Voilà! I can now run builds from any of my build scripts. They inherit properties hierarchically like you'd expect, and the system is quite easy to maintain. If you'd like to use these tasks, I've included the code for them below (not much code, really). And if you've never written a nant task yourself before, here's <a href="http://blogs.geekdojo.net/rcase/archive/2005/01/06/5971.aspx" target="_blank">the article</a> I used to figure out how it's done (it's super easy). <a href="http://nant.sourceforge.net/release/latest/help/fundamentals/tasks.html#taskloader" target="_blank">Here's</a> what you should read to learn about the various options for deploying your custom task assembly so nant recognizes it.</p>
<p>Enjoy!</p>
<p>Here is <b>FindMarkedDirTask.cs</b></p><pre>using System;
using System.Collections.Generic;
using System.Text;
using NAnt.Core;
using NAnt.Core.Attributes;
using System.IO;

namespace PluralsightNantTasks {

[TaskName("findmarkeddir")]
public class FindMarkedDirTask : Task {

  [TaskAttribute("markerfile", Required = true)]
  [StringValidator(AllowEmpty = false)]
  public string MarkerFileName { get; set; }

  [TaskAttribute("property", Required = true)]
  [StringValidator(AllowEmpty = false)]
  public string PropertyName { get; set; }

  protected override void ExecuteTask() {
    string searchDir = this.Project.BaseDirectory;
    do {
      if (MarkerFileExistsIn(searchDir)) {
        this.Project.Properties[PropertyName] = searchDir;
        return;
      }
      searchDir = ParentOf(searchDir);
    } while (!IsRootDirectory(searchDir));
  }

  private bool IsRootDirectory(string path) {
    return Path.GetPathRoot(path) == Path.GetFullPath(path);
  }

  private string ParentOf(string directory) {
    return Path.GetFullPath(Path.Combine(directory, ".."));
  }

  private bool MarkerFileExistsIn(string directory) {
    return File.Exists(Path.Combine(directory, MarkerFileName));
  }
}
}
</pre>
<p>And here is <b>IncludeFromParentTask.cs</b> (note I derive from the built-in include task):</p><pre>using System;
using System.Collections.Generic;
using System.Text;
using NAnt.Core;
using NAnt.Core.Attributes;
using NAnt.Core.Tasks;
using System.IO;
using System.Globalization;

namespace PluralsightNantTasks {

[TaskName("includefromparent")]
public class IncludeFromParentTask : IncludeTask {

  protected override void Initialize() {
    string fileName = BuildFileName;
    if (fileName.Contains("/") || fileName.Contains(@"\\"))
      throw new BuildException(string.Format(
        CultureInfo.CurrentCulture,
        "buildfile attribute must only be a filename"));

    string relativePathToFoundFile = SearchParentDirectory(
      Project.BaseDirectory, fileName, 0);
      
    if (null == relativePathToFoundFile)
      throw new BuildException(string.Format(
        CultureInfo.CurrentCulture,
        "Couldn't find a file named {0}" +
        " in a parent directory of {1}",
        fileName, Project.BaseDirectory));

    // have to use a relative path here
    // because <include /> task uses
    // Path.Combine(projectDir, BuildFileName)
    // to get the full path
    BuildFileName = relativePathToFoundFile;

    base.Initialize();
  }

  private string SearchParentDirectory(string directory,
                        string fileName, int searchDepth) {
    ++searchDepth;
  
    // see if we've traversed all the way to the root
    string currentPath = Path.GetFullPath(directory);
    if (currentPath == Path.GetPathRoot(currentPath))
      return null;

    // recurse until we find the file
    string parentDir = Path.GetFullPath(
      Path.Combine(currentPath, ".."));
    string path = Path.Combine(parentDir, fileName);
    if (File.Exists(path)) {
      StringBuilder sb = new StringBuilder();
      for (int i = 0; i &lt; searchDepth; ++i)
        sb.Append(@"..\");
      return Path.Combine(sb.ToString(), fileName);
    }
    else return SearchParentDirectory(parentDir,
                          fileName, searchDepth);
  }
}
}
</pre><div style="clear:both;"></div><img src="http://pluralsight.com/community/aggbug.aspx?PostID=50388" width="1" height="1">]]></content:encoded>
      <pubDate>Fri, 07 Mar 2008 09:49:00 +0000</pubDate>
      <category domain="http://securityratty.com/tag/nant">nant</category>
      <category domain="http://securityratty.com/tag/root script defines">root script defines</category>
      <category domain="http://securityratty.com/tag/script">script</category>
      <category domain="http://securityratty.com/tag/root">root</category>
      <category domain="http://securityratty.com/tag/task">task</category>
      <category domain="http://securityratty.com/tag/simple nant task">simple nant task</category>
      <category domain="http://securityratty.com/tag/root nant project">root nant project</category>
      <category domain="http://securityratty.com/tag/return path">return path</category>
      <category domain="http://securityratty.com/tag/return">return</category>
      <source url="http://pluralsight.com/community/blogs/keith/archive/2008/03/07/50388.aspx">Enabling hierarchical nant builds</source>
    </item>
    <item>
      <title><![CDATA[Enabling hierarchical nant builds]]></title>
      <link>http://securityratty.com/article/83d94a82ba041a457afd0b8abf809cf5</link>
      <guid>http://securityratty.com/article/83d94a82ba041a457afd0b8abf809cf5</guid>
      <description><![CDATA[In a recent post , I talked about my experience enabling continuous integration for the internal builds here at Pluralsight. I recently worked with Craig to restructure our nant build. As part of...]]></description>
      <content:encoded><![CDATA[<p>In a <a href="http://www.pluralsight.com/blogs/keith/archive/2008/01/18/49967.aspx" target="_blank">recent post</a>, I talked about my experience enabling continuous integration for the internal builds here at Pluralsight. I recently worked with Craig to restructure our nant build. As part of that, I wanted to ensure that I could run the build from anywhere in the source tree. We use a typical hierarchical build where each project has a build script that knows how to compile, test, deploy, etc. based on the specified target. Then at the top of the tree, there's a build script that runs all the other ones. That root build script is what gets run automatically by <a href="http://ccnet.thoughtworks.com/" target="_blank">Cruise Control</a>.</p>
<p>My root script defines a bunch of properties, like where the output directories for the overall build live, where the tools live, and so on. And that works fine when I run the build from the root. The properties get defined, all the child scripts are run with &lt;nant/&gt; tasks, and they see those properties. But if I want to drill down into the tree and run one of the build scripts lower down, suddenly there's problems because it depends on properties that are only defined in the root script. I really like being able to run builds from anywhere in the tree for perf - if I'm trying to fix a particular project, I don't necessarily want to wait for unit tests on the entire tree to run in order to see if mine passed.</p>
<p>Craig made a great suggestion. Put the properties into a separate script (we named it properties.nant) and &lt;include/&gt; that script. Then to enable hierarchical builds, we'd create a properties.nant file for each folder in the tree, which would &lt;include/&gt; its parent. That way I could define properties anywhere in the tree, and they would be "inherited" by anything below it.</p>
<p>I took that idea one step further, because I didn't want to maintain a bunch of property scripts with nothing in them but an &lt;include/&gt; for the parent. I wrote an &lt;includefromparent/&gt; nant task that walks up the directory tree looking for the target file. So now I can do this:</p>
<p><tt>&lt;includefromparent buildfile="properties.nant"/&gt;</tt></p>
<p>This worked great! But now I ran into a problem. Many of my properties are defined like so in the root properties.nant file:</p>
<p><tt>&lt;property name="libraryOutputDir" value="${project::get-base-directory()}\artifacts\libraries"/&gt;</tt></p>
<p>Do you see the issue? If I run the build with the root script, everything works fine, because it's the root nant project I'm building, and get-base-directory() refers to the root of the project, where the artifacts folder lives. But if I run from lower in the tree, it's a different project, and get-base-directory() refers to a subfolder, where the artifacts folder definitely should NOT be.</p>
<p>I needed a way to find the root of the project tree. So I build a second really simple nant task:</p>
<p><tt>&lt;findmarkeddir markerfile="filetolookfor.txt" property="root"/&gt;</tt></p>
<p>This task simply looks up the directory hierarchy until it finds the specified marker file, then puts the name of that directory (the "marked" directory) into a designated property (here I've called it root). With that in place, I rewrote my property definitions in terms of the base directory:</p>
<p><tt>&lt;property name="libraryOutputDir" value="${root}\artifacts\libraries"/&gt;</tt></p>
<p>Voilà! I can now run builds from any of my build scripts. They inherit properties hierarchically like you'd expect, and the system is quite easy to maintain. If you'd like to use these tasks, I've included the code for them below (not much code, really). And if you've never written a nant task yourself before, here's <a href="http://blogs.geekdojo.net/rcase/archive/2005/01/06/5971.aspx" target="_blank">the article</a> I used to figure out how it's done (it's super easy). <a href="http://nant.sourceforge.net/release/latest/help/fundamentals/tasks.html#taskloader" target="_blank">Here's</a> what you should read to learn about the various options for deploying your custom task assembly so nant recognizes it.</p>
<p>Enjoy!</p>
<p>Here is <b>FindMarkedDirTask.cs</b></p><pre>using System;
using System.Collections.Generic;
using System.Text;
using NAnt.Core;
using NAnt.Core.Attributes;
using System.IO;

namespace PluralsightNantTasks {

[TaskName("findmarkeddir")]
public class FindMarkedDirTask : Task {

  [TaskAttribute("markerfile", Required = true)]
  [StringValidator(AllowEmpty = false)]
  public string MarkerFileName { get; set; }

  [TaskAttribute("property", Required = true)]
  [StringValidator(AllowEmpty = false)]
  public string PropertyName { get; set; }

  protected override void ExecuteTask() {
    string searchDir = this.Project.BaseDirectory;
    do {
      if (MarkerFileExistsIn(searchDir)) {
        this.Project.Properties[PropertyName] = searchDir;
        return;
      }
      searchDir = ParentOf(searchDir);
    } while (!IsRootDirectory(searchDir));
  }

  private bool IsRootDirectory(string path) {
    return Path.GetPathRoot(path) == Path.GetFullPath(path);
  }

  private string ParentOf(string directory) {
    return Path.GetFullPath(Path.Combine(directory, ".."));
  }

  private bool MarkerFileExistsIn(string directory) {
    return File.Exists(Path.Combine(directory, MarkerFileName));
  }
}
}
</pre>
<p>And here is <b>IncludeFromParentTask.cs</b> (note I derive from the built-in include task):</p><pre>using System;
using System.Collections.Generic;
using System.Text;
using NAnt.Core;
using NAnt.Core.Attributes;
using NAnt.Core.Tasks;
using System.IO;
using System.Globalization;

namespace PluralsightNantTasks {

[TaskName("includefromparent")]
public class IncludeFromParentTask : IncludeTask {

  protected override void Initialize() {
    string fileName = BuildFileName;
    if (fileName.Contains("/") || fileName.Contains(@"\\"))
      throw new BuildException(string.Format(
        CultureInfo.CurrentCulture,
        "buildfile attribute must only be a filename"));

    string relativePathToFoundFile = SearchParentDirectory(
      Project.BaseDirectory, fileName, 0);
      
    if (null == relativePathToFoundFile)
      throw new BuildException(string.Format(
        CultureInfo.CurrentCulture,
        "Couldn't find a file named {0}" +
        " in a parent directory of {1}",
        fileName, Project.BaseDirectory));

    // have to use a relative path here
    // because <include /> task uses
    // Path.Combine(projectDir, BuildFileName)
    // to get the full path
    BuildFileName = relativePathToFoundFile;

    base.Initialize();
  }

  private string SearchParentDirectory(string directory,
                        string fileName, int searchDepth) {
    ++searchDepth;
  
    // see if we've traversed all the way to the root
    string currentPath = Path.GetFullPath(directory);
    if (currentPath == Path.GetPathRoot(currentPath))
      return null;

    // recurse until we find the file
    string parentDir = Path.GetFullPath(
      Path.Combine(currentPath, ".."));
    string path = Path.Combine(parentDir, fileName);
    if (File.Exists(path)) {
      StringBuilder sb = new StringBuilder();
      for (int i = 0; i &lt; searchDepth; ++i)
        sb.Append(@"..\");
      return Path.Combine(sb.ToString(), fileName);
    }
    else return SearchParentDirectory(parentDir,
                          fileName, searchDepth);
  }
}
}
</pre><div style="clear:both;"></div><img src="http://www.pluralsight.com/community/aggbug.aspx?PostID=50388" width="1" height="1">]]></content:encoded>
      <pubDate>Fri, 07 Mar 2008 09:49:00 +0000</pubDate>
      <category domain="http://securityratty.com/tag/nant">nant</category>
      <category domain="http://securityratty.com/tag/root script defines">root script defines</category>
      <category domain="http://securityratty.com/tag/script">script</category>
      <category domain="http://securityratty.com/tag/root">root</category>
      <category domain="http://securityratty.com/tag/task">task</category>
      <category domain="http://securityratty.com/tag/simple nant task">simple nant task</category>
      <category domain="http://securityratty.com/tag/root nant project">root nant project</category>
      <category domain="http://securityratty.com/tag/return path">return path</category>
      <category domain="http://securityratty.com/tag/return">return</category>
      <source url="http://www.pluralsight.com/community/blogs/keith/archive/2008/03/07/50388.aspx">Enabling hierarchical nant builds</source>
    </item>
    <item>
      <title><![CDATA[Enabling hierarchical nant builds]]></title>
      <link>http://securityratty.com/article/960ca4f58e5dc775718cb2749c340681</link>
      <guid>http://securityratty.com/article/960ca4f58e5dc775718cb2749c340681</guid>
      <description><![CDATA[In a recent post , I talked about my experience enabling continuous integration for the internal builds here at Pluralsight. I recently worked with Craig to restructure our nant build. As part of...]]></description>
      <content:encoded><![CDATA[<p>In a <a href="http://www.pluralsight.com/blogs/keith/archive/2008/01/18/49967.aspx" target="_blank">recent post</a>, I talked about my experience enabling continuous integration for the internal builds here at Pluralsight. I recently worked with Craig to restructure our nant build. As part of that, I wanted to ensure that I could run the build from anywhere in the source tree. We use a typical hierarchical build where each project has a build script that knows how to compile, test, deploy, etc. based on the specified target. Then at the top of the tree, there's a build script that runs all the other ones. That root build script is what gets run automatically by <a href="http://ccnet.thoughtworks.com/" target="_blank">Cruise Control</a>.</p>
<p>My root script defines a bunch of properties, like where the output directories for the overall build live, where the tools live, and so on. And that works fine when I run the build from the root. The properties get defined, all the child scripts are run with &lt;nant/&gt; tasks, and they see those properties. But if I want to drill down into the tree and run one of the build scripts lower down, suddenly there's problems because it depends on properties that are only defined in the root script. I really like being able to run builds from anywhere in the tree for perf - if I'm trying to fix a particular project, I don't necessarily want to wait for unit tests on the entire tree to run in order to see if mine passed.</p>
<p>Craig made a great suggestion. Put the properties into a separate script (we named it properties.nant) and &lt;include/&gt; that script. Then to enable hierarchical builds, we'd create a properties.nant file for each folder in the tree, which would &lt;include/&gt; its parent. That way I could define properties anywhere in the tree, and they would be "inherited" by anything below it.</p>
<p>I took that idea one step further, because I didn't want to maintain a bunch of property scripts with nothing in them but an &lt;include/&gt; for the parent. I wrote an &lt;includefromparent/&gt; nant task that walks up the directory tree looking for the target file. So now I can do this:</p>
<p><tt>&lt;includefromparent buildfile="properties.nant"/&gt;</tt></p>
<p>This worked great! But now I ran into a problem. Many of my properties are defined like so in the root properties.nant file:</p>
<p><tt>&lt;property name="libraryOutputDir" value="${project::get-base-directory()}\artifacts\libraries"/&gt;</tt></p>
<p>Do you see the issue? If I run the build with the root script, everything works fine, because it's the root nant project I'm building, and get-base-directory() refers to the root of the project, where the artifacts folder lives. But if I run from lower in the tree, it's a different project, and get-base-directory() refers to a subfolder, where the artifacts folder definitely should NOT be.</p>
<p>I needed a way to find the root of the project tree. So I build a second really simple nant task:</p>
<p><tt>&lt;findmarkeddir markerfile="filetolookfor.txt" property="root"/&gt;</tt></p>
<p>This task simply looks up the directory hierarchy until it finds the specified marker file, then puts the name of that directory (the "marked" directory) into a designated property (here I've called it root). With that in place, I rewrote my property definitions in terms of the base directory:</p>
<p><tt>&lt;property name="libraryOutputDir" value="${root}\artifacts\libraries"/&gt;</tt></p>
<p>Voilà! I can now run builds from any of my build scripts. They inherit properties hierarchically like you'd expect, and the system is quite easy to maintain. If you'd like to use these tasks, I've included the code for them below (not much code, really). And if you've never written a nant task yourself before, here's <a href="http://blogs.geekdojo.net/rcase/archive/2005/01/06/5971.aspx" target="_blank">the article</a> I used to figure out how it's done (it's super easy). <a href="http://nant.sourceforge.net/release/latest/help/fundamentals/tasks.html#taskloader" target="_blank">Here's</a> what you should read to learn about the various options for deploying your custom task assembly so nant recognizes it.</p>
<p>Enjoy!</p>
<p>Here is <b>FindMarkedDirTask.cs</b></p><pre>using System;
using System.Collections.Generic;
using System.Text;
using NAnt.Core;
using NAnt.Core.Attributes;
using System.IO;

namespace PluralsightNantTasks {

[TaskName("findmarkeddir")]
public class FindMarkedDirTask : Task {

  [TaskAttribute("markerfile", Required = true)]
  [StringValidator(AllowEmpty = false)]
  public string MarkerFileName { get; set; }

  [TaskAttribute("property", Required = true)]
  [StringValidator(AllowEmpty = false)]
  public string PropertyName { get; set; }

  protected override void ExecuteTask() {
    string searchDir = this.Project.BaseDirectory;
    do {
      if (MarkerFileExistsIn(searchDir)) {
        this.Project.Properties[PropertyName] = searchDir;
        return;
      }
      searchDir = ParentOf(searchDir);
    } while (!IsRootDirectory(searchDir));
  }

  private bool IsRootDirectory(string path) {
    return Path.GetPathRoot(path) == Path.GetFullPath(path);
  }

  private string ParentOf(string directory) {
    return Path.GetFullPath(Path.Combine(directory, ".."));
  }

  private bool MarkerFileExistsIn(string directory) {
    return File.Exists(Path.Combine(directory, MarkerFileName));
  }
}
}
</pre>
<p>And here is <b>IncludeFromParentTask.cs</b> (note I derive from the built-in include task):</p><pre>using System;
using System.Collections.Generic;
using System.Text;
using NAnt.Core;
using NAnt.Core.Attributes;
using NAnt.Core.Tasks;
using System.IO;
using System.Globalization;

namespace PluralsightNantTasks {

[TaskName("includefromparent")]
public class IncludeFromParentTask : IncludeTask {

  protected override void Initialize() {
    string fileName = BuildFileName;
    if (fileName.Contains("/") || fileName.Contains(@"\\"))
      throw new BuildException(string.Format(
        CultureInfo.CurrentCulture,
        "buildfile attribute must only be a filename"));

    string relativePathToFoundFile = SearchParentDirectory(
      Project.BaseDirectory, fileName, 0);
      
    if (null == relativePathToFoundFile)
      throw new BuildException(string.Format(
        CultureInfo.CurrentCulture,
        "Couldn't find a file named {0}" +
        " in a parent directory of {1}",
        fileName, Project.BaseDirectory));

    // have to use a relative path here
    // because <include /> task uses
    // Path.Combine(projectDir, BuildFileName)
    // to get the full path
    BuildFileName = relativePathToFoundFile;

    base.Initialize();
  }

  private string SearchParentDirectory(string directory,
                        string fileName, int searchDepth) {
    ++searchDepth;
  
    // see if we've traversed all the way to the root
    string currentPath = Path.GetFullPath(directory);
    if (currentPath == Path.GetPathRoot(currentPath))
      return null;

    // recurse until we find the file
    string parentDir = Path.GetFullPath(
      Path.Combine(currentPath, ".."));
    string path = Path.Combine(parentDir, fileName);
    if (File.Exists(path)) {
      StringBuilder sb = new StringBuilder();
      for (int i = 0; i &lt; searchDepth; ++i)
        sb.Append(@"..\");
      return Path.Combine(sb.ToString(), fileName);
    }
    else return SearchParentDirectory(parentDir,
                          fileName, searchDepth);
  }
}
}
</pre><img src ="http://pluralsight.com/blogs/keith/aggbug/50388.aspx" width = "1" height = "1" />]]></content:encoded>
      <pubDate>Fri, 07 Mar 2008 02:49:00 +0000</pubDate>
      <category domain="http://securityratty.com/tag/nant">nant</category>
      <category domain="http://securityratty.com/tag/root script defines">root script defines</category>
      <category domain="http://securityratty.com/tag/script">script</category>
      <category domain="http://securityratty.com/tag/root">root</category>
      <category domain="http://securityratty.com/tag/task">task</category>
      <category domain="http://securityratty.com/tag/simple nant task">simple nant task</category>
      <category domain="http://securityratty.com/tag/root nant project">root nant project</category>
      <category domain="http://securityratty.com/tag/return path">return path</category>
      <category domain="http://securityratty.com/tag/return">return</category>
      <source url="http://pluralsight.com/blogs/keith/archive/2008/03/07/50388.aspx">Enabling hierarchical nant builds</source>
    </item>
    <item>
      <title><![CDATA[Risk of Knowing Too Much About Risk]]></title>
      <link>http://securityratty.com/article/a9e709ef7a9e4009c206f5962e3219c7</link>
      <guid>http://securityratty.com/article/a9e709ef7a9e4009c206f5962e3219c7</guid>
      <description><![CDATA[Interesting : Dread is a powerful force. The problem with dread is that it leads to terrible decision-making
Slovic says all of this results from how our brains process risk, which is in two ways. The...]]></description>
      <content:encoded><![CDATA[<p><a href="http://www2.csoonline.com/exclusives/column.html?CID=33571">Interesting</a>:</p>

<blockquote>Dread is a powerful force. The problem with dread is that it leads to terrible decision-making.

<p>Slovic says all of this results from how our brains process risk, which is in two ways. The first is intuitive, emotional and experience based. Not only do we fear more what we can't control, but we also fear more what we can imagine or what we experience. This seems to be an evolutionary survival mechanism. In the presence of uncertainty, fear is a valuable defense. Our brains react emotionally, generate anxiety and tell us, "Remember the news report that showed what happened when those other kids took the bus? Don't put your kids on the bus."</p>

<p>The second way we process risk is analytical: we use probability and statistics to override, or at least prioritize, our dread. That is, our brain plays devil's advocate with its initial intuitive reaction, and tries to say, "I know it seems scary, but eight times as many people die in cars as they do on buses. In fact, only one person dies on a bus for every 500 million miles buses travel. Buses are safer than cars."</p>

<p>Unfortunately for us, that's often not the voice that wins. Intuitive risk processors can easily overwhelm analytical ones, especially in the presence of those etched-in images, sounds and experiences. Intuition is so strong, in fact, that if you presented someone who had experienced a bus accident with factual risk analysis about the relative safety of buses over cars, it's highly possible that they'd still choose to drive their kids to school, because their brain washes them in those dreadful images and reminds them that they control a car but don't control a bus. A car just feels safer. "We have to work real hard in the presence of images to get the analytical part of risk response to work in our brains," says Slovic. "It's not easy at all."</p>

<p>And we're making it harder by disclosing more risks than ever to more people than ever. Not only does all of this disclosure make us feel helpless, but it also gives us ever more of those images and experiences that trigger the intuitive response without analytical rigor to override the fear. Slovic points to several recent cases where reason has lost to fear: The sniper who terrorized Washington D.C.; pathogenic threats like MRSA and brain-eating amoeba. Even the widely publicized drunk-driving death of a baseball player this year led to decisions that, from a risk perspective, were irrational.</blockquote></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~f/schneier/fulltext?a=2CLusHF"><img src="http://feeds.feedburner.com/~f/schneier/fulltext?i=2CLusHF" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/schneier/fulltext?a=tnoEwuF"><img src="http://feeds.feedburner.com/~f/schneier/fulltext?i=tnoEwuF" border="0"></img></a>
</div>]]></content:encoded>
      <pubDate>Thu, 06 Mar 2008 03:24:50 +0000</pubDate>
      <category domain="http://securityratty.com/tag/intuitive">intuitive</category>
      <category domain="http://securityratty.com/tag/intuitive risk processors">intuitive risk processors</category>
      <category domain="http://securityratty.com/tag/analytical">analytical</category>
      <category domain="http://securityratty.com/tag/analytical rigor">analytical rigor</category>
      <category domain="http://securityratty.com/tag/intuitive response">intuitive response</category>
      <category domain="http://securityratty.com/tag/brains process risk">brains process risk</category>
      <category domain="http://securityratty.com/tag/brains react">brains react</category>
      <category domain="http://securityratty.com/tag/images">images</category>
      <category domain="http://securityratty.com/tag/dreadful images">dreadful images</category>
      <source url="http://www.schneier.com/blog/archives/2008/03/risk_of_knowing.html">Risk of Knowing Too Much About Risk</source>
    </item>
    <item>
      <title><![CDATA[Your Brain on Fear]]></title>
      <link>http://securityratty.com/article/2926978283c67fd3fd6ec80b6ca795ea</link>
      <guid>http://securityratty.com/article/2926978283c67fd3fd6ec80b6ca795ea</guid>
      <description><![CDATA[Interesting article from Newsweek : The evolutionary primacy of the brain's fear circuitry makes it more powerful than the brain's reasoning faculties. The amygdala sprouts a profusion of connections...]]></description>
      <content:encoded><![CDATA[<p>Interesting <a href="http://www.newsweek.com/id/78178">article</a> from <i>Newsweek</i>:</p>

<blockquote>The evolutionary primacy of the brain's fear circuitry makes it more powerful than the brain's reasoning faculties. The amygdala sprouts a profusion of connections to higher brain regions -- neurons that carry one-way traffic from amygdala to neocortex. Few connections run from the cortex to the amygdala, however. That allows the amygdala to override the products of the logical, thoughtful cortex, but not vice versa. So although it is sometimes possible to think yourself out of fear ("I <i>know</i> that dark shape in the alley is just a trash can"), it takes great effort and persistence. Instead, fear tends to overrule reason, as the amygdala hobbles our logic and reasoning circuits. That makes fear "far, far more powerful than reason," says neurobiologist Michael Fanselow of the University of California, Los Angeles. "It evolved as a mechanism to protect us from life-threatening situations, and from an evolutionary standpoint there's nothing more important than that."</blockquote>

<p>I've <a href="http://www.schneier.com/essay-155.html">already written</a> about this sort of thing.</p><div class="feedflare">
<a href="http://feeds.feedburner.com/~f/schneier/fulltext?a=qeSFcnD"><img src="http://feeds.feedburner.com/~f/schneier/fulltext?i=qeSFcnD" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/schneier/fulltext?a=BQDGAXD"><img src="http://feeds.feedburner.com/~f/schneier/fulltext?i=BQDGAXD" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/schneier/fulltext?a=hZC1BzD"><img src="http://feeds.feedburner.com/~f/schneier/fulltext?i=hZC1BzD" border="0"></img></a>
</div>]]></content:encoded>
      <pubDate>Wed, 09 Jan 2008 03:10:54 +0000</pubDate>
      <category domain="http://securityratty.com/tag/fear">fear</category>
      <category domain="http://securityratty.com/tag/brain">brain</category>
      <category domain="http://securityratty.com/tag/amygdala">amygdala</category>
      <category domain="http://securityratty.com/tag/amygdala hobbles">amygdala hobbles</category>
      <category domain="http://securityratty.com/tag/fear circuitry">fear circuitry</category>
      <category domain="http://securityratty.com/tag/amygdala sprouts">amygdala sprouts</category>
      <category domain="http://securityratty.com/tag/brain regions">brain regions</category>
      <category domain="http://securityratty.com/tag/overrule reason">overrule reason</category>
      <category domain="http://securityratty.com/tag/cortex">cortex</category>
      <source url="http://www.schneier.com/blog/archives/2008/01/your_brain_on_f.html">Your Brain on Fear</source>
    </item>
  </channel>
</rss>
