/apps/desktop/libvncserver/auth.c

http://ftk.googlecode.com/ · C · 375 lines · 215 code · 64 blank · 96 comment · 46 complexity · feddd093061af51c14cc0df88ae5f67f MD5 · raw file

  1. /*
  2. * auth.c - deal with authentication.
  3. *
  4. * This file implements the VNC authentication protocol when setting up an RFB
  5. * connection.
  6. */
  7. /*
  8. * Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin
  9. * OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
  10. * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
  11. * All Rights Reserved.
  12. *
  13. * This is free software; you can redistribute it and/or modify
  14. * it under the terms of the GNU General Public License as published by
  15. * the Free Software Foundation; either version 2 of the License, or
  16. * (at your option) any later version.
  17. *
  18. * This software is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU General Public License
  24. * along with this software; if not, write to the Free Software
  25. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  26. * USA.
  27. */
  28. #include <rfb/rfb.h>
  29. /* RFB 3.8 clients are well informed */
  30. void rfbClientSendString(rfbClientPtr cl, char *reason);
  31. /*
  32. * Handle security types
  33. */
  34. static rfbSecurityHandler* securityHandlers = NULL;
  35. /*
  36. * This method registers a list of new security types.
  37. * It avoids same security type getting registered multiple times.
  38. * The order is not preserved if multiple security types are
  39. * registered at one-go.
  40. */
  41. void
  42. rfbRegisterSecurityHandler(rfbSecurityHandler* handler)
  43. {
  44. rfbSecurityHandler *head = securityHandlers, *next = NULL;
  45. if(handler == NULL)
  46. return;
  47. next = handler->next;
  48. while(head != NULL) {
  49. if(head == handler) {
  50. rfbRegisterSecurityHandler(next);
  51. return;
  52. }
  53. head = head->next;
  54. }
  55. handler->next = securityHandlers;
  56. securityHandlers = handler;
  57. rfbRegisterSecurityHandler(next);
  58. }
  59. /*
  60. * This method unregisters a list of security types.
  61. * These security types won't be available for any new
  62. * client connection.
  63. */
  64. void
  65. rfbUnregisterSecurityHandler(rfbSecurityHandler* handler)
  66. {
  67. rfbSecurityHandler *cur = NULL, *pre = NULL;
  68. if(handler == NULL)
  69. return;
  70. if(securityHandlers == handler) {
  71. securityHandlers = securityHandlers->next;
  72. rfbUnregisterSecurityHandler(handler->next);
  73. return;
  74. }
  75. cur = pre = securityHandlers;
  76. while(cur) {
  77. if(cur == handler) {
  78. pre->next = cur->next;
  79. break;
  80. }
  81. pre = cur;
  82. cur = cur->next;
  83. }
  84. rfbUnregisterSecurityHandler(handler->next);
  85. }
  86. /*
  87. * Send the authentication challenge.
  88. */
  89. static void
  90. rfbVncAuthSendChallenge(rfbClientPtr cl)
  91. {
  92. /* 4 byte header is alreay sent. Which is rfbSecTypeVncAuth
  93. (same as rfbVncAuth). Just send the challenge. */
  94. rfbRandomBytes(cl->authChallenge);
  95. if (rfbWriteExact(cl, (char *)cl->authChallenge, CHALLENGESIZE) < 0) {
  96. rfbLogPerror("rfbAuthNewClient: write");
  97. rfbCloseClient(cl);
  98. return;
  99. }
  100. /* Dispatch client input to rfbVncAuthProcessResponse. */
  101. cl->state = RFB_AUTHENTICATION;
  102. }
  103. /*
  104. * Send the NO AUTHENTICATION. SCARR
  105. */
  106. static void
  107. rfbVncAuthNone(rfbClientPtr cl)
  108. {
  109. uint32_t authResult;
  110. if (cl->protocolMajorVersion==3 && cl->protocolMinorVersion > 7) {
  111. rfbLog("rfbProcessClientSecurityType: returning securityResult for client rfb version >= 3.8\n");
  112. authResult = Swap32IfLE(rfbVncAuthOK);
  113. if (rfbWriteExact(cl, (char *)&authResult, 4) < 0) {
  114. rfbLogPerror("rfbAuthProcessClientMessage: write");
  115. rfbCloseClient(cl);
  116. return;
  117. }
  118. }
  119. cl->state = RFB_INITIALISATION;
  120. return;
  121. }
  122. /*
  123. * Advertise the supported security types (protocol 3.7). Here before sending
  124. * the list of security types to the client one more security type is added
  125. * to the list if primaryType is not set to rfbSecTypeInvalid. This security
  126. * type is the standard vnc security type which does the vnc authentication
  127. * or it will be security type for no authentication.
  128. * Different security types will be added by applications using this library.
  129. */
  130. static rfbSecurityHandler VncSecurityHandlerVncAuth = {
  131. rfbSecTypeVncAuth,
  132. rfbVncAuthSendChallenge,
  133. NULL
  134. };
  135. static rfbSecurityHandler VncSecurityHandlerNone = {
  136. rfbSecTypeNone,
  137. rfbVncAuthNone,
  138. NULL
  139. };
  140. static void
  141. rfbSendSecurityTypeList(rfbClientPtr cl, int primaryType)
  142. {
  143. /* The size of the message is the count of security types +1,
  144. * since the first byte is the number of types. */
  145. int size = 1;
  146. rfbSecurityHandler* handler;
  147. #define MAX_SECURITY_TYPES 255
  148. uint8_t buffer[MAX_SECURITY_TYPES+1];
  149. /* Fill in the list of security types in the client structure. (NOTE: Not really in the client structure) */
  150. switch (primaryType) {
  151. case rfbSecTypeNone:
  152. rfbRegisterSecurityHandler(&VncSecurityHandlerNone);
  153. break;
  154. case rfbSecTypeVncAuth:
  155. rfbRegisterSecurityHandler(&VncSecurityHandlerVncAuth);
  156. break;
  157. }
  158. for (handler = securityHandlers;
  159. handler && size<MAX_SECURITY_TYPES; handler = handler->next) {
  160. buffer[size] = handler->type;
  161. size++;
  162. }
  163. buffer[0] = (unsigned char)size-1;
  164. /* Send the list. */
  165. if (rfbWriteExact(cl, (char *)buffer, size) < 0) {
  166. rfbLogPerror("rfbSendSecurityTypeList: write");
  167. rfbCloseClient(cl);
  168. return;
  169. }
  170. /*
  171. * if count is 0, we need to send the reason and close the connection.
  172. */
  173. if(size <= 1) {
  174. /* This means total count is Zero and so reason msg should be sent */
  175. /* The execution should never reach here */
  176. char* reason = "No authentication mode is registered!";
  177. rfbClientSendString(cl, reason);
  178. return;
  179. }
  180. /* Dispatch client input to rfbProcessClientSecurityType. */
  181. cl->state = RFB_SECURITY_TYPE;
  182. }
  183. /*
  184. * Tell the client what security type will be used (protocol 3.3).
  185. */
  186. static void
  187. rfbSendSecurityType(rfbClientPtr cl, int32_t securityType)
  188. {
  189. uint32_t value32;
  190. /* Send the value. */
  191. value32 = Swap32IfLE(securityType);
  192. if (rfbWriteExact(cl, (char *)&value32, 4) < 0) {
  193. rfbLogPerror("rfbSendSecurityType: write");
  194. rfbCloseClient(cl);
  195. return;
  196. }
  197. /* Decide what to do next. */
  198. switch (securityType) {
  199. case rfbSecTypeNone:
  200. /* Dispatch client input to rfbProcessClientInitMessage. */
  201. cl->state = RFB_INITIALISATION;
  202. break;
  203. case rfbSecTypeVncAuth:
  204. /* Begin the standard VNC authentication procedure. */
  205. rfbVncAuthSendChallenge(cl);
  206. break;
  207. default:
  208. /* Impossible case (hopefully). */
  209. rfbLogPerror("rfbSendSecurityType: assertion failed");
  210. rfbCloseClient(cl);
  211. }
  212. }
  213. /*
  214. * rfbAuthNewClient is called right after negotiating the protocol
  215. * version. Depending on the protocol version, we send either a code
  216. * for authentication scheme to be used (protocol 3.3), or a list of
  217. * possible "security types" (protocol 3.7).
  218. */
  219. void
  220. rfbAuthNewClient(rfbClientPtr cl)
  221. {
  222. int32_t securityType = rfbSecTypeInvalid;
  223. if (!cl->screen->authPasswdData || cl->reverseConnection) {
  224. /* chk if this condition is valid or not. */
  225. securityType = rfbSecTypeNone;
  226. } else if (cl->screen->authPasswdData) {
  227. securityType = rfbSecTypeVncAuth;
  228. }
  229. if (cl->protocolMajorVersion==3 && cl->protocolMinorVersion < 7)
  230. {
  231. /* Make sure we use only RFB 3.3 compatible security types. */
  232. if (securityType == rfbSecTypeInvalid) {
  233. rfbLog("VNC authentication disabled - RFB 3.3 client rejected\n");
  234. rfbClientConnFailed(cl, "Your viewer cannot handle required "
  235. "authentication methods");
  236. return;
  237. }
  238. rfbSendSecurityType(cl, securityType);
  239. } else {
  240. /* Here it's ok when securityType is set to rfbSecTypeInvalid. */
  241. rfbSendSecurityTypeList(cl, securityType);
  242. }
  243. }
  244. /*
  245. * Read the security type chosen by the client (protocol 3.7).
  246. */
  247. void
  248. rfbProcessClientSecurityType(rfbClientPtr cl)
  249. {
  250. int n;
  251. uint8_t chosenType;
  252. rfbSecurityHandler* handler;
  253. /* Read the security type. */
  254. n = rfbReadExact(cl, (char *)&chosenType, 1);
  255. if (n <= 0) {
  256. if (n == 0)
  257. rfbLog("rfbProcessClientSecurityType: client gone\n");
  258. else
  259. rfbLogPerror("rfbProcessClientSecurityType: read");
  260. rfbCloseClient(cl);
  261. return;
  262. }
  263. /* Make sure it was present in the list sent by the server. */
  264. for (handler = securityHandlers; handler; handler = handler->next) {
  265. if (chosenType == handler->type) {
  266. rfbLog("rfbProcessClientSecurityType: executing handler for type %d\n", chosenType);
  267. handler->handler(cl);
  268. return;
  269. }
  270. }
  271. rfbLog("rfbProcessClientSecurityType: wrong security type (%d) requested\n", chosenType);
  272. rfbCloseClient(cl);
  273. }
  274. /*
  275. * rfbAuthProcessClientMessage is called when the client sends its
  276. * authentication response.
  277. */
  278. void
  279. rfbAuthProcessClientMessage(rfbClientPtr cl)
  280. {
  281. int n;
  282. uint8_t response[CHALLENGESIZE];
  283. uint32_t authResult;
  284. if ((n = rfbReadExact(cl, (char *)response, CHALLENGESIZE)) <= 0) {
  285. if (n != 0)
  286. rfbLogPerror("rfbAuthProcessClientMessage: read");
  287. rfbCloseClient(cl);
  288. return;
  289. }
  290. if(!cl->screen->passwordCheck(cl,(const char*)response,CHALLENGESIZE)) {
  291. rfbErr("rfbAuthProcessClientMessage: password check failed\n");
  292. authResult = Swap32IfLE(rfbVncAuthFailed);
  293. if (rfbWriteExact(cl, (char *)&authResult, 4) < 0) {
  294. rfbLogPerror("rfbAuthProcessClientMessage: write");
  295. }
  296. /* support RFB 3.8 clients, they expect a reason *why* it was disconnected */
  297. if (cl->protocolMinorVersion > 7) {
  298. rfbClientSendString(cl, "password check failed!");
  299. }
  300. else
  301. rfbCloseClient(cl);
  302. return;
  303. }
  304. authResult = Swap32IfLE(rfbVncAuthOK);
  305. if (rfbWriteExact(cl, (char *)&authResult, 4) < 0) {
  306. rfbLogPerror("rfbAuthProcessClientMessage: write");
  307. rfbCloseClient(cl);
  308. return;
  309. }
  310. cl->state = RFB_INITIALISATION;
  311. }