Exemple #1
0
 public static extern bool CreateProcessAsUser(
     IntPtr hToken,
     String lpApplicationName,
     String lpCommandLine,
     ref SecurityWin32.SECURITY_ATTRIBUTES lpProcessAttributes,
     ref SecurityWin32.SECURITY_ATTRIBUTES lpThreadAttributes,
     bool bInheritHandle,
     ProcessWin32.ProcessCreationFlags dwCreationFlags,
     IntPtr lpEnvironment,
     String lpCurrentDirectory,
     ref ProcessWin32.STARTUPINFO lpStartupInfo,
     out ProcessWin32.PROCESS_INFORMATION lpProcessInformation);
        /// <summary>
        /// ASP.NET で偽装ユーザーのコンテキストで実行されるプロセスを生成する
        /// http://support.microsoft.com/kb/889251/ja
        /// </summary>
        /// <param name="commandLinePath">コマンドライン</param>
        /// <param name="currentDirectory">カレント・ディレクトリ</param>
        /// <param name="impersonationLevel">偽装レベル</param>
        /// <param name="errorInfo">エラー情報</param>
        /// <returns>
        /// ・true:成功
        /// ・false:失敗
        /// </returns>
        public static bool CreateProcessAsImpersonationUser(
            string commandLinePath, string currentDirectory,
            SecurityWin32.SECURITY_IMPERSONATION_LEVEL impersonationLevel, out string errorInfo)
        {
            // エラー情報の初期化
            errorInfo = "";

            // 失敗するので初期化
            if (string.IsNullOrEmpty(currentDirectory))
            {   
                currentDirectory = 
                    Environment.GetEnvironmentVariable(
                        "SystemRoot", EnvironmentVariableTarget.Process);
            }

            // トークン
            IntPtr token = IntPtr.Zero;
            // 継承可能にする。
            IntPtr tokenDuplicate = IntPtr.Zero;

            // 戻り値
            bool ret;

            // 偽装ユーザのアカウント・トークン
            token = WindowsIdentity.GetCurrent().Token;

            // SECURITY_ATTRIBUTES構造体
            SecurityWin32.SECURITY_ATTRIBUTES sa 
                = new SecurityWin32.SECURITY_ATTRIBUTES();

            // Security Descriptor
            sa.lpSecurityDescriptor = IntPtr.Zero; // = (IntPtr)0;
            // Security Descriptorのハンドルは継承不可能
            sa.bInheritHandle = false;
            // サイズ
            sa.Length = Marshal.SizeOf(sa);

            try
            {
                // 偽装アクセストークンハンドルは、
                // CreateProcessAsUserに指定できないため、 
                // DuplicateTokenExでプライマリ・トークンに変換する
                ret = SecurityWin32.DuplicateTokenEx(
                    token, (uint)SecurityWin32.ACCESS_MASK.GENERIC_ALL, ref sa,
                    (int)impersonationLevel, (int)SecurityWin32.TOKEN_TYPE.TokenPrimary, ref tokenDuplicate);

                // 戻り値判定
                if (ret)
                {
                    // true(成功)

                    // STARTUPINFO構造体
                    ProcessWin32.STARTUPINFO si = new ProcessWin32.STARTUPINFO();
                    // デスクトップ名
                    si.lpDesktop = "";
                    // サイズ
                    si.cb = Marshal.SizeOf(si);

                    // PROCESS_INFORMATION構造体
                    ProcessWin32.PROCESS_INFORMATION pi = new ProcessWin32.PROCESS_INFORMATION();

                    // 偽装可能にしたトークンを指定してプロセス起動
                    ret = ProcessWin32.CreateProcessAsUser(
                        tokenDuplicate, null, commandLinePath, ref sa, ref sa, false,
                        0, IntPtr.Zero, currentDirectory, ref si, out pi);

                    // 戻り値判定
                    if (ret)
                    {
                        // true(成功)

                        CmnWin32.CloseHandle(pi.hProcess);
                        CmnWin32.CloseHandle(pi.hThread);

                        // 偽装可能にしたトークンのハンドラを閉じる
                        ret = CmnWin32.CloseHandle(tokenDuplicate);
                    }
                    else
                    {
                        // asp.net - Running cscript.exe from C# .ashx does not execute code in vbscript file - Stack Overflow
                        // http://stackoverflow.com/questions/3842020/running-cscript-exe-from-c-sharp-ashx-does-not-execute-code-in-vbscript-file

                        // false(失敗)
                        errorInfo = "CreateProcessAsUser failed with " + Marshal.GetLastWin32Error()
                            + ": if 1314, make sure user is a member 'Replace a process level token' Control Panel -> Administrative Tools -> Local Security Settings.";
                    }
                }
                else
                {
                    // false(失敗)
                    errorInfo = "DuplicateTokenEx failed with " + Marshal.GetLastWin32Error();
                }
            }
            finally
            {
                // 失敗(例外発生)時など。

                // トークンハンドル、
                // 偽装アクセストークンハンドルをクローズ
                if (token != IntPtr.Zero)
                {
                    CmnWin32.CloseHandle(token);
                }
                if (tokenDuplicate != IntPtr.Zero)
                {
                    CmnWin32.CloseHandle(tokenDuplicate);
                }
            }

            // false(失敗)
            return false;
        }