blob: fc8314821e4175b9f591ca569cd5eefa3b7e2cc6 [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>
34#include <rfb/SSecurityVncAuth.h>
35#include <rfb/SSecurityTLS.h>
36
37using namespace rfb;
38using namespace rdr;
39using namespace std;
40
41static LogWriter vlog("SVeNCrypt");
42
43StringParameter SSecurityVeNCrypt::X509_CertFile
44("x509cert",
45 "specifies path to the x509 certificate in PEM format",
46 "", ConfServer);
47
48StringParameter SSecurityVeNCrypt::X509_KeyFile
49("x509key",
50 "specifies path to the key of the x509 certificate in PEM format",
51 "", ConfServer);
52
53StringParameter SSecurityVeNCrypt::secTypesStr
54("VeNCryptTypes",
55 "Specify which security scheme to use for VeNCrypt connections (TLSNone, "
56 "TLSVnc, TLSPlain, X509None, X509Vnc, X509Plain)",
57 "TLSVnc,TLSPlain,X509Vnc,X509Plain", ConfServer);
58
59SSecurityVeNCrypt::SSecurityVeNCrypt(void)
60{
61 ssecurityStack = NULL;
62 haveSentVersion = false;
63 haveRecvdMajorVersion = false;
64 haveRecvdMinorVersion = false;
65 majorVersion = 0;
66 minorVersion = 0;
67 haveSentTypes = false;
68 haveChosenType = false;
69 chosenType = secTypeVeNCrypt;
70 numTypes = 0;
71 subTypes = NULL;
72}
73
74SSecurityVeNCrypt::~SSecurityVeNCrypt()
75{
76 if (subTypes) {
77 delete [] subTypes;
78 subTypes = NULL;
79 }
80}
81
82bool SSecurityVeNCrypt::processMsg(SConnection* sc)
83{
84 rdr::InStream* is = sc->getInStream();
85 rdr::OutStream* os = sc->getOutStream();
86 rdr::U8 i;
87
88 /* VeNCrypt initialization */
89
90 /* Send the highest version we can support */
91 if (!haveSentVersion) {
92 os->writeU8(0);
93 os->writeU8(2);
94 haveSentVersion = true;
95 os->flush();
96
97 return false;
98 }
99
100 /* Receive back highest version that client can support (up to and including ours) */
101 if (!haveRecvdMajorVersion) {
102 majorVersion = is->readU8();
103 haveRecvdMajorVersion = true;
104
105 return false;
106 }
107
108 if (!haveRecvdMinorVersion) {
109 minorVersion = is->readU8();
110 haveRecvdMinorVersion = true;
111
112 /* WORD value with major version in upper 8 bits and minor version in lower 8 bits */
113 U16 Version = (((U16)majorVersion) << 8) | ((U16)minorVersion);
114
115 switch (Version) {
116 case 0x0000: /* 0.0 - The client cannot support us! */
117 case 0x0001: /* 0.1 Legacy VeNCrypt, not supported */
118 os->writeU8(0xFF); /* This is not OK */
119 os->flush();
120 throw AuthFailureException("The client cannot support the server's "
121 "VeNCrypt version");
122
123 case 0x0002: /* 0.2 */
124 os->writeU8(0); /* OK */
125 break;
126
127 default:
128 os->writeU8(0xFF); /* Not OK */
129 os->flush();
130 throw AuthFailureException("The client returned an unsupported VeNCrypt version");
131 }
132 }
133
134 /*
135 * send number of supported VeNCrypt authentication types (U8) followed
136 * by authentication types (U32s)
137 */
138 if (!haveSentTypes) {
139 list<U32> listSubTypes;
140 SSecurityVeNCrypt::getSecTypes(&listSubTypes);
141
142 numTypes = listSubTypes.size();
143 subTypes = new U32[numTypes];
144
145 for (i = 0; i < numTypes; i++) {
146 subTypes[i] = listSubTypes.front();
147 listSubTypes.pop_front();
148 }
149
150 if (numTypes) {
151 os->writeU8(numTypes);
152 for (i = 0; i < numTypes; i++)
153 os->writeU32(subTypes[i]);
154
155 os->flush();
156 haveSentTypes = true;
157 return false;
158 } else
159 throw AuthFailureException("There are no VeNCrypt sub-types to send to the client");
160 }
161
162 /* get type back from client (must be one of the ones we sent) */
163 if (!haveChosenType) {
164 is->check(4);
165 chosenType = is->readU32();
166
167 for (i = 0; i < numTypes; i++) {
168 if (chosenType == subTypes[i]) {
169 haveChosenType = true;
170 break;
171 }
172 }
173
174 if (!haveChosenType)
175 chosenType = secTypeInvalid;
176
177 /* Set up the stack according to the chosen type */
178 switch(chosenType) {
179 case secTypeTLSNone:
180 case secTypeTLSVnc:
181 case secTypeTLSPlain:
182 case secTypeX509None:
183 case secTypeX509Vnc:
184 case secTypeX509Plain:
185 ssecurityStack = SSecurityVeNCrypt::getSSecurityStack(chosenType);
186 break;
187 case secTypeInvalid:
188 case secTypeVeNCrypt: /* This would cause looping */
189 default:
190 throw AuthFailureException("No valid VeNCrypt sub-type");
191 }
192
193 }
194
195 /* continue processing the messages */
196 return ssecurityStack->processMsg(sc);
197}
198
199SSecurityStack* SSecurityVeNCrypt::getSSecurityStack(int secType)
200{
201 switch (secType) {
202 case secTypeTLSNone:
203 return new SSecurityStack(secTypeTLSNone, new SSecurityTLS());
204 case secTypeTLSVnc:
205 return new SSecurityStack(secTypeTLSVnc, new SSecurityTLS(), new SSecurityVncAuth());
206#if 0
207 /* Following types are not implemented, yet */
208 case secTypeTLSPlain:
209 case secTypeX509None:
210 case secTypeX509Vnc:
211 case secTypeX509Plain:
212#endif
213 default:
214 throw Exception("Bug in the SSecurityVeNCrypt::getSSecurityStack");
215 }
216}
217
218void SSecurityVeNCrypt::getSecTypes(list<U32>* secTypes)
219{
220 CharArray types;
221
222 types.buf = SSecurityVeNCrypt::secTypesStr.getData();
223 list<U32> configured = SSecurityVeNCrypt::parseSecTypes(types.buf);
224 list<U32>::iterator i;
225 for (i = configured.begin(); i != configured.end(); i++)
226 secTypes->push_back(*i);
227}
228
229U32 SSecurityVeNCrypt::secTypeNum(const char *name)
230{
231 if (strcasecmp(name, "TLSNone") == 0)
232 return secTypeTLSNone;
233 if (strcasecmp(name, "TLSVnc") == 0)
234 return secTypeTLSVnc;
235 if (strcasecmp(name, "TLSPlain") == 0)
236 return secTypeTLSPlain;
237 if (strcasecmp(name, "X509None") == 0)
238 return secTypeX509None;
239 if (strcasecmp(name, "X509Vnc") == 0)
240 return secTypeX509Vnc;
241 if (strcasecmp(name, "X509Plain") == 0)
242 return secTypeX509Plain;
243
244 return secTypeInvalid;
245}
246
247char* SSecurityVeNCrypt::secTypeName(U32 num)
248{
249 switch (num) {
250 case secTypePlain:
251 return "Plain";
252 case secTypeTLSNone:
253 return "TLSNone";
254 case secTypeTLSVnc:
255 return "TLSVnc";
256 case secTypeTLSPlain:
257 return "TLSPlain";
258 case secTypeX509None:
259 return "X509None";
260 case secTypeX509Vnc:
261 return "X509Vnc";
262 case secTypeX509Plain:
263 return "X509Plain";
264 default:
265 return "[unknown secType]";
266 }
267}
268
269list<U32> SSecurityVeNCrypt::parseSecTypes(const char *secTypes)
270{
271 list<U32> result;
272 CharArray types(strDup(secTypes)), type;
273 while (types.buf) {
274 strSplit(types.buf, ',', &type.buf, &types.buf);
275 int typeNum = SSecurityVeNCrypt::secTypeNum(type.buf);
276 if (typeNum != secTypeInvalid)
277 result.push_back(typeNum);
278 }
279 return result;
280}
281
282