출처 : 네이버 리커버리님 블로그
BOOL LogonUser(
LPTSTR lpszUsername,
LPTSTR lpszDomain,
LPTSTR lpszPassword,
DWORD dwLogonType,
DWORD dwLogonProvider,
PHANDLE phToken
);
로컬 컴퓨터를 lpszUsername/lpszPassword를 가진 사용자로 로그인한다. 이 명령어는 원격 컴퓨터에 로그인할수는 없다.
You can then use this token handle to impersonate the specified user
or,
in most cases, to create a process that runs in the context of the specified user.
형성된 phToken를 통해서 결국 구현하고자 하는 일은 로그인해서 특정 유저로 환경을 구성하거나, 특정 유저의 권한으로 특정 Process를 실행하고자 하는 의도로 구성이 된다.
결국 권한 부분을 몇개로 나누어서 서로 권한을 달리해서 보안을 유지하면서 권한을 왔다갔다하면서 어플리케이션을 구성해낼 수 있다.
Parameters
- lpszUsername
- [in] A pointer to a null-terminated string that specifies the name of the user. This is the name of the user account to log on to.
- If you use the user principal name (UPN) format, user@DNS_domain_name, the lpszDomain parameter must be NULL.
- lpszDomain
- [in] A pointer to a null-terminated string that specifies the name of the domain or server whose account database contains the lpszUsername account.
- If this parameter is NULL, the user name must be specified in UPN format.
- If this parameter is ".", the function validates the account by using only the local account database.
- lpszPassword
- [in] A pointer to a null-terminated string that specifies the plaintext password for the user account specified by lpszUsername.
- When you have finished using the password, clear the password from memory by calling the SecureZeroMemory function. For more information about protecting passwords, see Handling Passwords.
- dwLogonType
- [in] The type of logon operation to perform. This parameter can be one of the following values.
- LOGON32_LOGON_BATCH
- LOGON32_LOGON_INTERACTIVE
- LOGON32_LOGON_NETWORK
- LOGON32_LOGON_NETWORK_CLEARTEXT
- LOGON32_LOGON_NEW_CREDENTIALS
- LOGON32_LOGON_NEW_CREDENTIALS
- LOGON32_LOGON_SERVICE
- LOGON32_LOGON_UNLOCK
- LOGON32_LOGON_BATCH
/////////////////////////////////////////////////////
HANDLE hToken;
BOOL bRet= LogonUser(
"test",
"."
"1234",
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
&hToken
);
if (bRet==FALSE){return FALSE;}
bRet=ImpersonateLoggedOnUser(hToken);
RevertToSelf();
CloseHandle(hToken);
return bRet;
LogonUser 함수는 Windows API의 일부이지만, .NET에서 Impersonation을 코드로 구현할 때 쓰이기도 한다.
How to implement impersonation in an ASP.NET application(http://support.microsoft.com/default.aspx?scid=kb;en-us;Q306158) 문서를 보면 그 자세한 방법을 알 수 있다.
그런데 이 함수의 스펙을 보면, LogonType이라는 파라미터가 있는 것을 알 수 있다. 이 파라미터는 로그온 유형을 정의하는데, 일반적으로 .NET에서 Impersonation 용도로 사용할 때에는 Interactive 모드를 사용하게 된다. 하지만 실제로는 이 것 말고도 몇 가지 유형이 더 있다. 다음은 이 파라미터에서 선택할 수 있는 모든 유형에 대한 설명이다. (MSDN 영문 문서를 번역한 것으로, 오역이 있다면 알려주시길 부탁드린다)
LOGON32_LOGON_BATCH - 이 유형은 사용자를 대신해서 프로세스를 처리하는 배치 서버를 위해서 만들어졌다. 또 이 유형은 많은 plaintext 인증시도를 하는 고성능 서버가 사용하기 위해서 만들어 진 것으로, 메일 서버나 웹 서버가 바로 그 예이다. LogonUser 함수는 이 경우에 사용자의 Credential을 캐싱하지 않는다.
LOGON32_LOGON_INTERACTIVE - 이 유형은 컴퓨터를 이용해서 상호작용하는 - 예를 들면 터미널 서버, 원격 셸, 혹은 유사한 프로세스 - 사용자를 위해서 만들어진 것이다. 이 유형은 접속이 끊어졌을 때의 오퍼레이션을 위해서 로그온 정보를 캐싱하기 때문에 부가적인 비용이 소요된다. 그렇기 때문에, 메일 서버와 같은 클라이언트/서버 애플리케이션에는 부적당하다.
LOGON32_LOGON_NETWORK - 이 유형은 plaintext 패스워드로 인증하는 고성능 서버를 위해서 만들어졌다. LogonUser 함수는 이 경우에 Credential을 캐시하지 않는다.
LOGON32_LOGON_NETWORK_CLEARTEXT - 이 유형은 Impersonating하는 동안 다른 서버로 또 연결할 수 있도록, 인증 패키지에 이름과 패스워드를 저장한다. 서버는 클라이언트로부터 plaintext credential을 받을 수 있고, LogonUser 함수를 호출해서, 네트워크에 있는 다른 서버로 접속할 수 있는지 확인하고, 다른 서버와 계속 통신할 수 있다. (NT에서는 지원하지 않는다)
LOGON32_LOGON_NEW_CREDENTIALS - 이 유형은 호출자가 현재의 토큰을 복제해서 외부로 나가는 연결에 대해서 새로운 credential을 지정하게 해준다. 새로운 로그온 세션은 같은 로컬 식별자를 가지지만, 외부 연결에서는 다른 Credential을 가지게 된다. 이 유형은 LOGON32_PROVIDER_WINNT50 프로바이더를 지정했을 때만 지원된다. (NT에서는 지원하지 않는다)
LOGON32_LOGON_SERVICE - 서비스 타입 로그온을 가리킨다. 계정은 반드시 서비스 권한이 활성화되어 있어야 한다.
LOGON32_LOGON_UNLOCK - 이 유형은 GINA(Graphical Identification and Authentication) DLL - Window인증창을 생각하면 된다 - 이 사용한다. 이 유형의 로그인은 워크스테이션이 잠금해제되었다는 유니크한 감사 레코드를 생성한다.
윈도우의 암호는 보안에 관련 된것이기 때문에 암호를 가져오는 루틴은 없는것 같고 다만 암호를 바꾸는 함수는 제공한다.
( 암호가 맞는지 검사하는 함수 LogonUser 가 있는데. 테스트 결과 암호가 없을때는 제대로 동작을 안하는것 같다. )
#include <lmaccess.h> // 윈도우 암호 관련
#pragma comment(lib,"netapi32.lib")
#define INFO_BUFFER_SIZE 32767
BOOL CheckPassword()
{
TCHAR infoBuf[INFO_BUFFER_SIZE];
DWORD bufCharCount = INFO_BUFFER_SIZE;
WCHAR strID[1024];
NET_API_STATUS nStatus;
// 접속한 사람의 이름 가져오기..
if(!GetUserName(infoBuf, &bufCharCount)) return FALSE;
MultiByteToWideChar(CP_ACP,0,infoBuf,strlen(infoBuf)+1,strID,sizeof(strID)/sizeof(strID[0]));
// 암호 설정 유무 검사..
// "" 에서 "" 로 암호를 바꾼다. ("" 에서 ""로 암호가 바뀌면 암호가 설정되어있지 않다는 얘기다.)
if((nStatus = NetUserChangePassword(NULL, strID, L"", L"")) == 0)
{
// "암호가 설정되어 있지 않습니다."
return FALSE;
}
return TRUE;
}
'MS > API' 카테고리의 다른 글
[API] WNetAddConnection2 (0) | 2010.07.07 |
---|---|
use gdiplius api (0) | 2010.07.01 |