LibVNCServer/LibVNCClient
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
rfbproto.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2000-2002 Constantin Kaplinsky. All Rights Reserved.
3  * Copyright (C) 2000 Tridia Corporation. All Rights Reserved.
4  * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
5  *
6  * This is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This software is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this software; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19  * USA.
20  */
21 
22 /*
23  * rfbproto.c - functions to deal with client side of RFB protocol.
24  */
25 
26 #ifdef __STRICT_ANSI__
27 #define _BSD_SOURCE
28 #define _POSIX_SOURCE
29 #endif
30 #ifndef WIN32
31 #include <unistd.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <pwd.h>
35 #endif
36 #include <errno.h>
37 #include <rfb/rfbclient.h>
38 #ifdef WIN32
39 #undef SOCKET
40 #undef socklen_t
41 #endif
42 #ifdef LIBVNCSERVER_HAVE_LIBZ
43 #include <zlib.h>
44 #ifdef __CHECKER__
45 #undef Z_NULL
46 #define Z_NULL NULL
47 #endif
48 #endif
49 #ifdef LIBVNCSERVER_HAVE_LIBJPEG
50 #ifdef _RPCNDR_H /* This Windows header typedefs 'boolean', jpeglib has to know */
51 #define HAVE_BOOLEAN
52 #endif
53 #include <jpeglib.h>
54 #endif
55 #include <stdarg.h>
56 #include <time.h>
57 
58 #ifdef LIBVNCSERVER_WITH_CLIENT_GCRYPT
59 #include <gcrypt.h>
60 #endif
61 
62 #include "minilzo.h"
63 #include "tls.h"
64 
65 /*
66  * rfbClientLog prints a time-stamped message to the log file (stderr).
67  */
68 
70 
71 static void
72 rfbDefaultClientLog(const char *format, ...)
73 {
74  va_list args;
75  char buf[256];
76  time_t log_clock;
77 
79  return;
80 
81  va_start(args, format);
82 
83  time(&log_clock);
84  strftime(buf, 255, "%d/%m/%Y %X ", localtime(&log_clock));
85  fprintf(stderr, "%s", buf);
86 
87  vfprintf(stderr, format, args);
88  fflush(stderr);
89 
90  va_end(args);
91 }
92 
93 rfbClientLogProc rfbClientLog=rfbDefaultClientLog;
94 rfbClientLogProc rfbClientErr=rfbDefaultClientLog;
95 
96 /* extensions */
97 
99 
101 {
103  rfbClientExtensions = e;
104 }
105 
106 /* client data */
107 
108 void rfbClientSetClientData(rfbClient* client, void* tag, void* data)
109 {
110  rfbClientData* clientData = client->clientData;
111 
112  while(clientData && clientData->tag != tag)
113  clientData = clientData->next;
114  if(clientData == NULL) {
115  clientData = calloc(sizeof(rfbClientData), 1);
116  clientData->next = client->clientData;
117  client->clientData = clientData;
118  clientData->tag = tag;
119  }
120 
121  clientData->data = data;
122 }
123 
124 void* rfbClientGetClientData(rfbClient* client, void* tag)
125 {
126  rfbClientData* clientData = client->clientData;
127 
128  while(clientData) {
129  if(clientData->tag == tag)
130  return clientData->data;
131  clientData = clientData->next;
132  }
133 
134  return NULL;
135 }
136 
137 /* messages */
138 
139 static void FillRectangle(rfbClient* client, int x, int y, int w, int h, uint32_t colour) {
140  int i,j;
141 
142 #define FILL_RECT(BPP) \
143  for(j=y*client->width;j<(y+h)*client->width;j+=client->width) \
144  for(i=x;i<x+w;i++) \
145  ((uint##BPP##_t*)client->frameBuffer)[j+i]=colour;
146 
147  switch(client->format.bitsPerPixel) {
148  case 8: FILL_RECT(8); break;
149  case 16: FILL_RECT(16); break;
150  case 32: FILL_RECT(32); break;
151  default:
152  rfbClientLog("Unsupported bitsPerPixel: %d\n",client->format.bitsPerPixel);
153  }
154 }
155 
156 static void CopyRectangle(rfbClient* client, uint8_t* buffer, int x, int y, int w, int h) {
157  int j;
158 
159 #define COPY_RECT(BPP) \
160  { \
161  int rs = w * BPP / 8, rs2 = client->width * BPP / 8; \
162  for (j = ((x * (BPP / 8)) + (y * rs2)); j < (y + h) * rs2; j += rs2) { \
163  memcpy(client->frameBuffer + j, buffer, rs); \
164  buffer += rs; \
165  } \
166  }
167 
168  switch(client->format.bitsPerPixel) {
169  case 8: COPY_RECT(8); break;
170  case 16: COPY_RECT(16); break;
171  case 32: COPY_RECT(32); break;
172  default:
173  rfbClientLog("Unsupported bitsPerPixel: %d\n",client->format.bitsPerPixel);
174  }
175 }
176 
177 /* TODO: test */
178 static void CopyRectangleFromRectangle(rfbClient* client, int src_x, int src_y, int w, int h, int dest_x, int dest_y) {
179  int i,j;
180 
181 #define COPY_RECT_FROM_RECT(BPP) \
182  { \
183  uint##BPP##_t* _buffer=((uint##BPP##_t*)client->frameBuffer)+(src_y-dest_y)*client->width+src_x-dest_x; \
184  if (dest_y < src_y) { \
185  for(j = dest_y*client->width; j < (dest_y+h)*client->width; j += client->width) { \
186  if (dest_x < src_x) { \
187  for(i = dest_x; i < dest_x+w; i++) { \
188  ((uint##BPP##_t*)client->frameBuffer)[j+i]=_buffer[j+i]; \
189  } \
190  } else { \
191  for(i = dest_x+w-1; i >= dest_x; i--) { \
192  ((uint##BPP##_t*)client->frameBuffer)[j+i]=_buffer[j+i]; \
193  } \
194  } \
195  } \
196  } else { \
197  for(j = (dest_y+h-1)*client->width; j >= dest_y*client->width; j-=client->width) { \
198  if (dest_x < src_x) { \
199  for(i = dest_x; i < dest_x+w; i++) { \
200  ((uint##BPP##_t*)client->frameBuffer)[j+i]=_buffer[j+i]; \
201  } \
202  } else { \
203  for(i = dest_x+w-1; i >= dest_x; i--) { \
204  ((uint##BPP##_t*)client->frameBuffer)[j+i]=_buffer[j+i]; \
205  } \
206  } \
207  } \
208  } \
209  }
210 
211  switch(client->format.bitsPerPixel) {
212  case 8: COPY_RECT_FROM_RECT(8); break;
213  case 16: COPY_RECT_FROM_RECT(16); break;
214  case 32: COPY_RECT_FROM_RECT(32); break;
215  default:
216  rfbClientLog("Unsupported bitsPerPixel: %d\n",client->format.bitsPerPixel);
217  }
218 }
219 
220 static rfbBool HandleRRE8(rfbClient* client, int rx, int ry, int rw, int rh);
221 static rfbBool HandleRRE16(rfbClient* client, int rx, int ry, int rw, int rh);
222 static rfbBool HandleRRE32(rfbClient* client, int rx, int ry, int rw, int rh);
223 static rfbBool HandleCoRRE8(rfbClient* client, int rx, int ry, int rw, int rh);
224 static rfbBool HandleCoRRE16(rfbClient* client, int rx, int ry, int rw, int rh);
225 static rfbBool HandleCoRRE32(rfbClient* client, int rx, int ry, int rw, int rh);
226 static rfbBool HandleHextile8(rfbClient* client, int rx, int ry, int rw, int rh);
227 static rfbBool HandleHextile16(rfbClient* client, int rx, int ry, int rw, int rh);
228 static rfbBool HandleHextile32(rfbClient* client, int rx, int ry, int rw, int rh);
229 static rfbBool HandleUltra8(rfbClient* client, int rx, int ry, int rw, int rh);
230 static rfbBool HandleUltra16(rfbClient* client, int rx, int ry, int rw, int rh);
231 static rfbBool HandleUltra32(rfbClient* client, int rx, int ry, int rw, int rh);
232 static rfbBool HandleUltraZip8(rfbClient* client, int rx, int ry, int rw, int rh);
233 static rfbBool HandleUltraZip16(rfbClient* client, int rx, int ry, int rw, int rh);
234 static rfbBool HandleUltraZip32(rfbClient* client, int rx, int ry, int rw, int rh);
235 #ifdef LIBVNCSERVER_HAVE_LIBZ
236 static rfbBool HandleZlib8(rfbClient* client, int rx, int ry, int rw, int rh);
237 static rfbBool HandleZlib16(rfbClient* client, int rx, int ry, int rw, int rh);
238 static rfbBool HandleZlib32(rfbClient* client, int rx, int ry, int rw, int rh);
239 #ifdef LIBVNCSERVER_HAVE_LIBJPEG
240 static rfbBool HandleTight8(rfbClient* client, int rx, int ry, int rw, int rh);
241 static rfbBool HandleTight16(rfbClient* client, int rx, int ry, int rw, int rh);
242 static rfbBool HandleTight32(rfbClient* client, int rx, int ry, int rw, int rh);
243 
244 static long ReadCompactLen (rfbClient* client);
245 
246 static void JpegInitSource(j_decompress_ptr cinfo);
247 static boolean JpegFillInputBuffer(j_decompress_ptr cinfo);
248 static void JpegSkipInputData(j_decompress_ptr cinfo, long num_bytes);
249 static void JpegTermSource(j_decompress_ptr cinfo);
250 static void JpegSetSrcManager(j_decompress_ptr cinfo, uint8_t *compressedData,
251  int compressedLen);
252 #endif
253 static rfbBool HandleZRLE8(rfbClient* client, int rx, int ry, int rw, int rh);
254 static rfbBool HandleZRLE15(rfbClient* client, int rx, int ry, int rw, int rh);
255 static rfbBool HandleZRLE16(rfbClient* client, int rx, int ry, int rw, int rh);
256 static rfbBool HandleZRLE24(rfbClient* client, int rx, int ry, int rw, int rh);
257 static rfbBool HandleZRLE24Up(rfbClient* client, int rx, int ry, int rw, int rh);
258 static rfbBool HandleZRLE24Down(rfbClient* client, int rx, int ry, int rw, int rh);
259 static rfbBool HandleZRLE32(rfbClient* client, int rx, int ry, int rw, int rh);
260 #endif
261 
262 /*
263  * Server Capability Functions
264  */
265 rfbBool
266 SupportsClient2Server(rfbClient* client, int messageType)
267 {
268  return (client->supportedMessages.client2server[((messageType & 0xFF)/8)] & (1<<(messageType % 8)) ? TRUE : FALSE);
269 }
270 
271 rfbBool
272 SupportsServer2Client(rfbClient* client, int messageType)
273 {
274  return (client->supportedMessages.server2client[((messageType & 0xFF)/8)] & (1<<(messageType % 8)) ? TRUE : FALSE);
275 }
276 
277 void
278 SetClient2Server(rfbClient* client, int messageType)
279 {
280  client->supportedMessages.client2server[((messageType & 0xFF)/8)] |= (1<<(messageType % 8));
281 }
282 
283 void
284 SetServer2Client(rfbClient* client, int messageType)
285 {
286  client->supportedMessages.server2client[((messageType & 0xFF)/8)] |= (1<<(messageType % 8));
287 }
288 
289 void
290 ClearClient2Server(rfbClient* client, int messageType)
291 {
292  client->supportedMessages.client2server[((messageType & 0xFF)/8)] &= (!(1<<(messageType % 8)));
293 }
294 
295 void
296 ClearServer2Client(rfbClient* client, int messageType)
297 {
298  client->supportedMessages.server2client[((messageType & 0xFF)/8)] &= (!(1<<(messageType % 8)));
299 }
300 
301 
302 void
304 {
305  memset((char *)&client->supportedMessages,0,sizeof(client->supportedMessages));
306 
307  /* Default client supported messages (universal RFB 3.3 protocol) */
309  /* SetClient2Server(client, rfbFixColourMapEntries); Not currently supported */
312  SetClient2Server(client, rfbKeyEvent);
315  /* technically, we only care what we can *send* to the server
316  * but, we set Server2Client Just in case it ever becomes useful
317  */
320  SetServer2Client(client, rfbBell);
322 }
323 
324 void
326 {
327  DefaultSupportedMessages(client);
329  SetClient2Server(client, rfbSetScale);
331  SetClient2Server(client, rfbSetSW);
332  SetClient2Server(client, rfbTextChat);
334  /* technically, we only care what we can *send* to the server */
338  SetServer2Client(client, rfbTextChat);
339 }
340 
341 
342 void
344 {
345  DefaultSupportedMessages(client);
348  SetClient2Server(client, rfbSetSW);
349  /* SetClient2Server(client, rfbTextChat); */
350  /* technically, we only care what we can *send* to the server */
352  SetServer2Client(client, rfbTextChat);
353 }
354 
355 #ifndef WIN32
356 static rfbBool
357 IsUnixSocket(const char *name)
358 {
359  struct stat sb;
360  if(stat(name, &sb) == 0 && (sb.st_mode & S_IFMT) == S_IFSOCK)
361  return TRUE;
362  return FALSE;
363 }
364 #endif
365 
366 /*
367  * ConnectToRFBServer.
368  */
369 
370 rfbBool
371 ConnectToRFBServer(rfbClient* client,const char *hostname, int port)
372 {
373  if (client->serverPort==-1) {
374  /* serverHost is a file recorded by vncrec. */
375  const char* magic="vncLog0.0";
376  char buffer[10];
377  rfbVNCRec* rec = (rfbVNCRec*)malloc(sizeof(rfbVNCRec));
378  client->vncRec = rec;
379 
380  rec->file = fopen(client->serverHost,"rb");
381  rec->tv.tv_sec = 0;
382  rec->readTimestamp = FALSE;
383  rec->doNotSleep = FALSE;
384 
385  if (!rec->file) {
386  rfbClientLog("Could not open %s.\n",client->serverHost);
387  return FALSE;
388  }
389  setbuf(rec->file,NULL);
390  fread(buffer,1,strlen(magic),rec->file);
391  if (strncmp(buffer,magic,strlen(magic))) {
392  rfbClientLog("File %s was not recorded by vncrec.\n",client->serverHost);
393  fclose(rec->file);
394  return FALSE;
395  }
396  client->sock = -1;
397  return TRUE;
398  }
399 
400 #ifndef WIN32
401  if(IsUnixSocket(hostname))
402  /* serverHost is a UNIX socket. */
403  client->sock = ConnectClientToUnixSock(hostname);
404  else
405 #endif
406  {
407 #ifdef LIBVNCSERVER_IPv6
408  client->sock = ConnectClientToTcpAddr6(hostname, port);
409  if (client->sock == -1)
410 #endif
411  {
412  unsigned int host;
413 
414  /* serverHost is a hostname */
415  if (!StringToIPAddr(hostname, &host)) {
416  rfbClientLog("Couldn't convert '%s' to host address\n", hostname);
417  return FALSE;
418  }
419  client->sock = ConnectClientToTcpAddr(host, port);
420  }
421  }
422 
423  if (client->sock < 0) {
424  rfbClientLog("Unable to connect to VNC server\n");
425  return FALSE;
426  }
427 
428  if(client->QoS_DSCP && !SetDSCP(client->sock, client->QoS_DSCP))
429  return FALSE;
430 
431  return SetNonBlocking(client->sock);
432 }
433 
434 /*
435  * ConnectToRFBRepeater.
436  */
437 
438 rfbBool ConnectToRFBRepeater(rfbClient* client,const char *repeaterHost, int repeaterPort, const char *destHost, int destPort)
439 {
441  int major,minor;
442  char tmphost[250];
443 
444 #ifdef LIBVNCSERVER_IPv6
445  client->sock = ConnectClientToTcpAddr6(repeaterHost, repeaterPort);
446  if (client->sock == -1)
447 #endif
448  {
449  unsigned int host;
450  if (!StringToIPAddr(repeaterHost, &host)) {
451  rfbClientLog("Couldn't convert '%s' to host address\n", repeaterHost);
452  return FALSE;
453  }
454 
455  client->sock = ConnectClientToTcpAddr(host, repeaterPort);
456  }
457 
458  if (client->sock < 0) {
459  rfbClientLog("Unable to connect to VNC repeater\n");
460  return FALSE;
461  }
462 
463  if (!SetNonBlocking(client->sock))
464  return FALSE;
465 
467  return FALSE;
468  pv[sz_rfbProtocolVersionMsg] = 0;
469 
470  /* UltraVNC repeater always report version 000.000 to identify itself */
471  if (sscanf(pv,rfbProtocolVersionFormat,&major,&minor) != 2 || major != 0 || minor != 0) {
472  rfbClientLog("Not a valid VNC repeater (%s)\n",pv);
473  return FALSE;
474  }
475 
476  rfbClientLog("Connected to VNC repeater, using protocol version %d.%d\n", major, minor);
477 
478  snprintf(tmphost, sizeof(tmphost), "%s:%d", destHost, destPort);
479  if (!WriteToRFBServer(client, tmphost, sizeof(tmphost)))
480  return FALSE;
481 
482  return TRUE;
483 }
484 
485 extern void rfbClientEncryptBytes(unsigned char* bytes, char* passwd);
486 extern void rfbClientEncryptBytes2(unsigned char *where, const int length, unsigned char *key);
487 
488 rfbBool
490 {
491  uint32_t authResult=0, reasonLen=0;
492  char *reason=NULL;
493 
494  if (!ReadFromRFBServer(client, (char *)&authResult, 4)) return FALSE;
495 
496  authResult = rfbClientSwap32IfLE(authResult);
497 
498  switch (authResult) {
499  case rfbVncAuthOK:
500  rfbClientLog("VNC authentication succeeded\n");
501  return TRUE;
502  break;
503  case rfbVncAuthFailed:
504  if (client->major==3 && client->minor>7)
505  {
506  /* we have an error following */
507  if (!ReadFromRFBServer(client, (char *)&reasonLen, 4)) return FALSE;
508  reasonLen = rfbClientSwap32IfLE(reasonLen);
509  reason = malloc(reasonLen+1);
510  if (!ReadFromRFBServer(client, reason, reasonLen)) { free(reason); return FALSE; }
511  reason[reasonLen]=0;
512  rfbClientLog("VNC connection failed: %s\n",reason);
513  free(reason);
514  return FALSE;
515  }
516  rfbClientLog("VNC authentication failed\n");
517  return FALSE;
518  case rfbVncAuthTooMany:
519  rfbClientLog("VNC authentication failed - too many tries\n");
520  return FALSE;
521  }
522 
523  rfbClientLog("Unknown VNC authentication result: %d\n",
524  (int)authResult);
525  return FALSE;
526 }
527 
528 static void
529 ReadReason(rfbClient* client)
530 {
531  uint32_t reasonLen;
532  char *reason;
533 
534  /* we have an error following */
535  if (!ReadFromRFBServer(client, (char *)&reasonLen, 4)) return;
536  reasonLen = rfbClientSwap32IfLE(reasonLen);
537  reason = malloc(reasonLen+1);
538  if (!ReadFromRFBServer(client, reason, reasonLen)) { free(reason); return; }
539  reason[reasonLen]=0;
540  rfbClientLog("VNC connection failed: %s\n",reason);
541  free(reason);
542 }
543 
544 static rfbBool
545 ReadSupportedSecurityType(rfbClient* client, uint32_t *result, rfbBool subAuth)
546 {
547  uint8_t count=0;
548  uint8_t loop=0;
549  uint8_t flag=0;
550  uint8_t tAuth[256];
551  char buf1[500],buf2[10];
552  uint32_t authScheme;
553 
554  if (!ReadFromRFBServer(client, (char *)&count, 1)) return FALSE;
555 
556  if (count==0)
557  {
558  rfbClientLog("List of security types is ZERO, expecting an error to follow\n");
559  ReadReason(client);
560  return FALSE;
561  }
562 
563  rfbClientLog("We have %d security types to read\n", count);
564  authScheme=0;
565  /* now, we have a list of available security types to read ( uint8_t[] ) */
566  for (loop=0;loop<count;loop++)
567  {
568  if (!ReadFromRFBServer(client, (char *)&tAuth[loop], 1)) return FALSE;
569  rfbClientLog("%d) Received security type %d\n", loop, tAuth[loop]);
570  if (flag) continue;
571  if (tAuth[loop]==rfbVncAuth || tAuth[loop]==rfbNoAuth ||
572  (tAuth[loop]==rfbARD && client->GetCredential) ||
573  (!subAuth && (tAuth[loop]==rfbTLS || (tAuth[loop]==rfbVeNCrypt && client->GetCredential))))
574  {
575  if (!subAuth && client->clientAuthSchemes)
576  {
577  int i;
578  for (i=0;client->clientAuthSchemes[i];i++)
579  {
580  if (client->clientAuthSchemes[i]==(uint32_t)tAuth[loop])
581  {
582  flag++;
583  authScheme=tAuth[loop];
584  break;
585  }
586  }
587  }
588  else
589  {
590  flag++;
591  authScheme=tAuth[loop];
592  }
593  if (flag)
594  {
595  rfbClientLog("Selecting security type %d (%d/%d in the list)\n", authScheme, loop, count);
596  /* send back a single byte indicating which security type to use */
597  if (!WriteToRFBServer(client, (char *)&tAuth[loop], 1)) return FALSE;
598  }
599  }
600  }
601  if (authScheme==0)
602  {
603  memset(buf1, 0, sizeof(buf1));
604  for (loop=0;loop<count;loop++)
605  {
606  if (strlen(buf1)>=sizeof(buf1)-1) break;
607  snprintf(buf2, sizeof(buf2), (loop>0 ? ", %d" : "%d"), (int)tAuth[loop]);
608  strncat(buf1, buf2, sizeof(buf1)-strlen(buf1)-1);
609  }
610  rfbClientLog("Unknown authentication scheme from VNC server: %s\n",
611  buf1);
612  return FALSE;
613  }
614  *result = authScheme;
615  return TRUE;
616 }
617 
618 static rfbBool
619 HandleVncAuth(rfbClient *client)
620 {
621  uint8_t challenge[CHALLENGESIZE];
622  char *passwd=NULL;
623  int i;
624 
625  if (!ReadFromRFBServer(client, (char *)challenge, CHALLENGESIZE)) return FALSE;
626 
627  if (client->serverPort!=-1) { /* if not playing a vncrec file */
628  if (client->GetPassword)
629  passwd = client->GetPassword(client);
630 
631  if ((!passwd) || (strlen(passwd) == 0)) {
632  rfbClientLog("Reading password failed\n");
633  return FALSE;
634  }
635  if (strlen(passwd) > 8) {
636  passwd[8] = '\0';
637  }
638 
639  rfbClientEncryptBytes(challenge, passwd);
640 
641  /* Lose the password from memory */
642  for (i = strlen(passwd); i >= 0; i--) {
643  passwd[i] = '\0';
644  }
645  free(passwd);
646 
647  if (!WriteToRFBServer(client, (char *)challenge, CHALLENGESIZE)) return FALSE;
648  }
649 
650  /* Handle the SecurityResult message */
651  if (!rfbHandleAuthResult(client)) return FALSE;
652 
653  return TRUE;
654 }
655 
656 static void
657 FreeUserCredential(rfbCredential *cred)
658 {
659  if (cred->userCredential.username) free(cred->userCredential.username);
660  if (cred->userCredential.password) free(cred->userCredential.password);
661  free(cred);
662 }
663 
664 static rfbBool
665 HandlePlainAuth(rfbClient *client)
666 {
667  uint32_t ulen, ulensw;
668  uint32_t plen, plensw;
669  rfbCredential *cred;
670 
671  if (!client->GetCredential)
672  {
673  rfbClientLog("GetCredential callback is not set.\n");
674  return FALSE;
675  }
676  cred = client->GetCredential(client, rfbCredentialTypeUser);
677  if (!cred)
678  {
679  rfbClientLog("Reading credential failed\n");
680  return FALSE;
681  }
682 
683  ulen = (cred->userCredential.username ? strlen(cred->userCredential.username) : 0);
684  ulensw = rfbClientSwap32IfLE(ulen);
685  plen = (cred->userCredential.password ? strlen(cred->userCredential.password) : 0);
686  plensw = rfbClientSwap32IfLE(plen);
687  if (!WriteToRFBServer(client, (char *)&ulensw, 4) ||
688  !WriteToRFBServer(client, (char *)&plensw, 4))
689  {
690  FreeUserCredential(cred);
691  return FALSE;
692  }
693  if (ulen > 0)
694  {
695  if (!WriteToRFBServer(client, cred->userCredential.username, ulen))
696  {
697  FreeUserCredential(cred);
698  return FALSE;
699  }
700  }
701  if (plen > 0)
702  {
703  if (!WriteToRFBServer(client, cred->userCredential.password, plen))
704  {
705  FreeUserCredential(cred);
706  return FALSE;
707  }
708  }
709 
710  FreeUserCredential(cred);
711 
712  /* Handle the SecurityResult message */
713  if (!rfbHandleAuthResult(client)) return FALSE;
714 
715  return TRUE;
716 }
717 
718 /* Simple 64bit big integer arithmetic implementation */
719 /* (x + y) % m, works even if (x + y) > 64bit */
720 #define rfbAddM64(x,y,m) ((x+y)%m+(x+y<x?(((uint64_t)-1)%m+1)%m:0))
721 /* (x * y) % m */
722 static uint64_t
723 rfbMulM64(uint64_t x, uint64_t y, uint64_t m)
724 {
725  uint64_t r;
726  for(r=0;x>0;x>>=1)
727  {
728  if (x&1) r=rfbAddM64(r,y,m);
729  y=rfbAddM64(y,y,m);
730  }
731  return r;
732 }
733 /* (x ^ y) % m */
734 static uint64_t
735 rfbPowM64(uint64_t b, uint64_t e, uint64_t m)
736 {
737  uint64_t r;
738  for(r=1;e>0;e>>=1)
739  {
740  if(e&1) r=rfbMulM64(r,b,m);
741  b=rfbMulM64(b,b,m);
742  }
743  return r;
744 }
745 
746 static rfbBool
747 HandleMSLogonAuth(rfbClient *client)
748 {
749  uint64_t gen, mod, resp, priv, pub, key;
750  uint8_t username[256], password[64];
751  rfbCredential *cred;
752 
753  if (!ReadFromRFBServer(client, (char *)&gen, 8)) return FALSE;
754  if (!ReadFromRFBServer(client, (char *)&mod, 8)) return FALSE;
755  if (!ReadFromRFBServer(client, (char *)&resp, 8)) return FALSE;
756  gen = rfbClientSwap64IfLE(gen);
757  mod = rfbClientSwap64IfLE(mod);
758  resp = rfbClientSwap64IfLE(resp);
759 
760  if (!client->GetCredential)
761  {
762  rfbClientLog("GetCredential callback is not set.\n");
763  return FALSE;
764  }
765  rfbClientLog("WARNING! MSLogon security type has very low password encryption! "\
766  "Use it only with SSH tunnel or trusted network.\n");
767  cred = client->GetCredential(client, rfbCredentialTypeUser);
768  if (!cred)
769  {
770  rfbClientLog("Reading credential failed\n");
771  return FALSE;
772  }
773 
774  memset(username, 0, sizeof(username));
775  strncpy((char *)username, cred->userCredential.username, sizeof(username));
776  memset(password, 0, sizeof(password));
777  strncpy((char *)password, cred->userCredential.password, sizeof(password));
778  FreeUserCredential(cred);
779 
780  srand(time(NULL));
781  priv = ((uint64_t)rand())<<32;
782  priv |= (uint64_t)rand();
783 
784  pub = rfbPowM64(gen, priv, mod);
785  key = rfbPowM64(resp, priv, mod);
786  pub = rfbClientSwap64IfLE(pub);
787  key = rfbClientSwap64IfLE(key);
788 
789  rfbClientEncryptBytes2(username, sizeof(username), (unsigned char *)&key);
790  rfbClientEncryptBytes2(password, sizeof(password), (unsigned char *)&key);
791 
792  if (!WriteToRFBServer(client, (char *)&pub, 8)) return FALSE;
793  if (!WriteToRFBServer(client, (char *)username, sizeof(username))) return FALSE;
794  if (!WriteToRFBServer(client, (char *)password, sizeof(password))) return FALSE;
795 
796  /* Handle the SecurityResult message */
797  if (!rfbHandleAuthResult(client)) return FALSE;
798 
799  return TRUE;
800 }
801 
802 #ifdef LIBVNCSERVER_WITH_CLIENT_GCRYPT
803 static rfbBool
804 rfbMpiToBytes(const gcry_mpi_t value, uint8_t *result, size_t size)
805 {
806  gcry_error_t error;
807  size_t len;
808  int i;
809 
810  error = gcry_mpi_print(GCRYMPI_FMT_USG, result, size, &len, value);
811  if (gcry_err_code(error) != GPG_ERR_NO_ERROR)
812  {
813  rfbClientLog("gcry_mpi_print error: %s\n", gcry_strerror(error));
814  return FALSE;
815  }
816  for (i=size-1;i>(int)size-1-(int)len;--i)
817  result[i] = result[i-size+len];
818  for (;i>=0;--i)
819  result[i] = 0;
820  return TRUE;
821 }
822 
823 static rfbBool
824 HandleARDAuth(rfbClient *client)
825 {
826  uint8_t gen[2], len[2];
827  size_t keylen;
828  uint8_t *mod = NULL, *resp, *pub, *key, *shared;
829  gcry_mpi_t genmpi = NULL, modmpi = NULL, respmpi = NULL;
830  gcry_mpi_t privmpi = NULL, pubmpi = NULL, keympi = NULL;
831  gcry_md_hd_t md5 = NULL;
832  gcry_cipher_hd_t aes = NULL;
833  gcry_error_t error;
834  uint8_t userpass[128], ciphertext[128];
835  int passwordLen, usernameLen;
836  rfbCredential *cred = NULL;
837  rfbBool result = FALSE;
838 
839  while (1)
840  {
841  if (!ReadFromRFBServer(client, (char *)gen, 2))
842  break;
843  if (!ReadFromRFBServer(client, (char *)len, 2))
844  break;
845 
846  if (!client->GetCredential)
847  {
848  rfbClientLog("GetCredential callback is not set.\n");
849  break;
850  }
851  cred = client->GetCredential(client, rfbCredentialTypeUser);
852  if (!cred)
853  {
854  rfbClientLog("Reading credential failed\n");
855  break;
856  }
857 
858  keylen = 256*len[0]+len[1];
859  mod = (uint8_t*)malloc(keylen*4);
860  if (!mod)
861  {
862  rfbClientLog("malloc out of memory\n");
863  break;
864  }
865  resp = mod+keylen;
866  pub = resp+keylen;
867  key = pub+keylen;
868 
869  if (!ReadFromRFBServer(client, (char *)mod, keylen))
870  break;
871  if (!ReadFromRFBServer(client, (char *)resp, keylen))
872  break;
873 
874  error = gcry_mpi_scan(&genmpi, GCRYMPI_FMT_USG, gen, 2, NULL);
875  if (gcry_err_code(error) != GPG_ERR_NO_ERROR)
876  {
877  rfbClientLog("gcry_mpi_scan error: %s\n", gcry_strerror(error));
878  break;
879  }
880  error = gcry_mpi_scan(&modmpi, GCRYMPI_FMT_USG, mod, keylen, NULL);
881  if (gcry_err_code(error) != GPG_ERR_NO_ERROR)
882  {
883  rfbClientLog("gcry_mpi_scan error: %s\n", gcry_strerror(error));
884  break;
885  }
886  error = gcry_mpi_scan(&respmpi, GCRYMPI_FMT_USG, resp, keylen, NULL);
887  if (gcry_err_code(error) != GPG_ERR_NO_ERROR)
888  {
889  rfbClientLog("gcry_mpi_scan error: %s\n", gcry_strerror(error));
890  break;
891  }
892 
893  privmpi = gcry_mpi_new(keylen);
894  if (!privmpi)
895  {
896  rfbClientLog("gcry_mpi_new out of memory\n");
897  break;
898  }
899  gcry_mpi_randomize(privmpi, (keylen/8)*8, GCRY_STRONG_RANDOM);
900 
901  pubmpi = gcry_mpi_new(keylen);
902  if (!pubmpi)
903  {
904  rfbClientLog("gcry_mpi_new out of memory\n");
905  break;
906  }
907  gcry_mpi_powm(pubmpi, genmpi, privmpi, modmpi);
908 
909  keympi = gcry_mpi_new(keylen);
910  if (!keympi)
911  {
912  rfbClientLog("gcry_mpi_new out of memory\n");
913  break;
914  }
915  gcry_mpi_powm(keympi, respmpi, privmpi, modmpi);
916 
917  if (!rfbMpiToBytes(pubmpi, pub, keylen))
918  break;
919  if (!rfbMpiToBytes(keympi, key, keylen))
920  break;
921 
922  error = gcry_md_open(&md5, GCRY_MD_MD5, 0);
923  if (gcry_err_code(error) != GPG_ERR_NO_ERROR)
924  {
925  rfbClientLog("gcry_md_open error: %s\n", gcry_strerror(error));
926  break;
927  }
928  gcry_md_write(md5, key, keylen);
929  error = gcry_md_final(md5);
930  if (gcry_err_code(error) != GPG_ERR_NO_ERROR)
931  {
932  rfbClientLog("gcry_md_final error: %s\n", gcry_strerror(error));
933  break;
934  }
935  shared = gcry_md_read(md5, GCRY_MD_MD5);
936 
937  passwordLen = strlen(cred->userCredential.password)+1;
938  usernameLen = strlen(cred->userCredential.username)+1;
939  if (passwordLen > sizeof(userpass)/2)
940  passwordLen = sizeof(userpass)/2;
941  if (usernameLen > sizeof(userpass)/2)
942  usernameLen = sizeof(userpass)/2;
943 
944  gcry_randomize(userpass, sizeof(userpass), GCRY_STRONG_RANDOM);
945  memcpy(userpass, cred->userCredential.username, usernameLen);
946  memcpy(userpass+sizeof(userpass)/2, cred->userCredential.password, passwordLen);
947 
948  error = gcry_cipher_open(&aes, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_ECB, 0);
949  if (gcry_err_code(error) != GPG_ERR_NO_ERROR)
950  {
951  rfbClientLog("gcry_cipher_open error: %s\n", gcry_strerror(error));
952  break;
953  }
954  error = gcry_cipher_setkey(aes, shared, 16);
955  if (gcry_err_code(error) != GPG_ERR_NO_ERROR)
956  {
957  rfbClientLog("gcry_cipher_setkey error: %s\n", gcry_strerror(error));
958  break;
959  }
960  error = gcry_cipher_encrypt(aes, ciphertext, sizeof(ciphertext), userpass, sizeof(userpass));
961  if (gcry_err_code(error) != GPG_ERR_NO_ERROR)
962  {
963  rfbClientLog("gcry_cipher_encrypt error: %s\n", gcry_strerror(error));
964  break;
965  }
966 
967  if (!WriteToRFBServer(client, (char *)ciphertext, sizeof(ciphertext)))
968  break;
969  if (!WriteToRFBServer(client, (char *)pub, keylen))
970  break;
971 
972  /* Handle the SecurityResult message */
973  if (!rfbHandleAuthResult(client))
974  break;
975 
976  result = TRUE;
977  break;
978  }
979 
980  if (cred)
981  FreeUserCredential(cred);
982  if (mod)
983  free(mod);
984  if (genmpi)
985  gcry_mpi_release(genmpi);
986  if (modmpi)
987  gcry_mpi_release(modmpi);
988  if (respmpi)
989  gcry_mpi_release(respmpi);
990  if (privmpi)
991  gcry_mpi_release(privmpi);
992  if (pubmpi)
993  gcry_mpi_release(pubmpi);
994  if (keympi)
995  gcry_mpi_release(keympi);
996  if (md5)
997  gcry_md_close(md5);
998  if (aes)
999  gcry_cipher_close(aes);
1000  return result;
1001 }
1002 #endif
1003 
1004 /*
1005  * SetClientAuthSchemes.
1006  */
1007 
1008 void
1009 SetClientAuthSchemes(rfbClient* client,const uint32_t *authSchemes, int size)
1010 {
1011  int i;
1012 
1013  if (client->clientAuthSchemes)
1014  {
1015  free(client->clientAuthSchemes);
1016  client->clientAuthSchemes = NULL;
1017  }
1018  if (authSchemes)
1019  {
1020  if (size<0)
1021  {
1022  /* If size<0 we assume the passed-in list is also 0-terminate, so we
1023  * calculate the size here */
1024  for (size=0;authSchemes[size];size++) ;
1025  }
1026  client->clientAuthSchemes = (uint32_t*)malloc(sizeof(uint32_t)*(size+1));
1027  for (i=0;i<size;i++)
1028  client->clientAuthSchemes[i] = authSchemes[i];
1029  client->clientAuthSchemes[size] = 0;
1030  }
1031 }
1032 
1033 /*
1034  * InitialiseRFBConnection.
1035  */
1036 
1037 rfbBool
1039 {
1041  int major,minor;
1042  uint32_t authScheme;
1043  uint32_t subAuthScheme;
1044  rfbClientInitMsg ci;
1045 
1046  /* if the connection is immediately closed, don't report anything, so
1047  that pmw's monitor can make test connections */
1048 
1049  if (client->listenSpecified)
1051 
1052  if (!ReadFromRFBServer(client, pv, sz_rfbProtocolVersionMsg)) return FALSE;
1054 
1056 
1057  pv[sz_rfbProtocolVersionMsg] = 0;
1058 
1059  if (sscanf(pv,rfbProtocolVersionFormat,&major,&minor) != 2) {
1060  rfbClientLog("Not a valid VNC server (%s)\n",pv);
1061  return FALSE;
1062  }
1063 
1064 
1065  DefaultSupportedMessages(client);
1066  client->major = major;
1067  client->minor = minor;
1068 
1069  /* fall back to viewer supported version */
1070  if ((major==rfbProtocolMajorVersion) && (minor>rfbProtocolMinorVersion))
1071  client->minor = rfbProtocolMinorVersion;
1072 
1073  /* UltraVNC uses minor codes 4 and 6 for the server */
1074  if (major==3 && (minor==4 || minor==6)) {
1075  rfbClientLog("UltraVNC server detected, enabling UltraVNC specific messages\n",pv);
1077  }
1078 
1079  /* UltraVNC Single Click uses minor codes 14 and 16 for the server */
1080  if (major==3 && (minor==14 || minor==16)) {
1081  minor = minor - 10;
1082  client->minor = minor;
1083  rfbClientLog("UltraVNC Single Click server detected, enabling UltraVNC specific messages\n",pv);
1085  }
1086 
1087  /* TightVNC uses minor codes 5 for the server */
1088  if (major==3 && minor==5) {
1089  rfbClientLog("TightVNC server detected, enabling TightVNC specific messages\n",pv);
1091  }
1092 
1093  /* we do not support > RFB3.8 */
1094  if ((major==3 && minor>8) || major>3)
1095  {
1096  client->major=3;
1097  client->minor=8;
1098  }
1099 
1100  rfbClientLog("VNC server supports protocol version %d.%d (viewer %d.%d)\n",
1102 
1103  sprintf(pv,rfbProtocolVersionFormat,client->major,client->minor);
1104 
1105  if (!WriteToRFBServer(client, pv, sz_rfbProtocolVersionMsg)) return FALSE;
1106 
1107 
1108  /* 3.7 and onwards sends a # of security types first */
1109  if (client->major==3 && client->minor > 6)
1110  {
1111  if (!ReadSupportedSecurityType(client, &authScheme, FALSE)) return FALSE;
1112  }
1113  else
1114  {
1115  if (!ReadFromRFBServer(client, (char *)&authScheme, 4)) return FALSE;
1116  authScheme = rfbClientSwap32IfLE(authScheme);
1117  }
1118 
1119  rfbClientLog("Selected Security Scheme %d\n", authScheme);
1120  client->authScheme = authScheme;
1121 
1122  switch (authScheme) {
1123 
1124  case rfbConnFailed:
1125  ReadReason(client);
1126  return FALSE;
1127 
1128  case rfbNoAuth:
1129  rfbClientLog("No authentication needed\n");
1130 
1131  /* 3.8 and upwards sends a Security Result for rfbNoAuth */
1132  if ((client->major==3 && client->minor > 7) || client->major>3)
1133  if (!rfbHandleAuthResult(client)) return FALSE;
1134 
1135  break;
1136 
1137  case rfbVncAuth:
1138  if (!HandleVncAuth(client)) return FALSE;
1139  break;
1140 
1141  case rfbMSLogon:
1142  if (!HandleMSLogonAuth(client)) return FALSE;
1143  break;
1144 
1145  case rfbARD:
1146 #ifndef LIBVNCSERVER_WITH_CLIENT_GCRYPT
1147  rfbClientLog("GCrypt support was not compiled in\n");
1148  return FALSE;
1149 #else
1150  if (!HandleARDAuth(client)) return FALSE;
1151 #endif
1152  break;
1153 
1154  case rfbTLS:
1155  if (!HandleAnonTLSAuth(client)) return FALSE;
1156  /* After the TLS session is established, sub auth types are expected.
1157  * Note that all following reading/writing are through the TLS session from here.
1158  */
1159  if (!ReadSupportedSecurityType(client, &subAuthScheme, TRUE)) return FALSE;
1160  client->subAuthScheme = subAuthScheme;
1161 
1162  switch (subAuthScheme) {
1163 
1164  case rfbConnFailed:
1165  ReadReason(client);
1166  return FALSE;
1167 
1168  case rfbNoAuth:
1169  rfbClientLog("No sub authentication needed\n");
1170  /* 3.8 and upwards sends a Security Result for rfbNoAuth */
1171  if ((client->major==3 && client->minor > 7) || client->major>3)
1172  if (!rfbHandleAuthResult(client)) return FALSE;
1173  break;
1174 
1175  case rfbVncAuth:
1176  if (!HandleVncAuth(client)) return FALSE;
1177  break;
1178 
1179  default:
1180  rfbClientLog("Unknown sub authentication scheme from VNC server: %d\n",
1181  (int)subAuthScheme);
1182  return FALSE;
1183  }
1184 
1185  break;
1186 
1187  case rfbVeNCrypt:
1188  if (!HandleVeNCryptAuth(client)) return FALSE;
1189 
1190  switch (client->subAuthScheme) {
1191 
1192  case rfbVeNCryptTLSNone:
1193  case rfbVeNCryptX509None:
1194  rfbClientLog("No sub authentication needed\n");
1195  if (!rfbHandleAuthResult(client)) return FALSE;
1196  break;
1197 
1198  case rfbVeNCryptTLSVNC:
1199  case rfbVeNCryptX509VNC:
1200  if (!HandleVncAuth(client)) return FALSE;
1201  break;
1202 
1203  case rfbVeNCryptTLSPlain:
1204  case rfbVeNCryptX509Plain:
1205  if (!HandlePlainAuth(client)) return FALSE;
1206  break;
1207 
1208  default:
1209  rfbClientLog("Unknown sub authentication scheme from VNC server: %d\n",
1210  client->subAuthScheme);
1211  return FALSE;
1212  }
1213 
1214  break;
1215 
1216  default:
1217  rfbClientLog("Unknown authentication scheme from VNC server: %d\n",
1218  (int)authScheme);
1219  return FALSE;
1220  }
1221 
1222  ci.shared = (client->appData.shareDesktop ? 1 : 0);
1223 
1224  if (!WriteToRFBServer(client, (char *)&ci, sz_rfbClientInitMsg)) return FALSE;
1225 
1226  if (!ReadFromRFBServer(client, (char *)&client->si, sz_rfbServerInitMsg)) return FALSE;
1227 
1230  client->si.format.redMax = rfbClientSwap16IfLE(client->si.format.redMax);
1231  client->si.format.greenMax = rfbClientSwap16IfLE(client->si.format.greenMax);
1232  client->si.format.blueMax = rfbClientSwap16IfLE(client->si.format.blueMax);
1233  client->si.nameLength = rfbClientSwap32IfLE(client->si.nameLength);
1234 
1235  client->desktopName = malloc(client->si.nameLength + 1);
1236  if (!client->desktopName) {
1237  rfbClientLog("Error allocating memory for desktop name, %lu bytes\n",
1238  (unsigned long)client->si.nameLength);
1239  return FALSE;
1240  }
1241 
1242  if (!ReadFromRFBServer(client, client->desktopName, client->si.nameLength)) return FALSE;
1243 
1244  client->desktopName[client->si.nameLength] = 0;
1245 
1246  rfbClientLog("Desktop name \"%s\"\n",client->desktopName);
1247 
1248  rfbClientLog("Connected to VNC server, using protocol version %d.%d\n",
1249  client->major, client->minor);
1250 
1251  rfbClientLog("VNC server default format:\n");
1252  PrintPixelFormat(&client->si.format);
1253 
1254  return TRUE;
1255 }
1256 
1257 
1258 /*
1259  * SetFormatAndEncodings.
1260  */
1261 
1262 rfbBool
1264 {
1266  char buf[sz_rfbSetEncodingsMsg + MAX_ENCODINGS * 4];
1267 
1269  uint32_t *encs = (uint32_t *)(&buf[sz_rfbSetEncodingsMsg]);
1270  int len = 0;
1271  rfbBool requestCompressLevel = FALSE;
1272  rfbBool requestQualityLevel = FALSE;
1273  rfbBool requestLastRectEncoding = FALSE;
1275 
1276  if (!SupportsClient2Server(client, rfbSetPixelFormat)) return TRUE;
1277 
1278  spf.type = rfbSetPixelFormat;
1279  spf.format = client->format;
1283 
1284  if (!WriteToRFBServer(client, (char *)&spf, sz_rfbSetPixelFormatMsg))
1285  return FALSE;
1286 
1287 
1288  if (!SupportsClient2Server(client, rfbSetEncodings)) return TRUE;
1289 
1290  se->type = rfbSetEncodings;
1291  se->nEncodings = 0;
1292 
1293  if (client->appData.encodingsString) {
1294  const char *encStr = client->appData.encodingsString;
1295  int encStrLen;
1296  do {
1297  const char *nextEncStr = strchr(encStr, ' ');
1298  if (nextEncStr) {
1299  encStrLen = nextEncStr - encStr;
1300  nextEncStr++;
1301  } else {
1302  encStrLen = strlen(encStr);
1303  }
1304 
1305  if (strncasecmp(encStr,"raw",encStrLen) == 0) {
1307  } else if (strncasecmp(encStr,"copyrect",encStrLen) == 0) {
1309 #ifdef LIBVNCSERVER_HAVE_LIBZ
1310 #ifdef LIBVNCSERVER_HAVE_LIBJPEG
1311  } else if (strncasecmp(encStr,"tight",encStrLen) == 0) {
1313  requestLastRectEncoding = TRUE;
1314  if (client->appData.compressLevel >= 0 && client->appData.compressLevel <= 9)
1315  requestCompressLevel = TRUE;
1316  if (client->appData.enableJPEG)
1317  requestQualityLevel = TRUE;
1318 #endif
1319 #endif
1320  } else if (strncasecmp(encStr,"hextile",encStrLen) == 0) {
1322 #ifdef LIBVNCSERVER_HAVE_LIBZ
1323  } else if (strncasecmp(encStr,"zlib",encStrLen) == 0) {
1325  if (client->appData.compressLevel >= 0 && client->appData.compressLevel <= 9)
1326  requestCompressLevel = TRUE;
1327  } else if (strncasecmp(encStr,"zlibhex",encStrLen) == 0) {
1329  if (client->appData.compressLevel >= 0 && client->appData.compressLevel <= 9)
1330  requestCompressLevel = TRUE;
1331  } else if (strncasecmp(encStr,"zrle",encStrLen) == 0) {
1333  } else if (strncasecmp(encStr,"zywrle",encStrLen) == 0) {
1335  requestQualityLevel = TRUE;
1336 #endif
1337  } else if ((strncasecmp(encStr,"ultra",encStrLen) == 0) || (strncasecmp(encStr,"ultrazip",encStrLen) == 0)) {
1338  /* There are 2 encodings used in 'ultra' */
1341  } else if (strncasecmp(encStr,"corre",encStrLen) == 0) {
1343  } else if (strncasecmp(encStr,"rre",encStrLen) == 0) {
1345  } else {
1346  rfbClientLog("Unknown encoding '%.*s'\n",encStrLen,encStr);
1347  }
1348 
1349  encStr = nextEncStr;
1350  } while (encStr && se->nEncodings < MAX_ENCODINGS);
1351 
1352  if (se->nEncodings < MAX_ENCODINGS && requestCompressLevel) {
1353  encs[se->nEncodings++] = rfbClientSwap32IfLE(client->appData.compressLevel +
1355  }
1356 
1357  if (se->nEncodings < MAX_ENCODINGS && requestQualityLevel) {
1358  if (client->appData.qualityLevel < 0 || client->appData.qualityLevel > 9)
1359  client->appData.qualityLevel = 5;
1360  encs[se->nEncodings++] = rfbClientSwap32IfLE(client->appData.qualityLevel +
1362  }
1363  }
1364  else {
1365  if (SameMachine(client->sock)) {
1366  /* TODO:
1367  if (!tunnelSpecified) {
1368  */
1369  rfbClientLog("Same machine: preferring raw encoding\n");
1371  /*
1372  } else {
1373  rfbClientLog("Tunneling active: preferring tight encoding\n");
1374  }
1375  */
1376  }
1377 
1379 #ifdef LIBVNCSERVER_HAVE_LIBZ
1380 #ifdef LIBVNCSERVER_HAVE_LIBJPEG
1382  requestLastRectEncoding = TRUE;
1383 #endif
1384 #endif
1386 #ifdef LIBVNCSERVER_HAVE_LIBZ
1390 #endif
1395 
1396  if (client->appData.compressLevel >= 0 && client->appData.compressLevel <= 9) {
1397  encs[se->nEncodings++] = rfbClientSwap32IfLE(client->appData.compressLevel +
1399  } else /* if (!tunnelSpecified) */ {
1400  /* If -tunnel option was provided, we assume that server machine is
1401  not in the local network so we use default compression level for
1402  tight encoding instead of fast compression. Thus we are
1403  requesting level 1 compression only if tunneling is not used. */
1405  }
1406 
1407  if (client->appData.enableJPEG) {
1408  if (client->appData.qualityLevel < 0 || client->appData.qualityLevel > 9)
1409  client->appData.qualityLevel = 5;
1410  encs[se->nEncodings++] = rfbClientSwap32IfLE(client->appData.qualityLevel +
1412  }
1413  }
1414 
1415 
1416 
1417  /* Remote Cursor Support (local to viewer) */
1418  if (client->appData.useRemoteCursor) {
1419  if (se->nEncodings < MAX_ENCODINGS)
1421  if (se->nEncodings < MAX_ENCODINGS)
1423  if (se->nEncodings < MAX_ENCODINGS)
1425  }
1426 
1427  /* Keyboard State Encodings */
1428  if (se->nEncodings < MAX_ENCODINGS)
1430 
1431  /* New Frame Buffer Size */
1432  if (se->nEncodings < MAX_ENCODINGS && client->canHandleNewFBSize)
1434 
1435  /* Last Rect */
1436  if (se->nEncodings < MAX_ENCODINGS && requestLastRectEncoding)
1438 
1439  /* Server Capabilities */
1440  if (se->nEncodings < MAX_ENCODINGS)
1442  if (se->nEncodings < MAX_ENCODINGS)
1444  if (se->nEncodings < MAX_ENCODINGS)
1446 
1447  /* xvp */
1448  if (se->nEncodings < MAX_ENCODINGS)
1450 
1451  /* client extensions */
1452  for(e = rfbClientExtensions; e; e = e->next)
1453  if(e->encodings) {
1454  int* enc;
1455  for(enc = e->encodings; *enc; enc++)
1456  encs[se->nEncodings++] = rfbClientSwap32IfLE(*enc);
1457  }
1458 
1459  len = sz_rfbSetEncodingsMsg + se->nEncodings * 4;
1460 
1462 
1463  if (!WriteToRFBServer(client, buf, len)) return FALSE;
1464 
1465  return TRUE;
1466 }
1467 
1468 
1469 /*
1470  * SendIncrementalFramebufferUpdateRequest.
1471  */
1472 
1473 rfbBool
1475 {
1476  return SendFramebufferUpdateRequest(client,
1477  client->updateRect.x, client->updateRect.y,
1478  client->updateRect.w, client->updateRect.h, TRUE);
1479 }
1480 
1481 
1482 /*
1483  * SendFramebufferUpdateRequest.
1484  */
1485 
1486 rfbBool
1487 SendFramebufferUpdateRequest(rfbClient* client, int x, int y, int w, int h, rfbBool incremental)
1488 {
1490 
1492 
1494  fur.incremental = incremental ? 1 : 0;
1495  fur.x = rfbClientSwap16IfLE(x);
1496  fur.y = rfbClientSwap16IfLE(y);
1497  fur.w = rfbClientSwap16IfLE(w);
1498  fur.h = rfbClientSwap16IfLE(h);
1499 
1500  if (!WriteToRFBServer(client, (char *)&fur, sz_rfbFramebufferUpdateRequestMsg))
1501  return FALSE;
1502 
1503  return TRUE;
1504 }
1505 
1506 
1507 /*
1508  * SendScaleSetting.
1509  */
1510 rfbBool
1511 SendScaleSetting(rfbClient* client,int scaleSetting)
1512 {
1513  rfbSetScaleMsg ssm;
1514 
1515  ssm.scale = scaleSetting;
1516  ssm.pad = 0;
1517 
1518  /* favor UltraVNC SetScale if both are supported */
1519  if (SupportsClient2Server(client, rfbSetScale)) {
1520  ssm.type = rfbSetScale;
1521  if (!WriteToRFBServer(client, (char *)&ssm, sz_rfbSetScaleMsg))
1522  return FALSE;
1523  }
1524 
1527  if (!WriteToRFBServer(client, (char *)&ssm, sz_rfbSetScaleMsg))
1528  return FALSE;
1529  }
1530 
1531  return TRUE;
1532 }
1533 
1534 /*
1535  * TextChatFunctions (UltraVNC)
1536  * Extremely bandwidth friendly method of communicating with a user
1537  * (Think HelpDesk type applications)
1538  */
1539 
1540 rfbBool TextChatSend(rfbClient* client, char *text)
1541 {
1542  rfbTextChatMsg chat;
1543  int count = strlen(text);
1544 
1545  if (!SupportsClient2Server(client, rfbTextChat)) return TRUE;
1546  chat.type = rfbTextChat;
1547  chat.pad1 = 0;
1548  chat.pad2 = 0;
1549  chat.length = (uint32_t)count;
1550  chat.length = rfbClientSwap32IfLE(chat.length);
1551 
1552  if (!WriteToRFBServer(client, (char *)&chat, sz_rfbTextChatMsg))
1553  return FALSE;
1554 
1555  if (count>0) {
1556  if (!WriteToRFBServer(client, text, count))
1557  return FALSE;
1558  }
1559  return TRUE;
1560 }
1561 
1563 {
1564  rfbTextChatMsg chat;
1565 
1566  if (!SupportsClient2Server(client, rfbTextChat)) return TRUE;
1567  chat.type = rfbTextChat;
1568  chat.pad1 = 0;
1569  chat.pad2 = 0;
1571  return (WriteToRFBServer(client, (char *)&chat, sz_rfbTextChatMsg) ? TRUE : FALSE);
1572 }
1573 
1575 {
1576  rfbTextChatMsg chat;
1577  if (!SupportsClient2Server(client, rfbTextChat)) return TRUE;
1578  chat.type = rfbTextChat;
1579  chat.pad1 = 0;
1580  chat.pad2 = 0;
1582  return (WriteToRFBServer(client, (char *)&chat, sz_rfbTextChatMsg) ? TRUE : FALSE);
1583 }
1584 
1586 {
1587  rfbTextChatMsg chat;
1588  if (!SupportsClient2Server(client, rfbTextChat)) return TRUE;
1589  chat.type = rfbTextChat;
1590  chat.pad1 = 0;
1591  chat.pad2 = 0;
1593  return (WriteToRFBServer(client, (char *)&chat, sz_rfbTextChatMsg) ? TRUE : FALSE);
1594 }
1595 
1596 /*
1597  * UltraVNC Server Input Disable
1598  * Apparently, the remote client can *prevent* the local user from interacting with the display
1599  * I would think this is extremely helpful when used in a HelpDesk situation
1600  */
1601 rfbBool PermitServerInput(rfbClient* client, int enabled)
1602 {
1604 
1605  if (!SupportsClient2Server(client, rfbSetServerInput)) return TRUE;
1606  /* enabled==1, then server input from local keyboard is disabled */
1607  msg.type = rfbSetServerInput;
1608  msg.status = (enabled ? 1 : 0);
1609  msg.pad = 0;
1610  return (WriteToRFBServer(client, (char *)&msg, sz_rfbSetServerInputMsg) ? TRUE : FALSE);
1611 }
1612 
1613 
1614 /*
1615  * send xvp client message
1616  * A client supporting the xvp extension sends this to request that the server initiate
1617  * a clean shutdown, clean reboot or abrupt reset of the system whose framebuffer the
1618  * client is displaying.
1619  *
1620  * only version 1 is defined in the protocol specs
1621  *
1622  * possible values for code are:
1623  * rfbXvp_Shutdown
1624  * rfbXvp_Reboot
1625  * rfbXvp_Reset
1626  */
1627 
1628 rfbBool SendXvpMsg(rfbClient* client, uint8_t version, uint8_t code)
1629 {
1630  rfbXvpMsg xvp;
1631 
1632  if (!SupportsClient2Server(client, rfbXvp)) return TRUE;
1633  xvp.type = rfbXvp;
1634  xvp.pad = 0;
1635  xvp.version = version;
1636  xvp.code = code;
1637 
1638  if (!WriteToRFBServer(client, (char *)&xvp, sz_rfbXvpMsg))
1639  return FALSE;
1640 
1641  return TRUE;
1642 }
1643 
1644 
1645 /*
1646  * SendPointerEvent.
1647  */
1648 
1649 rfbBool
1650 SendPointerEvent(rfbClient* client,int x, int y, int buttonMask)
1651 {
1652  rfbPointerEventMsg pe;
1653 
1654  if (!SupportsClient2Server(client, rfbPointerEvent)) return TRUE;
1655 
1656  pe.type = rfbPointerEvent;
1657  pe.buttonMask = buttonMask;
1658  if (x < 0) x = 0;
1659  if (y < 0) y = 0;
1660 
1661  pe.x = rfbClientSwap16IfLE(x);
1662  pe.y = rfbClientSwap16IfLE(y);
1663  return WriteToRFBServer(client, (char *)&pe, sz_rfbPointerEventMsg);
1664 }
1665 
1666 
1667 /*
1668  * SendKeyEvent.
1669  */
1670 
1671 rfbBool
1672 SendKeyEvent(rfbClient* client, uint32_t key, rfbBool down)
1673 {
1674  rfbKeyEventMsg ke;
1675 
1676  if (!SupportsClient2Server(client, rfbKeyEvent)) return TRUE;
1677 
1678  ke.type = rfbKeyEvent;
1679  ke.down = down ? 1 : 0;
1680  ke.key = rfbClientSwap32IfLE(key);
1681  return WriteToRFBServer(client, (char *)&ke, sz_rfbKeyEventMsg);
1682 }
1683 
1684 
1685 /*
1686  * SendClientCutText.
1687  */
1688 
1689 rfbBool
1690 SendClientCutText(rfbClient* client, char *str, int len)
1691 {
1692  rfbClientCutTextMsg cct;
1693 
1694  if (!SupportsClient2Server(client, rfbClientCutText)) return TRUE;
1695 
1696  cct.type = rfbClientCutText;
1697  cct.length = rfbClientSwap32IfLE(len);
1698  return (WriteToRFBServer(client, (char *)&cct, sz_rfbClientCutTextMsg) &&
1699  WriteToRFBServer(client, str, len));
1700 }
1701 
1702 
1703 
1704 /*
1705  * HandleRFBServerMessage.
1706  */
1707 
1708 rfbBool
1710 {
1712 
1713  if (client->serverPort==-1)
1714  client->vncRec->readTimestamp = TRUE;
1715  if (!ReadFromRFBServer(client, (char *)&msg, 1))
1716  return FALSE;
1717 
1718  switch (msg.type) {
1719 
1721  {
1722  /* TODO:
1723  int i;
1724  uint16_t rgb[3];
1725  XColor xc;
1726 
1727  if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
1728  sz_rfbSetColourMapEntriesMsg - 1))
1729  return FALSE;
1730 
1731  msg.scme.firstColour = rfbClientSwap16IfLE(msg.scme.firstColour);
1732  msg.scme.nColours = rfbClientSwap16IfLE(msg.scme.nColours);
1733 
1734  for (i = 0; i < msg.scme.nColours; i++) {
1735  if (!ReadFromRFBServer(client, (char *)rgb, 6))
1736  return FALSE;
1737  xc.pixel = msg.scme.firstColour + i;
1738  xc.red = rfbClientSwap16IfLE(rgb[0]);
1739  xc.green = rfbClientSwap16IfLE(rgb[1]);
1740  xc.blue = rfbClientSwap16IfLE(rgb[2]);
1741  xc.flags = DoRed|DoGreen|DoBlue;
1742  XStoreColor(dpy, cmap, &xc);
1743  }
1744  */
1745 
1746  break;
1747  }
1748 
1749  case rfbFramebufferUpdate:
1750  {
1752  int linesToRead;
1753  int bytesPerLine;
1754  int i;
1755 
1756  if (!ReadFromRFBServer(client, ((char *)&msg.fu) + 1,
1758  return FALSE;
1759 
1760  msg.fu.nRects = rfbClientSwap16IfLE(msg.fu.nRects);
1761 
1762  for (i = 0; i < msg.fu.nRects; i++) {
1763  if (!ReadFromRFBServer(client, (char *)&rect, sz_rfbFramebufferUpdateRectHeader))
1764  return FALSE;
1765 
1766  rect.encoding = rfbClientSwap32IfLE(rect.encoding);
1767  if (rect.encoding == rfbEncodingLastRect)
1768  break;
1769 
1770  rect.r.x = rfbClientSwap16IfLE(rect.r.x);
1771  rect.r.y = rfbClientSwap16IfLE(rect.r.y);
1772  rect.r.w = rfbClientSwap16IfLE(rect.r.w);
1773  rect.r.h = rfbClientSwap16IfLE(rect.r.h);
1774 
1775 
1776  if (rect.encoding == rfbEncodingXCursor ||
1777  rect.encoding == rfbEncodingRichCursor) {
1778 
1779  if (!HandleCursorShape(client,
1780  rect.r.x, rect.r.y, rect.r.w, rect.r.h,
1781  rect.encoding)) {
1782  return FALSE;
1783  }
1784  continue;
1785  }
1786 
1787  if (rect.encoding == rfbEncodingPointerPos) {
1788  if (!client->HandleCursorPos(client,rect.r.x, rect.r.y)) {
1789  return FALSE;
1790  }
1791  continue;
1792  }
1793 
1794  if (rect.encoding == rfbEncodingKeyboardLedState) {
1795  /* OK! We have received a keyboard state message!!! */
1796  client->KeyboardLedStateEnabled = 1;
1797  if (client->HandleKeyboardLedState!=NULL)
1798  client->HandleKeyboardLedState(client, rect.r.x, 0);
1799  /* stash it for the future */
1800  client->CurrentKeyboardLedState = rect.r.x;
1801  continue;
1802  }
1803 
1804  if (rect.encoding == rfbEncodingNewFBSize) {
1805  client->width = rect.r.w;
1806  client->height = rect.r.h;
1807  client->updateRect.x = client->updateRect.y = 0;
1808  client->updateRect.w = client->width;
1809  client->updateRect.h = client->height;
1810  client->MallocFrameBuffer(client);
1811  SendFramebufferUpdateRequest(client, 0, 0, rect.r.w, rect.r.h, FALSE);
1812  rfbClientLog("Got new framebuffer size: %dx%d\n", rect.r.w, rect.r.h);
1813  continue;
1814  }
1815 
1816  /* rect.r.w=byte count */
1817  if (rect.encoding == rfbEncodingSupportedMessages) {
1818  int loop;
1819  if (!ReadFromRFBServer(client, (char *)&client->supportedMessages, sz_rfbSupportedMessages))
1820  return FALSE;
1821 
1822  /* msgs is two sets of bit flags of supported messages client2server[] and server2client[] */
1823  /* currently ignored by this library */
1824 
1825  rfbClientLog("client2server supported messages (bit flags)\n");
1826  for (loop=0;loop<32;loop+=8)
1827  rfbClientLog("%02X: %04x %04x %04x %04x - %04x %04x %04x %04x\n", loop,
1828  client->supportedMessages.client2server[loop], client->supportedMessages.client2server[loop+1],
1829  client->supportedMessages.client2server[loop+2], client->supportedMessages.client2server[loop+3],
1830  client->supportedMessages.client2server[loop+4], client->supportedMessages.client2server[loop+5],
1831  client->supportedMessages.client2server[loop+6], client->supportedMessages.client2server[loop+7]);
1832 
1833  rfbClientLog("server2client supported messages (bit flags)\n");
1834  for (loop=0;loop<32;loop+=8)
1835  rfbClientLog("%02X: %04x %04x %04x %04x - %04x %04x %04x %04x\n", loop,
1836  client->supportedMessages.server2client[loop], client->supportedMessages.server2client[loop+1],
1837  client->supportedMessages.server2client[loop+2], client->supportedMessages.server2client[loop+3],
1838  client->supportedMessages.server2client[loop+4], client->supportedMessages.server2client[loop+5],
1839  client->supportedMessages.server2client[loop+6], client->supportedMessages.server2client[loop+7]);
1840  continue;
1841  }
1842 
1843  /* rect.r.w=byte count, rect.r.h=# of encodings */
1845  char *buffer;
1846  buffer = malloc(rect.r.w);
1847  if (!ReadFromRFBServer(client, buffer, rect.r.w))
1848  {
1849  free(buffer);
1850  return FALSE;
1851  }
1852 
1853  /* buffer now contains rect.r.h # of uint32_t encodings that the server supports */
1854  /* currently ignored by this library */
1855  free(buffer);
1856  continue;
1857  }
1858 
1859  /* rect.r.w=byte count */
1860  if (rect.encoding == rfbEncodingServerIdentity) {
1861  char *buffer;
1862  buffer = malloc(rect.r.w+1);
1863  if (!ReadFromRFBServer(client, buffer, rect.r.w))
1864  {
1865  free(buffer);
1866  return FALSE;
1867  }
1868  buffer[rect.r.w]=0; /* null terminate, just in case */
1869  rfbClientLog("Connected to Server \"%s\"\n", buffer);
1870  free(buffer);
1871  continue;
1872  }
1873 
1874  /* rfbEncodingUltraZip is a collection of subrects. x = # of subrects, and h is always 0 */
1875  if (rect.encoding != rfbEncodingUltraZip)
1876  {
1877  if ((rect.r.x + rect.r.w > client->width) ||
1878  (rect.r.y + rect.r.h > client->height))
1879  {
1880  rfbClientLog("Rect too large: %dx%d at (%d, %d)\n",
1881  rect.r.w, rect.r.h, rect.r.x, rect.r.y);
1882  return FALSE;
1883  }
1884 
1885  /* UltraVNC with scaling, will send rectangles with a zero W or H
1886  *
1887  if ((rect.encoding != rfbEncodingTight) &&
1888  (rect.r.h * rect.r.w == 0))
1889  {
1890  rfbClientLog("Zero size rect - ignoring (encoding=%d (0x%08x) %dx, %dy, %dw, %dh)\n", rect.encoding, rect.encoding, rect.r.x, rect.r.y, rect.r.w, rect.r.h);
1891  continue;
1892  }
1893  */
1894 
1895  /* If RichCursor encoding is used, we should prevent collisions
1896  between framebuffer updates and cursor drawing operations. */
1897  client->SoftCursorLockArea(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h);
1898  }
1899 
1900  switch (rect.encoding) {
1901 
1902  case rfbEncodingRaw: {
1903  int y=rect.r.y, h=rect.r.h;
1904 
1905  bytesPerLine = rect.r.w * client->format.bitsPerPixel / 8;
1906  linesToRead = RFB_BUFFER_SIZE / bytesPerLine;
1907 
1908  while (h > 0) {
1909  if (linesToRead > h)
1910  linesToRead = h;
1911 
1912  if (!ReadFromRFBServer(client, client->buffer,bytesPerLine * linesToRead))
1913  return FALSE;
1914 
1915  CopyRectangle(client, (uint8_t *)client->buffer,
1916  rect.r.x, y, rect.r.w,linesToRead);
1917 
1918  h -= linesToRead;
1919  y += linesToRead;
1920 
1921  }
1922  } break;
1923 
1924  case rfbEncodingCopyRect:
1925  {
1926  rfbCopyRect cr;
1927 
1928  if (!ReadFromRFBServer(client, (char *)&cr, sz_rfbCopyRect))
1929  return FALSE;
1930 
1931  cr.srcX = rfbClientSwap16IfLE(cr.srcX);
1932  cr.srcY = rfbClientSwap16IfLE(cr.srcY);
1933 
1934  /* If RichCursor encoding is used, we should extend our
1935  "cursor lock area" (previously set to destination
1936  rectangle) to the source rectangle as well. */
1937  client->SoftCursorLockArea(client,
1938  cr.srcX, cr.srcY, rect.r.w, rect.r.h);
1939 
1940  if (client->GotCopyRect != NULL) {
1941  client->GotCopyRect(client, cr.srcX, cr.srcY, rect.r.w, rect.r.h,
1942  rect.r.x, rect.r.y);
1943  } else
1944  CopyRectangleFromRectangle(client,
1945  cr.srcX, cr.srcY, rect.r.w, rect.r.h,
1946  rect.r.x, rect.r.y);
1947 
1948  break;
1949  }
1950 
1951  case rfbEncodingRRE:
1952  {
1953  switch (client->format.bitsPerPixel) {
1954  case 8:
1955  if (!HandleRRE8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1956  return FALSE;
1957  break;
1958  case 16:
1959  if (!HandleRRE16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1960  return FALSE;
1961  break;
1962  case 32:
1963  if (!HandleRRE32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1964  return FALSE;
1965  break;
1966  }
1967  break;
1968  }
1969 
1970  case rfbEncodingCoRRE:
1971  {
1972  switch (client->format.bitsPerPixel) {
1973  case 8:
1974  if (!HandleCoRRE8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1975  return FALSE;
1976  break;
1977  case 16:
1978  if (!HandleCoRRE16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1979  return FALSE;
1980  break;
1981  case 32:
1982  if (!HandleCoRRE32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1983  return FALSE;
1984  break;
1985  }
1986  break;
1987  }
1988 
1989  case rfbEncodingHextile:
1990  {
1991  switch (client->format.bitsPerPixel) {
1992  case 8:
1993  if (!HandleHextile8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1994  return FALSE;
1995  break;
1996  case 16:
1997  if (!HandleHextile16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1998  return FALSE;
1999  break;
2000  case 32:
2001  if (!HandleHextile32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
2002  return FALSE;
2003  break;
2004  }
2005  break;
2006  }
2007 
2008  case rfbEncodingUltra:
2009  {
2010  switch (client->format.bitsPerPixel) {
2011  case 8:
2012  if (!HandleUltra8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
2013  return FALSE;
2014  break;
2015  case 16:
2016  if (!HandleUltra16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
2017  return FALSE;
2018  break;
2019  case 32:
2020  if (!HandleUltra32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
2021  return FALSE;
2022  break;
2023  }
2024  break;
2025  }
2026  case rfbEncodingUltraZip:
2027  {
2028  switch (client->format.bitsPerPixel) {
2029  case 8:
2030  if (!HandleUltraZip8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
2031  return FALSE;
2032  break;
2033  case 16:
2034  if (!HandleUltraZip16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
2035  return FALSE;
2036  break;
2037  case 32:
2038  if (!HandleUltraZip32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
2039  return FALSE;
2040  break;
2041  }
2042  break;
2043  }
2044 
2045 #ifdef LIBVNCSERVER_HAVE_LIBZ
2046  case rfbEncodingZlib:
2047  {
2048  switch (client->format.bitsPerPixel) {
2049  case 8:
2050  if (!HandleZlib8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
2051  return FALSE;
2052  break;
2053  case 16:
2054  if (!HandleZlib16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
2055  return FALSE;
2056  break;
2057  case 32:
2058  if (!HandleZlib32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
2059  return FALSE;
2060  break;
2061  }
2062  break;
2063  }
2064 
2065 #ifdef LIBVNCSERVER_HAVE_LIBJPEG
2066  case rfbEncodingTight:
2067  {
2068  switch (client->format.bitsPerPixel) {
2069  case 8:
2070  if (!HandleTight8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
2071  return FALSE;
2072  break;
2073  case 16:
2074  if (!HandleTight16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
2075  return FALSE;
2076  break;
2077  case 32:
2078  if (!HandleTight32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
2079  return FALSE;
2080  break;
2081  }
2082  break;
2083  }
2084 #endif
2085  case rfbEncodingZRLE:
2086  /* Fail safe for ZYWRLE unsupport VNC server. */
2087  client->appData.qualityLevel = 9;
2088  /* fall through */
2089  case rfbEncodingZYWRLE:
2090  {
2091  switch (client->format.bitsPerPixel) {
2092  case 8:
2093  if (!HandleZRLE8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
2094  return FALSE;
2095  break;
2096  case 16:
2097  if (client->si.format.greenMax > 0x1F) {
2098  if (!HandleZRLE16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
2099  return FALSE;
2100  } else {
2101  if (!HandleZRLE15(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
2102  return FALSE;
2103  }
2104  break;
2105  case 32:
2106  {
2107  uint32_t maxColor=(client->format.redMax<<client->format.redShift)|
2108  (client->format.greenMax<<client->format.greenShift)|
2109  (client->format.blueMax<<client->format.blueShift);
2110  if ((client->format.bigEndian && (maxColor&0xff)==0) ||
2111  (!client->format.bigEndian && (maxColor&0xff000000)==0)) {
2112  if (!HandleZRLE24(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
2113  return FALSE;
2114  } else if (!client->format.bigEndian && (maxColor&0xff)==0) {
2115  if (!HandleZRLE24Up(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
2116  return FALSE;
2117  } else if (client->format.bigEndian && (maxColor&0xff000000)==0) {
2118  if (!HandleZRLE24Down(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
2119  return FALSE;
2120  } else if (!HandleZRLE32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
2121  return FALSE;
2122  break;
2123  }
2124  }
2125  break;
2126  }
2127 
2128 #endif
2129 
2130  default:
2131  {
2132  rfbBool handled = FALSE;
2134 
2135  for(e = rfbClientExtensions; !handled && e; e = e->next)
2136  if(e->handleEncoding && e->handleEncoding(client, &rect))
2137  handled = TRUE;
2138 
2139  if(!handled) {
2140  rfbClientLog("Unknown rect encoding %d\n",
2141  (int)rect.encoding);
2142  return FALSE;
2143  }
2144  }
2145  }
2146 
2147  /* Now we may discard "soft cursor locks". */
2148  client->SoftCursorUnlockScreen(client);
2149 
2150  client->GotFrameBufferUpdate(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h);
2151  }
2152 
2154  return FALSE;
2155 
2156  if (client->FinishedFrameBufferUpdate)
2157  client->FinishedFrameBufferUpdate(client);
2158 
2159  break;
2160  }
2161 
2162  case rfbBell:
2163  {
2164  client->Bell(client);
2165 
2166  break;
2167  }
2168 
2169  case rfbServerCutText:
2170  {
2171  char *buffer;
2172 
2173  if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
2175  return FALSE;
2176 
2178 
2179  buffer = malloc(msg.sct.length+1);
2180 
2181  if (!ReadFromRFBServer(client, buffer, msg.sct.length))
2182  return FALSE;
2183 
2184  buffer[msg.sct.length] = 0;
2185 
2186  if (client->GotXCutText)
2187  client->GotXCutText(client, buffer, msg.sct.length);
2188 
2189  free(buffer);
2190 
2191  break;
2192  }
2193 
2194  case rfbTextChat:
2195  {
2196  char *buffer=NULL;
2197  if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
2198  sz_rfbTextChatMsg- 1))
2199  return FALSE;
2200  msg.tc.length = rfbClientSwap32IfLE(msg.sct.length);
2201  switch(msg.tc.length) {
2202  case rfbTextChatOpen:
2203  rfbClientLog("Received TextChat Open\n");
2204  if (client->HandleTextChat!=NULL)
2205  client->HandleTextChat(client, (int)rfbTextChatOpen, NULL);
2206  break;
2207  case rfbTextChatClose:
2208  rfbClientLog("Received TextChat Close\n");
2209  if (client->HandleTextChat!=NULL)
2210  client->HandleTextChat(client, (int)rfbTextChatClose, NULL);
2211  break;
2212  case rfbTextChatFinished:
2213  rfbClientLog("Received TextChat Finished\n");
2214  if (client->HandleTextChat!=NULL)
2215  client->HandleTextChat(client, (int)rfbTextChatFinished, NULL);
2216  break;
2217  default:
2218  buffer=malloc(msg.tc.length+1);
2219  if (!ReadFromRFBServer(client, buffer, msg.tc.length))
2220  {
2221  free(buffer);
2222  return FALSE;
2223  }
2224  /* Null Terminate <just in case> */
2225  buffer[msg.tc.length]=0;
2226  rfbClientLog("Received TextChat \"%s\"\n", buffer);
2227  if (client->HandleTextChat!=NULL)
2228  client->HandleTextChat(client, (int)msg.tc.length, buffer);
2229  free(buffer);
2230  break;
2231  }
2232  break;
2233  }
2234 
2235  case rfbXvp:
2236  {
2237  if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
2238  sz_rfbXvpMsg -1))
2239  return FALSE;
2240 
2241  SetClient2Server(client, rfbXvp);
2242  /* technically, we only care what we can *send* to the server
2243  * but, we set Server2Client Just in case it ever becomes useful
2244  */
2245  SetServer2Client(client, rfbXvp);
2246 
2247  if(client->HandleXvpMsg)
2248  client->HandleXvpMsg(client, msg.xvp.version, msg.xvp.code);
2249 
2250  break;
2251  }
2252 
2253  case rfbResizeFrameBuffer:
2254  {
2255  if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
2257  return FALSE;
2260  client->updateRect.x = client->updateRect.y = 0;
2261  client->updateRect.w = client->width;
2262  client->updateRect.h = client->height;
2263  client->MallocFrameBuffer(client);
2264  SendFramebufferUpdateRequest(client, 0, 0, client->width, client->height, FALSE);
2265  rfbClientLog("Got new framebuffer size: %dx%d\n", client->width, client->height);
2266  break;
2267  }
2268 
2270  {
2271  if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
2273  return FALSE;
2274  client->width = rfbClientSwap16IfLE(msg.prsfb.buffer_w);
2275  client->height = rfbClientSwap16IfLE(msg.prsfb.buffer_h);
2276  client->updateRect.x = client->updateRect.y = 0;
2277  client->updateRect.w = client->width;
2278  client->updateRect.h = client->height;
2279  client->MallocFrameBuffer(client);
2280  SendFramebufferUpdateRequest(client, 0, 0, client->width, client->height, FALSE);
2281  rfbClientLog("Got new framebuffer size: %dx%d\n", client->width, client->height);
2282  break;
2283  }
2284 
2285  default:
2286  {
2287  rfbBool handled = FALSE;
2289 
2290  for(e = rfbClientExtensions; !handled && e; e = e->next)
2291  if(e->handleMessage && e->handleMessage(client, &msg))
2292  handled = TRUE;
2293 
2294  if(!handled) {
2295  char buffer[256];
2296  rfbClientLog("Unknown message type %d from VNC server\n",msg.type);
2297  ReadFromRFBServer(client, buffer, 256);
2298  return FALSE;
2299  }
2300  }
2301  }
2302 
2303  return TRUE;
2304 }
2305 
2306 
2307 #define GET_PIXEL8(pix, ptr) ((pix) = *(ptr)++)
2308 
2309 #define GET_PIXEL16(pix, ptr) (((uint8_t*)&(pix))[0] = *(ptr)++, \
2310  ((uint8_t*)&(pix))[1] = *(ptr)++)
2311 
2312 #define GET_PIXEL32(pix, ptr) (((uint8_t*)&(pix))[0] = *(ptr)++, \
2313  ((uint8_t*)&(pix))[1] = *(ptr)++, \
2314  ((uint8_t*)&(pix))[2] = *(ptr)++, \
2315  ((uint8_t*)&(pix))[3] = *(ptr)++)
2316 
2317 /* CONCAT2 concatenates its two arguments. CONCAT2E does the same but also
2318  expands its arguments if they are macros */
2319 
2320 #define CONCAT2(a,b) a##b
2321 #define CONCAT2E(a,b) CONCAT2(a,b)
2322 #define CONCAT3(a,b,c) a##b##c
2323 #define CONCAT3E(a,b,c) CONCAT3(a,b,c)
2324 
2325 #define BPP 8
2326 #include "rre.c"
2327 #include "corre.c"
2328 #include "hextile.c"
2329 #include "ultra.c"
2330 #include "zlib.c"
2331 #include "tight.c"
2332 #include "zrle.c"
2333 #undef BPP
2334 #define BPP 16
2335 #include "rre.c"
2336 #include "corre.c"
2337 #include "hextile.c"
2338 #include "ultra.c"
2339 #include "zlib.c"
2340 #include "tight.c"
2341 #include "zrle.c"
2342 #define REALBPP 15
2343 #include "zrle.c"
2344 #undef BPP
2345 #define BPP 32
2346 #include "rre.c"
2347 #include "corre.c"
2348 #include "hextile.c"
2349 #include "ultra.c"
2350 #include "zlib.c"
2351 #include "tight.c"
2352 #include "zrle.c"
2353 #define REALBPP 24
2354 #include "zrle.c"
2355 #define REALBPP 24
2356 #define UNCOMP 8
2357 #include "zrle.c"
2358 #define REALBPP 24
2359 #define UNCOMP -8
2360 #include "zrle.c"
2361 #undef BPP
2362 
2363 
2364 /*
2365  * PrintPixelFormat.
2366  */
2367 
2368 void
2370 {
2371  if (format->bitsPerPixel == 1) {
2372  rfbClientLog(" Single bit per pixel.\n");
2373  rfbClientLog(
2374  " %s significant bit in each byte is leftmost on the screen.\n",
2375  (format->bigEndian ? "Most" : "Least"));
2376  } else {
2377  rfbClientLog(" %d bits per pixel.\n",format->bitsPerPixel);
2378  if (format->bitsPerPixel != 8) {
2379  rfbClientLog(" %s significant byte first in each pixel.\n",
2380  (format->bigEndian ? "Most" : "Least"));
2381  }
2382  if (format->trueColour) {
2383  rfbClientLog(" TRUE colour: max red %d green %d blue %d"
2384  ", shift red %d green %d blue %d\n",
2385  format->redMax, format->greenMax, format->blueMax,
2386  format->redShift, format->greenShift, format->blueShift);
2387  } else {
2388  rfbClientLog(" Colour map (not true colour).\n");
2389  }
2390  }
2391 }
2392 
2393 /* avoid name clashes with LibVNCServer */
2394 
2395 #define rfbEncryptBytes rfbClientEncryptBytes
2396 #define rfbEncryptBytes2 rfbClientEncryptBytes2
2397 #define rfbDes rfbClientDes
2398 #define rfbDesKey rfbClientDesKey
2399 #define rfbUseKey rfbClientUseKey
2400 #define rfbCPKey rfbClientCPKey
2401 
2402 #include "vncauth.c"
2403 #include "d3des.c"