目錄服務對象?;顒幽夸浄战涌冢?/span>
ADSI
)包括創建和修改
ACL
內容的程序。更多信息參見:控制訪問活動目錄對象。
ACE
一個訪問控制實體(ACE)是ACL中的一個元素。一個ACL可能包含0到多個ACE。每個ACE通過一個指定的托管來控制或監視一個對象。更多關于添加、刪除、改變ACE,見修改ACL對象。
Window Me/98/95:不支持訪問控制
有6種類型的ACE,三種被所有的安全對象支持,其他類型是對象特定的ACE,由目錄服務對象支持。
所有ACE類型都包含下面訪問控制信息:
1.? 一個安全標示符號(SID)來標示ACE應用的托管
2.? 一個訪問掩碼指定ACE控制的訪問權限
3.? 一個指示ACE類型的標志位
4.? 一系列位標志決定是否子容器或對象可以繼承ACE從基本對象到ACL附著的對象。
下表列出了三個所有安全對象支持的ACE類型:
Type | Description |
訪問拒絕ACE | 用在一個DACL中拒絕到一個托管的訪問權限 |
訪問允許ACE | 用在一個DACL中允許到托管的訪問權限 |
系統評估ACE | 用在SACL中,當托管嘗試檢查指定訪問權限時產生一個評估記錄 |
對于對象指定的ACE,參見對象指定ACE。
注意,系統警告ACE對象現在不支持。
托管
一個托管是一個用戶帳戶、組帳戶或登錄會話到一個ACE應用。每個ACL中的ACE都有一個SID來標示托管。用戶帳戶包含人使用的帳戶或程序帳戶(例如,Window服務用來登錄到本地計算機的)。組帳戶不能用來登錄到計算機,但在ACE中非常有用,用來拒絕或允許一到多個用戶帳戶的訪問權限。一個登錄SID表示當前的登錄會話用來允許和拒絕訪問權限,直到用戶登出。
NT4.0和后來版本中訪問控制函數使用TRUSTEE結構體來表示一個托管。這個結構體能使你用一個字符串或一個SID來表示一個托管。如果你使用一個名字,從TRUSTEE結構創建ACE的函數執行SID緩沖區分配工作并且查詢SID對應的帳戶名稱。有兩個助手函數,BuildTrusteeWithSid和BuildTrusteeWithName,可以用SID或名字來初始化一個TRUSTEE結構。BuildTrusteeWithObjectsAndSid和BuildTrusteeWithObjectsAndName允許你使用一個對象指定的ACE信息來初始化一個TRUSTEE結構體。其他3個助手函數,GetTrusteeFrorm、GetTrusteeName和GetTrusteeType,返回TRUSTEE結構各成員的值。
Window XP/2000:TRUSTEE的ptstrName成員可以是一個指向OBJECTS_AND_NAME或OBJECTS_AND_SID結構體的指針。這些結構體說明對象指定ACE的信息,除了托管的名字和SID之外。這可以象SetEntriesInAcl和GetExplicitEntriesFromAcl這樣的函數存儲對象指定ACE的信息到EXPLICIT_ACCESS結構體的Trustee成員中。
TRUSTEE結構體:
typedef struct _TRUSTEE {
? PTRUSTEE pMultipleTrustee;
? MULTIPLE_TRUSTEE_OPERATION MultipleTrusteeOperation;
? TRUSTEE_FORM TrusteeForm;
? TRUSTEE_TYPE TrusteeType;
? LPTSTR ptstrName;
} TRUSTEE, *PTRUSTEE;
訪問權限和訪問掩碼
?
一個訪問權限是一個標志位對應到一個特殊操作集合,這個集合表示線程可以在安全對象上執行的操作。例如:注冊表鍵KEY_SET_VALUE訪問權限,對應到線程在這個鍵下設置的值的能力。如果線程想在一個對象執行一個操作,但沒有必要的訪問權限,系統不執行操作。
一個訪問掩碼是一個32位的值,它對應到對象支持的訪問權限。所有的Windows NT/2000/XP 安全對象使用一個Windows訪問掩碼格式,這個格式包含下面的訪問權限位:
1.? 通用訪問權限
2.? 標準訪問權限
3.? SACL訪問權限
4.? 目錄服務訪問權限
當一個線程想打開一個對象的句柄,線程通常指定一個訪問掩碼來請求一系列的訪問權限。例如,需要設置和查詢注冊表鍵的程序可以使用一個訪問掩碼來請求KEY_SET_VALUE和KEY_QUERY_VALUE訪問權限來打開該鍵。
下面表顯示了操作每種類型安全對象的信息:
對象類型 | 安全描述符號函數 |
NTFS上的文件或目錄系統 | GetNamedSecurityInfo, SetNamedSecurityInfo, GetSecurityInfo, SetSecurityInfo |
命名管道和匿名管道 | GetSecurityInfo, SetSecurityInfo |
控制臺屏幕緩沖區 | Not supported. |
進程和線程 | GetSecurityInfo, SetSecurityInfo |
文件映射對象 | GetNamedSecurityInfo, SetNamedSecurityInfo, GetSecurityInfo, SetSecurityInfo |
Access tokens | SetKernelObjectSecurity, GetKernelObjectSecurity |
Windows管理對象 (windows工作站和桌面) | GetSecurityInfo, SetSecurityInfo |
注冊表鍵 | GetNamedSecurityInfo, SetNamedSecurityInfo, GetSecurityInfo, SetSecurityInfo |
Windows服務 | GetNamedSecurityInfo, SetNamedSecurityInfo, GetSecurityInfo, SetSecurityInfo |
本地和遠程打印機 | GetNamedSecurityInfo, SetNamedSecurityInfo, GetSecurityInfo, SetSecurityInfo |
網絡共享 | GetNamedSecurityInfo, SetNamedSecurityInfo, GetSecurityInfo, SetSecurityInfo |
進程間同步對象 (事件, mutexes, semaphores, and waitable timers) | GetNamedSecurityInfo, SetNamedSecurityInfo, GetSecurityInfo, SetSecurityInfo |
作業對象 | GetNamedSecurityInfo, SetNamedSecurityInfo, GetSecurityInfo, SetSecurityInfo |
?
通用訪問權限
安全對象使用Windows 訪問掩碼格式,四個高位說明通用訪問權限。每個安全對象類型映射到這些位到一系列標準和對象特殊訪問權限。例如:一個Window文件對象映射GENERIC_READ位到READ_CONTROL和SYNCHRONIZE 標準訪問權限和FILE_READ_DATA、FILE_READ_EA和FILE_READ_ATTRIBUTES對象指定訪問權限。其他類型對象映射GENERIC_READ位到與類型對象適應的一些訪問權限。
你可以在你打開一個對象句柄的時候使用通用訪問權限來指定需要的訪問類型;這通常比指定所有對應標準和特指權限要簡單。
下表顯示了通用訪問權限定義的常量。
常量 | 解釋 |
GENERIC_ALL | 讀、寫和執行訪問 |
GENERIC_EXECUTE | 執行 |
GENERIC_READ | 讀 |
GENERIC_WRITE | 寫 |
應用程序定義的私有安全訪問對象能使用通用訪問權限。
安全描述符
安全描述符包含了安全對象相關的安全信息。安全描述父由一個SECURITY_DESCRIPTOR結構體組成,它關聯到一個安全對象。一個安全描述符包含下面的安全信息:
1.? 擁有者或基本組對象的安全ID(SIDs)
2.? DACL指定特殊用戶或組的允許或拒絕的訪問權限
3.? SACL指定對象通用評估記錄嘗試的訪問類型
4.? 一個控制位集合,說明安全描述符的含義或它每個成員
程序不需要直接操作安全描述符的內容。Windows API提供設置和返回安全描述符號的函數。另外,有用來創建和初始化一個新對象安全描述符號的函數。
?
Windows NT 3.51和更早的版本,Windows ME/98/95:參見:低級訪問控制。
?
工作在活動目錄對象上安全描述符程序能使用Windows的安全函數或ADSI(活動目錄服務接口)提供的安全接口。更多ADSI的信息參見:訪問控制如何在活動目錄中工作?
DACL是怎么控制訪問對象的?
當一個線程想訪問一個安全對象時候,系統要么允許訪問,要拒絕訪問。如果對象沒有DACL,系統賦予訪問權限,否則系統查找DACL中的該線程的ACE。每個對象DACL中的ACE指定托管的訪問允許或拒絕的訪問權限,它可以是一個用戶帳戶、組帳戶或登錄會話。
?
系統比較ACE中的托管和線程訪問標記的托管標示。一個訪問標記包含SID來說明用戶和用戶輸入的組帳戶。一個標記也包含一個登錄SID,來表示當前的登錄會話。在訪問檢查期間,系統忽略不可用的組SID。更多可用不可用信息以及拒絕SID,見訪問標記中的SID屬性。
通常,系統使用現成餓基本訪問標記來請求訪問。然而,如果現成正在扮演其他用戶,系統使用現成的扮演標記。
系統家產序列中的每個ACE,直到下面的情況發生:
1.? 一個顯式拒絕任何與線程訪問標記中列出托管不同的訪問ACE出現
2.? 線程訪問標記中列出的一個或多個允許訪問的ACE出現,這個標記顯式賦予所有權限。
3.? 所有的ACE都檢查過,并且至少一個訪問權限沒有顯式的允許,這種情況下暗示拒絕。
下圖描述一個DACL對象允許訪問一個線程而拒絕訪

問另一個線程。
對于線程A,系統讀ACE1并且立即拒絕訪問,因為訪問拒絕ACE應用到線程訪問標記中的用戶。這種情況下,系統并沒有檢查ACE2和3。對于線程B,ACE1沒有應用,因此系統處理ACE2,其允許寫操作,并且ACE3允許讀和執行操作。
因為系統在請求訪問并顯式允許或拒絕的時候停止檢查,DACL中的ACE順序非常重要。注意,如果ACE順序與例子中的不同,系統可能分配訪問權限給A。對于系統對象,操作系統定義一個首選的DACL中ACE的順序。
創建一個DACL
創建適當的
DACL
是你程序開發中必要和重要的,因為一個
NULL DACL
允許所有用戶所有訪問權限,不要使用
NULL DACL
。
下面例子演示了如何正常創建一個
DACL
。例子,包含一個函數,
CreateMyDACL
,用安全描述符定義語言(
SDDL
)來定義那些賦予的和拒絕的
DACL
中的訪問控制。為了提供對你程序對象的不同訪問,根據你的需要來修改
CreateMyDACL
。
在例子中:
1.??????
main
函數傳遞一個
SECURITY_ATTRIBUTES
結構體的地址給
CreateMyDACL
函數
2.??????
CreateMyDACL
函數使用
SDDL
字符串來:
2???????
拒絕
guest
和匿名登錄用戶訪問
2???????
允許授權用戶的讀
/
寫
/
執行訪問
2???????
允許管理員所有控制
3.??????
更多的
SDDL
字符串格式
4.??????
CreateMyDACL
函數調用
ConvertStringSecurityDescriptorToSecurityDescriptor
函數轉換
SDDL
字符串為一個安全描述符。安全描述符號通過
SECURITY_ATTRIBUTES
結構體的
lpSecurityDescriptor
成員來指定。
CreateMyDACL
發送
ConvertStringSecurityDescriptorToSecurityDescriptor
的返回值給
main
函數。
5.??????
main
函數完成使用
SECURITY_ATTRIBUTES
結構體時,
main
函數釋放
lpSecurityDescriptor
成員的內存,調用
LocalFree
函數來完成。
注意,成功編譯
SDDL
函數,例如:
ConvertStringSecurityDescriptorToSecurityDescriptor,
你必須定義
_WIN32_WINNT
常量為
0x0500
或更大。
SDDL
在
Windows 2003
家族
,Windows XP
和
2000
操作系統上可用。


?1
#define?_WIN32_WINNT?0x0500
?2
?3
#include?<windows.h>
?4
#include?<sddl.h>
?5
#include?<stdio.h>
?6
?7
BOOL?CreateMyDACL(SECURITY_ATTRIBUTES?*);
?8
?9
void?main()
10

{
11
?????SECURITY_ATTRIBUTES??sa;
12
?????sa.nLength?=?sizeof(SECURITY_ATTRIBUTES);
13
?????sa.bInheritHandle?=?FALSE;??
14
?????//?Call?function?to?set?the?DACL.?The?DACL
15
?????//?is?set?in?the?SECURITY_ATTRIBUTES?
16
?????//?lpSecurityDescriptor?member.
17
?????if?(!CreateMyDACL(&sa))
18
?????
{
19
?????????//?Error?encountered;?generate?message?and?exit.
20
?????????printf("Failed?CreateMyDACL\n");
21
?????????exit(1);
22
?????}
23
24
?????//?Use?the?updated?SECURITY_ATTRIBUTES?to?specify
25
?????//?security?attributes?for?securable?objects.
26
?????//?This?example?uses?security?attributes?during
27
?????//?creation?of?a?new?directory.
28
?????if?(0?==?CreateDirectory(TEXT("C:\\MyFolder"),?&sa))
29
?????
{
30
?????????//?Error?encountered;?generate?message?and?exit.
31
?????????printf("Failed?CreateDirectory\n");
32
?????????exit(1);
33
?????}
34
35
?????//?Free?the?memory?allocated?for?the?SECURITY_DESCRIPTOR.
36
?????if?(NULL?!=?LocalFree(sa.lpSecurityDescriptor))
37
?????
{
38
?????????//?Error?encountered;?generate?message?and?exit.
39
?????????printf("Failed?LocalFree\n");
40
?????????exit(1);
41
?????}
42
}
43
44
45
//?CreateMyDACL.
46
//????Create?a?security?descriptor?that?contains?the?DACL?you?want.
47
//????This?function?uses?SDDL?to?make?Deny?and?Allow?ACEs.
48
//
49
//?Parameter:
50
//????SECURITY_ATTRIBUTES?*?pSA
51
//????Pointer?to?a?SECURITY_ATTRIBUTES?structure.?It?is?the?caller's
52
//????responsibility?to?properly?initialize?the?structure?and?to?free?
53
//????the?structure's?lpSecurityDescriptor?member?when?the?caller?has
54
//????finished?using?it.?To?free?the?structure's?lpSecurityDescriptor?
55
//????member,?call?the?LocalFree?function.
56
//?
57
//?Return?value:
58
//????FALSE?if?the?address?to?the?structure?is?NULL.?
59
//????Otherwise,?this?function?returns?the?value?from?the
60
//????ConvertStringSecurityDescriptorToSecurityDescriptor?function.
61
BOOL?CreateMyDACL(SECURITY_ATTRIBUTES?*?pSA)
62

{
63
?????//?Define?the?SDDL?for?the?DACL.?This?example?sets?
64
?????//?the?following?access:
65
?????//?????Built-in?guests?are?denied?all?access.
66
?????//?????Anonymous?logon?is?denied?all?access.
67
?????//?????Authenticated?users?are?allowed?read/write/execute?access.
68
?????//?????Administrators?are?allowed?full?control.
69
?????//?Modify?these?values?as?needed?to?generate?the?proper
70
?????//?DACL?for?your?application.?
71
?????TCHAR?*?szSD?=?TEXT("D:")???????//?Discretionary?ACL
72
????????TEXT("(D;OICI;GA;;;BG)")?????//?Deny?access?to?built-in?guests
73
????????TEXT("(D;OICI;GA;;;AN)")?????//?Deny?access?to?anonymous?logon
74
????????TEXT("(A;OICI;GRGWGX;;;AU)")?//?Allow?read/write/execute?to?authenticated?users
75
????????TEXT("(A;OICI;GA;;;BA)");????//?Allow?full?control?to?administrators
76
77
????if?(NULL?==?pSA)
78
????????return?FALSE;
79
?????return?ConvertStringSecurityDescriptorToSecurityDescriptor(
80
????????????????szSD,
81
????????????????SDDL_REVISION_1,
82
????????????????&(pSA->lpSecurityDescriptor),
83
????????????????NULL);
84
}
85
可保安全對象
一個安全對象有一個安全描述符。所有有名字的
Windows
對象都是安全的。有些沒有名字的對象,例如:進程和線程對象也有安全描述符。對于大多數安全對象來說,你可以在創建對象的時候指定一個對象的安全描述符。例如:你能在
CreateFile
和
CreateProcess
函數中指定安全描述符。
另外,
Windows
安全函數是你能夠為操作系統創建的而不是
Windows
創建的安全對象得到和設置安全信息。
Windows
安全函數也提供支持私有使用安全描述符和程序定義對象。更多關于私有安全對象信息參見客戶服務器訪問控制。
?
每個安全對象定義它自己的一系列訪問權限,并且它擁有的映射通用訪問權限。更多關于指定和通用訪問權限的信息,參見對象類型總覽。
下表顯示了函數來操作通用安全對象的安全信息:
對象類型
|
安全描述符函數
|
NTFS文件系統的文件和目錄
|
GetNamedSecurityInfo
, SetNamedSecurityInfo, GetSecurityInfo, SetSecurityInfo
|
Named pipes
Anonymous pipes
|
GetSecurityInfo
, SetSecurityInfo
|
Processes
Threads
|
GetSecurityInfo
, SetSecurityInfo
|
File-mapping objects
|
GetNamedSecurityInfo
, SetNamedSecurityInfo, GetSecurityInfo, SetSecurityInfo
|
Access tokens
|
SetKernelObjectSecurity
, GetKernelObjectSecurity
|
Window-management objects ( window stations and desktops)
|
GetSecurityInfo
, SetSecurityInfo
|
Registry keys
|
GetNamedSecurityInfo
, SetNamedSecurityInfo, GetSecurityInfo, SetSecurityInfo
|
Windows services
|
GetNamedSecurityInfo
, SetNamedSecurityInfo, GetSecurityInfo, SetSecurityInfo
|
Local or remote printers
|
GetNamedSecurityInfo
, SetNamedSecurityInfo, GetSecurityInfo, SetSecurityInfo
|
Network shares
|
GetNamedSecurityInfo
, SetNamedSecurityInfo, GetSecurityInfo, SetSecurityInfo
|
Interprocess synchronization objects (events, mutexes, semaphores, and waitable timers)
|
GetNamedSecurityInfo
, SetNamedSecurityInfo, GetSecurityInfo, SetSecurityInfo
|
Job objects
|
GetNamedSecurityInfo
, SetNamedSecurityInfo, GetSecurityInfo, SetSecurityInfo
|
Directory service objects
|
These objects are handled by Active Directory Objects. See Active Directory Service Interfaces.
|
?
登錄會話
一個登錄繪畫從用戶登錄到計算機時候開始。所有登錄會話中的進程有相同的基本訪問標記。訪問標記包含登錄會話相關的安全上下文,包含用戶的
SID
和登錄標示以及登錄
SID
。
?
登錄
SID
?
一個安全標示符(
SID
)用來表示登錄會話。你可以使用
DACL
中的登錄
SID
來在登錄會話過程中控制訪問。登錄
SID
只有在用戶登出的時候無效。登錄
SID
是計算機運行的時候唯一的。沒有其他會話有系統的
SID
。然而,可能的登錄
SID
集合在計算機啟動的時候被復位。為了從訪問標記中返回登錄
SID
,為
TokenGroups
調用
GetTokenInformation
函數。
?
訪問標記
?
一個訪問標記包含登錄會話的安全信息。系統在用戶登錄的時候創建一個安全標記,每個進程執行用戶由于的標記副本。標記表示用戶、用戶組和用戶權限。系統使用標記來控制訪問安全對象和控制用戶在本地計算機上執行各種系統相關操作。兩種訪問標記:私有的和偽裝的。
?
偽裝標記:
?
一個被創建來捕獲客戶進程安全信息、允許服務器在安全操作中偽裝客戶進程的訪問標記。
?
主標記:
一個
Windows
內核創建的標記。可能分配給一個進程來表示默認的進程安全信息。