blob: 2dd331e926d2803eea69600cd46407081e5e3810 [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
Adam Tkacdf799702010-04-28 15:45:53 +000029#ifndef HAVE_GNUTLS
30#error "This source should not be compiled without HAVE_GNUTLS defined"
31#endif
32
Adam Tkacdfe19cf2010-04-23 14:14:11 +000033#include <rfb/SSecurityVeNCrypt.h>
34#include <rfb/Exception.h>
35#include <rfb/LogWriter.h>
36#include <rdr/InStream.h>
37#include <rdr/OutStream.h>
38#include <rfb/SSecurityVncAuth.h>
39#include <rfb/SSecurityTLS.h>
40
41using namespace rfb;
42using namespace rdr;
43using namespace std;
44
45static LogWriter vlog("SVeNCrypt");
46
47StringParameter SSecurityVeNCrypt::X509_CertFile
48("x509cert",
49 "specifies path to the x509 certificate in PEM format",
50 "", ConfServer);
51
52StringParameter SSecurityVeNCrypt::X509_KeyFile
53("x509key",
54 "specifies path to the key of the x509 certificate in PEM format",
55 "", ConfServer);
56
Adam Tkaca0325932010-07-20 15:14:08 +000057SSecurityVeNCrypt::SSecurityVeNCrypt(Security *sec) : security(sec)
Adam Tkacdfe19cf2010-04-23 14:14:11 +000058{
Adam Tkacc86db212010-07-20 15:08:58 +000059 ssecurity = NULL;
Adam Tkacdfe19cf2010-04-23 14:14:11 +000060 haveSentVersion = false;
61 haveRecvdMajorVersion = false;
62 haveRecvdMinorVersion = false;
63 majorVersion = 0;
64 minorVersion = 0;
65 haveSentTypes = false;
66 haveChosenType = false;
67 chosenType = secTypeVeNCrypt;
68 numTypes = 0;
69 subTypes = NULL;
70}
71
72SSecurityVeNCrypt::~SSecurityVeNCrypt()
73{
74 if (subTypes) {
75 delete [] subTypes;
76 subTypes = NULL;
77 }
78}
79
80bool SSecurityVeNCrypt::processMsg(SConnection* sc)
81{
82 rdr::InStream* is = sc->getInStream();
83 rdr::OutStream* os = sc->getOutStream();
84 rdr::U8 i;
85
86 /* VeNCrypt initialization */
87
88 /* Send the highest version we can support */
89 if (!haveSentVersion) {
90 os->writeU8(0);
91 os->writeU8(2);
92 haveSentVersion = true;
93 os->flush();
94
95 return false;
96 }
97
98 /* Receive back highest version that client can support (up to and including ours) */
99 if (!haveRecvdMajorVersion) {
100 majorVersion = is->readU8();
101 haveRecvdMajorVersion = true;
102
103 return false;
104 }
105
106 if (!haveRecvdMinorVersion) {
107 minorVersion = is->readU8();
108 haveRecvdMinorVersion = true;
109
110 /* WORD value with major version in upper 8 bits and minor version in lower 8 bits */
111 U16 Version = (((U16)majorVersion) << 8) | ((U16)minorVersion);
112
113 switch (Version) {
114 case 0x0000: /* 0.0 - The client cannot support us! */
115 case 0x0001: /* 0.1 Legacy VeNCrypt, not supported */
116 os->writeU8(0xFF); /* This is not OK */
117 os->flush();
118 throw AuthFailureException("The client cannot support the server's "
119 "VeNCrypt version");
120
121 case 0x0002: /* 0.2 */
122 os->writeU8(0); /* OK */
123 break;
124
125 default:
126 os->writeU8(0xFF); /* Not OK */
127 os->flush();
128 throw AuthFailureException("The client returned an unsupported VeNCrypt version");
129 }
130 }
131
132 /*
133 * send number of supported VeNCrypt authentication types (U8) followed
134 * by authentication types (U32s)
135 */
136 if (!haveSentTypes) {
137 list<U32> listSubTypes;
Adam Tkac814fa892010-07-20 15:14:50 +0000138
139 listSubTypes = security->GetEnabledExtSecTypes();
Adam Tkacdfe19cf2010-04-23 14:14:11 +0000140
141 numTypes = listSubTypes.size();
142 subTypes = new U32[numTypes];
143
144 for (i = 0; i < numTypes; i++) {
145 subTypes[i] = listSubTypes.front();
146 listSubTypes.pop_front();
147 }
148
149 if (numTypes) {
150 os->writeU8(numTypes);
151 for (i = 0; i < numTypes; i++)
152 os->writeU32(subTypes[i]);
153
154 os->flush();
155 haveSentTypes = true;
156 return false;
157 } else
158 throw AuthFailureException("There are no VeNCrypt sub-types to send to the client");
159 }
160
161 /* get type back from client (must be one of the ones we sent) */
162 if (!haveChosenType) {
163 is->check(4);
164 chosenType = is->readU32();
165
166 for (i = 0; i < numTypes; i++) {
167 if (chosenType == subTypes[i]) {
168 haveChosenType = true;
169 break;
170 }
171 }
172
173 if (!haveChosenType)
174 chosenType = secTypeInvalid;
175
Adam Tkacdb062b62010-07-20 15:13:24 +0000176 vlog.debug("Choosing security type %s (%d)", secTypeName(chosenType),
177 chosenType);
Adam Tkacdfe19cf2010-04-23 14:14:11 +0000178
Adam Tkac814fa892010-07-20 15:14:50 +0000179 /* Set up the stack according to the chosen type */
180 if (chosenType == secTypeInvalid || chosenType == secTypeVeNCrypt)
181 throw AuthFailureException("No valid VeNCrypt sub-type");
182
183 ssecurity = SSecurityVeNCrypt::getSSecurityStack(chosenType);
Adam Tkacdfe19cf2010-04-23 14:14:11 +0000184 }
185
186 /* continue processing the messages */
Adam Tkacc86db212010-07-20 15:08:58 +0000187 return ssecurity->processMsg(sc);
Adam Tkacdfe19cf2010-04-23 14:14:11 +0000188}
189
190SSecurityStack* SSecurityVeNCrypt::getSSecurityStack(int secType)
191{
192 switch (secType) {
193 case secTypeTLSNone:
194 return new SSecurityStack(secTypeTLSNone, new SSecurityTLS());
195 case secTypeTLSVnc:
196 return new SSecurityStack(secTypeTLSVnc, new SSecurityTLS(), new SSecurityVncAuth());
197#if 0
198 /* Following types are not implemented, yet */
199 case secTypeTLSPlain:
200 case secTypeX509None:
201 case secTypeX509Vnc:
202 case secTypeX509Plain:
203#endif
204 default:
205 throw Exception("Bug in the SSecurityVeNCrypt::getSSecurityStack");
206 }
207}
208