Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

SConnection.cxx 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
  2. * Copyright 2011 Pierre Ossman for Cendio AB
  3. *
  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. */
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include <rfb/Exception.h>
  22. #include <rfb/Security.h>
  23. #include <rfb/msgTypes.h>
  24. #include <rfb/fenceTypes.h>
  25. #include <rfb/SMsgReader.h>
  26. #include <rfb/SMsgWriter.h>
  27. #include <rfb/SConnection.h>
  28. #include <rfb/ServerCore.h>
  29. #include <rfb/encodings.h>
  30. #include <rfb/EncodeManager.h>
  31. #include <rfb/SSecurity.h>
  32. #include <rfb/LogWriter.h>
  33. using namespace rfb;
  34. static LogWriter vlog("SConnection");
  35. // AccessRights values
  36. const SConnection::AccessRights SConnection::AccessView = 0x0001;
  37. const SConnection::AccessRights SConnection::AccessKeyEvents = 0x0002;
  38. const SConnection::AccessRights SConnection::AccessPtrEvents = 0x0004;
  39. const SConnection::AccessRights SConnection::AccessCutText = 0x0008;
  40. const SConnection::AccessRights SConnection::AccessSetDesktopSize = 0x0010;
  41. const SConnection::AccessRights SConnection::AccessDefault = 0x03ff;
  42. const SConnection::AccessRights SConnection::AccessNoQuery = 0x0400;
  43. const SConnection::AccessRights SConnection::AccessFull = 0xffff;
  44. SConnection::SConnection(bool reverseConnection_)
  45. : readyForSetColourMapEntries(false),
  46. is(0), os(0), reader_(0), writer_(0),
  47. security(0), ssecurity(0), state_(RFBSTATE_UNINITIALISED),
  48. reverseConnection(reverseConnection_),
  49. preferredEncoding(encodingRaw)
  50. {
  51. defaultMajorVersion = 3;
  52. defaultMinorVersion = 8;
  53. if (rfb::Server::protocol3_3)
  54. defaultMinorVersion = 3;
  55. cp.setVersion(defaultMajorVersion, defaultMinorVersion);
  56. security = new SecurityServer();
  57. }
  58. SConnection::~SConnection()
  59. {
  60. if (ssecurity) ssecurity->destroy();
  61. deleteReaderAndWriter();
  62. }
  63. void SConnection::deleteReaderAndWriter()
  64. {
  65. delete reader_;
  66. reader_ = 0;
  67. delete writer_;
  68. writer_ = 0;
  69. }
  70. void SConnection::setStreams(rdr::InStream* is_, rdr::OutStream* os_)
  71. {
  72. is = is_;
  73. os = os_;
  74. }
  75. void SConnection::initialiseProtocol()
  76. {
  77. cp.writeVersion(os);
  78. state_ = RFBSTATE_PROTOCOL_VERSION;
  79. }
  80. void SConnection::processMsg()
  81. {
  82. switch (state_) {
  83. case RFBSTATE_PROTOCOL_VERSION: processVersionMsg(); break;
  84. case RFBSTATE_SECURITY_TYPE: processSecurityTypeMsg(); break;
  85. case RFBSTATE_SECURITY: processSecurityMsg(); break;
  86. case RFBSTATE_INITIALISATION: processInitMsg(); break;
  87. case RFBSTATE_NORMAL: reader_->readMsg(); break;
  88. case RFBSTATE_QUERYING:
  89. throw Exception("SConnection::processMsg: bogus data from client while "
  90. "querying");
  91. case RFBSTATE_UNINITIALISED:
  92. throw Exception("SConnection::processMsg: not initialised yet?");
  93. default:
  94. throw Exception("SConnection::processMsg: invalid state");
  95. }
  96. }
  97. void SConnection::processVersionMsg()
  98. {
  99. vlog.debug("reading protocol version");
  100. bool done;
  101. if (!cp.readVersion(is, &done)) {
  102. state_ = RFBSTATE_INVALID;
  103. throw Exception("reading version failed: not an RFB client?");
  104. }
  105. if (!done) return;
  106. vlog.info("Client needs protocol version %d.%d",
  107. cp.majorVersion, cp.minorVersion);
  108. if (cp.majorVersion != 3) {
  109. // unknown protocol version
  110. char msg[256];
  111. sprintf(msg,"Error: client needs protocol version %d.%d, server has %d.%d",
  112. cp.majorVersion, cp.minorVersion,
  113. defaultMajorVersion, defaultMinorVersion);
  114. throwConnFailedException(msg);
  115. }
  116. if (cp.minorVersion != 3 && cp.minorVersion != 7 && cp.minorVersion != 8) {
  117. vlog.error("Client uses unofficial protocol version %d.%d",
  118. cp.majorVersion,cp.minorVersion);
  119. if (cp.minorVersion >= 8)
  120. cp.minorVersion = 8;
  121. else if (cp.minorVersion == 7)
  122. cp.minorVersion = 7;
  123. else
  124. cp.minorVersion = 3;
  125. vlog.error("Assuming compatibility with version %d.%d",
  126. cp.majorVersion,cp.minorVersion);
  127. }
  128. versionReceived();
  129. std::list<rdr::U8> secTypes;
  130. std::list<rdr::U8>::iterator i;
  131. secTypes = security->GetEnabledSecTypes();
  132. if (cp.isVersion(3,3)) {
  133. // cope with legacy 3.3 client only if "no authentication" or "vnc
  134. // authentication" is supported.
  135. for (i=secTypes.begin(); i!=secTypes.end(); i++) {
  136. if (*i == secTypeNone || *i == secTypeVncAuth) break;
  137. }
  138. if (i == secTypes.end()) {
  139. char msg[256];
  140. sprintf(msg,"No supported security type for %d.%d client",
  141. cp.majorVersion, cp.minorVersion);
  142. throwConnFailedException(msg);
  143. }
  144. os->writeU32(*i);
  145. if (*i == secTypeNone) os->flush();
  146. state_ = RFBSTATE_SECURITY;
  147. ssecurity = security->GetSSecurity(*i);
  148. processSecurityMsg();
  149. return;
  150. }
  151. // list supported security types for >=3.7 clients
  152. if (secTypes.empty())
  153. throwConnFailedException("No supported security types");
  154. os->writeU8(secTypes.size());
  155. for (i=secTypes.begin(); i!=secTypes.end(); i++)
  156. os->writeU8(*i);
  157. os->flush();
  158. state_ = RFBSTATE_SECURITY_TYPE;
  159. }
  160. void SConnection::processSecurityTypeMsg()
  161. {
  162. vlog.debug("processing security type message");
  163. int secType = is->readU8();
  164. processSecurityType(secType);
  165. }
  166. void SConnection::processSecurityType(int secType)
  167. {
  168. // Verify that the requested security type should be offered
  169. std::list<rdr::U8> secTypes;
  170. std::list<rdr::U8>::iterator i;
  171. secTypes = security->GetEnabledSecTypes();
  172. for (i=secTypes.begin(); i!=secTypes.end(); i++)
  173. if (*i == secType) break;
  174. if (i == secTypes.end())
  175. throw Exception("Requested security type not available");
  176. vlog.info("Client requests security type %s(%d)",
  177. secTypeName(secType),secType);
  178. try {
  179. state_ = RFBSTATE_SECURITY;
  180. ssecurity = security->GetSSecurity(secType);
  181. } catch (rdr::Exception& e) {
  182. throwConnFailedException(e.str());
  183. }
  184. processSecurityMsg();
  185. }
  186. void SConnection::processSecurityMsg()
  187. {
  188. vlog.debug("processing security message");
  189. try {
  190. bool done = ssecurity->processMsg(this);
  191. if (done) {
  192. state_ = RFBSTATE_QUERYING;
  193. queryConnection(ssecurity->getUserName());
  194. setAccessRights(ssecurity->getAccessRights());
  195. }
  196. } catch (AuthFailureException& e) {
  197. vlog.error("AuthFailureException: %s", e.str());
  198. os->writeU32(secResultFailed);
  199. if (!cp.beforeVersion(3,8)) // 3.8 onwards have failure message
  200. os->writeString(e.str());
  201. os->flush();
  202. throw;
  203. }
  204. }
  205. void SConnection::processInitMsg()
  206. {
  207. vlog.debug("reading client initialisation");
  208. reader_->readClientInit();
  209. }
  210. void SConnection::throwConnFailedException(const char* msg)
  211. {
  212. vlog.info("%s", msg);
  213. if (state_ == RFBSTATE_PROTOCOL_VERSION) {
  214. if (cp.majorVersion == 3 && cp.minorVersion == 3) {
  215. os->writeU32(0);
  216. os->writeString(msg);
  217. os->flush();
  218. } else {
  219. os->writeU8(0);
  220. os->writeString(msg);
  221. os->flush();
  222. }
  223. }
  224. state_ = RFBSTATE_INVALID;
  225. throw ConnFailedException(msg);
  226. }
  227. void SConnection::writeConnFailedFromScratch(const char* msg,
  228. rdr::OutStream* os)
  229. {
  230. os->writeBytes("RFB 003.003\n", 12);
  231. os->writeU32(0);
  232. os->writeString(msg);
  233. os->flush();
  234. }
  235. void SConnection::setEncodings(int nEncodings, rdr::S32* encodings)
  236. {
  237. int i;
  238. preferredEncoding = encodingRaw;
  239. for (i = 0;i < nEncodings;i++) {
  240. if (EncodeManager::supported(encodings[i])) {
  241. preferredEncoding = encodings[i];
  242. break;
  243. }
  244. }
  245. SMsgHandler::setEncodings(nEncodings, encodings);
  246. }
  247. void SConnection::versionReceived()
  248. {
  249. }
  250. void SConnection::authSuccess()
  251. {
  252. }
  253. void SConnection::queryConnection(const char* userName)
  254. {
  255. approveConnection(true);
  256. }
  257. void SConnection::approveConnection(bool accept, const char* reason)
  258. {
  259. if (state_ != RFBSTATE_QUERYING)
  260. throw Exception("SConnection::approveConnection: invalid state");
  261. if (!reason) reason = "Authentication failure";
  262. if (!cp.beforeVersion(3,8) || ssecurity->getType() != secTypeNone) {
  263. if (accept) {
  264. os->writeU32(secResultOK);
  265. } else {
  266. os->writeU32(secResultFailed);
  267. if (!cp.beforeVersion(3,8)) // 3.8 onwards have failure message
  268. os->writeString(reason);
  269. }
  270. os->flush();
  271. }
  272. if (accept) {
  273. state_ = RFBSTATE_INITIALISATION;
  274. reader_ = new SMsgReader(this, is);
  275. writer_ = new SMsgWriter(&cp, os);
  276. authSuccess();
  277. } else {
  278. state_ = RFBSTATE_INVALID;
  279. throw AuthFailureException(reason);
  280. }
  281. }
  282. void SConnection::clientInit(bool shared)
  283. {
  284. writer_->writeServerInit();
  285. state_ = RFBSTATE_NORMAL;
  286. }
  287. void SConnection::setPixelFormat(const PixelFormat& pf)
  288. {
  289. SMsgHandler::setPixelFormat(pf);
  290. readyForSetColourMapEntries = true;
  291. if (!pf.trueColour)
  292. writeFakeColourMap();
  293. }
  294. void SConnection::framebufferUpdateRequest(const Rect& r, bool incremental)
  295. {
  296. if (!readyForSetColourMapEntries) {
  297. readyForSetColourMapEntries = true;
  298. if (!cp.pf().trueColour) {
  299. writeFakeColourMap();
  300. }
  301. }
  302. }
  303. void SConnection::fence(rdr::U32 flags, unsigned len, const char data[])
  304. {
  305. if (!(flags & fenceFlagRequest))
  306. return;
  307. // We cannot guarantee any synchronisation at this level
  308. flags = 0;
  309. writer()->writeFence(flags, len, data);
  310. }
  311. void SConnection::enableContinuousUpdates(bool enable,
  312. int x, int y, int w, int h)
  313. {
  314. }
  315. void SConnection::writeFakeColourMap(void)
  316. {
  317. int i;
  318. rdr::U16 red[256], green[256], blue[256];
  319. for (i = 0;i < 256;i++)
  320. cp.pf().rgbFromPixel(i, &red[i], &green[i], &blue[i]);
  321. writer()->writeSetColourMapEntries(0, 256, red, green, blue);
  322. }