Compartir a través de


Interoperabilidad de SSPI/Kerberos con GSSAPI

Se debe tener cuidado al usar el proveedor de compatibilidad para seguridad (SSP) de Kerberos si la interoperabilidad con GSSAPI es un requisito. Las siguientes convenciones de código permiten la interoperabilidad con aplicaciones basadas en GSSAPI:

Puede encontrar código de ejemplo en el Kit de desarrollo de software de plataforma (SDK) en Samples\Security\SSPI\GSS. Además, el ejemplo de UNIX equivalente se distribuye en las distribuciones MIT y Heimdal Kerberos, el cliente y el servidor GSS.

Nombres compatibles con Windows

Las funciones de GSSAPI usan un formato de nombre conocido como gss_nt_service_name tal como se especifica en la RFC. Por ejemplo, sample@host.dom.com es un nombre que se puede usar en una aplicación basada en GSSAPI. El sistema operativo Windows no reconoce el formato gss_nt_service_name y se debe usar el nombre de la entidad de seguridad de servicio completo, por ejemplo sample/host.dom.com@REALM.

Autenticación

La autenticación normalmente se controla cuando una conexión se configura por primera vez entre un cliente y un servidor. En este ejemplo, el cliente usa la interfaz del proveedor de compatibilidad para seguridad (SSPI) y el servidor usa GSSAPI.

Para configurar la autenticación en el cliente SSPI

  1. Obtenga las credenciales de salida mediante AcquireCredentialsHandle.
  2. Cree un nombre de servicio con gss_import_name() y obtenga credenciales entrantes mediante gss_acquire_cred.
  3. Obtenga un token de autenticación para enviar al servidor mediante InitializeSecurityContext (Kerberos).
  4. Envíe el token al servidor.

Para configurar la autenticación en el servidor GSSAPI

  1. Analice el mensaje del cliente para extraer el token de seguridad. Use la función gss_accept_sec_context y pase el token como argumento.

  2. Analice el mensaje del servidor para extraer el token de seguridad. Pase este token de seguridad a InitializeSecurityContext (Kerberos).

  3. Envíe un token de respuesta al cliente.

    La función gss_accept_sec_context puede devolver un token que puede devolver al cliente.

  4. Si es necesario continuar, envíe un token de respuesta al servidor; de lo contrario, se ha completado la configuración de la autenticación.

  5. Si es necesario continuar, espere al siguiente token del cliente; de lo contrario, se ha completado la configuración de la autenticación.

Integridad y privacidad de los mensajes

La mayoría de las aplicaciones basadas en GSSAPI usan la función GSS_Wrap para firmar un mensaje antes de enviarlo. Por el contrario, la función GSS_Unwrap comprueba la firma. GSS_Wrap está disponible en la versión 2.0 de la API y ahora se usa ampliamente y se especifica en estándares de Internet que describen el uso de GSSAPI para agregar seguridad a los protocolos. Anteriormente, las funciones SignMessage y SealMessage de GSS se usaban para la integridad y privacidad de los mensajes. GSS_Wrap y GSS_Unwrap se usan tanto para la integridad como para la privacidad con el uso de la privacidad controlada por el valor del argumento "conf_flag".

Si se especifica un protocolo basado en GSSAPI para usar las funciones gss_get_mic y gss_verify_mic, las funciones SSPI correctas serían MakeSignature y VerifySignature. Tenga en cuenta que MakeSignature y VerifySignature no interoperarán con GSS_Wrap cuando conf_flag esté establecido en cero o con GSS_Unwrap. Lo mismo sucede para mezclar EncryptMessage (Kerberos) establecido solo para la firma y gss_verify_mic.

Nota:

No use las funciones MakeSignature o VerifySignature cuando se llame a GSS_Wrap y GSS_Unwrap.

 

El SSPI equivalente a GSS_Wrap es EncryptMessage (Kerberos) para la integridad y la privacidad.

En el ejemplo siguiente se muestra el uso de EncryptMessage (Kerberos) para firmar los datos que GSS_Unwrap comprobará.

En el cliente 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.

En el servidor 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.

El SSPI equivalente a GSS_Unwrap es DecryptMessage (Kerberos). Este es un ejemplo que muestra cómo usar DecryptMessage (Kerberos) para descifrar los datos cifrados por GSS_Wrap.

En el servidor 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.

En el cliente 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.