Współdziałanie interfejsu SSPI/Kerberos z interfejsem GSSAPI
Należy zachować ostrożność podczas korzystania z dostawcy obsługi zabezpieczeń protokołu Kerberos (SSP), jeśli wymagana jest współdziałanie z interfejsem GSSAPI. Następujące konwencje kodu umożliwiają współdziałanie z aplikacjami opartymi na interfejsie GSSAPI:
Przykładowy kod można znaleźć w zestawie Sdk platformy w obszarze Samples\Security\SSPI\GSS. Ponadto odpowiedni przykład systemu UNIX jest dystrybuowany w dystrybucjach MIT i Heimdal Kerberos, klienta I serwera GSS.
nazwy Windows-Compatible
Funkcje GSSAPI używają formatu nazwy znanego jako gss_nt_service_name określonego w specyfikacji RFC. Na przykład sample@host.dom.com to nazwa, która może być używana w aplikacji opartej na GSSAPI. System operacyjny Windows nie rozpoznaje formatu gss_nt_service_name, a należy użyć pełnej nazwy głównej usługi , na przykład sample/host.dom.com@REALM.
Uwierzytelnianie
Uwierzytelnianie jest zwykle obsługiwane, gdy najpierw skonfigurowano połączenie między klientem a serwerem. W tym przykładzie klient korzysta z interfejsu dostawcy obsługi zabezpieczeń (SSPI), a serwer korzysta z interfejsu GSSAPI.
Aby skonfigurować uwierzytelnianie w klienta SSPI
- Uzyskiwanie poświadczeń wychodzących przy użyciu AcquireCredentialsHandle.
- Utwórz nazwę usługi z () gss_import_name i uzyskaj poświadczenia przychodzące przy użyciu gss_acquire_cred.
- Pobierz token uwierzytelniania do wysłania na serwer przy użyciu InitializeSecurityContext (Kerberos).
- Wyślij token do serwera.
Aby skonfigurować uwierzytelnianie na serwerze GSSAPI
Przeanalizuj komunikat od klienta, aby wyodrębnić token zabezpieczający. Użyj funkcji gss_accept_sec_context, przekazując token jako argument.
Przeanalizuj komunikat z serwera, aby wyodrębnić token zabezpieczający. Przekaż ten token zabezpieczający do initializeSecurityContext (Kerberos).
Wyślij token odpowiedzi do klienta.
Funkcja gss_accept_sec_context może zwrócić token, który można odesłać do klienta.
Jeśli konieczne jest kontynuowanie, wyślij token odpowiedzi do serwera; w przeciwnym razie konfiguracja uwierzytelniania zostanie ukończona.
Jeśli konieczne jest kontynuowanie, zaczekaj na następny token od klienta; w przeciwnym razie konfiguracja uwierzytelniania zostanie ukończona.
Integralność i prywatność komunikatów
Większość aplikacji opartych na GSSAPI używa funkcji GSS_Wrap do podpisania komunikatu przed wysłaniem go. Z drugiej strony funkcja GSS_Unwrap weryfikuje podpis. GSS_Wrap jest dostępna w wersji 2.0 interfejsu API i jest obecnie powszechnie używana i określana w standardach internetowych, które opisują używanie interfejsu GSSAPI do dodawania zabezpieczeń do protokołów. Wcześniej funkcje usługi GSS SignMessage i SealMessage były używane do integralności komunikatów i prywatności . GSS_Wrap i GSS_Unwrap są używane zarówno do integralności, jak i prywatności przy użyciu prywatności kontrolowanej przez wartość argumentu "conf_flag".
Jeśli określono protokół oparty na interfejsie GSSAPI do używania funkcji gss_get_mic i gss_verify_mic, poprawne funkcje interfejsu SSPI będą MakeSignature i VerifySignature. Należy pamiętać, że makeSignature i VerifySignature nie będą współdziałać z GSS_Wrap, gdy conf_flag jest ustawiona na zero lub GSS_Unwrap. To samo dotyczy mieszania EncryptMessage (Kerberos) ustawione tylko dla podpisu i gss_verify_mic.
Nuta
Nie należy używać funkcji MakeSignature ani VerifySigna ture, gdy są wywoływane funkcje GSS_Wrap i GSS_Unwrap.
Interfejs SSPI odpowiadający GSS_Wrap to EncryptMessage (Kerberos) zarówno dla integralności, jak i prywatności.
W poniższym przykładzie pokazano używanie EncryptMessage (Kerberos) do podpisywania danych, które zostaną zweryfikowane przez GSS_Unwrap.
W kliencie SSPI:
// 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.
Na serwerze GSSAPI:
// 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.
Interfejs SSPI odpowiadający GSS_Unwrap to DecryptMessage (Kerberos). Oto przykład pokazujący, jak używać DecryptMessage (Kerberos) do odszyfrowania danych zaszyfrowanych przez GSS_Wrap.
Na serwerze GSSAPI:
// 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.
W kliencie SSPI:
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.