Category Archives: C#

masks

Programmatic impersonation in C#

Impersonation

I recently deployed a WPF app on a server that allowed the user to stop and start some application-related services. The purpose of the app was to allow users with administrative rights an easy way to manage the services that they needed to manage. Granted, they could manage the services through the services MMC, but the little WPF app was a requirement, and it’s our job as developers to make things easier for our clients – right?

All went well until a change of requirements meant that a user without administrative rights needed to use the program to stop and start the required services. When I tried to use the app, I got an exception – quite rightly, stopping and starting the services required admin rights. We needed the restricted user to be able to log on and use the app, but still needed to restrict their permissions.

So – step in programmatic impersonation in C# – a way to give restricted users the power that that’s required, all within the confines of your application.

The first thing to point out is that I got quite a bit of this code from a google search, but I had to do a bit of work to get things in a state that I found really useful.

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Runtime.InteropServices;
using System.Linq;
using System.Security.Principal;
using System.Text;
namespace ServiceControllerApp.Security
{
    public class Impersonator : IDisposable
    {
        private WindowsImpersonationContext _impersonatedUser = null;
        private IntPtr _userHandle;
        public Impersonator()
        {
            _userHandle = new IntPtr(0);
            string user = "servicecontroller";
            string userDomain = ConfigurationManager.AppSettings["MachineDomain"];
            string password = "yourpassword";
            bool returnValue = LogonUser(user, userDomain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref _userHandle);
            if (!returnValue)
                throw new ApplicationException("Could not impersonate user");
            WindowsIdentity newId = new WindowsIdentity(_userHandle);
            _impersonatedUser = newId.Impersonate();
        }
        #region IDisposable Members
        public void Dispose()
        {
            if (_impersonatedUser != null)
            {
                _impersonatedUser.Undo();
                CloseHandle(_userHandle);
            }
        }
        #endregion
        #region Interop imports/constants
        public const int LOGON32_LOGON_INTERACTIVE = 2;
        public const int LOGON32_LOGON_SERVICE = 3;
        public const int LOGON32_PROVIDER_DEFAULT = 0;
        [DllImport("advapi32.dll", CharSet = CharSet.Auto)]
        public static extern bool LogonUser(String lpszUserName, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public extern static bool CloseHandle(IntPtr handle);
        #endregion
    }
}

Impersonator is a simple class that uses interop to call Win32 LogonUser and CloseHandle functions. We have to use interop because .NET doesn’t provide the equivalent methods.

The code shown above has a user, domain and password actually in the code – for some situations this is a security risk, so the credentials should be obtained in another manner, but for my needs, it was satisfactory, and their direct inclusion simplifies this example.

The class has a WindowsImpersonationContext to manage the impersonation, and the constructor sets up the required logon rights using the LogonUser interop.

Crucially, the impersonation must end, with an equivalent Log Off – and the class implements IDisposable to call the required log off code. Using the class is easy.

using (Impersonator impersonator = new Impersonator())
{
    // code in here
}

The good thing is that because the class implements IDisposable, you don’t have to pepper your code with the log off code equivalent. I hope it’s of use to somebody wishing to implement impersonation.

Gravatar Control Update

Update – 12 June 2008

An updated version of this post, containing full source for the control and explanation is available here.

Original Post

The guys over at Gravatar.com have been hard at work updating their service, and I’ve updated the ASP.NET control I developed to reflect the changes.

The maximum size of Gravatars has now been increased from 80 to 512, so there’s a code change in the Render method:

// if the size property has been specified, and in the range
// 1..512:
try
{
    // if it's not in the allowed range, throw an exception:
    if (Size < 1 || Size > 512)
        throw new ArgumentOutOfRangeException();
}
catch
{
    Size = 80;
}

So, a default of 80 will still be used if the value specified is not within the 1 to 512 range, or it is not specified, but allows for a larger size.

The avatar.php URL serving the images now supports abbreviation, but the code in the control has not been changed.

Design time view of the control

The image shows the Design time view of the control, with the width set at the default value of 80. I’ve checked the control at 512 pixels, but my Gravatar doesn’t look too good expanded out to that size, so I’ve decided to stick at size 80 for the screenshot!

Gravatar ASP.NET Control

Update – 12 June 2008

An updated version of this post, containing full source for the control and explanation is available here.

Original Post

I just got myself a freshclickmedia.com Gravatar over at gravatar.com. A Gravatar is a little avatar associated with an email address, and quite a few blogs use them to decorate post comments. Signing up is easy – all you need to do is supply an email address, and image, and give your image a content rating.

The source of the gravatar image tag points to gravatar.com’s image generator and includes an MD5 hash of the email address to prevent email harvesting. A ‘max rating’ parameter prevents the display of unsavoury content.

There are a wide number of blogging gravatar plugins, so I decided to write an ASP.NET custom control to do the job. Here I present the control and its features.

Continue reading