フォルダのアクセス権について(2006/06/02)
https://www.petitmonte.com/bbs/answers?question_id=4002
これの続きです( もう3年も前の話で、とても古いけど)
ママんさんのコードがだめだったのは、参照したいフォルダに新たに設定された
アクセス許可エントリしか取得できず、上位フォルダから継承されたもアクセス
許可エントリが取得できなかったため。
GetNamedSecurityInfo の引数を変えてやれば取得できたかもしれませんが、
今回Vista の UAC対策に、もうちょっと突っ込んでやってみました。
※ 今回、特に参考にした資料
フォルダのアクセス権チェック方法について
http://social.msdn.microsoft.com/forums/ja-JP/vcgeneralja/thread/a4225c57-ebc3-4808-8464-dc731548ab99/
アクセスコントロール / アクセスチェック
http://eternalwindows.jp/security/accesscontrol/accesscontrol04.html
主な宣言
var
hToken,
hTokenImpersonatation:THandle;
dwTokenUserLength: DWORD;
pTokenUser: ^TSIDAndAttributes;
pSecurityDescriptor: PSECURITY_DESCRIPTOR;
pDACL: PACL;
細かいとこはSDKとか読んでください。
また、NT系のみ、2000以降のみとかAPIも使っているかもしれませんが、
それもSDKとかで確認してください。
1) GetVolumeInformationを使って NTFS か判定する。
これは、上記の質問内にコードが含まれています。
2) GetNamedSecurityInfo を使用して、セキュリティ記述子を取得する
if GetNamedSecurityInfo(PChar("調査フォルダ"),
SE_FILE_OBJECT,
OWNER_SECURITY_INFORMATION or GROUP_SECURITY_INFORMATION or
DACL_SECURITY_INFORMATION, // 取得するセキュリティ情報のタイプ
nil, nil, @pDACL, nil,
pSecurityDescriptor) = 0 then //成功
3) 自プロセスのトークンを取得する
NT, 2000, XP とかなら、フォルダのアクセス権がそのまま、自分のアクセス権に
なりますが、VistaのUACの存在が、ユーザー権限で動作を行うため、アカウントの
アクセス権では判定できないのです(たぶん)。
OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY or TOKEN_DUPLICATE, htoken)
4) トークン情報を取得する
「AccessCheckに指定するトークンは偽装トークンでなければならないため」
(By 参考資料に二つ目のリンクより一部抜粋)
ということで、トークンを取得して、偽装トークンに複製する必要があります。
そのための準備
//1回目で情報のサイズを取得し
GetTokenInformation(hToken, TokenUser, nil, 0, dwTokenUserLength);
//メモリ確保
pTokenUser := GetMemory(dwTokenUserLength)
//ここで本当にトークン情報を取得する
GetTokenInformation(hToken, TokenUser, pTokenUser,
dwTokenUserLength, dwTokenUserLength);
5) 偽装トークンに複製
DuplicateTokenEx(hToken, GENERIC_ALL, nil, SecurityImpersonation,
TokenImpersonation, hTokenImpersonatation)
6) アクセス許可の判定
{アクセス権の調査}
var
genericMapping: TGenericMapping;
dwDesiredAccess: Cardinal;
dwSize: Cardinal;
privilegeSet: TPrivilegeSet;
dwGrantedAccess: DWORD;
accessStatus: LongBool;
begin
{初期化}
FillChar(genericMapping, SizeOf(TGenericMapping), 0);
//この FILE_GENERIC_READ, FILE_GENERIC_WRITE 定数については
//Delphiのユニットには含まれていない可能性が高いので
//Googleさんなどで検索してくださいな
//読み込み可能であるか調べる場合
//dwDesiredAccess := FILE_GENERIC_READ;
//書き込み可能であるか調べる場合
dwDesiredAccess := FILE_GENERIC_WRITE;
{調査するアクセス権のマッピングを用意}
genericMapping.GenericRead := FILE_GENERIC_READ;
genericMapping.GenericWrite := FILE_GENERIC_WRITE;
genericMapping.GenericExecute := FILE_GENERIC_EXECUTE;
genericMapping.GenericAll := FILE_ALL_ACCESS;
{アクセスマスク内の汎用のアクセス権を、特定の標準的なアクセス権にマップする}
MapGenericMask(dwDesiredAccess, genericMapping);
{初期化}
dwSize := SizeOf(PRIVILEGE_SET);
privilegeSet.PrivilegeCount := 0;
{アクセス トークンによって識別されたクライアントに対して、
指定されたアクセス権利セットを、セキュリティ記述子が許可しているか
どうかを調べます。通常、サーバーアプリケーションはこの関数を使って、
プライベートオブジェクトへのアクセスを確認します。}
if AccessCheck(pSecurityDescriptor, hTokenImpersonatation,
dwDesiredAccess, genericMapping, privilegeSet, dwSize,
dwGrantedAccess, accessStatus) then begin
if accessStatus then //アクセス許可されています
else //アクセス許可されていません
end
else begin
//アクセス権の取得に失敗
end;
end;
以上で、Vista,Sevenでも、UACが有効で、ユーザー権限で動作中のアクセス権と、
admin権限での動作のアクセス権が判定できると思います。
一応、XP SP2、Vista UAC オンの通常起動、Vista UAC オンのadmin権限起動で
フォントフォルダのアクセス権の判定がうまくいっています。
ソースを完全掲載じゃないので、足りないトコは自分で調べてください m(v_v)m
ツイート | ![]() |