SSPI/Kerberos-Interoperabilität mit GSSAPI

Bei der Verwendung des Kerberos-Sicherheitsunterstützungsanbieters (Security Support Provider, SSP) ist Vorsicht erforderlich, wenn die Interoperabilität mit GSSAPI erforderlich ist. Die folgenden Codekonventionen ermöglichen die Interoperabilität mit GSSAPI-basierten Anwendungen:

Beispielcode finden Sie im Platform Software Development Kit (SDK) unter Samples\Security\SSPI\GSS. Darüber hinaus wird das entsprechende UNIX-Beispiel in den Kerberos-Distributionen MIT und Heimdal, GSS-Client und -Server verteilt.

Windows-Compatible Namen

GSSAPI-Funktionen verwenden ein Namensformat, das als gss_nt_service_name bezeichnet wird, wie im RFC angegeben. Beispielsweise ist ein Name, sample@host.dom.com der in einer GSSAPI-basierten Anwendung verwendet werden kann. Das Windows-Betriebssystem erkennt das gss_nt_service_name-Format nicht, und der Vollständige Dienstprinzipalname, z. B. Sample/host.dom.com@REALM, muss verwendet werden.

Authentifizierung

Die Authentifizierung wird in der Regel verarbeitet, wenn zum ersten Mal eine Verbindung zwischen einem Client und einem Server eingerichtet wird. In diesem Beispiel verwendet der Client SSPI ( Security Support Provider Interface ), und der Server verwendet GSSAPI.

So richten Sie die Authentifizierung im SSPI-Client ein

  1. Abrufen ausgehender Anmeldeinformationen mithilfe von AcquireCredentialsHandle.
  2. Erstellen Sie einen Dienstnamen mit gss_import_name(), und rufen Sie eingehende Anmeldeinformationen mithilfe von gss_acquire_cred ab.
  3. Rufen Sie ein Authentifizierungstoken ab, das mithilfe von InitializeSecurityContext (Kerberos) an den Server gesendet werden soll.
  4. Senden Sie das Token an den Server.

So richten Sie die Authentifizierung auf dem GSSAPI-Server ein

  1. Analysieren Sie die Nachricht vom Client, um das Sicherheitstoken zu extrahieren. Verwenden Sie die gss_accept_sec_context-Funktion , und übergeben Sie das Token als Argument.

  2. Analysieren Sie die Nachricht vom Server, um das Sicherheitstoken zu extrahieren. Übergeben Sie dieses Sicherheitstoken an InitializeSecurityContext (Kerberos).

  3. Senden sie ein Antworttoken an den Client.

    Die funktion gss_accept_sec_context kann ein Token zurückgeben, das Sie an den Client zurücksenden können.

  4. Wenn der Vorgang fortgesetzt werden muss, senden Sie ein Antworttoken an den Server. Andernfalls ist die Einrichtung der Authentifizierung abgeschlossen.

  5. Wenn der Vorgang fortgesetzt werden muss, warten Sie auf das nächste Token vom Client. Andernfalls ist die Einrichtung der Authentifizierung abgeschlossen.

Nachrichtenintegrität und Datenschutz

Die meisten GSSAPI-basierten Anwendungen verwenden die funktion GSS_Wrap , um eine Nachricht vor dem Senden zu signieren. Umgekehrt überprüft die funktion GSS_Unwrap die Signatur. GSS_Wrap ist in Version 2.0 der API verfügbar und wird jetzt häufig verwendet und in Internetstandards angegeben, die die Verwendung der GSSAPI zum Hinzufügen von Sicherheit zu Protokollen beschreiben. Zuvor wurden die GSS-Funktionen SignMessage und SealMessage für die Nachrichtenintegrität und den Datenschutz verwendet. GSS_Wrap und GSS_Unwrap werden sowohl für Die Integrität als auch für den Datenschutz verwendet, wobei der Datenschutz durch den Wert des Arguments "conf_flag" gesteuert wird.

Wenn ein GSSAPI-basiertes Protokoll für die Verwendung der funktionen gss_get_mic und gss_verify_mic angegeben wird, wären die richtigen SSPI-Funktionen MakeSignature und VerifySignature. Beachten Sie, dass MakeSignature und VerifySignature nicht mit GSS_Wrap zusammenarbeiten, wenn conf_flag auf null festgelegt ist, oder mit GSS_Unwrap. Gleiches gilt für das Mischen von EncryptMessage (Kerberos), die nur für Signatur und gss_verify_mic festgelegt ist.

Hinweis

Verwenden Sie die Funktionen MakeSignature oder VerifySignature nicht, wenn GSS_Wrap und GSS_Unwrap aufgerufen werden.

 

Das SSPI-Äquivalent zu GSS_Wrap ist EncryptMessage (Kerberos) aus Gründen der Integrität und des Datenschutzes.

Das folgende Beispiel zeigt die Verwendung von EncryptMessage (Kerberos) zum Signieren von Daten, die von GSS_Unwrap überprüft werden.

Im SSPI-Client:

// Need three descriptors, two for the SSP and
// one to hold the application data. 
in_buf_desc.cBuffers = 3;
in_buf_desc.pBuffers = wrap_bufs;
in_buf_desc.ulVersion = SECBUFFER_VERSION;
wrap_bufs[0].cbBuffer = sizes.cbSecurityTrailer;
wrap_bufs[0].BufferType = SECBUFFER_TOKEN;
wrap_bufs[0].pvBuffer = malloc(sizes.cbSecurityTrailer);

// This buffer holds the application data.
wrap_bufs[1].BufferType = SECBUFFER_DATA;
wrap_bufs[1].cbBuffer = in_buf.cbBuffer;
wrap_bufs[1].pvBuffer = malloc(wrap_bufs[1].cbBuffer);
memcpy(wrap_bufs[1].pvBuffer, in_buf.pvBuffer, in_buf.cbBuffer);
wrap_bufs[2].BufferType = SECBUFFER_PADDING;
wrap_bufs[2].cbBuffer = sizes.cbBlockSize;
wrap_bufs[2].pvBuffer = malloc(wrap_bufs[2].cbBuffer);
maj_stat = EncryptMessage(&context,
SignOnly ? KERB_WRAP_NO_ENCRYPT : 0,
&in_buf_desc, 0);

// Send a message to the server.

Auf dem GSSAPI-Server:

// Received message is in recv_buf. 
maj_stat = gss_unwrap(&min_stat, context, &recv_buf, &msg_buf,
    &conf_state, (gss_qop_t *) NULL);
(void) gss_release_buffer(&min_stat, &recv_buf);

// Original message is in msg_buf.

Die SSPI, die GSS_Unwrap entspricht, ist DecryptMessage (Kerberos). Hier ist ein Beispiel, das zeigt, wie DecryptMessage (Kerberos) zum Entschlüsseln von Daten verwendet wird, die von GSS_Wrap verschlüsselt wurden.

Auf dem GSSAPI-Server:

// Seal the message.
send_buf.value = msg;
send_buf.length = msglen;

// If encrypt_flag = 1, privacy; encrypt_flag = 0, integrity.
maj_stat = gss_wrap(&min_stat, context, encrypt_flag,
    GSS_C_QOP_DEFAULT, &send_buf, &state, &msg_buf); 

// The message to send is in msg_buf.

Im SSPI-Client:

wrap_buf_desc.cBuffers = 2;
wrap_buf_desc.pBuffers = wrap_bufs;
wrap_buf_desc.ulVersion = SECBUFFER_VERSION; 

// This buffer is for SSPI.
wrap_bufs[0].BufferType = SECBUFFER_STREAM;
wrap_bufs[0].pvBuffer = xmit_buf.pvBuffer;
wrap_bufs[0].cbBuffer = xmit_buf.cbBuffer;

// This buffer holds the application data.
wrap_bufs[1].BufferType = SECBUFFER_DATA;
wrap_bufs[1].cbBuffer = 0;
wrap_bufs[1].pvBuffer = NULL;
maj_stat = DecryptMessage(
&context,
&wrap_buf_desc,
0, // no sequence number
&qop
);

// This is where the data is.
msg_buf = wrap_bufs[1];

// Check QOP of received message.
// If QOP is KERB_WRAP_NO_ENCRYPT, the message is signed only; 
// otherwise, it is encrypted.