Schannel
Das Schannel-Sicherheitspaket (Secure Channel), dessen Authentifizierungsdienstbezeichner RPC C AUTHN GSS SCHANNEL ist, unterstützt die folgenden auf öffentlichen Schlüsseln basierenden _ _ _ _ Protokolle: SSL (Secure Sockets Layer) Versionen 2.0 und 3.0, Transport Layer Security (TLS) 1.0 und Private Communication Technology (PCT) 1.0. TLS 1.0 ist eine standardisierte, leicht geänderte Version von SSL 3.0, die von der Internet Engineering Task Force (IETF) im Januar 1999 im Dokument RFC 2246ausgegeben wurde. Da TLS standardisiert wurde, wird Entwicklern empfohlen, ANSTELLE von SSL TLS zu verwenden. PCT ist nur aus Gründen der Abwärtskompatibilität enthalten und sollte nicht für neue Entwicklungen verwendet werden. Wenn das Schannel-Sicherheitspaket verwendet wird, handelt DCOM abhängig von den Client- und Serverfunktionen automatisch das beste Protokoll aus.
In den folgenden Themen werden das TLS-Protokoll und seine Funktionsweise mit DCOM kurz beschrieben.
- Verwendung von TLS
- Kurze Übersicht über die Funktionsweise von TLS
- X.509-Zertifikate
- Verwenden von TLS in COM
- Zugehörige Themen
Hinweis
Alle Informationen zum TLS-Protokoll in diesen Abschnitten gelten auch für die PROTOKOLLE SSL und PCT.
Verwendung von TLS
TLS ist die einzige verfügbare Sicherheitsoption, wenn Server ihre Identität anonymen Clients nachweisen müssen. Dies ist besonders wichtig für Websites, die am E-Commerce teilnehmen möchten, da sie die Übertragung vertraulicher Informationen wie Kreditkartennummern schützen. TLS stellt sicher, dass die E-Commerce-Kunden sicher sein können, mit wem sie Geschäfte machen, da sie einen Nachweis der Identität des Servers erhalten. Außerdem erhält der E-Commerce-Server die Effizienz, sich nicht um die Authentifizierung der Identität der einzelnen Kunden zu sorgen.
TLS erfordert, dass alle Server ihre Identität clients nachweisen. Darüber hinaus bietet TLS die Möglichkeit, dass Clients ihre Identität den Servern nachweisen. Diese gegenseitige Authentifizierung kann hilfreich sein, um den Zugriff auf bestimmte Webseiten in einem großen Unternehmensintranet zu beschränken.
TLS unterstützt die stärksten Authentifizierungsebenen und bietet eine offene Architektur, die es ermöglicht, die Verschlüsselungsstärke im Laufe der Zeit zu erhöhen, um mit technologischen Innovationen Schritt zu halten. TLS ist die beste Wahl für Umgebungen, in denen die höchste Sicherheitsstufe für die Daten während der Übertragung gewünscht ist.
Kurze Übersicht über die Funktionsweise von TLS
TLS basiert auf einer Public Key-Infrastruktur (PKI), die öffentliche/private Schlüsselpaare zum Aktivieren der Datenverschlüsselung und zum Einrichten der Datenintegrität verwendet und X.509-Zertifikate für die Authentifizierung verwendet.
Viele Sicherheitsprotokolle, z. B. das Kerberos v5-Protokoll, sind von einem einzigen Schlüssel abhängig, um Daten zu verschlüsseln und zu entschlüsseln. Solche Protokolle hängen daher vom sicheren Austausch von Verschlüsselungsschlüsseln ab. im Kerberos-Protokoll erfolgt dies über Tickets, die sie vom Schlüsselverteilungscenter (KDC) erhalten. Dies erfordert, dass alle Benutzer, die das Kerberos-Protokoll verwenden, beim KDC registriert werden. Dies wäre eine unpraktische Einschränkung für einen E-Commerce-Webserver, der Millionen von Kunden aus der ganzen Welt gewinnen soll. TLS basiert daher auf einer PKI, die zwei Schlüssel für die Datenverschlüsselung verwendet. Wenn ein Schlüssel des Paars die Daten verschlüsselt, kann nur der andere Schlüssel des Paars sie entschlüsseln. Der Hauptvorteil dieses Entwurfs besteht in der Verschlüsselung, ohne dass der sichere Austausch von Verschlüsselungsschlüsseln erforderlich ist.
Eine PKI verwendet ein Verfahren, bei dem einer der Schlüssel privat gehalten wird und nur für den Prinzipal verfügbar ist, bei dem er registriert ist, während der andere Schlüssel öffentlich für jeden zugänglich gemacht wird. Wenn jemand eine private Nachricht an den Besitzer eines Schlüsselpaars senden möchte, kann die Nachricht mit dem öffentlichen Schlüssel verschlüsselt werden, und nur der private Schlüssel kann zum Entschlüsseln der Nachricht verwendet werden.
Schlüsselpaare werden auch verwendet, um die Integrität der gesendeten Daten zu überprüfen. Hierzu kann der Besitzer des Schlüsselpaars eine digitale Signatur an die Daten anfügen, bevor er sie sendet. Beim Erstellen einer digitalen Signatur wird ein Hash der Daten berechnet und der Hash mit dem privaten Schlüssel verschlüsselt. Jeder, der den öffentlichen Schlüssel zum Entschlüsseln der digitalen Signatur verwendet, ist sicher, dass die digitale Signatur nur von der Person stammen muss, die den privaten Schlüssel besitzt. Darüber hinaus kann der Empfänger einen Hash der Daten mit dem gleichen Algorithmus wie der Absender berechnen. Wenn der berechnete Hash mit dem in der digitalen Signatur gesendeten Hashwert identisch ist, kann der Empfänger sicher sein, dass die Daten nach der digitalen Signatur nicht geändert wurden.
Ein Nachteil der Verwendung einer PKI für die Datenverschlüsselung mit hohem Volumen ist die relativ geringe Leistung. Aufgrund der intensiven Mathematik kann die Verschlüsselung und Entschlüsselung von Daten mithilfe einer asymmetrischen Verschlüsselung, die von einem Schlüsselpaar abhängt, bis zu 1.000-mal langsamer sein als die Verschlüsselung und Entschlüsselung mithilfe einer symmetrischen Verschlüsselung, die nur von einem einzelnen Schlüssel abhängt. TLS verwendet daher eine PKI nur zum Generieren digitaler Signaturen und zum Aushandeln des sitzungsspezifischen einzelnen Schlüssels, der sowohl vom Client als auch vom Server für die Massenverschlüsselung und -entschlüsselung von Daten verwendet wird. TLS unterstützt eine Vielzahl von symmetrischen Verschlüsselungen mit nur einem Schlüssel, und in Zukunft können weitere Verschlüsselungen hinzugefügt werden.
Weitere Informationen zum TLS-Handshakeprotokoll finden Sie unter TLS Handshake Protocol.
Weitere Informationen zur Kryptografie hinter dem TLS-Protokoll finden Sie unter Cryptography Essentials.
X.509-Zertifikate
Ein wichtiges Problem, das von einer PKI behandelt werden muss, ist die Fähigkeit, der Authentizität des verwendeten öffentlichen Schlüssels zu vertrauen. Wenn Sie einen öffentlichen Schlüssel verwenden, der für ein Unternehmen ausgestellt wurde, mit dem Sie Geschäfte machen möchten, möchten Sie sicher sein, dass der Schlüssel tatsächlich zum Unternehmen gehört und nicht zu einem Kefef, der Ihre Kreditkartennummer entdecken möchte.
Um die Identität eines Prinzipals mit einem Schlüsselpaar zu gewährleisten, wird dem Prinzipal von einer Zertifizierungsstelle ein X.509-Zertifikat ausgestellt. Dieses Zertifikat enthält Informationen, die den Prinzipal identifizieren, den öffentlichen Schlüssel des Prinzipals enthalten und von der Zertifizierungsstelle digital signiert werden. Diese digitale Signatur gibt an, dass die Zertifizierungsstelle der Meinung ist, dass der im Zertifikat enthaltene öffentliche Schlüssel tatsächlich zu dem Prinzipal gehört, der vom Zertifikat identifiziert wird.
Und wie vertrauen Sie der Zertifizierungsstelle? Da die Zertifizierungsstelle selbst ein X.509-Zertifikat enthält, das von einer Höheren Zertifizierungsstelle signiert wurde. Diese Kette von Zertifikatsignaturen wird fortgesetzt, bis sie eine Stammzertifizierungsstelle erreicht, bei der es sich um eine Zertifizierungsstelle handelt, die ihre eigenen Zertifikate signiert. Wenn Sie der Integrität der Stammzertifizierungsstelle eines Zertifikats vertrauen, sollten Sie der Authentizität des Zertifikats selbst vertrauen können. Daher ist die Auswahl der Stammzertifizierungsstelle, der Sie vertrauen möchten, eine wichtige Aufgabe für einen Systemadministrator.
Clientzertifikate
Bei der ersten Entwicklung von Protokollen auf Sicherheitstransportebene war ihr Hauptzweck die Sicherstellung, dass ein Client eine Verbindung mit einem authentic-Server hergestellt hat, und den Schutz der Daten während der Übertragung zu unterstützen. SSL 3.0 und TLS 1.0 bieten jedoch auch Unterstützung für die Übertragung eines Clientzertifikats während des Handshakes des Protokolls. Dieses optionale Feature ermöglicht die gegenseitige Authentifizierung von Client und Server.
Die Entscheidung, ob ein Clientzertifikat verwendet werden soll, sollte im Kontext der Anwendung getroffen werden. Clientzertifikate sind nicht erforderlich, wenn die primäre Anforderung die Authentifizierung des Servers ist. Wenn die Clientauthentifizierung jedoch wichtig ist, kann das Zertifikat eines Clients verwendet werden, anstatt sich auf die benutzerdefinierte Authentifizierung innerhalb der Anwendung zu verlassen. Die Verwendung von Clientzertifikaten ist der benutzerdefinierten Authentifizierung vorzuziehen, da sie Benutzern ein Szenario für einmaliges Anmelden bietet.
Verwenden von TLS in COM
TLS unterstützt nur die Identitätswechselebene (RPC _ C _ IMP LEVEL _ _ IMPERSONATE). Wenn COM TLS als Authentifizierungsdienst auf einem Proxy aushandelt, wird die Identitätswechselebene von COM unabhängig vom Standardprozess so festgelegt, dass die Identität angenommen wird. Damit der Identitätswechsel in TLS ordnungsgemäß funktioniert, muss der Client dem Server ein X.509-Zertifikat bereitstellen, und dem Server muss dieses Zertifikat einem bestimmten Benutzerkonto auf dem Server zugeordnet sein. Weitere Informationen finden Sie in der Schritt-für-Schritt-Anleitung zum Zuordnen von Zertifikaten zu Benutzerkonten.
TLS unterstützt keine Verhenkung von. Wenn ein Cloaking-Flag und TLS in einem CoInitializeSecurity- oder IClientSecurity::SetBlanket-Aufruf angegeben werden, wird E _ INVALIDARG zurückgegeben.
TLS funktioniert nicht mit der Authentifizierungsebene, die auf Keine festgelegt ist. Der Handshake zwischen Client und Server untersucht die jeweils festgelegten Authentifizierungsebenen und wählt die höhere Sicherheitseinstellung für die Verbindung aus.
Die Sicherheitsparameter für TLS können durch Aufrufen von CoInitializeSecurity und CoSetProxyBlanket festgelegt werden. In den folgenden Abschnitten werden die Nuancen beschrieben, die mit diesen Aufrufen verbunden sind.
So legt ein Server die Sicherheitsbeauftragung fest
Wenn ein Server TLS verwenden möchte, muss er Schannel (RPC _ C AUTHN GSS SCHANNEL) als Authentifizierungsdienst im _ _ _ asAuthSvc-Parameter von CoInitializeSecurity angeben. Um zu verhindern, dass Clients mithilfe eines weniger sicheren Authentifizierungsdiensts eine Verbindung mit dem Server herstellen, sollte der Server nur Schannel als Authentifizierungsdienst angeben, wenn er CoInitializeSecurity aufruft. Der Server kann die Sicherheitsrisiken nicht ändern, nachdem er CoInitializeSecurity aufgerufen hat.
Um TLS zu verwenden, sollten die folgenden Parameter angegeben werden, wenn ein Server CoInitializeSecurity aufruft:
- pVoid sollte entweder ein Zeiger auf ein IAccessControl-Objekt oder ein Zeiger auf einen SECURITY _ DESCRIPTOR sein. Es sollte weder NULL noch ein Zeiger auf eine AppID sein.
- cAuthSvc darf nicht 0 oder -1 sein. COM-Server wählen schannel nie aus, wenn cAuthSvc-1 ist.
- asAuthSvc muss Schannel als möglichen Authentifizierungsdienst angeben. Dies erfolgt durch Festlegen der folgenden PARAMETER für DEN SOLE AUTHENTICATION _ _ SERVICE für das Schannel-Mitglied der LISTE DER _ ALLEINIGEN _ AUTHENTIFIZIERUNG:
- dwAuthnSvc muss RPC _ C _ AUTHN _ GSS _ SCHANNEL sein.
- dwAuthzSvc sollte RPC _ C _ RPCHZ NONE _ lauten. Derzeit wird sie ignoriert.
- pPrincipalName muss ein Zeiger auf einen CERT _ CONTEXTsein, der als Zeiger in OLECHAR, das das X.509-Zertifikat des Servers darstellt, cast ist.
- dwAuthnLevel gibt die minimale Authentifizierungsebene an, die von Clients für eine erfolgreiche Verbindung akzeptiert wird. Es darf nicht RPC _ C _ AUTHN _ LEVEL NONE _ sein.
- für dwCapabilities sollte das _ EOAC-APPID-Flag nicht festgelegt sein. Das EOAC ACCESS CONTROL-Flag sollte festgelegt werden, wenn pVoid auf ein IAccessControl-Objekt zeigt. Es sollte nicht festgelegt werden, wenn pVoid auf einen _ _ SECURITY _ DESCRIPTOR zeigt. Informationen zu anderen Flags, die festgelegt werden können, finden Sie unter CoInitializeSecurity.
Weitere Informationen zur Verwendung von CoInitializeSecurity finden Sieunter Setting Processwide Security with CoInitializeSecurity.
So legt ein Client die Sicherheitsbeauftragung fest
Wenn ein Client TLS verwenden möchte, muss er Schannel (RPC _ C AUTHN GSS SCHANNEL) in der Liste der Authentifizierungsdienste im _ _ _ pAuthList-Parameter von CoInitializeSecurity angeben. Wenn Schannel beim Aufruf von CoInitializeSecurity nicht als möglicher Authentifizierungsdienst angegeben wird, wird bei einem späteren Aufruf von CoSetProxyBlanket (oder IClientSecurity::SetBlanket)ein Fehler auftreten, wenn versucht wird, Schannel als Authentifizierungsdienst anzugeben.
Die folgenden Parameter sollten angegeben werden, wenn ein Client CoInitializeSecurity aufruft:
- dwAuthnLevel gibt die Standardauthentifizierungsebene an, die der Client verwenden möchte. Es darf nicht RPC _ C _ AUTHN _ LEVEL NONE _ sein.
- dwImpLevel muss RPC _ C IMP LEVEL _ _ _ IMPERSONATE sein.
- pAuthList muss als Mitglied der Liste über die folgenden PARAMETER FÜR DIE INFORMATION ZUR AUTHENTIFIZIERUNG _ _ verfügen:
- dwAuthnSvc muss RPC _ C _ AUTHN _ GSS _ SCHANNEL sein.
- dwAuthzSvc muss RPC _ _ CAUTHHZ _ NONE lauten.
- pAuthInfo ist ein Zeiger auf einen CERT _ CONTEXT,der als Zeiger auf void umfällt, der das X.509-Zertifikat des Clients darstellt. Wenn der Client nicht über ein Zertifikat verfügt oder sein Zertifikat dem Server nicht präsentieren möchte, muss pAuthInfo NULL sein, und es wird versucht, eine anonyme Verbindung mit dem Server herzustellen.
- dwCapabilities ist ein Satz von Flags, die zusätzliche Clientfunktionen angeben. Informationen dazu, welche Flags festgelegt werden sollen, finden Sie unter CoInitializeSecurity.
Weitere Informationen zur Verwendung von CoInitializeSecurity finden Sieunter Setting Processwide Security with CoInitializeSecurity.
Wie ein Client die Sicherheitsbeauftragung ändert
Wenn ein Client TLS verwenden, aber die Sicherheitsunterlage nach dem Aufruf von CoInitializeSecurityändern möchte, muss er entweder CoSetProxyBlanket oder IClientSecurity::SetBlanket mit Parametern aufrufen, die denen im Aufruf von CoInitializeSecurity ähneln, mit den folgenden Unterschieden:
- pServerPrincName gibt den Prinzipalnamen des Servers im msstd- oder fullsic-Format an. Informationen zu diesen Formaten finden Sie unter Prinzipalnamen. Wenn der Client über das X.509-Zertifikat des Servers verfügt, kann er den Prinzipalnamen durch Aufrufen von RpcCertGeneratePrincipalName finden.
- pAuthInfo ist ein Zeiger auf einen CERT _ CONTEXT,der als Zeiger auf RPC AUTH IDENTITY HANDLE, das das _ _ _ X.509-Zertifikat des Clients darstellt, umgegangen wird. Wenn der Client nicht über ein Zertifikat verfügt oder sein Zertifikat dem Server nicht präsentieren möchte, muss pAuthInfo NULL sein, und es wird versucht, eine anonyme Verbindung mit dem Server herzustellen.
- dwCapabilities besteht aus Flags, die zusätzliche Clientfunktionen angeben. Es können nur vier Flags verwendet werden, um Einstellungen für Sicherheitseinstellungen zu ändern: _ EOAC DEFAULT, EOAC _ MUTUAL _ AUTH, EOAC ANY AUTHORITY (dieses Flag ist veraltet) und _ _ EOAC _ MAKE _ FULLSIC. Weitere Informationen finden Sie unter CoSetProxyBlanket.
Weitere Informationen zur Verwendung von CoSetProxyBlanket findenSie unter Festlegen der Sicherheit auf Schnittstellenproxyebene.
Beispiel: Client ändert sicherheitsretin
Im folgenden Beispiel wird veranschaulicht, wie ein Client die Sicherheit ändern kann, um eine Anforderung vom Server für den Client zur Bereitstellung seines X.509-Zertifikats zu unterstützen. Fehlerbehandlungscode wird aus Kürze weggelassen.
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();
}