Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
A estrutura KERB_SMARTCARD_CSP_INFO contém informações sobre um CSP ( provedor de serviços criptográficos ) de cartão inteligente.
Essa estrutura não é declarada em um cabeçalho público.
Sintaxe
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
-
O tamanho, em bytes, dessa estrutura, incluindo todos os dados acrescentados.
-
MessageType
-
O tipo de mensagem que está sendo passada. Esse membro deve ser definido como 1.
-
Contextinformation
-
Reservado.
-
SpaceHolderForWow64
-
Reservado.
-
flags
-
Reservado.
-
KeySpec
-
A chave privada a ser usada do contêiner de chave especificado no bBuffer do buffer. A chave pode ser um dos seguintes valores, definidos em WinCrypt.h.
Value Meaning - AT_KEYEXCHANGE
- 1
A chave é uma chave de troca de chaves. - AT_SIGNATURE
- 2
A chave é uma chave de assinatura. -
nCardNameOffset
-
O número de caracteres no buffer bBuffer que precede o nome do cartão inteligente nesse buffer.
Importante
Se o nome do cartão inteligente não for fornecido, o buffer deverá conter uma cadeia de caracteres vazia.
-
nReaderNameOffset
-
O número de caracteres no buffer bBuffer que precede o nome do leitor de cartão inteligente nesse buffer.
Importante
Se o nome do leitor de cartão inteligente não for fornecido, o buffer deverá conter uma cadeia de caracteres vazia.
-
nContainerNameOffset
-
O número de caracteres no buffer bBuffer que precede o nome do contêiner de chave nesse buffer. Essa cadeia de caracteres não pode estar vazia.
-
nCSPNameOffset
-
O número de caracteres no buffer bBuffer que precede o nome do CSP nesse buffer.
-
bBuffer
-
Uma matriz de caracteres inicializada em um comprimento de
sizeof(DWORD). Esse buffer contém os nomes referenciados pelos membros nCardNameOffset, nReaderNameOffset, nContainerNameOffset e nCSPNameOffset , bem como quaisquer dados adicionais fornecidos pelo CSP.Todos os nomes que não são fornecidos devem ser representados nesse buffer por cadeias de caracteres vazias.
Observações
layout do bBuffer
O bBuffer começa com um espaço reservado/prefixo do tamanho de DWORD de sizeof(DWORD) bytes e armazena cadeias de caracteres terminadas em nulo para os nomes de cartão, leitor, contêiner e CSP (cada um pode ser uma cadeia de caracteres vazia, exceto o nome do contêiner que deve ser não vazio), seguido por quaisquer dados extras específicos do CSP.
| Componente (ordem do início do bBuffer) | Description | Requirement |
|---|---|---|
| Prefixo DWORD | Espaço reservado (sizeof(DWORD) = 4 bytes) |
Sempre presente |
| CardName | Cadeia de caracteres vazia ou nome do cartão encerrado em nulo | Opcional |
| ReaderName | Nome do leitor de cadeia de caracteres vazia ou terminada em nulo | Opcional |
| Nome do Contêiner | Nome do contêiner de chave terminada em nulo | Necessário; deve ser não vazio |
| CSPName | Cadeia de caracteres vazia ou nome CSP encerrado em nulo | Opcional |
| Dados adicionais | Dados anexados específicos do CSP após nomes | Opcional; Formato definido por CSP |
-
Deslocamentos:
nCardNameOffset,nReaderNameOffset,nContainerNameOffsetenCSPNameOffsetsão o número de caracteres do iníciobBufferao início de cada cadeia de caracteres respectiva. Essas contagens incluem a região reservada inicial e são medidassizeof(DWORD)emTCHARunidades (ANSIcharou Unicodewchar_t, dependendo do build). - Nomes vazios: Quando um nome não é fornecido, o buffer deve conter uma cadeia de caracteres vazia (comprimento zero seguido pelo terminador) nessa posição.
- Alinhamento de serialização: Quando serializados, os membros da estrutura devem ser alinhados aos limites de 2 bytes.
Exemplos
Como KERB_SMARTCARD_CSP_INFO não é declarado em um cabeçalho público, você deve declará-lo por conta própria. A #pragma pack(push, 2) diretiva é necessária para garantir o alinhamento de membro de 2 bytes quando a estrutura é serializada.
Os exemplos a seguir pressupõem um build Unicode (WCHAR / PCWSTR), portanto, os deslocamentos são medidos em WCHAR unidades.
#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)
A função auxiliar a seguir aloca e popula uma estrutura de KERB_SMARTCARD_CSP_INFO . Ele demonstra como calcular o tamanho total, definir os deslocamentos do bBuffer e copiar as cadeias de caracteres de nome para o 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;
}
O exemplo a seguir usa CreateSmartCardCspInfo junto com KERB_CERTIFICATE_LOGON para executar um logon de cartão inteligente interativo via LsaLogonUser. Todos os campos de tipo ponteiro em KERB_CERTIFICATE_LOGON são armazenados como deslocamentos de bytes relativos ao início da estrutura, não como ponteiros absolutos.
// 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;
}
Requirements
| Requirement | Value |
|---|---|
| Cliente mínimo com suporte |
Windows Vista [somente aplicativos da área de trabalho] |
| Servidor mínimo com suporte |
Windows Server 2008 [somente aplicativos da área de trabalho] |