Partager via


Interopérabilité SSPI/Kerberos avec GSSAPI

Soyez vigilent lors de l’utilisation du fournisseur de support de sécurité (SSP) Kerberos si l’interopérabilité avec GSSAPI est requise. Les conventions de code suivantes permettent l’interopérabilité avec les applications basées sur GSSAPI :

Vous trouverez un exemple de code dans le kit de développement logiciel (SDK) de plateforme sous Samples\Security\SSPI\GSS. De plus, l’exemple UNIX équivalent est distribué dans les distributions MIT et Heimdal Kerberos, ainsi que les serveurs et clients GSS.

Noms compatibles avec Windows

Les fonctions GSSAPI utilisent un format de nom appelé gss_nt_service_name comme spécifié dans la RFC. Par exemple, sample@host.dom.com est un nom qui peut être utilisé dans une application basée sur GSSAPI. Le système d’exploitation Windows ne reconnaît pas le format de gss_nt_service_name. Le nom complet de principal du service, par exemple sample/host.dom.com@REALM, doit être utilisé.

Authentification

L’authentification est généralement gérée lors de la première connexion entre un client et un serveur. Dans cet exemple, le client utilise l’interface SSPI (Security Support Provider Interface) et le serveur utilise GSSAPI.

Pour configurer l’authentification dans le client SSPI

  1. Obtenez des informations d’identification sortantes à l’aide d'AcquireCredentialsHandle.
  2. Créez un nom de service avec gss_import_name() et obtenez des informations d’identification entrantes à l’aide de gss_acquire_cred.
  3. Obtenez un jeton d’authentification à envoyer au serveur à l’aide de InitializeSecurityContext (Kerberos).
  4. Envoyez le jeton au serveur.

Pour configurer l’authentification sur le serveur GSSAPI

  1. Analysez le message du client pour extraire le jeton de sécurité. Utilisez la fonction gss_accept_sec_context en transmettant le jeton en tant qu’argument.

  2. Analysez le message du serveur pour extraire le jeton de sécurité. Transmettez ce jeton de sécurité à InitializeSecurityContext (Kerberos).

  3. Envoyez un jeton de réponse au client.

    La fonction gss_accept_sec_context peut renvoyer un jeton que vous pouvez renvoyer au client.

  4. S’il est nécessaire de continuer, envoyez un jeton de réponse au serveur. Sinon, la configuration de l’authentification est terminée.

  5. S’il est nécessaire de continuer, attendez le jeton suivant du client. Sinon, la configuration de l’authentification est terminée.

Intégrité et confidentialité des messages

La plupart des applications basées sur GSSAPI utilisent la fonction GSS_Wrap pour signer un message avant de l’envoyer. À l’inverse, la fonction GSS_Unwrap vérifie la signature. GSS_Wrap est disponible dans la version 2.0 de l’API et est désormais largement utilisé et spécifié dans les normes Internet qui décrivent l’utilisation de GSSAPI pour ajouter une couche de sécurité aux protocoles. Auparavant, les fonctions GSS SignMessage et SealMessage étaient utilisées pour l’intégrité et la confidentialité des messages. GSS_Wrap et GSS_Unwrap sont utilisés pour l’intégrité et la confidentialité, et contrôlent la confidentialité grâce à la valeur de l’argument « conf_flag ».

Si l'utilisation des fonctions gss_get_mic et gss_verify_mic est spécifiée pour un protocole basé sur GSSAPI, les fonctions SSPI correctes sont MakeSignature et VerifySignature. N’oubliez pas que MakeSignature et VerifySignature n’interopéreront pas avec GSS_Wrap lorsque conf_flag est défini sur zéro ou avec GSS_Unwrap. Il en va de même pour combiner EncryptMessage (Kerberos) défini pour la signature uniquement et gss_verify_mic.

Remarque

N’utilisez pas les fonctions MakeSignature ou VerifySignature lorsque GSS_Wrap et GSS_Unwrap sont appelés.

 

Le SSPI équivalent à GSS_Wrap est EncryptMessage (Kerberos) pour l’intégrité et la confidentialité.

L’exemple suivant montre comment utiliser EncryptMessage (Kerberos) pour signer des données qui seront vérifiées par GSS_Unwrap.

Dans le 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.

Dans le serveur 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.

Le SSPI équivalent à GSS_Unwrap est DecryptMessage (Kerberos). Voici un exemple qui montre comment utiliser DecryptMessage (Kerberos) pour déchiffrer les données chiffrées par GSS_Wrap.

Dans le serveur 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.

Dans le 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.