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