Adam's patch for the VeNCrypt security type reminded me that I still hadn't written up the SASL security type. So here it is...
Regards, Daniel Index: rfbproto.rst =================================================================== --- rfbproto.rst (revision 4086) +++ rfbproto.rst (working copy) @@ -603,6 +603,346 @@ Note that the `ServerInit`_ message is extended when the Tight security type has been activated. +SASL security type +------------------ + +The SASL security type provides a mapping of RFC 2222 into the RFB protocol. +It design allows for arbitrary pluggable authentication and session encryption +capabilities, without further changes being required to either the RFB protocol +or client/server implementations. + +The author recommends that an SSF layer (session encryption) always be requested +during negotiation unless it is known that the RFB connection is secured by a +prior authentication exchange (see TLS & VeNCrypt security types) or externally +via a independent technology (eg stunnel or SSH). + +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. There are many libraries implementing +the RFC, two common open source implementations are Cyrus-SASL and gSASL. The +reference implementations of this security type are QEMU on the server side and +GTK-VNC on the client side, both using Cyrus-SASL. In the case of ambiguities in +this specification, the reference implementation(s) shall define what is compliant. + +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. + +================== =============================== ======================= +No. 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 SASL library function:: + + err = sasl_listmech(vs->saslconn, + NULL, + "", /* Prefix */ + ",", /* Separator */ + "", /* Suffix */ + &mechlist, NULL, NULL); + +The library used for the SASL implementation will usually provide a +means for the administrator to configure exactly what mechanisms are +enabled for an application. The server now waits for the +(`SASL client start message`_) + +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 *mechlist-string* received +from the server. The client shall normally supply a list of +interaction prompts (callbacks) that the library can use to +collect credentials from the user. If interaction prompts are +omitted, this may list the set of mechanisms that can be used. +Client implementations of this spec are encouraged to support +as many of the SASL prompts as practical, to maximise the +interoperability with server supported mechanisms. + +If the ``sasl_client_start`` call is succesfull, the chosen +mechanism name and generated *clientout* data will need to be +sent to the server in a message + +=================== =============================== ======================= +No. of bytes Type Description +=================== =============================== ======================= +4 ``U32`` *mechname-length* +*mechname-length* ``U8`` array *mechname-string* +4 ``U32`` *clientout-length* +*clientout-length* ``U8`` array *clientout-data* +=================== =============================== ======================= + +The distinction between NULL and "" (empty string) in the *clientout-data* +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 must validate that it was one of the mechanisms originally +advertised to the client. + +Given a successfull call to:: + + sasl_client_start(saslconn, + mechlist, + &interact, + &clientout, + &clientoutlen, + &mech); + +When sending the server reply the following logic is compliant with the +wire protocol described above:: + + 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 the `SASL server start message`_ + +SASL server start message +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Upon receiving the `SASL client start message`_, the server must validate +that the chosen mechanism was amongst those originally advertised to +the client. It shall then call the ``sasl_server_start`` API passing +the *clientout-data* from the `SASL client start message`_, 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 back to the client. + +=================== =============================== ======================= +No. of bytes Type Description +=================== =============================== ======================= +4 ``U32`` *serverout-length* +*serverout-length* ``U8`` array *serverout-data* +1 ``U8`` *continue-flag* +=================== =============================== ======================= + +The distinction between NULL and "" (empty string) is critical to preserve. +Thus the *serverout-length* will specify the length of the *serverout-data* +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-flag* 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 described above:: + + 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-flag* is zero, then the server continues with the +`SASL server result check`_ phase, otherwise the server waits for +the `SASL client step message`_. + +SASL client step message +~~~~~~~~~~~~~~~~~~~~~~~~ + +Upon receiving either a `SASL server start message`_, or a +`SASL server step message`_, the client must always call the +``sasl_client_step`` API providing the *serverin-data* received. +The final call to ``sasl_client_step`` is important for the client +to validate that the server was truthful in indicating completion +for mechanisms that perform mutual authentication. + +A compliant client shall be prepared to receive zero or more +`SASL server step message`_, as dictated by the negotiated security +mechanism. + +If the ``sasl_client_step`` call is successful, and the previously +received `SASL server start message`_ or `SASL server step message`_ +had the *continue-flag* value set to 0, the client continues with the +`SASL client result check`_ phase. Otherwise if the *continue-flag* +value was 1, the *clientout-data* from the ``sasl_client_step`` +API call will need to be sent to the server. + +=================== =============================== ======================= +No. of bytes Type Description +=================== =============================== ======================= +4 ``U32`` *clientout-length* +*clientout-length* ``U8`` array *clientout-data* +=================== =============================== ======================= + +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 previous *continue-flag* value of '1', when the following logic for sending +a response to the server 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 `SASL server step message`_ + +SASL server step message +~~~~~~~~~~~~~~~~~~~~~~~~ + +Upon receiving a `SASL client step message`_, the server must +call the ``sasl_server_step`` API passing the *clientout-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 + +=================== =============================== ======================= +No. of bytes Type Description +=================== =============================== ======================= +4 ``U32`` *serverout-length* +*serverout-length* ``U8`` array *serverout-data* +1 ``U8`` *continue-flag* +=================== =============================== ======================= + +The distinction between NULL and "" (empty string) is critical to preserve. Thus +the *serverout-length* will specify the length of the *serverout-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-flag* value shall be 1, otherwise upon successful +completion, or failure of authentication it shall be 0. + +Given a call to:: + + err = sasl_server_step(saslconn, + clientin, + clientinlen, + &serverout, + &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-flag* is zero, then the server continues with the +`SASL server result check`_ phase, otherwise it waits for a further +`SASL client step message`_. + +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 must 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 `SecurityResult`_ message shall be passed through ``sasl_decode``. + +The client now proceeds to wait for the ``SecurityResult`` message, to +determine whether the server considers the negotiation successful. + +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 `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 `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 ``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 `SecurityResult`_ message indicating +successful authentication. + Initialisation Messages +++++++++++++++++++++++ -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
signature.asc
Description: Digital signature
------------------------------------------------------------------------------ This SF.net email is sponsored by Sprint What will you do first with EVO, the first 4G phone? Visit sprint.com/first -- http://p.sf.net/sfu/sprint-com-first
_______________________________________________ tigervnc-rfbproto mailing list tigervnc-rfbproto@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/tigervnc-rfbproto