题目中的Windows凭据(Credential)其实就是指用户帐户和口令。最近项目中存在一台Windows(PC)机去管理服务器(Server),这之中就设计到服务器管理员权限的问题。需要用户对Windows上存储的用户名和密码进行管理。

       在Windows XP和Server 2003 中都已存在了“存储的用户名和密码”。在XP中,通过控制面板中的用户帐户-〉选择用户-〉管理我的网络密码。而在Server 2003中,则在控制面板下直接有“存储的用户名和密码”项。

       我们调用一些API,如WTSOpenServer,QueryServiceStatus,NetUserEnum等等涉及到RPC的,只要当前用户存储有目标远程机的权限合适的凭据,则这些API就不会因产生ERROR_ACCESS_DENIED而执行失败。因为我还不Windows的底层是如何进行控制的,比如,是否调用了SSPI,所以,执行这些API时,我只能向用户要管理员口令。但又不可能每次都让用户去输入一遍用户名和密码,那么,也就需要保存密码。

       既然保存了密码,就必须考虑删除密码,那么密码管理的问题也就来了。说到密码管理,我在前些年看电视的时候,看到介绍一个叫什么“网络螃蟹”的网站,他就是专门提供个人密码管理的,当时我就想,有人会去把自己的密码交给别人打理吗?这好像不大可能。后来也就没听到什么网络螃蟹横行的消息。

       现在我的项目中,如果用户有了一台机器(PC)的密码,那么,他就有了N台服务器的管理员权限。这当然是不被允许的了。怎么办?

       找了一些API,是Authentication Functions系列的。于是,下面一个小实验代码就是想来枚举用户凭据的。

#include <windows.h>
#include 
<WinCred.h>
int main(){

  DWORD dwCount 
= 0;
  PCREDENTIAL 
* pCredArray = NULL ;

  
if( CredEnumerate( NULL, 0&dwCount, &pCredArray ) ){

    
for( DWORD dwIndex = 0; dwIndex < dwCount; dwIndex++){
      PCREDENTIAL pCredential 
= pCredArray[dwIndex];

      cout 
<< "*********************************\r\n";

      cout
<<  "Flags: " << pCredential->Flags << "\n"
          
<<  "Type:  " <<  pCredential->Type << "\n"
          
<<  "Name:  " << pCredential->TargetName << "\n"
          
<<  "Persist: "<< pCredential->Persist  <<  "\n"
          
<<  "User:  " <<  pCredential->UserName <<  "\n";

      cout 
<< "Data:  \r\n";

      
char szHexBuffer[256= "";
      
char szAsciiBuffer[256= "";
      
char szHex[16];
      
char szAscii[2];
      DWORD dwByte;

      
for (dwByte = 0; dwByte < pCredential->CredentialBlobSize; dwByte++)
      
{
        BYTE byte1 
= pCredential->CredentialBlob[dwByte];
        sprintf(szHex, 
"%2.2X ", byte1);
        szAscii[
1= '\0';

        
if (byte1 >= 32 && byte1 < 128)
          szAscii[
0= (UCHAR)byte1;
        
else
          szAscii[
0= ' ';

        strcat(szHexBuffer, szHex);
        strcat(szAsciiBuffer, szAscii);

        
if (dwByte == pCredential->CredentialBlobSize - 1 
          
|| dwByte % 16 == 15)
        
{
          printf(
"%-50s %s\r\n", szHexBuffer, szAsciiBuffer);
          szHexBuffer[
0= '\0';
          szAsciiBuffer[
0= '\0';
        }


      }


      cout 
<< "*********************************\r\n";

    }


    CredFree( pCredArray );
  }

  
//system( "rundll32 keymgr.dll,KRShowKeyMgr");
  return 0;
}

      好像凭据数据还没能打出来。

       后来,本着“编程的最高境界就是不编程”的精神,我想,如果直接把Windows的那个“存储的用户名和密码”对话框调出来用用不也可以吗。用ProcessExplorer,找到一个叫keymgr.dll的东西,嗯,估计对话框就在里面。

       在“运行”中输入“control keymgr.dll”或“rundll32 keymgr.dll,KRShowKeyMgr”,对话框就出来了。
       又省事了!