Solved

How to execute code with current user privilege on the service application.

Posted on 2009-07-08
5
724 Views
Last Modified: 2012-05-07
Hello.
I made a serivce application. ( it is executed with System user account )

When i trying to some jobs on the service application, the code does not work.
Because of service application has limitted privileges.
So, i must made other win32 program which is executed by service application with current logon user system privileges.

I think this way is not efficient. Because i must made another program.

So, I looking for the solution that execute some procedure or function with current logon user privileges at the service application.

For Example)
// Service application body
begin
....
   do_excute_some_code( parameter 1 ); // this procedure will execute with current logon user privileges

end;

Is this possible ???
If you know how to do this, please let me know or give me some example code.

Thanks.
0
Comment
Question by:schiva
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
5 Comments
 
LVL 14

Expert Comment

by:SteveBay
ID: 24813662
I am almost certain you will not be able to change the account under which you are running while running.
Is there a reason why you can not just run the entire service from a user's account with all of the approriate priveleges?

As an alternative you could perhaps write two services and run them under different accounts and have service1 send a message to service2 that will then execute some code but it sounds like alot of work.
0
 
LVL 37

Expert Comment

by:Geert Gruwez
ID: 24815866
you need to change to the user you need with impersonate user and then run that task

  if LogonUser(user, domain or empty string , pass, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, h) then
  try
    if ImpersonateLoggedOnUser(h) then
    try
      do whatever as user
    finally
      if not RevertToSelf then// either this, or exit the thread
        showmessage(syserrormessage(getlasterror));
    end
    else
      showmessage(syserrormessage(getlasterror));
  finally
    closehandle(h);        
  end;

Open in new window

0
 
LVL 2

Accepted Solution

by:
Wegelin earned 500 total points
ID: 24912639
I have a class wher you can do both
Run a Process as logged on user  or run Code as loggen on user
Import the Class ProcessAsUser

How you can Start a Process as Logged On User ?

ProcessAsUser.launch("c:\wondos\notepad.exe")


How you run Code as logged On User ?



WindowsImpersonationContext impctx = WindowsIdentity.Impersonate(ProcessAsUser.GetUserToken);

 do_excute_some_code( parameter 1 ); // this procedure will execute with current logon user privileges

impctx.Undo();

Imports System.Runtime.InteropServices
Imports System.Security.Permissions
Imports System.Reflection
Public Class ProcessAsUser
    <StructLayout(LayoutKind.Sequential)> _
Friend Structure PROCESS_INFORMATION
        Public hProcess As IntPtr
        Public hThread As IntPtr
        Public dwProcessId As Int32
        Public dwThreadId As Int32
    End Structure
    <StructLayout(LayoutKind.Sequential)> _
    Friend Structure SECURITY_ATTRIBUTES
        Public nLength As Int32
        Public lpSecurityDescriptor As IntPtr
        Public bInheritHandle As Boolean
    End Structure
 
    <StructLayout(LayoutKind.Sequential)> _
    Public Structure STARTUPINFO
        Public cb As Int32
        Public lpReserved As String
        Public lpDesktop As String
        Public lpTitle As String
        Public dwX As Int32
        Public dwY As Int32
        Public dwXSize As Int32
        Public dwYSize As Int32
        Public dwXCountChars As Int32
        Public dwYCountChars As Int32
        Public dwFillAttribute As Int32
        Public dwFlags As Int32
        Public wShowWindow As Short
        Public cbReserved2 As Short
        Public lpReserved2 As IntPtr
        Public hStdInput As IntPtr
        Public hStdOutput As IntPtr
        Public hStdError As IntPtr
    End Structure
 
    Public Enum SECURITY_IMPERSONATION_LEVEL
        SecurityAnonymous
        SecurityIdentification
        SecurityImpersonation
        SecurityDelegation
    End Enum
    Public Enum TOKEN_TYPE
 
        TokenPrimary = 1
 
        TokenImpersonation
    End Enum
 
    Private Shared STANDARD_RIGHTS_REQUIRED As UInteger = 983040
 
    Private Shared STANDARD_RIGHTS_READ As UInteger = 131072
 
    Private Shared TOKEN_ASSIGN_PRIMARY As UInteger = 1
 
    Private Shared TOKEN_DUPLICATE As UInteger = 2
 
    Private Shared TOKEN_IMPERSONATE As UInteger = 4
 
    Private Shared TOKEN_QUERY As UInteger = 8
 
    Private Shared TOKEN_QUERY_SOURCE As UInteger = 16
 
    Private Shared TOKEN_ADJUST_PRIVILEGES As UInteger = 32
 
    Private Shared TOKEN_ADJUST_GROUPS As UInteger = 64
 
    Private Shared TOKEN_ADJUST_DEFAULT As UInteger = 128
 
    Private Shared TOKEN_ADJUST_SESSIONID As UInteger = 256
 
    Private Shared TOKEN_READ As UInteger = (STANDARD_RIGHTS_READ Or TOKEN_QUERY)
    Private Shared TOKEN_ALL_ACCESS As UInteger = (STANDARD_RIGHTS_REQUIRED _
                   Or (TOKEN_ASSIGN_PRIMARY _
                   Or (TOKEN_DUPLICATE _
                   Or (TOKEN_IMPERSONATE _
                   Or (TOKEN_QUERY _
                   Or (TOKEN_QUERY_SOURCE _
                   Or (TOKEN_ADJUST_PRIVILEGES _
                   Or (TOKEN_ADJUST_GROUPS _
                   Or (TOKEN_ADJUST_DEFAULT Or TOKEN_ADJUST_SESSIONID)))))))))
 
    ' Private Declare Auto Function CreateProcessAsUser Lib "advapi32.dll" (ByVal token As IntPtr, ByVal applicationName As String, ByVal commandLine As String, ByRef processAttributes As SECURITY_ATTRIBUTES, ByRef threadAttributes As SECURITY_ATTRIBUTES, ByVal inheritHandles As Boolean, ByVal creationFlags As UInteger, ByVal environment As IntPtr, ByVal currentDirectory As String, ByRef startupInfo As STARTUPINFO, ByRef processInformation As PROCESS_INFORMATION) As Boolean
    Private Declare Auto Function CreateProcessAsUser Lib "advapi32" ( _
      ByVal hToken As IntPtr, _
      ByVal strApplicationName As String, _
      ByVal strCommandLine As String, _
      ByRef lpProcessAttributes As SECURITY_ATTRIBUTES, _
      ByRef lpThreadAttributes As SECURITY_ATTRIBUTES, _
      ByVal bInheritHandles As Boolean, _
      ByVal dwCreationFlags As Integer, _
      ByVal lpEnvironment As IntPtr, _
      ByVal lpCurrentDriectory As String, _
      ByRef lpStartupInfo As STARTUPINFO, _
      ByRef lpProcessInformation As PROCESS_INFORMATION) As Boolean
 
    Public Declare Function DuplicateTokenEx Lib "advapi32.dll" (ByVal existingToken As IntPtr, ByVal desiredAccess As UInteger, ByVal tokenAttributes As IntPtr, ByVal impersonationLevel As SECURITY_IMPERSONATION_LEVEL, ByVal tokenType As TOKEN_TYPE, ByRef newToken As IntPtr) As Boolean
    Declare Function CreateEnvironmentBlock Lib "userenv.dll" (ByRef lpEnvironment As IntPtr, ByVal hToken As IntPtr, ByVal bInherit As Boolean) As Boolean
    Declare Function OpenProcessToken Lib "advapi32.dll" (ByVal ProcessHandle As IntPtr, ByVal DesiredAccess As Integer, ByRef TokenHandle As IntPtr) As Boolean
    Private Declare Function CloseHandle Lib "kernel32.dll" (ByVal handle As IntPtr) As Boolean
 
    Declare Function DestroyEnvironmentBlock Lib "userenv.dll" (ByVal lpEnvironment As IntPtr) As Boolean
    Private Const SW_SHOW As Short = 5
    Private Const SW_SHOWMAXIMIZED As Short = 7
    ' Private Const TOKEN_QUERY = 8
    'Private Const TOKEN_DUPLICATE = 2
    'Private Const TOKEN_ASSIGN_PRIMARY = 1
    Private Const GENERIC_ALL_ACCESS = 268435456
    Private Const STARTF_USESHOWWINDOW = 1
    Private Const STARTF_FORCEONFEEDBACK = 64
    Private Const CREATE_UNICODE_ENVIRONMENT = 1024
    Public Shared ErrStr As String = ""
 
    Private Shared Function LaunchProcessAsUser(ByVal cmdLine As String, ByVal _
      token As IntPtr, ByVal envBlock As IntPtr) As Boolean
        Dim result As Boolean = False
        Dim pi As PROCESS_INFORMATION = New PROCESS_INFORMATION
        Dim saProcess As SECURITY_ATTRIBUTES = New SECURITY_ATTRIBUTES
        Dim saThread As SECURITY_ATTRIBUTES = New SECURITY_ATTRIBUTES
 
        saProcess.nLength = Marshal.SizeOf(saProcess)
        saThread.nLength = Marshal.SizeOf(saThread)
        Dim si As STARTUPINFO = New STARTUPINFO
        si.cb = Marshal.SizeOf(si)
        'si.lpDesktop = "WinSta0\Default"
        si.lpDesktop = Nothing
        si.dwFlags = STARTF_USESHOWWINDOW Or STARTF_FORCEONFEEDBACK
        si.wShowWindow = SW_SHOW
        result = CreateProcessAsUser(token, cmdLine, "", saProcess, saThread, _
          False, CREATE_UNICODE_ENVIRONMENT, envBlock, Nothing, si, pi)
        If result = False Then
            Dim iError As Integer = Marshal.GetLastWin32Error
            ErrStr = String.Format("CreateProcessAsUser Error:" & _
              "{0}", iError)
            ' Debug.WriteLine(message)
        Else
            CloseHandle(token)
        End If
        Return result
    End Function
 
    Private Shared Function GetPrimaryToken(ByVal processId As Integer) As  _
      IntPtr
        Dim token As IntPtr = IntPtr.Zero
        Dim primaryToken As IntPtr = IntPtr.Zero
        Dim retVal As Boolean = False
        Dim p As Process = Nothing
        Try
            p = Process.GetProcessById(processId)
        Catch generatedExceptionVariable0 As ArgumentException
            Dim details As String = String.Format("ProcessID {0} Not" & _
              "Available", processId)
            Debug.WriteLine(details)
            Return primaryToken
        End Try
        retVal = OpenProcessToken(p.Handle, TOKEN_DUPLICATE, token)
        If retVal = True Then
            Dim sa As SECURITY_ATTRIBUTES = New SECURITY_ATTRIBUTES
            sa.nLength = Marshal.SizeOf(sa)
            retVal = DuplicateTokenEx(token, TOKEN_ASSIGN_PRIMARY Or _
              TOKEN_DUPLICATE Or TOKEN_QUERY, IntPtr.Zero, CType( _
              SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, Integer), _
              CType(TOKEN_TYPE.TokenPrimary, Integer), primaryToken)
            If retVal = False Then
                ErrStr = String.Format("DuplicateTokenEx Error:" & _
                  "{0}", Marshal.GetLastWin32Error)
 
                'Debug.WriteLine(message)
            End If
        Else
            ErrStr = String.Format("OpenProcessToken Error:" & _
              "{0}", Marshal.GetLastWin32Error)
            'Debug.WriteLine(message)
        End If
        Return primaryToken
    End Function
 
    Private Shared Function GetEnvironmentBlock(ByVal token As IntPtr) As IntPtr
        Dim envBlock As IntPtr = IntPtr.Zero
        Dim retVal As Boolean = CreateEnvironmentBlock(envBlock, token, False)
        If retVal = False Then
            Dim message As String = String.Format("CreateEnvironmentBlock" & _
              "Error: {0}", Marshal.GetLastWin32Error)
            ' Debug.WriteLine(message)
        End If
        Return envBlock
    End Function
 
    Public Shared Function Launch(ByVal appCmdLine As String) As Boolean
        Dim ret As Boolean = False
        Dim ps As Process() = Process.GetProcessesByName("explorer")
        Dim processId As Integer = -1
        If ps.Length > 0 Then
            processId = ps(0).Id
        End If
        If processId > 1 Then
            Dim token As IntPtr = GetPrimaryToken(processId)
            If Not (token.Equals(IntPtr.Zero)) Then
                Dim envBlock As IntPtr = GetEnvironmentBlock(token)
                ret = LaunchProcessAsUser(appCmdLine, token, envBlock)
                If Not (envBlock.Equals(IntPtr.Zero)) Then
                    DestroyEnvironmentBlock(envBlock)
                End If
            End If
        End If
        Return ret
    End Function
    Public Shared Function GetUserToken() As IntPtr
        ErrStr = ""
        Dim token As IntPtr
        Dim ps As Process() = Process.GetProcessesByName("explorer")
        Dim processId As Integer = -1
        If ps.Length > 0 Then
            processId = ps(0).Id
        End If
        If processId > 1 Then
            token = GetPrimaryToken(processId)
 
        End If
 
        Return token
    End Function
 
    Public Sub New()
        MyBase.New()
    End Sub
End Class

Open in new window

0
 
LVL 37

Expert Comment

by:Geert Gruwez
ID: 25138086
lol, mlmcc
accepting a VB solution in a Delphi zone

ahh, there is general programming languages too
0

Featured Post

The Ultimate Checklist to Optimize Your Website

Websites are getting bigger and complicated by the day. Video, images, custom fonts are all great for showcasing your product/service. But the price to pay in terms of reduced page load times and ultimately, decreased sales, can lead to some difficult decisions about what to cut.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
This tutorial will introduce the viewer to VisualVM for the Java platform application. This video explains an example program and covers the Overview, Monitor, and Heap Dump tabs.
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …

726 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question