diff options
author | Adam Tkac <atkac@redhat.com> | 2010-04-23 14:14:11 +0000 |
---|---|---|
committer | Adam Tkac <atkac@redhat.com> | 2010-04-23 14:14:11 +0000 |
commit | dfe19cfff8deed3adbf0b4190763bbd243e56d07 (patch) | |
tree | 5003cda4be862ab009368b994f4d27462abc3dcd /common/rfb/SSecurityVeNCrypt.cxx | |
parent | 35e6d4c554e6f9fd9c1446db647fbaf3dbc6c087 (diff) | |
download | tigervnc-dfe19cfff8deed3adbf0b4190763bbd243e56d07.tar.gz tigervnc-dfe19cfff8deed3adbf0b4190763bbd243e56d07.zip |
[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
Diffstat (limited to 'common/rfb/SSecurityVeNCrypt.cxx')
-rw-r--r-- | common/rfb/SSecurityVeNCrypt.cxx | 282 |
1 files changed, 282 insertions, 0 deletions
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;
+}
+
+
|