blob: c704d1e5ac484bc7782d373b5df85a2c57ea6adc [file] [log] [blame]
Adam Tkacdfe19cf2010-04-23 14:14:11 +00001/*
2 * Copyright (C) 2005-2006 Martin Koegler
3 * Copyright (C) 2006 OCCAM Financial Technology
4 * Copyright (C) 2010 TigerVNC Team
5 *
6 * This is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This software is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this software; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19 * USA.
20 */
21/*
22 * SSecurityVeNCrypt
23 */
24
25#ifdef HAVE_CONFIG_H
26#include <config.h>
27#endif
28
29#include <rfb/SSecurityVeNCrypt.h>
30#include <rfb/Exception.h>
31#include <rfb/LogWriter.h>
32#include <rdr/InStream.h>
33#include <rdr/OutStream.h>
Adam Tkacdfe19cf2010-04-23 14:14:11 +000034
35using namespace rfb;
36using namespace rdr;
37using namespace std;
38
39static LogWriter vlog("SVeNCrypt");
40
41StringParameter SSecurityVeNCrypt::X509_CertFile
42("x509cert",
43 "specifies path to the x509 certificate in PEM format",
44 "", ConfServer);
45
46StringParameter SSecurityVeNCrypt::X509_KeyFile
47("x509key",
48 "specifies path to the key of the x509 certificate in PEM format",
49 "", ConfServer);
50
Adam Tkaca0325932010-07-20 15:14:08 +000051SSecurityVeNCrypt::SSecurityVeNCrypt(Security *sec) : security(sec)
Adam Tkacdfe19cf2010-04-23 14:14:11 +000052{
Adam Tkacc86db212010-07-20 15:08:58 +000053 ssecurity = NULL;
Adam Tkacdfe19cf2010-04-23 14:14:11 +000054 haveSentVersion = false;
55 haveRecvdMajorVersion = false;
56 haveRecvdMinorVersion = false;
57 majorVersion = 0;
58 minorVersion = 0;
59 haveSentTypes = false;
60 haveChosenType = false;
61 chosenType = secTypeVeNCrypt;
62 numTypes = 0;
63 subTypes = NULL;
64}
65
66SSecurityVeNCrypt::~SSecurityVeNCrypt()
67{
68 if (subTypes) {
69 delete [] subTypes;
70 subTypes = NULL;
71 }
72}
73
74bool SSecurityVeNCrypt::processMsg(SConnection* sc)
75{
76 rdr::InStream* is = sc->getInStream();
77 rdr::OutStream* os = sc->getOutStream();
78 rdr::U8 i;
79
80 /* VeNCrypt initialization */
81
82 /* Send the highest version we can support */
83 if (!haveSentVersion) {
84 os->writeU8(0);
85 os->writeU8(2);
86 haveSentVersion = true;
87 os->flush();
88
89 return false;
90 }
91
92 /* Receive back highest version that client can support (up to and including ours) */
93 if (!haveRecvdMajorVersion) {
94 majorVersion = is->readU8();
95 haveRecvdMajorVersion = true;
96
97 return false;
98 }
99
100 if (!haveRecvdMinorVersion) {
101 minorVersion = is->readU8();
102 haveRecvdMinorVersion = true;
103
104 /* WORD value with major version in upper 8 bits and minor version in lower 8 bits */
105 U16 Version = (((U16)majorVersion) << 8) | ((U16)minorVersion);
106
107 switch (Version) {
108 case 0x0000: /* 0.0 - The client cannot support us! */
109 case 0x0001: /* 0.1 Legacy VeNCrypt, not supported */
110 os->writeU8(0xFF); /* This is not OK */
111 os->flush();
112 throw AuthFailureException("The client cannot support the server's "
113 "VeNCrypt version");
114
115 case 0x0002: /* 0.2 */
116 os->writeU8(0); /* OK */
117 break;
118
119 default:
120 os->writeU8(0xFF); /* Not OK */
121 os->flush();
122 throw AuthFailureException("The client returned an unsupported VeNCrypt version");
123 }
124 }
125
126 /*
127 * send number of supported VeNCrypt authentication types (U8) followed
128 * by authentication types (U32s)
129 */
130 if (!haveSentTypes) {
131 list<U32> listSubTypes;
Adam Tkac814fa892010-07-20 15:14:50 +0000132
133 listSubTypes = security->GetEnabledExtSecTypes();
Adam Tkacdfe19cf2010-04-23 14:14:11 +0000134
135 numTypes = listSubTypes.size();
136 subTypes = new U32[numTypes];
137
138 for (i = 0; i < numTypes; i++) {
139 subTypes[i] = listSubTypes.front();
140 listSubTypes.pop_front();
141 }
142
143 if (numTypes) {
144 os->writeU8(numTypes);
145 for (i = 0; i < numTypes; i++)
146 os->writeU32(subTypes[i]);
147
148 os->flush();
149 haveSentTypes = true;
150 return false;
151 } else
152 throw AuthFailureException("There are no VeNCrypt sub-types to send to the client");
153 }
154
155 /* get type back from client (must be one of the ones we sent) */
156 if (!haveChosenType) {
157 is->check(4);
158 chosenType = is->readU32();
159
160 for (i = 0; i < numTypes; i++) {
161 if (chosenType == subTypes[i]) {
162 haveChosenType = true;
163 break;
164 }
165 }
166
167 if (!haveChosenType)
168 chosenType = secTypeInvalid;
169
Adam Tkacdb062b62010-07-20 15:13:24 +0000170 vlog.debug("Choosing security type %s (%d)", secTypeName(chosenType),
171 chosenType);
Adam Tkacdfe19cf2010-04-23 14:14:11 +0000172
Adam Tkac814fa892010-07-20 15:14:50 +0000173 /* Set up the stack according to the chosen type */
174 if (chosenType == secTypeInvalid || chosenType == secTypeVeNCrypt)
175 throw AuthFailureException("No valid VeNCrypt sub-type");
176
Adam Tkac707d3612010-07-20 15:16:10 +0000177 ssecurity = security->GetSSecurity(chosenType);
Adam Tkacdfe19cf2010-04-23 14:14:11 +0000178 }
179
180 /* continue processing the messages */
Adam Tkacc86db212010-07-20 15:08:58 +0000181 return ssecurity->processMsg(sc);
Adam Tkacdfe19cf2010-04-23 14:14:11 +0000182}
183