Identificatore di sicurezza

L'identificatore di sicurezza viene usato da Windows come valore definitivo per distinguere le entità di sicurezza tra loro. Ad esempio, un identificatore di sicurezza univoco viene assegnato a ogni nuovo account creato per singoli utenti nel sistema. Per un file system, viene effettivamente usato solo questo SID.

Nella figura seguente viene illustrata la struttura dell'identificatore di sicurezza.

diagramma che illustra la struttura dell'identificatore di sicurezza.

Oltre ai SID univoci, il sistema Windows definisce un set di identificatori noti. Ad esempio, l'amministratore locale è un SID noto. Windows fornisce un meccanismo in-kernel per la conversione tra SID e nomi utente all'interno dell'ambiente kernel. Queste chiamate di funzione sono disponibili dal driver ksecdd, che implementa queste funzioni usando i servizi helper in modalità utente. Di conseguenza, l'uso all'interno di file system deve rispettare le normali regole per la comunicazione con i servizi in modalità utente. Queste chiamate non possono essere usate durante il paging dei file di I/O.

Le funzioni includono quanto segue:

  • SecMakeSPN: crea una stringa di nome del provider di servizi che può essere usata durante la comunicazione con provider di servizi di sicurezza specifici.

  • SecMakeSPNEx: versione aumentata di SecMakeSPN. Questa funzione è disponibile in Microsoft Windows XP e versioni successive di Windows.

  • SecMakeSPNEx2: versione aumentata di SecMakeSPNEx. Questa funzione è disponibile in Windows Vista, Windows Server 2008 e versioni successive di Windows.

  • SecLookupAccountSid, dato un SID, questa routine restituirà un nome account. Questa funzione è disponibile in Windows XP e versioni successive.

  • SecLookupAccountName, in base al nome di un account, questa routine recupera il SID. Questa funzione è disponibile in Windows XP e versioni successive.

  • SecLookupWellKnownSid, dato un tipo SID noto, questa routine restituirà il SID corretto. Questa funzione è disponibile in Windows Server 2003 e versioni successive.

Inoltre, qualsiasi driver del kernel può creare un SID usando le routine di libreria di runtime standard seguenti:

  • RtlInitializeSid: inizializza un buffer per un nuovo SID.

  • RtlLengthSid: determina le dimensioni del SID archiviato all'interno del buffer specificato.

  • RtlValidSid: determina se il buffer SID specificato è un buffer formattato valido.

Si noti che RtlLengthSid e RtlValidSid presuppongono che l'intestazione fissa a 8 byte per un SID sia presente. Quindi un driver deve verificare la lunghezza minima per un'intestazione SID prima di chiamare queste funzioni.

Sebbene siano presenti diverse altre funzioni RTL, queste sono le funzioni primarie necessarie quando si costruisce un SID.

Nell'esempio di codice seguente viene illustrato come creare un SID per l'entità "sistema locale":

{
    //
    // temporary stack-based storage for an SID
    //
    UCHAR sidBuffer[128];
    PISID localSid = (PISID) sidBuffer;
    SID_IDENTIFIER_AUTHORITY localSidAuthority = 
        SECURITY_NT_AUTHORITY;

    //
    // build the local system SID
    //
    RtlZeroMemory(sidBuffer, sizeof(sidBuffer));
 
    localSid->Revision = SID_REVISION;
    localSid->SubAuthorityCount = 1;
    localSid->IdentifierAuthority = localSidAuthority;
    localSid->SubAuthority[0] = SECURITY_LOCAL_SYSTEM_RID;
 
    //
    // make sure it is valid
    //
    if (!RtlValidSid(localSid)) {
        DbgPrint("no dice - SID is invalid\n");
        return(1);
    }
}

Si noti che questa operazione potrebbe essere stata eseguita anche usando la funzione più semplice SecLookupWellKnownSid introdotta in Windows Server 2003.

Nell'esempio di codice seguente viene illustrato come creare un SID usando la funzione SecLookupWellKnownSid per l'entità "sistema locale":

{
    UCHAR sidBuffer[128];
    PISID localSid = (PISID) sidBuffer;
    SIZE_T sidSize;
    status = SecLookupWellKnownSid(WinLocalSid,
                                   &localSid,
                                   sizeof(sidBuffer),
                                   &sidSize);

    if (!NT_SUCCESS(status)) {
      //
      // error handling
      //
    }
  }

Uno di questi approcci è valido, anche se quest'ultimo codice è preferito. Si noti che questi esempi di codice usano buffer locali per l'archiviazione del SID. Questi buffer non possono essere usati all'esterno del contesto di chiamata corrente. Se il buffer SID deve essere persistente, il buffer deve essere allocato dalla memoria del pool.