잊지 않겠습니다.

'인증'에 해당되는 글 1건

  1. 2010.11.11 WindowsIdentify 를 이용한 인증
Network Copy등을 하기 위해서 ID와 Password를 알고 있는데, code 상으로 구현하는 방법을 한번 정리.

일단, WindowsIdentify는 win32 dll을 이용하고, Windows Token을 사용한다. Windows Token은 어떤 시스템에 Logon한 이후에, 일정시간 유지가 되는 Windows의 memory안에 자신의 Identity를 저장하게 된다. 

먼저, Win32의 [DllImport("advapi32.dll", SetLastError = true)] 를 이용해서 LogonUser method를 dll import 시켜온다.

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


마지막 값인 phToken값을 이용해서 WindowsIdentify를 얻어 내면 타 시스템에 접근이 가능하다. 여기에서 userName은 upn형태로 넣어져야지 되며, 이 형식은 ykyoon@vplex.net 과 같은 email과 같은 형식으로 입력이 되어야지 된다.

다음은 NetworkCopy를 하는 Test code이다. 




[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
[DllImport("kernel32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
private unsafe static extern int FormatMessage(int dwFlags, ref IntPtr lpSource, int dwMessageId, int dwLanguageId, ref String lpBuffer, int nSize, IntPtr* Arguments);

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public extern static bool CloseHandle(IntPtr handle);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public extern static bool DuplicateToken(IntPtr ExistingTokenHandle, int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);

public unsafe static string GetErrorMessage(int errorCode)
{
    int FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100;
    int FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200;
    int FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;

    int messageSize = 255;
    String lpMsgBuf = "";
    int dwFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;

    IntPtr ptrlpSource = IntPtr.Zero;
    IntPtr prtArguments = IntPtr.Zero;

    int retVal = FormatMessage(dwFlags, ref ptrlpSource, errorCode, 0, ref lpMsgBuf, messageSize, &prtArguments);
    if(0 == retVal)
    {
        throw new Exception("Failed to format message for error code " + errorCode + ". ");
    }

    return lpMsgBuf;
}

static void Main(string[] args)
{
    const int LOGON32_PROVIDER_DEFAULT = 0;
    const int LOGON32_LOGON_INTERACTIVE = 2;
    const int SecurityImpersonation = 2;

    var tokenHandle = IntPtr.Zero;
    bool returnValue = LogonUser(@"Administrator@vplex.net", "network ip in here", "this is password", 9, 0, ref tokenHandle);
    Console.WriteLine("LogonUser called.");
    if(false == returnValue)
    {
        int ret = Marshal.GetLastWin32Error();
        Console.WriteLine("LogonUser failed with error code : {0}", ret);
        Console.WriteLine("\nError: [{0}] {1}\n", ret, GetErrorMessage(ret));
        int errorCode = 0x5; //ERROR_ACCESS_DENIED
        throw new System.ComponentModel.Win32Exception(errorCode);
    }
    else
    {
        var ykyoonAdmin = new WindowsIdentity(tokenHandle);
        var wic = ykyoonAdmin.Impersonate();
        File.Copy("C:\\System.Web.Mvc.dll", "\\\\10.30.3.24\\c$\\abc.dll", true);
        wic.Undo();
        wic.Dispose();
    }
    CloseHandle(tokenHandle);
}
Posted by Y2K
,