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.

CConnection.cxx 7.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  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/CMsgReaderV3.h>
  22. #include <rfb/CMsgWriterV3.h>
  23. #include <rfb/CSecurity.h>
  24. #include <rfb/Security.h>
  25. #include <rfb/CConnection.h>
  26. #include <rfb/util.h>
  27. #include <rfb/LogWriter.h>
  28. using namespace rfb;
  29. static LogWriter vlog("CConnection");
  30. CConnection::CConnection()
  31. : csecurity(0), is(0), os(0), reader_(0), writer_(0),
  32. shared(false),
  33. state_(RFBSTATE_UNINITIALISED), useProtocol3_3(false)
  34. {
  35. security = new Security(SecurityViewer);
  36. }
  37. CConnection::~CConnection()
  38. {
  39. if (csecurity) csecurity->destroy();
  40. deleteReaderAndWriter();
  41. }
  42. void CConnection::deleteReaderAndWriter()
  43. {
  44. delete reader_;
  45. reader_ = 0;
  46. delete writer_;
  47. writer_ = 0;
  48. }
  49. void CConnection::setStreams(rdr::InStream* is_, rdr::OutStream* os_)
  50. {
  51. is = is_;
  52. os = os_;
  53. }
  54. void CConnection::initialiseProtocol()
  55. {
  56. state_ = RFBSTATE_PROTOCOL_VERSION;
  57. }
  58. void CConnection::processMsg()
  59. {
  60. switch (state_) {
  61. case RFBSTATE_PROTOCOL_VERSION: processVersionMsg(); break;
  62. case RFBSTATE_SECURITY_TYPES: processSecurityTypesMsg(); break;
  63. case RFBSTATE_SECURITY: processSecurityMsg(); break;
  64. case RFBSTATE_SECURITY_RESULT: processSecurityResultMsg(); break;
  65. case RFBSTATE_INITIALISATION: processInitMsg(); break;
  66. case RFBSTATE_NORMAL: reader_->readMsg(); break;
  67. case RFBSTATE_UNINITIALISED:
  68. throw Exception("CConnection::processMsg: not initialised yet?");
  69. default:
  70. throw Exception("CConnection::processMsg: invalid state");
  71. }
  72. }
  73. void CConnection::processVersionMsg()
  74. {
  75. vlog.debug("reading protocol version");
  76. bool done;
  77. if (!cp.readVersion(is, &done)) {
  78. state_ = RFBSTATE_INVALID;
  79. throw Exception("reading version failed: not an RFB server?");
  80. }
  81. if (!done) return;
  82. vlog.info("Server supports RFB protocol version %d.%d",
  83. cp.majorVersion, cp.minorVersion);
  84. // The only official RFB protocol versions are currently 3.3, 3.7 and 3.8
  85. if (cp.beforeVersion(3,3)) {
  86. char msg[256];
  87. sprintf(msg,"Server gave unsupported RFB protocol version %d.%d",
  88. cp.majorVersion, cp.minorVersion);
  89. vlog.error(msg);
  90. state_ = RFBSTATE_INVALID;
  91. throw Exception(msg);
  92. } else if (useProtocol3_3 || cp.beforeVersion(3,7)) {
  93. cp.setVersion(3,3);
  94. } else if (cp.afterVersion(3,8)) {
  95. cp.setVersion(3,8);
  96. }
  97. cp.writeVersion(os);
  98. state_ = RFBSTATE_SECURITY_TYPES;
  99. vlog.info("Using RFB protocol version %d.%d",
  100. cp.majorVersion, cp.minorVersion);
  101. }
  102. void CConnection::processSecurityTypesMsg()
  103. {
  104. vlog.debug("processing security types message");
  105. int secType = secTypeInvalid;
  106. std::list<rdr::U8> secTypes;
  107. secTypes = security->GetEnabledSecTypes();
  108. if (cp.isVersion(3,3)) {
  109. // legacy 3.3 server may only offer "vnc authentication" or "none"
  110. secType = is->readU32();
  111. if (secType == secTypeInvalid) {
  112. throwConnFailedException();
  113. } else if (secType == secTypeNone || secType == secTypeVncAuth) {
  114. std::list<rdr::U8>::iterator i;
  115. for (i = secTypes.begin(); i != secTypes.end(); i++)
  116. if (*i == secType) {
  117. secType = *i;
  118. break;
  119. }
  120. if (i == secTypes.end())
  121. secType = secTypeInvalid;
  122. } else {
  123. vlog.error("Unknown 3.3 security type %d", secType);
  124. throw Exception("Unknown 3.3 security type");
  125. }
  126. } else {
  127. // >=3.7 server will offer us a list
  128. int nServerSecTypes = is->readU8();
  129. if (nServerSecTypes == 0)
  130. throwConnFailedException();
  131. std::list<rdr::U8>::iterator j;
  132. int secTypePos, secTypePosMin;
  133. secTypePosMin = secTypes.size();
  134. for (int i = 0; i < nServerSecTypes; i++) {
  135. rdr::U8 serverSecType = is->readU8();
  136. vlog.debug("Server offers security type %s(%d)",
  137. secTypeName(serverSecType),serverSecType);
  138. // We keep trying types, to find the one that matches and
  139. // which appears first in the client's list of supported types.
  140. for (j = secTypes.begin(), secTypePos = 0; j != secTypes.end(); j++, secTypePos++) {
  141. if (*j == serverSecType && secTypePos < secTypePosMin) {
  142. secType = *j;
  143. secTypePosMin = secTypePos;
  144. break;
  145. }
  146. }
  147. }
  148. // Inform the server of our decision
  149. if (secType != secTypeInvalid) {
  150. os->writeU8(secType);
  151. os->flush();
  152. vlog.debug("Choosing security type %s(%d)",secTypeName(secType),secType);
  153. }
  154. }
  155. if (secType == secTypeInvalid) {
  156. state_ = RFBSTATE_INVALID;
  157. vlog.error("No matching security types");
  158. throw Exception("No matching security types");
  159. }
  160. state_ = RFBSTATE_SECURITY;
  161. csecurity = security->GetCSecurity(secType);
  162. processSecurityMsg();
  163. }
  164. void CConnection::processSecurityMsg()
  165. {
  166. vlog.debug("processing security message");
  167. if (csecurity->processMsg(this)) {
  168. state_ = RFBSTATE_SECURITY_RESULT;
  169. processSecurityResultMsg();
  170. }
  171. }
  172. void CConnection::processSecurityResultMsg()
  173. {
  174. vlog.debug("processing security result message");
  175. int result;
  176. if (cp.beforeVersion(3,8) && csecurity->getType() == secTypeNone) {
  177. result = secResultOK;
  178. } else {
  179. if (!is->checkNoWait(1)) return;
  180. result = is->readU32();
  181. }
  182. switch (result) {
  183. case secResultOK:
  184. securityCompleted();
  185. return;
  186. case secResultFailed:
  187. vlog.debug("auth failed");
  188. break;
  189. case secResultTooMany:
  190. vlog.debug("auth failed - too many tries");
  191. break;
  192. default:
  193. throw Exception("Unknown security result from server");
  194. }
  195. CharArray reason;
  196. if (cp.beforeVersion(3,8))
  197. reason.buf = strDup("Authentication failure");
  198. else
  199. reason.buf = is->readString();
  200. state_ = RFBSTATE_INVALID;
  201. throw AuthFailureException(reason.buf);
  202. }
  203. void CConnection::processInitMsg()
  204. {
  205. vlog.debug("reading server initialisation");
  206. reader_->readServerInit();
  207. }
  208. void CConnection::throwConnFailedException()
  209. {
  210. state_ = RFBSTATE_INVALID;
  211. CharArray reason;
  212. reason.buf = is->readString();
  213. throw ConnFailedException(reason.buf);
  214. }
  215. void CConnection::securityCompleted()
  216. {
  217. state_ = RFBSTATE_INITIALISATION;
  218. reader_ = new CMsgReaderV3(this, is);
  219. writer_ = new CMsgWriterV3(&cp, os);
  220. vlog.debug("Authentication success!");
  221. authSuccess();
  222. writer_->writeClientInit(shared);
  223. }
  224. void CConnection::authSuccess()
  225. {
  226. }
  227. void CConnection::serverInit()
  228. {
  229. state_ = RFBSTATE_NORMAL;
  230. vlog.debug("initialisation done");
  231. }