前回のSIDがAPIのCインタフェースでどうなっているのか。
Everyoneを表すSIDであるS-1-1-0、これはworldとも呼ばれるが、最初のS-1は固定、次の1がEveryoneを表すauthorityが以下のようにdefineされている。
1 |
#define SECURITY_WORLD_SID_AUTHORITY {0,0,0,0,0,1} |
以下のように定義する。
1 |
SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY; |
最後の0がEveryoneを表すRIDで以下のように定義されている。
1 |
#define SECURITY_WORLD_RID (0x00000000L) |
ここから内部表現であるSIDへのポインタPSIDを得るにはAllocateAndInitializeSidを使う。
1 2 3 4 |
AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pSIDEveryone)) |
第1引数がauthority
第2引数がsubauthorityの数で最大8個まで指定でき、全部引数で渡す。RIDはsubauthorityの一つのようだ。
最後の引数が結果のSIDが返る。SIDを使い終わったらFreeSidで解放する。
ここからACLを作成するにはSetEntriesInAclを使う。ACLはACEのリストでACEの中にSIDがある。
この関数は以下のように宣言されている。
1 2 3 4 5 6 7 8 9 |
WINADVAPI DWORD WINAPI SetEntriesInAclW( __in ULONG cCountOfExplicitEntries, __in_ecount_opt(cCountOfExplicitEntries) PEXPLICIT_ACCESS_W pListOfExplicitEntries, __in_opt PACL OldAcl, __out PACL * NewAcl ); |
この関数はEXPLICIT_ACCESSという構造体を渡す。以下のように宣言されている。
1 2 3 4 5 6 |
typedef struct _EXPLICIT_ACCESS { DWORD grfAccessPermissions; ACCESS_MODE grfAccessMode; DWORD grfInheritance; TRUSTEE Trustee; } EXPLICIT_ACCESS, *PEXPLICIT_ACCESS; |
grfAccessPermissionsはDWORDのビットマスクの変数で読み込みや書き込みなどを指定する。たとえば以下のような値を指定できる。
1 2 3 4 |
#define GENERIC_READ (0x80000000L) #define GENERIC_WRITE (0x40000000L) #define GENERIC_EXECUTE (0x20000000L) #define GENERIC_ALL (0x10000000L) |
grfAccessModeは許可、拒否をなどを指定する。以下のenumを使う。
1 2 3 4 5 6 7 8 9 10 |
typedef enum _ACCESS_MODE { NOT_USED_ACCESS = 0, GRANT_ACCESS, SET_ACCESS, DENY_ACCESS, REVOKE_ACCESS, SET_AUDIT_SUCCESS, SET_AUDIT_FAILURE } ACCESS_MODE; |
この2つがエクスプローラなどのファイルのセキュリティで表示されるものなのだろう。
grfInheritanceは継承関係を指定するがここではスルー、NO_INHERITANCE(=0)などを指定する。
TrusteeはTRUSTEE構造体、以下のように宣言されている。
1 2 3 4 5 6 7 |
typedef struct _TRUSTEE { PTRUSTEE pMultipleTrustee; MULTIPLE_TRUSTEE_OPERATION MultipleTrusteeOperation; TRUSTEE_FORM TrusteeForm; TRUSTEE_TYPE TrusteeType; LPTSTR ptstrName; } TRUSTEE, *PTRUSTEE; |
pMultipleTrusteeはNULL固定
MultipleTrusteeOperationはNO_MULTIPLE_TRUSTEE固定
TrusteeFormは最後の引数の型を指定する。TRUSTEE_IS_SID(=0)を指定してSIDを渡す。
TrusteeTypeは渡すSIDがユーザかグループかを指定するらしいが、これはSIDで指定されるはずなので重複な気がする。everyoneの場合はTRUSTEE_IS_WELL_KNOWN_GROUPを指定する。
ptstrNameでSIDを指定する。
OldAclは既存のACLに追加する場合に指定する。新しく作る場合はNULL。
NewAclに結果が返る。使い終わったらLocalFreeで解放する。
これでACLができたので、これをたとえばファイルに適用するにはSetNamedSecurityInfoを使う。詳細はスルー
C:\T\Test.txtをeveryoneでの読み書き許可を与えるには以下のコードになる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
#include <windows.h> #include <tchar.h> #include <Aclapi.h> int _tmain(int argc, _TCHAR* argv[]) { SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY; PSID pSIDEveryone = NULL; if(!AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pSIDEveryone)) { return 1; } TRUSTEE trustee = {0}; trustee.pMultipleTrustee = NULL; trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; trustee.TrusteeForm = TRUSTEE_IS_SID; trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; trustee.ptstrName = (LPTSTR)pSIDEveryone; EXPLICIT_ACCESS ea = {0}; ea.grfAccessPermissions = GENERIC_READ | GENERIC_WRITE; ea.grfAccessMode = GRANT_ACCESS; ea.grfInheritance = NO_INHERITANCE; ea.Trustee = trustee; PACL pACL = NULL; if(ERROR_SUCCESS != SetEntriesInAcl(1, &ea, NULL, &pACL)) { return 1; } if(ERROR_SUCCESS != SetNamedSecurityInfo( _T("C:\\T\\Test.txt"), SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, pACL, NULL)) { return 1; } LocalFree(pACL); FreeSid(pSIDEveryone); return 0; } |
ファイルのセキュリティをエクスプローラで見るとeveryoneが追加されているはず、vista以降は管理者権限が必要かもしれない。このコードは新規のACLを指定したにもかかわらず、ファイルのセキュリティには他のACLも表示されるが、これは継承しているためだと思われる。