Dela via


SSPI/Kerberos-samverkan med GSSAPI

Var försiktig när du använder KerberosSSP (Security Support Provider) om samverkan med GSSAPI är ett krav. Följande kodkonventioner tillåter samverkan med GSSAPI-baserade program:

Du hittar exempelkod i Platform Software Development Kit (SDK) under Samples\Security\SSPI\GSS. Dessutom distribueras motsvarande UNIX-exempel i MIT- och Heimdal Kerberos-distributionerna, GSS-klienten och servern.

Windows-Compatible namn

GSSAPI-funktioner använder ett namnformat som kallas gss_nt_service_name som anges i RFC. Till exempel är sample@host.dom.com ett namn som kan användas i ett GSSAPI-baserat program. Windows-operativsystemet känner inte igen gss_nt_service_name format och det fullständiga tjänstens huvudnamn, till exempel exempel sample/host.dom.com@REALM, måste användas.

Autentisering

Autentisering hanteras vanligtvis när en anslutning först konfigureras mellan en klient och en server. I det här exemplet använder klienten SSPI (Security Support Provider Interface) och servern använder GSSAPI.

Konfigurera autentisering i SSPI-klienten

  1. Hämta utgående autentiseringsuppgifter med hjälp av AcquireCredentialsHandle.
  2. Skapa ett tjänstnamn med gss_import_name() och hämta inkommande autentiseringsuppgifter med hjälp av gss_acquire_cred.
  3. Hämta en autentiseringstoken som ska skickas till servern med hjälp av InitializeSecurityContext (Kerberos).
  4. Skicka token till servern.

Konfigurera autentisering på GSSAPI-servern

  1. Parsa meddelandet från klienten för att extrahera säkerhetstoken. Använd funktionen gss_accept_sec_context och skicka token som ett argument.

  2. Parsa meddelandet från servern för att extrahera säkerhetstoken. Skicka den här säkerhetstoken till InitializeSecurityContext (Kerberos).

  3. Skicka en svarstoken till klienten.

    Funktionen gss_accept_sec_context kan returnera en token som du kan skicka tillbaka till klienten.

  4. Om det är nödvändigt att fortsätta skickar du en svarstoken till servern. annars är autentiseringskonfigurationen klar.

  5. Om det är nödvändigt att fortsätta väntar du på nästa token från klienten. annars är autentiseringskonfigurationen klar.

Meddelandeintegritet och sekretess

De flesta GSSAPI-baserade program använder funktionen GSS_Wrap för att signera ett meddelande innan det skickas. Omvänt verifierar funktionen GSS_Unwrap signaturen. GSS_Wrap är tillgängligt i version 2.0 av API:et och används nu ofta och anges i Internetstandarder som beskriver hur du använder GSSAPI för att lägga till säkerhet i protokoll. Tidigare användes funktionerna GSS SignMessage och SealMessage för integritet och sekretess. GSS_Wrap och GSS_Unwrap används för både integritet och sekretess med användning av sekretess som styrs av värdet för argumentet "conf_flag".

Om ett GSSAPI-baserat protokoll har angetts för att använda funktionerna gss_get_mic och gss_verify_mic är rätt SSPI-funktioner MakeSignature och VerifySignature. Tänk på att MakeSignature och VerifySignature inte samverkar med GSS_Wrap när conf_flag är inställt på noll eller med GSS_Unwrap. Detsamma gäller för blandning av EncryptMessage (Kerberos) endast för signatur och gss_verify_mic.

Not

Använd inte funktionerna MakeSignature eller VerifySignature när GSS_Wrap och GSS_Unwrap anropas.

 

SSPI:n som motsvarar GSS_Wrap är EncryptMessage (Kerberos) för både integritet och sekretess.

I följande exempel visas hur du använder EncryptMessage (Kerberos) för att signera data som ska verifieras av GSS_Unwrap.

I SSPI-klienten:

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

På GSSAPI-servern:

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

SSPI:n som motsvarar GSS_Unwrap är DecryptMessage (Kerberos). Här är ett exempel som visar hur du använder DecryptMessage (Kerberos) för att dekryptera data som krypterats av GSS_Wrap.

På GSSAPI-servern:

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

I SSPI-klienten:

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.