blob: 521f7060f0ea1ac75fce9696340e8d92a7748d09 [file] [log] [blame]
Adam Tkacb10489b2010-04-23 14:16:04 +00001/*
2 * Copyright (C) 2006 OCCAM Financial Technology
3 * Copyright (C) 2005-2006 Martin Koegler
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// CSecurityVeNCrypt
23//
24
25#include <rfb/Exception.h>
26#include <rdr/InStream.h>
27#include <rdr/OutStream.h>
28#include <rfb/CConnection.h>
29#include <rfb/CSecurityTLS.h>
30#include <rfb/CSecurityVeNCrypt.h>
31#include <rfb/CSecurityVncAuth.h>
32#include <rfb/SSecurityVeNCrypt.h>
33#include <list>
34
35using namespace rfb;
36using namespace rdr;
37using namespace std;
38
Adam Tkacc86db212010-07-20 15:08:58 +000039CSecurityVeNCrypt::CSecurityVeNCrypt(void) : csecurity(NULL)
Adam Tkacb10489b2010-04-23 14:16:04 +000040{
41 haveRecvdMajorVersion = false;
42 haveRecvdMinorVersion = false;
43 haveSentVersion = false;
44 haveAgreedVersion = false;
45 haveListOfTypes = false;
46 haveNumberOfTypes = false;
47 haveChosenType = false;
48 majorVersion = 0;
49 minorVersion = 0;
50 chosenType = secTypeVeNCrypt;
51 nAvailableTypes = 0;
52 availableTypes = NULL;
53 iAvailableType = 0;
54}
55
56CSecurityVeNCrypt::~CSecurityVeNCrypt()
57{
58 if (availableTypes)
59 delete[] availableTypes;
60}
61
62bool CSecurityVeNCrypt::processMsg(CConnection* cc)
63{
64 InStream* is = cc->getInStream();
65 OutStream* os = cc->getOutStream();
66
67 /* get major, minor versions, send what we can support (or 0.0 for can't support it) */
68 if (!haveRecvdMajorVersion) {
69 majorVersion = is->readU8();
70 haveRecvdMajorVersion = true;
71
72 return false;
73 }
74
75 if (!haveRecvdMinorVersion) {
76 minorVersion = is->readU8();
77 haveRecvdMinorVersion = true;
78 }
79
80 /* major version in upper 8 bits and minor version in lower 8 bits */
81 U16 Version = (((U16) majorVersion) << 8) | ((U16) minorVersion);
82
83 if (!haveSentVersion) {
84 /* Currently we don't support former VeNCrypt 0.1 */
85 if (Version >= 0x0002) {
86 majorVersion = 0;
87 minorVersion = 2;
88 os->writeU8(majorVersion);
89 os->writeU8(minorVersion);
90 os->flush();
91 } else {
92 /* Send 0.0 to indicate no support */
93 majorVersion = 0;
94 minorVersion = 0;
95 os->writeU8(0);
96 os->writeU8(0);
97 os->flush();
98 throw AuthFailureException("The server reported an unsupported VeNCrypt version");
99 }
100
101 haveSentVersion = true;
102 return false;
103 }
104
105 /* Check that the server is OK */
106 if (!haveAgreedVersion) {
107 if (is->readU8())
108 throw AuthFailureException("The server reported it could not support the "
109 "VeNCrypt version");
110
111 haveAgreedVersion = true;
112 return false;
113 }
114
115 /* get a number of types */
116 if (!haveNumberOfTypes) {
117 nAvailableTypes = is->readU8();
118 iAvailableType = 0;
119
120 if (!nAvailableTypes)
121 throw AuthFailureException("The server reported no VeNCrypt sub-types");
122
123 availableTypes = new rdr::U32[nAvailableTypes];
124 haveNumberOfTypes = true;
125 return false;
126 }
127
128 if (nAvailableTypes) {
129 /* read in the types possible */
130 if (!haveListOfTypes) {
131 if (is->checkNoWait(4)) {
132 availableTypes[iAvailableType++] = is->readU32();
133 haveListOfTypes = (iAvailableType >= nAvailableTypes);
134
135 if (!haveListOfTypes)
136 return false;
137
138 } else
139 return false;
140 }
141
142 /* make a choice and send it to the server, meanwhile set up the stack */
143 if (!haveChosenType) {
144 chosenType = 0;
145 U8 i;
146 list<U32>::iterator j;
147 list<U32> preferredList;
148
149 /* Try preferred choice */
150 SSecurityVeNCrypt::getSecTypes(&preferredList);
151
152 for (j = preferredList.begin(); j != preferredList.end(); j++) {
153 for (i = 0; i < nAvailableTypes; i++) {
154 if (*j == availableTypes[i]) {
155 chosenType = *j;
156 break;
157 }
158 }
159
160 if (chosenType)
161 break;
162 }
163
164 /* Set up the stack according to the chosen type: */
165 switch (chosenType) {
166 case secTypeTLSNone:
167 case secTypeTLSVnc:
168 case secTypeTLSPlain:
169 case secTypeX509None:
170 case secTypeX509Vnc:
171 case secTypeX509Plain:
Adam Tkacc86db212010-07-20 15:08:58 +0000172 csecurity = CSecurityVeNCrypt::getCSecurityStack(chosenType);
Adam Tkacb10489b2010-04-23 14:16:04 +0000173 break;
174
175 case secTypeInvalid:
176 case secTypeVeNCrypt: /* would cause looping */
177 default:
178 throw AuthFailureException("No valid VeNCrypt sub-type");
179 }
180
181 /* send chosen type to server */
182 os->writeU32(chosenType);
183 os->flush();
184
185 haveChosenType = true;
186 }
187 } else {
188 /*
189 * Server told us that there are 0 types it can support - this should not
190 * happen, since if the server supports 0 sub-types, it doesn't support
191 * this security type
192 */
193 throw AuthFailureException("The server reported 0 VeNCrypt sub-types");
194 }
195
Adam Tkacc86db212010-07-20 15:08:58 +0000196 return csecurity->processMsg(cc);
Adam Tkacb10489b2010-04-23 14:16:04 +0000197}
198
199CSecurityStack* CSecurityVeNCrypt::getCSecurityStack(int secType)
200{
201 switch (secType) {
202 case secTypeTLSNone:
203 return new CSecurityStack(secTypeTLSNone, "TLS with no password",
204 new CSecurityTLS());
205 case secTypeTLSVnc:
206 return new CSecurityStack(secTypeTLSVnc, "TLS with VNCAuth",
207 new CSecurityTLS(), new CSecurityVncAuth());
208#if 0
209 /* Following subtypes are not implemented, yet */
210 case secTypeTLSPlain:
211 case secTypeX509None:
212 case secTypeX509Vnc:
213 case secTypeX509Plain:
214#endif
215 default:
216 throw Exception("Unsupported VeNCrypt subtype");
217 }
218
219 return NULL; /* not reached */
220}