- PR -

C#.NETよりフォルダのアクセス権限の変更

1
投稿者投稿内容
kirua
常連さん
会議室デビュー日: 2006/05/30
投稿数: 31
投稿日時: 2006-07-31 20:22
以下のオペレーションをすると、エクスプローラのフォルダ ⇒ プロパティ ⇒ セキュリティタブのユーザに不明なID(S-1-5-21…)と表示されます。

*1 エクスプローラのフォルダ ⇒ プロパティ ⇒ セキュリティタブ

@ AというユーザをActiveDirectoryに登録
A AというユーザをActiveDirectoryから削除
B AというユーザをActiveDirectoryに登録
とした場合に

(1) @を行ってからWEBアプリ上でXCACLSを使用して
   あるフォルダにユーザ:Aの権限を付与。
*1で確認すると正しくユーザ:Aに対してアクセス権限が付与されます。

(2) Bを行ってから(1)と同様なことを行うと、
   *1で確認した内容が不明なID(S-1-5-21…)と表示されます。

プログラム以外の対応で以下の通り行うと解決できます。
1. Aを行った後に、IISを再起動しBを行う
2. Aを行った後に、プログラムをリビルドしBを行う

これをプログラムで行うにはどのようにするのでしょうか?
ご教授お願い致します。

参考までに
※ユーザの登録方法
{
ArrayList arNewArrayList;

// コンテナチェック
if (adeContainer == null)
{
// コンテナオブジェクト生成
adeContainer = new DirectoryEntry(ContainerPath,ADirUserId,
ADirUserPasswd);
}

try
{
// グループリスト数分繰り返しながらADユーザーを追加する。
foreach(string strGroupName in ahtAddMemberToGroup.Keys)
{
arNewArrayList = new ArrayList();
// コンテナからグループオブジェクト検索
DirectoryEntry deGroup = adeContainer.Children.Find("CN="+strGroupName, "group");
if (deGroup != null)
{
// グループオブジェクトが存在する場合ユーザー追加処理を行う。
ArrayList tmpArrayList = (ArrayList) ahtAddMemberToGroup[strGroupName];

// 追加するユーザー名リストからユーザー区別者リストを再作成する。
foreach (string strMemberName in tmpArrayList)
{
DirectorySearcher dsrResult = new DirectorySearcher();
dsrResult.SearchRoot = adeContainer;
dsrResult.Filter = "(samaccountname=" + strMemberName + ")";
dsrResult.SearchScope = SearchScope.Subtree;
dsrResult.PropertiesToLoad.Add("distinguishedname");
SearchResult serResult = dsrResult.FindOne();

if (serResult != null)
{
arNewArrayList.Add(serResult.Properties["distinguishedname"][0].ToString());
}
dsrResult.Dispose();
}

// 該当グループに追加するユーザー数分繰り返しながら追加処理を行う。
foreach(string strMemberDistinguishedName in arNewArrayList)
{
deGroup.Properties["member"].Add(strMemberDistinguishedName);
}
// 変更コミット
deGroup.CommitChanges();
}
deGroup.Dispose();
}
}

※ユーザー削除
public void DeleteIfExists(DirectoryEntry adeContainer, string astrUserName)
{
try
{
// コンテナチェック
if (adeContainer == null)
{
// コンテナオブジェクト生成
adeContainer = new DirectoryEntry(ContainerPath, ADirUserId, ADirUserPasswd);
}

// コンテナからユーザーオブジェクト検索
DirectoryEntry deUser = adeContainer.Children.Find("CN="+astrUserName, "user");

if (deUser != null)
{
// ユーザーオブジェクト削除
adeContainer.Children.Remove(deUser);
// 変更コミット
adeContainer.CommitChanges();
deUser.Dispose();
}
adeContainer.Dispose();
}
catch (Exception ex)
{
string strErrMsg = "ユーザー削除時、エラーが発生しました。";
string strParam = "ユーザー名=" + astrUserName;
throw new ADirUseException(ex.Message, ex.StackTrace, strErrMsg, strParam);

}
}
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2006-07-31 23:18
iisreset

って、タイトルと関係ないやん。。。


マニュアル操作でユーザを削除するときに、どんなメッセージが出て、それがどういう結果をもたらすことを意味しているか、理解していますか?
kirua
常連さん
会議室デビュー日: 2006/05/30
投稿数: 31
投稿日時: 2006-08-01 01:34
jittaさん書き込みありがとうございます。

>マニュアル操作でユーザを削除するときに、どんなメッセージが出て、それがどうい>う結果をもたらすことを意味しているか、理解していますか?

理解をしていないんだと思います。

行いたい事は、同ユーザを登録した後に、XCACLSで作成したフォルダに対して、
そのユーザ:Aの権限を与えた場合にどのようにしたら不明なID(S-1-5-21…)
とならずに、正しくユーザ:Aの権限が与えられるのかです。

WEBサーバー上で同XCACLSのコマンドを実行すると
正しくユーザ:Aの権限が与えられます。

ADサーバーの再起動では、正しく権限が与えられません。

このことから推測すると、WEBサーバー上のどこかにキャッシュが、
残ってしまっているのでないかと考えています。
どうなんでしょうか…
kirua
常連さん
会議室デビュー日: 2006/05/30
投稿数: 31
投稿日時: 2006-08-01 15:44
解決しました。

大事な説明を忘れていました…
処理の流れは
@ ユーザ:AをActiveDirectoryへの登録
A フォルダの作成
B Aで作成したフォルダに対してXCACLSを使用してユーザ:Aのアクセス権限を付与

上記のBの前にユーザ:Aを偽装でログインをすると、
正しくアクセス権限が登録することができました。

****** 偽装ロジック ******
public class Impersonate : IDisposable
{
//
private static int LOGON32_LOGON_INTERACTIVE = 2;
private static int LOGON32_PROVIDER_DEFAULT = 0;
private WindowsImpersonationContext impersonationContext;
[DllImport("advapi32.dll", SetLastError=true)]
private static extern bool LogonUser(
string lpszUsername,
string lpszDomain,
string lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken
);
[DllImport("advapi32.dll", SetLastError=true)]
private extern static bool DuplicateToken(
IntPtr ExistingTokenHandle,
int SECURITY_IMPERSONATION_LEVEL,
ref IntPtr DuplicateTokenHandle
);
[DllImport("advapi32.dll", SetLastError=true)]
private static extern bool RevertToSelf();
[DllImport("kernel32.dll", SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr hObject);
private Impersonate(WindowsIdentity tempWindowsIdentity)
{
impersonationContext = tempWindowsIdentity.Impersonate();
}
// 本体
public static Impersonate ImpersonateValidUser(
string userName,
string domain,
string password)
{
WindowsIdentity tempWindowsIdentity;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;
Impersonate retValue = null;
try
{
if (RevertToSelf()/* != 0*/)
{
if (LogonUser(userName, domain, password,
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token)/* != 0*/)
{
if (DuplicateToken(token, 2, ref tokenDuplicate)/* != 0*/)
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
retValue = new Impersonate(tempWindowsIdentity);
if (retValue.impersonationContext == null)
{
retValue = null;
}
}
}
}
return retValue;
}
finally
{
// try - finally は2重にするべき。。。
if (!(tokenDuplicate.Equals(IntPtr.Zero)))
{
CloseHandle(tokenDuplicate);
}
if (!(token.Equals(IntPtr.Zero)))
{
CloseHandle(token);
}
}
}
public virtual void Dispose()
{
if (!((impersonationContext) == null))
{
impersonationContext.Undo();
impersonationContext = null;
}
}
}
#endregion
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2006-08-01 21:50
う〜ん。。。

 「同じユーザ」と表現されていますが、手動でアカウントを削除するときには

各ユーザー アカウントは、ユーザー名とは別の一意の識別子によって表されます。このユーザー アカウントを削除した後、将来、同じ名前のユーザー アカウントを作成しても、現在アクセス制御リストでこのユーザー アカウントに登録されているリソースへのアクセスは復元されません。

というメッセージが表示されます。つまり、Windows 内部では「同じユーザ」ではない、ということです。
 Windows では、アカウントを GUID で管理しています。この GUID は使い捨てで、いくつかの条件が重ならない限り、2回以上同じ GUID が割り振られることはありません。不明な ID の後に出る文字列はその GUID で、上のメッセージで「一意の識別子」と表現されているものです。

 ActiveDirectory には詳しくないのですが、削除したアカウントに対するアクセス制御リストを削除する、という行為を、誰が、いつ行うかという問題があると思います。
 AD から削除したタイミングで行っても、その時に起動していない PC にあるアクセス制御リストはどうなるの?という問題があります。
 ディレクトリやファイルへアクセスしたときに、AD に問い合わせて不明となったエントリを削除すると、例えばリムーバブル ディスクを使用していると、不都合が生じるかもしれません。


 解決したということですが、気になる。。。
「A アカウントに偽装してログインすると」ということだけど、「B アカウントに偽装してログイン」とどう違うのさ?
kirua
常連さん
会議室デビュー日: 2006/05/30
投稿数: 31
投稿日時: 2006-08-02 00:37
jittaさん書き込みありがとうございます。

@ AというユーザをActiveDirectoryに登録
A AというユーザをActiveDirectoryから削除
B AというユーザをActiveDirectoryに登録

(1) @、Bの場合
   ユーザ:AをActiveDirectoryへの登録
  A
   ユーザ:AをActiveDirectoryへの削除
(2) @、Bの場合
   フォルダの作成
  Aの場合
   フォルダの削除
(3) @、Bの場合
   (2)で作成したフォルダに対してXCACLSを使用してユーザ:Aのアクセス権限を付与

対処前はBを行った後に(3)を行うと、
不明なID(S-1-5-21…)と表示されていました。
その「S-1-5-21…」なのですが、
@でユーザ:AをActiveDirectoryを登録した際のGUID(SID?)でした。
キャッシュ上に過去のユーザ:Aに対する情報が残っていたのかな???

っで、(3)を行う前に、偽装でユーザ:Aでログイン(ActiveDirectoryの認証を受ける)
することにより現在のGUIDを取得(?)することができ(キャッシュも書き換え?)、
(3)でのアクセス権限変更が正常に起動しているのではと思っています。

1

スキルアップ/キャリアアップ(JOB@IT)