[Development] Implement VeNCrypt security type on server side. Currently only
TLSNone and TLSVnc VeNCrypt subtypes are implemented.


git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4045 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/common/rfb/Makefile.am b/common/rfb/Makefile.am
index 138fec8..ee797a8 100644
--- a/common/rfb/Makefile.am
+++ b/common/rfb/Makefile.am
@@ -15,9 +15,10 @@
 	ScaledPixelBuffer.h ScaleFilters.h SConnection.h ScreenSet.h \
 	screenTypes.h SDesktop.h ServerCore.h SMsgHandler.h \
 	SMsgReader.h SMsgReaderV3.h SMsgWriter.h SMsgWriterV3.h \
-	Security.h SSecurity.h SSecurityNone.h \
-	SSecurityVncAuth.h Threading.h tightDecode.h TightDecoder.h \
-	tightEncode.h TightEncoder.h TightPalette.h Timer.h \
+	Security.h SSecurity.h SSecurityNone.h SSecurityPlain.h \
+	SSecurityStack.h SSecurityTLS.h SSecurityTLSBase.h SSecurityVeNCrypt.h \
+	SSecurityVncAuth.h Threading.h tightDecode.h \
+	TightDecoder.h tightEncode.h TightEncoder.h TightPalette.h Timer.h \
 	TransImageGetter.h transInitTempl.h transTempl.h TrueColourMap.h \
 	UpdateTracker.h UserPasswdGetter.h util.h VNCSConnectionST.h \
 	VNCServer.h VNCServerST.h zrleDecode.h ZRLEDecoder.h zrleEncode.h \
@@ -34,15 +35,17 @@
 	RREEncoder.cxx RREDecoder.cxx RawDecoder.cxx RawEncoder.cxx \
 	Region.cxx SConnection.cxx SMsgHandler.cxx \
 	SMsgReader.cxx SMsgReaderV3.cxx SMsgWriter.cxx SMsgWriterV3.cxx \
-	ServerCore.cxx Security.cxx SSecurityVncAuth.cxx \
+	ServerCore.cxx Security.cxx SSecurityPlain.cxx SSecurityStack.cxx \
+	SSecurityTLS.cxx SSecurityTLSBase.cxx SSecurityVeNCrypt.cxx \
+	SSecurityVncAuth.cxx \
 	ScaledPixelBuffer.cxx ScaleFilters.cxx Timer.cxx TightDecoder.cxx \
 	TightEncoder.cxx TightPalette.cxx TransImageGetter.cxx \
 	UpdateTracker.cxx VNCSConnectionST.cxx \
 	VNCServerST.cxx ZRLEEncoder.cxx ZRLEDecoder.cxx encodings.cxx \
 	util.cxx
 
-librfb_la_CPPFLAGS = -I$(top_srcdir)/common -I$(top_srcdir)/win
-librfb_la_LIBADD =
+librfb_la_CPPFLAGS = -I$(top_srcdir)/common -I$(top_srcdir)/win @GNUTLS_CFLAGS@
+librfb_la_LIBADD = @GNUTLS_LIBS@
 
 if INCLUDED_JPEG
 librfb_la_CPPFLAGS += -I$(top_srcdir)/common/jpeg -I$(top_builddir)/common/jpeg
diff --git a/common/rfb/SSecurityPlain.cxx b/common/rfb/SSecurityPlain.cxx
new file mode 100644
index 0000000..d1f9264
--- /dev/null
+++ b/common/rfb/SSecurityPlain.cxx
@@ -0,0 +1,93 @@
+/* Copyright (C) 2005 Martin Koegler

+ * Copyright (C) 2006 OCCAM Financial Technology

+ * 

+ * This is free software; you can redistribute it and/or modify

+ * it under the terms of the GNU General Public License as published by

+ * the Free Software Foundation; either version 2 of the License, or

+ * (at your option) any later version.

+ * 

+ * This software is distributed in the hope that it will be useful,

+ * but WITHOUT ANY WARRANTY; without even the implied warranty of

+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

+ * GNU General Public License for more details.

+ * 

+ * You should have received a copy of the GNU General Public License

+ * along with this software; if not, write to the Free Software

+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,

+ * USA.

+ */

+

+#include <rfb/SSecurityPlain.h>

+#include <rfb/SConnection.h>

+#include <rfb/Exception.h>

+#include <rdr/InStream.h>

+

+using namespace rfb;

+

+StringParameter PasswordValidator::plainUsers

+("PlainUsers",

+ "Users permitted to access via Plain security type (including TLSPlain, X509Plain etc.)",

+ "");

+

+bool PasswordValidator::validUser(const char* username)

+{

+  CharArray users(strDup(plainUsers.getValueStr())), user;

+  while (users.buf) {

+    strSplit(users.buf, ',', &user.buf, &users.buf);

+#ifdef WIN32

+    if(0==stricmp(user.buf, "*"))

+	  return true;

+    if(0==stricmp(user.buf, username))

+	  return true;

+#else

+    if(!strcmp (user.buf, "*"))

+	  return true;

+    if(!strcmp (user.buf, username))

+	  return true;

+#endif

+  }

+  return false;

+}

+

+SSecurityPlain::SSecurityPlain(PasswordValidator* _valid)

+{

+  valid=_valid;

+  state=0;

+}

+

+bool SSecurityPlain::processMsg(SConnection* sc)

+{

+  rdr::InStream* is = sc->getInStream();

+  char* pw;

+  char *uname;

+  CharArray password;

+

+  if(state==0)

+  {

+    if(!is->checkNoWait(8))

+      return false;

+    ulen=is->readU32();

+    plen=is->readU32();

+    state=1;

+  }

+  if(state==1)

+  {

+    if(is->checkNoWait(ulen+plen+2))

+      return false;

+    state=2;

+    pw=new char[plen+1];

+    uname=new char[ulen+1];

+    username.replaceBuf(uname);

+    password.replaceBuf(pw);

+    is->readBytes(uname,ulen);

+    is->readBytes(pw,plen);

+    pw[plen]=0;

+    uname[ulen]=0;

+    plen=0;

+    if(!valid->validate(sc,uname,pw))

+	  throw AuthFailureException("invalid password or username");

+    return true;

+  }

+  return true;

+}

+

diff --git a/common/rfb/SSecurityPlain.h b/common/rfb/SSecurityPlain.h
new file mode 100644
index 0000000..610ef5b
--- /dev/null
+++ b/common/rfb/SSecurityPlain.h
@@ -0,0 +1,56 @@
+/* Copyright (C) 2005 Martin Koegler

+ * Copyright (C) 2006 OCCAM Financial Technology

+ * Copyright (C) 2010 TigerVNC Team

+ * 

+ * This is free software; you can redistribute it and/or modify

+ * it under the terms of the GNU General Public License as published by

+ * the Free Software Foundation; either version 2 of the License, or

+ * (at your option) any later version.

+ * 

+ * This software is distributed in the hope that it will be useful,

+ * but WITHOUT ANY WARRANTY; without even the implied warranty of

+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

+ * GNU General Public License for more details.

+ * 

+ * You should have received a copy of the GNU General Public License

+ * along with this software; if not, write to the Free Software

+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,

+ * USA.

+ */

+#ifndef __RFB_SSECURITYPLAIN_H__

+#define __RFB_SSECURITYPLAIN_H__

+

+#include <rfb/SConnection.h>

+#include <rfb/SSecurity.h>

+#include <rfb/SSecurityVeNCrypt.h>

+#include <rfb/util.h>

+#include <rfb/Configuration.h>

+

+namespace rfb {

+

+  class PasswordValidator {

+  public:

+    // validate username / password combination

+	bool validate(SConnection* sc, const char *username, const char *password) { return validUser(username) ? validateInternal(sc, username, password) : false; };

+	static StringParameter plainUsers;

+  protected:

+    virtual bool validateInternal(SConnection* sc, const char *username, const char *password)=0;

+	static bool validUser(const char* username);

+  };

+

+  class SSecurityPlain : public SSecurity {

+  public:

+    SSecurityPlain(PasswordValidator* valid);

+    virtual bool processMsg(SConnection* sc);

+    virtual int getType() const {return secTypePlain;};

+    virtual const char* getUserName() const { return username.buf; }

+

+  private:

+    PasswordValidator* valid;

+    unsigned int ulen,plen,state;

+    CharArray username;

+  };

+

+}

+#endif

+

diff --git a/common/rfb/SSecurityStack.cxx b/common/rfb/SSecurityStack.cxx
new file mode 100644
index 0000000..9ddc9f2
--- /dev/null
+++ b/common/rfb/SSecurityStack.cxx
@@ -0,0 +1,67 @@
+/* Copyright (C) 2005 Martin Koegler
+ * 
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
+ * USA.
+ */
+
+#include <rfb/SSecurityStack.h>
+
+using namespace rfb;
+
+SSecurityStack::SSecurityStack(int Type, SSecurity* s0, SSecurity* s1)
+  :state(0), state0(s0), state1(s1), type(Type) {}
+
+SSecurityStack::~SSecurityStack()
+{
+  if (state0)
+    delete state0;
+  if (state1)
+    delete state1;
+}
+
+bool SSecurityStack::processMsg(SConnection* cc)
+{
+  bool res = true;
+
+  if (state == 0) {
+    if (state0)
+      res = state0->processMsg(cc);
+    if (!res)
+      return res;
+    state++;
+  }
+
+  if (state == 1) {
+    if (state1)
+      res = state1->processMsg(cc);
+    if (!res)
+      return res;
+    state++;
+  }
+
+  return res;
+}
+
+const char* SSecurityStack::getUserName() const
+{
+  const char* c = 0;
+
+  if (state1 && !c)
+    c = state1->getUserName();
+  if (state0 && !c)
+    c = state0->getUserName();
+
+  return c;
+}
diff --git a/common/rfb/SSecurityStack.h b/common/rfb/SSecurityStack.h
new file mode 100644
index 0000000..0630dac
--- /dev/null
+++ b/common/rfb/SSecurityStack.h
@@ -0,0 +1,41 @@
+/* Copyright (C) 2005 Martin Koegler

+ * Copyright (C) 2006 OCCAM Financial Technology

+ * Copyright (C) 2010 TigerVNC Team

+ * 

+ * This is free software; you can redistribute it and/or modify

+ * it under the terms of the GNU General Public License as published by

+ * the Free Software Foundation; either version 2 of the License, or

+ * (at your option) any later version.

+ * 

+ * This software is distributed in the hope that it will be useful,

+ * but WITHOUT ANY WARRANTY; without even the implied warranty of

+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

+ * GNU General Public License for more details.

+ * 

+ * You should have received a copy of the GNU General Public License

+ * along with this software; if not, write to the Free Software

+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,

+ * USA.

+ */

+#ifndef __RFB_SSECURITYSTACK_H__

+#define __RFB_SSECURITYSTACK_H__

+

+#include <rfb/SSecurity.h>

+

+namespace rfb {

+

+  class SSecurityStack : public SSecurity {

+  public:

+    SSecurityStack(int Type, SSecurity* s0 = 0, SSecurity* s1 = 0);

+    ~SSecurityStack();

+    virtual bool processMsg(SConnection* cc);

+    virtual int getType() const { return type; };

+    virtual const char* getUserName() const;

+  protected:

+    short state;

+    SSecurity* state0;

+    SSecurity* state1;

+    int type;

+  };

+}

+#endif

diff --git a/common/rfb/SSecurityTLS.cxx b/common/rfb/SSecurityTLS.cxx
new file mode 100644
index 0000000..f54158e
--- /dev/null
+++ b/common/rfb/SSecurityTLS.cxx
@@ -0,0 +1,82 @@
+/* 
+ * Copyright (C) 2004 Red Hat Inc.
+ * Copyright (C) 2005 Martin Koegler
+ * Copyright (C) 2010 TigerVNC Team
+ *    
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
+ * USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_GNUTLS
+
+#include <rfb/SSecurityTLS.h>
+#include <rfb/Exception.h>
+
+#define DH_BITS 1024
+
+#undef TLS_DEBUG
+
+using namespace rfb;
+
+SSecurityTLS::SSecurityTLS() : dh_params(0), anon_cred(0)
+{
+}
+
+SSecurityTLS::~SSecurityTLS()
+{
+  shutdown();
+  if (dh_params)
+    gnutls_dh_params_deinit(dh_params);
+  if (anon_cred)
+    gnutls_anon_free_server_credentials(anon_cred);
+}
+
+void SSecurityTLS::freeResources()
+{
+  if (dh_params)
+    gnutls_dh_params_deinit(dh_params);
+  dh_params = 0;
+  if (anon_cred)
+    gnutls_anon_free_server_credentials(anon_cred);
+  anon_cred = 0;
+}
+
+void SSecurityTLS::setParams(gnutls_session session)
+{
+  static const int kx_priority[] = {GNUTLS_KX_ANON_DH, 0};
+  gnutls_kx_set_priority(session, kx_priority);
+
+  if (gnutls_anon_allocate_server_credentials(&anon_cred) != GNUTLS_E_SUCCESS)
+    throw AuthFailureException("gnutls_anon_allocate_server_credentials failed");
+
+  if (gnutls_dh_params_init(&dh_params) != GNUTLS_E_SUCCESS)
+    throw AuthFailureException("gnutls_dh_params_init failed");
+
+  if (gnutls_dh_params_generate2(dh_params, DH_BITS) != GNUTLS_E_SUCCESS)
+    throw AuthFailureException("gnutls_dh_params_generate2 failed");
+
+  gnutls_anon_set_server_dh_params(anon_cred, dh_params);
+
+  if (gnutls_credentials_set(session, GNUTLS_CRD_ANON, anon_cred) 
+    != GNUTLS_E_SUCCESS)
+    throw AuthFailureException("gnutls_credentials_set failed");
+
+}
+
+#endif /* HAVE_GNUTLS */
diff --git a/common/rfb/SSecurityTLS.h b/common/rfb/SSecurityTLS.h
new file mode 100644
index 0000000..f137f31
--- /dev/null
+++ b/common/rfb/SSecurityTLS.h
@@ -0,0 +1,55 @@
+/* 

+ * Copyright (C) 2004 Red Hat Inc.

+ * Copyright (C) 2005 Martin Koegler

+ * Copyright (C) 2010 TigerVNC Team

+ *    

+ * This is free software; you can redistribute it and/or modify

+ * it under the terms of the GNU General Public License as published by

+ * the Free Software Foundation; either version 2 of the License, or

+ * (at your option) any later version.

+ * 

+ * This software is distributed in the hope that it will be useful,

+ * but WITHOUT ANY WARRANTY; without even the implied warranty of

+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

+ * GNU General Public License for more details.

+ * 

+ * You should have received a copy of the GNU General Public License

+ * along with this software; if not, write to the Free Software

+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,

+ * USA.

+ */

+

+#ifndef __S_SECURITY_TLS_H__

+#define __S_SECURITY_TLS_H__

+

+#ifdef HAVE_CONFIG_H

+#include <config.h>

+#endif

+

+#ifdef HAVE_GNUTLS

+

+#include <rfb/SSecurityTLSBase.h>

+#include <rfb/SSecurityVeNCrypt.h>

+

+namespace rfb {

+

+  class SSecurityTLS : public SSecurityTLSBase {

+  public:

+    SSecurityTLS();

+    virtual ~SSecurityTLS();

+    virtual int getType() const {return secTypeTLSNone;}

+  protected:

+    virtual void freeResources();

+    virtual void setParams(gnutls_session session);

+

+  private:

+    static void initGlobal();

+

+    gnutls_dh_params dh_params;

+    gnutls_anon_server_credentials anon_cred;

+  };

+

+}

+#endif /* HAVE_GNUTLS */

+

+#endif /* __S_SECURITY_TLS_H__ */

diff --git a/common/rfb/SSecurityTLSBase.cxx b/common/rfb/SSecurityTLSBase.cxx
new file mode 100644
index 0000000..2fec9bc
--- /dev/null
+++ b/common/rfb/SSecurityTLSBase.cxx
@@ -0,0 +1,146 @@
+/* 
+ * Copyright (C) 2004 Red Hat Inc.
+ * Copyright (C) 2005 Martin Koegler
+ * Copyright (C) 2010 TigerVNC Team
+ *    
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
+ * USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_GNUTLS
+
+#include <rfb/SSecurityTLSBase.h>
+#include <rfb/SConnection.h>
+#include <rfb/LogWriter.h>
+#include <rfb/Exception.h>
+#include <rdr/TLSInStream.h>
+#include <rdr/TLSOutStream.h>
+
+#define TLS_DEBUG
+
+using namespace rfb;
+
+static LogWriter vlog("TLS");
+
+#ifdef TLS_DEBUG
+static void debug_log(int level, const char* str)
+{
+  vlog.debug(str);
+}
+#endif
+
+void SSecurityTLSBase::initGlobal()
+{
+  static bool globalInitDone = false;
+
+  if (!globalInitDone) {
+    if (gnutls_global_init() != GNUTLS_E_SUCCESS)
+      throw AuthFailureException("gnutls_global_init failed");
+
+#ifdef TLS_DEBUG
+    gnutls_global_set_log_level(10);
+    gnutls_global_set_log_function(debug_log);
+#endif
+
+    globalInitDone = true;
+  }
+}
+
+SSecurityTLSBase::SSecurityTLSBase() : session(0)
+{
+  fis=0;
+  fos=0;
+}
+
+void SSecurityTLSBase::shutdown()
+{
+  if(session)
+    ;//gnutls_bye(session, GNUTLS_SHUT_RDWR);
+}
+
+
+SSecurityTLSBase::~SSecurityTLSBase()
+{
+  if (session) {
+    //gnutls_bye(session, GNUTLS_SHUT_RDWR);
+    gnutls_deinit(session);
+  }
+  if(fis)
+    delete fis;
+  if(fos)
+    delete fos;
+  /* FIXME: should be doing gnutls_global_deinit() at some point */
+}
+
+bool SSecurityTLSBase::processMsg(SConnection *sc)
+{
+  rdr::InStream* is = sc->getInStream();
+  rdr::OutStream* os = sc->getOutStream();
+
+  vlog.debug("Process security message (session %p)", session);
+
+  if (!session) {
+    initGlobal();
+
+    if (gnutls_init(&session, GNUTLS_SERVER) != GNUTLS_E_SUCCESS)
+      throw AuthFailureException("gnutls_init failed");
+
+    if (gnutls_set_default_priority(session) != GNUTLS_E_SUCCESS)
+      throw AuthFailureException("gnutls_set_default_priority failed");
+
+    try {
+      setParams(session);
+    }
+    catch(...) {
+      os->writeU8(0);
+      throw;
+    }
+
+    gnutls_transport_set_pull_function(session,rdr::gnutls_InStream_pull);
+    gnutls_transport_set_push_function(session,rdr::gnutls_OutStream_push);
+    gnutls_transport_set_ptr2(session,
+			      (gnutls_transport_ptr)is,
+			      (gnutls_transport_ptr)os);
+    os->writeU8(1);
+    os->flush();
+  }
+
+  int err;
+  if ((err = gnutls_handshake(session)) != GNUTLS_E_SUCCESS) {
+    if (!gnutls_error_is_fatal(err)) {
+      vlog.debug("Deferring completion of TLS handshake: %s", gnutls_strerror(err));
+      return false;
+    }
+    vlog.error("TLS Handshake failed: %s", gnutls_strerror (err));
+    gnutls_bye(session, GNUTLS_SHUT_RDWR);
+    freeResources();
+    gnutls_deinit(session);
+    session = 0;
+    throw AuthFailureException("TLS Handshake failed");
+  }
+
+  vlog.debug("Handshake completed");
+
+  sc->setStreams(fis=new rdr::TLSInStream(is,session),
+		 fos=new rdr::TLSOutStream(os,session));
+
+  return true;
+}
+
+#endif /* HAVE_GNUTLS */
diff --git a/common/rfb/SSecurityTLSBase.h b/common/rfb/SSecurityTLSBase.h
new file mode 100644
index 0000000..4daad21
--- /dev/null
+++ b/common/rfb/SSecurityTLSBase.h
@@ -0,0 +1,62 @@
+/* 
+ * Copyright (C) 2004 Red Hat Inc.
+ * Copyright (C) 2005 Martin Koegler
+ * Copyright (C) 2010 TigerVNC Team
+ *    
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
+ * USA.
+ */
+
+#ifndef __S_SECURITY_TLSBASE_H__
+#define __S_SECURITY_TLSBASE_H__
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_GNUTLS
+
+#include <rfb/SSecurity.h>
+#include <rdr/InStream.h>
+#include <rdr/OutStream.h>
+#include <gnutls/gnutls.h>
+
+namespace rfb {
+
+  class SSecurityTLSBase : public SSecurity {
+  public:
+    SSecurityTLSBase();
+    virtual ~SSecurityTLSBase();
+    virtual bool processMsg(SConnection* sc);
+    virtual const char* getUserName() const {return 0;}
+
+  protected:
+    void shutdown();
+    virtual void freeResources()=0;
+    virtual void setParams(gnutls_session session)=0;
+
+  private:
+    static void initGlobal();
+
+    gnutls_session session;
+    rdr::InStream* fis;
+    rdr::OutStream* fos;
+  };
+
+}
+
+#endif /* HAVE_GNUTLS */
+
+#endif
diff --git a/common/rfb/SSecurityVeNCrypt.cxx b/common/rfb/SSecurityVeNCrypt.cxx
new file mode 100644
index 0000000..fc83148
--- /dev/null
+++ b/common/rfb/SSecurityVeNCrypt.cxx
@@ -0,0 +1,282 @@
+/*

+ * Copyright (C) 2005-2006 Martin Koegler

+ * Copyright (C) 2006 OCCAM Financial Technology

+ * Copyright (C) 2010 TigerVNC Team

+ * 

+ * This is free software; you can redistribute it and/or modify

+ * it under the terms of the GNU General Public License as published by

+ * the Free Software Foundation; either version 2 of the License, or

+ * (at your option) any later version.

+ * 

+ * This software is distributed in the hope that it will be useful,

+ * but WITHOUT ANY WARRANTY; without even the implied warranty of

+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

+ * GNU General Public License for more details.

+ * 

+ * You should have received a copy of the GNU General Public License

+ * along with this software; if not, write to the Free Software

+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,

+ * USA.

+ */

+/*

+ * SSecurityVeNCrypt

+ */

+

+#ifdef HAVE_CONFIG_H

+#include <config.h>

+#endif

+

+#include <rfb/SSecurityVeNCrypt.h>

+#include <rfb/Exception.h>

+#include <rfb/LogWriter.h>

+#include <rdr/InStream.h>

+#include <rdr/OutStream.h>

+#include <rfb/SSecurityVncAuth.h>

+#include <rfb/SSecurityTLS.h>

+

+using namespace rfb;

+using namespace rdr;

+using namespace std;

+

+static LogWriter vlog("SVeNCrypt");

+

+StringParameter SSecurityVeNCrypt::X509_CertFile

+("x509cert",

+ "specifies path to the x509 certificate in PEM format",

+ "", ConfServer);

+

+StringParameter SSecurityVeNCrypt::X509_KeyFile

+("x509key",

+ "specifies path to the key of the x509 certificate in PEM format",

+ "", ConfServer);

+

+StringParameter SSecurityVeNCrypt::secTypesStr

+("VeNCryptTypes",

+ "Specify which security scheme to use for VeNCrypt connections (TLSNone, "

+ "TLSVnc, TLSPlain, X509None, X509Vnc, X509Plain)",

+ "TLSVnc,TLSPlain,X509Vnc,X509Plain", ConfServer);

+

+SSecurityVeNCrypt::SSecurityVeNCrypt(void)

+{

+  ssecurityStack = NULL;

+  haveSentVersion = false;

+  haveRecvdMajorVersion = false;

+  haveRecvdMinorVersion = false;

+  majorVersion = 0;

+  minorVersion = 0;

+  haveSentTypes = false;

+  haveChosenType = false;

+  chosenType = secTypeVeNCrypt;

+  numTypes = 0;

+  subTypes = NULL;

+}

+

+SSecurityVeNCrypt::~SSecurityVeNCrypt()

+{

+  if (subTypes) {

+    delete [] subTypes;

+    subTypes = NULL;

+  }

+}

+

+bool SSecurityVeNCrypt::processMsg(SConnection* sc)

+{

+  rdr::InStream* is = sc->getInStream();

+  rdr::OutStream* os = sc->getOutStream();

+  rdr::U8 i;

+

+  /* VeNCrypt initialization */

+

+  /* Send the highest version we can support */

+  if (!haveSentVersion) {

+    os->writeU8(0);

+    os->writeU8(2);

+    haveSentVersion = true;

+    os->flush();

+

+    return false;

+  }

+

+  /* Receive back highest version that client can support (up to and including ours) */

+  if (!haveRecvdMajorVersion) {

+    majorVersion = is->readU8();

+    haveRecvdMajorVersion = true;

+

+    return false;

+  }

+

+  if (!haveRecvdMinorVersion) {

+    minorVersion = is->readU8();

+    haveRecvdMinorVersion = true;

+

+    /* WORD value with major version in upper 8 bits and minor version in lower 8 bits */

+    U16 Version = (((U16)majorVersion) << 8) | ((U16)minorVersion);

+

+    switch (Version) {

+    case 0x0000: /* 0.0 - The client cannot support us! */

+    case 0x0001: /* 0.1 Legacy VeNCrypt, not supported */

+      os->writeU8(0xFF); /* This is not OK */

+      os->flush();

+      throw AuthFailureException("The client cannot support the server's "

+				 "VeNCrypt version");

+

+    case 0x0002: /* 0.2 */

+      os->writeU8(0); /* OK */

+      break;

+

+    default:

+      os->writeU8(0xFF); /* Not OK */

+      os->flush();

+      throw AuthFailureException("The client returned an unsupported VeNCrypt version");

+    }

+  }

+

+  /*

+   * send number of supported VeNCrypt authentication types (U8) followed

+   * by authentication types (U32s)

+   */

+  if (!haveSentTypes) {

+    list<U32> listSubTypes;

+    SSecurityVeNCrypt::getSecTypes(&listSubTypes);

+

+    numTypes = listSubTypes.size();

+    subTypes = new U32[numTypes];

+

+    for (i = 0; i < numTypes; i++) {

+      subTypes[i] = listSubTypes.front();

+      listSubTypes.pop_front();

+    }

+

+    if (numTypes) { 

+      os->writeU8(numTypes);

+      for (i = 0; i < numTypes; i++)

+	os->writeU32(subTypes[i]);

+

+      os->flush(); 

+      haveSentTypes = true;

+      return false;

+    } else

+      throw AuthFailureException("There are no VeNCrypt sub-types to send to the client");

+  }

+

+  /* get type back from client (must be one of the ones we sent) */

+  if (!haveChosenType) {

+    is->check(4);

+    chosenType = is->readU32();

+

+    for (i = 0; i < numTypes; i++) {

+      if (chosenType == subTypes[i]) {

+	haveChosenType = true;

+	break;

+      }

+    }

+

+    if (!haveChosenType)

+      chosenType = secTypeInvalid;

+

+    /* Set up the stack according to the chosen type */

+    switch(chosenType) {

+    case secTypeTLSNone:

+    case secTypeTLSVnc:

+    case secTypeTLSPlain:

+    case secTypeX509None:

+    case secTypeX509Vnc:

+    case secTypeX509Plain:

+      ssecurityStack = SSecurityVeNCrypt::getSSecurityStack(chosenType);

+	break;  

+    case secTypeInvalid:

+    case secTypeVeNCrypt: /* This would cause looping */

+    default:

+      throw AuthFailureException("No valid VeNCrypt sub-type");

+    }

+

+  }

+

+  /* continue processing the messages */

+  return ssecurityStack->processMsg(sc);

+}

+

+SSecurityStack* SSecurityVeNCrypt::getSSecurityStack(int secType)

+{

+  switch (secType) {

+  case secTypeTLSNone:

+    return new SSecurityStack(secTypeTLSNone, new SSecurityTLS());

+  case secTypeTLSVnc:

+    return new SSecurityStack(secTypeTLSVnc, new SSecurityTLS(), new SSecurityVncAuth());

+#if 0

+  /* Following types are not implemented, yet */

+  case secTypeTLSPlain:

+  case secTypeX509None:

+  case secTypeX509Vnc:

+  case secTypeX509Plain:

+#endif

+  default:

+    throw Exception("Bug in the SSecurityVeNCrypt::getSSecurityStack");

+  }

+}

+

+void SSecurityVeNCrypt::getSecTypes(list<U32>* secTypes)

+{

+  CharArray types;

+

+  types.buf = SSecurityVeNCrypt::secTypesStr.getData();

+  list<U32> configured = SSecurityVeNCrypt::parseSecTypes(types.buf);

+  list<U32>::iterator i;

+  for (i = configured.begin(); i != configured.end(); i++)

+    secTypes->push_back(*i);

+}

+

+U32 SSecurityVeNCrypt::secTypeNum(const char *name)

+{

+  if (strcasecmp(name, "TLSNone") == 0)

+    return secTypeTLSNone;

+  if (strcasecmp(name, "TLSVnc") == 0)

+    return secTypeTLSVnc;

+  if (strcasecmp(name, "TLSPlain") == 0)

+    return secTypeTLSPlain;

+  if (strcasecmp(name, "X509None") == 0)

+    return secTypeX509None;

+  if (strcasecmp(name, "X509Vnc") == 0)

+    return secTypeX509Vnc;

+  if (strcasecmp(name, "X509Plain") == 0)

+    return secTypeX509Plain;

+

+  return secTypeInvalid;

+}

+

+char* SSecurityVeNCrypt::secTypeName(U32 num)

+{

+  switch (num) {

+  case secTypePlain:

+    return "Plain";

+  case secTypeTLSNone:

+    return "TLSNone";

+  case secTypeTLSVnc:

+    return "TLSVnc";

+  case secTypeTLSPlain:

+    return "TLSPlain";

+  case secTypeX509None:

+    return "X509None";

+  case secTypeX509Vnc:

+    return "X509Vnc";

+  case secTypeX509Plain:

+    return "X509Plain";

+  default:

+    return "[unknown secType]";

+  }

+}

+

+list<U32> SSecurityVeNCrypt::parseSecTypes(const char *secTypes)

+{

+  list<U32> result;

+  CharArray types(strDup(secTypes)), type;

+  while (types.buf) {

+    strSplit(types.buf, ',', &type.buf, &types.buf);

+    int typeNum = SSecurityVeNCrypt::secTypeNum(type.buf);

+    if (typeNum != secTypeInvalid)

+      result.push_back(typeNum);

+  }

+  return result;

+}

+

+

diff --git a/common/rfb/SSecurityVeNCrypt.h b/common/rfb/SSecurityVeNCrypt.h
new file mode 100644
index 0000000..3d1e0e0
--- /dev/null
+++ b/common/rfb/SSecurityVeNCrypt.h
@@ -0,0 +1,68 @@
+/*

+ * Copyright (C) 2005-2006 Martin Koegler

+ * Copyright (C) 2006 OCCAM Financial Technology

+ * Copyright (C) 2010 TigerVNC Team

+ * 

+ * This is free software; you can redistribute it and/or modify

+ * it under the terms of the GNU General Public License as published by

+ * the Free Software Foundation; either version 2 of the License, or

+ * (at your option) any later version.

+ * 

+ * This software is distributed in the hope that it will be useful,

+ * but WITHOUT ANY WARRANTY; without even the implied warranty of

+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

+ * GNU General Public License for more details.

+ * 

+ * You should have received a copy of the GNU General Public License

+ * along with this software; if not, write to the Free Software

+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,

+ * USA.

+ */

+//

+// SSecurityVeNCrypt

+//

+

+#ifndef __SSECURITYVENCRYPT_H__

+#define __SSECURITYVENCRYPT_H__

+

+#include <rfb/SSecurityStack.h>

+#include <rfb/SConnection.h>

+

+namespace rfb {

+

+  /* VeNCrypt subtypes */

+  const int secTypePlain	= 256;

+  const int secTypeTLSNone	= 257;

+  const int secTypeTLSVnc	= 258;

+  const int secTypeTLSPlain	= 259;

+  const int secTypeX509None	= 260;

+  const int secTypeX509Vnc	= 261;

+  const int secTypeX509Plain	= 262;

+

+  class SSecurityVeNCrypt : public SSecurity {

+  public:

+    SSecurityVeNCrypt(void);

+    ~SSecurityVeNCrypt();

+    virtual bool processMsg(SConnection* sc);// { return true; }

+    virtual int getType() const { return secTypeVeNCrypt; }

+    virtual const char* getUserName() const { return NULL; }

+

+    static StringParameter X509_CertFile, X509_KeyFile, secTypesStr;

+

+  protected:

+    static SSecurityStack* getSSecurityStack(int secType);

+

+    /* XXX Derive Security class and merge those functions appropriately ? */

+    static void getSecTypes(std::list<rdr::U32>* secTypes);

+    static rdr::U32 secTypeNum(const char *name);

+    static char* secTypeName(rdr::U32 num);

+    static std::list<rdr::U32> parseSecTypes(const char *types);

+

+    SSecurityStack *ssecurityStack;

+    bool haveSentVersion, haveRecvdMajorVersion, haveRecvdMinorVersion;

+    bool haveSentTypes, haveChosenType;

+    rdr::U8 majorVersion, minorVersion, numTypes;

+    rdr::U32 *subTypes, chosenType;

+  };

+}

+#endif

diff --git a/common/rfb/Security.cxx b/common/rfb/Security.cxx
index fac2d4b..589eaa6 100644
--- a/common/rfb/Security.cxx
+++ b/common/rfb/Security.cxx
@@ -28,6 +28,7 @@
 #include <rfb/Security.h>
 #include <rfb/SSecurityNone.h>
 #include <rfb/SSecurityVncAuth.h>
+#include <rfb/SSecurityVeNCrypt.h>
 #include <rfb/util.h>
 
 using namespace rdr;
@@ -80,6 +81,7 @@
   switch (secType) {
   case secTypeNone: return new SSecurityNone();
   case secTypeVncAuth: return new SSecurityVncAuth();
+  case secTypeVeNCrypt: return new SSecurityVeNCrypt();
   }
 
 bail:
@@ -110,7 +112,8 @@
   if (strcasecmp(name, "RA2") == 0)        return secTypeRA2;
   if (strcasecmp(name, "RA2ne") == 0)      return secTypeRA2ne;
   if (strcasecmp(name, "SSPI") == 0)       return secTypeSSPI;
-  if (strcasecmp(name, "SSPIne") == 0)       return secTypeSSPIne;
+  if (strcasecmp(name, "SSPIne") == 0)     return secTypeSSPIne;
+  if (strcasecmp(name, "VeNCrypt") == 0)   return secTypeVeNCrypt;
   return secTypeInvalid;
 }
 
@@ -124,6 +127,7 @@
   case secTypeRA2ne:      return "RA2ne";
   case secTypeSSPI:       return "SSPI";
   case secTypeSSPIne:     return "SSPIne";
+  case secTypeVeNCrypt:   return "VeNCrypt";
   default:                return "[unknown secType]";
   }
 }
diff --git a/common/rfb/Security.h b/common/rfb/Security.h
index edbcd44..3231f1f 100644
--- a/common/rfb/Security.h
+++ b/common/rfb/Security.h
@@ -44,6 +44,7 @@
   const rdr::U8 secTypeTight   = 16;
   const rdr::U8 secTypeUltra   = 17;
   const rdr::U8 secTypeTLS     = 18;
+  const rdr::U8 secTypeVeNCrypt= 19;
 
   // result types