Having repeatedly said that we should be doing TLS encryption for VNC, I figured I ought to get down & implement it. So, in the spirit of 'release early, release often', here is the very first cut of my patch for QEMU. This isn't suitable for inclusion in CVS yet - I just want to put it out for people to see / experiment with. - The event loop in vl.c does not handle removal of file descriptors in a safe way, so if you remove a filedescriptor during a read event, there is a pretty good chance the event loop will SEGV when checking the write condition. The way I've got around this is that in the qemu_set_fd_handler2() method, instead of removing the IOHandlerRecord object from the list, we simply set the fd to -1. In the main_loop_wait() method, when processing the results from select() we skip over any fd's set to -1, and then have a 2nd loop over the IOHandlerRecord records to finally remove any objects whose fd is set to -1. This lets us safely remove filedescriptors from within callbacks. - The VNC code now negotiates any protocol version out of 3.3, 3.7, 3.8 - There is support for the current 'None' auth type, the standard 'VNC' challenge/response auth type, and finally the VeNCrypt extension which implements a TLS layer with several sub-auth types. Since it can now do any protocol version, and negotiate auth types, we should be able to easily add more auth types if we want compatability with other RFB auth extensions from projects like UltraVNC/TightVNC/etc. - When choosing the VeNCrypt auth type, the client/server then negotiate which sub-auth type they want to use. Then they perform a standard TLS handshake, and if this is successful move on to do the actual authentication. So the actual auth data exchange, and all subsequent RFB protocol traffic is TLS encrypted. - The sub-auth types supported by VeNCrypt are: - Plain - username & password - no TLS at all - TLS Anon + None - TLS anonymous credential exchange, followed by standard 'None' auth type. - TLS Anon + VNC - TLS anonymous credential exchange, followed by standard 'VNC' auth type. - TLS Anon + Plain - TLS anonymous credential exchange, followed by customer 'Plain' username/password auth type. - TLS X509 + None - TLS x509 cert credential exchange, followed by standard 'None' auth type. - TLS X509 + VNC - TLS x509 cert credential exchange, followed by standard 'VNC' auth type. - TLS X509 + Plain - TLS x509 cert credential exchange, followed by customer 'Plain' username/password auth type. - I did not implement any of the 'Plain' sub-auth types above. I may add the TLS encrtyped Plain auth types, but certainly not the clear text version. - The 3 TLS Anon subauth types use the basic diffie-hellman anonymous credential exchange. Since there is no apriori trust relationship, this is subject to MITM attacks, so only marginally more useful than the existing clear text wire format. - The 3 TLS x509 subauth types do a full x509 certificate exchange. This is exactly the same top security model as used in the most recent HTTPS protocol implementationss, so the mode I'd recommend. The server needs to be configured with a CA cert, a CA revocation list (to block revoked clients), and its own server cert & key. The server is currently setup to request a client cert and will verify the cert against the CA cert & CRL. I need to make it possible to turn this client cert verification on/off. If you used TLS X509 + None, then a whitelist of client CNAMEs and client cert verification could be your primary auth. If you use the TLS X509 + VNC / Plain auth schemes, then client cert verification should be optional. So client programs connecting at very least need access to the CA Cert, and if the server does cert verification client programs will need to supply their own certificate too. - Currently I've just hardcode which auth scheme the server will activate in vnc_display_init() method - this is one of the reasons the patch isn't ready to commit to CVS yet. I need to tie in the auth setup into either extra command line args, or extra monitor commands (or probably a mix of both). eg I need to hook up Anthony Ligouri's monitor command for changing the password to this. I also need to figure out to best specify the paths to the server key/key and CA cert/ CRL files. Currently they're hardcoded to be in the files cert.pem, key.pem, ca-cert.pem ca-crl.pem in the current working directory. - I hardcoded the makefile to call pkg-config to determine gnutls compiler/linker flags. This obviously needs to be fixed to be done in the regular configure script. Also all the TLS support needs to be #ifdef HAVE_TLS so that people can still build QEMU without gnutls if desired. - The separately attached d3des.h, d3des.c files are the standard DES implementation shared across every single VNC client / server impl out there. I've just included them 'as-is' with no change. - If configured to use the None, or VNC auth types, any of the standard VNC viewer programs will connect and if neccessary do the challenge/response authentication just fine. If the TLS VeNCrypt authentication type is activated, then you will obviously need a client program which supports this - the VeNCrypt project on sourceforge supplies a vncviewer implementing this scheme. I am also working with Anthony Ligouri to extend his awesome GTK VNC widget to support all the different authentication types. This widget will provide a very easy way for people who want to build GUI frontends around QEMU to drop in secure console support. I intend to integrate it in virt-manager for example. Regards, Dan. -- |=- Red Hat, Engineering, Emerging Technologies, Boston. +1 978 392 2496 -=| |=- Perl modules: http://search.cpan.org/~danberr/ -=| |=- Projects: http://freshmeat.net/~danielpb/ -=| |=- GnuPG: 7D3B9505 F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 -=|