2

Sytem.IntPtrクライアントが偽装を使用してコードを呼び出すことができるように、サービス呼び出しからを返そうとしています。WCF サービスからトークンを返さない場合、私の偽装コードは正しく機能します。なぜこれが機能しないのかわかりません。次のエラーが表示されます。

「偽装の無効なトークン - 複製できません。」

これは、トークンをサービスから WinForm C# クライアントに渡して偽装する場合を除いて、機能するコードです。

[DllImport("advapi32.dll", EntryPoint = "DuplicateTokenEx")]
public extern static bool DuplicateTokenEx(IntPtr ExistingTokenHandle, uint dwDesiredAccess, ref SECURITY_ATTRIBUTES lpThreadAttributes, int TokenType, int ImpersonationLevel, ref IntPtr DuplicateTokenHandle);

private IntPtr tokenHandle = new IntPtr(0);
private IntPtr dupeTokenHandle = new IntPtr(0);

[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
    public int Length;
    public IntPtr lpSecurityDescriptor;
    public bool bInheritHandle;
}



public enum SecurityImpersonationLevel
{
    SecurityAnonymous = 0,
    SecurityIdentification = 1,
    SecurityImpersonation = 2,
    SecurityDelegation = 3
}

public enum TokenType
{
    TokenPrimary = 1,
    TokenImpersonation = 2
}

private const int MAXIMUM_ALLOWED = 0x2000000;


[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
public System.IntPtr GetWindowsUserToken(string UserName, string Password, string DomainName)
{

    IntPtr tokenHandle = new IntPtr(0);
    IntPtr dupTokenHandle = new IntPtr(0);

    const int LOGON32_PROVIDER_DEFAULT = 0;
    //This parameter causes LogonUser to create a primary token.
    const int LOGON32_LOGON_INTERACTIVE = 2;

    //Initialize the token handle            
    tokenHandle = IntPtr.Zero;

    //Call LogonUser to obtain a handle to an access token for credentials supplied.
    bool returnValue = LogonUser(UserName, DomainName, Password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref tokenHandle);        

    //Make sure a token was returned; if no populate the ResultCode and throw an exception:
    int ResultCode = 0;
    if (false == returnValue)
    {
        ResultCode = Marshal.GetLastWin32Error();
        throw new System.ComponentModel.Win32Exception(ResultCode, "API call to LogonUser failed with error code : " + ResultCode);
    }

    SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
    sa.bInheritHandle = true;
    sa.Length = Marshal.SizeOf(sa);
    sa.lpSecurityDescriptor = (IntPtr)0;


    bool dupReturnValue = DuplicateTokenEx(tokenHandle, MAXIMUM_ALLOWED, ref sa, (int)SecurityImpersonationLevel.SecurityDelegation, (int)TokenType.TokenImpersonation, ref dupTokenHandle);

    int ResultCodeDup = 0;
    if (false == dupReturnValue)
    {
        ResultCodeDup = Marshal.GetLastWin32Error();
        throw new System.ComponentModel.Win32Exception(ResultCode, "API call to DuplicateToken failed with error code : " + ResultCode);
    }

    //Return the user token
    return dupTokenHandle;

}

DuplicateTokenExへの呼び出しを正しく使用していない場合、何か考えはありますか? ここで読んだMSDNのドキュメントによると、委任に有効なトークンを作成し、リモートシステムのコンテキスト全体で使用できるはずです。「SecurityDelegation」を使用すると、サーバー プロセスはリモート システムでクライアントのセキュリティ コンテキストを偽装できます。

ありがとう!

4

1 に答える 1

2

値 TokenAccessLevels.MaximumAllowed を、許可されている最大の権限であるかのように使用しています。つまり、すべての権限を与えるかのように...

...しかし、そうではありません。

TokanAccesslevels.MaximumAllowed の値は 0x02000000 です。これは、列挙がいつでも増加できる最大値であり、将来の実装の参考になります。

列挙型の実際の実装については、このページを参照してください。

コードを機能させるには、ビット単位の演算を使用して、目的のアクセス レベルを 1 つずつ設定する必要があります。

MAXIMUM_ALLOWED を代入すると、コードは確実に実行されます

(uint)(TokenAccessLevels.Query | TokenAccessLevels.Duplicate | TokenAccessLevels.Impersonate)

DuplicateTokenEx 関数の PInvoke 呼び出しで。

もう問題がないことはわかっていますが、それは他の人を助けることができ、結局のところ、同じ問題に再び遭遇する可能性があります... ;)

于 2015-11-17T19:21:45.817 に答える