Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
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,nContainerNameOffsetenCSPNameOffsetsono il numero di caratteri dall'inizio all'inizio dibBufferogni rispettiva stringa. Questi conteggi includono l'area riservatasizeof(DWORD)iniziale e vengono misurati inTCHARunità (ANSIcharo Unicodewchar_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,
"as, &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] |