blob: 2ea51fac63fb8b2bdadca64f5d6ca0c796bb0c40 [file] [log] [blame]
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +00001/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
Adam Tkacdf799702010-04-28 15:45:53 +00002 * Copyright (C) 2010 TigerVNC Team
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +00003 *
4 * This is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This software is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this software; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
17 * USA.
18 */
Adam Tkacdf799702010-04-28 15:45:53 +000019
20#ifdef HAVE_CONFIG_H
21#include <config.h>
22#endif
23
Adam Tkac1d15e2d2010-04-23 14:06:38 +000024#include <assert.h>
25#include <stdlib.h>
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +000026#include <string.h>
27#ifdef _WIN32
28#define strcasecmp _stricmp
29#endif
Adam Tkacc210e8a2010-04-23 14:09:16 +000030#include <rfb/CSecurityNone.h>
Adam Tkac707d3612010-07-20 15:16:10 +000031#include <rfb/CSecurityStack.h>
Adam Tkacb10489b2010-04-23 14:16:04 +000032#include <rfb/CSecurityVeNCrypt.h>
Adam Tkacc210e8a2010-04-23 14:09:16 +000033#include <rfb/CSecurityVncAuth.h>
Adam Tkac8c048382010-09-02 12:37:00 +000034#include <rfb/CSecurityPlain.h>
Adam Tkac1d15e2d2010-04-23 14:06:38 +000035#include <rdr/Exception.h>
36#include <rfb/LogWriter.h>
Adam Tkacb6eb3992010-04-23 14:05:00 +000037#include <rfb/Security.h>
Adam Tkac1d15e2d2010-04-23 14:06:38 +000038#include <rfb/SSecurityNone.h>
Adam Tkac707d3612010-07-20 15:16:10 +000039#include <rfb/SSecurityStack.h>
Adam Tkac520fc412010-09-02 14:13:24 +000040#include <rfb/SSecurityPlain.h>
Adam Tkac1d15e2d2010-04-23 14:06:38 +000041#include <rfb/SSecurityVncAuth.h>
Adam Tkacdfe19cf2010-04-23 14:14:11 +000042#include <rfb/SSecurityVeNCrypt.h>
Adam Tkac707d3612010-07-20 15:16:10 +000043#ifdef HAVE_GNUTLS
Adam Tkac3c5be392010-07-21 09:27:34 +000044#include <rfb/CSecurityTLS.h>
Adam Tkac21b61a52010-07-21 09:19:00 +000045#include <rfb/SSecurityTLS.h>
Adam Tkacdf799702010-04-28 15:45:53 +000046#endif
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +000047#include <rfb/util.h>
48
Adam Tkac1d15e2d2010-04-23 14:06:38 +000049using namespace rdr;
50using namespace rfb;
51using namespace std;
52
53static LogWriter vlog("Security");
54
Adam Tkacb10489b2010-04-23 14:16:04 +000055UserPasswdGetter *CSecurity::upg = NULL;
56
Adam Tkacfb993152010-08-12 14:17:28 +000057StringParameter Security::secTypesViewer
Adam Tkaca6578bf2010-04-23 14:07:41 +000058("SecurityTypes",
59 "Specify which security scheme to use (None, VncAuth)",
Adam Tkac80fb7ef2010-08-12 14:24:43 +000060#ifdef HAVE_GNUTLS
Adam Tkac8c048382010-09-02 12:37:00 +000061 "VeNCrypt,X509Plain,TLSPlain,X509Vnc,TLSVnc,X509None,TLSNone,VncAuth,None",
Adam Tkac80fb7ef2010-08-12 14:24:43 +000062#else
63 "VncAuth,None",
64#endif
65ConfViewer);
Adam Tkaca6578bf2010-04-23 14:07:41 +000066
Adam Tkacfb993152010-08-12 14:17:28 +000067StringParameter Security::secTypesServer
68("SecurityTypes",
69 "Specify which security scheme to use (None, VncAuth)",
Adam Tkac80fb7ef2010-08-12 14:24:43 +000070#ifdef HAVE_GNUTLS
71 "VeNCrypt,TLSVnc,VncAuth",
72#else
73 "VncAuth",
74#endif
75ConfServer);
Adam Tkacfb993152010-08-12 14:17:28 +000076
77Security::Security(SecurityClassType secClassType)
Adam Tkac1d15e2d2010-04-23 14:06:38 +000078{
Adam Tkacfb993152010-08-12 14:17:28 +000079 char *secTypesStr;
80
81 switch (secClassType) {
82 case SecurityViewer:
83 secTypesStr = secTypesViewer.getData();
84 break;
85 case SecurityServer:
86 secTypesStr = secTypesServer.getData();
87 break;
88 };
Adam Tkac1d15e2d2010-04-23 14:06:38 +000089
90 enabledSecTypes = parseSecTypes(secTypesStr);
91
92 delete secTypesStr;
93}
94
Adam Tkac0c77e512010-07-20 15:10:16 +000095const std::list<rdr::U8> Security::GetEnabledSecTypes(void)
Adam Tkac1d15e2d2010-04-23 14:06:38 +000096{
Adam Tkac0c77e512010-07-20 15:10:16 +000097 list<rdr::U8> result;
98 list<U32>::iterator i;
99
100 for (i = enabledSecTypes.begin(); i != enabledSecTypes.end(); i++)
101 if (*i < 0x100)
102 result.push_back(*i);
103
104 return result;
105}
106
107const std::list<rdr::U32> Security::GetEnabledExtSecTypes(void)
108{
109 list<rdr::U32> result;
110 list<U32>::iterator i;
111
112 for (i = enabledSecTypes.begin(); i != enabledSecTypes.end(); i++)
Adam Tkac95e2fe82010-08-12 13:54:59 +0000113 if (*i != secTypeVeNCrypt) /* Do not include VeNCrypt type to avoid loops */
Adam Tkac0c77e512010-07-20 15:10:16 +0000114 result.push_back(*i);
115
116 return result;
117}
118
119void Security::EnableSecType(U32 secType)
120{
121 list<U32>::iterator i;
Adam Tkac1d15e2d2010-04-23 14:06:38 +0000122
123 for (i = enabledSecTypes.begin(); i != enabledSecTypes.end(); i++)
124 if (*i == secType)
125 return;
126
127 enabledSecTypes.push_back(secType);
128}
129
Adam Tkac0c77e512010-07-20 15:10:16 +0000130bool Security::IsSupported(U32 secType)
Adam Tkac1d15e2d2010-04-23 14:06:38 +0000131{
Adam Tkac0c77e512010-07-20 15:10:16 +0000132 list<U32>::iterator i;
Adam Tkac1d15e2d2010-04-23 14:06:38 +0000133
134 for (i = enabledSecTypes.begin(); i != enabledSecTypes.end(); i++)
135 if (*i == secType)
136 return true;
137
138 return false;
139}
140
Adam Tkac0c77e512010-07-20 15:10:16 +0000141SSecurity* Security::GetSSecurity(U32 secType)
Adam Tkac1d15e2d2010-04-23 14:06:38 +0000142{
143 if (!IsSupported(secType))
144 goto bail;
145
146 switch (secType) {
147 case secTypeNone: return new SSecurityNone();
148 case secTypeVncAuth: return new SSecurityVncAuth();
Adam Tkaca0325932010-07-20 15:14:08 +0000149 case secTypeVeNCrypt: return new SSecurityVeNCrypt(this);
Adam Tkac520fc412010-09-02 14:13:24 +0000150 case secTypePlain: return new SSecurityPlain();
Adam Tkac707d3612010-07-20 15:16:10 +0000151#ifdef HAVE_GNUTLS
152 case secTypeTLSNone:
Adam Tkac21b61a52010-07-21 09:19:00 +0000153 return new SSecurityStack(secTypeTLSNone, new SSecurityTLS(true));
Adam Tkac707d3612010-07-20 15:16:10 +0000154 case secTypeTLSVnc:
Adam Tkac21b61a52010-07-21 09:19:00 +0000155 return new SSecurityStack(secTypeTLSVnc, new SSecurityTLS(true), new SSecurityVncAuth());
Adam Tkac520fc412010-09-02 14:13:24 +0000156 case secTypeTLSPlain:
157 return new SSecurityStack(secTypeTLSPlain, new SSecurityTLS(true), new SSecurityPlain());
Adam Tkac5bf73fb2010-07-21 09:08:24 +0000158 case secTypeX509None:
Adam Tkac21b61a52010-07-21 09:19:00 +0000159 return new SSecurityStack(secTypeX509None, new SSecurityTLS(false));
Adam Tkac5bf73fb2010-07-21 09:08:24 +0000160 case secTypeX509Vnc:
Adam Tkac21b61a52010-07-21 09:19:00 +0000161 return new SSecurityStack(secTypeX509None, new SSecurityTLS(false), new SSecurityVncAuth());
Adam Tkac520fc412010-09-02 14:13:24 +0000162 case secTypeX509Plain:
163 return new SSecurityStack(secTypeX509Plain, new SSecurityTLS(false), new SSecurityPlain());
Adam Tkacdf799702010-04-28 15:45:53 +0000164#endif
Adam Tkacc210e8a2010-04-23 14:09:16 +0000165 }
166
167bail:
168 throw Exception("Security type not supported");
169}
170
Adam Tkac0c77e512010-07-20 15:10:16 +0000171CSecurity* Security::GetCSecurity(U32 secType)
Adam Tkacc210e8a2010-04-23 14:09:16 +0000172{
Adam Tkacb10489b2010-04-23 14:16:04 +0000173 assert (CSecurity::upg != NULL); /* (upg == NULL) means bug in the viewer */
Adam Tkacc210e8a2010-04-23 14:09:16 +0000174
175 if (!IsSupported(secType))
176 goto bail;
177
178 switch (secType) {
179 case secTypeNone: return new CSecurityNone();
Adam Tkacb10489b2010-04-23 14:16:04 +0000180 case secTypeVncAuth: return new CSecurityVncAuth();
Adam Tkaca0325932010-07-20 15:14:08 +0000181 case secTypeVeNCrypt: return new CSecurityVeNCrypt(this);
Adam Tkac8c048382010-09-02 12:37:00 +0000182 case secTypePlain: return new CSecurityPlain();
Adam Tkac707d3612010-07-20 15:16:10 +0000183#ifdef HAVE_GNUTLS
184 case secTypeTLSNone:
185 return new CSecurityStack(secTypeTLSNone, "TLS with no password",
Adam Tkac3c5be392010-07-21 09:27:34 +0000186 new CSecurityTLS(true));
Adam Tkac707d3612010-07-20 15:16:10 +0000187 case secTypeTLSVnc:
188 return new CSecurityStack(secTypeTLSVnc, "TLS with VNCAuth",
Adam Tkac3c5be392010-07-21 09:27:34 +0000189 new CSecurityTLS(true), new CSecurityVncAuth());
Adam Tkac8c048382010-09-02 12:37:00 +0000190 case secTypeTLSPlain:
191 return new CSecurityStack(secTypeTLSPlain, "TLS with Username/Password",
192 new CSecurityTLS(true), new CSecurityPlain());
Adam Tkacf5f6a002010-07-21 09:09:19 +0000193 case secTypeX509None:
194 return new CSecurityStack(secTypeX509None, "X509 with no password",
Adam Tkac3c5be392010-07-21 09:27:34 +0000195 new CSecurityTLS(false));
Adam Tkacf5f6a002010-07-21 09:09:19 +0000196 case secTypeX509Vnc:
197 return new CSecurityStack(secTypeX509None, "X509 with VNCAuth",
Adam Tkac3c5be392010-07-21 09:27:34 +0000198 new CSecurityTLS(false), new CSecurityVncAuth());
Adam Tkac8c048382010-09-02 12:37:00 +0000199 case secTypeX509Plain:
200 return new CSecurityStack(secTypeX509Plain, "X509 with Username/Password",
201 new CSecurityTLS(false), new CSecurityPlain());
Adam Tkacdf799702010-04-28 15:45:53 +0000202#endif
Adam Tkac1d15e2d2010-04-23 14:06:38 +0000203 }
204
205bail:
206 throw Exception("Security type not supported");
207}
208
Adam Tkac0c77e512010-07-20 15:10:16 +0000209rdr::U32 rfb::secTypeNum(const char* name)
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +0000210{
211 if (strcasecmp(name, "None") == 0) return secTypeNone;
212 if (strcasecmp(name, "VncAuth") == 0) return secTypeVncAuth;
213 if (strcasecmp(name, "Tight") == 0) return secTypeTight;
214 if (strcasecmp(name, "RA2") == 0) return secTypeRA2;
215 if (strcasecmp(name, "RA2ne") == 0) return secTypeRA2ne;
216 if (strcasecmp(name, "SSPI") == 0) return secTypeSSPI;
Adam Tkacdfe19cf2010-04-23 14:14:11 +0000217 if (strcasecmp(name, "SSPIne") == 0) return secTypeSSPIne;
218 if (strcasecmp(name, "VeNCrypt") == 0) return secTypeVeNCrypt;
Adam Tkacb3e60c62010-07-20 15:10:59 +0000219
220 /* VeNCrypt subtypes */
Adam Tkac957a5ae2010-07-20 15:12:41 +0000221 if (strcasecmp(name, "Plain") == 0) return secTypePlain;
Adam Tkacb3e60c62010-07-20 15:10:59 +0000222 if (strcasecmp(name, "TLSNone") == 0) return secTypeTLSNone;
223 if (strcasecmp(name, "TLSVnc") == 0) return secTypeTLSVnc;
Adam Tkac957a5ae2010-07-20 15:12:41 +0000224 if (strcasecmp(name, "TLSPlain") == 0) return secTypeTLSPlain;
Adam Tkacb3e60c62010-07-20 15:10:59 +0000225 if (strcasecmp(name, "X509None") == 0) return secTypeX509None;
226 if (strcasecmp(name, "X509Vnc") == 0) return secTypeX509Vnc;
Adam Tkacb3e60c62010-07-20 15:10:59 +0000227 if (strcasecmp(name, "X509Plain") == 0) return secTypeX509Plain;
Adam Tkacb3e60c62010-07-20 15:10:59 +0000228
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +0000229 return secTypeInvalid;
230}
231
Adam Tkac0c77e512010-07-20 15:10:16 +0000232const char* rfb::secTypeName(rdr::U32 num)
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +0000233{
234 switch (num) {
235 case secTypeNone: return "None";
236 case secTypeVncAuth: return "VncAuth";
237 case secTypeTight: return "Tight";
238 case secTypeRA2: return "RA2";
239 case secTypeRA2ne: return "RA2ne";
240 case secTypeSSPI: return "SSPI";
241 case secTypeSSPIne: return "SSPIne";
Adam Tkacdfe19cf2010-04-23 14:14:11 +0000242 case secTypeVeNCrypt: return "VeNCrypt";
Adam Tkacb3e60c62010-07-20 15:10:59 +0000243
244 /* VeNCrypt subtypes */
Adam Tkac957a5ae2010-07-20 15:12:41 +0000245 case secTypePlain: return "Plain";
Adam Tkacb3e60c62010-07-20 15:10:59 +0000246 case secTypeTLSNone: return "TLSNone";
247 case secTypeTLSVnc: return "TLSVnc";
Adam Tkacb3e60c62010-07-20 15:10:59 +0000248 case secTypeTLSPlain: return "TLSPlain";
249 case secTypeX509None: return "X509None";
250 case secTypeX509Vnc: return "X509Vnc";
251 case secTypeX509Plain: return "X509Plain";
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +0000252 default: return "[unknown secType]";
253 }
254}
255
Adam Tkac0c77e512010-07-20 15:10:16 +0000256std::list<rdr::U32> rfb::parseSecTypes(const char* types_)
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +0000257{
Adam Tkac0c77e512010-07-20 15:10:16 +0000258 std::list<rdr::U32> result;
Adam Tkacd36b6262009-09-04 10:57:20 +0000259 CharArray types(strDup(types_)), type;
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +0000260 while (types.buf) {
261 strSplit(types.buf, ',', &type.buf, &types.buf);
Adam Tkac0c77e512010-07-20 15:10:16 +0000262 rdr::U32 typeNum = secTypeNum(type.buf);
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +0000263 if (typeNum != secTypeInvalid)
264 result.push_back(typeNum);
265 }
266 return result;
267}