Win'te SSLHTTP
Microsoft Windows HTTP Hizmetleri (WinHTTP), istemci sertifikaları da dahil olmak üzere Güvenli Yuva Katmanı (SSL) işlemlerini destekler. Bu konu başlığı altında, BIR SSL işlemiyle ilgili kavramlar ve Bunların WinHTTP kullanılarak nasıl işlenmeleri açıklanmaktadır.
Güvenli Yuva Katmanı
SSL, güvenli HTTP işlemleri sağlamaya yönelik yerleşik bir standarttır. SSL, istemci ile sunucu arasındaki tüm işlemlerde 128 bit'e kadar şifreleme gerçekleştirmek için bir mekanizma sağlar. İstemcinin sunucu sertifikaları kullanarak sunucunun güvenilir bir varlığa ait olduğunu doğrulamasını sağlar. Ayrıca sunucunun istemci sertifikalarıyla istemci kimliğini onaylamasını sağlar.
Bu sorunların her biri şifreleme, sunucu kimliği ve istemci kimliği, bir istemci güvenli köprü metni aktarım protokolü (HTTPS) sunucusundan ilk kez bir kaynak istediğinde oluşan SSL el sıkışmasında anlaşılır. Temelde, istemci ve sunucu her biri gerekli ve tercih edilen ayarların bir listesini sunar. Ortak bir gereksinim kümesi üzerinde anlaşmaya varılabilir ve karşılanabilirse, bir SSL bağlantısı kurulur.
WinHTTP, SSL kullanmak için üst düzey bir arabirim sağlar. SSL el sıkışması ve işleminin ayrıntıları dahili olarak işlenirken, WinHTTP şifreleme düzeylerini almanıza, güvenlik protokollerini belirtmenize ve sunucu ve istemci sertifikalarıyla etkileşim kurmanıza olanak tanır. Aşağıdaki bölümlerde, BIR SSL protokolü sürümü seçen, sunucu sertifikalarını inceleyen ve HTTPS sunucularına göndermek üzere istemci sertifikalarını seçen WinHTTP tabanlı uygulamalar oluşturmayla ilgili ayrıntılar sağlanır.
Sunucu Sertifikaları
Sunucu sertifikaları sunucudan istemciye gönderilir, böylece istemci sunucu için bir ortak anahtar alabilir ve sunucunun bir sertifika yetkilisi tarafından doğrulandığından emin olur. Sertifikalar farklı veri türleri içerebilir. Örneğin, X.509 sertifikası sertifikanın biçimini, sertifikanın seri numarasını, sertifikayı imzalamak için kullanılan algoritmayı, sertifikayı veren sertifika yetkilisinin (CA) adını, sertifikayı isteyen varlığın adını ve ortak anahtarını ve CA'nın imzasını içerir.
WinHTTP uygulama programlama arabirimini (API) kullanırken, WinHttpQueryOption çağırıp WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT bayrağını belirterek bir sunucu sertifikası alabilirsiniz. Sunucu sertifikası WINHTTP_CERTIFICATE_INFO bir yapıda döndürülür. Sertifika bağlamını almayı tercih ediyorsanız, bunun yerine WINHTTP_OPTION_SERVER_CERT_CONTEXT bayrağını belirtin.
Bir sunucu sertifikası hata içeriyorsa, hatayla ilgili ayrıntılar durum geri çağırma işlevinden alınabilir. WINHTTP_CALLBACK_STATUS_SECURE_FAILURE bildirimi, sunucu sertifikasıyla ilgili bir hatayı gösterir. lpvStatusInformation parametresi bir veya daha fazla ayrıntılı hata bayrağı içerir. Daha fazla bilgi için bkz. WINHTTP_STATUS_CALLBACK.
İstemci Sertifikaları
SSL el sıkışması sırasında sunucu kimlik doğrulaması gerektirebilir. İstemcinin kimliği, sunucuya geçerli bir istemci sertifikası sağlayarak doğrulanır. WinHTTP,yerel birsertifika deposundan sertifika seçmenizi ve göndermenizi sağlar. Aşağıdaki bölümlerde WinHTTP API veya WinHttpRequest nesnesi kullanılırken istemci sertifikaları sağlayan işlem açıklanmaktadır.
WinHTTP API
Hem WinHttpSendRequesthem de WinHttpReceiveResponse, HTTPS sunucusu kimlik doğrulaması gerektirdiğinden isteğin başarısız olduğunu gösterebileceğinden başarısız olabilir. Bu gibi durumlarda, ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED döndürmek için GetLastErrorçağır. Bu hatayı aldıktan sonra uygun bir sertifika bulmak için uygun CryptoAPI işlevlerini kullanın. WINHTTP_OPTION_CLIENT_CERT_CONTEXT bayrağıyla WinHttpSetOption çağırarak bu sertifikanın bir sonraki istekle gönderilmesi gerektiğini belirtin.
Aşağıdaki kod örneği, ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED hatası döndürüldükten sonra sertifika deposu açmayı ve konu adına göre bir sertifika bulmayı gösterir.
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.
}
}
}
İstemci sertifikası içeren bir isteği yeniden göndermeden önce, desteklenen şifreleme düzeyinin uygulamanız için kabul edilebilir olup olmadığını belirleyebilirsiniz. WinHttpQueryOptionçağırın ve kullanılan şifreleme düzeyini belirlemek için WINHTTP_OPTION_SECURITY_FLAGS bayrağını belirtin.
SSL İstemci Kimlik Doğrulaması için Veren Listesi Alma
WinHttp istemci uygulaması SSL istemci kimlik doğrulaması gerektiren güvenli bir HTTP sunucusuna istek gönderdiğinde, uygulama bir istemci sertifikası sağlamadıysa WinHttp bir ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED döndürür. Windows Server 2008 ve Windows Vista üzerinde çalışan bilgisayarlar için WinHttp, uygulamanın kimlik doğrulama sınamasında sunucu tarafından sağlanan sertifika veren listesini almasını sağlar. Veren Listesi, sunucu tarafından istemci sertifikaları verme yetkisi verilen Sertifika Yetkililerinin (CA) listesini belirtir. Uygulama, gerekli sertifikayı almak için veren listesini filtreler.
WinHttp istemci uygulaması, WinHttpSendRequestveya WinHttpReceiveResponseERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDEDdöndürdüğünde veren listesini alır. Bu hata döndürülürse, uygulama WINHTTP_OPTION_CLIENT_CERT_ISSUER_LIST seçeneğiyle winhttpqueryOptionçağırır. lpBuffer parametresi, SecPkgContext_IssuerListInfoEx yapısına bir işaretçi içerecek kadar büyük olmalıdır. Aşağıdaki kod örneğinde, veren listesinin nasıl alıncağı gösterilmektedir.
#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.
}
}
SecPkgContext_IssuerListInfoEx yapısındaki cIssuers ve aIssuersbilgileri, aşağıdaki kod örneğinde gösterildiği gibi sertifikayı aramak için kullanılabilir. Daha fazla bilgi için bkz. 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;
}
İsteğe Bağlı İstemci SSL Sertifikaları
Windows Server 2008 ve Windows Vista'dan başlayarak, WinHttp API isteğe bağlı istemci sertifikalarını destekler. Sunucu bir istemci sertifikası istediğinde, WinHttpSendRequestveya WinHttpRecieveResponseERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED hatası döndürür. Sunucu sertifikayı ister ancak sertifikayı gerektirmezse, uygulama sertifikaya sahip olmadığını belirtmek için bu seçeneği belirtebilir. Sunucu başka bir kimlik doğrulama şeması seçebilir veya sunucuya anonim erişim izni verebilir. Uygulama, aşağıdaki kod örneğinde gösterildiği gibi WinHttpSetOptionlpBuffer parametresinde WINHTTP_NO_CLIENT_CERT_CONTEXT makrosunu belirtir.
BOOL fRet = WinHttpSetOption ( hRequest,
WINHTTP_OPTION_CLIENT_CERT_CONTEXT,
WINHTTP_NO_CLIENT_CERT_CONTEXT,
0);
WINHTTP_NO_CLIENT_CERT_CONTEXT ayarlanmışsa ve sunucu hala bir istemci sertifikası gerektiriyorsa, 403 HTTP durum kodu gönderebilir. Daha fazla bilgi için WINHTTP_OPTION_CLIENT_CERT_ISSUER_LIST seçeneğine bakın.
WinHttpRequest Nesnesi
bir istekle sunucuya gönderilecek istemci sertifikalarını seçmek için WinHttpRequest nesnesinin SetClientCertificate yöntemini kullanın. SetClientCertificate yöntemiyle bir sertifika seçim dizesi belirterek bir sertifika seçin. Sertifika seçim dizesi sertifika konumundan,sertifika deposundan ve ters eğik çizgilerle ayrılmış konu adından oluşur. Aşağıdaki tabloda bu seçim dizesinin bileşenleri listelenmiştir.
Parça | Açıklama | Olası değerler |
---|---|---|
Yer | Sertifikaların altında depolandığı kayıt defteri anahtarını belirler. |
sertifika deposuHKEY_LOCAL_MACHINE altında olduğunu belirtmek için olası değerler "LOCAL_MACHINE"dir ve "CURRENT_USER", sertifika deposu kimliğine bürünülmeyenHKEY_CURRENT_USER altında olduğunu gösterir. Bu bileşen büyük/küçük harfe duyarlıdır. |
Sertifika deposu | İlgili sertifikayı içeren sertifika deposu adını gösterir. | tipiksertifika depoları "MY", "Root" ve "TrustedPeople" şeklindedir. Bu bileşen büyük/küçük harfe duyarlıdır. |
Konu adı | belirtilensertifika deposu içinde bir sertifika tanımlar. Bu bileşen için belirtilen dizeyi içeren ilk sertifika seçilir. | Konu adı herhangi bir dize olabilir. Boş dize, sertifika deposundaki ilk sertifikanın kullanılması gerektiğini belirtir. Bu bileşen büyük/küçük harfe duyarlı değildir. |
sertifika deposu adı ve konumu isteğe bağlı bileşenlerdir. Ancak, birsertifika deposu belirtirseniz, sertifika deposunun konumunu da belirtmeniz gerekir. Varsayılan konum CURRENT_USER ve varsayılan sertifika deposu "MY" olur.
Aşağıdaki kod örneği, kayıt defterinde HKEY_LOCAL_MACHINEaltındaki "Kişisel" sertifika deposu "Middle-Tier Sertifikam" konusuna sahip bir sertifikanın nasıl seçileceğini gösterir.
HttpReq.SetClientCertificate("LOCAL_MACHINE\Personal\My Middle-Tier Certificate")
Not
Bazı dillerde ters eğik çizgi bir kaçış karakteridir. Bunu hesaba katıp sertifika seçim dizesini değiştirmeyi unutmayın. Örneğin, Microsoft JScript'te bir yerine iki bitişik ters eğik çizgi kullanın.
Bir sertifika belirtmezseniz ve HTTPS sunucusu bir istemci sertifikası gerektiriyorsa, WinHTTP varsayılan sertifika deposundaki ilk sertifikayıseçer. Sertifika yoksa bir hata oluşur. Sertifika kabul edilmezse, sunucu isteğin karşılanamayacağını belirten bir 403 durum kodu döndürür. Daha sonra SetClientCertificate ile daha uygun bir sertifika seçebilir ve isteği yeniden gönderebilirsiniz.