views:

32

answers:

2

I am trying to use WCF to do some remote user management things. I and reusing some code I had on a server 2003 box and worked fine, but on my windows 7 test box when I check to see if the user who called the function is administrator it says it is not.

[OperationBehavior(Impersonation=ImpersonationOption.Required)]
public string SetPassword(string username)
{
    WindowsPrincipal principal = new WindowsPrincipal(OperationContext.Current.ServiceSecurityContext.WindowsIdentity);
    System.Diagnostics.Debug.Print(WindowsIdentity.GetCurrent().Name);
    System.Diagnostics.Debug.Print(principal.Identity.Name);
    if (principal.IsInRole(WindowsBuiltInRole.Administrator))
    {
        //try
        {
            lock (Watchdog.m_principalContext)
            {
                using (UserPrincipal up = UserPrincipal.FindByIdentity(Watchdog.m_principalContext, username))
                {
                    string newpassword = CreateRandomPassword();
                    up.SetPassword(newpassword);
                    up.Save();
                    return newpassword;
                }
            }
        }
        //catch
        {
            return null;
        }
    }
    else 
        throw new System.Security.SecurityException("User not administrator");
}

principal.IsInRole(WindowsBuiltInRole.Administrator) is returning false every time. Both my current identity and principal.idenity are the correct user to be impersonated. and that user is a member of the administrators user group.

I think it has to do with UAC that was implemented in windows vista and up. this will be a issue because the production machine this will be going on to is a win2k8-r2 box.

Any suggestions on what to do?

+2  A: 

Take a look at this article, under the section, "Coping with Windows Vista" , a very well written article with about UAC and checking Admin privs programatically.

RandomNoob
Ugh, I was worried about something like that. Is there no easier way to check if there a user is a administrator?
Scott Chamberlain
A: 

As I did not want to do all that work (from RandomNoob's post) for check if the user is an administrator and the service is already running in a administrative context, I decided to just drop impersonation. I created a new user group called WCFUsers and anyone who will be using the service was added to that group. It now does the System.DirectoryServices.AccountManagement operations in its own context.

[OperationBehavior(Impersonation=ImpersonationOption.NotAllowed)]
public string SetPassword(string username)
{
    WindowsPrincipal principal = new WindowsPrincipal(OperationContext.Current.ServiceSecurityContext.WindowsIdentity);
    if (principal.IsInRole("WCFUsers"))
    {
        try
        {
            lock (Watchdog.m_principalContext)
            {
                using (UserPrincipal up = UserPrincipal.FindByIdentity(Watchdog.m_principalContext, username))
                {
                    string newpassword = CreateRandomPassword();
                    up.SetPassword(newpassword);
                    up.Save();
                    return newpassword;
                }
            }
        }
        catch
        {
            return null;
        }
    }
    else
        return null;
}
Scott Chamberlain
Have you looked into using the attribute based permission demand at the operation level? [PrincipalPermission(SecurityAction.Demand, Role ="Administrators")]
RandomNoob