2

I'm writing a Windows Forms app that runs from a non-privileged user account.

For one action, I need to prompt for a username/pwd for an account with Admin privs.

So, the app doesn't actually have to run from a privileged account; but the user has to specify an admin account in order to be allowed to do certain actions.

Does anyone know how to validate a username/pwd as an account which has admin privs?

user3012629
  • 657
  • 7
  • 16
  • 3
    You can't elevate just one part of your code to run at a higher privilege level than the app itself. If you really need to do this, put the part of your code that needs elevated privileges in a separate app, give it a manifest that requires administrator privileges, and start that application from your lower-privileged application when the elevated privileges are needed. – Ken White Jun 19 '14 at 22:16
  • Did you want to use the admin user's privileges, or just confirm that the username/password combination is valid and belongs to an administrator? – Harry Johnston Jun 19 '14 at 22:23
  • 1
    I will note that passing admin credentials to a non-privileged process is a bad idea from a security standpoint. If the non-privileged account happened to be compromised, an attacker could gather the admin credentials and use them to elevate his privilege. It would be preferable to use UAC to authenticate the admin user instead, as @KenWhite said; the only catch is that it wouldn't work if UAC is disabled, so you'd have to detect that case and fall back to another solution. – Harry Johnston Jun 19 '14 at 22:29
  • Re Harry's first post question - Yes, all I want to do is confirm that the username/pwd is valid & belongs to an admin user. Don't need to actually run any code in any privileged mode. – user3012629 Jun 20 '14 at 07:58
  • In Win32 code you could do this by calling `LogonUser` with `LOGON32_LOGON_BATCH` and then calling `CheckTokenMembership`. There is probably a way to do the same thing directly in .NET, so hopefully someone can post an answer. – Harry Johnston Jun 21 '14 at 04:42

1 Answers1

2

As Harry Johnston commented, you can use the following to authenticate a username/password:

Private Declare Auto Function CloseHandle Lib "kernel32.dll"   
                             (ByVal  clsTokenToClose As IntPtr) As Integer

Private Declare Auto Function LogonUser Lib "advapi32.dll" ( _
                                ByVal lpszUsername As String, _
                                ByVal lpszDomain As String, _
                                ByVal lpszPassword As String, _
                                ByVal dwLogonType As Integer, _
                                ByVal dwLogonProvider As Integer, _
                                ByRef phToken As IntPtr) As Boolean

Const DOMAIN_NAME As String = "MYDOMAIN"
Dim token As IntPtr

'Use the Win32API LogonUser to authenticate UserName and Password.
'If successful, a token representing the user is returned.

 If LogonUser("UserName", DOMAIN_NAME, "password", LOGON32_LOGON_BATCH,  
              LOGON32_PROVIDER_DEFAULT, token) Then

     'The token is used to create a WindowsIdentity, which is in turn
     'used to create a WindowsPrincipal.  The WindowsPrincipal is checked
     'to see if it belongs to the desired group in ActiveDirectory.

     Dim WIdent As New WindowsIdentity(token)

     Dim WPrincipal As New WindowsPrincipal(WIdent)

     If WPrincipal.IsInRole("Administrators") Then 
        'User has admin privilege, carry on.

     End If

     CloseHandle(token)

 End If

Be sure to replace "Administrators" in the WPrincipal.IsInRole call with the group you want to check against.

Casey Wilkins
  • 2,555
  • 2
  • 23
  • 31
  • Many thanks Casey. I've been trying this out under Windows 7 Home Premium; I couldn't get it to recognise my account which has Admin privs. However, Harry Johnston's suggestion to use logonType of LOGON32_LOGON_BATCH was the answer. So, the problem was solved by using your code, and changing the Interactive login to Batch. Many thanks! ;-) – user3012629 Oct 07 '14 at 16:00
  • I have updated my answer for a batch login and closed the handle as pointed out by @HarryJohnston. – Casey Wilkins Oct 07 '14 at 17:44
  • +1. The reason you need LOGON32_LOGON_BATCH in particular is [explained here](http://stackoverflow.com/a/21718198/886887). – Harry Johnston Oct 07 '14 at 19:17