Hey, Scripting Guy!

Hey, Scripting Guy!

新しい TechNet コラムへようこそ。このコラムでは、よく寄せられるシステム管理スクリプトに関する質問に Scripting Guys がお答えします。システム管理スクリプトについて質問がある場合は、scripter@microsoft.com (英語のみ) までお送りください。すべての質問に回答することはできないかもしれませんが、可能な限り対応いたします。

今日の質問 : ローカル ユーザーのパスワードが変更されないようにするにはどうすればよいでしょうか。


ローカル ユーザーのパスワードが変更されないようにするにはどうすればよいでしょうか。

Q

Scripting Guy さん、よろしくお願いします。ローカル ユーザーが自分でパスワードを変更できないように、ローカル ユーザー アカウントを構成するにはどうすればよいでしょうか。

-- DC

A

DC さん、こんにちは。今回は、謎の userFlags 属性に秘密が隠されています。始めに、ユーザーが自分のパスワードを変更できないようにユーザー アカウントを設定する方法を示します。それから、userFlags 属性を使用して管理することのできる他のいくつかのローカル ユーザー アカウント プロパティを紹介します。そして、願わくばそのときまでに昼食の時間になっていることを祈ります。

まずは、ユーザーが自分のパスワードを変更できないようにするスクリプトです。

Const ADS_UF_PASSWD_CANT_CHANGE = &H0040

Set objUser = GetObject("WinNT://atl-ws-01/kenmyer")

If Not objUser.UserFlags AND ADS_UF_PASSWD_CANT_CHANGE Then
    objPasswordNoChangeFlag = objUser.UserFlags XOR ADS_UF_PASSWD_CANT_CHANGE
    objUser.Put "userFlags", objPasswordNoChangeFlag 
    objUser.SetInfo
End If

最初に定数 (ADS_UF_PASSWD_CANT_CHANGE という覚えやすい名前です) を定義します。この定数は、userFlags 属性の中の適切な “スイッチ” を識別するのに必要になります。userFlags 属性はビットマスク属性の一例で、1 つの属性の中に複数のプロパティやプロパティ値が含まれています。ここでは差し当たり、ビットマスクを一連のスイッチの集まりと捉え、それぞれのスイッチがさまざまなプロパティを表しているものと考えてください。“ユーザーはパスワードを変更できない” に対応するスイッチがオンの場合、ユーザーは自分のパスワードを変更することができません。スイッチがオフの場合、ユーザーは自分のパスワードを変更することができます。このことはかなり直感的にわかると思いますが、ただ 1 つビットマスクが扱いにくい点は、“スイッチ”に、“ユーザーはパスワードを変更できない” というような名前が付いていないことです。その代わりに、&H0040 のような 16 進値を持っています。今回の作業を実行するには、&H0040 というスイッチを反転する必要があります。そのために先ほどの定数を定義しています。

次に、コンピュータ atl-ws-01 の kenmyer アカウントに接続します。その時点で、問題のスイッチが既にオンになっているかどうかをチェックします。ビットマスクを操作するときは、しばしば次のようなコードを見かけます。

If objUser.UserFlags AND ADS_UF_PASSWD_CANT_CHANGE Then

わかりやすく言えば、このコードは “userFlags 属性が存在して、かつ、ADS_UF_PASSWD_CANT_CHANGE スイッチがオンならば、この文が True なので何か実行する必要がある” という意味です。今回の例では、オンになっているスイッチに注目する必要はありません。“パスワードを変更できない” フラグが既にセットされていれば、私たちの作業は済むからです。注目する必要があるのは、オフになっているスイッチだけです。そこで、次のコード行を使用します。このコードは、スイッチがオンではない場合にのみ、処理を実行します。

If Not objUser.UserFlags AND ADS_UF_PASSWD_CANT_CHANGE Then

さて、ここで皆さんを本当に戸惑わせることになると思います。次のコード行を見てください。

objPasswordNoChangeFlag = objUser.UserFlags XOR ADS_UF_PASSWD_CANT_CHANGE

実際、–見かけ上は– とてもシンプルなコードです。ここで実行していることは、“ユーザーはパスワードを変更できない” スイッチの値を切り替えているだけです。それを、この XOR コマンドで実行しています。スイッチがオンの場合は、XOR によってスイッチがオフになります。スイッチがオフの場合は、XOR によってスイッチがオンになります。userFlags 属性の現在の値を受け取り、“ユーザーはパスワードを変更できない” スイッチを切り替えているわけです。このスイッチはオフであることはわかっているので (If Not 文を使ったばかりです)、XOR によってそのスイッチがオンになります。そして、変数 objPasswordNoChangeFlag には、“ユーザーはパスワードを変更できない” スイッチがオフではなくオンになった点だけを除いて、現在の userFlags 属性にあるものとまったく同じ値が格納されます。

よろしいでしょうか。スクリプトの残りの部分は簡単です。次のコード行によって、変数 objPasswordNoChangeFlag の値を userFlags 属性に書き込みます。

objUser.Put "userFlags", objPasswordNoChangeFlag

それから、SetInfo コマンドを使用してそれらの変更内容をユーザー アカウントに書き込みます。これだけで簡単に、ローカル ユーザー Ken Myer はコンピュータ atl-ws-01 で自分のパスワードを変更する権限を持たなくなります。

それでは、Ken Myer が自分のパスワードを変更できるようにしたい場合はどうすればよいでしょうか。簡単ですよね。“ユーザーはパスワードを変更できない” スイッチがオンかどうかをチェックし、XOR を使用してそれをオフにするだけです。

Const ADS_UF_PASSWD_CANT_CHANGE = &H0040

Set objUser = GetObject("WinNT://atl-ws-01/kenmyer")

If objUser.UserFlags AND ADS_UF_PASSWD_CANT_CHANGE Then
    objPasswordNoChangeFlag = objUser.UserFlags XOR ADS_UF_PASSWD_CANT_CHANGE
    objUser.Put "userFlags", objPasswordNoChangeFlag 
    objUser.SetInfo
End If

ただ 1 つ違うのは、If - Then 文から単語 Not を取り除いたことだけです。そんなわけで、スイッチがオンになっていて、オフにした方がよい、という事例がここで欲しいところです。

こういうビットマップ属性は確かに戸惑いますね。私たちもそう思います。もう少し情報や図解が必要だという人は、『Microsoft Windows 2000 Scripting Guide』のこの箇所 (英語) を参照してください。さて、冒頭で約束したとおり、userFlags 属性を使用して管理することのできるいくつかのローカル ユーザー アカウント プロパティをここで紹介しておきます。

プロパティ定数

Logon script will be executed (ログオン スクリプトが実行される)

ADS_UF_SCRIPT

&H0001

Account is disabled (アカウントが無効にされる)

ADS_UF_ACCOUNTDISABLE

&H0002

Account requires a home directory (アカウントでホーム ディレクトリを必要とする)

ADS_UF_HOMEDIR_REQUIRED

&H0008

Account is locked out (アカウントがロックアウトされる)

ADS_UF_LOCKOUT

&H0010

Account does not require a password (アカウントでパスワードを必要としない)

ADS_UF_PASSWD_NOTREQD

&H0020

User cannot change password (ユーザーはパスワードを変更できない)

ADS_UF_PASSWD_CANT_CHANGE

&H0040

Encrypted text password allowed (暗号化されたテキスト パスワードを許可する)

ADS_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED

&H0080

Account password never expires (アカウントのパスワードを無期限にする)

ADS_UF_DONT_EXPIRE_PASSWD

&H10000

ログオンでスマートカードを必要とする

ADS_UF_SMARTCARD_REQUIRED

&H40000

Password has expired (パスワードを期限切れにする)

ADS_UF_PASSWORD_EXPIRED

&H800000

いつか退屈なときに、これらの値を今回の “ユーザーはパスワードを変更できない” スクリプトに代入して、何が起きるか確かめてみてください (もちろん、いつものことですが、この種のスクリプトを実験するときは、テスト用のコンピュータを使用するか、または少なくともテスト用のアカウントを使用することをお勧めします)。


関連情報

Hey, Scripting Guy! - アーカイブ もチェックしてください。

ページのトップへページのトップへ