I have defined a mapping of the SASL authentication scheme into the RFB authentication protocol. Please could you allocate an official security type code for use with this auth scheme, under the name "SASL".
There are a number of reasons why it is desirable to support SASL in the RFB protocol - It is an official internet RFC with API support across all OS platforms, providing for both authentication and session data encryption. - The SASL protocol is independant of authentication mechanism allowing new mechanisms to be plugged in without any application code changes - The DIGEST-MD5 SASL mechanism will provide a simple username+password based alternative to the existing "VNC" security type, but with stronger security, and session data encryption. - The GSSAPI SASL mechanism will provider integration with Kerberos for Single-Sign-On capabilities, again also having session data encryption There are a variety of other plugins that will be useful to many people such as passwd auth against a SQL database, auth against LDAP, one-time passwords, and NTLM. I intend to implement client side support for this "SASL" security type in the GTK-VNC client, the GNOME VINO server (remote desktop), and the QEMU built-in VNC server (OS virtualization). My current security type protocol spec documentation follows, though I may well refine details of it as I finish the implementations. I currently have GTK-VNC and QEMU operational, without session encryption. NB, the protocol description that follows, just picks security code 100 out of the hat. This will obviously be updated to reflect the actual security type code officially allocated. Daniel 6.2.100 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. 6.2.100.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, "", /* Prefix */ ",", /* Separator */ "", /* Suffix */ &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.100.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 successfull, 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.100.3 server start" message 6.2.100.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 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_start" method indicates that further steps in the negotiation process are required, the "continue" value shall be 1, otherwise upon succesful completion, or failure of authentiction 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.100.7 server security check". Otherwise the protocol continues with "6.2.100.4 SASL client step" message. 6.2.100.4 SASL client step message ---------------------------------- Upon receiving a "6.2.100.3 server start" message, or a "6.2.100.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 successfull, and the previously received "6.2.100.3 sever start' or "6.2.100.5 server step" message had the "continue" value set to 0, the client protocol continues to 6.2.100.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.100.5 server step" message 6.2.100.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 succesful completion, or failure of authentiction it shall be 0. If "continue" is zero, then the protocol continues with "6.2.100.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.100.7 server security check". Otherwise the protocol continues with another "6.2.100.4 SASL client step" message. 6.2.100.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.100.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 fialed 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 succesfull authentication. -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| _______________________________________________ VNC-List mailing list VNC-List@realvnc.com To remove yourself from the list visit: http://www.realvnc.com/mailman/listinfo/vnc-list