0

We use Windows Auth in Sql Server and on the network to control access to any kind of resource.

There are two users involved. The user logged into Windows and the user who has the authority to do things in the database and folders. So this is more of a windows thing than a sql thing.

I have a windows program. Right now it runs as whoever is logged on to windows. When it did database inserts, the "Last User" column was correctly populated with my user name, because we want to track the specific user making the changes. I got this value by sending My.User.Name in the Sql.

Then the situation changed. My program broke when the DBA took away my database priviledges. We worked around it by using Run As , and the program does not fail. However, inserts to the database show the auth user and not my user.

I think it would be unrealistic to expect all our users to have to CTRL+SHIFT+Right click and do Run As Different user. They don't know that password anyway.

So I have two questions:

  1. Instead of Run As, what .Net code can I use to (internally) switch my program to be running under the auth user? It needs to access folders and not just databases under that user, who has elevated privs over regular users.

  2. Once I'm running as that auth user, how can I discover the windows logged on user so I can stick that into my logging?

EDIT:

Here's my code to go back and get the windows user. The sid returned does not match anything.

Public Function WindowsUser() As String
    Dim DesktopHandle As IntPtr = GetProcessWindowStation()

    If DesktopHandle = IntPtr.Zero Then Return Nothing

    ' get the length of the name.
    Dim Length As Integer = 0
    Dim name As String = [String].Empty
    Dim UOI_USER_SID As Integer = 4
    GetUserObjectInformation(DesktopHandle, UOI_USER_SID, IntPtr.Zero, 0, Length)

    'get the name.
    Dim SID As IntPtr = Marshal.AllocHGlobal(Length)
    Dim result As Boolean = GetUserObjectInformation(DesktopHandle, UOI_USER_SID, SID, Length, Length)

    Dim StringPointer As IntPtr
    ConvertSidToStringSid(SID, StringPointer)
    Dim SidString As String = Marshal.PtrToStringAuto(StringPointer)

    Dim s As New SecurityIdentifier(SidString)
    Return s.Translate(GetType(NTAccount)).ToString
  End Function
toddmo
  • 20,682
  • 14
  • 97
  • 107

2 Answers2

1

Here's what I ended up doing to solve both problems:

Module Main

  Sub Main()
    MyCompanyNamespace.DataAccess.DatabaseObject.CurrentUser = Security.WindowsUser 'Save current username for logging / tracing
    'LOGON32_LOGON_NETWORK: didn't work with sql server
    'LOGON32_LOGON_BATCH: LogonUser returned "Could not impersonate the elevated user.  LogonUser returned error code 1385."
    'LOGON32_LOGON_INTERACTIVE: This seems to work!
    Using (New Impersonation("(the domain)", "(the user)", "(the password)", Impersonation.LogonTypes.LOGON32_LOGON_INTERACTIVE))
      Application.EnableVisualStyles()
      Application.SetCompatibleTextRenderingDefault(False)
      Dim frmApplication As New frmApplication
      Application.Run(frmApplication)
    End Using
  End Sub
End Module

The Impersonation implementation comes from my answer in this article: How do you do Impersonation in .NET?

We will store the domain, user and password in the config and encrypt it.

Community
  • 1
  • 1
toddmo
  • 20,682
  • 14
  • 97
  • 107
0
    • You can always do a stunt with CreateProcessAsUser/CreateProcessWithLogonW or something like sudo for Windows to run a program as another user without specifying a password manually. (You do understand that the 1st two ways are effectively giving your password to any user who puts enough effort to have a look?)
    • You can try to do impersonation (the process's account needs to have SeImpersonatePrivilege); WindowsIdentity is effectively a wrapper around those facilities. I never bothered with this as it proved times and times again to be a constant source of trouble.
  1. You can

But, first of all, I'd try organizational means (as they were the root cause). As things currently are, mssql-related operations are in no way connected to the "current user", their "names" becoming but random strings that you personally decide on. And your program now takes upon itself the burden to control access to DB instead of the integrated security settings! Is your DBA (or whoever is in charge of your environment) really okay with this?

Community
  • 1
  • 1
ivan_pozdeev
  • 33,874
  • 19
  • 107
  • 152
  • Thank you, I don't know. I'll go ask him. I thought I understood him this morning to mean what I have asked here, but I'll double check. – toddmo Nov 10 '14 at 23:10
  • While I do, what are the disadvantages of `CreateProcessWithLogonW` in terms of lost debugging capability? Right now I debug it in Visual Studio. Will I lose my debug ability if it launches a new process? – toddmo Nov 10 '14 at 23:15
  • Do you think the `WindowsIdentity` class would be cleaner? https://social.msdn.microsoft.com/Forums/vstudio/en-US/9fa5cb1f-999f-409d-aba9-94a20fc5480a/changing-credentials-on-the-current-thread?forum=clr – toddmo Nov 10 '14 at 23:17
  • `WindowsIdentity` works, but I could not get the window station to work. My routine is very long and complicated. I get a Sid string, but it does not match anything returned by `wmic useraccount get name,sid`. Would you like to see an edit with my code? – toddmo Nov 11 '14 at 00:56
  • Yes, I knew they would work but didn't know they would actually yield a [logon session SID](http://support.microsoft.com/kb/243330) rather than user's SID. – ivan_pozdeev Nov 11 '14 at 06:12
  • I got around that by caching the user's login name before I did any impersonation. – toddmo Nov 11 '14 at 19:03