Interoperabilità SSPI/Kerberos con GSSAPI

È necessario prestare attenzione quando si usa il provider di supporto per la sicurezzaKerberos se l'interoperabilità con GSSAPI è un requisito. Le convenzioni di codice seguenti consentono l'interoperabilità con le applicazioni basate su GSSAPI:

È possibile trovare codice di esempio in Platform Software Development Kit (SDK) in Samples\Security\SSPI\GSS. Inoltre, l'esempio UNIX equivalente viene distribuito nelle distribuzioni MIT e Heimdal Kerberos, client e server GSS.

nomi Windows-Compatible

Le funzioni GSSAPI usano un formato di nome noto come gss_nt_service_name come specificato nella RFC. Ad esempio, sample@host.dom.com è un nome che può essere usato in un'applicazione basata su GSSAPI. Il sistema operativo Windows non riconosce il formato gss_nt_service_name e il nome dell'entità servizio completo, ad esempio esempio di esempio/host.dom.com@REALM, deve essere usato.

Authentication

L'autenticazione viene in genere gestita quando viene configurata una connessione tra un client e un server. In questo esempio il client usa l'interfaccia del provider di supporto della sicurezza (SSPI) e il server usa GSSAPI.

Per configurare l'autenticazione nel client SSPI

  1. Ottenere le credenziali in uscita usando AcquireCredentialsHandle.
  2. Creare un nome del servizio con gss_import_name() e ottenere le credenziali in ingresso usando gss_acquire_cred.
  3. Ottenere un token di autenticazione da inviare al server usando InitializeSecurityContext (Kerberos).
  4. Inviare il token al server.

Per configurare l'autenticazione nel server GSSAPI

  1. Analizzare il messaggio dal client per estrarre il token di sicurezza. Usare la funzione gss_accept_sec_context , passando il token come argomento.

  2. Analizzare il messaggio dal server per estrarre il token di sicurezza. Passare questo token di sicurezza a InitializeSecurityContext (Kerberos).

  3. Inviare un token di risposta al client.

    La funzione gss_accept_sec_context può restituire un token che è possibile inviare nuovamente al client.

  4. Se è necessario continuare, inviare un token di risposta al server; in caso contrario, la configurazione dell'autenticazione è stata completata.

  5. Se è necessario continuare, attendere il token successivo dal client; in caso contrario, la configurazione dell'autenticazione è stata completata.

Integrità e privacy dei messaggi

La maggior parte delle applicazioni basate su GSSAPI usa la funzione GSS_Wrap per firmare un messaggio prima di inviarlo. Al contrario, la funzione GSS_Unwrap verifica la firma. GSS_Wrap è disponibile nella versione 2.0 dell'API ed è ora ampiamente usato e specificato negli standard Internet che descrivono l'uso di GSSAPI per aggiungere la sicurezza ai protocolli. In precedenza, le funzioni GSS SignMessage e SealMessage sono state usate per l'integrità e la privacy dei messaggi. GSS_Wrap e GSS_Unwrap vengono usati sia per l'integrità che per la privacy con l'uso della privacy controllata dal valore dell'argomento "conf_flag".

Se viene specificato un protocollo basato su GSSAPI per usare le funzioni gss_get_mic e gss_verify_mic , le funzioni SSPI corrette saranno MakeSignature e VerifySignature. Tenere presente che MakeSignature e VerifySignature non interoperativi con GSS_Wrap quando conf_flag è impostato su zero o con GSS_Unwrap. Lo stesso vale per la combinazione di EncryptMessage (Kerberos) impostata solo per la firma e gss_verify_mic.

Nota

Non usare le funzioni MakeSignature o VerifySignature quando vengono chiamate GSS_Wrap e GSS_Unwrap .

 

SSPI equivalente a GSS_Wrap è EncryptMessage (Kerberos) sia per l'integrità che per la privacy.

Nell'esempio seguente viene illustrato l'uso di EncryptMessage (Kerberos) per firmare i dati che verranno verificati da GSS_Unwrap.

Nel client 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.

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

SSPI equivalente a GSS_Unwrap è DecryptMessage (Kerberos). Ecco un esempio che illustra come usare DecryptMessage (Kerberos) per decrittografare i dati crittografati da GSS_Wrap.

Nel server 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.

Nel client 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.