Bạn hiện đang ngoại tuyến, hãy chờ internet để kết nối lại

Làm thế nào để xác nhận chứng chỉ người dùng trên hệ điều hành Microsoft

QUAN TRỌNG: Bài viết này được dịch bằng phần mềm dịch máy của Microsoft chứ không phải do con người dịch. Microsoft cung cấp các bài viết do con người dịch và cả các bài viết do máy dịch để bạn có thể truy cập vào tất cả các bài viết trong Cơ sở Kiến thức của chúng tôi bằng ngôn ngữ của bạn. Tuy nhiên, bài viết do máy dịch không phải lúc nào cũng hoàn hảo. Loại bài viết này có thể chứa các sai sót về từ vựng, cú pháp hoặc ngữ pháp, giống như một người nước ngoài có thể mắc sai sót khi nói ngôn ngữ của bạn. Microsoft không chịu trách nhiệm về bất kỳ sự thiếu chính xác, sai sót hoặc thiệt hại nào do việc dịch sai nội dung hoặc do hoạt động sử dụng của khách hàng gây ra. Microsoft cũng thường xuyên cập nhật phần mềm dịch máy này.

Nhấp chuột vào đây để xem bản tiếng Anh của bài viết này:180548
TÓM TẮT
Đôi khi, bạn có thể muốn một ứng dụng để xác minh một của người sử dụng tên người dùng và mật khẩu (sau đây gọi là chứng chỉ). Bạn có thể làm điều này một vài cách khác nhau, tùy thuộc vào hệ điều hành trên đó chạy ứng dụng.

Bài viết này mô tả tất cả những cách phổ biến để xác minh thông tin đăng nhập của người dùng và các yêu cầu đặc biệt cho mỗi phương pháp.

Chú ý Thu thập các chứng chỉ người dùng từ một ứng dụng chế độ người dùng có thể gây phiền nhiễu để những người sử dụng và có thể cung cấp một lỗ hổng bảo mật có thể trong các doanh nghiệp môi trường máy tính. Yêu cầu đăng nhập thống nhất (một yêu cầu rằng người sử dụng nên chỉ được yêu cầu nhập ủy nhiệm của họ một thời gian tại các CTRL + ALT + DEL màn hình), đã được thêm vào các yêu cầu logo Microsoft BackOffice vì những lý do rất. Nó là quan trọng để đảm bảo rằng bạn thực sự cần phải thu thập thông tin đăng nhập và rằng một số phương pháp khác của khách hàng/máy chủ xác nhận thích hợp không hơn. Tham khảo tài liệu an ninh trong nền tảng SDK để biết thêm chi tiết về mạo danh và lập trình máy chủ an toàn.
THÔNG TIN THÊM
Các LogonUser API đã có sẵn và tài liệu từ Windows NT 3.51, và thường được sử dụng để xác minh chứng chỉ người dùng. API này có sẵn trên Windows NT, Windows 2000 và Windows XP. Thật không may, có một số hạn chế ngày bằng cách sử dụng LogonUser mà không phải luôn luôn thuận tiện để đáp ứng.

Lần đầu tiên và lớn nhất của những sự hạn chế đó là trên Windows NT và Windows 2000, các quá trình đó kêu gọi LogonUser phải có các đặc quyền SE_TCB_NAME (trong người dùng Quản lý, điều này là quyền "Hoạt động như một phần của hệ điều hành"). Các Đặc quyền SE_TCB_NAME là rất mạnh mẽ và không nên được trao cho bất kỳ bất kỳ người dùng chỉ cần để cho họ có thể chạy một ứng dụng mà cần phải xác nhận thông tin đăng nhập. Các phương pháp được đề nghị là để gọi cho LogonUser từ một dịch vụ mà là chạy trong trương mục hệ thống địa phương, bởi vì hệ thống địa phương tài khoản đã có các đặc quyền SE_TCB_NAME.

Chú ý LogonUser Win32 API không đòi hỏi TCB đặc quyền trong Microsoft Windows Server 2003, tuy nhiên, để tương thích downlevel, đây vẫn là các phương pháp tốt nhất.

Trên Windows XP, nó không còn cần thiết mà một quá trình có các đặc quyền SE_TCB_NAME để gọi LogonUser. Vì vậy, các phương pháp đơn giản nhất để xác nhận một người sử dụng thông tin đăng nhập vào Windows XP, là để gọi các LogonUser API.

Một trong những vấn đề khác với LogonUser là API không được thực hiện trên Windows 95, Windows 98, hoặc Windows Millennium Edition.

Như là một tùy chọn khác, bạn có thể sử dụng các nhà cung cấp hỗ trợ bảo mật Giao diện (SSPI) để làm một phong cách mạng đăng nhập với chứng chỉ người dùng cung cấp. Phương pháp này xác nhận có lợi thế là không đòi hỏi bất kỳ đặc biệt đặc quyền, cũng như làm việc trên tất cả các phiên bản của Windows. Kết quả cuối cùng của bằng cách sử dụng các dịch vụ SSPI để xác nhận ủy nhiệm là một đăng nhập là tương tự như gọi điện thoại LogonUser API với đăng nhập LOGON32_LOGON_NETWORK loại. Nhược điểm lớn nhất để loại đăng nhập là bạn không thể truy nhập tài nguyên mạng từ xa sau khi mạo mạng nhập đăng nhập. Nếu của bạn ứng dụng đang gọi LogonUser với các loại hình đăng nhập LOGON32_LOGON_INTERACTIVE để việc Windows NT của không có khả năng thực hiện đoàn đại biểu, sau đó SSPI đăng nhập/xác nhận sẽ có lẽ không phải là một thay thế khả thi.

Các mã mẫu cung cấp dưới đây cho thấy làm thế nào để gọi cho các dịch vụ SSPI để thực hiện xác nhận ủy nhiệm.

Sử dụng phương pháp này trên Windows 95, Windows 98, và Windows Millennium Edition, bạn cũng cần phải kích hoạt tính năng bảo mật NTLM dịch vụ bằng cách mở Control Panel, mạng, điều khiển truy cập, và sau đó chọn Cấp độ người dùng truy cập kiểm soát.

Trên Windows XP, đăng ký ForceGuest giá trị được thiết lập để 1 theo mặc định trong khóa registry sau đây:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa
Trên một máy tính Windows XP là một thành viên của một nhóm làm việc:
  • Nếu ForceGuest được kích hoạt (thiết lập để 1), SSPI sẽ luôn luôn cố gắng để đăng nhập bằng trương mục khách.
  • Nếu trương mục khách được kích hoạt, một đăng nhập SSPI sẽ thành công như khách cho bất kỳ chứng chỉ người dùng.
  • Nếu trương mục khách bị tắt, một đăng nhập SSPI sẽ không thành công ngay cả đối với chứng chỉ hợp lệ.
  • Nếu ForceGuest bị tắt (đặt là 0), SSPI sẽ đăng nhập như người dùng đã chỉ định.
Ngoài ra, nếu trương mục khách được kích hoạt, SSPI đăng nhập có thể thành công như khách cho chứng chỉ người dùng mà không phải là hợp lệ. C mẫu mã trong bài viết này chứng tỏ làm thế nào bạn có thể kiểm tra xem mã thông báo truy cập của bối cảnh an ninh được thành lập. Các IsGuest chức năng helper trong mẫu mã cho thấy làm thế nào bạn có thể xác minh rằng đăng nhập xảy ra như là người dùng đã chỉ định hoặc là khách mời.

Mã mẫu

///////////////////////////////////////////////////////////////////////////////////  SSPI Authentication Sample////  This program demonstrates how to use SSPI to authenticate user credentials.////  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF//  ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED//  TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A//  PARTICULAR PURPOSE.////  Copyright (C) 2007.  Microsoft Corporation.  All rights reserved.///////////////////////////////////////////////////////////////////////////////#define SECURITY_WIN32#include <windows.h>#include <tchar.h>#include <stdio.h>#include <conio.h>#include <sspi.h>#include <lm.h>#include <lmcons.h>// Older versions of WinError.h do not have SEC_I_COMPLETE_NEEDED #define.// So, in such an SDK environment setup, we will include issperr.h which has the// definition for SEC_I_COMPLETE_NEEDED. Include issperr.h only if// SEC_I_COMPLETE_NEEDED is not defined.#ifndef SEC_I_COMPLETE_NEEDED#include <issperr.h>#endiftypedef struct _AUTH_SEQ {   BOOL fInitialized;   BOOL fHaveCredHandle;   BOOL fHaveCtxtHandle;   CredHandle hcred;   struct _SecHandle hctxt;} AUTH_SEQ, *PAUTH_SEQ;// Function pointersACCEPT_SECURITY_CONTEXT_FN       _AcceptSecurityContext     = NULL;ACQUIRE_CREDENTIALS_HANDLE_FN    _AcquireCredentialsHandle  = NULL;COMPLETE_AUTH_TOKEN_FN           _CompleteAuthToken         = NULL;DELETE_SECURITY_CONTEXT_FN       _DeleteSecurityContext     = NULL;FREE_CONTEXT_BUFFER_FN           _FreeContextBuffer         = NULL;FREE_CREDENTIALS_HANDLE_FN       _FreeCredentialsHandle     = NULL;INITIALIZE_SECURITY_CONTEXT_FN   _InitializeSecurityContext = NULL;QUERY_SECURITY_PACKAGE_INFO_FN   _QuerySecurityPackageInfo  = NULL;QUERY_SECURITY_CONTEXT_TOKEN_FN  _QuerySecurityContextToken = NULL;#define CheckAndLocalFree(ptr) \            if (ptr != NULL) \            { \               LocalFree(ptr); \               ptr = NULL; \            }#pragma comment(lib, "netapi32.lib")LPVOID RetrieveTokenInformationClass(      HANDLE hToken,      TOKEN_INFORMATION_CLASS InfoClass,      LPDWORD lpdwSize){   LPVOID pInfo = NULL;   BOOL fSuccess = FALSE;   __try   {      *lpdwSize = 0;      //      // Determine the size of the buffer needed      //      GetTokenInformation(            hToken,            InfoClass,            NULL,            *lpdwSize, lpdwSize);      if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)      {         _tprintf(_T("GetTokenInformation failed with %d\n"), GetLastError());         __leave;      }      //      // Allocate a buffer for getting token information      //      pInfo = LocalAlloc(LPTR, *lpdwSize);      if (pInfo == NULL)      {         _tprintf(_T("LocalAlloc failed with %d\n"), GetLastError());         __leave;      }      if (!GetTokenInformation(            hToken,            InfoClass,            pInfo,            *lpdwSize, lpdwSize))      {         _tprintf(_T("GetTokenInformation failed with %d\n"), GetLastError());         __leave;      }      fSuccess = TRUE;   }   __finally   {      // Free pDomainAndUserName only if failed      // Otherwise, the caller has to free after use      if (fSuccess == FALSE)      {         CheckAndLocalFree(pInfo);      }   }   return pInfo;}PSID GetUserSidFromWellKnownRid(DWORD Rid){    PUSER_MODALS_INFO_2 umi2;    NET_API_STATUS nas;    UCHAR SubAuthorityCount;    PSID pSid = NULL;    BOOL bSuccess = FALSE; // assume failure    nas = NetUserModalsGet(NULL, 2, (LPBYTE *)&umi2);    if (nas != NERR_Success)    {        printf("NetUserModalsGet failed with error code : [%d]\n", nas);        SetLastError(nas);        return NULL;    }    SubAuthorityCount = *GetSidSubAuthorityCount                       (umi2->usrmod2_domain_id);    //     // Allocate storage for new Sid. account domain Sid + account Rid    //     pSid = (PSID)LocalAlloc(LPTR,          GetSidLengthRequired((UCHAR)(SubAuthorityCount + 1)));    if (pSid != NULL)    {        if (InitializeSid(              pSid,              GetSidIdentifierAuthority(umi2->usrmod2_domain_id),              (BYTE)(SubAuthorityCount+1)              ))        {            DWORD SubAuthIndex = 0;            //             // Copy existing subauthorities from account domain Sid into            // new Sid            //             for (; SubAuthIndex < SubAuthorityCount ; SubAuthIndex++)            {                *GetSidSubAuthority(pSid, SubAuthIndex) =                *GetSidSubAuthority(umi2->usrmod2_domain_id,                                  SubAuthIndex);            }            //             // Append Rid to new Sid            //             *GetSidSubAuthority(pSid, SubAuthorityCount) = Rid;        }    }    NetApiBufferFree(umi2);    return pSid;}BOOL IsGuest(HANDLE hToken){    BOOL fGuest = FALSE;    PSID pGuestSid = NULL;    PSID pUserSid = NULL;    TOKEN_USER *pUserInfo = NULL;    DWORD dwSize = 0;    pGuestSid = GetUserSidFromWellKnownRid(DOMAIN_USER_RID_GUEST);    if (pGuestSid == NULL)        return fGuest;    //    // Get user information    //    pUserInfo = (TOKEN_USER *)RetrieveTokenInformationClass(hToken, TokenUser, &dwSize);    if (pUserInfo != NULL)    {        if (EqualSid(pGuestSid, pUserInfo->User.Sid))            fGuest = TRUE;    }    CheckAndLocalFree(pUserInfo);    CheckAndLocalFree(pGuestSid);    return fGuest;}///////////////////////////////////////////////////////////////////////////////void UnloadSecurityDll(HMODULE hModule) {   if (hModule)      FreeLibrary(hModule);   _AcceptSecurityContext      = NULL;   _AcquireCredentialsHandle   = NULL;   _CompleteAuthToken          = NULL;   _DeleteSecurityContext      = NULL;   _FreeContextBuffer          = NULL;   _FreeCredentialsHandle      = NULL;   _InitializeSecurityContext  = NULL;   _QuerySecurityPackageInfo   = NULL;   _QuerySecurityContextToken  = NULL;}///////////////////////////////////////////////////////////////////////////////HMODULE LoadSecurityDll() {   HMODULE hModule;   BOOL    fAllFunctionsLoaded = FALSE;   TCHAR   lpszDLL[MAX_PATH];   OSVERSIONINFO VerInfo;   //   //  Find out which security DLL to use, depending on   //  whether we are on Windows NT or Windows 95, Windows 2000, Windows XP, or Windows Server 2003   //  We have to use security.dll on Windows NT 4.0.   //  All other operating systems, we have to use Secur32.dll   //   VerInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);   if (!GetVersionEx (&VerInfo))   // If this fails, something has gone wrong   {      return FALSE;   }   if (VerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&      VerInfo.dwMajorVersion == 4 &&      VerInfo.dwMinorVersion == 0)   {      lstrcpy (lpszDLL, _T("security.dll"));   }   else   {      lstrcpy (lpszDLL, _T("secur32.dll"));   }   hModule = LoadLibrary(lpszDLL);   if (!hModule)      return NULL;   __try {      _AcceptSecurityContext = (ACCEPT_SECURITY_CONTEXT_FN)            GetProcAddress(hModule, "AcceptSecurityContext");      if (!_AcceptSecurityContext)         __leave;#ifdef UNICODE      _AcquireCredentialsHandle = (ACQUIRE_CREDENTIALS_HANDLE_FN)            GetProcAddress(hModule, "AcquireCredentialsHandleW");#else      _AcquireCredentialsHandle = (ACQUIRE_CREDENTIALS_HANDLE_FN)            GetProcAddress(hModule, "AcquireCredentialsHandleA");#endif      if (!_AcquireCredentialsHandle)         __leave;      // CompleteAuthToken is not present on Windows 9x Secur32.dll      // Do not check for the availablity of the function if it is NULL;      _CompleteAuthToken = (COMPLETE_AUTH_TOKEN_FN)            GetProcAddress(hModule, "CompleteAuthToken");      _DeleteSecurityContext = (DELETE_SECURITY_CONTEXT_FN)            GetProcAddress(hModule, "DeleteSecurityContext");      if (!_DeleteSecurityContext)         __leave;      _FreeContextBuffer = (FREE_CONTEXT_BUFFER_FN)            GetProcAddress(hModule, "FreeContextBuffer");      if (!_FreeContextBuffer)         __leave;      _FreeCredentialsHandle = (FREE_CREDENTIALS_HANDLE_FN)            GetProcAddress(hModule, "FreeCredentialsHandle");      if (!_FreeCredentialsHandle)         __leave;#ifdef UNICODE      _InitializeSecurityContext = (INITIALIZE_SECURITY_CONTEXT_FN)            GetProcAddress(hModule, "InitializeSecurityContextW");#else      _InitializeSecurityContext = (INITIALIZE_SECURITY_CONTEXT_FN)            GetProcAddress(hModule, "InitializeSecurityContextA");#endif      if (!_InitializeSecurityContext)         __leave;#ifdef UNICODE      _QuerySecurityPackageInfo = (QUERY_SECURITY_PACKAGE_INFO_FN)            GetProcAddress(hModule, "QuerySecurityPackageInfoW");#else      _QuerySecurityPackageInfo = (QUERY_SECURITY_PACKAGE_INFO_FN)            GetProcAddress(hModule, "QuerySecurityPackageInfoA");#endif      if (!_QuerySecurityPackageInfo)         __leave;      _QuerySecurityContextToken = (QUERY_SECURITY_CONTEXT_TOKEN_FN)            GetProcAddress(hModule, "QuerySecurityContextToken");      if (!_QuerySecurityContextToken)         __leave;      fAllFunctionsLoaded = TRUE;   } __finally {      if (!fAllFunctionsLoaded) {         UnloadSecurityDll(hModule);         hModule = NULL;      }   }   return hModule;}///////////////////////////////////////////////////////////////////////////////BOOL GenClientContext(PAUTH_SEQ pAS, PSEC_WINNT_AUTH_IDENTITY pAuthIdentity,      PVOID pIn, DWORD cbIn, PVOID pOut, PDWORD pcbOut, PBOOL pfDone) {/*++ Routine Description:   Optionally takes an input buffer coming from the server and returns   a buffer of information to send back to the server.  Also returns   an indication of whether or not the context is complete. Return Value:   Returns TRUE if successful; otherwise FALSE.--*/   SECURITY_STATUS ss;   TimeStamp       tsExpiry;   SecBufferDesc   sbdOut;   SecBuffer       sbOut;   SecBufferDesc   sbdIn;   SecBuffer       sbIn;   ULONG           fContextAttr;   if (!pAS->fInitialized) {      ss = _AcquireCredentialsHandle(NULL, _T("NTLM"),            SECPKG_CRED_OUTBOUND, NULL, pAuthIdentity, NULL, NULL,            &pAS->hcred, &tsExpiry);      if (ss < 0) {         fprintf(stderr, "AcquireCredentialsHandle failed with %08X\n", ss);         return FALSE;      }      pAS->fHaveCredHandle = TRUE;   }   // Prepare output buffer   sbdOut.ulVersion = 0;   sbdOut.cBuffers = 1;   sbdOut.pBuffers = &sbOut;   sbOut.cbBuffer = *pcbOut;   sbOut.BufferType = SECBUFFER_TOKEN;   sbOut.pvBuffer = pOut;   // Prepare input buffer   if (pAS->fInitialized)  {      sbdIn.ulVersion = 0;      sbdIn.cBuffers = 1;      sbdIn.pBuffers = &sbIn;      sbIn.cbBuffer = cbIn;      sbIn.BufferType = SECBUFFER_TOKEN;      sbIn.pvBuffer = pIn;   }   ss = _InitializeSecurityContext(&pAS->hcred,         pAS->fInitialized ? &pAS->hctxt : NULL, NULL, 0, 0,         SECURITY_NATIVE_DREP, pAS->fInitialized ? &sbdIn : NULL,         0, &pAS->hctxt, &sbdOut, &fContextAttr, &tsExpiry);   if (ss < 0)  {      // <winerror.h>      fprintf(stderr, "InitializeSecurityContext failed with %08X\n", ss);      return FALSE;   }   pAS->fHaveCtxtHandle = TRUE;   // If necessary, complete token   if (ss == SEC_I_COMPLETE_NEEDED || ss == SEC_I_COMPLETE_AND_CONTINUE) {      if (_CompleteAuthToken) {         ss = _CompleteAuthToken(&pAS->hctxt, &sbdOut);         if (ss < 0)  {            fprintf(stderr, "CompleteAuthToken failed with %08X\n", ss);            return FALSE;         }      }      else {         fprintf (stderr, "CompleteAuthToken not supported.\n");         return FALSE;      }   }   *pcbOut = sbOut.cbBuffer;   if (!pAS->fInitialized)      pAS->fInitialized = TRUE;   *pfDone = !(ss == SEC_I_CONTINUE_NEEDED         || ss == SEC_I_COMPLETE_AND_CONTINUE );   return TRUE;}///////////////////////////////////////////////////////////////////////////////BOOL GenServerContext(PAUTH_SEQ pAS, PVOID pIn, DWORD cbIn, PVOID pOut,      PDWORD pcbOut, PBOOL pfDone) {/*++ Routine Description:    Takes an input buffer coming from the client and returns a buffer    to be sent to the client.  Also returns an indication of whether or    not the context is complete. Return Value:    Returns TRUE if successful; otherwise FALSE.--*/   SECURITY_STATUS ss;   TimeStamp       tsExpiry;   SecBufferDesc   sbdOut;   SecBuffer       sbOut;   SecBufferDesc   sbdIn;   SecBuffer       sbIn;   ULONG           fContextAttr;   if (!pAS->fInitialized)  {      ss = _AcquireCredentialsHandle(NULL, _T("NTLM"),            SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL, &pAS->hcred,            &tsExpiry);      if (ss < 0) {         fprintf(stderr, "AcquireCredentialsHandle failed with %08X\n", ss);         return FALSE;      }      pAS->fHaveCredHandle = TRUE;   }   // Prepare output buffer   sbdOut.ulVersion = 0;   sbdOut.cBuffers = 1;   sbdOut.pBuffers = &sbOut;   sbOut.cbBuffer = *pcbOut;   sbOut.BufferType = SECBUFFER_TOKEN;   sbOut.pvBuffer = pOut;   // Prepare input buffer   sbdIn.ulVersion = 0;   sbdIn.cBuffers = 1;   sbdIn.pBuffers = &sbIn;   sbIn.cbBuffer = cbIn;   sbIn.BufferType = SECBUFFER_TOKEN;   sbIn.pvBuffer = pIn;   ss = _AcceptSecurityContext(&pAS->hcred,         pAS->fInitialized ? &pAS->hctxt : NULL, &sbdIn, 0,         SECURITY_NATIVE_DREP, &pAS->hctxt, &sbdOut, &fContextAttr,         &tsExpiry);   if (ss < 0)  {      fprintf(stderr, "AcceptSecurityContext failed with %08X\n", ss);      return FALSE;   }   pAS->fHaveCtxtHandle = TRUE;   // If necessary, complete token   if (ss == SEC_I_COMPLETE_NEEDED || ss == SEC_I_COMPLETE_AND_CONTINUE) {      if (_CompleteAuthToken) {         ss = _CompleteAuthToken(&pAS->hctxt, &sbdOut);         if (ss < 0)  {            fprintf(stderr, "CompleteAuthToken failed with %08X\n", ss);            return FALSE;         }      }      else {         fprintf (stderr, "CompleteAuthToken not supported.\n");         return FALSE;      }   }   *pcbOut = sbOut.cbBuffer;   if (!pAS->fInitialized)      pAS->fInitialized = TRUE;   *pfDone = !(ss == SEC_I_CONTINUE_NEEDED         || ss == SEC_I_COMPLETE_AND_CONTINUE);   return TRUE;}///////////////////////////////////////////////////////////////////////////////BOOL WINAPI SSPLogonUser(LPTSTR szDomain, LPTSTR szUser, LPTSTR szPassword) {   AUTH_SEQ    asServer   = {0};   AUTH_SEQ    asClient   = {0};   BOOL        fDone      = FALSE;   BOOL        fResult    = FALSE;   DWORD       cbOut      = 0;   DWORD       cbIn       = 0;   DWORD       cbMaxToken = 0;   PVOID       pClientBuf = NULL;   PVOID       pServerBuf = NULL;   PSecPkgInfo pSPI       = NULL;   HMODULE     hModule    = NULL;   SEC_WINNT_AUTH_IDENTITY ai;   __try {      hModule = LoadSecurityDll();      if (!hModule)         __leave;      // Get max token size      _QuerySecurityPackageInfo(_T("NTLM"), &pSPI);      cbMaxToken = pSPI->cbMaxToken;      _FreeContextBuffer(pSPI);      // Allocate buffers for client and server messages      pClientBuf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbMaxToken);      pServerBuf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbMaxToken);      // Initialize auth identity structure      ZeroMemory(&ai, sizeof(ai));#if defined(UNICODE) || defined(_UNICODE)      ai.Domain = szDomain;      ai.DomainLength = lstrlen(szDomain);      ai.User = szUser;      ai.UserLength = lstrlen(szUser);      ai.Password = szPassword;      ai.PasswordLength = lstrlen(szPassword);      ai.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;#else      ai.Domain = (unsigned char *)szDomain;      ai.DomainLength = lstrlen(szDomain);      ai.User = (unsigned char *)szUser;      ai.UserLength = lstrlen(szUser);      ai.Password = (unsigned char *)szPassword;      ai.PasswordLength = lstrlen(szPassword);      ai.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;#endif      // Prepare client message (negotiate) .      cbOut = cbMaxToken;      if (!GenClientContext(&asClient, &ai, NULL, 0, pClientBuf, &cbOut, &fDone))         __leave;      // Prepare server message (challenge) .      cbIn = cbOut;      cbOut = cbMaxToken;      if (!GenServerContext(&asServer, pClientBuf, cbIn, pServerBuf, &cbOut,            &fDone))         __leave;         // Most likely failure: AcceptServerContext fails with SEC_E_LOGON_DENIED         // in the case of bad szUser or szPassword.         // Unexpected Result: Logon will succeed if you pass in a bad szUser and         // the guest account is enabled in the specified domain.      // Prepare client message (authenticate) .      cbIn = cbOut;      cbOut = cbMaxToken;      if (!GenClientContext(&asClient, &ai, pServerBuf, cbIn, pClientBuf, &cbOut,            &fDone))         __leave;      // Prepare server message (authentication) .      cbIn = cbOut;      cbOut = cbMaxToken;      if (!GenServerContext(&asServer, pClientBuf, cbIn, pServerBuf, &cbOut,            &fDone))         __leave;      fResult = TRUE;      {         HANDLE hToken = NULL;         if (_QuerySecurityContextToken(&asServer.hctxt, &hToken) == 0)         {            if (IsGuest(hToken))            {               printf("Logged in as Guest\n");               fResult = FALSE;            }            else               printf("Logged in as the desired user\n");            CloseHandle(hToken);         }      }   } __finally {      // Clean up resources      if (asClient.fHaveCtxtHandle)         _DeleteSecurityContext(&asClient.hctxt);      if (asClient.fHaveCredHandle)         _FreeCredentialsHandle(&asClient.hcred);      if (asServer.fHaveCtxtHandle)         _DeleteSecurityContext(&asServer.hctxt);      if (asServer.fHaveCredHandle)         _FreeCredentialsHandle(&asServer.hcred);      if (hModule)         UnloadSecurityDll(hModule);      HeapFree(GetProcessHeap(), 0, pClientBuf);      HeapFree(GetProcessHeap(), 0, pServerBuf);   }   return fResult;}//--------------------------------------------------------------------// The GetConsoleInput function gets an array of characters from the // keyboard, while printing only asterisks to the screen.void GetConsoleInput(TCHAR* strInput, int intMaxChars){	char ch;	char minChar = ' ';	minChar++;	ch = getch();	while (ch != '\r')	{		if (ch == '\b' && strlen(strInput) > 0)		{			strInput[strlen(strInput)-1]   = '\0';			printf("\b \b");		}		else if (ch >= minChar && (int)strlen(strInput) < intMaxChars)		{			strInput[strlen(strInput)+1] = '\0';			strInput[strlen(strInput)]   = ch;			putch('*');		}		ch = getch();	}	putch('\n');}void _tmain(int argc, TCHAR **argv){	TCHAR password[PWLEN+1];   if (argc != 3) 	{		_tprintf(_T("Usage: %s DomainName UserName\n"), argv[0]);		return;	}	_tprintf(_T("Enter password for the specified user : "));	password[0] = 0;	GetConsoleInput(password, PWLEN);	_tprintf(_T("\n"));   // argv[1] - Domain Name   // argv[2] - User Name   if (SSPLogonUser(argv[1], argv[2], password))   {      _tprintf(_T("User Credentials are valid\n"));   }   else      _tprintf(_T("User Credentials are NOT valid\n"));}
win95 win98 winnt winme win2000 winxp

Cảnh báo: Bài viết này đã được dịch tự động

Thuộc tính

ID Bài viết: 180548 - Xem lại Lần cuối: 08/20/2011 07:54:00 - Bản sửa đổi: 2.0

Microsoft Win32 Application Programming Interface

  • kbapi kbFAQ kbhowto kbkernbase kbsecurity kbmt KB180548 KbMtvi
Phản hồi