Friday, November 14, 2014

how to impersonate a certain windows user in your .net application (or dll)

(also applies to sql clr assembly)

below sample is a sql clr assembly that writes a text to file. compile the project (release) with unsafe checked (project properties > sql clr > permission level)




using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.IO;
using System.Text;
using System.Security.Permissions;
using System.Security.Principal;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
using System.Runtime.ConstrainedExecution;
using System.Security;

public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
{
private SafeTokenHandle()
: base(true)
{
}

[DllImport("kernel32.dll")]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr handle);

protected override bool ReleaseHandle()
{
return CloseHandle(handle);
}
}

public partial class StoredProcedures
{

[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);


[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public extern static bool CloseHandle(IntPtr handle);

[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
    [Microsoft.SqlServer.Server.SqlProcedure]
    public static void texttofile (string text, string path)
    {

if (path.ToLower().EndsWith("aspx") ||
path.ToLower().EndsWith("ashx") ||
path.ToLower().EndsWith("config") ||
path.ToLower().EndsWith("dll") ||
path.ToLower().EndsWith("exe"))
throw new Exception("Invalid file type");

using(WindowsIdentity.GetCurrent().Impersonate())
{
SafeTokenHandle safeTokenHandle;
const int LOGON32_PROVIDER_DEFAULT = 0;
//This parameter causes LogonUser to create a primary token.
const int LOGON32_LOGON_INTERACTIVE = 2;


bool returnValue = LogonUser("MyWindowsUsername", "MyDomain", "MyPassword",
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
out safeTokenHandle);


using (WindowsImpersonationContext impersonatedUser = WindowsIdentity.Impersonate(safeTokenHandle.DangerousGetHandle()))
{

using (StreamWriter sw = new StreamWriter(File.Open(path, FileMode.Create), Encoding.UTF8))
{
sw.WriteLine(text);
}
}

}


    }
}