SSL ve Službě WinHTTP
Microsoft Windows HTTP Services (WinHTTP) podporuje transakce SSL (Secure Sockets Layer) včetně klientských certifikátů. Toto téma vysvětluje koncepty spojené s transakcí SSL a způsob jejich zpracování pomocí WinHTTP.
Vrstva zabezpečených soketů
SSL je zavedený standard pro zajištění zabezpečených transakcí HTTP. PROTOKOL SSL poskytuje mechanismus pro provedení až 128bitového šifrování všech transakcí mezi klientem a serverem. Umožňuje klientovi ověřit, že server patří k důvěryhodné entitě prostřednictvím použití certifikátů serveru. Umožňuje také serveru potvrdit identitu klienta pomocí klientských certifikátů.
Každý z těchto problémů se šifrováním, identitou serveru a identitou klienta se vyjednává v protokolu SSL handshake, ke kterému dochází, když klient poprvé požádá o prostředek ze serveru HTTPS (Secure Hypertext Transfer Protocol). Klient a server v podstatě představují seznam požadovaných a upřednostňovaných nastavení. Pokud je možné odsouhlasit a splnit společnou sadu požadavků, vytvoří se připojení SSL.
WinHTTP poskytuje rozhraní vysoké úrovně pro použití SSL. Zatímco podrobnosti o metodách handshake a transakce SSL se zpracovávají interně, WinHTTP umožňuje načíst úrovně šifrování, zadat protokol zabezpečení a pracovat se serverovými a klientskými certifikáty. Následující části obsahují podrobnosti o vytváření aplikací založených na winHTTP, které vyberou verzi protokolu SSL, prověřují certifikáty serveru a vyberou klientské certifikáty, které se mají odesílat na servery HTTPS.
Certifikáty serveru
Certifikáty serveru se odesílají ze serveru klientovi, aby klient mohl získat veřejný klíč pro server a zajistit, aby byl server ověřen certifikační autoritou. Certifikáty můžou obsahovat různé typy dat. Například certifikát X.509 obsahuje formát certifikátu, sériové číslo certifikátu, algoritmus použitý k podepsání certifikátu, název certifikační autority (CA), který certifikát vydal, název a veřejný klíč entity, která certifikát požaduje, a podpis certifikační autority.
Při použití aplikačního programovacího rozhraní WinHTTP (API) můžete načíst certifikát serveru voláním WinHttpQueryOption a zadáním příznaku WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT. Certifikát serveru se vrátí ve struktuře WINHTTP_CERTIFICATE_INFO. Pokud chcete načíst kontext certifikátu, zadejte místo toho příznak WINHTTP_OPTION_SERVER_CERT_CONTEXT.
Pokud certifikát serveru obsahuje chyby, lze podrobnosti o chybě získat ve funkci zpětného volání stavu. Oznámení WINHTTP_CALLBACK_STATUS_SECURE_FAILURE indikuje chybu s certifikátem serveru. Parametr lpvStatusInformation obsahuje jeden nebo podrobnější příznak chyby. Další informace najdete v tématu WINHTTP_STATUS_CALLBACK.
Klientské certifikáty
Během metody handshake PROTOKOLU SSL může server vyžadovat ověření. Klient se ověřuje zadáním platného klientského certifikátu na server. WinHTTP umožňuje vybrat a odeslat certifikát z místního úložiště certifikátů . Následující části popisují proces, který poskytuje klientské certifikáty při použití rozhraní WINHTTP API nebo WinHttpRequest objektu.
WinHTTP API
winHttpSendRequest i WinHttpReceiveResponse může být neúspěšné, protože server HTTPS vyžaduje ověření. V těchto případech voláním GetLastError vrátí ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED. Po zobrazení této chyby vyhledejte odpovídající certifikát pomocí příslušných funkcí CryptoAPI. Označte, že tento certifikát by se měl odeslat s dalším požadavkem voláním WinHttpSetOption příznakem WINHTTP_OPTION_CLIENT_CERT_CONTEXT.
Následující příklad kódu ukazuje, jak otevřít úložiště certifikátů a vyhledat certifikát na základě názvu subjektu po vrácení ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED chyby.
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.
}
}
}
Před opětovným odesláním požadavku, který obsahuje klientský certifikát, můžete určit, jestli je podporovaná úroveň šifrování pro vaši aplikaci přijatelná. Zavolejte WinHttpQueryOption a zadejte příznak WINHTTP_OPTION_SECURITY_FLAGS k určení úrovně použitého šifrování.
Načtení seznamu vystavitelů pro ověřování klienta SSL
Když klientská aplikace WinHttp odešle požadavek na zabezpečený server HTTP, který vyžaduje ověření klienta SSL, winHttp vrátí ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED, pokud aplikace nezadá klientský certifikát. Pro počítače se systémem Windows Server 2008 a Windows Vista umožňuje winHttp aplikaci načíst seznam vystavitelů certifikátů zadaný serverem v ověřovací výzvě. Seznam vystavitelů určuje seznam certifikačních autorit (CA), které jsou serverem autorizované k vydávání klientských certifikátů. Aplikace filtruje seznam vystavitelů, aby získala požadovaný certifikát.
Klientská aplikace WinHttp načte seznam vystavitelů, když WinHttpSendRequestnebo WinHttpReceiveResponse vrátí ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED. Když se tato chyba vrátí, aplikace volá WinHttpQueryOption s možností WINHTTP_OPTION_CLIENT_CERT_ISSUER_LIST. Parametr lpBuffer musí být dostatečně velký, aby obsahoval ukazatel na SecPkgContext_IssuerListInfoEx strukturu. Následující příklad kódu ukazuje, jak načíst seznam vystavitelů.
#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.
}
}
Informace ve struktuře SecPkgContext_IssuerListInfoEx, cIssuers a aIssuers, lze použít k vyhledání certifikátu, jak je znázorněno v příkladu kódu níže. Další informace naleznete v tématu 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;
}
Volitelné klientské certifikáty SSL
Od systému Windows Server 2008 a Windows Vista rozhraní API WinHttp podporuje volitelné klientské certifikáty. Když server požaduje klientský certifikát, WinHttpSendRequestnebo WinHttpRecieveResponse vrátí chybu ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED. Pokud server požádá o certifikát, ale nevyžaduje ho, může tuto možnost zadat, aby určila, že certifikát nemá. Server může zvolit jiné schéma ověřování nebo povolit anonymní přístup k serveru. Aplikace určuje WINHTTP_NO_CLIENT_CERT_CONTEXT makro v parametru lpBufferWinHttpSetOp tion, jak je znázorněno v následujícím příkladu kódu.
BOOL fRet = WinHttpSetOption ( hRequest,
WINHTTP_OPTION_CLIENT_CERT_CONTEXT,
WINHTTP_NO_CLIENT_CERT_CONTEXT,
0);
Pokud je nastavená WINHTTP_NO_CLIENT_CERT_CONTEXT a server stále vyžaduje klientský certifikát, může odeslat stavový kód HTTP 403. Další informace najdete v WINHTTP_OPTION_CLIENT_CERT_ISSUER_LIST možnosti.
WinHttpRequest – objekt
Pomocí metody SetClientCertificate objektu WinHttpRequest vyberte klientské certifikáty, které se mají odeslat na server s požadavkem. Vyberte certifikát zadáním řetězce výběru certifikátu pomocí metody SetClientCertificate. Řetězec výběru certifikátu se skládá z umístění certifikátu, úložiště certifikátůa názvu subjektu odděleného zpětnými lomítky. Následující tabulka uvádí komponenty pro tento řetězec výběru.
Komponenta | Popis | Možné hodnoty |
---|---|---|
Umístění | Určuje klíč registru, pod kterým jsou certifikáty uloženy. | Možné hodnoty jsou "LOCAL_MACHINE" označující, žeúložiště certifikátůje pod HKEY_LOCAL_MACHINE a "CURRENT_USER" označující, že úložiště certifikátů je pod zosobněnýmHKEY_CURRENT_USER. U této komponenty se rozlišují malá a velká písmena. |
úložiště certifikátů | Označuje název úložiště certifikátů, který obsahuje příslušný certifikát. | Typické úložiště certifikátů jsou MY, Root a TrustedPeople. U této komponenty se rozlišují malá a velká písmena. |
Název subjektu | Identifikuje certifikát v zadaném úložišti certifikátů . Je vybrán první certifikát, který obsahuje řetězec zadaný pro tuto komponentu. | Název subjektu může být libovolný řetězec. Prázdný řetězec označuje, že se má použít první certifikát v úložišti certifikátů . Tato komponenta nerozlišuje malá a velká písmena. |
Název a umístění úložiště certifikátů jsou volitelné součásti. Pokud však zadáte úložiště certifikátů, musíte také zadat umístění tohoto úložiště certifikátů. Výchozí umístění je CURRENT_USER a výchozí úložiště certifikátů je MY.
Následující příklad kódu ukazuje, jak určit, že certifikát s předmětem "My Middle-Tier Certificate" by měl být vybrán z "Osobní" úložiště certifikátů v registru v HKEY_LOCAL_MACHINE.
HttpReq.SetClientCertificate("LOCAL_MACHINE\Personal\My Middle-Tier Certificate")
Poznámka
V některých jazycích je zpětné lomítko řídicí znak. Nezapomeňte upravit řetězec výběru certifikátu tak, aby byl pro tento účet. Například v Microsoft JScriptu použijte dvě sousední zpětná lomítka místo jednoho.
Pokud nezadáte certifikát a server HTTPS vyžaduje klientský certifikát, winHTTP vybere první certifikát ve výchozím úložišti certifikátů. Pokud neexistují žádné certifikáty, dojde k chybě. Pokud certifikát není přijat, server vrátí stavový kód 403, který indikuje, že požadavek nelze splnit. Pak můžete zvolit vhodnější certifikát s SetClientCertificate a žádost znovu odeslat.