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 /* 9 * Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin 10 * OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk (at) incompleteness.net>. 11 * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge. 12 * All Rights Reserved. 13 * 14 * This is free software; you can redistribute it and/or modify 15 * it under the terms of the GNU General Public License as published by 16 * the Free Software Foundation; either version 2 of the License, or 17 * (at your option) any later version. 18 * 19 * This software is distributed in the hope that it will be useful, 20 * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 * GNU General Public License for more details. 23 * 24 * You should have received a copy of the GNU General Public License 25 * along with this software; if not, write to the Free Software 26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 27 * USA. 28 */ 29 30 #include <rfb/rfb.h> 31 32 /* RFB 3.8 clients are well informed */ 33 void rfbClientSendString(rfbClientPtr cl, const char *reason); 34 35 36 /* 37 * Handle security types 38 */ 39 40 static rfbSecurityHandler* securityHandlers = NULL; 41 42 /* 43 * This method registers a list of new security types. 44 * It avoids same security type getting registered multiple times. 45 * The order is not preserved if multiple security types are 46 * registered at one-go. 47 */ 48 void 49 rfbRegisterSecurityHandler(rfbSecurityHandler* handler) 50 { 51 rfbSecurityHandler *head = securityHandlers, *next = NULL; 52 53 if(handler == NULL) 54 return; 55 56 next = handler->next; 57 58 while(head != NULL) { 59 if(head == handler) { 60 rfbRegisterSecurityHandler(next); 61 return; 62 } 63 64 head = head->next; 65 } 66 67 handler->next = securityHandlers; 68 securityHandlers = handler; 69 70 rfbRegisterSecurityHandler(next); 71 } 72 73 /* 74 * This method unregisters a list of security types. 75 * These security types won't be available for any new 76 * client connection. 77 */ 78 void 79 rfbUnregisterSecurityHandler(rfbSecurityHandler* handler) 80 { 81 rfbSecurityHandler *cur = NULL, *pre = NULL; 82 83 if(handler == NULL) 84 return; 85 86 if(securityHandlers == handler) { 87 securityHandlers = securityHandlers->next; 88 rfbUnregisterSecurityHandler(handler->next); 89 return; 90 } 91 92 cur = pre = securityHandlers; 93 94 while(cur) { 95 if(cur == handler) { 96 pre->next = cur->next; 97 break; 98 } 99 pre = cur; 100 cur = cur->next; 101 } 102 rfbUnregisterSecurityHandler(handler->next); 103 } 104 105 /* 106 * Send the authentication challenge. 107 */ 108 109 static void 110 rfbVncAuthSendChallenge(rfbClientPtr cl) 111 { 112 113 /* 4 byte header is alreay sent. Which is rfbSecTypeVncAuth 114 (same as rfbVncAuth). Just send the challenge. */ 115 rfbRandomBytes(cl->authChallenge); 116 if (rfbWriteExact(cl, (char *)cl->authChallenge, CHALLENGESIZE) < 0) { 117 rfbLogPerror("rfbAuthNewClient: write"); 118 rfbCloseClient(cl); 119 return; 120 } 121 122 /* Dispatch client input to rfbVncAuthProcessResponse. */ 123 cl->state = RFB_AUTHENTICATION; 124 } 125 126 /* 127 * Send the NO AUTHENTICATION. SCARR 128 */ 129 130 /* 131 * The rfbVncAuthNone function is currently the only function that contains 132 * special logic for the built-in Mac OS X VNC client which is activated by 133 * a protocolMinorVersion == 889 coming from the Mac OS X VNC client. 134 * The rfbProcessClientInitMessage function does understand how to handle the 135 * RFB_INITIALISATION_SHARED state which was introduced to support the built-in 136 * Mac OS X VNC client, but rfbProcessClientInitMessage does not examine the 137 * protocolMinorVersion version field and so its support for the 138 * RFB_INITIALISATION_SHARED state is not restricted to just the OS X client. 139 */ 140 141 static void 142 rfbVncAuthNone(rfbClientPtr cl) 143 { 144 /* The built-in Mac OS X VNC client behaves in a non-conforming fashion 145 * when the server version is 3.7 or later AND the list of security types 146 * sent to the OS X client contains the 'None' authentication type AND 147 * the OS X client sends back the 'None' type as its choice. In this case, 148 * and this case ONLY, the built-in Mac OS X VNC client will NOT send the 149 * ClientInit message and instead will behave as though an implicit 150 * ClientInit message containing a shared-flag of true has been sent. 151 * The special state RFB_INITIALISATION_SHARED represents this case. 152 * The Mac OS X VNC client can be detected by checking protocolMinorVersion 153 * for a value of 889. No other VNC client is known to use this value 154 * for protocolMinorVersion. */ 155 uint32_t authResult; 156 157 /* The built-in Mac OS X VNC client expects to NOT receive a SecurityResult 158 * message for authentication type 'None'. Since its protocolMinorVersion 159 * is greater than 7 (it is 889) this case must be tested for specially. */ 160 if (cl->protocolMajorVersion==3 && cl->protocolMinorVersion > 7 && cl->protocolMinorVersion != 889) { 161 rfbLog("rfbProcessClientSecurityType: returning securityResult for client rfb version >= 3.8\n"); 162 authResult = Swap32IfLE(rfbVncAuthOK); 163 if (rfbWriteExact(cl, (char *)&authResult, 4) < 0) { 164 rfbLogPerror("rfbAuthProcessClientMessage: write"); 165 rfbCloseClient(cl); 166 return; 167 } 168 } 169 cl->state = cl->protocolMinorVersion == 889 ? RFB_INITIALISATION_SHARED : RFB_INITIALISATION; 170 if (cl->state == RFB_INITIALISATION_SHARED) 171 /* In this case we must call rfbProcessClientMessage now because 172 * otherwise we would hang waiting for data to be received from the 173 * client (the ClientInit message which will never come). */ 174 rfbProcessClientMessage(cl); 175 return; 176 } 177 178 179 /* 180 * Advertise the supported security types (protocol 3.7). Here before sending 181 * the list of security types to the client one more security type is added 182 * to the list if primaryType is not set to rfbSecTypeInvalid. This security 183 * type is the standard vnc security type which does the vnc authentication 184 * or it will be security type for no authentication. 185 * Different security types will be added by applications using this library. 186 */ 187 188 static rfbSecurityHandler VncSecurityHandlerVncAuth = { 189 rfbSecTypeVncAuth, 190 rfbVncAuthSendChallenge, 191 NULL 192 }; 193 194 static rfbSecurityHandler VncSecurityHandlerNone = { 195 rfbSecTypeNone, 196 rfbVncAuthNone, 197 NULL 198 }; 199 200 201 static void 202 rfbSendSecurityTypeList(rfbClientPtr cl, int primaryType) 203 { 204 /* The size of the message is the count of security types +1, 205 * since the first byte is the number of types. */ 206 int size = 1; 207 rfbSecurityHandler* handler; 208 #define MAX_SECURITY_TYPES 255 209 uint8_t buffer[MAX_SECURITY_TYPES+1]; 210 211 212 /* Fill in the list of security types in the client structure. (NOTE: Not really in the client structure) */ 213 switch (primaryType) { 214 case rfbSecTypeNone: 215 rfbRegisterSecurityHandler(&VncSecurityHandlerNone); 216 break; 217 case rfbSecTypeVncAuth: 218 rfbRegisterSecurityHandler(&VncSecurityHandlerVncAuth); 219 break; 220 } 221 222 for (handler = securityHandlers; 223 handler && size<MAX_SECURITY_TYPES; handler = handler->next) { 224 buffer[size] = handler->type; 225 size++; 226 } 227 buffer[0] = (unsigned char)size-1; 228 229 /* Send the list. */ 230 if (rfbWriteExact(cl, (char *)buffer, size) < 0) { 231 rfbLogPerror("rfbSendSecurityTypeList: write"); 232 rfbCloseClient(cl); 233 return; 234 } 235 236 /* 237 * if count is 0, we need to send the reason and close the connection. 238 */ 239 if(size <= 1) { 240 /* This means total count is Zero and so reason msg should be sent */ 241 /* The execution should never reach here */ 242 char* reason = "No authentication mode is registered!"; 243 244 rfbClientSendString(cl, reason); 245 return; 246 } 247 248 /* Dispatch client input to rfbProcessClientSecurityType. */ 249 cl->state = RFB_SECURITY_TYPE; 250 } 251 252 253 254 255 /* 256 * Tell the client what security type will be used (protocol 3.3). 257 */ 258 static void 259 rfbSendSecurityType(rfbClientPtr cl, int32_t securityType) 260 { 261 uint32_t value32; 262 263 /* Send the value. */ 264 value32 = Swap32IfLE(securityType); 265 if (rfbWriteExact(cl, (char *)&value32, 4) < 0) { 266 rfbLogPerror("rfbSendSecurityType: write"); 267 rfbCloseClient(cl); 268 return; 269 } 270 271 /* Decide what to do next. */ 272 switch (securityType) { 273 case rfbSecTypeNone: 274 /* Dispatch client input to rfbProcessClientInitMessage. */ 275 cl->state = RFB_INITIALISATION; 276 break; 277 case rfbSecTypeVncAuth: 278 /* Begin the standard VNC authentication procedure. */ 279 rfbVncAuthSendChallenge(cl); 280 break; 281 default: 282 /* Impossible case (hopefully). */ 283 rfbLogPerror("rfbSendSecurityType: assertion failed"); 284 rfbCloseClient(cl); 285 } 286 } 287 288 289 290 /* 291 * rfbAuthNewClient is called right after negotiating the protocol 292 * version. Depending on the protocol version, we send either a code 293 * for authentication scheme to be used (protocol 3.3), or a list of 294 * possible "security types" (protocol 3.7). 295 */ 296 297 void 298 rfbAuthNewClient(rfbClientPtr cl) 299 { 300 int32_t securityType = rfbSecTypeInvalid; 301 302 if (!cl->screen->authPasswdData || cl->reverseConnection) { 303 /* chk if this condition is valid or not. */ 304 securityType = rfbSecTypeNone; 305 } else if (cl->screen->authPasswdData) { 306 securityType = rfbSecTypeVncAuth; 307 } 308 309 if (cl->protocolMajorVersion==3 && cl->protocolMinorVersion < 7) 310 { 311 /* Make sure we use only RFB 3.3 compatible security types. */ 312 if (securityType == rfbSecTypeInvalid) { 313 rfbLog("VNC authentication disabled - RFB 3.3 client rejected\n"); 314 rfbClientConnFailed(cl, "Your viewer cannot handle required " 315 "authentication methods"); 316 return; 317 } 318 rfbSendSecurityType(cl, securityType); 319 } else { 320 /* Here it's ok when securityType is set to rfbSecTypeInvalid. */ 321 rfbSendSecurityTypeList(cl, securityType); 322 } 323 } 324 325 /* 326 * Read the security type chosen by the client (protocol 3.7). 327 */ 328 329 void 330 rfbProcessClientSecurityType(rfbClientPtr cl) 331 { 332 int n; 333 uint8_t chosenType; 334 rfbSecurityHandler* handler; 335 336 /* Read the security type. */ 337 n = rfbReadExact(cl, (char *)&chosenType, 1); 338 if (n <= 0) { 339 if (n == 0) 340 rfbLog("rfbProcessClientSecurityType: client gone\n"); 341 else 342 rfbLogPerror("rfbProcessClientSecurityType: read"); 343 rfbCloseClient(cl); 344 return; 345 } 346 347 /* Make sure it was present in the list sent by the server. */ 348 for (handler = securityHandlers; handler; handler = handler->next) { 349 if (chosenType == handler->type) { 350 rfbLog("rfbProcessClientSecurityType: executing handler for type %d\n", chosenType); 351 handler->handler(cl); 352 return; 353 } 354 } 355 356 rfbLog("rfbProcessClientSecurityType: wrong security type (%d) requested\n", chosenType); 357 rfbCloseClient(cl); 358 } 359 360 361 362 /* 363 * rfbAuthProcessClientMessage is called when the client sends its 364 * authentication response. 365 */ 366 367 void 368 rfbAuthProcessClientMessage(rfbClientPtr cl) 369 { 370 int n; 371 uint8_t response[CHALLENGESIZE]; 372 uint32_t authResult; 373 374 if ((n = rfbReadExact(cl, (char *)response, CHALLENGESIZE)) <= 0) { 375 if (n != 0) 376 rfbLogPerror("rfbAuthProcessClientMessage: read"); 377 rfbCloseClient(cl); 378 return; 379 } 380 381 if(!cl->screen->passwordCheck(cl,(const char*)response,CHALLENGESIZE)) { 382 rfbErr("rfbAuthProcessClientMessage: password check failed\n"); 383 authResult = Swap32IfLE(rfbVncAuthFailed); 384 if (rfbWriteExact(cl, (char *)&authResult, 4) < 0) { 385 rfbLogPerror("rfbAuthProcessClientMessage: write"); 386 } 387 /* support RFB 3.8 clients, they expect a reason *why* it was disconnected */ 388 if (cl->protocolMinorVersion > 7) { 389 rfbClientSendString(cl, "password check failed!"); 390 } 391 else 392 rfbCloseClient(cl); 393 return; 394 } 395 396 authResult = Swap32IfLE(rfbVncAuthOK); 397 398 if (rfbWriteExact(cl, (char *)&authResult, 4) < 0) { 399 rfbLogPerror("rfbAuthProcessClientMessage: write"); 400 rfbCloseClient(cl); 401 return; 402 } 403 404 cl->state = RFB_INITIALISATION; 405 } 406