struttura KERB_SMARTCARD_CSP_INFO

La struttura KERB_SMARTCARD_CSP_INFO contiene informazioni su un provider di servizi di crittografia (CSP) smart card.

Questa struttura non è dichiarata in un'intestazione pubblica.

Sintassi

typedef struct _KERB_SMARTCARD_CSP_INFO {
  DWORD dwCspInfoLen;
  DWORD MessageType;
  union {
    PVOID   ContextInformation;
    ULONG64 SpaceHolderForWow64;
  };
  DWORD flags;
  DWORD KeySpec;
  ULONG nCardNameOffset;
  ULONG nReaderNameOffset;
  ULONG nContainerNameOffset;
  ULONG nCSPNameOffset;
  TCHAR bBuffer;
} KERB_SMARTCARD_CSP_INFO, *PKERB_SMARTCARD_CSP_INFO;

Members

dwCspInfoLen

Dimensione, in byte, di questa struttura, inclusi i dati accodati.

MessageType

Tipo di messaggio passato. Questo membro deve essere impostato su 1.

ContextInformation

Riservato.

SpaceHolderForWow64

Riservato.

flags

Riservato.

KeySpec

Chiave privata da usare dal contenitore di chiavi specificato all'interno del buffer bBuffer. La chiave può essere uno dei valori seguenti, definiti in WinCrypt.h.

Value Meaning
AT_KEYEXCHANGE
1
La chiave è una chiave di scambio di chiavi.
AT_SIGNATURE
2
La chiave è una chiave di firma.

nCardNameOffset

Numero di caratteri nel buffer bBuffer che precede il nome della smart card nel buffer.

Importante

Se il nome della smart card non viene specificato, il buffer deve contenere una stringa vuota.

nReaderNameOffset

Numero di caratteri nel buffer bBuffer che precede il nome del lettore di smart card nel buffer.

Importante

Se il nome del lettore di smart card non viene specificato, il buffer deve contenere una stringa vuota.

nContainerNameOffset

Numero di caratteri nel buffer bBuffer che precede il nome del contenitore di chiavi nel buffer. Questa stringa non può essere vuota.

nCSPNameOffset

Numero di caratteri nel buffer bBuffer che precede il nome del provider di servizi di configurazione nel buffer.

bBuffer

Matrice di caratteri inizializzata a una lunghezza di sizeof(DWORD). Questo buffer contiene i nomi a cui fanno riferimento i membri nCardNameOffset, nReaderNameOffset, nContainerNameOffset e nCSPNameOffset , nonché eventuali dati aggiuntivi forniti dal provider di servizi di configurazione.

Tutti i nomi non specificati devono essere rappresentati in questo buffer da stringhe vuote.

Osservazioni:

Layout bBuffer

BBuffer inizia con un segnaposto/prefisso di sizeof(DWORD) byte di dimensioni DWORD e quindi archivia stringhe con terminazione Null per i nomi di scheda, lettore, contenitore e CSP (ognuno può essere una stringa vuota tranne il nome del contenitore che deve essere non vuoto), seguito da eventuali dati aggiuntivi specifici di CSP.

Componente (ordine dall'inizio di bBuffer) Description Requisito
Prefisso DWORD Segnaposto riservato (sizeof(DWORD) = 4 byte) Sempre presente
CardName Stringa vuota o nome della scheda con terminazione Null Opzionale
ReaderName Stringa vuota o nome lettore con terminazione Null Opzionale
Nome del Contenitore Nome del contenitore di chiavi con terminazione Null Obbligatorio; deve essere non vuoto
CSPName Stringa vuota o nome CSP con terminazione Null Opzionale
Dati aggiuntivi Dati aggiunti specifici di CSP dopo i nomi Opzionale; Formato definito da CSP
  • Offset:nCardNameOffset, nReaderNameOffset, nContainerNameOffsete nCSPNameOffset sono il numero di caratteri dall'inizio all'inizio di bBuffer ogni rispettiva stringa. Questi conteggi includono l'area riservata sizeof(DWORD) iniziale e vengono misurati in TCHAR unità (ANSI char o Unicode wchar_t, a seconda della compilazione).
  • Nomi vuoti: Quando non viene specificato un nome, il buffer deve contenere una stringa vuota (lunghezza zero seguita dal terminatore) in tale posizione.
  • Allineamento della serializzazione: In caso di serializzazione, i membri della struttura devono essere allineati ai limiti a 2 byte.

Examples

Poiché KERB_SMARTCARD_CSP_INFO non è dichiarato in un'intestazione pubblica, è necessario dichiararlo manualmente. La #pragma pack(push, 2) direttiva è necessaria per garantire l'allineamento dei membri a 2 byte quando la struttura viene serializzata.

Gli esempi seguenti presuppongono una compilazione Unicode (WCHAR / PCWSTR), quindi gli offset vengono misurati in WCHAR unità.

#pragma pack(push, 2)
typedef struct _KERB_SMARTCARD_CSP_INFO {
    DWORD   dwCspInfoLen;
    DWORD   MessageType;
    union {
        PVOID   ContextInformation;
        ULONG64 SpaceHolderForWow64;
    };
    DWORD   flags;
    DWORD   KeySpec;
    ULONG   nCardNameOffset;
    ULONG   nReaderNameOffset;
    ULONG   nContainerNameOffset;
    ULONG   nCSPNameOffset;
    WCHAR   bBuffer;
} KERB_SMARTCARD_CSP_INFO, *PKERB_SMARTCARD_CSP_INFO;
#pragma pack(pop)

La funzione helper seguente alloca e popola una struttura KERB_SMARTCARD_CSP_INFO . Viene illustrato come calcolare le dimensioni totali, impostare gli offset bBuffer e copiare le stringhe dei nomi nel buffer.

// Returns a LocalAlloc'd KERB_SMARTCARD_CSP_INFO, or NULL on failure.
// The caller must free the returned pointer with LocalFree.
//
// szContainerName must be non-empty. All other name parameters may be L"".
PKERB_SMARTCARD_CSP_INFO CreateSmartCardCspInfo(
    _In_ PCWSTR szCardName,       // Smart card name, or L"" if not available
    _In_ PCWSTR szReaderName,     // Card reader name, or L"" if not available
    _In_ PCWSTR szContainerName,  // Key container name (required)
    _In_ PCWSTR szCspName,        // CSP/KSP name, or L"" to let Windows choose
    _In_ DWORD  dwKeySpec)        // AT_KEYEXCHANGE or AT_SIGNATURE
{
    if (!szCardName || !szReaderName || !szContainerName || !szCspName ||
        szContainerName[0] == L'\0')
    {
        return NULL;
    }

    // Compute the length of each name, including its null terminator.
    ULONG cchCard      = (ULONG)wcslen(szCardName)      + 1;
    ULONG cchReader    = (ULONG)wcslen(szReaderName)    + 1;
    ULONG cchContainer = (ULONG)wcslen(szContainerName) + 1;
    ULONG cchCsp       = (ULONG)wcslen(szCspName)       + 1;

    // bBuffer begins with a sizeof(DWORD)-byte reserved prefix (= 2 WCHARs in
    // Unicode builds), followed by the four null-terminated name strings.
    const ULONG cchPrefix = sizeof(DWORD) / sizeof(WCHAR); // = 2
    ULONGLONG cchBuf = (ULONGLONG)cchPrefix + cchCard + cchReader + cchContainer + cchCsp;

    // Total byte size = fixed header fields up to bBuffer, plus string data.
    ULONGLONG cbTotal = FIELD_OFFSET(KERB_SMARTCARD_CSP_INFO, bBuffer)
                      + cchBuf * sizeof(WCHAR);
    if (cbTotal > MAXDWORD)
        return NULL;

    PKERB_SMARTCARD_CSP_INFO p =
        (PKERB_SMARTCARD_CSP_INFO)LocalAlloc(LPTR, (SIZE_T)cbTotal);
    if (!p)
        return NULL;

    p->dwCspInfoLen = (DWORD)cbTotal;
    p->MessageType  = 1;         // Must always be 1.
    p->KeySpec      = dwKeySpec;

    // Each offset is the number of WCHARs from the start of bBuffer to the
    // beginning of the corresponding name string.
    p->nCardNameOffset      = cchPrefix;
    p->nReaderNameOffset    = p->nCardNameOffset      + cchCard;
    p->nContainerNameOffset = p->nReaderNameOffset    + cchReader;
    p->nCSPNameOffset       = p->nContainerNameOffset + cchContainer;

    // Copy names into bBuffer at the computed offsets.
    // The 2-WCHAR prefix region is already zeroed by LPTR.
    PWCH buf = &p->bBuffer;
    wcscpy_s(buf + p->nCardNameOffset,      cchCard,      szCardName);
    wcscpy_s(buf + p->nReaderNameOffset,    cchReader,    szReaderName);
    wcscpy_s(buf + p->nContainerNameOffset, cchContainer, szContainerName);
    wcscpy_s(buf + p->nCSPNameOffset,       cchCsp,       szCspName);

    return p;
}

Nell'esempio seguente viene CreateSmartCardCspInfo usato insieme KERB_CERTIFICATE_LOGON per eseguire un accesso interattivo tramite LsaLogonUser. Tutti i campi di tipo puntatore in KERB_CERTIFICATE_LOGON vengono archiviati come offset di byte rispetto all'inizio della struttura, non come puntatori assoluti.

// Performs an interactive smart card logon.
// On success, *phToken receives a handle to the logon token.
NTSTATUS SmartCardCertLogon(
    _In_  PCWSTR  szPin,
    _In_  PCWSTR  szCardName,
    _In_  PCWSTR  szReaderName,
    _In_  PCWSTR  szContainerName,
    _In_  PCWSTR  szCspName,
    _Out_ PHANDLE phToken)
{
    PKERB_SMARTCARD_CSP_INFO pCspInfo = CreateSmartCardCspInfo(
        szCardName, szReaderName, szContainerName, szCspName, AT_KEYEXCHANGE);
    if (!pCspInfo)
        return STATUS_NO_MEMORY;

    // Build a single contiguous buffer:
    //   [KERB_CERTIFICATE_LOGON | PIN string | KERB_SMARTCARD_CSP_INFO]
    ULONG cbLogon = sizeof(KERB_CERTIFICATE_LOGON);
    ULONG cbPin   = ((ULONG)wcslen(szPin) + 1) * sizeof(WCHAR);
    ULONG cbCsp   = pCspInfo->dwCspInfoLen;
    ULONG cbTotal = cbLogon + cbPin + cbCsp;

    NTSTATUS status = STATUS_NO_MEMORY;
    PBYTE pBuf = (PBYTE)LocalAlloc(LPTR, cbTotal);
    if (pBuf)
    {
        PKERB_CERTIFICATE_LOGON pLogon = (PKERB_CERTIFICATE_LOGON)pBuf;
        PWCH  pPinDst = (PWCH)(pBuf + cbLogon);
        PBYTE pCspDst =        pBuf + cbLogon + cbPin;

        wcscpy_s(pPinDst, cbPin / sizeof(WCHAR), szPin);
        memcpy(pCspDst, pCspInfo, cbCsp);

        // Pointer fields are stored as byte offsets relative to pBuf.
        pLogon->MessageType       = KerbCertificateLogon;
        pLogon->Pin.Length        = (USHORT)(wcslen(szPin) * sizeof(WCHAR));
        pLogon->Pin.MaximumLength = (USHORT)cbPin;
        pLogon->Pin.Buffer        = (PWSTR)(ULONG_PTR)cbLogon;
        pLogon->CspDataLength     = cbCsp;
        pLogon->CspData           = (PUCHAR)(ULONG_PTR)(cbLogon + cbPin);

        HANDLE hLsa;
        status = LsaConnectUntrusted(&hLsa);
        if (status >= 0)
        {
            LSA_STRING packageName;
            ULONG authPackage;
            RtlInitString(&packageName, MICROSOFT_KERBEROS_NAME_A);
            status = LsaLookupAuthenticationPackage(
                hLsa, &packageName, &authPackage);
            if (status >= 0)
            {
                LSA_STRING   origin      = {};
                TOKEN_SOURCE tokenSource = {};
                PVOID        pProfile   = NULL;
                ULONG        cbProfile  = 0;
                LUID         logonId;
                QUOTA_LIMITS quotas;
                NTSTATUS     subStatus;

                RtlInitString(&origin, "LogonOrigin");
                memcpy(tokenSource.SourceName, "SmartCrd", TOKEN_SOURCE_LENGTH);
                AllocateLocallyUniqueId(&tokenSource.SourceIdentifier);

                status = LsaLogonUser(
                    hLsa, &origin, Interactive, authPackage,
                    pBuf, cbTotal, NULL, &tokenSource,
                    &pProfile, &cbProfile, &logonId, phToken,
                    &quotas, &subStatus);

                if (status >= 0 && pProfile != NULL)
                    LsaFreeReturnBuffer(pProfile);
                else if (subStatus < 0)
                    status = subStatus;
            }
            LsaDeregisterLogonProcess(hLsa);
        }
        LocalFree(pBuf);
    }

    LocalFree(pCspInfo);
    return status;
}

Requisiti

Requisito Value
Client minimo supportato
Windows Vista [solo app desktop]
Server minimo supportato
Windows Server 2008 [solo app desktop]

Vedere anche

KERB_CERTIFICATE_LOGON