プロが教える店舗&オフィスのセキュリティ対策術

CreateProcessAsUser関数を使うために、LogonUser関数を実行したのですが
以下のエラーになりました。

// A required privilege is not held by the client.
#define ERROR_PRIVILEGE_NOT_HELD 1314L

環境は
・Windows2000 Pro
・VC++ 6.0
です。

そのマシンにはオートログオンの設定がしてあり、オートログオンした
ユーザとパスワードを LogonUser関数に指定したのですがNGでした。
EXEはエクスプローラからダブルクリックして実行しました。

<オートログオン>
ユーザ:ABC
パスワード:123

例えば上記のような設定で、以下のコードのようにしました。

HANDLE hToken;
BOOL  bRet;
DWORD dwLastError;

bRet = LogonUser( "ABC",
         ".",
         "123",
         LOGON32_LOGON_INTERACTIVE,
         LOGON32_PROVIDER_DEFAULT,
         &hToken);

if (bRet == 0) {
dwLastError = GetLastError();
}

LogonUser関数は 0 が返り、詳細エラーは 0x522(1314) でした。
権限がない、というようなエラーですが、ログオンしたユーザと
取得しようとしたユーザが同じなのにエラーとなります。
何がいけないのでしょうか。

全然間違った考えことを言ってたら、ごめんなさい。。。
ここら辺の関数を使うのが初めてで、MSDN を何回も読んだのですが
理解できませんでした。
識者の方、アドバイスなどをお願いします。

A 回答 (3件)

こんにちは。

itohhといいます。

その後、解決したのでしょうか?
「回答に対する補足」が投稿されたのを今まで知りませんでした。

SE_TCB_NAME特権は、そもそもユーザのポリシーに付加されていないと
いけないのだと思います。

わたしが前に行ったときも特定のユーザIDに特権を付加した記憶があります。
もしかしたら、正当な解決方法ではないのかもしれませんが。

付加の方法は、
「コントロールパネル」「管理ツール」「ローカルセキュリティポリシー」を使用します。
この中の「ローカルポリシー」「ユーザ権利の割り当て」で
「オペレーティングシステムの一部として機能」に該当ユーザを設定します。

>マシンにログオンしているユーザ/パスワードと LogonUser関数に渡す
>パラメータは同じなのです
同一ならば、EnablePrivilege関数を呼ぶ必要もありません。
    • good
    • 0
この回答へのお礼

お礼が遅くなり、ほんとに申し訳ありませんでした。
今回は別手段にて回避させました。
セキュリティ関連については、今後勉強していきたいと思います。
ありがとうございました。

お礼日時:2002/04/05 18:09

こんにちは。

itohhといいます。

>EnablePrivilege関数についてMSDNを見たのですが、載っていませんでした。
すみません、わたしが自作した関数でした。
失念していました。

改めて解説します。

MSDNライブラリの解説に
>LogonUser 関数を呼び出すプロセスは、SE_TCB_NAME 特権を備えていなければなりません。
とあるように特権を動的にプログラム内から設定しなければいけません。

処理の流れとしては、以下のとおりです。
1.アクセストークンのオープン
2.Privilegeの名前に対するLUIDを取得
3.特権の設定(Enable/Disable)
4.アクセストークンのクローズ

EnablePrivilege関数のサンプルを載せておきます。
(インデントするために行の先頭に全角スペースを挿入しています)
この関数で一時的にSE_TCB_NAME 特権を有効にするように使ってください。
(クラスのメンバ関数としても良いと思います)

BOOL EnablePrivilege(LPCTSTR pszPrivName, BOOL bEnable)
{
 HANDLE hToken;
 TOKEN_PRIVILEGES tp;
 LUID luid;
 BOOL bResult = FALSE;

 // アクセストークンのオープン
 if (!::OpenProcessToken( ::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)){
  return FALSE;
 }

 // Privilegeの名前に対するLUIDを取得
 if (::LookupPrivilegeValue(NULL, pszPrivName, &luid)){
  tp.PrivilegeCount = 1;
  tp.Privileges[0].Luid = luid;
  // (Enable/Disable)に応じてアトリビュートを設定する。
  if( bEnable ){
   tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  }
  else {
   tp.Privileges[0].Attributes = 0;
  }
  // 特権のEnable/Disableを設定
  if (::AdjustTokenPrivileges( hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), 0, 0) ){
   bResult = TRUE;
  }
 }
 // アクセストークンをクローズする。
 ::CloseHandle(hToken);
 return bResult;
}

この回答への補足

早速の回答ありがとうございました。
大変勉強になりました。
教えていただいた通りに実行したところ、
・OpenProcessToken
・LookupPrivilegeValue
・AdjustTokenPrivileges
の関数は正常終了しました。
LookupPrivilegeValue関数の第2パラメータには SE_TCB_NAME
を指定しました。
しかし、LogonUser関数はエラーとなってしまいました。
エラーは同じく、ERROR_PRIVILEGE_NOT_HELD (1314) でした。

マシンにログオンしているユーザ/パスワードと LogonUser関数に渡す
パラメータは同じなのですが、、、
MSDN には SE_TCB_NAME 特権がないとこのエラーになると書いてありますが
他にも要因があるのでしょうか。

お手数かけますが、心当たりあればアドバイスお願いします。

補足日時:2002/02/15 14:10
    • good
    • 0
この回答へのお礼

すみません、補足に追加があるため「お礼」で投稿します。
AdjustTokenPrivileges関数は正常終了していましたが、
GetLastError関数で確認したところ、詳細コードは以下でした。

// Not all privileges referenced are assigned to the caller.
#define ERROR_NOT_ALL_ASSIGNED 1300L

このため SE_TCB_NAME 特権が有効にならず、LogonUser関数も
エラーになったと思われます。

お礼日時:2002/02/15 15:22

こんにちは。

itohhといいます。

特権 SE_TCB_NAMEを有効にしてからLogonUser関数を実行してみてください。

// 特権 SE_TCB_NAME を有効にする。
if (!::EnablePrivilege(SE_TCB_NAME, TRUE)){
 return FALSE;
}

bRet = LogonUser( "ABC",
         ".",
         "123",
         LOGON32_LOGON_INTERACTIVE,
         LOGON32_PROVIDER_DEFAULT,
         &hToken);

if (bRet == 0) {
 dwLastError = GetLastError();
}

// 特権 SE_TCB_NAME を無効にする。
::EnablePrivilege(SE_TCB_NAME, FALSE);

この回答への補足

回答ありがとうございました。
ちょっと教えていただきたいことがあります。
EnablePrivilege関数についてMSDNを見たのですが、載っていませんでした。
(2001年110月版です)
また、実際にコンパイルしてみてもエラーとなりました。
使用しているのは VC++ 6.0 です。
何か環境が古いのでしょうか。

補足日時:2002/02/15 10:53
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!