您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

SConnection.cxx 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
  2. *
  3. * This is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation; either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This software is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this software; if not, write to the Free Software
  15. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  16. * USA.
  17. */
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include <rfb/Exception.h>
  21. #include <rfb/secTypes.h>
  22. #include <rfb/msgTypes.h>
  23. #include <rfb/CapsList.h>
  24. #include <rfb/SMsgReaderV3.h>
  25. #include <rfb/SMsgWriterV3.h>
  26. #include <rfb/SConnection.h>
  27. #include <rfb/ServerCore.h>
  28. #include <rfb/LogWriter.h>
  29. using namespace rfb;
  30. static LogWriter vlog("SConnection");
  31. // AccessRights values
  32. const SConnection::AccessRights SConnection::AccessView = 0x0001;
  33. const SConnection::AccessRights SConnection::AccessKeyEvents = 0x0002;
  34. const SConnection::AccessRights SConnection::AccessPtrEvents = 0x0004;
  35. const SConnection::AccessRights SConnection::AccessCutText = 0x0008;
  36. const SConnection::AccessRights SConnection::AccessDefault = 0x03ff;
  37. const SConnection::AccessRights SConnection::AccessNoQuery = 0x0400;
  38. const SConnection::AccessRights SConnection::AccessFull = 0xffff;
  39. SConnection::SConnection(SSecurityFactory* secFact, bool reverseConnection_)
  40. : readyForSetColourMapEntries(false),
  41. is(0), os(0), reader_(0), writer_(0),
  42. security(0), securityFactory(secFact), state_(RFBSTATE_UNINITIALISED),
  43. reverseConnection(reverseConnection_)
  44. {
  45. defaultMajorVersion = 3;
  46. defaultMinorVersion = 8;
  47. if (rfb::Server::protocol3_3)
  48. defaultMinorVersion = 3;
  49. cp.setVersion(defaultMajorVersion, defaultMinorVersion);
  50. }
  51. SConnection::~SConnection()
  52. {
  53. if (security) security->destroy();
  54. deleteReaderAndWriter();
  55. }
  56. void SConnection::deleteReaderAndWriter()
  57. {
  58. delete reader_;
  59. reader_ = 0;
  60. delete writer_;
  61. writer_ = 0;
  62. }
  63. void SConnection::setStreams(rdr::InStream* is_, rdr::OutStream* os_)
  64. {
  65. is = is_;
  66. os = os_;
  67. }
  68. void SConnection::initialiseProtocol()
  69. {
  70. cp.writeVersion(os);
  71. state_ = RFBSTATE_PROTOCOL_VERSION;
  72. }
  73. void SConnection::processMsg()
  74. {
  75. switch (state_) {
  76. case RFBSTATE_PROTOCOL_VERSION: processVersionMsg(); break;
  77. case RFBSTATE_SECURITY_TYPE: processSecurityTypeMsg(); break;
  78. case RFBSTATE_TIGHT_TUNN_TYPE: processTunnelTypeMsg(); break;
  79. case RFBSTATE_TIGHT_AUTH_TYPE: processAuthTypeMsg(); break;
  80. case RFBSTATE_SECURITY: processSecurityMsg(); break;
  81. case RFBSTATE_INITIALISATION: processInitMsg(); break;
  82. case RFBSTATE_NORMAL: reader_->readMsg(); break;
  83. case RFBSTATE_QUERYING:
  84. throw Exception("SConnection::processMsg: bogus data from client while "
  85. "querying");
  86. case RFBSTATE_UNINITIALISED:
  87. throw Exception("SConnection::processMsg: not initialised yet?");
  88. default:
  89. throw Exception("SConnection::processMsg: invalid state");
  90. }
  91. }
  92. void SConnection::processVersionMsg()
  93. {
  94. vlog.debug("reading protocol version");
  95. bool done;
  96. if (!cp.readVersion(is, &done)) {
  97. state_ = RFBSTATE_INVALID;
  98. throw Exception("reading version failed: not an RFB client?");
  99. }
  100. if (!done) return;
  101. vlog.info("Client needs protocol version %d.%d",
  102. cp.majorVersion, cp.minorVersion);
  103. if (cp.majorVersion != 3) {
  104. // unknown protocol version
  105. char msg[256];
  106. sprintf(msg,"Error: client needs protocol version %d.%d, server has %d.%d",
  107. cp.majorVersion, cp.minorVersion,
  108. defaultMajorVersion, defaultMinorVersion);
  109. throwConnFailedException(msg);
  110. }
  111. if (cp.minorVersion != 3 && cp.minorVersion != 7 && cp.minorVersion != 8) {
  112. vlog.error("Client uses unofficial protocol version %d.%d",
  113. cp.majorVersion,cp.minorVersion);
  114. if (cp.minorVersion >= 8)
  115. cp.minorVersion = 8;
  116. else if (cp.minorVersion == 7)
  117. cp.minorVersion = 7;
  118. else
  119. cp.minorVersion = 3;
  120. vlog.error("Assuming compatibility with version %d.%d",
  121. cp.majorVersion,cp.minorVersion);
  122. }
  123. versionReceived();
  124. std::list<rdr::U8> secTypes;
  125. std::list<rdr::U8>::iterator i;
  126. securityFactory->getSecTypes(&secTypes, reverseConnection);
  127. if (cp.isVersion(3,3)) {
  128. // cope with legacy 3.3 client only if "no authentication" or "vnc
  129. // authentication" is supported.
  130. for (i=secTypes.begin(); i!=secTypes.end(); i++) {
  131. if (*i == secTypeNone || *i == secTypeVncAuth) break;
  132. }
  133. if (i == secTypes.end()) {
  134. char msg[256];
  135. sprintf(msg,"No supported security type for %d.%d client",
  136. cp.majorVersion, cp.minorVersion);
  137. throwConnFailedException(msg);
  138. }
  139. os->writeU32(*i);
  140. if (*i == secTypeNone) os->flush();
  141. state_ = RFBSTATE_SECURITY;
  142. security = securityFactory->getSSecurity(*i, reverseConnection);
  143. processSecurityMsg();
  144. return;
  145. }
  146. // Add a special security type to advertise TightVNC protocol extensions.
  147. secTypes.push_back(secTypeTight);
  148. // list supported security types for >=3.7 clients
  149. if (secTypes.empty())
  150. throwConnFailedException("No supported security types");
  151. os->writeU8(secTypes.size());
  152. for (i=secTypes.begin(); i!=secTypes.end(); i++)
  153. os->writeU8(*i);
  154. os->flush();
  155. state_ = RFBSTATE_SECURITY_TYPE;
  156. }
  157. void SConnection::processSecurityTypeMsg()
  158. {
  159. vlog.debug("processing security type message");
  160. int secType = is->readU8();
  161. if (secType == secTypeTight) {
  162. vlog.info("Enabling TightVNC protocol extensions");
  163. cp.tightExtensionsEnabled = true;
  164. offerTunneling();
  165. } else {
  166. processSecurityType(secType);
  167. }
  168. }
  169. //
  170. // TightVNC-specific protocol initialization (tunneling, authentication)
  171. //
  172. void SConnection::offerTunneling()
  173. {
  174. vlog.debug("offering list of tunneling methods");
  175. int nTypes = 0;
  176. // Advertise our tunneling capabilities (currently, nothing to advertise).
  177. os->writeU32(nTypes);
  178. os->flush();
  179. if (nTypes) {
  180. // NOTE: Never executed in current version.
  181. state_ = RFBSTATE_TIGHT_TUNN_TYPE;
  182. } else {
  183. offerAuthentication();
  184. }
  185. }
  186. // NOTE: This function is never called in current version.
  187. void SConnection::processTunnelTypeMsg()
  188. {
  189. vlog.debug("processing tunneling type message (TightVNC extension)");
  190. int tunnelType = is->readU32();
  191. vlog.error("unsupported tunneling type %d requested, ignoring", tunnelType);
  192. offerAuthentication();
  193. }
  194. void SConnection::offerAuthentication()
  195. {
  196. vlog.debug("offering list of authentication methods");
  197. // See processVersionMsg(), the code below is similar.
  198. std::list<rdr::U8> secTypes;
  199. std::list<rdr::U8>::iterator i;
  200. // NOTE: In addition to standard security types, we might want to offer
  201. // TightVNC-specific authentication types. But currently we support
  202. // only the standard security types: secTypeNone and secTypeVncAuth.
  203. securityFactory->getSecTypes(&secTypes, reverseConnection);
  204. CapsList caps;
  205. for (i = secTypes.begin(); i != secTypes.end(); i++) {
  206. // FIXME: Capability info should be provided by SSecurity objects.
  207. switch (*i) {
  208. case secTypeNone: caps.addStandard(*i, "NOAUTH__"); break;
  209. case secTypeVncAuth: caps.addStandard(*i, "VNCAUTH_"); break;
  210. default:
  211. // This should not ever happen.
  212. vlog.error("not offering unknown security type %d", (int)*i);
  213. }
  214. }
  215. if (caps.getSize() < 1)
  216. throwConnFailedException("No supported security types");
  217. if (caps.includesOnly(secTypeNone)) {
  218. // Special case - if caps includes nothing else than secTypeNone, we send
  219. // an empty capability list and do not expect security type selection from
  220. // the client. Then, continue the protocol like if the client has selected
  221. // secTypeNone (starting at base protocol version 3.8, "security result"
  222. // will follow).
  223. os->writeU32(0);
  224. os->flush();
  225. processSecurityType(secTypeNone);
  226. } else {
  227. // Normal case - sending the list of authentication capabilities.
  228. os->writeU32(caps.getSize());
  229. caps.write(os);
  230. os->flush();
  231. state_ = RFBSTATE_TIGHT_AUTH_TYPE;
  232. }
  233. }
  234. void SConnection::processAuthTypeMsg()
  235. {
  236. vlog.debug("processing authentication type message (TightVNC extension)");
  237. // NOTE: Currently, we support only the standard security types, so we
  238. // just pass TightVNC authentication type for standard processing,
  239. // just as it was usual RFB security type.
  240. int secType = is->readU32();
  241. processSecurityType(secType);
  242. }
  243. //
  244. // End of TightVNC-specific code
  245. //
  246. void SConnection::processSecurityType(int secType)
  247. {
  248. // Verify that the requested security type should be offered
  249. std::list<rdr::U8> secTypes;
  250. std::list<rdr::U8>::iterator i;
  251. securityFactory->getSecTypes(&secTypes, reverseConnection);
  252. for (i=secTypes.begin(); i!=secTypes.end(); i++)
  253. if (*i == secType) break;
  254. if (i == secTypes.end())
  255. throw Exception("Requested security type not available");
  256. vlog.info("Client requests security type %s(%d)",
  257. secTypeName(secType),secType);
  258. try {
  259. state_ = RFBSTATE_SECURITY;
  260. security = securityFactory->getSSecurity(secType, reverseConnection);
  261. } catch (rdr::Exception& e) {
  262. throwConnFailedException(e.str());
  263. }
  264. processSecurityMsg();
  265. }
  266. void SConnection::processSecurityMsg()
  267. {
  268. vlog.debug("processing security message");
  269. try {
  270. bool done = security->processMsg(this);
  271. if (done) {
  272. state_ = RFBSTATE_QUERYING;
  273. queryConnection(security->getUserName());
  274. }
  275. } catch (AuthFailureException& e) {
  276. vlog.error("AuthFailureException: %s", e.str());
  277. os->writeU32(secResultFailed);
  278. if (!cp.beforeVersion(3,8)) // 3.8 onwards have failure message
  279. os->writeString(e.str());
  280. os->flush();
  281. throw;
  282. }
  283. }
  284. void SConnection::processInitMsg()
  285. {
  286. vlog.debug("reading client initialisation");
  287. reader_->readClientInit();
  288. }
  289. void SConnection::throwConnFailedException(const char* msg)
  290. {
  291. vlog.info(msg);
  292. if (state_ == RFBSTATE_PROTOCOL_VERSION) {
  293. if (cp.majorVersion == 3 && cp.minorVersion == 3) {
  294. os->writeU32(0);
  295. os->writeString(msg);
  296. os->flush();
  297. } else {
  298. os->writeU8(0);
  299. os->writeString(msg);
  300. os->flush();
  301. }
  302. }
  303. state_ = RFBSTATE_INVALID;
  304. throw ConnFailedException(msg);
  305. }
  306. void SConnection::writeConnFailedFromScratch(const char* msg,
  307. rdr::OutStream* os)
  308. {
  309. os->writeBytes("RFB 003.003\n", 12);
  310. os->writeU32(0);
  311. os->writeString(msg);
  312. os->flush();
  313. }
  314. void SConnection::versionReceived()
  315. {
  316. }
  317. void SConnection::authSuccess()
  318. {
  319. }
  320. void SConnection::queryConnection(const char* userName)
  321. {
  322. approveConnection(true);
  323. }
  324. void SConnection::approveConnection(bool accept, const char* reason)
  325. {
  326. if (state_ != RFBSTATE_QUERYING)
  327. throw Exception("SConnection::approveConnection: invalid state");
  328. if (!reason) reason = "Authentication failure";
  329. if (!cp.beforeVersion(3,8) || security->getType() != secTypeNone) {
  330. if (accept) {
  331. os->writeU32(secResultOK);
  332. } else {
  333. os->writeU32(secResultFailed);
  334. if (!cp.beforeVersion(3,8)) // 3.8 onwards have failure message
  335. os->writeString(reason);
  336. }
  337. os->flush();
  338. }
  339. if (accept) {
  340. state_ = RFBSTATE_INITIALISATION;
  341. reader_ = new SMsgReaderV3(this, is);
  342. writer_ = new SMsgWriterV3(&cp, os);
  343. authSuccess();
  344. } else {
  345. state_ = RFBSTATE_INVALID;
  346. throw AuthFailureException(reason);
  347. }
  348. }
  349. void SConnection::setInitialColourMap()
  350. {
  351. }
  352. void SConnection::clientInit(bool shared)
  353. {
  354. writer_->writeServerInit();
  355. // FIXME: Send interaction capabilities via writer_?
  356. if (cp.tightExtensionsEnabled)
  357. sendInteractionCaps();
  358. state_ = RFBSTATE_NORMAL;
  359. }
  360. // FIXME: Move sendInteractionCaps() to a class derived from SMsgWriterV3?
  361. void SConnection::sendInteractionCaps()
  362. {
  363. //
  364. // Advertise support for non-standard server-to-client messages
  365. //
  366. CapsList scaps;
  367. //
  368. // Advertise support for non-standard client-to-server messages
  369. //
  370. CapsList ccaps;
  371. //
  372. // Advertise all supported encoding types (except raw encoding).
  373. //
  374. CapsList ecaps;
  375. // First, add true encodings.
  376. for (int i = 1; i <= encodingMax; i++) {
  377. if (Encoder::supported(i)) {
  378. // FIXME: Capability info should be provided by Encoder objects.
  379. switch (i) {
  380. case encodingRRE: ecaps.addStandard(i, "RRE_____"); break;
  381. case encodingCoRRE: ecaps.addStandard(i, "CORRE___"); break;
  382. case encodingHextile: ecaps.addStandard(i, "HEXTILE_"); break;
  383. case encodingZRLE: ecaps.addStandard(i, "ZRLE____"); break;
  384. case encodingTight: ecaps.addTightExt(i, "TIGHT___"); break;
  385. default:
  386. // This should not ever happen.
  387. vlog.error("not advertising unknown encoding type %d", (int)i);
  388. }
  389. }
  390. }
  391. // CopyRect is special - Encoder::supported() returns 0 for it,
  392. // that's why we add it here explicitly.
  393. ecaps.addStandard(encodingCopyRect, "COPYRECT");
  394. // Add supported pseudo encodings as well.
  395. ecaps.addTightExt(pseudoEncodingCompressLevel0, "COMPRLVL");
  396. ecaps.addTightExt(pseudoEncodingQualityLevel0, "JPEGQLVL");
  397. ecaps.addTightExt(pseudoEncodingXCursor, "X11CURSR");
  398. ecaps.addTightExt(pseudoEncodingCursor, "RCHCURSR");
  399. ecaps.addTightExt(pseudoEncodingLastRect, "LASTRECT");
  400. ecaps.addStandard(pseudoEncodingDesktopSize, "NEWFBSIZ");
  401. os->writeU16(scaps.getSize());
  402. os->writeU16(ccaps.getSize());
  403. os->writeU16(ecaps.getSize());
  404. os->writeU16(0);
  405. if (scaps.getSize())
  406. scaps.write(os);
  407. if (ccaps.getSize())
  408. ccaps.write(os);
  409. if (ecaps.getSize())
  410. ecaps.write(os);
  411. os->flush();
  412. }
  413. void SConnection::setPixelFormat(const PixelFormat& pf)
  414. {
  415. SMsgHandler::setPixelFormat(pf);
  416. readyForSetColourMapEntries = true;
  417. }
  418. void SConnection::framebufferUpdateRequest(const Rect& r, bool incremental)
  419. {
  420. if (!readyForSetColourMapEntries) {
  421. readyForSetColourMapEntries = true;
  422. if (!cp.pf().trueColour) {
  423. setInitialColourMap();
  424. }
  425. }
  426. }