0

on my website (written in ASP.NET/C#) I want the moderaters to be able to start a certain service. The code I have for this is:

    ServiceController svcController = new ServiceController("InvidualFileConversion");

    if (svcController != null)
    {
        try
        {
            svcController.Stop();
            svcController.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(10));
            svcController.Start();
        }
        catch (Exception ex)
        {
            // error
        }
    }

Now when I run this I get the error "Cannot open InvidualFileConversion service on computer", with the additional message: "Acces is denied".

I know this is a problem with permissions, but how do I give myself the proper permissions? Don't come with the answer where I should write: , cause I have tried it and it didn't work. Also I think that is not really the best way to set this up for the whole website when I just need it for these few lines of code.

EDIT: I've added this in my code and it still doesn't work, I get the same exception at the same place. Now it looks like this:

protected void ConvertLink_OnClick(object sender, EventArgs e)
{
    //convert();
    try
    {
        //--need to impersonate with the user having appropriate rights to start the service
        Impersonate objImpersonate = new Impersonate(domainName, userName, userPassword);
        if (objImpersonate.impersonateValidUser())
        {
            //--write code to start/stop the window service
            startWindowsService();
            objImpersonate.undoImpersonation();
        }
    }
    catch (Exception Ex)
    { Response.Write(Ex.Message + Ex.InnerException.Message); }
}

private void startWindowsService()
{
    ServiceController svcController = new ServiceController("InvidualFileConversion");

    if (svcController != null)
    {
        try
        {
            svcController.Stop();
            svcController.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(10));
            svcController.Start();
        }
        catch (Exception ex)
        {
            // error
        }
    }
}

I have a Impersonate class that looks like this:

using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections.Generic;
using System.Security.Principal;
using System.Runtime.InteropServices;

/// <summary>
/// Summary description for Impersonate
/// </summary>
public class Impersonate
{

#region "Class Members"
public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_PROVIDER_DEFAULT = 0;
WindowsImpersonationContext impersonationContext;
#endregion

#region "Class Properties"
public string domainName { get; set; }
public string userName { get; set; }
public string userPassword { get; set; }
#endregion

public Impersonate()
{
    //
    // TODO: Add constructor logic here
    //
}
public Impersonate(string domainName, string userName, string userPassword)
{
    this.domainName = domainName;
    this.userName = userName;
    this.userPassword = userPassword;
}

#region "Impersonation Code"
[DllImport("advapi32.dll")]
public static extern int LogonUserA(String lpszUserName,
    String lpszDomain,
    String lpszPassword,
    int dwLogonType,
    int dwLogonProvider,
    ref IntPtr phToken);

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int DuplicateToken(IntPtr hToken,
    int impersonationLevel,
    ref IntPtr hNewToken);

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool RevertToSelf();

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool CloseHandle(IntPtr handle);
public bool impersonateValidUser()
{
    WindowsIdentity tempWindowsIdentity;
    IntPtr token = IntPtr.Zero;
    IntPtr tokenDuplicate = IntPtr.Zero;

    if (RevertToSelf())
    {
        if (LogonUserA(this.userName, this.domainName, this.userPassword, LOGON32_LOGON_INTERACTIVE,
            LOGON32_PROVIDER_DEFAULT, ref token) != 0)
        {
            if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
            {
                tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
                impersonationContext = tempWindowsIdentity.Impersonate();
                if (impersonationContext != null)
                {
                    CloseHandle(token);
                    CloseHandle(tokenDuplicate);
                    return true;
                }
            }
        }
    }
    if (token != IntPtr.Zero)
        CloseHandle(token);
    if (tokenDuplicate != IntPtr.Zero)
        CloseHandle(tokenDuplicate);
    return false;
}

public void undoImpersonation()
{
    impersonationContext.Undo();
}
#endregion
}

So the validation thing works but doesn't solve my problem.. I guess there is still the problem with the permissions.. What do I do to change this?

EDIT 2: The next steps I took involve this:

  1. Creating a app pool where the identity is set to a user (which is member of an administrator group).
  2. Set the service "log on" to the same user.
  3. After running the web app again, it still fails..

However If I put in the Administrator account as credentials in the code, it works.. (Even though I did not use the Administrator in the App Pool and on the service...)

In other words, I can get what I want with the Administrator account, but not with an account I created myself and has the admin rights. I still want to make this work with a user I made myself as I think it is not so safe to put your Administrator credentials available.

On a sidenote, on the server which I work on I have an account that has administrator privileges but is not the 'Administrator'-account.

EDIT 3: This is getting weird. I seems to work now BUT: - without the Impersonation method (it did not work). - I just did what Rob said. I have my own application pool with a user I defined. The windows service has that user specified as well. (The user received Log On As Service right) - With this, it seems to work. - But if debug through my website I still get acces denied. But if just acces my website through the browser and its ip I can start the service.

To sum it up: - Impersonation method doesn't work. - Just using a self created app pool with the currect user works if the service has the user also specified. But it doesn't work in debug mode (still Acces Denied there).

This post is getting to big and I wonder if any still really reads it.. But maybe still someone can provide me with any details? I'm afraid it will fail again somewhere in the future..

Any comment will be appreciated! Floris

Floris Devriendt
  • 2,044
  • 4
  • 24
  • 34

1 Answers1

2

You have to make sure that your web site is running under a user who have enough right to start the service. Make sure also that the anonymous authentication is disabled on IIS A good way could be to create a user who has rights for starting service on the server web then create an application pool that runs under that user.then you have to make your web site use that application pool. Using this approach all the web site will run under the user you have just create. If you want be more granular you can still create the user that have the rights for starting the service but instead of use it for the application pool you can make only the page that needs to start the service run under that user using the impersonation. You can use the imporsonation feature only for this method!

for more details have a look at the links below:

http://forums.asp.net/t/1137962.aspx/1

http://support.microsoft.com/kb/306158

Massimiliano Peluso
  • 26,379
  • 6
  • 61
  • 70
  • Imporsonation doesn't seem to work yet. But at what level do you create the user? Must it be user on the server? Or through IIS7? – Floris Devriendt May 20 '11 at 12:00
  • You say it like this: 1. Create a user who has rights for starting service on the server web. **Is this on IIS or the server itself or..?** 2. Create an application pool that runs under that user. **When you create an application pool you don't specify any user, so what do I do to run it under that user?** 3. Have to make your web site use that application pool. **This is not a problem** The other methods I've tried.. But don't work.. – Floris Devriendt May 20 '11 at 12:27
  • This would be on IIS itself, specifically in the Application Pool. On IIS7, it's under Application Pools > Advanced Settings > Process Model > Identity. We normally make a special user in Active Directory that has high permissions and no password timeout and assign that user to the App Pool. – Rob May 20 '11 at 14:18
  • Ok I will test this tomorrow when I have acces to the server. I will let you know if it works. Thanks for you comment. – Floris Devriendt May 21 '11 at 14:04
  • Ok I tested this on my virtual server running Windows 2008 and IIS7. I managed to get it working there, I'll wait flagging this as the correct answer until I get working on the real server. – Floris Devriendt May 21 '11 at 14:43
  • sorry for the delay answer but I have been away for a while. Anyway I think Rob has already answer your comment :-) – Massimiliano Peluso May 23 '11 at 08:47
  • Well the solution he provid helped a bit, but did not entirely solve my problem. I've edited my post with the steps I took. – Floris Devriendt May 23 '11 at 09:23
  • make sure the anonymous access on IIS is disabled. You should create an user that can only start the service and execute you web app but it should not be into the Administrator group – Massimiliano Peluso May 23 '11 at 11:20
  • The website has enabled, if I turn it off people can't acces it anymore (I did not create the website, I'm just adding an extension to it). As for the problem, it's still but somehow it works now without the impersonation. However I'm not convinced it will stay working like this. See the main post for my third edit. – Floris Devriendt May 24 '11 at 11:44