Oi, Pessoal...
Estou tendo problemas para usar o Impersonate na minha aplicacao.
Meu problema é o seguinte:
Tenho uma aplicacao que é instalada no servidor. Ao rodar o executavel, ele deve verificar e instalar (se não estiver) um componente de autenticação (DLL). Esta instalação deve ser feita na pasta %ProgramFiles%\MeuDir
(que no Windows em PT_BR seria C:\Arquivos de Programas\MeuDir) da minha maquina LOCAL.
Meu usuario (padrao) não tem direitos de Administrador, mas a configuração da aplicação contem nome_usuário/senha de um administrador do dominio da rede.
Estou tentando o impersonate conforme codigo abaixo:
//////////////////////////////// Inicio das Defs //////////////////////////
szModuleName = "CopiaArqs.exe" // Executavel a rodar...
szCommandLine = "\"C:\\Tempo\"" \"C:\\Arquivos de Programas\\Grebs\"" // "DirOrigem DirDestino"
//////////////////////////////// Inicio do Codigo //////////////////////////
HANDLE m_hUserToken;
HANDLE m_hNewHandle;
DWORD m_dwErrorCode;
// Domain name was specified
if(domain.length() > 0) {
bLoggedOn = LogonUser(userName.c_str(), domain.c_str(), password.c_str(),
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &m_hUserToken);
} else {
bLoggedOn = LogonUser(userName.c_str(), domain.c_str(), password.c_str(),
LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_WINNT50, &m_hUserToken);
}
if(!bLoggedOn) {
m_dwErrorCode = GetLastError();
return false;
}
// Now impersonate them
if(!ImpersonateLoggedOnUser(m_hUserToken)) {
m_dwErrorCode = GetLastError();
ExpandErrorMessage(m_dwErrorCode);
return false;
}
PROCESS_INFORMATION Pi;
STARTUPINFO Si;
char* pCmdLine;
BOOL bRetorno;
int inTamanho;
memset(&Si, 0, sizeof(STARTUPINFO));
Si.cb= sizeof(STARTUPINFO);
GetStartupInfo(&Si);
inTamanho = szCommandLine.length() + 1;
pCmdLine = new char[inTamanho];
if(!pCmdLine) {
return FALSE;
}
memset(pCmdLine, 0, inTamanho);
strcpy(pCmdLine, szCommandLine.c_str());
DuplicateTokenEx(m_hUserToken, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenImpersonation , &m_hNewHandle);
bRetorno = CreateProcessAsUser(m_hNewHandle, szModuleName.c_str(), pCmdLine, NULL, NULL, FALSE,
NORMAL_PRIORITY_CLASS, NULL, NULL, &Si, &Pi);
if (!bRetorno) {
m_dwErrorCode = GetLastError();
ExpandErrorMessage(m_dwErrorCode);
}
CloseHandle(m_hNewHandle);
m_hNewHandle = NULL;
delete [] pCmdLine;
//////////////////////////////// Fim do Codigo //////////////////////////
Antes, obtinha erro 1314 ("Usuario nao tem direitos") ao tentar criar o novo Processo (copiar os arquivos).
Apos duplicar o Token (linha DuplicateTokenEx()... ) o erro passou a ser 1349 (Uso incorreto do Token/Token incompativel).
O codigo acima é uma copia/adaptação, pois está dividido em varias funções/métodos de uma classe (CImpersonate).
Por isso coloquei os valores de alguns membros (szModuleName, etc...)
Particularmente, dividi em funcoes para Logon/Logoff e CreateNewProcess.
Teoricamente o impersonate funciona (LogonUser com sucesso), falhando somente no CreateNewProcess.
Os exemplos (abundantes) na net nao demonstram como resolver o problema, sendo comum a sugestao de rodar o aplicativo como ADMIN (via RUNAS ou manifest). Esta opção não é viável, pois seria uma quebra de segurança
maior que a falta do componente... :-)
Vale salientar que somente neste momento (copia da DLL no primeiro acesso) é que necessito de direitos de administrador.
Desde já agradeco a toda e qualquer ajuda.
Sem mais para o momento,
Fernando / Tercete
C/C++ Developer