blob: 0666041cb861252f6d9abceef31d4a38aa781c08 [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>
Adam Tkacc210e8a2010-04-23 14:09:16 +000027#include <rfb/CSecurityNone.h>
Adam Tkac707d3612010-07-20 15:16:10 +000028#include <rfb/CSecurityStack.h>
Adam Tkacb10489b2010-04-23 14:16:04 +000029#include <rfb/CSecurityVeNCrypt.h>
Adam Tkacc210e8a2010-04-23 14:09:16 +000030#include <rfb/CSecurityVncAuth.h>
Adam Tkac8c048382010-09-02 12:37:00 +000031#include <rfb/CSecurityPlain.h>
Adam Tkac1d15e2d2010-04-23 14:06:38 +000032#include <rdr/Exception.h>
33#include <rfb/LogWriter.h>
Adam Tkacb6eb3992010-04-23 14:05:00 +000034#include <rfb/Security.h>
Adam Tkac1d15e2d2010-04-23 14:06:38 +000035#include <rfb/SSecurityNone.h>
Adam Tkac707d3612010-07-20 15:16:10 +000036#include <rfb/SSecurityStack.h>
Adam Tkac520fc412010-09-02 14:13:24 +000037#include <rfb/SSecurityPlain.h>
Adam Tkac1d15e2d2010-04-23 14:06:38 +000038#include <rfb/SSecurityVncAuth.h>
Adam Tkacdfe19cf2010-04-23 14:14:11 +000039#include <rfb/SSecurityVeNCrypt.h>
Adam Tkac707d3612010-07-20 15:16:10 +000040#ifdef HAVE_GNUTLS
Adam Tkac3c5be392010-07-21 09:27:34 +000041#include <rfb/CSecurityTLS.h>
Adam Tkac21b61a52010-07-21 09:19:00 +000042#include <rfb/SSecurityTLS.h>
Adam Tkacdf799702010-04-28 15:45:53 +000043#endif
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +000044#include <rfb/util.h>
45
Adam Tkac1d15e2d2010-04-23 14:06:38 +000046using namespace rdr;
47using namespace rfb;
48using namespace std;
49
50static LogWriter vlog("Security");
51
Pierre Ossman27eb55e2015-01-29 13:31:06 +010052#ifdef HAVE_GNUTLS
53StringParameter Security::GnuTLSPriority("GnuTLSPriority",
54 "GnuTLS priority string that controls the TLS session’s handshake algorithms",
55 "NORMAL");
56#endif
57
Pierre Ossmane5fe0702011-05-16 12:46:16 +000058Security::Security()
59{
60}
61
Adam Tkacbfd66c12010-10-01 08:33:29 +000062Security::Security(StringParameter &secTypes)
Adam Tkac1d15e2d2010-04-23 14:06:38 +000063{
Adam Tkacfb993152010-08-12 14:17:28 +000064 char *secTypesStr;
65
Adam Tkacbfd66c12010-10-01 08:33:29 +000066 secTypesStr = secTypes.getData();
Adam Tkac1d15e2d2010-04-23 14:06:38 +000067 enabledSecTypes = parseSecTypes(secTypesStr);
68
Pierre Ossman5e04c262011-11-09 11:31:12 +000069 delete [] secTypesStr;
Adam Tkac1d15e2d2010-04-23 14:06:38 +000070}
71
Adam Tkac0c77e512010-07-20 15:10:16 +000072const std::list<rdr::U8> Security::GetEnabledSecTypes(void)
Adam Tkac1d15e2d2010-04-23 14:06:38 +000073{
Adam Tkac0c77e512010-07-20 15:10:16 +000074 list<rdr::U8> result;
75 list<U32>::iterator i;
76
Pierre Ossman1f8aba32015-12-29 15:02:11 +010077 /* Partial workaround for Vino's stupid behaviour. It doesn't allow
78 * the basic authentication types as part of the VeNCrypt handshake,
79 * making it impossible for a client to do opportunistic encryption.
80 * At least make it possible to connect when encryption is explicitly
81 * disabled. */
82 for (i = enabledSecTypes.begin(); i != enabledSecTypes.end(); i++) {
83 if (*i >= 0x100) {
84 result.push_back(secTypeVeNCrypt);
85 break;
86 }
87 }
88
Adam Tkac0c77e512010-07-20 15:10:16 +000089 for (i = enabledSecTypes.begin(); i != enabledSecTypes.end(); i++)
90 if (*i < 0x100)
91 result.push_back(*i);
92
93 return result;
94}
95
96const std::list<rdr::U32> Security::GetEnabledExtSecTypes(void)
97{
98 list<rdr::U32> result;
99 list<U32>::iterator i;
100
101 for (i = enabledSecTypes.begin(); i != enabledSecTypes.end(); i++)
Adam Tkac95e2fe82010-08-12 13:54:59 +0000102 if (*i != secTypeVeNCrypt) /* Do not include VeNCrypt type to avoid loops */
Adam Tkac0c77e512010-07-20 15:10:16 +0000103 result.push_back(*i);
104
105 return result;
106}
107
108void Security::EnableSecType(U32 secType)
109{
110 list<U32>::iterator i;
Adam Tkac1d15e2d2010-04-23 14:06:38 +0000111
112 for (i = enabledSecTypes.begin(); i != enabledSecTypes.end(); i++)
113 if (*i == secType)
114 return;
115
116 enabledSecTypes.push_back(secType);
117}
118
Adam Tkac0c77e512010-07-20 15:10:16 +0000119bool Security::IsSupported(U32 secType)
Adam Tkac1d15e2d2010-04-23 14:06:38 +0000120{
Adam Tkac0c77e512010-07-20 15:10:16 +0000121 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 true;
DRC674bf062011-02-21 13:14:16 +0000126 if (secType == secTypeVeNCrypt)
127 return true;
Adam Tkac1d15e2d2010-04-23 14:06:38 +0000128
129 return false;
130}
131
Adam Tkaca9a7b4b2011-02-01 14:34:55 +0000132char *Security::ToString(void)
133{
134 list<U32>::iterator i;
135 static char out[128]; /* Should be enough */
136 bool firstpass = true;
137 const char *name;
138
139 memset(out, 0, sizeof(out));
140
141 for (i = enabledSecTypes.begin(); i != enabledSecTypes.end(); i++) {
142 name = secTypeName(*i);
143 if (name[0] == '[') /* Unknown security type */
144 continue;
145
146 if (!firstpass)
147 strncat(out, ",", sizeof(out) - 1);
148 else
149 firstpass = false;
150 strncat(out, name, sizeof(out) - 1);
151 }
152
153 return out;
154}
155
Adam Tkac0c77e512010-07-20 15:10:16 +0000156rdr::U32 rfb::secTypeNum(const char* name)
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +0000157{
158 if (strcasecmp(name, "None") == 0) return secTypeNone;
159 if (strcasecmp(name, "VncAuth") == 0) return secTypeVncAuth;
160 if (strcasecmp(name, "Tight") == 0) return secTypeTight;
161 if (strcasecmp(name, "RA2") == 0) return secTypeRA2;
162 if (strcasecmp(name, "RA2ne") == 0) return secTypeRA2ne;
163 if (strcasecmp(name, "SSPI") == 0) return secTypeSSPI;
Adam Tkacdfe19cf2010-04-23 14:14:11 +0000164 if (strcasecmp(name, "SSPIne") == 0) return secTypeSSPIne;
165 if (strcasecmp(name, "VeNCrypt") == 0) return secTypeVeNCrypt;
Adam Tkacb3e60c62010-07-20 15:10:59 +0000166
167 /* VeNCrypt subtypes */
Adam Tkac957a5ae2010-07-20 15:12:41 +0000168 if (strcasecmp(name, "Plain") == 0) return secTypePlain;
Adam Tkacb3e60c62010-07-20 15:10:59 +0000169 if (strcasecmp(name, "TLSNone") == 0) return secTypeTLSNone;
170 if (strcasecmp(name, "TLSVnc") == 0) return secTypeTLSVnc;
Adam Tkac957a5ae2010-07-20 15:12:41 +0000171 if (strcasecmp(name, "TLSPlain") == 0) return secTypeTLSPlain;
Adam Tkacb3e60c62010-07-20 15:10:59 +0000172 if (strcasecmp(name, "X509None") == 0) return secTypeX509None;
173 if (strcasecmp(name, "X509Vnc") == 0) return secTypeX509Vnc;
Adam Tkacb3e60c62010-07-20 15:10:59 +0000174 if (strcasecmp(name, "X509Plain") == 0) return secTypeX509Plain;
Adam Tkacb3e60c62010-07-20 15:10:59 +0000175
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +0000176 return secTypeInvalid;
177}
178
Adam Tkac0c77e512010-07-20 15:10:16 +0000179const char* rfb::secTypeName(rdr::U32 num)
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +0000180{
181 switch (num) {
182 case secTypeNone: return "None";
183 case secTypeVncAuth: return "VncAuth";
184 case secTypeTight: return "Tight";
185 case secTypeRA2: return "RA2";
186 case secTypeRA2ne: return "RA2ne";
187 case secTypeSSPI: return "SSPI";
188 case secTypeSSPIne: return "SSPIne";
Adam Tkacdfe19cf2010-04-23 14:14:11 +0000189 case secTypeVeNCrypt: return "VeNCrypt";
Adam Tkacb3e60c62010-07-20 15:10:59 +0000190
191 /* VeNCrypt subtypes */
Adam Tkac957a5ae2010-07-20 15:12:41 +0000192 case secTypePlain: return "Plain";
Adam Tkacb3e60c62010-07-20 15:10:59 +0000193 case secTypeTLSNone: return "TLSNone";
194 case secTypeTLSVnc: return "TLSVnc";
Adam Tkacb3e60c62010-07-20 15:10:59 +0000195 case secTypeTLSPlain: return "TLSPlain";
196 case secTypeX509None: return "X509None";
197 case secTypeX509Vnc: return "X509Vnc";
198 case secTypeX509Plain: return "X509Plain";
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +0000199 default: return "[unknown secType]";
200 }
201}
202
Adam Tkac0c77e512010-07-20 15:10:16 +0000203std::list<rdr::U32> rfb::parseSecTypes(const char* types_)
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +0000204{
Adam Tkac0c77e512010-07-20 15:10:16 +0000205 std::list<rdr::U32> result;
Adam Tkacd36b6262009-09-04 10:57:20 +0000206 CharArray types(strDup(types_)), type;
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +0000207 while (types.buf) {
208 strSplit(types.buf, ',', &type.buf, &types.buf);
Adam Tkac0c77e512010-07-20 15:10:16 +0000209 rdr::U32 typeNum = secTypeNum(type.buf);
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +0000210 if (typeNum != secTypeInvalid)
211 result.push_back(typeNum);
212 }
213 return result;
214}