Condividi tramite


Rappresentazione

Alcuni file system potrebbero risultare utili per eseguire operazioni per conto del chiamante originale. Ad esempio, un file system di rete potrebbe dover acquisire le informazioni di sicurezza del chiamante al momento dell'apertura di un file in modo che sia possibile eseguire un'operazione successiva usando le credenziali appropriate. Senza dubbio ci sono numerosi altri casi speciali in cui questo tipo di funzionalità è utile, sia all'interno di un file system che in applicazioni specifiche.

Le routine chiave necessarie per la rappresentazione includono:

  • PsImpersonateClientSeImpersonateClientEx---initiates impersonation. A meno che non venga indicato un thread specifico, la rappresentazione viene eseguita nel contesto del thread corrente.

  • PsRevertToSelf---termina la rappresentazione all'interno del contesto del thread corrente.

  • PsReferencePrimaryToken- contiene un riferimento sul token primario (processo) per il processo specificato. Questa funzione può essere usata per acquisire il token per qualsiasi processo nel sistema.

  • PsDereferencePrimaryToken- rilascia un riferimento su un token primario a cui si fa riferimento in precedenza.

  • SeCreateClientSecurityFromSubjectContext--restituisce un contesto di sicurezza client utile per la rappresentazione da un contesto soggetto (fornito al fsd durante la gestione del IRP_MJ_CREATE , ad esempio).

  • SeCreateClientSecurity: crea un contesto di sicurezza client basato sulle credenziali di sicurezza di un thread esistente nel sistema.

  • ImpersonateSecurityContext---impersona il contesto di sicurezza all'interno di ksecdd.sys, il servizio di sicurezza del kernel.

  • RevertSecurityContext---termina la rappresentazione all'interno di ksecdd.sys, il servizio di sicurezza del kernel.

La rappresentazione è semplice da implementare. Nell'esempio di codice seguente viene illustrata la rappresentazione di base:

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;
}

Esistono numerose varianti di questo codice di rappresentazione disponibili per gli sviluppatori di file system, ma questo fornisce un'illustrazione di base della tecnica.