Interoperabilità SSPI/Kerberos con GSSAPI

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

Il codice di esempio è disponibile 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 compatibili con Windows

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 di gss_nt_service_name e il nome completo dell'entità servizio, ad esempio sample/host.dom.com@REALM, deve essere usato.

Autenticazione

L'autenticazione viene in genere gestita quando viene configurata per la prima volta una connessione tra un client e un server. In questo esempio il client usa SSPI (Security Support Provider Interface ) 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).Get an authentication token to send to the server by using 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 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. Viceversa, 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 sicurezza ai protocolli. In precedenza, le funzioni GSS SignMessage e SealMessage venivano 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 controllato 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.

L'esempio seguente illustra 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). Di seguito è riportato 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.