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
- Ottenere le credenziali in uscita usando AcquireCredentialsHandle.
- Creare un nome del servizio con gss_import_name() e ottenere le credenziali in ingresso usando gss_acquire_cred.
- 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).
- Inviare il token al server.
Per configurare l'autenticazione nel server GSSAPI
Analizzare il messaggio dal client per estrarre il token di sicurezza. Usare la funzione gss_accept_sec_context , passando il token come argomento.
Analizzare il messaggio dal server per estrarre il token di sicurezza. Passare questo token di sicurezza a InitializeSecurityContext (Kerberos).
Inviare un token di risposta al client.
La funzione gss_accept_sec_context può restituire un token che è possibile inviare al client.
Se è necessario continuare, inviare un token di risposta al server; in caso contrario, la configurazione dell'autenticazione è stata completata.
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.