Re: Access Denied executing Batch File from CreateProcessAsUser

From: S Hayes (SHayes_at_discussions.microsoft.com)
Date: 04/27/05


Date: Wed, 27 Apr 2005 05:30:15 -0700

I can't use System.Diagnostics.Process in my case since this class ALWAYS
creates the process with the underlying process security context, not the
impersonated users security context.

This code is being executed within a ASP.NET web services.

The following is the function that is being called. When the executable
parameter passed in is a batch file, I get the 'Access Denied' error on the
CreateProcessAsUser call. If the executable parameter is a program, then
everything works nicely. As stated in earlier Threads, both the batch file
and the program file are in the same directory and the impersonated user has
Full rights.

<<**********************************
                #region Win32 declarations

                [StructLayout(LayoutKind.Sequential)]
                private struct STARTUPINFO
                {
                        public int cb;
                        public String lpReserved;
                        public String lpDesktop;
                        public String lpTitle;
                        public uint dwX;
                        public uint dwY;
                        public uint dwXSize;
                        public uint dwYSize;
                        public uint dwXCountChars;
                        public uint dwYCountChars;
                        public uint dwFillAttribute;
                        public uint dwFlags;
                        public short wShowWindow;
                        public short cbReserved2;
                        public IntPtr lpReserved2;
                        public IntPtr hStdInput;
                        public IntPtr hStdOutput;
                        public IntPtr hStdError;
                }

                [StructLayout(LayoutKind.Sequential)]
                private struct PROCESS_INFORMATION
                {
                        public IntPtr hProcess;
                        public IntPtr hThread;
                        public uint dwProcessId;
                        public uint dwThreadId;
                }

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

                [DllImport("kernel32.dll")]
                private static extern bool GetExitCodeProcess(IntPtr hProcess, out uint
lpExitCode);

                [DllImport("kernel32", SetLastError=true, ExactSpelling=true)]
                private static extern Int32 WaitForSingleObject(IntPtr handle, Int32
milliseconds);

                [DllImport("kernel32.dll", EntryPoint="CloseHandle", SetLastError=true,
CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
                private extern static bool CloseHandle(IntPtr handle);

                [DllImport("advapi32.dll", EntryPoint="CreateProcessAsUser",
SetLastError=true, CharSet=CharSet.Ansi,
CallingConvention=CallingConvention.StdCall)]
                private extern static bool CreateProcessAsUser(IntPtr hToken, String
lpApplicationName, String lpCommandLine, ref SECURITY_ATTRIBUTES
lpProcessAttributes,
                        ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandle, int
dwCreationFlags, IntPtr lpEnvironment,
                        String lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out
PROCESS_INFORMATION lpProcessInformation);

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

                #endregion

public static int RunProcessAsUser(string executable,string cmdLine,int
timeOut)
{
   int errorCode = 0;
   bool ret;
   IntPtr token = new IntPtr(0);
   IntPtr dupedToken = new IntPtr(0);

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

   token = WindowsIdentity.GetCurrent().Token;
   const uint GENERIC_ALL = 0x10000000;

   const int SecurityImpersonation = 2;
   const int TokenType = 1;

   ret = DuplicateTokenEx(token, GENERIC_ALL, ref sa, SecurityImpersonation,
TokenType, ref dupedToken);

   if (ret == false)
   {
      errorCode = Marshal.GetLastWin32Error();
      throw new Exceptions.SecurityException("Unable to duplicate User
Security Token",new Win32Exception(errorCode));
   }

   STARTUPINFO si = new STARTUPINFO();
   si.cb = Marshal.SizeOf(si);
   si.lpDesktop = "";

   PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
   ret = CreateProcessAsUser(dupedToken, executable, cmdLine, ref sa, ref
sa, false, 0, (IntPtr)0, null, ref si, out pi);

   if (ret == false)
   {
      errorCode = Marshal.GetLastWin32Error();
      throw new Exceptions.SecurityException("Unable to Create Process for
User",new Win32Exception(errorCode));
   }

   if(WaitForSingleObject( pi.hProcess, timeOut ) != 0)
      throw new Exceptions.WarningException("Timeout running User Process");

   uint ec;
   GetExitCodeProcess(pi.hProcess,out ec);
   errorCode = (int)ec;

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

   CloseHandle(dupedToken);

   return errorCode;
}

**********************************>>

"Yunus Emre ALPĂ–ZEN [MCP]" wrote:

> do u develop an ASP.NET web service ???
>
> "CreateProcessAsUser property specifies whether a CGI process is created in
> the system context or in the context of the requesting user"
> not a batch application.
>
> My advice u to use System.Diagnostics.Process...
>
> Do u have any sample code to cause error again??
>
> "S Hayes" <SHayes@discussions.microsoft.com> wrote in message
> news:9416D77B-8EC7-43BC-94A2-E7EBE59F176A@microsoft.com...
> >I don't understand what you mean by "The batch file executed under IIS user
> > account". I am using the CreateProcessAsUser which will create the
> > process
> > using the credentials of the passed in Token which I am getting from the
> > Impersonated user. Again, I have verified this works when executing a
> > program file, but fails when executing a batch file.
> >
> > "Yunus Emre ALPĂ–ZEN [MCP]" wrote:
> >
> >> The batch file executed under IIS user account. You should define rights
> >> for
> >> it. Impersonation doesn't work for your scenario
> >>
> >>
> >> "S Hayes" <SHayes@discussions.microsoft.com> wrote in message
> >> news:C178C869-2CD6-426B-9A89-C11D0B30C500@microsoft.com...
> >> >I am trying to run a batch file from within an Asp.net webservice and am
> >> > receiving an Access Denied error. I have verified that the
> >> > impersonated
> >> > user
> >> > has proper rights to the directory that the batch file is in by
> >> > executing
> >> > a
> >> > program from the same directory. It seems that everything works fine
> >> > for
> >> > non
> >> > batch file execution, but batch files return an error.
> >> >
> >> > I'm currently running under IIS 5.
> >> >
> >> > --
> >> > STH
> >>
> >>
> >>
>
>
>



Relevant Pages

  • Re: Security Running a DTS Package
    ... the security context of the service account. ... related to the service account and the permissions. ... Yes I am actually referring to running the package from a job. ... It sounds like you are referring to executing the ...
    (microsoft.public.sqlserver.dts)
  • Re: Active Directory error 80004005
    ... (I think the problem is that the security context that you are running the ... until you tell us what account the query is being ... one of the Member Server. ... :>: Actually when i executing the following line of VBScript ...
    (microsoft.public.inetserver.iis.security)
  • Re: xpsql.cpp: Error 87 from GetProxyAccount on line 604
    ... In SQL Server 2000, if the security context of the user ... executing the xp_cmdshell statement is not a sysadmin, ... > I am trying to execute a stored proc from ASP. ...
    (microsoft.public.sqlserver.security)
  • Re: Security Running a DTS Package
    ... It depends on what you mean by run a package - through a job ... It sounds like you are referring to executing the ... security context of the SQL Agent service account. ... package but when it writes a file the SQL Server sceurity is no longer valid? ...
    (microsoft.public.sqlserver.dts)
  • Re: Active Directory error 80004005
    ... What security context is this query running under? ... Does taht security ... Actually when i executing the following line of VBScript ...
    (microsoft.public.inetserver.iis.security)