Interopérabilité SSPI/Kerberos avec GSSAPI

Lors de l’utilisation du fournisseur de support de sécuritéKerberos (SSP), vous devez faire attention si l’interopérabilité avec GSSAPI est requise. Les conventions de code suivantes permettent l’interopérabilité avec les applications GSSAPI :

Vous trouverez un exemple de code dans le Kit de développement logiciel (SDK) de plateforme sous Exemples\Sécurité\SSPI\GSS. En outre, l’exemple UNIX équivalent est distribué dans les distributions Kerberos MIT et Heimdal, le client GSS et le serveur.

noms de Windows-Compatible

Les fonctions GSSAPI utilisent un format de nom appelé gss_nt_service_name comme spécifié dans le 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 gss_nt_service_name et le nom du principal de service complet, 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 configuration d’une 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 les informations d’identificationsortantes à l’aide de AcquireCredentialsHandle.
  2. Créez un nom de service avec gss_import_name() et obtenez les 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 dans le serveur GSSAPI

  1. Analysez le message du client pour extraire le jeton de sécurité. Utilisez la fonction gss_accept_sec_context , en passant le jeton comme argument.

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

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

    La fonction gss_accept_sec_context peut retourner 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. Inversement, 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 la GSSAPI pour ajouter la sécurité aux protocoles. Auparavant, les fonctions SignMessage et SealMessage GSS étaient utilisées pour l’intégrité et laconfidentialité des messages. GSS_Wrap et GSS_Unwrap sont utilisés à des fins d’intégrité et de confidentialité avec l’utilisation de la confidentialité contrôlée par la valeur de l’argument « conf_flag ».

Si un protocole basé sur GSSAPI est spécifié pour utiliser les fonctions gss_get_mic et gss_verify_mic , les fonctions SSPI appropriées sont MakeSignature et VerifySignature. N’oubliez pas que MakeSignature et VerifySignature n’interagissent pas avec GSS_Wrap lorsque conf_flag est défini sur zéro ou avec GSS_Unwrap. Il en va de même pour le mélange de EncryptMessage (Kerberos) défini pour la signature uniquement et gss_verify_mic.

Notes

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

 

L’équivalent SSPI de 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.

L’équivalent SSPI de GSS_Unwrap est DecryptMessage (Kerberos). Voici un exemple qui montre comment utiliser Kerberos (DecryptMessage) pour déchiffrer des 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.