Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
O Microsoft Windows HTTP Services (WinHTTP) suporta transações SSL (Secure Sockets Layer), incluindo certificados de cliente. Este tópico explica os conceitos envolvidos em uma transação SSL e como eles são tratados usando WinHTTP.
Camada de soquetes segura
SSL é um padrão estabelecido para garantir transações HTTP seguras. O SSL fornece um mecanismo para executar criptografia de até 128 bits em todas as transações entre o cliente e o servidor. Ele permite que o cliente verifique se o servidor pertence a uma entidade confiável através do uso de certificados de servidor. Ele também permite que o servidor confirme a identidade do cliente com certificados de cliente.
Cada um desses problemas de criptografia, identidade do servidor e identidade do cliente são negociados no handshake SSL que ocorre quando um cliente solicita pela primeira vez um recurso de um servidor HTTPS (Secure Hypertext Transfer Protocol). Essencialmente, o cliente e o servidor apresentam uma lista de configurações necessárias e preferidas. Se um conjunto comum de requisitos puder ser acordado e atendido, uma conexão SSL será estabelecida.
WinHTTP fornece uma interface de alto nível para usar SSL. Enquanto os detalhes do handshake SSL e da transação são tratados internamente, o WinHTTP permite recuperar níveis de criptografia, especificar o protocolo de segurança e interagir com certificados de servidor e cliente. As seções a seguir fornecem detalhes sobre a criação de aplicativos baseados em WinHTTP que elegem uma versão do protocolo SSL, examinam certificados de servidor e selecionam certificados de cliente para enviar a servidores HTTPS.
Certificados de servidor
Os certificados de servidor são enviados do servidor para o cliente para que o cliente possa obter uma chave pública para o servidor e garantir que o servidor tenha sido verificado por uma autoridade de certificação. Os certificados podem conter diferentes tipos de dados. Por exemplo, um certificado X.509 inclui o formato do certificado, o número de série do certificado, o algoritmo usado para assinar o certificado, o nome da autoridade de certificação (CA) que emitiu o certificado, o nome e a chave pública da entidade que solicita o certificado e a assinatura da autoridade de certificação.
Ao usar a interface de programação de aplicativo (API) WinHTTP, você pode recuperar um certificado de servidor chamando WinHttpQueryOption e especificando o sinalizador WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT. O certificado do servidor é retornado em uma estrutura WINHTTP_CERTIFICATE_INFO. Se preferir recuperar o contexto do certificado, especifique o sinalizador WINHTTP_OPTION_SERVER_CERT_CONTEXT.
Se um certificado de servidor contiver erros, detalhes sobre o erro podem ser obtidos na função de retorno de chamada de status. A notificação WINHTTP_CALLBACK_STATUS_SECURE_FAILURE indica um erro com um certificado de servidor. O parâmetro lpvStatusInformation contém um ou mais sinalizadores de erro detalhados. Consulte WINHTTP_STATUS_CALLBACK para obter mais informações.
Certificados de Cliente
Durante o handshake SSL, o servidor pode exigir autenticação. O cliente é autenticado fornecendo um certificado de cliente válido para o servidor. WinHTTP permite que você selecione e envie um certificado de um armazenamento de certificados local. As seções a seguir descrevem o processo que fornece certificados de cliente ao usar a API WinHTTP ou o objetoWinHttpRequest.
WinHTTP API
Tanto WinHttpSendRequest quanto WinHttpReceiveResponse podem falhar ao indicar que uma solicitação não foi bem-sucedida porque o servidor HTTPS requer autenticação. Nesses casos, chame GetLastError para retornar ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED. Ao receber esse erro, use o apropriado CryptoAPI funções para encontrar um certificado apropriado. Indique que esse certificado deve ser enviado com a próxima solicitação chamando WinHttpSetOption com o sinalizador WINHTTP_OPTION_CLIENT_CERT_CONTEXT.
O exemplo de código a seguir mostra como abrir umde armazenamento de certificadose localizar um certificado com base no nome da entidade após o erro de ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED ter sido retornado.
if( !WinHttpReceiveResponse( hRequest, NULL ) )
{
if( GetLastError( ) == ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED )
{
//MY is the store the certificate is in.
hMyStore = CertOpenSystemStore( 0, TEXT("MY") );
if( hMyStore )
{
pCertContext = CertFindCertificateInStore( hMyStore,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
0,
CERT_FIND_SUBJECT_STR,
(LPVOID) szCertName, //Subject string in the certificate.
NULL );
if( pCertContext )
{
WinHttpSetOption( hRequest,
WINHTTP_OPTION_CLIENT_CERT_CONTEXT,
(LPVOID) pCertContext,
sizeof(CERT_CONTEXT) );
CertFreeCertificateContext( pCertContext );
}
CertCloseStore( hMyStore, 0 );
// NOTE: Application should now resend the request.
}
}
}
Antes de reenviar uma solicitação que contém um certificado de cliente, você pode determinar se o nível suportado de criptografia é aceitável para seu aplicativo. Chame WinHttpQueryOption e especifique o sinalizador WINHTTP_OPTION_SECURITY_FLAGS para determinar o nível de criptografia usado.
Recuperação da lista de emissores para autenticação de cliente SSL
Quando o aplicativo cliente WinHttp envia uma solicitação para um servidor HTTP seguro que requer autenticação de cliente SSL, WinHttp retorna um ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED se o aplicativo não forneceu um certificado de cliente. Para computadores que executam o Windows Server 2008 e o Windows Vista, o WinHttp permite que o aplicativo recupere a lista de emissores de certificados fornecida pelo servidor no desafio de autenticação. A Lista de Emissores especifica uma lista de Autoridades de Certificação (CAs) autorizadas pelo servidor a emitir certificados de cliente. O aplicativo filtra a lista de emissores para obter o certificado necessário.
O aplicativo cliente WinHttp recupera a lista de emissores quando WinHttpSendRequestou WinHttpReceiveResponse retorna ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED. Quando esse erro é retornado, o aplicativo chama WinHttpQueryOption com a opção WINHTTP_OPTION_CLIENT_CERT_ISSUER_LIST. O parâmetro lpBuffer deve ser grande o suficiente para conter um ponteiro para a estrutura SecPkgContext_IssuerListInfoEx. O exemplo de código a seguir mostra como recuperar a lista de emissores.
#include <windows.h>
#include <winhttp.h>
#include <schannel.h>
//...
void GetIssuerList(HINTERNET hRequest)
{
SecPkgContext_IssuerListInfoEx* pIssuerList = NULL;
DWORD dwBufferSize = sizeof(SecPkgContext_IssuerListInfoEx*);
if (WinHttpQueryOption(hRequest,
WINHTTP_OPTION_CLIENT_CERT_ISSUER_LIST,
&pIssuerList,
&dwBufferSize) == TRUE)
{
// Use the pIssuerList for cert store filtering.
GlobalFree(pIssuerList); // Free the issuer list when done.
}
}
As informações na estrutura SecPkgContext_IssuerListInfoEx, cIssuers e aIssuers, podem ser usadas para procurar o certificado, conforme mostrado no exemplo de código abaixo. Para obter mais informações, consulte CertFindChainInStore.
PCERT_CONTEXT pClientCert = NULL;
PCCERT_CHAIN_CONTEXT pClientCertChain = NULL;
CERT_CHAIN_FIND_BY_ISSUER_PARA SrchCriteria;
::ZeroMemory(&SrchCriteria, sizeof(CERT_CHAIN_FIND_BY_ISSUER_PARA));
SrchCriteria.cbSize = sizeof(CERT_CHAIN_FIND_BY_ISSUER_PARA);
SrchCriteria.cIssuer = pIssuerList->cIssuers;
SrchCriteria.rgIssuer = pIssuerList->aIssuers;
pClientCertChain = CertFindChainInStore(
hClientCertStore,
X509_ASN_ENCODING,
CERT_CHAIN_FIND_BY_ISSUER_CACHE_ONLY_URL_FLAG |
// Do not perform wire download when building chains.
CERT_CHAIN_FIND_BY_ISSUER_CACHE_ONLY_FLAG,
// Do not search pCacheEntry->_ClientCertStore
// for issuer certs.
CERT_CHAIN_FIND_BY_ISSUER,
&SrchCriteria,
NULL);
if (pClientCertChain)
{
pClientCert = (PCERT_CONTEXT) pClientCertChain->rgpChain[0]->rgpElement[0]->pCertContext;
CertDuplicateCertificateContext(pClientCert);
CertFreeCertificateChain(pClientCertChain);
pClientCertChain = NULL;
}
Certificados SSL de cliente opcionais
A partir do Windows Server 2008 e do Windows Vista, a API WinHttp oferece suporte a certificados de cliente opcionais. Quando o servidor solicita um certificado de cliente, WinHttpSendRequestou WinHttpRecieveResponse retorna um erro ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED. Se o servidor solicitar o certificado, mas não o exigir, o aplicativo poderá especificar essa opção para indicar que não tem um certificado. O servidor pode escolher outro esquema de autenticação ou permitir acesso anônimo ao servidor. O aplicativo especifica a macro WINHTTP_NO_CLIENT_CERT_CONTEXT no parâmetro lpBuffer de WinHttpSetOption conforme mostrado no exemplo de código a seguir.
BOOL fRet = WinHttpSetOption ( hRequest,
WINHTTP_OPTION_CLIENT_CERT_CONTEXT,
WINHTTP_NO_CLIENT_CERT_CONTEXT,
0);
Se o WINHTTP_NO_CLIENT_CERT_CONTEXT estiver definido e o servidor ainda exigir um certificado de cliente, ele poderá enviar um código de status HTTP 403. Para obter mais informações, consulte a opção WINHTTP_OPTION_CLIENT_CERT_ISSUER_LIST.
Objeto WinHttpRequest
Use o método SetClientCertificate do objeto WinHttpRequest para selecionar certificados de cliente a serem enviados ao servidor com uma solicitação. Selecione um certificado especificando uma cadeia de caracteres de seleção de certificado com o métodoSetClientCertificate. A cadeia de caracteres de seleção de certificado consiste no local do certificado, de armazenamento de certificados e no nome do assunto delimitado por barras invertidas. A tabela a seguir lista os componentes para essa cadeia de caracteres de seleção.
| Componente | Descrição | Valores possíveis |
|---|---|---|
| Localização | Determina a chave do Registro sob a qual os certificados são armazenados. | Os valores possíveis são "LOCAL_MACHINE" para indicar que ode armazenamento de certificadosestá sob HKEY_LOCAL_MACHINE e "CURRENT_USER" para indicar que o de armazenamento de certificados está sob aHKEY_CURRENT_USER não representada. Este componente diferencia maiúsculas de minúsculas. |
| Armazenamento de certificados | Indica o nome dode armazenamento de certificadosque contém o certificado relevante. | Armazenamentos de certificados típicos são "MY", "Root" e "TrustedPeople". Este componente diferencia maiúsculas de minúsculas. |
| Nome do assunto | Identifica um certificado dentro do armazenamento de certificados especificado. O primeiro certificado que contém a cadeia de caracteres especificada para este componente é selecionado. | O nome do assunto pode ser qualquer cadeia de caracteres. Uma cadeia de caracteres em branco indica que o primeiro certificado node armazenamento de certificadosdeve ser usado. Este componente não diferencia maiúsculas de minúsculas. |
O armazenamento de certificados nome e local são componentes opcionais. No entanto, se você especificar um armazenamento de certificados, também deverá especificar o local desse armazenamento de certificados. O local padrão é CURRENT_USER e o padrão de armazenamento de certificados é "MY".
O exemplo de código a seguir mostra como especificar que um certificado com o assunto "My Middle-Tier Certificate" deve ser escolhido node armazenamento de certificados do"Pessoal" no Registro em HKEY_LOCAL_MACHINE.
HttpReq.SetClientCertificate("LOCAL_MACHINE\Personal\My Middle-Tier Certificate")
Observação
Em algumas línguas, a barra invertida é um personagem de fuga. Lembre-se de modificar a cadeia de caracteres de seleção de certificado para levar isso em conta. Por exemplo, no Microsoft JScript, use duas barras invertidas adjacentes em vez de uma.
Se você não especificar um certificado e um servidor HTTPS exigir um certificado de cliente, o WinHTTP selecionará o primeiro certificado no armazenamento de certificados padrão. Se não existirem certificados, é gerado um erro. Se o certificado não for aceito, o servidor retornará um código de status 403 para indicar que a solicitação não pode ser atendida. Em seguida, você pode escolher um certificado mais apropriado com SetClientCertificate e reenviar a solicitação.