static rfbBool HandleH264 (rfbClient* client, int rx, int ry, int rw, int rh) { rfbH264Header hdr; char *framedata; DebugLog(("Framebuffer update with H264 (x: %d, y: %d, w: %d, h: %d)\n", rx, ry, rw, rh)); /* First, read the frame size and allocate buffer to store the data */ if (!ReadFromRFBServer(client, (char *)&hdr, sz_rfbH264Header)) return FALSE; hdr.slice_type = rfbClientSwap32IfLE(hdr.slice_type); hdr.nBytes = rfbClientSwap32IfLE(hdr.nBytes); hdr.width = rfbClientSwap32IfLE(hdr.width); hdr.height = rfbClientSwap32IfLE(hdr.height); framedata = (char*) malloc(hdr.nBytes); /* Obtain frame data from the server */ DebugLog(("Reading %d bytes of frame data (type: %d)\n", hdr.nBytes, hdr.slice_type)); if (!ReadFromRFBServer(client, framedata, hdr.nBytes)) return FALSE; /* First make sure we have a large enough raw buffer to hold the * decompressed data. In practice, with a fixed BPP, fixed frame * buffer size and the first update containing the entire frame * buffer, this buffer allocation should only happen once, on the * first update. */ if ( client->raw_buffer_size < (( rw * rh ) * ( BPP / 8 ))) { if ( client->raw_buffer != NULL ) { free( client->raw_buffer ); } client->raw_buffer_size = (( rw * rh ) * ( BPP / 8 )); client->raw_buffer = (char*) malloc( client->raw_buffer_size ); rfbClientLog("Allocated raw buffer of %d bytes (%dx%dx%d BPP)\n", client->raw_buffer_size, rw, rh, BPP); } /* Decode frame if frame data was sent. Server only sends frame data for the first * framebuffer update message for a particular frame buffer contents. * If more than 1 rectangle is updated, the messages after the first one (with * the H.264 frame) have nBytes == 0. */ if (hdr.nBytes > 0) { DebugLog((" decoding %d bytes of H.264 data\n", hdr.nBytes)); h264_decode_frame(hdr.width, hdr.height, framedata, hdr.nBytes, hdr.slice_type); } DebugLog((" updating rectangle (%d, %d)-(%d, %d)\n", rx, ry, rw, rh)); put_updated_rectangle(client, rx, ry, rw, rh, hdr.width, hdr.height, hdr.nBytes != 0); free(framedata); return TRUE; }
static rfbBool handleBackChannelMessage(rfbClient* client, rfbServerToClientMsg* message) { backChannelMsg msg; char* text; if(message->type != rfbBackChannel) return FALSE; rfbClientSetClientData(client, sendMessage, sendMessage); if(!ReadFromRFBServer(client, ((char*)&msg)+1, sizeof(msg)-1)) return TRUE; msg.size = rfbClientSwap32IfLE(msg.size); text = malloc(msg.size); if(!ReadFromRFBServer(client, text, msg.size)) { free(text); return TRUE; } rfbClientLog("got back channel message: %s\n", text); free(text); return TRUE; }
static void sendMessage(rfbClient* client, char* text) { backChannelMsg msg; uint32_t length = strlen(text)+1; msg.type = rfbBackChannel; msg.size = rfbClientSwap32IfLE(length); if(!WriteToRFBServer(client, (char*)&msg, sizeof(msg)) || !WriteToRFBServer(client, text, length)) { rfbClientLog("enableBackChannel: write error (%d: %s)", errno, strerror(errno)); } }
rfbBool ReadFromRFBServer(rfbClient* client, char *out, unsigned int n) { #undef DEBUG_READ_EXACT #ifdef DEBUG_READ_EXACT char* oout=out; int nn=n; rfbClientLog("ReadFromRFBServer %d bytes\n",n); #endif if (client->serverPort==-1) { /* vncrec playing */ rfbVNCRec* rec = client->vncRec; struct timeval tv; if (rec->readTimestamp) { rec->readTimestamp = FALSE; if (!fread(&tv,sizeof(struct timeval),1,rec->file)) return FALSE; tv.tv_sec = rfbClientSwap32IfLE (tv.tv_sec); tv.tv_usec = rfbClientSwap32IfLE (tv.tv_usec); if (rec->tv.tv_sec!=0 && !rec->doNotSleep) { struct timeval diff; diff.tv_sec = tv.tv_sec - rec->tv.tv_sec; diff.tv_usec = tv.tv_usec - rec->tv.tv_usec; if(diff.tv_usec<0) { diff.tv_sec--; diff.tv_usec+=1000000; } #ifndef __MINGW32__ sleep (diff.tv_sec); usleep (diff.tv_usec); #else Sleep (diff.tv_sec * 1000 + diff.tv_usec/1000); #endif } rec->tv=tv; } return (fread(out,1,n,rec->file) != n ? FALSE : TRUE); } if (n <= client->buffered) { memcpy(out, client->bufoutptr, n); client->bufoutptr += n; client->buffered -= n; #ifdef DEBUG_READ_EXACT goto hexdump; #endif return TRUE; } memcpy(out, client->bufoutptr, client->buffered); out += client->buffered; n -= client->buffered; client->bufoutptr = client->buf; client->buffered = 0; if (n <= RFB_BUF_SIZE) { while (client->buffered < n) { int i; if (client->tlsSession) { i = ReadFromTLS(client, client->buf + client->buffered, RFB_BUF_SIZE - client->buffered); } else { i = read(client->sock, client->buf + client->buffered, RFB_BUF_SIZE - client->buffered); } if (i <= 0) { if (i < 0) { #ifdef WIN32 errno=WSAGetLastError(); #endif if (errno == EWOULDBLOCK || errno == EAGAIN) { /* TODO: ProcessXtEvents(); */ WaitForMessage(client, 100000); i = 0; } else { rfbClientErr("read (%d: %s)\n",errno,strerror(errno)); return FALSE; } } else { if (errorMessageOnReadFailure) { rfbClientLog("VNC server closed connection\n"); } return FALSE; } } client->buffered += i; } memcpy(out, client->bufoutptr, n); client->bufoutptr += n; client->buffered -= n; } else { while (n > 0) { int i; if (client->tlsSession) { i = ReadFromTLS(client, out, n); } else { i = read(client->sock, out, n); } if (i <= 0) { if (i < 0) { #ifdef WIN32 errno=WSAGetLastError(); #endif if (errno == EWOULDBLOCK || errno == EAGAIN) { /* TODO: ProcessXtEvents(); */ WaitForMessage(client, 100000); i = 0; } else { rfbClientErr("read (%s)\n",strerror(errno)); return FALSE; } } else { if (errorMessageOnReadFailure) { rfbClientLog("VNC server closed connection\n"); } return FALSE; } } out += i; n -= i; } } #ifdef DEBUG_READ_EXACT hexdump: { int ii; for(ii=0;ii<nn;ii++) fprintf(stderr,"%02x ",(unsigned char)oout[ii]); fprintf(stderr,"\n"); } #endif return TRUE; }
static rfbBool handleEncodingLZORLE( rfbClient *client, rfbFramebufferUpdateRectHeader *r ) { if( r->encoding != rfbEncodingLZORLE ) { return false; } uint16_t rx = r->r.x; uint16_t ry = r->r.y; const uint16_t rw = r->r.w; const uint16_t rh = r->r.h; RfbLZORLE::Header hdr; if( !ReadFromRFBServer( client, (char *) &hdr, sizeof( hdr ) ) ) { qWarning( "failed reading RfbLZORLE::Header from server" ); return false; } if( !hdr.compressed ) { return handleRaw( client, rx, ry, rw, rh ); } hdr.bytesLZO = rfbClientSwap32IfLE( hdr.bytesLZO ); hdr.bytesRLE = rfbClientSwap32IfLE( hdr.bytesRLE ); auto lzo_data = new uint8_t[hdr.bytesLZO]; if( !ReadFromRFBServer( client, (char *) lzo_data, hdr.bytesLZO ) ) { qWarning( "failed reading LZO data from server" ); delete[] lzo_data; return false; } auto rle_data = new uint8_t[hdr.bytesRLE]; lzo_uint decomp_bytes = hdr.bytesRLE; lzo1x_decompress_safe( (const unsigned char *) lzo_data, (lzo_uint) hdr.bytesLZO, (unsigned char *) rle_data, (lzo_uint *) &decomp_bytes, nullptr ); if( decomp_bytes != hdr.bytesRLE ) { delete[] rle_data; delete[] lzo_data; qCritical( "handleEncodingLZORLE(...): expected and real " "size of decompressed data do not match!" ); return false; } QRgb *dst = ( (QRgb *) client->frameBuffer ) + client->width*ry + rx; int dx = 0; bool done = FALSE; const int sh = client->height; for( uint32_t i = 0; i < hdr.bytesRLE && done == false; i+=4 ) { const QRgb val = rfbClientSwap24IfLE( *( (QRgb*)( rle_data + i ) ) ); const uint8_t rleCount = rle_data[i+3]; for( uint16_t j = 0; j <= rleCount; ++j ) { *dst = val; if( ++dx >= rw ) { dx = 0; if( ry+1 < sh ) { ++ry; dst = ( (QRgb *) client->frameBuffer ) + client->width*ry + rx; } else { done = true; break; } } else { ++dst; } } } if( dx != 0 ) { qWarning( "handleEncodingLZORLE(...): dx(%d) != 0", dx ); } delete[] lzo_data; delete[] rle_data; return true; }
/* VeNCrypt sub auth. 1 byte auth count, followed by count * 4 byte integers */ static rfbBool ReadVeNCryptSecurityType(rfbClient* client, uint32_t *result) { uint8_t count=0; uint8_t loop=0; uint8_t flag=0; uint32_t tAuth[256], t; char buf1[500],buf2[10]; uint32_t authScheme; if (!ReadFromRFBServer(client, (char *)&count, 1)) return FALSE; if (count==0) { rfbClientLog("List of security types is ZERO. Giving up.\n"); return FALSE; } if (count>sizeof(tAuth)) { rfbClientLog("%d security types are too many; maximum is %d\n", count, sizeof(tAuth)); return FALSE; } rfbClientLog("We have %d security types to read\n", count); authScheme=0; /* now, we have a list of available security types to read ( uint8_t[] ) */ for (loop=0;loop<count;loop++) { if (!ReadFromRFBServer(client, (char *)&tAuth[loop], 4)) return FALSE; t=rfbClientSwap32IfLE(tAuth[loop]); rfbClientLog("%d) Received security type %d\n", loop, t); if (flag) continue; if (t==rfbVeNCryptTLSNone || t==rfbVeNCryptTLSVNC || t==rfbVeNCryptTLSPlain || t==rfbVeNCryptX509None || t==rfbVeNCryptX509VNC || t==rfbVeNCryptX509Plain) { flag++; authScheme=t; rfbClientLog("Selecting security type %d (%d/%d in the list)\n", authScheme, loop, count); /* send back 4 bytes (in original byte order!) indicating which security type to use */ if (!WriteToRFBServer(client, (char *)&tAuth[loop], 4)) return FALSE; } tAuth[loop]=t; } if (authScheme==0) { memset(buf1, 0, sizeof(buf1)); for (loop=0;loop<count;loop++) { if (strlen(buf1)>=sizeof(buf1)-1) break; snprintf(buf2, sizeof(buf2), (loop>0 ? ", %d" : "%d"), (int)tAuth[loop]); strncat(buf1, buf2, sizeof(buf1)-strlen(buf1)-1); } rfbClientLog("Unknown VeNCrypt authentication scheme from VNC server: %s\n", buf1); return FALSE; } *result = authScheme; return TRUE; }
static rfbBool HandleZRLE (rfbClient* client, int rx, int ry, int rw, int rh) { rfbZRLEHeader header; int remaining; int inflateResult; int toRead; int min_buffer_size = rw * rh * (REALBPP / 8) * 2; /* First make sure we have a large enough raw buffer to hold the * decompressed data. In practice, with a fixed REALBPP, fixed frame * buffer size and the first update containing the entire frame * buffer, this buffer allocation should only happen once, on the * first update. */ if ( client->raw_buffer_size < min_buffer_size) { if ( client->raw_buffer != NULL ) { free( client->raw_buffer ); } client->raw_buffer_size = min_buffer_size; client->raw_buffer = (char*) malloc( client->raw_buffer_size ); } if (!ReadFromRFBServer(client, (char *)&header, sz_rfbZRLEHeader)) return FALSE; remaining = rfbClientSwap32IfLE(header.length); /* Need to initialize the decompressor state. */ client->decompStream.next_in = ( Bytef * )client->buffer; client->decompStream.avail_in = 0; client->decompStream.next_out = ( Bytef * )client->raw_buffer; client->decompStream.avail_out = client->raw_buffer_size; client->decompStream.data_type = Z_BINARY; /* Initialize the decompression stream structures on the first invocation. */ if ( client->decompStreamInited == FALSE ) { inflateResult = inflateInit( &client->decompStream ); if ( inflateResult != Z_OK ) { rfbClientLog( "inflateInit returned error: %d, msg: %s\n", inflateResult, client->decompStream.msg); return FALSE; } client->decompStreamInited = TRUE; } inflateResult = Z_OK; /* Process buffer full of data until no more to process, or * some type of inflater error, or Z_STREAM_END. */ while (( remaining > 0 ) && ( inflateResult == Z_OK )) { if ( remaining > RFB_BUFFER_SIZE ) { toRead = RFB_BUFFER_SIZE; } else { toRead = remaining; } /* Fill the buffer, obtaining data from the server. */ if (!ReadFromRFBServer(client, client->buffer,toRead)) return FALSE; client->decompStream.next_in = ( Bytef * )client->buffer; client->decompStream.avail_in = toRead; /* Need to uncompress buffer full. */ inflateResult = inflate( &client->decompStream, Z_SYNC_FLUSH ); /* We never supply a dictionary for compression. */ if ( inflateResult == Z_NEED_DICT ) { rfbClientLog("zlib inflate needs a dictionary!\n"); return FALSE; } if ( inflateResult < 0 ) { rfbClientLog( "zlib inflate returned error: %d, msg: %s\n", inflateResult, client->decompStream.msg); return FALSE; } /* Result buffer allocated to be at least large enough. We should * never run out of space! */ if (( client->decompStream.avail_in > 0 ) && ( client->decompStream.avail_out <= 0 )) { rfbClientLog("zlib inflate ran out of space!\n"); return FALSE; } remaining -= toRead; } /* while ( remaining > 0 ) */ if ( inflateResult == Z_OK ) { char* buf=client->raw_buffer; int i,j; remaining = client->raw_buffer_size-client->decompStream.avail_out; for(j=0; j<rh; j+=rfbZRLETileHeight) for(i=0; i<rw; i+=rfbZRLETileWidth) { int subWidth=(i+rfbZRLETileWidth>rw)?rw-i:rfbZRLETileWidth; int subHeight=(j+rfbZRLETileHeight>rh)?rh-j:rfbZRLETileHeight; int result=HandleZRLETile(client,(uint8_t *)buf,remaining,rx+i,ry+j,subWidth,subHeight); if(result<0) { rfbClientLog("ZRLE decoding failed (%d)\n",result); return TRUE; return FALSE; } buf+=result; remaining-=result; } } else { rfbClientLog( "zlib inflate returned error: %d, msg: %s\n", inflateResult, client->decompStream.msg); return FALSE; } return TRUE; }
static rfbBool HandleZlibBPP (rfbClient* client, int rx, int ry, int rw, int rh) { rfbZlibHeader hdr; int remaining; int inflateResult; int toRead; /* First make sure we have a large enough raw buffer to hold the * decompressed data. In practice, with a fixed BPP, fixed frame * buffer size and the first update containing the entire frame * buffer, this buffer allocation should only happen once, on the * first update. */ if ( client->raw_buffer_size < (( rw * rh ) * ( BPP / 8 ))) { if ( client->raw_buffer != NULL ) { free( client->raw_buffer ); } client->raw_buffer_size = (( rw * rh ) * ( BPP / 8 )); client->raw_buffer = (char*) malloc( client->raw_buffer_size ); } if (!ReadFromRFBServer(client, (char *)&hdr, sz_rfbZlibHeader)) return FALSE; remaining = rfbClientSwap32IfLE(hdr.nBytes); /* Need to initialize the decompressor state. */ client->decompStream.next_in = ( Bytef * )client->buffer; client->decompStream.avail_in = 0; client->decompStream.next_out = ( Bytef * )client->raw_buffer; client->decompStream.avail_out = client->raw_buffer_size; client->decompStream.data_type = Z_BINARY; /* Initialize the decompression stream structures on the first invocation. */ if ( client->decompStreamInited == FALSE ) { inflateResult = inflateInit( &client->decompStream ); if ( inflateResult != Z_OK ) { rfbClientLog( "inflateInit returned error: %d, msg: %s\n", inflateResult, client->decompStream.msg); return FALSE; } client->decompStreamInited = TRUE; } inflateResult = Z_OK; /* Process buffer full of data until no more to process, or * some type of inflater error, or Z_STREAM_END. */ while (( remaining > 0 ) && ( inflateResult == Z_OK )) { if ( remaining > RFB_BUFFER_SIZE ) { toRead = RFB_BUFFER_SIZE; } else { toRead = remaining; } /* Fill the buffer, obtaining data from the server. */ if (!ReadFromRFBServer(client, client->buffer,toRead)) return FALSE; client->decompStream.next_in = ( Bytef * )client->buffer; client->decompStream.avail_in = toRead; /* Need to uncompress buffer full. */ inflateResult = inflate( &client->decompStream, Z_SYNC_FLUSH ); /* We never supply a dictionary for compression. */ if ( inflateResult == Z_NEED_DICT ) { rfbClientLog("zlib inflate needs a dictionary!\n"); return FALSE; } if ( inflateResult < 0 ) { rfbClientLog( "zlib inflate returned error: %d, msg: %s\n", inflateResult, client->decompStream.msg); return FALSE; } /* Result buffer allocated to be at least large enough. We should * never run out of space! */ if (( client->decompStream.avail_in > 0 ) && ( client->decompStream.avail_out <= 0 )) { rfbClientLog("zlib inflate ran out of space!\n"); return FALSE; } remaining -= toRead; } /* while ( remaining > 0 ) */ if ( inflateResult == Z_OK ) { /* Put the uncompressed contents of the update on the screen. */ CopyRectangle(client, (uint8_t *)client->raw_buffer, rx, ry, rw, rh); } else { rfbClientLog( "zlib inflate returned error: %d, msg: %s\n", inflateResult, client->decompStream.msg); return FALSE; } return TRUE; }
rfbBool ReadFromRFBServer(rfbClient* client, char *out, unsigned int n) { #undef DEBUG_READ_EXACT #ifdef DEBUG_READ_EXACT char* oout=out; int nn=n; rfbClientLog("ReadFromRFBServer %d bytes\n",n); #endif /* Handle attempts to write to NULL out buffer that might occur when an outside malloc() fails. For instance, memcpy() to NULL results in undefined behaviour and probably memory corruption.*/ if(!out) return FALSE; if (client->serverPort==-1) { /* vncrec playing */ rfbVNCRec* rec = client->vncRec; struct timeval tv; if (rec->readTimestamp) { rec->readTimestamp = FALSE; if (!fread(&tv,sizeof(struct timeval),1,rec->file)) return FALSE; tv.tv_sec = rfbClientSwap32IfLE (tv.tv_sec); tv.tv_usec = rfbClientSwap32IfLE (tv.tv_usec); if (rec->tv.tv_sec!=0 && !rec->doNotSleep) { struct timeval diff; diff.tv_sec = tv.tv_sec - rec->tv.tv_sec; diff.tv_usec = tv.tv_usec - rec->tv.tv_usec; if(diff.tv_usec<0) { diff.tv_sec--; diff.tv_usec+=1000000; } #ifndef WIN32 sleep (diff.tv_sec); usleep (diff.tv_usec); #else Sleep (diff.tv_sec * 1000 + diff.tv_usec/1000); #endif } rec->tv=tv; } return (fread(out,1,n,rec->file) != n ? FALSE : TRUE); } if (n <= client->buffered) { memcpy(out, client->bufoutptr, n); client->bufoutptr += n; client->buffered -= n; #ifdef DEBUG_READ_EXACT goto hexdump; #endif return TRUE; } memcpy(out, client->bufoutptr, client->buffered); out += client->buffered; n -= client->buffered; client->bufoutptr = client->buf; client->buffered = 0; if (n <= RFB_BUF_SIZE) { while (client->buffered < n) { int i; if (client->tlsSession) i = ReadFromTLS(client, client->buf + client->buffered, RFB_BUF_SIZE - client->buffered); else #ifdef LIBVNCSERVER_HAVE_SASL if (client->saslconn) i = ReadFromSASL(client, client->buf + client->buffered, RFB_BUF_SIZE - client->buffered); else { #endif /* LIBVNCSERVER_HAVE_SASL */ i = read(client->sock, client->buf + client->buffered, RFB_BUF_SIZE - client->buffered); #ifdef WIN32 if (i < 0) errno=WSAGetLastError(); #endif #ifdef LIBVNCSERVER_HAVE_SASL } #endif if (i <= 0) { if (i < 0) { if (errno == EWOULDBLOCK || errno == EAGAIN) { /* TODO: ProcessXtEvents(); */ WaitForMessage(client, 100000); i = 0; } else { rfbClientErr("read (%d: %s)\n",errno,strerror(errno)); return FALSE; } } else { if (errorMessageOnReadFailure) { rfbClientLog("VNC server closed connection\n"); } return FALSE; } } client->buffered += i; } memcpy(out, client->bufoutptr, n); client->bufoutptr += n; client->buffered -= n; } else { while (n > 0) { int i; if (client->tlsSession) i = ReadFromTLS(client, out, n); else #ifdef LIBVNCSERVER_HAVE_SASL if (client->saslconn) i = ReadFromSASL(client, out, n); else #endif i = read(client->sock, out, n); if (i <= 0) { if (i < 0) { #ifdef WIN32 errno=WSAGetLastError(); #endif if (errno == EWOULDBLOCK || errno == EAGAIN) { /* TODO: ProcessXtEvents(); */ WaitForMessage(client, 100000); i = 0; } else { rfbClientErr("read (%s)\n",strerror(errno)); return FALSE; } } else { if (errorMessageOnReadFailure) { rfbClientLog("VNC server closed connection\n"); } return FALSE; } } out += i; n -= i; } } #ifdef DEBUG_READ_EXACT hexdump: { int ii; for(ii=0;ii<nn;ii++) fprintf(stderr,"%02x ",(unsigned char)oout[ii]); fprintf(stderr,"\n"); } #endif return TRUE; }