Azure IaaS is awesome but…

AzureUnlocked

Azure IaaS (Infrastructure as a Service) is so unbelievably cool. You can make new VMs and delete them… wait. You can delete them, right? Well yes and no. You can delete the VM but for some unknown reason the disk image storage blob stays locked for … I don’t know. Forever? It’s very frustrating to me. In fact, it’s the only frustration thing I have found about Azure (aside from only being allowed to have one NIC per VM). So I did what I always do, wrote a tool. And that was great, but it didn’t benefit you, the reader. So now you can benefit! Here’s the code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;
 
namespace ConsoleApplication1
{
    public static class AzureStorage
    {
        public static void BreakContainerLease(string AccountName, string AccountKey, string Container)
        {
            var account = new CloudStorageAccount(new StorageCredentialsAccountAndKey(AccountName, AccountKey), true);
            var client = new CloudBlobClient(account.BlobEndpoint, account.Credentials);
            var container = client.GetContainerReference(Container);
            container.BreakLease(new TimeSpan(0, 0, 1));
        }
 
        public static void BreakBlobLease(string AccountName, string AccountKey, string Container, string BlobName)
        {
            var account = new CloudStorageAccount(new StorageCredentialsAccountAndKey(AccountName, AccountKey), true);
            var client = new CloudBlobClient(account.BlobEndpoint, account.Credentials);
            var container = client.GetContainerReference(Container);
            var blob = container.GetBlobReference(BlobName);
            blob.BreakLease(new TimeSpan(0, 0, 1));
        }
    }
}

And as always, here’s the link to the running SSL encrypted version on my site: Azure Blob Unlocker!!!!

Reflexil Is Awesome, But…

reflexil_all_the_things

Reflexil together with .NET Reflector is pretty much the most awesome thing ever for getting someone else’s closed source thing to work properly. It’s simple: open the assembly in Reflector, edit the badness using Reflexil and save as a new assembly. Include said new assembly in your project and win!

But…

Sometimes thar be dragons… like when the author signed it. Which is why Reflexil has the very cool ability to strip out the assembly signing (strong name) and make it a normal assembly.

This part gave me some issues…

Sometimes when referencing the “fixed” assembly you will get this:

ReferenceError

 

Basically there was some weird problem, so the easy way around it is to launch your friendly neighborhood Visual Studio Command Prompt and issue some pretty simple commands:

ildasm Patched.dll /output:Patched_And_Fixed.il
ilasm /DLL Patched_And_Fixed.il

Now you’ll have Patched_And_Fixed.dll which will work!

Thanks goes out to the guys behind all these great tools to make our lives easier!

Impersonate a Windows Identity Easily!

Not Me

Why would you want to do Windows Identity impersonation?

Because it’s cool. Really. You can run a program as someone other than who you are. This is especially useful for services, websites, and pretty much anything where you want to run an application in a mode that has different privileges. Do you want more permissions than normal? Use an application in a domain? Lock it down? The sky is the limit!

How is it done?

That part is pretty simple. In fact it’s outlined on this MSDN page. I’ve also got it wrapped up in a much easier to use class here:

using System;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Security.Principal;
using Microsoft.Win32.SafeHandles;
 
namespace ConsoleApplication1
{
    /// Impersonates a windows identity.
    /// Based on: http://msdn.microsoft.com/en-us/library/w070t6ka.aspx
    public class WindowsIdentityImpersonator : IDisposable
    {
        WindowsIdentity _newId;
        SafeTokenHandle _safeTokenHandle;
        WindowsImpersonationContext _impersonatedUser;
 
        public WindowsIdentity Identity { get { return _newId; } }
 
        [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
        public WindowsIdentityImpersonator(string Domain, string Username, string Password)
        {
            bool returnValue = LogonUser(Username, Domain, Password, 2, 0, out _safeTokenHandle);
 
            if (returnValue == false)
            {
                throw new UnauthorizedAccessException("Could not login as " + Domain + "\\" + Username + ".",
                    new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()));
            }
        }
 
        public void BeginImpersonate()
        {
            _newId = new WindowsIdentity(_safeTokenHandle.DangerousGetHandle());
            _impersonatedUser = _newId.Impersonate();
        }
 
        public void EndImpersonate()
        {
            if (_newId != null)
            {
                _newId.Dispose();
            }
 
            if (_impersonatedUser != null)
            {
                _impersonatedUser.Dispose();
            }
        }
 
        public void Dispose()
        {
            this.EndImpersonate();
 
            if (_safeTokenHandle != null)
            {
                _safeTokenHandle.Dispose();
            }
        }
 
        [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
            int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);
 
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public extern static bool CloseHandle(IntPtr handle);
    }
 
    public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
    {
        private SafeTokenHandle() : base(true)
        {
        }
 
        [DllImport("kernel32.dll")]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        [SuppressUnmanagedCodeSecurity]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool CloseHandle(IntPtr handle);
 
        protected override bool ReleaseHandle()
        {
            return CloseHandle(handle);
        }
    }
}

Using this class is simple:

using (var wim = new WindowsIdentityImpersonator("domain", "username", "password"))
{
    wim.BeginImpersonate();
    {
        Console.WriteLine("Thread B: {0}", WindowsIdentity.GetCurrent().Name);
    }
    wim.EndImpersonate();
}

For domain if you want to use your local machine just put in “.”

Ok, that’s cool but what else have you got?

You want more? Okay wise guy, throw this bad boy in a separate thread (even a ThreadPool will work) and you can run that thread under this identity. Want another one? Start another thread. It’s that easy! One application can perform actions under a hundred different identities!

Happy coding!

Cache Control for Fun and Profit

cache_control

So you have a website and it’s really important. Maybe people are using it publicly and entering credit cards or something. What’s the worst thing that can happen? Well I’ll tell you, the next guy could come up and hit the back button and see everyone’s credit card numbers. Think it’s not plausible? I once went to the DMV near me and found a kiosk to renew my driver’s license. It was just a computer hooked up to the internet in a very poor kiosk mode. So the first thing I did was hit the unmarked backspace key and saw the last guy’s credit card number. Why did that happen? Improper cache-control!!! Sorry, that just came out.

I digress.

So you how you do it in .NET? I mean, we want to cache some things, but not others. Well it’s pretty easy, but in practice there are a few tricks. First, we want to cache static content (pictures, JavaScript files, etc) but we DO NOT want to cache our pages. So let’s setup static content caching in our web.config at the configuration level:

<staticContent>
  <clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="7.00:00:00" />
</staticContent>

That was easy enough, and it works! But we still have some other content (the content we want secured) marked as “private” in the caching, that’s bad. So we’ll fix that by using the powers of Global.asax.cs!

protected void Application_EndRequest(Object sender, EventArgs e)
{
  if ((Response.Headers["Cache-Control"] ?? "") == "private")
  {
    // Stop Caching in IE
    Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);
    // Stop Caching in Firefox
    Response.Cache.SetNoStore();
  }
}

So we are now checking for things that are marked “private” cache and making them expire immediately. But why am I not using Response.CacheControl? It turns out that Response.CacheControl is not as responsive as I would like:

Not the same

As you can see, Response.CacheControl thinks the static content is “private” where in reality it is “max-age”. Boo. But by directly checking the Response.Headers we will find the correct value and can check for it. This results in epic win!

PropaCaching

 

Enjoy!

What?!? Too many certificates?

AngryCerts

Update: There’s a Microsoft KB Article on this subject: TLS client authentication fails between Unified Communications peers with a logged Schannel warning

So when running an SSL WCF (Windows Communication Foundation) web service you may run into this error when connection with your client:

The HTTP request was forbidden with client authentication scheme 'Anonymous'.

But you’ve checked everything and the certificates are correct, everything looks good it even works when you publish the code on other machines. So what’s wrong? Well have you checked your event log? You might have too many trusted root certificates!

So filter your System logs to only include Schannel entries:

SChannel Filter

 

And look for entries that mention this:

When asking for client authentication, this server sends a list of trusted certificate authorities to the client. The client uses this list to choose a client certificate that is trusted by the server. Currently, this server trusts so many certificate authorities that the list has grown too long. This list has thus been truncated. The administrator of this machine should review the certificate authorities trusted for client authentication and remove those that do not really need to be trusted.

TooManyCerts

 

Notice this part:

This list has thus been truncated. The administrator of this machine should review the certificate authorities trusted for client authentication and remove those that do not really need to be trusted.

That means you have too many certificates in your “Trusted Root Certification Authorities” and the one you are using is relying on a root certificate that is in the truncated portion of the list. Delete the root certificates you don’t need and your client should work again!