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 用戶端中設定驗證
- 使用AcquireCredentialsHandle取得輸出認證。
- 使用 gss_import_name () 建立服務名稱,並使用 gss_acquire_cred取得輸入認證。
- 使用 InitializeSecurityCoNtext (Kerberos) 取得要傳送至伺服器的驗證權杖。
- 將權杖傳送至伺服器。
在 GSSAPI 伺服器中設定驗證
剖析來自用戶端的訊息,以擷取安全性權杖。 使用 gss_accept_sec_coNtext 函式,將權杖傳遞為引數。
剖析伺服器中的訊息以擷取安全性權杖。 將此安全性權杖傳遞至 InitializeSecurityCoNtext (Kerberos) 。
將回應權杖傳送至用戶端。
gss_accept_sec_coNtext函式可以傳回您可以傳回給用戶端的權杖。
如果需要繼續,請將回應權杖傳送至伺服器;否則,驗證的設定就會完成。
如果需要繼續,請等候用戶端的下一個權杖;否則,驗證的設定就會完成。
訊息完整性和隱私權
大部分的 GSSAPI 型應用程式會先使用 GSS_Wrap 函式來簽署訊息,再傳送訊息。 相反地, GSS_Unwrap 函式會驗證簽章。 GSS_Wrap 可在 2.0 版的 API 中使用,現在已在網際網路標準中廣泛使用並指定,這些標準描述使用 GSSAPI 將安全性新增至通訊協定。 先前,GSS SignMessage 和 SealMessage 函式用於訊息 完整性 和 隱私權。 GSS_Wrap 和 GSS_Unwrap 用於完整性和隱私權,並使用 「conf_flag」 引數值所控制的隱私權。
如果指定 GSSAPI 型通訊協定來使用 gss_get_mic 和 gss_verify_mic 函式,則正確的 SSPI 函式會是 MakeSignature 和 VerifySignature。 請注意,當conf_flag設定為零或GSS_Unwrap時,MakeSignature和VerifySignature不會與GSS_Wrap交互操作。 這也適用于只針對簽章和gss_verify_mic設定的EncryptMessage (Kerberos) 混合。
注意
呼叫 GSS_Wrap和GSS_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.
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應