diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/rfb/Makefile.am | 15 | ||||
-rw-r--r-- | common/rfb/SSecurityPlain.cxx | 93 | ||||
-rw-r--r-- | common/rfb/SSecurityPlain.h | 56 | ||||
-rw-r--r-- | common/rfb/SSecurityStack.cxx | 67 | ||||
-rw-r--r-- | common/rfb/SSecurityStack.h | 41 | ||||
-rw-r--r-- | common/rfb/SSecurityTLS.cxx | 82 | ||||
-rw-r--r-- | common/rfb/SSecurityTLS.h | 55 | ||||
-rw-r--r-- | common/rfb/SSecurityTLSBase.cxx | 146 | ||||
-rw-r--r-- | common/rfb/SSecurityTLSBase.h | 62 | ||||
-rw-r--r-- | common/rfb/SSecurityVeNCrypt.cxx | 282 | ||||
-rw-r--r-- | common/rfb/SSecurityVeNCrypt.h | 68 | ||||
-rw-r--r-- | common/rfb/Security.cxx | 6 | ||||
-rw-r--r-- | common/rfb/Security.h | 1 |
13 files changed, 967 insertions, 7 deletions
diff --git a/common/rfb/Makefile.am b/common/rfb/Makefile.am index 138fec80..ee797a83 100644 --- a/common/rfb/Makefile.am +++ b/common/rfb/Makefile.am @@ -15,9 +15,10 @@ HDRS = Blacklist.h CapsContainer.h CapsList.h CConnection.h \ 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 @@ librfb_la_SOURCES = $(HDRS) Blacklist.cxx CConnection.cxx CMsgHandler.cxx \ 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 00000000..d1f92646 --- /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 00000000..610ef5bd --- /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 00000000..9ddc9f2f --- /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 00000000..0630dacd --- /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 00000000..f54158e7 --- /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 00000000..f137f31b --- /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 00000000..2fec9bc1 --- /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 00000000..4daad217 --- /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 00000000..fc831482 --- /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 00000000..3d1e0e0a --- /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 fac2d4bd..589eaa66 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 @@ SSecurity* Security::GetSSecurity(U8 secType) switch (secType) { case secTypeNone: return new SSecurityNone(); case secTypeVncAuth: return new SSecurityVncAuth(); + case secTypeVeNCrypt: return new SSecurityVeNCrypt(); } bail: @@ -110,7 +112,8 @@ rdr::U8 rfb::secTypeNum(const char* name) 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 @@ const char* rfb::secTypeName(rdr::U8 num) 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 edbcd444..3231f1f5 100644 --- a/common/rfb/Security.h +++ b/common/rfb/Security.h @@ -44,6 +44,7 @@ namespace rfb { const rdr::U8 secTypeTight = 16; const rdr::U8 secTypeUltra = 17; const rdr::U8 secTypeTLS = 18; + const rdr::U8 secTypeVeNCrypt= 19; // result types |