|
|
![]() |
|
||
|
|
|||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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. |
![]() |