How to run c# application with admin creds?

你说的曾经没有我的故事 提交于 2019-12-29 07:42:32

问题


I wrote a C# application that unlocks users when they are locked out of their account (Active Directory). The application searches for users in a specific OU and will list the locked out users in a ComboBox. Then you select that user from the ComboBox and choose unlock.

If you are logged in as an admin, it works perfect. If you are a normal user no.

I want to run my application with admin creds but under a normal user also as secure as possible.

I was reading that maybe program a windows service but I'm unclear on how to program my application to install, run as a service, and run under admin creds.


回答1:


Looks like you want to impersonate the admin user. Here's an article and demo. Looks to be written in .Net 1 but should get you started. Also check out the WindowsIdentity class.




回答2:


The goal behind this application strikes me as wrong. You are basically trying to create a means of allowing non-admin users to unlock accounts...which is, for good reason, a feature not available to normal users.




回答3:


You don't have to use a windows service to do something as someone else. You can use impersonation to login as another user to do the actual switch. Here’s an example I found that uses the windows dll "advapi32.dll" to login.

Grab the sample code off the bottom of the page. I didn’t want to just copy his code here.

http://csharptuning.blogspot.com/2007/06/impersonation-in-c.html

One cavet with Impersonation though is that the computer doing the impersonation needs to be on the same domain as the user that your impersonating.




回答4:


Here is the class I use to perform impersonation on a ASP.NET 2.0 website, running on Windows 2000.

Example Usage:

if (iu.impersonateValidUser("AdminUserName", "DomainName", "AdminPassword"))
{            
    // Do Something Under Other Users Security Context
    iu.undoImpersonation();
}

That's it... Complete class below.

using System;
using System.Runtime.InteropServices;
using System.Security.Principal;


public class ImpersonateUser
{
    public const int LOGON32_LOGON_INTERACTIVE = 2;
    public const int LOGON32_PROVIDER_DEFAULT = 0;

    WindowsImpersonationContext impersonationContext;

    [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(String userName, String domain, String password)
    {
        WindowsIdentity tempWindowsIdentity;
        IntPtr token = IntPtr.Zero;
        IntPtr tokenDuplicate = IntPtr.Zero;

        if (RevertToSelf())
        {
            if (LogonUserA(userName, domain, password, 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();
    }
}



回答5:


You cannot use a Windows Service (easily), since a Windows Service cannot have a GUI. The only way to do this as a service would be to install the service, and then make a GUI app that used IPC to communicate the request to the service. This would open up a potential loophole, though.

If you're running on Vista, a good option would be to edit the manifest file and add requireAdministrator.


Edit:

It sounds like my first suggestion may be what you want... To do this, the basic process is:

  • Make your application a windows service. There is a walkthrough of this process on MSDN.
  • Make your service respond to some form of IPC. You could use sockets, pipes, or any other form of communication. The service would "listen" for a request to unblock a user, then perform this.
  • Install the service on the machine. This will make it run as an administrator, and just be always on.
  • Make a second application to act as a client. Use the same IPC technology to communicate with the server. This would send the request to unblock the client to the service.

You could then run the client as a normal user (since it just needs to talk to the service, it does not do anything that requires permissions).




回答6:


I have a very similar widget on my intranet site, so members of the IT department located in different time zones can handle password resets that also performs a account unlock when the domain admins on the west coast are not available. This is a pretty simple tasks and here is an except of how I did this...

        using System.DirectoryServices;

        // Impersonate the Admin to Reset the Password / Unlock Account //
        // Change variables below.
        ImpersonateUser iu = new ImpersonateUser();
        if (iu.impersonateValidUser("AdminUserName", "DomainName", "AdminPassword"))
        {
            resetPassword("AdminUserName", "AdminPassword", UserToReset, "NewPassword");
            iu.undoImpersonation();
        }

        // Perform the Reset / Unlock //
        public void resetPassword(string username, string password, string acct, string newpassword)
        {
            string Path = // LDAP Connection String
            string Username = username;
            string Password = password;
            string Domain = "DomainName\\"; // Change to your domain name

            DirectoryEntry de = new DirectoryEntry(Path, Domain + Username, Password, AuthenticationTypes.Secure);

            DirectorySearcher ds = new DirectorySearcher(de);

            ds.Filter = "(&(objectClass=user)(|(sAMAccountName=" + acct + ")))";

            ds.PropertiesToLoad.Add("displayName");
            ds.PropertiesToLoad.Add("sAMAccountName");
            ds.PropertiesToLoad.Add("DistinguishedName");
            ds.PropertiesToLoad.Add("CN");

            SearchResult result = ds.FindOne();

            string dn = result.Properties["DistinguishedName"][0].ToString();

            DirectoryEntry uEntry = new DirectoryEntry("LDAP://" + dn, username, password);

            uEntry.Invoke("SetPassword", new object[] { newpassword });
            uEntry.Properties["LockOutTime"].Value = 0;
            uEntry.CommitChanges();
            uEntry.Close();
        }

I strongly agree that this can lead to security issues if incorrectly used, we have every change logged and emailed to the domain admins (so their in the loop) and we auto generate the passwords. This has been a huge help for our small IT department, since admins no longer have to wake up at 4 AM to reset a password.




回答7:


This code will allow you to call another executable and run it is an administrator.

try
{
   path = path_to_your_executable;

   ProcessStartInfo myProcess = new ProcessStartInfo(path);
   myProcess.Domain = domain;
   myProcess.UserName = username;
   myProcess.Password = password;
   myProcess.UseShellExecute = false;

   Process.Start(myProcess);
}
catch (Exception myException)
{
   // error handling
}

Not exactly what you're looking for but it is a possible solution.



来源:https://stackoverflow.com/questions/916714/how-to-run-c-sharp-application-with-admin-creds

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!