6.2.20 SASL Authentication

SASL authentication is to be used, optionally with a encryption capability for the protocol data to be negotiated between the client and server. The author recommends that an SSF layer always be requested during negotiation unless it is known that the connection is secured by a prior authentication exchange such as TLS / VeNCrypt, or externally via a SSH tunnel.

The SASL negotiation is a multi-step protocol, initiated by the server. The precise number of steps required for the complete negotiation is determined by the SASL mechanism chosen for auth. Compliant implementations must expect an arbitrary number of steps.

The SASL protocol is defined in RFC 2222. Recommended libraries for implementation on either client or server end are Cyrus-SASL and gSASL.

This specification is currently supported by GTK-VNC, and QEMU.

6.2.20.1 SASL server initialization message

The server initializes the SASL authentication process by sending the list of mechanisms it is prepared to accept from the client.

  • # of bytes

    Type

    Description

    4

    u32

    mechlist-length

    mechlist-length

    u8 array

    mechlist-string

The "mechlist-string" is a list of SASL mechanism names, each separated by a comma. The "mechlist-length" is the number of characters in the string. The trailing '\0' is not transmitted on the wire. Some example "mechlist-string" values are

  • "DIGEST-MD5,GSSAPI" "ANONYMOUS,KERBEROS_V4,DIGEST-MD5"

The "mechlist-string" is typically generated on the server by a call to the function:

  • err = sasl_listmech(vs->saslconn,

    • NULL,

      "", ",", "", &mechlist, NULL, NULL);

The library used for the SASL implementation will usually provide a means for the adminsitrator to configure exactly what mechanisms are enabled.

6.2.20.2 SASL client start message

Upon receiving the list of mechanisms allowed by the server, the client may choose a specific mechanism from the list, or allow the SASL library to make the choice.

The client shall call "sasl_client_start" providing either a specific mechanism name, or the full list supported by the server. The client shall normally supply a list of prompts it is prepared to support for collecting credentials from the user.

If the "sasl_client_start" call is succesfull, the returned "clientout" data will need to be sent to the server.

  • # of bytes

    Type

    Description

    4

    u32

    mechname-length

    mechname-length

    u8 array

    mechname-string

    4

    u32

    clientout-length

    clientout-length

    u8 array

    clientout

The distinction between NULL and "" (empty string) is critical to preserve. Thus the "clientout-length" will specify the length of the "clientout" data INCLUDING the trailing '\0', such that the empty string has "clientout-length" equal to 1, while NULL data will be transmitted with "clientout-length" equal to 0.

The "mechname-string" is the mechanism name chosen by the client from the list of advertised mechanisms from the server. The data sent does not include the trailing '\0' character. Upon receiving the chosen "mechname-string" from the client, the server shall validate that it was one of the mechanisms originally advertised to the client.

Given a successfull call

  • sasl_client_start(saslconn,
    • mechlist,

      &interact, &clientout, &clientoutlen, &mech);

When sending the server reply the following logic is compliant with the wire protocol

  • write_u32(strlen(mech)) write_u8(mech, strlen(mech)) if (clientout != NULL) {
    • write_u32(strlen(clientout) + 1) write_u8(clientout, strlen(clientout) + 1)
    } else {
    • write_u32(0)
    }

The client shall now wait for a "6.2.20.3 server start" message

6.2.20.3 SASL server start message

Upon receiving the client start message, the server shall validate that the chosen mechanism was amongst those originally advertised to the client. It shall now call the "sasl_server_start" API passing the "clientin" data received from the client, taking care to preserve the NULL vs "" distinction when de-serializing.

If the "sasl_server_start" call is successful, the returned "serverout" data will need to be sent to the server.

  • # of bytes

    Type

    Description

    4

    u32

    serverout-length

    serverout-length

    u8 array

    serverout

    1

    u8

    continue

The distinction between NULL and "" (empty string) is critical to preserve. Thus the "serverout-length" will specify the length of the "clientout" data INCLUDING the trailing '\0', such that the empty string has "serverout-length" equal to 1, while NULL data will be transmitted with "serverout-length" equal to 0.

If the "sasl_server_start" method indicates that further steps in the negotiation process are required, the "continue" value shall be 1, otherwise upon successful completion, or failure of authentication it shall be 0.

Given a call to

  • err = sasl_server_start(saslconn,
    • mechname,

      &clientin, &clientinlen, &servertout, &serveroutlen);

When sending the server reply the following logic is compliant with the wire protocol

  • if (err == SASL_OK or err == SASL_CONTINUE) {
    • if (serverout != NULL) {
      • write_u32(strlen(serverout) + 1) write_u8(serverout, strlen(serverout) + 1)
      } else {
      • write_u32(0)
      } if (err == SASL_OK)
      • write_u8(0)
      else
      • write_u8(1)
  • } else {
    • write_u8(0) write_u8(0)
    }

If "continue" is zero, then the server protocol continues to "6.2.20.7 server security check". Otherwise the protocol continues with "6.2.20.4 SASL client step" message.

6.2.20.4 SASL client step message

Upon receiving a "6.2.20.3 server start" message, or a "6.2.20.5 server step" message, the client shall call the "sasl_client_step" providing the "serverin" data received.

A compliant client shall be prepared to receive 0 or more "6.2.100.5 server step" messages, as required by the activated security mechanism.

If the "sasl_client_step" call is successful, and the previously received "6.2.20.3 sever start' or "6.2.20.5 server step" message had the "continue" value set to 0, the client protocol continues to 6.2.20.6 client security check". The final call to "sasl_client_step" is important for the client to validate that the server was truthful in indicating that authentication was complete.

If the "continue" value was 1, the "clientout" data from the "sasl_client_step" API call will need to be sent to the server.

  • # of bytes

    Type

    Description

    4

    u32

    clientout-length

    clientout-length

    u8 array

    clientout

The distinction between NULL and "" (empty string) is critical to preserve. Thus the "clientout-length" will specify the length of the "clientout" data INCLUDING the trailing '\0', such that the empty string has "clientout-length" equal to 1, while NULL data will be transmitted with "clientout-length" equal to 0.

Given a successfull call

  • sasl_client_step(saslconn,
    • &serverin, &serverinlen, &clientout, &clientoutlen)

And a continue value of '1', when sending the server reply the following logic is compliant with the wire protocol

  • if (clientout != NULL) {
    • write_u32(strlen(clientout) + 1) write_u8(clientout, strlen(clientout) + 1)
    } else {
    • write_u32(0)
    }

The client shall now wait for a "6.2.20.5 server step" message

6.2.20.5 SASL server step message

Upon receiving the client step message, the shall validate that the chosen mechanism was amongst those originally advertised to the client. It shall then call the "sasl_server_step" API passing the "clientin" data received from the client, taking care to preserve the NULL vs "" distinction when de-serializing.

If the "sasl_server_step" call is successfull, the returned "serverout" data will need to be sent to the server.

  • # of bytes

    Type

    Description

    4

    u32

    serverout-length

    serverout-length

    u8 array

    serverout

    1

    u8

    continue

The distinction between NULL and "" (empty string) is critical to preserve. Thus the "serverout-length" will specify the length of the "clientout" data INCLUDING the trailing '\0', such that the empty string has "serverout-length" equal to 1, while NULL data will be transmitted with "serverout-length" equal to 0.

If the "sasl_server_step" method indicates that further steps in the negotiation process are required, the "continue" value shall be 1, otherwise upon successful completion, or failure of authentication it shall be 0. If "continue" is zero, then the protocol continues with "6.2.20.7 server security check"

Given a call to

  • err = sasl_server_step(saslconn,
    • &clientin, &clientinlen, &servertout, &serveroutlen);

When sending the server reply the following logic is compliant with the wire protocol

  • if (err == SASL_OK or err == SASL_CONTINUE) {
    • if (serverout != NULL) {
      • write_u32(strlen(serverout) + 1) write_u8(serverout, strlen(serverout) + 1)
      } else {
      • write_u32(0)
      } if (err == SASL_OK)
      • write_u8(0)
      else
      • write_u8(1)
  • } else {
    • write_u8(0) write_u8(0)
    }

If "continue" is zero, then the server protocol continues with the "6.2.20.7 server security check". Otherwise the protocol continues with another "6.2.20.4 SASL client step" message.

6.2.20.6 SASL client result check

At this point the client and server have completed the SASL negotiation process. If the client had requested an SSF layer during its initial it should now validate that a suitable SSF layer was negotiated with the server. If the SSF layer is unsuitable it shall drop the connection to the server.

If the SSF layer is enabled, and suitable for the client, all future messages transmitted over the RFB protocol shall be passed through the "sasl_encode" API, and all messages received from the server AFTER the forthcoming "6.1.3 SecurityResult" shall be passed through "sasl_decode".

The client now proceeds to wait for "6.1.3 SecurityResult", to determine whether the server considers the negotiation successful.

6.2.20.7 SASL server result check

At this point the client and server have completed the SASL negotation process.

If the SASL negotiation indicated that the client failed to correctly authenticate, it shall send "6.1.3 SecurityResult" message indicating that the authentication has failed and then drop the connection.

The client and server are now authenticated, but before continuing, if the server had requested an SSF layer during its initial it should now validate that a suitable SSF layer was negotiated with the client. If the SSF layer is unsuitable it shall send a "6.1.3 SecurityResult" message indicating that authentication has failed and then drop the connection to the client.

If the SSF layer is enabled, and suitable for the client, all messages transmitted over the RFB protocol AFTER the "6.1.3 SecurityResult" message shall be passed through the "sasl_encode" API, and all messages received from the client shall be passed through "sasl_decode".

The server proceeds to send the "6.1.3 SecurityResult" message indicating successful authentication.

Projects/gtk-vnc/extensions/SASL (last edited 2013-11-22 20:00:35 by WilliamJonMcCann)