Udostępnij za pośrednictwem


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

  1. Uzyskiwanie poświadczeń wychodzących przy użyciu AcquireCredentialsHandle.
  2. Utwórz nazwę usługi z () gss_import_name i uzyskaj poświadczenia przychodzące przy użyciu gss_acquire_cred.
  3. Pobierz token uwierzytelniania do wysłania na serwer przy użyciu InitializeSecurityContext (Kerberos).
  4. Wyślij token do serwera.

Aby skonfigurować uwierzytelnianie na serwerze GSSAPI

  1. Przeanalizuj komunikat od klienta, aby wyodrębnić token zabezpieczający. Użyj funkcji gss_accept_sec_context, przekazując token jako argument.

  2. Przeanalizuj komunikat z serwera, aby wyodrębnić token zabezpieczający. Przekaż ten token zabezpieczający do initializeSecurityContext (Kerberos).

  3. Wyślij token odpowiedzi do klienta.

    Funkcja gss_accept_sec_context może zwrócić token, który można odesłać do klienta.

  4. Jeśli konieczne jest kontynuowanie, wyślij token odpowiedzi do serwera; w przeciwnym razie konfiguracja uwierzytelniania zostanie ukończona.

  5. 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.