blob: 22201dd26a7240ab671fc2ec9ff5e16f83ee1b7c [file] [log] [blame]
Adam Tkac5522d612010-08-11 15:28:01 +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/CSecurityVeNCrypt.h>
30#include <rfb/LogWriter.h>
31#include <list>
32
33using namespace rfb;
34using namespace rdr;
35using namespace std;
36
37static LogWriter vlog("CVeNCrypt");
38
Pierre Ossmanad2b3c42018-09-21 15:31:11 +020039CSecurityVeNCrypt::CSecurityVeNCrypt(CConnection* cc, SecurityClient* sec)
40 : CSecurity(cc), csecurity(NULL), security(sec)
Adam Tkac5522d612010-08-11 15:28:01 +000041{
42 haveRecvdMajorVersion = false;
43 haveRecvdMinorVersion = false;
44 haveSentVersion = false;
45 haveAgreedVersion = false;
46 haveListOfTypes = false;
47 haveNumberOfTypes = false;
48 haveChosenType = false;
49 majorVersion = 0;
50 minorVersion = 0;
51 chosenType = secTypeVeNCrypt;
52 nAvailableTypes = 0;
53 availableTypes = NULL;
54 iAvailableType = 0;
55}
56
57CSecurityVeNCrypt::~CSecurityVeNCrypt()
58{
59 if (availableTypes)
60 delete[] availableTypes;
61}
62
Pierre Ossmanad2b3c42018-09-21 15:31:11 +020063bool CSecurityVeNCrypt::processMsg()
Adam Tkac5522d612010-08-11 15:28:01 +000064{
65 InStream* is = cc->getInStream();
66 OutStream* os = cc->getOutStream();
67
68 /* get major, minor versions, send what we can support (or 0.0 for can't support it) */
69 if (!haveRecvdMajorVersion) {
70 majorVersion = is->readU8();
71 haveRecvdMajorVersion = true;
72
73 return false;
74 }
75
76 if (!haveRecvdMinorVersion) {
77 minorVersion = is->readU8();
78 haveRecvdMinorVersion = true;
79 }
80
81 /* major version in upper 8 bits and minor version in lower 8 bits */
82 U16 Version = (((U16) majorVersion) << 8) | ((U16) minorVersion);
83
84 if (!haveSentVersion) {
85 /* Currently we don't support former VeNCrypt 0.1 */
86 if (Version >= 0x0002) {
87 majorVersion = 0;
88 minorVersion = 2;
89 os->writeU8(majorVersion);
90 os->writeU8(minorVersion);
91 os->flush();
92 } else {
93 /* Send 0.0 to indicate no support */
94 majorVersion = 0;
95 minorVersion = 0;
96 os->writeU8(0);
97 os->writeU8(0);
98 os->flush();
99 throw AuthFailureException("The server reported an unsupported VeNCrypt version");
100 }
101
102 haveSentVersion = true;
103 return false;
104 }
105
106 /* Check that the server is OK */
107 if (!haveAgreedVersion) {
108 if (is->readU8())
109 throw AuthFailureException("The server reported it could not support the "
110 "VeNCrypt version");
111
112 haveAgreedVersion = true;
113 return false;
114 }
115
116 /* get a number of types */
117 if (!haveNumberOfTypes) {
118 nAvailableTypes = is->readU8();
119 iAvailableType = 0;
120
121 if (!nAvailableTypes)
122 throw AuthFailureException("The server reported no VeNCrypt sub-types");
123
124 availableTypes = new rdr::U32[nAvailableTypes];
125 haveNumberOfTypes = true;
126 return false;
127 }
128
129 if (nAvailableTypes) {
130 /* read in the types possible */
131 if (!haveListOfTypes) {
132 if (is->checkNoWait(4)) {
133 availableTypes[iAvailableType++] = is->readU32();
134 haveListOfTypes = (iAvailableType >= nAvailableTypes);
135 vlog.debug("Server offers security type %s (%d)",
136 secTypeName(availableTypes[iAvailableType - 1]),
137 availableTypes[iAvailableType - 1]);
138
139 if (!haveListOfTypes)
140 return false;
141
142 } else
143 return false;
144 }
145
146 /* make a choice and send it to the server, meanwhile set up the stack */
147 if (!haveChosenType) {
148 chosenType = secTypeInvalid;
149 U8 i;
150 list<U32>::iterator j;
Adam Tkacccb92452011-02-21 13:40:33 +0000151 list<U32> secTypes;
Adam Tkac5522d612010-08-11 15:28:01 +0000152
Adam Tkacccb92452011-02-21 13:40:33 +0000153 secTypes = security->GetEnabledExtSecTypes();
Adam Tkac5522d612010-08-11 15:28:01 +0000154
Adam Tkacccb92452011-02-21 13:40:33 +0000155 /* Honor server's security type order */
156 for (i = 0; i < nAvailableTypes; i++) {
157 for (j = secTypes.begin(); j != secTypes.end(); j++) {
Adam Tkac5522d612010-08-11 15:28:01 +0000158 if (*j == availableTypes[i]) {
159 chosenType = *j;
160 break;
161 }
162 }
163
164 if (chosenType != secTypeInvalid)
165 break;
166 }
167
Pierre Ossman71d66662014-11-11 13:42:51 +0100168 vlog.info("Choosing security type %s (%d)", secTypeName(chosenType),
Adam Tkac5522d612010-08-11 15:28:01 +0000169 chosenType);
170
171 /* Set up the stack according to the chosen type: */
172 if (chosenType == secTypeInvalid || chosenType == secTypeVeNCrypt)
173 throw AuthFailureException("No valid VeNCrypt sub-type");
174
Pierre Ossmanad2b3c42018-09-21 15:31:11 +0200175 csecurity = security->GetCSecurity(cc, chosenType);
Adam Tkac5522d612010-08-11 15:28:01 +0000176
177 /* send chosen type to server */
178 os->writeU32(chosenType);
179 os->flush();
180
181 haveChosenType = true;
182 }
183 } else {
184 /*
185 * Server told us that there are 0 types it can support - this should not
186 * happen, since if the server supports 0 sub-types, it doesn't support
187 * this security type
188 */
189 throw AuthFailureException("The server reported 0 VeNCrypt sub-types");
190 }
191
Pierre Ossmanad2b3c42018-09-21 15:31:11 +0200192 return csecurity->processMsg();
Adam Tkac5522d612010-08-11 15:28:01 +0000193}
194
Pierre Ossmanb993ea72017-09-01 11:15:57 +0200195const char* CSecurityVeNCrypt::description() const
196{
197 if (csecurity)
198 return csecurity->description();
199 return "VeNCrypt";
200}
201
Pierre Ossmandaf3d882017-09-01 11:14:35 +0200202bool CSecurityVeNCrypt::isSecure() const
203{
204 if (csecurity && csecurity->isSecure())
205 return true;
206 return false;
207}