线程权限

来源:互联网 发布:阿里天池杯 交通大数据 编辑:程序博客网 时间:2024/06/05 09:10

// AclMultiThreadTest.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <accctrl.h>
#include <aclapi.h>

#define ProcessWinErr(x) /
{/
 printf(x);/
 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL,GetLastError(),/
     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),buf,MAX_PATH,NULL);/
 printf(buf);/
 getchar();/
 return FALSE;/
}

DWORD theErr;

DWORD WINAPI Fun1Proc(LPVOID lpParameter)

 //测试前"D://123//"这个文件夹已经被限制到只有指定的用户能访问,用此方法测试文件是否存在。
 if( ::GetFileAttributes("D://123//DC2451-4.TPR") ==INVALID_FILE_SIZE )  
   theErr=GetLastError();

 ::SetEvent( (HANDLE)lpParameter );
 return FALSE;
};

int main(int argc, char* argv[])
{

 HANDLE hToken;
 char buf[MAX_PATH];
 DWORD dwSDLen;  
 PSECURITY_DESCRIPTOR pOrigSd = NULL;
 PSECURITY_DESCRIPTOR pNewSd = NULL;
 EXPLICIT_ACCESS ea={0};
 PACL pOldDAcl = NULL;
 PACL pNewDAcl = NULL;
 BOOL bDAcl;
 BOOL bDefDAcl;
 DWORD dwRet;
 PACL pSacl = NULL;
 DWORD dwAclSize = 0;
 DWORD dwSaclSize = 0;
 DWORD dwSidOwnLen = 0;
 DWORD dwSidPrimLen = 0;
 PSID pSidOwner = NULL;
 PSID pSidPrimary = NULL;

 //很多地方摘自http://www.whitecell.org/list.php?id=35
 if (!::LogonUser("ftest","fc214","q1w",LOGON32_LOGON_INTERACTIVE,LOGON32_PROVIDER_DEFAULT,&hToken)) 
  ProcessWinErr("LogonUser()");
  
 BuildExplicitAccessWithName(&ea, "Everyone", TOKEN_ALL_ACCESS, GRANT_ACCESS, 0);

 if ( !GetKernelObjectSecurity( hToken,
  DACL_SECURITY_INFORMATION,
  pOrigSd,
  0,
  &dwSDLen ) )
 {
  // 第一次调用给出的参数肯定返回这个错误,这样做的目的是
  // 为了得到原安全描述符 pOrigSd 的长度   
  if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER )
  {
   pOrigSd = ( PSECURITY_DESCRIPTOR ) HeapAlloc( GetProcessHeap(),
    HEAP_ZERO_MEMORY,
    dwSDLen );
   if ( pOrigSd == NULL )
    ProcessWinErr("Allocate pSd memory to failed!/n");
   
   // 再次调用才正确得到安全描述符 pOrigSd   
   if ( !GetKernelObjectSecurity( hToken,
    DACL_SECURITY_INFORMATION,
    pOrigSd,
    dwSDLen,
    &dwSDLen ) )    
    ProcessWinErr( "GetKernelObjectSecurity()" );    
  }
 }

 // 得到原安全描述符的访问控制列表 ACL
 if ( !GetSecurityDescriptorDacl( pOrigSd, &bDAcl, &pOldDAcl, &bDefDAcl ) )
  ProcessWinErr("GetSecurityDescriptorDacl()");

 // 生成新 ACE 权限的访问控制列表 ACL
 dwRet = SetEntriesInAcl( 1, &ea, pOldDAcl, &pNewDAcl );
 if ( dwRet != ERROR_SUCCESS )
 {   
  pNewDAcl = NULL;
  ProcessWinErr( "SetEntriesInAcl() ");
 };
 
 if ( !MakeAbsoluteSD(
  pOrigSd,
  pNewSd,
  &dwSDLen,
  pOldDAcl,
  &dwAclSize,
  pSacl,
  &dwSaclSize,
  pSidOwner,
  &dwSidOwnLen,
  pSidPrimary,
  &dwSidPrimLen ) )
  {
   // 第一次调用给出的参数肯定返回这个错误,这样做的目的是
   // 为了创建新的安全描述符 pNewSd 而得到各项的长度   
   if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER )
   {
    pOldDAcl = ( PACL ) HeapAlloc(  GetProcessHeap(), HEAP_ZERO_MEMORY, dwAclSize );
    pSacl = ( PACL ) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwSaclSize );
    pSidOwner = ( PSID ) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwSidOwnLen );
    pSidPrimary = ( PSID ) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwSidPrimLen );
    pNewSd = ( PSECURITY_DESCRIPTOR ) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwSDLen );
    
    if ( pOldDAcl == NULL ||
      pSacl == NULL ||
      pSidOwner == NULL ||
      pSidPrimary == NULL ||
      pNewSd == NULL )      
      ProcessWinErr( "Allocate SID or ACL to failed!/n" );
     
    // 再次调用才可以成功创建新的安全描述符 pNewSd
    // 但新的安全描述符仍然是原访问控制列表 ACL     
    if ( !MakeAbsoluteSD( pOrigSd,
     pNewSd,
     &dwSDLen,
     pOldDAcl,
     &dwAclSize,
     pSacl,
     &dwSaclSize,
     pSidOwner,
     &dwSidOwnLen,
     pSidPrimary,
     &dwSidPrimLen ) )     
      ProcessWinErr( "MakeAbsoluteSD()" );
   }
   else
   {
    ProcessWinErr( "MakeAbsoluteSD() = " );     
   }
 };
 // 将具有所有访问权限的访问控制列表 pNewDAcl 加入到新的
 // 安全描述符 pNewSd 中  
 if ( !SetSecurityDescriptorDacl( pNewSd, bDAcl, pNewDAcl, bDefDAcl ) )
  ProcessWinErr("SetSecurityDescriptorDacl()" );

 if(! ImpersonateLoggedOnUser(hToken) )
  ProcessWinErr("ImpersonateLoggedOnUser");
 SECURITY_ATTRIBUTES sa={0};
 sa.nLength=dwSDLen;
 sa.lpSecurityDescriptor=pNewSd;
 sa.bInheritHandle=FALSE;

 
 HANDLE hEvt=::CreateEvent(&sa,FALSE,FALSE,NULL);
 if(!hEvt)
  ProcessWinErr("CreateEvent()");

 printf("Starting Wait.../n");
 HANDLE thread1;
 for(int idx=0;idx<50;idx++)//试试这个方法是否可靠,结果可靠的“拒绝访问”...
 {
  printf("Time%d/n",idx);
  theErr=0; 
  thread1=::CreateThread(&sa,0,Fun1Proc,hEvt,0,NULL);
  if(!thread1)
   ProcessWinErr("CreateThread()");
  
  ::WaitForSingleObject(hEvt,INFINITE);
  CloseHandle(thread1);
  
  if( theErr!=0 )
  {
   theErr=0;  
   thread1=::CreateThread(&sa,0,Fun1Proc,hEvt,0,NULL);
   if(!thread1)
    ProcessWinErr("CreateThread()");   
   ::WaitForSingleObject(hEvt,INFINITE);

   if( theErr!=0 )
   {
    FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL,theErr,
     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),buf,MAX_PATH,NULL);
    printf(buf);
   };
   CloseHandle(thread1);
  };
  

 };
 
 printf("Wait OK./n");

 CloseHandle(hEvt); 
 CloseHandle(hToken);
 if ( pOrigSd )
 {
   HeapFree( GetProcessHeap(), 0, pOrigSd );
 }  

 getchar();
 return 0;
}