Пример. Добавление вспомогательного маркера в задание передачи BITS
Вы можете настроить задание передачи фоновой интеллектуальной службы передачи (BITS) с дополнительным маркером безопасности. Задание передачи BITS использует этот вспомогательный маркер для проверки подлинности и доступа к ресурсам.
Дополнительные сведения см. в разделе вспомогательные маркеры для заданий передачи BITS.
Следующая процедура создает задание передачи BITS в контексте локального пользователя, получает учетные данные второго пользователя, создает вспомогательный маркер с этими учетными данными, а затем задает вспомогательный маркер в задании передачи BITS.
В этом примере используется заголовок и реализация, определенная в примере: общие классы.
Добавление вспомогательного маркера в задание передачи BITS
Инициализация параметров COM путем вызова функции CCoInitializer. Дополнительные сведения о функции CCoInitializer см. в примере : Общие классы.
Получите указатель на интерфейс IBackgroundCopyJob. В этом примере для управления указателями интерфейса COM используется класс CComPtr.
Инициализация безопасности процесса COM путем вызова CoInitializeSecurity. BITS требует по крайней мере уровня олицетворения олицетворения. BITS завершается ошибкой с E_ACCESSDENIED, если правильный уровень олицетворения не задан.
Получите указатель на интерфейс IBackgroundCopyManager и получите начальный указатель на BITS, вызвав функцию CoCreateInstance.
Создайте задание передачи BITS, вызвав метод IBackgroundCopyManager::CreateJob.
Получите указатель на интерфейс обратного вызова CNotifyInterface и вызовите метод IBackgroundCopyJob::SetNotifyInterface для получения уведомлений о событиях, связанных с заданием. Дополнительные сведения о CNotifyInterface см. в разделе "Пример: общие классы".
Вызовите метод IBackgroundCopyJob::SetNotifyFlags, чтобы задать типы уведомлений для получения. В этом примере задаются флаги BG_NOTIFY_JOB_TRANSFERRED и BG_NOTIFY_JOB_ERROR .
Получите указатель на интерфейс IBitsTokenOptions, вызвав метод IBackgroundCopyJob::QueryInterface с соответствующим идентификатором интерфейса.
Попытайтесь войти в систему пользователя вспомогательного маркера. Создайте дескриптор олицетворения и вызовите функцию LogonUser, чтобы заполнить дескриптор олицетворения. В случае успешного выполнения вызовите функцию ImpersonateLoggedOnUser. Если это не удалось, в примере вызывается функция RevertToSelf для завершения олицетворения пользователя, вошедшего в систему, возникает ошибка, и дескриптор закрывается.
Вызовите метод IBitsTokenOptions::SetHelperToken, чтобы олицетворить токен пользователя, вошедшего в систему. Если этот метод завершается ошибкой, в примере вызывается функция RevertToSelf для прекращения олицетворения пользователя, вошедшего в систему, возникает ошибка, и дескриптор закрывается.
Примечание.
В поддерживаемых версиях Windows до Windows 10 версии 1607 владелец задания должен иметь административные учетные данные для вызова метода IBitsTokenOptions::SetHelperTokenToken.
Начиная с Windows 10 версии 1607, владельцы заданий, не являющихся администраторами, могут задавать вспомогательные маркеры неадминистратора в заданиях BITS, которыми они принадлежат. Владельцы заданий по-прежнему должны иметь административные учетные данные, чтобы задать вспомогательные маркеры с правами администратора.
Вызовите метод IBitsTokenOptions::SetHelperTokenFlags, чтобы указать, какие ресурсы будут доступны с помощью контекста безопасности вспомогательного маркера.
После завершения олицетворения в примере вызывается функция RevertToSelf для завершения олицетворения вошедшего в систему пользователя, и дескриптор закрывается.
Добавьте файлы в задание передачи BITS путем вызова IBackgroundCopyJob::AddFile.
После добавления файла вызовите IBackgroundCopyJob::Resume , чтобы возобновить задание.
Настройте цикл времени, чтобы дождаться выхода сообщения из интерфейса обратного вызова во время передачи задания. Цикл while использует функцию GetTickCount для получения количества миллисекундах, прошедших с момента передачи задания.
После завершения задания передачи BITS удалите задание из очереди, вызвав IBackgroundCopyJob::Complete.
В следующем примере кода в задание передачи 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]);
}
См. также