Esempio: Aggiunta di un token helper a un processo di trasferimento BITS
È possibile configurare un processo di trasferimento BITS (Background Intelligent Transfer Service) con un token di sicurezza aggiuntivo. Il processo di trasferimento BITS usa questo token helper per l'autenticazione e per accedere alle risorse.
Per altre informazioni, vedere Token helper per i processi di trasferimento BITS.
La procedura seguente crea un processo di trasferimento BITS nel contesto dell'utente locale, ottiene le credenziali di un secondo utente, crea un token helper con queste credenziali e quindi imposta il token helper nel processo di trasferimento BITS.
In questo esempio viene usata l'intestazione e l'implementazione definita in Esempio: Classi comuni.
Per aggiungere un token helper a un processo di trasferimento BITS
Inizializzare i parametri COM chiamando la funzione CCoInitializer. Per altre informazioni sulla funzione CCoInitializer, vedere Esempio: Classi comuni.
Ottenere un puntatore all'interfaccia IBackgroundCopyJob . In questo esempio viene usata la classe CComPtr per gestire i puntatori di interfaccia COM.
Inizializzare la sicurezza del processo COM chiamando CoInitializeSecurity. BITS richiede almeno il livello IMPERSONATE di rappresentazione. BITS ha esito negativo con E_ACCESSDENIED se il livello di rappresentazione corretto non è impostato.
Ottenere un puntatore all'interfaccia IBackgroundCopyManager e ottenere il localizzatore iniziale in BITS chiamando la funzione CoCreateInstance.
Creare un processo di trasferimento BITS chiamando il metodo IBackgroundCopyManager::CreateJob.
Ottenere un puntatore all'interfaccia di callback CNotifyInterface e chiamare il metodo IBackgroundCopyJob::SetNotifyInterface per ricevere la notifica degli eventi correlati al processo. Per altre informazioni su CNotifyInterface, vedere Esempio: Classi comuni.
Chiamare il metodo IBackgroundCopyJob::SetNotifyFlags per impostare i tipi di notifiche da ricevere. In questo esempio vengono impostati i flag BG_NOTIFY_JOB_TRANSFERRED e BG_NOTIFY_JOB_ERROR .
Ottenere un puntatore all'interfaccia IBitsTokenOptions chiamando il metodo IBackgroundCopyJob::QueryInterface con l'identificatore di interfaccia appropriato.
Tentare di accedere all'utente del token helper. Creare un handle di rappresentazione e chiamare la funzione LogonUser per popolare l'handle di rappresentazione. In caso di esito positivo, chiamare la funzione ImpersonateLoggedOnUser. Se l'esempio chiama la funzione RevertToSelf per terminare la rappresentazione dell'utente connesso, viene generato un errore e l'handle viene chiuso.
Chiamare il metodo IBitsTokenOptions::SetHelperToken per rappresentare il token dell'utente connesso. Se questo metodo ha esito negativo, l'esempio chiama la funzione RevertToSelf per terminare la rappresentazione dell'utente connesso, viene generato un errore e l'handle viene chiuso.
Nota
Nelle versioni supportate di Windows precedenti a Windows 10, versione 1607, il proprietario del processo deve avere credenziali amministrative per chiamare il metodo IBitsTokenOptions::SetHelperToken.
A partire da Windows 10, versione 1607, i proprietari di processi non amministratori possono impostare token helper non amministratore nei processi BITS di cui sono proprietari. I proprietari dei processi devono comunque disporre di credenziali amministrative per impostare i token helper con privilegi di amministratore.
Chiamare il metodo IBitsTokenOptions::SetHelperTokenFlags per specificare le risorse a cui accedere usando il contesto di sicurezza del token helper.
Al termine della rappresentazione, nell'esempio viene chiamata la funzione RevertToSelf per terminare la rappresentazione dell'utente connesso e l'handle viene chiuso.
Aggiungere file al processo di trasferimento BITS chiamando IBackgroundCopyJob::AddFile.
Dopo aver aggiunto il file, chiama IBackgroundCopyJob::Resume per riprendere il processo.
Configurare un ciclo while per attendere il messaggio di chiusura dall'interfaccia di callback durante il trasferimento del processo. Il ciclo while usa la funzione GetTickCount per recuperare il numero di millisecondi trascorsi dall'avvio del trasferimento del processo.
Al termine del processo di trasferimento BITS, rimuovere il processo dalla coda chiamando IBackgroundCopyJob::Complete.
Nell'esempio di codice seguente viene aggiunto un token helper a un processo di trasferimento BITS.
#include <bits.h>
#include <bits4_0.h>
#include <stdio.h>
#include <tchar.h>
#include <lm.h>
#include <iostream>
#include <exception>
#include <string>
#include <atlbase.h>
#include <memory>
#include <new>
#include "CommonCode.h"
void HelperToken(const LPWSTR &remoteFile, const LPWSTR &localFile, const LPWSTR &domain, const LPWSTR &username, const LPWSTR &password)
{
// If CoInitializeEx fails, the exception is unhandled and the program terminates
CCoInitializer coInitializer(COINIT_APARTMENTTHREADED);
CComPtr<IBackgroundCopyJob> pJob;
try
{
//The impersonation level must be at least RPC_C_IMP_LEVEL_IMPERSONATE.
HRESULT hr = CoInitializeSecurity(
NULL,
-1,
NULL,
NULL,
RPC_C_AUTHN_LEVEL_CONNECT,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_DYNAMIC_CLOAKING,
0
);
if (FAILED(hr))
{
throw MyException(hr, L"CoInitializeSecurity");
}
// Connect to BITS.
CComPtr<IBackgroundCopyManager> pQueueMgr;
hr = CoCreateInstance(__uuidof(BackgroundCopyManager), NULL,
CLSCTX_LOCAL_SERVER,
__uuidof(IBackgroundCopyManager),
(void **)&pQueueMgr);
if (FAILED(hr))
{
// Failed to connect.
throw MyException(hr, L"CoCreateInstance");
}
// Create a job.
wprintf(L"Creating Job...\n");
GUID guidJob;
hr = pQueueMgr->CreateJob(L"HelperTokenSample",
BG_JOB_TYPE_DOWNLOAD,
&guidJob,
&pJob);
if(FAILED(hr))
{
// Failed to create job.
throw MyException(hr, L"CreateJob");
}
// Set the File Completed call.
CComPtr<CNotifyInterface> pNotify;
pNotify = new CNotifyInterface();
hr = pJob->SetNotifyInterface(pNotify);
if (FAILED(hr))
{
// Failed to SetNotifyInterface.
throw MyException(hr, L"SetNotifyInterface");
}
hr = pJob->SetNotifyFlags(BG_NOTIFY_JOB_TRANSFERRED |
BG_NOTIFY_JOB_ERROR);
if (FAILED(hr))
{
// Failed to SetNotifyFlags.
throw MyException(hr, L"SetNotifyFlags");
}
//Retrieve the IBitsTokenOptions interface pointer from the BITS transfer job.
CComPtr<IBitsTokenOptions> pTokenOptions;
hr = pJob->QueryInterface(__uuidof(IBitsTokenOptions), (void** ) &pTokenOptions);
if (FAILED(hr))
{
// Failed to QueryInterface.
throw MyException(hr, L"QueryInterface");
}
// Log on user of the helper token.
wprintf(L"Credentials for helper token %s\\%s %s\n", domain, username, password);
HANDLE hImpersonation = INVALID_HANDLE_VALUE;
if(LogonUser(username, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &hImpersonation))
{
// Impersonate the logged-on user.
if(ImpersonateLoggedOnUser(hImpersonation))
{
// Configure the impersonated logged-on user's token as the helper token.
hr = pTokenOptions->SetHelperToken();
if (FAILED(hr))
{
//Failed to set helper token.
CloseHandle(hImpersonation);
RevertToSelf();
throw MyException(hr, L"SetHelperToken");
}
hr = pTokenOptions->SetHelperTokenFlags(BG_TOKEN_LOCAL_FILE);
if (FAILED(hr))
{
//Failed to set helper token flags.
CloseHandle(hImpersonation);
RevertToSelf();
throw MyException(hr, L"SetHelperTokenFlags");
}
RevertToSelf();
}
CloseHandle(hImpersonation);
}
// Add a file.
// Replace parameters with variables that contain valid paths.
wprintf(L"Adding File to Job\n");
hr = pJob->AddFile(remoteFile,localFile);
if(FAILED(hr))
{
//Failed to add file to job.
throw MyException(hr, L"AddFile");
}
//Resume the job.
wprintf(L"Resuming Job...\n");
hr = pJob->Resume();
if (FAILED(hr))
{
// Resume failed.
throw MyException(hr, L"Resume");
}
}
catch(const std::bad_alloc &)
{
wprintf(L"Memory allocation failed");
if (pJob)
{
pJob->Cancel();
}
return;
}
catch(const MyException &ex)
{
wprintf(L"Error 0x%x occurred during operation", ex.Error);
if (pJob)
{
pJob->Cancel();
}
return;
}
wprintf(L"Transferring file and waiting for callback.\n");
// Wait for QuitMessage from CallBack
DWORD dwLimit = GetTickCount() + (15 * 60 * 1000); // set 15 minute limit
while (dwLimit > GetTickCount())
{
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
// If it is a quit message, exit.
if (msg.message == WM_QUIT)
{
return;
}
// Otherwise, dispatch the message.
DispatchMessage(&msg);
} // End of PeekMessage while loop
}
pJob->Cancel();
return;
}
void _cdecl _tmain(int argc, LPWSTR* argv)
{
if (argc != 6)
{
wprintf(L"Usage:");
wprintf(L"%s ", argv[0]);
wprintf(L"[remote name] [local name] [helpertoken domain] [helpertoken userrname] [helpertoken password]\n");
return;
}
HelperToken(argv[1],argv[2],argv[3],argv[4],argv[5]);
}
Argomenti correlati