Share via


Identitätswechsel

Einige Dateisysteme finden es möglicherweise nützlich, Vorgänge im Namen des ursprünglichen Aufrufers auszuführen. Beispielsweise muss ein Netzwerkdateisystem möglicherweise die Sicherheitsinformationen des Aufrufers zum Zeitpunkt des Öffnens einer Datei erfassen, damit ein nachfolgender Vorgang mit den entsprechenden Anmeldeinformationen ausgeführt werden kann. Zweifellos gibt es zahlreiche andere Sonderfälle, in denen diese Art von Feature nützlich ist, sowohl innerhalb eines Dateisystems als auch in bestimmten Anwendungen.

Zu den wichtigsten Routinen, die für den Identitätswechsel erforderlich sind, gehören:

  • PsImpersonateClientSeImpersonateClientEx initiiert identitätswechsel. Sofern kein bestimmter Thread angegeben ist, erfolgt der Identitätswechsel im aktuellen Threadkontext.

  • PsRevertToSelf- beendet den Identitätswechsel innerhalb des aktuellen Threadkontexts.

  • PsReferencePrimaryToken enthält einen Verweis auf das primäre Token (Prozess) für den angegebenen Prozess. Diese Funktion kann verwendet werden, um das Token für jeden Prozess im System zu erfassen.

  • PsDereferencePrimaryToken gibt einen Verweis auf ein zuvor referenziertes primäres Token frei.

  • SeCreateClientSecurityFromSubjectContext: Gibt einen Clientsicherheitskontext zurück, der für den Identitätswechsel aus einem Antragstellerkontext nützlich ist (z. B . während der IRP_MJ_CREATE Behandlung für die FSD bereitgestellt).

  • SeCreateClientSecurity: erstellt einen Clientsicherheitskontext basierend auf den Sicherheitsanmeldeinformationen eines vorhandenen Threads im System.

  • ImpersonateSecurityContext: imitiert den Sicherheitskontext innerhalb ksecdd.sys, des Kernelsicherheitsdiensts.

  • RevertSecurityContext: Beendet den Identitätswechsel innerhalb ksecdd.sys, dem Kernelsicherheitsdienst.

Der Identitätswechsel ist einfach zu implementieren. Im folgenden Codebeispiel wird der grundlegende Identitätswechsel veranschaulicht:

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

Es gibt zahlreiche Varianten dieses Identitätswechselcodes, die Dateisystementwicklern zur Verfügung stehen, aber dies bietet eine grundlegende Darstellung der Technik.