Schannel
Pakiet zabezpieczeń Secure Channel (Schannel), którego identyfikator usługi uwierzytelniania jest RPC_C_AUTHN_GSS_SCHANNEL, obsługuje następujące protokoły oparte na kluczu publicznym: SSL (Secure Sockets Layer) w wersjach 2.0 i 3.0, Transport Layer Security (TLS) 1.0 i Private Communication Technology (PCT) 1.0. PROTOKÓŁ TLS 1.0 jest ustandaryzowaną, nieco zmodyfikowaną wersją protokołu SSL 3.0 wydaną przez Internet Engineering Task Force (IETF) w styczniu 1999 r. w dokumencie RFC 2246. Ponieważ protokół TLS został ustandaryzowany, deweloperzy są zachęcani do korzystania z protokołu TLS, a nie SSL. PcT jest uwzględniana tylko w celu zapewnienia zgodności z poprzednimi wersjami i nie powinna być używana do tworzenia nowych rozwiązań. W przypadku użycia pakietu zabezpieczeń Schannel model DCOM automatycznie negocjuje najlepszy protokół w zależności od możliwości klienta i serwera.
W poniższych tematach krótko opisano protokół TLS i sposób jego działania z modelem DCOM.
- Kiedy używać TLS
- krótkie omówienie sposobu działania protokołu TLS
- certyfikatów X.509
-
używanie protokołu TLS w COM
- Jak serwer ustawia zabezpieczeń
- Jak klient ustawia koc zabezpieczeń
- Jak klient zmienia zabezpieczeń
- Przykład: klient zmienia zabezpieczeń
- Tematy pokrewne
Nuta
Wszystkie informacje o protokole TLS w tych sekcjach dotyczą również protokołów SSL i PCT.
Kiedy używać protokołu TLS
Protokół TLS jest jedyną opcją zabezpieczeń dostępną, gdy serwery muszą udowodnić swoją tożsamość klientom anonimowym. Jest to szczególnie ważne w przypadku witryn internetowych, które chcą uczestniczyć w handlu elektronicznym, ponieważ pomaga chronić przesyłanie poufnych informacji, takich jak numery kart kredytowych. Protokół TLS zapewnia, że klienci handlu elektronicznego mogą być pewni, z których korzystają z firmy, ponieważ otrzymują dowód tożsamości serwera. Zapewnia również serwer handlu elektronicznego efektywność, aby nie martwić się o uwierzytelnianie tożsamości każdego z jego klientów.
Protokół TLS wymaga, aby wszystkie serwery udowodniły swoją tożsamość klientom. Ponadto protokół TLS umożliwia klientom potwierdzenie tożsamości serwerom. To wzajemne uwierzytelnianie może być przydatne w ograniczaniu dostępu do niektórych stron internetowych w dużym intranecie firmowym.
Protokół TLS obsługuje najsilniejsze poziomy uwierzytelniania i oferuje otwartą architekturę, która pozwala zwiększyć siłę szyfrowania w czasie, aby nadążyć za innowacjami technologicznymi. Protokół TLS jest najlepszym wyborem w środowiskach, w których wymagany jest najwyższy poziom zabezpieczeń dla przesyłanych danych.
Krótkie omówienie działania protokołu TLS
Protokół TLS jest oparty na infrastrukturze kluczy publicznych (PKI), która używa par kluczy publicznych/prywatnych do włączania szyfrowania danych i ustanawiania integralności danych oraz używa certyfikatów X.509 do uwierzytelniania.
Wiele protokołów zabezpieczeń, takich jak protokół Kerberos v5, zależy od pojedynczego klucza do szyfrowania i odszyfrowania danych. Takie protokoły zależą zatem od bezpiecznej wymiany kluczy szyfrowania; w protokole Kerberos odbywa się to za pośrednictwem biletów uzyskanych z Centrum dystrybucji kluczy (KDC). Wymaga to zarejestrowania wszystkich użytkowników protokołu Kerberos w centrum dystrybucji kluczy, co byłoby niepraktycznym ograniczeniem dla serwera internetowego handlu elektronicznego, który ma przyciągnąć miliony klientów z całego świata. W związku z tym protokół TLS opiera się na infrastrukturze kluczy publicznych, która używa dwóch kluczy do szyfrowania danychâ €", gdy jeden klucz pary szyfruje dane, tylko drugi klucz pary może go odszyfrować. Korzyść z tego projektu jest taka, że szyfrowanie można wykonać bez konieczności bezpiecznej wymiany kluczy szyfrowania.
Infrastruktura kluczy publicznych używa techniki, w której jeden z kluczy jest przechowywany jako prywatny i jest dostępny tylko dla podmiotu zabezpieczeń, do którego jest zarejestrowany, podczas gdy drugi klucz jest publiczny dla każdego, kto ma dostęp. Jeśli ktoś chce wysłać wiadomość prywatną do właściciela pary kluczy, wiadomość może zostać zaszyfrowana przy użyciu klucza publicznego, a tylko klucz prywatny może służyć do odszyfrowania wiadomości.
Pary kluczy są również używane do weryfikowania integralności wysyłanych danych. W tym celu właściciel pary kluczy może dołączyć podpis cyfrowy do danych przed ich wysłaniem. Utworzenie podpisu cyfrowego obejmuje obliczanie skrótu danych i szyfrowanie skrótu przy użyciu klucza prywatnego. Każdy, kto używa klucza publicznego do odszyfrowywania podpisu cyfrowego, jest pewien, że podpis cyfrowy musi pochodzić tylko od osoby, która jest właścicielem klucza prywatnego. Ponadto odbiorca może obliczyć skrót danych przy użyciu tego samego algorytmu co nadawca, a jeśli obliczony skrót jest zgodny z tym, który został wysłany w podpisie cyfrowym, odbiorca może mieć pewność, że dane nie zostały zmodyfikowane po jego podpisie cyfrowym.
Jedną wadą używania infrastruktury kluczy publicznych do szyfrowania danych o dużej ilości jest stosunkowo niska wydajność. Z powodu intensywnej matematyki szyfrowanie i odszyfrowywanie danych przy użyciu asymetrycznego szyfrowania, które zależy od pary kluczy, może być do 1000 razy wolniejsze niż szyfrowanie i odszyfrowywanie przy użyciu symetrycznego szyfrowania, który zależy tylko od jednego klucza. W związku z tym protokół TLS używa infrastruktury kluczy publicznych tylko do generowania podpisów cyfrowych i negocjowania pojedynczego klucza specyficznego dla sesji, który będzie używany zarówno przez klienta, jak i serwer do zbiorczego szyfrowania i odszyfrowywania danych. Protokół TLS obsługuje szeroką gamę szyfrów symetrycznych z jednym kluczem, a w przyszłości można dodać dodatkowe szyfry.
Aby uzyskać więcej informacji na temat protokołu uzgadniania TLS, zobacz TLS Handshake Protocol.
Aby uzyskać więcej informacji na temat kryptografii za protokołem TLS, zobacz Cryptography Essentials.
Certyfikaty X.509
Krytycznym problemem, który musi być obsługiwany przez infrastrukturę kluczy publicznych, jest możliwość zaufania do autentyczności używanego klucza publicznego. Jeśli używasz klucza publicznego wystawionego firmie, z którą chcesz wykonywać interesy, chcesz mieć pewność, że klucz rzeczywiście należy do firmy, a nie do złodzieja, który chce odnaleźć swój numer karty kredytowej.
Aby zagwarantować tożsamość podmiotu zabezpieczeń zawierającego parę kluczy, podmiot zabezpieczeń jest wystawiany certyfikat X.509 przez urząd certyfikacji (CA). Ten certyfikat zawiera informacje identyfikujące podmiot zabezpieczeń, zawierający klucz publiczny podmiotu zabezpieczeń i podpisywane cyfrowo przez urząd certyfikacji. Ten podpis cyfrowy wskazuje, że urząd certyfikacji uważa, że klucz publiczny zawarty w certyfikacie rzeczywiście należy do podmiotu zabezpieczeń określonego przez certyfikat.
Jak ufać urzędowi certyfikacji? Ponieważ sam urząd certyfikacji posiada certyfikat X.509 podpisany przez urząd certyfikacji wyższego poziomu. Ten łańcuch podpisów certyfikatów będzie kontynuowany, dopóki nie osiągnie głównego urzędu certyfikacji, który jest urzędem certyfikacji podpisujący własne certyfikaty. Jeśli ufasz integralności głównego urzędu certyfikacji certyfikatu, powinno być możliwe zaufanie do autentyczności samego certyfikatu. W związku z tym wybór głównych urzędów certyfikacji, którym chcesz ufać, jest ważnym obowiązkiem administratora systemu.
Certyfikaty klienta
Po pierwszym pojawieniu się protokołów warstwy transportu zabezpieczeń ich głównym celem było zagwarantowanie, że klient łączy się z serwerem autentycznym i pomaga chronić prywatność danych podczas przesyłania. Jednak protokoły SSL 3.0 i TLS 1.0 obejmują również obsługę transmisji certyfikatu klienta podczas uzgadniania protokołu. Ta opcjonalna funkcja umożliwia wzajemne uwierzytelnianie klienta i serwera.
Decyzja o tym, czy używać certyfikatu klienta, powinna zostać podjęta w kontekście aplikacji. Certyfikaty klienta są niepotrzebne, jeśli podstawowe wymaganie uwierzytelnia serwer. Jeśli jednak uwierzytelnianie klienta jest niezbędne, można użyć certyfikatu klienta zamiast polegać na niestandardowym uwierzytelnianiu w aplikacji. Użycie certyfikatów klienta jest preferowane w przypadku uwierzytelniania niestandardowego, ponieważ zapewnia użytkownikom scenariusz logowania jednokrotnego.
Korzystanie z protokołu TLS w modelu COM
Protokół TLS obsługuje tylko poziom personifikacji (RPC_C_IMP_LEVEL_IMPERSONATE) personifikacji. Jeśli com negocjuje protokół TLS jako usługę uwierzytelniania na serwerze proxy, com ustawi poziom personifikacji na personifikację niezależnie od domyślnego procesu. Aby personifikacja działała prawidłowo w protokole TLS, klient musi podać certyfikat X.509 na serwerze, a serwer musi mieć ten certyfikat zamapowany na określone konto użytkownika na serwerze. Aby uzyskać więcej informacji, zobacz przewodnik krok po kroku mapowania certyfikatów na konta użytkowników.
Protokół TLS nie obsługuje maskowania. Jeśli w wywołaniu CoInitializeSecurity lub wywołaniu IClientSecurity::SetBlanket wywołanie E_INVALIDARG, zostanie zwrócona flaga maskowania i TLS.
Protokół TLS nie działa z poziomem uwierzytelniania ustawionym na Brak. Uzgadnianie między klientem a serwerem sprawdza poziom uwierzytelniania ustawiony przez poszczególne jednostki i wybiera wyższe ustawienie zabezpieczeń dla połączenia.
Parametry zabezpieczeń protokołu TLS można ustawić, wywołując CoInitializeSecurity i CoSetProxyBlanket. W poniższych sekcjach opisano niuanse związane z wykonywaniem tych wywołań.
Jak serwer ustawia koc zabezpieczeń
Jeśli serwer chce używać protokołu TLS, musi określić Schannel (RPC_C_AUTHN_GSS_SCHANNEL) jako usługę uwierzytelniania w asAuthSvc parametru CoInitializeSecurity. Aby uniemożliwić klientom nawiązywanie połączenia z serwerem przy użyciu mniej bezpiecznej usługi uwierzytelniania, serwer powinien określić tylko Schannel jako usługę uwierzytelniania, gdy wywołuje CoInitializeSecurity. Serwer nie może zmienić koca zabezpieczeń po wywołaniu CoInitializeSecurity.
Aby użyć protokołu TLS, należy określić następujące parametry, gdy serwer wywołuje CoInitializeSecurity:
- pVoid powinna być wskaźnikiem do obiektu IAccessControl lub wskaźnika do SECURITY_DESCRIPTOR. Nie należy null ani wskaźnika do identyfikatora AppID.
- cAuthSvc nie może być 0 ani -1. Serwery COM nigdy nie wybierają Schannel, gdy cAuthSvcwynosi -1.
-
asAuthSvc musi określić usługę uwierzytelniania Schannel jako usługę uwierzytelniania. W tym celu należy ustawić następujące parametry SOLE_AUTHENTICATION_SERVICE dla elementu członkowskiego Schannel SOLE_AUTHENTICATION_LIST:
- dwAuthnSvc musi być RPC_C_AUTHN_GSS_SCHANNEL.
- dwAuthzSvc powinny być RPC_C_AUTHZ_NONE. Obecnie jest on ignorowany.
- pPrincipalName musi być wskaźnikiem do CERT_CONTEXT, rzutowania jako wskaźnika do OLECHAR, który reprezentuje certyfikat X.509 serwera.
- dwAuthnLevel wskazuje minimalny poziom uwierzytelniania, który zostanie zaakceptowany przez klientów na potrzeby pomyślnego połączenia. Nie można tego RPC_C_AUTHN_LEVEL_NONE.
- dwCapabilities nie powinien mieć ustawionej flagi EOAC_APPID. Flaga EOAC_ACCESS_CONTROL powinna być ustawiona, jeśli pVoid wskazuje obiekt IAccessControl; Nie należy go ustawiać, jeśli pVoid wskazuje SECURITY_DESCRIPTOR. Aby uzyskać inne flagi, które mogą być ustawione, zobacz CoInitializeSecurity.
Aby uzyskać więcej informacji na temat używania CoInitializeSecurity, zobacz Setting Processwide Security with CoInitializeSecurity.
Jak klient ustawia koc zabezpieczeń
Jeśli klient chce używać protokołu TLS, musi określić Schannel (RPC_C_AUTHN_GSS_SCHANNEL) na liście usług uwierzytelniania w parametrze pAuthList parametru CoInitializeSecurity. Jeśli usługa Schannel nie zostanie określona jako możliwa usługa uwierzytelniania, gdy zostanie wywołana CoInitializeSecurity, późniejsze wywołanie CoSetProxyBlanket (lub IClientSecurity::SetBlanket) zakończy się niepowodzeniem, jeśli spróbuje określić Schannel jako usługę uwierzytelniania.
Następujące parametry należy określić, gdy klient wywołuje CoInitializeSecurity:
- dwAuthnLevel określa domyślny poziom uwierzytelniania, którego klient chce użyć. Nie można tego RPC_C_AUTHN_LEVEL_NONE.
- dwImpLevel musi być RPC_C_IMP_LEVEL_IMPERSONATE.
-
pAuthList musi mieć następujące parametry SOLE_AUTHENTICATION_INFO jako element członkowski listy:
- dwAuthnSvc musi być RPC_C_AUTHN_GSS_SCHANNEL.
- dwAuthzSvc musi być RPC_C_AUTHZ_NONE.
- pAuthInfo jest wskaźnikiem do CERT_CONTEXT, rzutowania jako wskaźnika na void, który reprezentuje certyfikat X.509 klienta. Jeśli klient nie ma certyfikatu lub nie chce przedstawić certyfikatu serwerowi, pAuthInfo musi być null i zostanie podjęta próba połączenia anonimowego z serwerem.
- dwCapabilities to zestaw flag wskazujący dodatkowe możliwości klienta. Aby uzyskać informacje na temat flag, które należy ustawić, zobacz CoInitializeSecurity.
Aby uzyskać więcej informacji na temat używania CoInitializeSecurity, zobacz Setting Processwide Security with CoInitializeSecurity.
Jak klient zmienia koc zabezpieczeń
Jeśli klient chce użyć protokołu TLS, ale zmienić koc zabezpieczeń po wywołaniu CoInitializeSecurity, musi wywołać CoSetProxyBlanket lub IClientSecurity::SetBlanket z parametrami podobnymi do tych używanych w wywołaniu do CoInitializeSecurity, z następującymi różnicami:
- pServerPrincName wskazuje główną nazwę serwera w formacie msstd lub fullsic. Aby uzyskać informacje na temat tych formatów, zobacz Principal Names. Jeśli klient ma certyfikat X.509 serwera, może znaleźć nazwę główną, wywołując RpcCertGeneratePrincipalName.
- pAuthInfo jest wskaźnikiem do CERT_CONTEXT, rzutowania jako wskaźnika do RPC_AUTH_IDENTITY_HANDLE, który reprezentuje certyfikat X.509 klienta. Jeśli klient nie ma certyfikatu lub nie chce przedstawić certyfikatu serwerowi, pAuthInfo musi być null i zostanie podjęta próba połączenia anonimowego z serwerem.
- dwCapabilities składa się z flag wskazujących dodatkowe możliwości klienta. Tylko cztery flagi mogą służyć do zmiany ustawień koca zabezpieczeń: EOAC_DEFAULT, EOAC_MUTUAL_AUTH, EOAC_ANY_AUTHORITY (ta flaga jest przestarzała) i EOAC_MAKE_FULLSIC. Aby uzyskać więcej informacji, zobacz CoSetProxyBlanket.
Aby uzyskać więcej informacji na temat używania coSetProxyBlanket, zobacz Ustawianie zabezpieczeń na poziomie serwera proxy interfejsu.
Przykład: Klient zmienia koc zabezpieczeń
W poniższym przykładzie pokazano, jak klient może zmienić koc zabezpieczeń, aby uwzględnić żądanie z serwera dla klienta w celu dostarczenia certyfikatu X.509. Kod obsługi błędów jest pomijany w celu zwięzłości.
void ClientChangesSecurity ()
{
HCRYPTPROV provider = 0;
HCERTSTORE cert_store = NULL;
PCCERT_CONTEXT client_cert = NULL;
PCCERT_CONTEXT server_cert = NULL;
WCHAR *server_princ_name = NULL;
ISecret *pSecret = NULL;
MULTI_QI server_instance;
COSERVERINFO server_machine;
SOLE_AUTHENTICATION_LIST auth_list;
SOLE_AUTHENTICATION_INFO auth_info[1];
// Specify all the authentication info.
// The client is willing to connect using SChannel,
// with no client certificate.
auth_list.cAuthInfo = 1;
auth_list.aAuthInfo = auth_info;
auth_info[0].dwAuthnSvc = RPC_C_AUTHN_GSS_SCHANNEL;
auth_info[0].dwAuthzSvc = RPC_C_AUTHZ_NONE;
auth_info[0].pAuthInfo = NULL; // No certificate
// Initialize client security with no client certificate.
CoInitializeSecurity( NULL, -1, NULL, NULL,
RPC_C_AUTHN_LEVEL_PKT,
RPC_C_IMP_LEVEL_IMPERSONATE, &auth_list,
EOAC_NONE, NULL );
// Specify info for the proxy.
server_instance = {&IID_ISecret, NULL, S_OK};
server_machine = {0, L"ServerMachineName", NULL, 0};
// Create a proxy.
CoCreateInstanceEx( CLSID_Secret, NULL, CLSCTX_REMOTE_SERVER,
&server_machine, 1, &server_instance);
pSecret = (ISecret *) server_instance.pItf;
//** The client obtained the server's certificate during the handshake.
//** The server requests a certificate from the client.
// Get the default certificate provider.
CryptAcquireContext( &provider, NULL, NULL, PROV_RSA_SCHANNEL, 0 );
// Open the certificate store.
cert_store = CertOpenSystemStore( provider, L"my" );
// Find the client's certificate.
client_cert =
CertFindCertificateInStore( cert_store,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
0,
CERT_FIND_SUBJECT_STR,
L"ClientName", // Use the principal name
NULL );
// Find the fullsic principal name of the server.
RpcCertGeneratePrincipalName( server_cert, RPC_C_FULL_CERT_CHAIN,
&server_princ_name );
// Change the client's security:
// Increase the authentication level and attach a certificate.
CoSetProxyBlanket( pSecret, RPC_C_AUTHN_GSS_SCHANNEL,
RPC_C_AUTHZ_NONE,
server_princ_name, RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
RPC_C_IMP_LEVEL_IMPERSONATE,
(RPC_AUTH_IDENTITY_HANDLE *) client_cert,
EOAC_NONE );
cleanup:
if (server_princ_name != NULL)
RpcStringFree( &server_princ_name );
if (client_cert != NULL)
CertFreeCertificateContext(client_cert);
if (server_cert != NULL)
CertFreeCertificateContext(server_cert);
if (cert_store != NULL)
CertCloseStore( cert_store, CERT_CLOSE_STORE_CHECK_FLAG );
if (provider != 0 )
CryptReleaseContext( provider, 0 );
if (pSecret != NULL)
pSecret->Release();
CoUninitialize();
}
Tematy pokrewne