blob: f094c8d0907e1d0de1d16295fd77424cee68df9d [file] [log] [blame]
Adam Tkac5522d612010-08-11 15:28:01 +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
35using namespace rfb;
36using namespace rdr;
37using namespace std;
38
39static LogWriter vlog("SVeNCrypt");
40
41SSecurityVeNCrypt::SSecurityVeNCrypt(Security *sec) : security(sec)
42{
43 ssecurity = NULL;
44 haveSentVersion = false;
45 haveRecvdMajorVersion = false;
46 haveRecvdMinorVersion = false;
47 majorVersion = 0;
48 minorVersion = 0;
49 haveSentTypes = false;
50 haveChosenType = false;
51 chosenType = secTypeVeNCrypt;
52 numTypes = 0;
53 subTypes = NULL;
54}
55
56SSecurityVeNCrypt::~SSecurityVeNCrypt()
57{
58 if (subTypes) {
59 delete [] subTypes;
60 subTypes = NULL;
61 }
62}
63
64bool SSecurityVeNCrypt::processMsg(SConnection* sc)
65{
66 rdr::InStream* is = sc->getInStream();
67 rdr::OutStream* os = sc->getOutStream();
68 rdr::U8 i;
69
70 /* VeNCrypt initialization */
71
72 /* Send the highest version we can support */
73 if (!haveSentVersion) {
74 os->writeU8(0);
75 os->writeU8(2);
76 haveSentVersion = true;
77 os->flush();
78
79 return false;
80 }
81
82 /* Receive back highest version that client can support (up to and including ours) */
83 if (!haveRecvdMajorVersion) {
84 majorVersion = is->readU8();
85 haveRecvdMajorVersion = true;
86
87 return false;
88 }
89
90 if (!haveRecvdMinorVersion) {
91 minorVersion = is->readU8();
92 haveRecvdMinorVersion = true;
93
94 /* WORD value with major version in upper 8 bits and minor version in lower 8 bits */
95 U16 Version = (((U16)majorVersion) << 8) | ((U16)minorVersion);
96
97 switch (Version) {
98 case 0x0000: /* 0.0 - The client cannot support us! */
99 case 0x0001: /* 0.1 Legacy VeNCrypt, not supported */
100 os->writeU8(0xFF); /* This is not OK */
101 os->flush();
102 throw AuthFailureException("The client cannot support the server's "
103 "VeNCrypt version");
104
105 case 0x0002: /* 0.2 */
106 os->writeU8(0); /* OK */
107 break;
108
109 default:
110 os->writeU8(0xFF); /* Not OK */
111 os->flush();
112 throw AuthFailureException("The client returned an unsupported VeNCrypt version");
113 }
114 }
115
116 /*
117 * send number of supported VeNCrypt authentication types (U8) followed
118 * by authentication types (U32s)
119 */
120 if (!haveSentTypes) {
121 list<U32> listSubTypes;
122
123 listSubTypes = security->GetEnabledExtSecTypes();
124
125 numTypes = listSubTypes.size();
126 subTypes = new U32[numTypes];
127
128 for (i = 0; i < numTypes; i++) {
129 subTypes[i] = listSubTypes.front();
130 listSubTypes.pop_front();
131 }
132
133 if (numTypes) {
134 os->writeU8(numTypes);
135 for (i = 0; i < numTypes; i++)
136 os->writeU32(subTypes[i]);
137
138 os->flush();
139 haveSentTypes = true;
140 return false;
141 } else
142 throw AuthFailureException("There are no VeNCrypt sub-types to send to the client");
143 }
144
145 /* get type back from client (must be one of the ones we sent) */
146 if (!haveChosenType) {
147 is->check(4);
148 chosenType = is->readU32();
149
150 for (i = 0; i < numTypes; i++) {
151 if (chosenType == subTypes[i]) {
152 haveChosenType = true;
153 break;
154 }
155 }
156
157 if (!haveChosenType)
158 chosenType = secTypeInvalid;
159
160 vlog.debug("Choosing security type %s (%d)", secTypeName(chosenType),
161 chosenType);
162
163 /* Set up the stack according to the chosen type */
164 if (chosenType == secTypeInvalid || chosenType == secTypeVeNCrypt)
165 throw AuthFailureException("No valid VeNCrypt sub-type");
166
167 ssecurity = security->GetSSecurity(chosenType);
168 }
169
170 /* continue processing the messages */
171 return ssecurity->processMsg(sc);
172}
173