Share via


SSPI/Kerberos 與 GSSAPI 的互通性

如果需要與 GSSAPI 的互通性,則必須小心使用 Kerberos安全性支援提供者 (SSP) 。 下列程式碼慣例允許與 GSSAPI 型應用程式的互通性:

您可以在 Samples\Security\SSPI\GSS 底下的 [平臺軟體發展工具組] (SDK) 中找到範例程式碼。 此外,對等的 UNIX 範例會散發在 MIT 和 一個 一般 Kerberos 散發套件、GSS 用戶端和伺服器中。

Windows-Compatible名稱

GSSAPI 函式會使用名為 gss_nt_service_name 的名稱格式,如 RFC 中所指定。 例如, sample@host.dom.com 是可在 GSSAPI 型應用程式中使用的名稱。 Windows 作業系統無法辨識gss_nt_service_name格式,而且必須使用範例/host.dom.com@REALM等完整 服務主體名稱

驗證

在用戶端與伺服器之間第一次設定連線時,通常會處理驗證。 在此範例中,用戶端使用 安全性支援提供者介面 (SSPI) ,而伺服器則使用 GSSAPI。

在 SSPI 用戶端中設定驗證

  1. 使用AcquireCredentialsHandle取得輸出認證
  2. 使用 gss_import_name () 建立服務名稱,並使用 gss_acquire_cred取得輸入認證。
  3. 使用 InitializeSecurityCoNtext (Kerberos) 取得要傳送至伺服器的驗證權杖。
  4. 將權杖傳送至伺服器。

在 GSSAPI 伺服器中設定驗證

  1. 剖析來自用戶端的訊息,以擷取安全性權杖。 使用 gss_accept_sec_coNtext 函式,將權杖傳遞為引數。

  2. 剖析伺服器中的訊息以擷取安全性權杖。 將此安全性權杖傳遞至 InitializeSecurityCoNtext (Kerberos)

  3. 將回應權杖傳送至用戶端。

    gss_accept_sec_coNtext函式可以傳回您可以傳回給用戶端的權杖。

  4. 如果需要繼續,請將回應權杖傳送至伺服器;否則,驗證的設定就會完成。

  5. 如果需要繼續,請等候用戶端的下一個權杖;否則,驗證的設定就會完成。

訊息完整性和隱私權

大部分的 GSSAPI 型應用程式會先使用 GSS_Wrap 函式來簽署訊息,再傳送訊息。 相反地, GSS_Unwrap 函式會驗證簽章。 GSS_Wrap 可在 2.0 版的 API 中使用,現在已在網際網路標準中廣泛使用並指定,這些標準描述使用 GSSAPI 將安全性新增至通訊協定。 先前,GSS SignMessageSealMessage 函式用於訊息 完整性隱私權GSS_WrapGSS_Unwrap 用於完整性和隱私權,並使用 「conf_flag」 引數值所控制的隱私權。

如果指定 GSSAPI 型通訊協定來使用 gss_get_micgss_verify_mic 函式,則正確的 SSPI 函式會是 MakeSignatureVerifySignature。 請注意,當conf_flag設定為零或GSS_Unwrap時,MakeSignatureVerifySignature不會與GSS_Wrap交互操作。 這也適用于只針對簽章和gss_verify_mic設定的EncryptMessage (Kerberos) 混合。

注意

呼叫 GSS_WrapGSS_Unwrap時,請勿使用MakeSignature 或 VerifySignature函式。

 

相當於 GSS_Wrap 的 SSPI 是 EncryptMessage (Kerberos) ,適用于完整性和隱私權。

下列範例示範如何使用 EncryptMessage (Kerberos) 來簽署 GSS_Unwrap將驗證的資料。

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

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

相當於 GSS_Unwrap 的 SSPI 是 DecryptMessage (Kerberos) 。 以下範例示範如何使用 DecryptMessage (Kerberos) 來解密 GSS_Wrap加密的資料。

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

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