blob: 2d91190f64e2ee6add50758a06fae62649153ee2 [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>
Adam Tkacb10489b2010-04-23 14:16:04 +000029#include <rfb/CSecurityVeNCrypt.h>
Adam Tkacdb062b62010-07-20 15:13:24 +000030#include <rfb/LogWriter.h>
Adam Tkacb10489b2010-04-23 14:16:04 +000031#include <list>
32
33using namespace rfb;
34using namespace rdr;
35using namespace std;
36
Adam Tkacdb062b62010-07-20 15:13:24 +000037static LogWriter vlog("CVeNCrypt");
38
Adam Tkaca0325932010-07-20 15:14:08 +000039CSecurityVeNCrypt::CSecurityVeNCrypt(Security* sec) : csecurity(NULL), security(sec)
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);
Adam Tkacdb062b62010-07-20 15:13:24 +0000134 vlog.debug("Server offers security type %s (%d)",
135 secTypeName(availableTypes[iAvailableType - 1]),
136 availableTypes[iAvailableType - 1]);
Adam Tkacb10489b2010-04-23 14:16:04 +0000137
138 if (!haveListOfTypes)
139 return false;
140
141 } else
142 return false;
143 }
144
145 /* make a choice and send it to the server, meanwhile set up the stack */
146 if (!haveChosenType) {
Adam Tkac814fa892010-07-20 15:14:50 +0000147 chosenType = secTypeInvalid;
Adam Tkacb10489b2010-04-23 14:16:04 +0000148 U8 i;
149 list<U32>::iterator j;
150 list<U32> preferredList;
151
152 /* Try preferred choice */
Adam Tkac814fa892010-07-20 15:14:50 +0000153 preferredList = security->GetEnabledExtSecTypes();
154
Adam Tkacb10489b2010-04-23 14:16:04 +0000155 for (j = preferredList.begin(); j != preferredList.end(); j++) {
156 for (i = 0; i < nAvailableTypes; i++) {
157 if (*j == availableTypes[i]) {
158 chosenType = *j;
159 break;
160 }
161 }
162
Adam Tkac814fa892010-07-20 15:14:50 +0000163 if (chosenType != secTypeInvalid)
Adam Tkacb10489b2010-04-23 14:16:04 +0000164 break;
165 }
166
Adam Tkacdb062b62010-07-20 15:13:24 +0000167 vlog.debug("Choosing security type %s (%d)", secTypeName(chosenType),
168 chosenType);
Adam Tkacb10489b2010-04-23 14:16:04 +0000169
Adam Tkac814fa892010-07-20 15:14:50 +0000170 /* Set up the stack according to the chosen type: */
171 if (chosenType == secTypeInvalid || chosenType == secTypeVeNCrypt)
172 throw AuthFailureException("No valid VeNCrypt sub-type");
173
Adam Tkac707d3612010-07-20 15:16:10 +0000174 csecurity = security->GetCSecurity(chosenType);
Adam Tkac814fa892010-07-20 15:14:50 +0000175
Adam Tkacb10489b2010-04-23 14:16:04 +0000176 /* send chosen type to server */
177 os->writeU32(chosenType);
178 os->flush();
179
180 haveChosenType = true;
181 }
182 } else {
183 /*
184 * Server told us that there are 0 types it can support - this should not
185 * happen, since if the server supports 0 sub-types, it doesn't support
186 * this security type
187 */
188 throw AuthFailureException("The server reported 0 VeNCrypt sub-types");
189 }
190
Adam Tkacc86db212010-07-20 15:08:58 +0000191 return csecurity->processMsg(cc);
Adam Tkacb10489b2010-04-23 14:16:04 +0000192}
193