|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Visual Basic Network Services InitializeSecurityContext: Authenticate User via the NT Challenge Process |
||
Posted: | Saturday March 16, 2002 | |
Updated: | Monday December 26, 2011 | |
Applies to: | VB4-32, VB5, VB6 | |
Developed with: | VB6, Windows XP | |
OS restrictions: | As coded, Windows 2000, Windows XP. | |
Author: | VBnet - Randy Birch, MSKB | |
Related: |
IsUserAnAdmin: Determine if the Current User is an Administrator LookupAccountName: Verify a User's Account LookupAccountSid: Determine if the Current Process is Running Under Admin Account OpenUserBrowser: Add Selection of Users and Groups |
|
Prerequisites |
Network or DUN connection. |
|
Windows
users in a corporate environment are familiar with the NT Challenge
procedure .. they call it logging on. In a nutshell, the NT
Challenge attempts to confirm the credentials entered by the user against
security information on the login machine - the local workstation or
domain server. When the challenge is successful, the login continues;
when it is not, the user's attempted login count is incremented by one
until the administrator-defined account lockout point is reached. The MSKB provides a rather complex and convoluted example of using InitializeSecurityContext, QuerySecurityPackageInfo, AcquireCredentialsHandle, AcceptSecurityContext to perform a NT Challenge. This demo, although still quite involved, attempts to trim some of the fat (not to mention the GoTo's) from the MSKB code to present a method that will validate the user against either the local workstation or a domain controller. There are three issues to consider with the following code: First, because MS decided, on NT4, to implement the APIs in a different core DLL than used on 9x through XP, an application wanting to perform the challenge must be coded to accommodate the APIs in use on the calling system. To use the code below on NT4, the references to "secur32" (secur32.dll) in the API declarations need to be changed to "security" (security.dll), and the code in the IsWin2000Plus() function downgraded to return True when running NT4 (OSV.dwVerMajor = 4). The second issue I discovered concerns the passing domain name ... if the user name and password are both correct, the call returns True regardless of what is entered in the Domain box. This appears to be an anomaly of systems system where authentication is performed against the local user manager table for that machine. Several readers using true Windows 2000 and NT4 domains have verified the methods work as expected (with the declare change mentioned for NT4). The third issue deals with Internationalization ... since the routine shown here uses the "A" versions of APIs rather than the "W" (wide) versions, usernames or passwords containing letters outside the norm for North American ANSI characters will not validate using this code. I do not have a "W" version of the routines available. And now a word from the System Admin (aka the BOFH): The process of collecting credentials from a user-mode application can provide a possible security hole in a network computing environment (as well as being annoying to a user). The Unified Logon requirement (which specifies that the user should only have to type his or her credentials once, at the logon screen), was added to the Microsoft BackOffice logo requirements for these reasons. It is important to ascertain whether your application's design really must rely on asking for a user's complete credentials, or whether a more secure method of credential validation is not more appropriate, for example by reconfirming just the user name as shown in LookupAccountName: Verify a User's Account . Regardless of the validation, it is strongly recommended that all developers consult both the local system administrator as well as security documentation in the Platform SDK for guidance. |
BAS Module Code |
None. |
|
Form Code |
To a form add a command button (Command1), a label (Label1) for the authentication result, and three text boxes (Text1, Text2, Text3), along with the following code: |
|
Option Explicit '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Copyright ©1996-2011 VBnet/Randy Birch, All Rights Reserved. ' Some pages may also contain other copyrights by the author. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Distribution: You can freely use this code in your own ' applications, but you may not reproduce ' or publish this code on any web site, ' online service, or distribute as source ' on any media without express permission. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Const SEC_E_OK = 0 Private Const HEAP_ZERO_MEMORY = &H8 Private Const SEC_WINNT_AUTH_IDENTITY_ANSI = &H1 Private Const SECBUFFER_TOKEN = &H2 Private Const SECURITY_NATIVE_DREP = &H10 Private Const SECPKG_CRED_INBOUND = &H1 Private Const SECPKG_CRED_OUTBOUND = &H2 Private Const SEC_I_CONTINUE_NEEDED = &H90312 Private Const SEC_I_COMPLETE_NEEDED = &H90313 Private Const SEC_I_COMPLETE_AND_CONTINUE = &H90314 Private Const VER_PLATFORM_WIN32_NT = &H2 Private Type SecPkgInfo fCapabilities As Long wVersion As Integer wRPCID As Integer cbMaxToken As Long Name As Long Comment As Long End Type Private Type SecHandle dwLower As Long dwUpper As Long End Type Private Type AUTH_SEQ fInitialized As Boolean fHaveCredHandle As Boolean fHaveCtxtHandle As Boolean hcred As SecHandle hctxt As SecHandle End Type Private Type SEC_WINNT_AUTH_IDENTITY User As String UserLength As Long Domain As String DomainLength As Long Password As String PasswordLength As Long Flags As Long End Type Private Type SEC_WINNT_AUTH_IDENTITYL User As Long UserLength As Long Domain As Long DomainLength As Long Password As Long PasswordLength As Long Flags As Long End Type Private Type TimeStamp LowPart As Long HighPart As Long End Type Private Type SecBuffer cbBuffer As Long BufferType As Long pvBuffer As Long End Type Private Type SecBufferDesc ulVersion As Long cBuffers As Long pBuffers As Long End Type Private Type OSVERSIONINFO OSVSize As Long dwVerMajor As Long dwVerMinor As Long dwBuildNumber As Long PlatformID As Long szCSDVersion As String * 128 End Type Private Declare Sub CopyMemory Lib "kernel32" _ Alias "RtlMoveMemory" _ (Destination As Any, _ Source As Any, _ ByVal Length As Long) Private Declare Function CompleteAuthToken Lib "secur32" _ (ByRef phContext As SecHandle, _ ByRef pToken As SecBufferDesc) As Long Private Declare Function DeleteSecurityContext Lib "secur32" _ (ByRef phContext As SecHandle) As Long Private Declare Function FreeCredentialsHandle Lib "secur32" _ (ByRef phContext As SecHandle) As Long Private Declare Function FreeContextBuffer Lib "secur32" _ (ByVal pvContextBuffer As Long) As Long Private Declare Function GetProcessHeap Lib "kernel32" () As Long Private Declare Function HeapAlloc Lib "kernel32" _ (ByVal hHeap As Long, _ ByVal dwFlags As Long, _ ByVal dwBytes As Long) As Long Private Declare Function HeapFree Lib "kernel32" _ (ByVal hHeap As Long, _ ByVal dwFlags As Long, _ ByVal lpMem As Long) As Long Private Declare Function GetVersionEx Lib "kernel32" _ Alias "GetVersionExA" _ (lpVersionInformation As OSVERSIONINFO) As Long Private Declare Function QuerySecurityPackageInfo Lib "secur32" _ Alias "QuerySecurityPackageInfoA" _ (ByVal PackageName As String, _ ByRef pPackageInfo As Long) As Long Private Declare Function InitializeSecurityContext Lib "secur32" _ Alias "InitializeSecurityContextA" _ (phCredential As Any, _ phContext As Any, _ ByVal pszTargetName As Long, _ ByVal fContextReq As Long, _ ByVal Reserved1 As Long, _ ByVal TargetDataRep As Long, _ pInput As Any, _ ByVal Reserved2 As Long, _ phNewContext As SecHandle, _ pOutput As SecBufferDesc, _ pfContextAttr As Long, _ ptsExpiry As TimeStamp) As Long Private Declare Function AcquireCredentialsHandle Lib "secur32" _ Alias "AcquireCredentialsHandleA" _ (ByVal pszPrincipal As Long, _ ByVal pszPackage As String, _ ByVal fCredentialUse As Long, _ ByVal pvLogonId As Long, _ pAuthData As Any, _ ByVal pGetKeyFn As Long, _ ByVal pvGetKeyArgument As Long, _ phCredential As SecHandle, _ ptsExpiry As TimeStamp) As Long Private Declare Function AcceptSecurityContext Lib "secur32" _ (phCredential As SecHandle, _ phContext As Any, _ pInput As SecBufferDesc, _ ByVal fContextReq As Long, _ ByVal TargetDataRep As Long, _ phNewContext As SecHandle, _ pOutput As SecBufferDesc, _ pfContextAttr As Long, _ ptsExpiry As TimeStamp) As Long Private Sub Form_Load() Label1.Caption = "" Text1.Text = " |
Comments |
Q279815 shows the original code this demo is based on. |
|
|
|
|||||
|
|||||
|
|||||
Copyright ©1996-2011 VBnet and Randy Birch. All Rights Reserved. |