Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
A estrutura KERB_SMARTCARD_CSP_INFO contém informações sobre um fornecedor de serviços criptográficos de cartões inteligentes (CSP).
Esta estrutura não é declarada num 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, desta estrutura, incluindo quaisquer dados anexados.
-
TipoDeMensagem
-
O tipo de mensagem que está a ser transmitida. Este membro deve ser definido para 1.
-
Informação de Contexto
-
Reservado.
-
EspaçoDeEspaçoParaWow64
-
Reservado.
-
flags
-
Reservado.
-
KeySpec
-
A chave privada a usar do contentor de chaves especificado dentro do buffer bBuffer. A chave pode ser um dos seguintes valores, definidos no WinCrypt.h.
Valor 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 deve conter uma cadeia vazia.
-
nReaderNameOffset
-
O número de caracteres no buffer bBuffer que precede o nome do leitor de smart card nesse buffer.
Importante
Se o nome do leitor de cartões inteligentes não for fornecido, o buffer deve conter uma cadeia vazia.
-
nNomeContentorOffset
-
O número de caracteres no buffer bBuffer que precede o nome do contentor de chaves nesse buffer. Esta cadeia não pode estar vazia.
-
nCSPNameOffset
-
O número de caracteres no buffer bBuffer que precedem o nome do CSP nesse buffer.
-
bBuffer
-
Um array de caracteres inicializado com um comprimento de
sizeof(DWORD). Este buffer contém os nomes referidos pelos membros nCardNameOffset, nReaderNameOffset, nContainerNameOffset e nCSPNameOffset , bem como quaisquer dados adicionais fornecidos pelo CSP.Quaisquer nomes que não sejam fornecidos devem ser representados neste buffer por cadeias vazias.
Observações
disposição do buffer bHand
O bBuffer começa com um marcador de lugar/prefixo de sizeof(DWORD) bytes do tamanho de DWORD e depois armazena cadeias terminadas em nulo para os nomes do cartão, leitor, contentor e CSP (cada um pode ser uma string vazia, exceto o nome do contentor que deve estar não vazio), seguido de quaisquer dados extra específicos do CSP.
| Componente (ordem a partir do início do bBuffer) | Description | Requisito |
|---|---|---|
| Prefixo DWORD | Reservado marcador de posição (sizeof(DWORD) = 4 bytes) |
Sempre presente |
| Nome do cartão | String vazia ou nome da carta terminada por nulo | Opcional |
| Nome do Leitor | String vazia ou nome do leitor terminado por nulo | Opcional |
| Nome do Contêiner | Nome do contentor da chave terminada por nulo | Obrigatório; deve ser não vazio |
| CSPName | String vazia ou nome CSP terminado por nulo | Opcional |
| Dados adicionais | Dados anexados específicos do CSP após nomes | Opcional; Formato definido pelo CSP |
-
Deslocamentos:
nCardNameOffset,nReaderNameOffset,nContainerNameOffset, enCSPNameOffsetsão o número de caracteres desde o início atébBufferao início de cada cadeia respetiva. Estas contagens incluem a região reservadasizeof(DWORD)inicial e são medidas emTCHARunidades (ANSIcharou Unicodewchar_t, dependendo da compilação). - Nomes vazios: Quando não é fornecido um nome, o buffer deve conter uma cadeia vazia (comprimento zero seguida pelo terminador) nessa posição.
- Alinhamento de serialização: Quando serializados, os membros da estrutura devem estar alinhados a limites de 2 bytes.
Examples
Como KERB_SMARTCARD_CSP_INFO não é declarado num cabeçalho público, deve declará-lo por si próprio. A #pragma pack(push, 2) diretiva é necessária para garantir o alinhamento dos membros a 2 bytes quando a estrutura é serializada.
Os exemplos abaixo assumem uma construção Unicode (WCHAR / PCWSTR), pelo que 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 seguinte função auxiliar aloca e preenche uma estrutura KERB_SMARTCARD_CSP_INFO . Demonstra como calcular o tamanho total, definir os deslocamentos do bBuffer e copiar as cadeias de nomes 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 seguinte, em CreateSmartCardCspInfo conjunto com KERB_CERTIFICATE_LOGON para realizar um login interativo com cartão inteligente através do LsaLogonUser. Todos os campos do 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;
}
Requerimentos
| Requisito | Valor |
|---|---|
| Cliente mínimo suportado |
Windows Vista [apenas aplicações de ambiente de trabalho] |
| Servidor mínimo suportado |
Windows Server 2008 [apenas aplicações de ambiente de trabalho] |