Олицетворение
В некоторых файловых системах может оказаться полезным выполнять операции от имени исходного вызывающего объекта. Например, сетевой файловой системе может потребоваться записать сведения о безопасности вызывающего абонента во время открытия файла, чтобы можно было выполнить последующую операцию с использованием соответствующих учетных данных. Несомненно, существует множество других особых случаев, когда этот тип функции полезен как в файловой системе, так и в конкретных приложениях.
Основные процедуры, необходимые для олицетворения:
PsImpersonateClientSeImpersonateClientEx — инициирует олицетворение. Если не указан конкретный поток, олицетворение выполняется в контексте текущего потока.
PsRevertToSelf завершает олицетворение в контексте текущего потока.
PsReferencePrimaryToken — содержит ссылку на основной маркер (процесс) для указанного процесса. Эта функция может использоваться для записи маркера для любого процесса в системе.
PsDereferencePrimaryToken — освобождает ссылку на ранее упоминавшийся первичный токен.
SeCreateClientSecurityFromSubjectContext — возвращает контекст безопасности клиента, полезный для олицетворения из контекста субъекта (например, предоставляется FSD во время обработки IRP_MJ_CREATE ).
SeCreateClientSecurity создает контекст безопасности клиента на основе учетных данных безопасности существующего потока в системе.
ImpersonateSecurityContext — олицетворяет контекст безопасности в ksecdd.sys, службе безопасности ядра.
RevertSecurityContext — завершает олицетворение в ksecdd.sys, службе безопасности ядра.
Олицетворение — это прямая реализация. В следующем примере кода демонстрируется базовое олицетворение:
NTSTATUS PerformSpecialTask(IN PFSD_CONTEXT Context)
{
BOOLEAN CopyOnOpen;
BOOLEAN EffectiveOnly;
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
NTSTATUS Status;
PACCESS_TOKEN oldToken;
//
// We need to perform a task in the system process context
//
if (NULL == Context->SystemProcess) {
return STATUS_NO_TOKEN;
}
//
// Save the existing token, if any (otherwise NULL)
//
oldToken = PsReferenceImpersonationToken(PsGetCurrentThread(),
&CopyOnOpen,
&EffectiveOnly,
&ImpersonationLevel);
Status = PsImpersonateClient( PsGetCurrentThread(),
Context->SystemProcess,
TRUE,
TRUE,
SecurityImpersonation);
if (!NT_SUCCESS(Status)) {
if (oldToken)
PsDereferenceImpersonationToken(oldToken);
return Status;
}
//
// Perform task - whatever it is
//
//
// Restore to previous impersonation level
//
if (oldToken) {
Status = PsImpersonateClient(PsGetCurrentThread(),
oldToken,
CopyOnOpen,
EffectiveOnly,
ImpersonationLevel);
if (!NT_SUCCESS(Status)) {
//
// This is bad - we can't restore, we can't leave it this way
//
PsRevertToSelf();
}
PsDereferenceImpersonationToken(oldToken);
} else {
PsRevertToSelf();
}
return Status;
}
Существует множество вариантов этого кода олицетворения, доступных разработчикам файловых систем, но это дает базовую иллюстрацию метода.