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 bool HandleRREBPP (uint32_t rx, uint32_t ry, uint32_t rw, uint32_t rh) { rfbRREHeader hdr; CARDBPP pix; rfbRectangle subrect; if (!ReadFromRFBServer((uint8_t *)&hdr, sz_rfbRREHeader)) return false; hdr.nSubrects = Swap32IfLE(hdr.nSubrects); if (!ReadFromRFBServer((uint8_t *)&pix, sizeof(pix))) return false; FillBufferRectangle(rx, ry, rw, rh, pix); for (uint32_t i = 0; i < hdr.nSubrects; i++) { if (!ReadFromRFBServer((uint8_t *)&pix, sizeof(pix))) return false; if (!ReadFromRFBServer((uint8_t *)&subrect, sz_rfbRectangle)) return false; subrect.x = Swap16IfLE(subrect.x); subrect.y = Swap16IfLE(subrect.y); subrect.w = Swap16IfLE(subrect.w); subrect.h = Swap16IfLE(subrect.h); FillBufferRectangle(rx + subrect.x, ry + subrect.y, subrect.w, subrect.h, pix); } return true; }
static int SelectSecurityType(void) { CARD8 nSecTypes; char *secTypeNames[] = {"None", "VncAuth"}; CARD8 knownSecTypes[] = {rfbSecTypeNone, rfbSecTypeVncAuth}; int nKnownSecTypes = sizeof(knownSecTypes); CARD8 *secTypes; CARD8 secType = rfbSecTypeInvalid; int i, j; /* Read the list of secutiry types. */ if (!ReadFromRFBServer((char *)&nSecTypes, sizeof(nSecTypes))) return rfbSecTypeInvalid; if (nSecTypes == 0) { ReadConnFailedReason(); return rfbSecTypeInvalid; } secTypes = malloc(nSecTypes); if (!ReadFromRFBServer((char *)secTypes, nSecTypes)) return rfbSecTypeInvalid; /* Find out if the server supports TightVNC protocol extensions */ for (j = 0; j < (int)nSecTypes; j++) { if (secTypes[j] == rfbSecTypeTight) { free(secTypes); secType = rfbSecTypeTight; if (!WriteExact(rfbsock, (char *)&secType, sizeof(secType))) return rfbSecTypeInvalid; fprintf(stderr, "Enabling TightVNC protocol extensions\n"); return rfbSecTypeTight; } } /* Find first supported security type */ for (j = 0; j < (int)nSecTypes; j++) { for (i = 0; i < nKnownSecTypes; i++) { if (secTypes[j] == knownSecTypes[i]) { secType = secTypes[j]; if (!WriteExact(rfbsock, (char *)&secType, sizeof(secType))) { free(secTypes); return rfbSecTypeInvalid; } break; } } if (secType != rfbSecTypeInvalid) break; } free(secTypes); if (secType == rfbSecTypeInvalid) fprintf(stderr, "Server did not offer supported security type\n"); return (int)secType; }
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 Bool HandleRREBPP (int rx, int ry, int rw, int rh) { rfbRREHeader hdr; XGCValues gcv; int i; CARDBPP pix; rfbRectangle subrect; if (!ReadFromRFBServer((char *)&hdr, sz_rfbRREHeader)) return False; hdr.nSubrects = Swap32IfLE(hdr.nSubrects); if (!ReadFromRFBServer((char *)&pix, sizeof(pix))) return False; #if (BPP == 8) gcv.foreground = (appData.useBGR233 ? BGR233ToPixel[pix] : pix); #else gcv.foreground = pix; #endif XChangeGC(dpy, gc, GCForeground, &gcv); XFillRectangle(dpy, desktopWin, gc, rx, ry, rw, rh); #if VNC_CAPTURE myxfillrec(dpy, gc, rx, ry, rw, rh); #endif for (i = 0; i < hdr.nSubrects; i++) { if (!ReadFromRFBServer((char *)&pix, sizeof(pix))) return False; if (!ReadFromRFBServer((char *)&subrect, sz_rfbRectangle)) return False; subrect.x = Swap16IfLE(subrect.x); subrect.y = Swap16IfLE(subrect.y); subrect.w = Swap16IfLE(subrect.w); subrect.h = Swap16IfLE(subrect.h); #if (BPP == 8) gcv.foreground = (appData.useBGR233 ? BGR233ToPixel[pix] : pix); #else gcv.foreground = pix; #endif XChangeGC(dpy, gc, GCForeground, &gcv); XFillRectangle(dpy, desktopWin, gc, rx + subrect.x, ry + subrect.y, subrect.w, subrect.h); #if VNC_CAPTURE myxfillrec(dpy, gc, rx+ subrect.x, ry+ subrect.y, subrect.w, subrect.h); #endif } return True; }
static Bool HandleCoRREBPP (int rx, int ry, int rw, int rh) { rfbRREHeader hdr; XGCValues gcv; int i; CARDBPP pix; CARD8 *ptr; int x, y, w, h; if (!ReadFromRFBServer((char *)&hdr, sz_rfbRREHeader)) return False; hdr.nSubrects = Swap32IfLE(hdr.nSubrects); if (!ReadFromRFBServer((char *)&pix, sizeof(pix))) return False; #if (BPP == 8) gcv.foreground = (appData.useBGR233 ? BGR233ToPixel[pix] : pix); #else gcv.foreground = pix; #endif XChangeGC(dpy, gc, GCForeground, &gcv); XFillRectangle(dpy, desktopWin, gc, rx, ry, rw, rh); if (!ReadFromRFBServer(buffer, hdr.nSubrects * (4 + (BPP / 8)))) return False; ptr = (CARD8 *)buffer; for (i = 0; i < hdr.nSubrects; i++) { pix = *(CARDBPP *)ptr; ptr += BPP/8; x = *ptr++; y = *ptr++; w = *ptr++; h = *ptr++; #if (BPP == 8) gcv.foreground = (appData.useBGR233 ? BGR233ToPixel[pix] : pix); #else gcv.foreground = pix; #endif XChangeGC(dpy, gc, GCForeground, &gcv); XFillRectangle(dpy, desktopWin, gc, rx + x, ry + y, w, h); } return True; }
static Bool ReadAuthenticationResult(void) { CARD32 authResult; if (!ReadFromRFBServer((char *)&authResult, 4)) return False; authResult = Swap32IfLE(authResult); switch (authResult) { case rfbAuthOK: if (!appData.ffInfo) { fprintf(stderr, "Authentication successful\n"); } break; case rfbAuthFailed: if (protocolMinorVersion >= 8) { ReadConnFailedReason(); } else { fprintf(stderr, "Authentication failure\n"); } return False; case rfbAuthTooMany: fprintf(stderr, "Authentication failure, too many tries\n"); return False; default: fprintf(stderr, "Unknown result of authentication (%d)\n", (int)authResult); return False; } return True; }
static Bool SetupTunneling(void) { rfbTunnelingCapsMsg caps; CARD32 tunnelType; /* In the protocol version 3.7t, the server informs us about supported tunneling methods. Here we read this information. */ if (!ReadFromRFBServer((char *)&caps, sz_rfbTunnelingCapsMsg)) return False; caps.nTunnelTypes = Swap32IfLE(caps.nTunnelTypes); if (caps.nTunnelTypes) { if (!ReadCapabilityList(tunnelCaps, caps.nTunnelTypes)) return False; /* We cannot do tunneling anyway yet. */ tunnelType = Swap32IfLE(rfbNoTunneling); if (!WriteExact(rfbsock, (char *)&tunnelType, sizeof(tunnelType))) return False; } return True; }
static Bool PerformAuthenticationTight(void) { rfbAuthenticationCapsMsg caps; CARD32 authScheme; int i; /* In the protocol version 3.7t, the server informs us about supported authentication schemes. Here we read this information. */ if (!ReadFromRFBServer((char *)&caps, sz_rfbAuthenticationCapsMsg)) return False; caps.nAuthTypes = Swap32IfLE(caps.nAuthTypes); if (!caps.nAuthTypes) { fprintf(stderr, "No authentication needed\n"); return True; } if (!ReadCapabilityList(authCaps, caps.nAuthTypes)) return False; /* Prefer Unix login authentication if a user name was given. */ if (appData.userLogin && CapsIsEnabled(authCaps, rfbAuthUnixLogin)) { authScheme = Swap32IfLE(rfbAuthUnixLogin); if (!WriteExact(rfbsock, (char *)&authScheme, sizeof(authScheme))) return False; return AuthenticateUnixLogin(); } /* Otherwise, try server's preferred authentication scheme. */ for (i = 0; i < CapsNumEnabled(authCaps); i++) { authScheme = CapsGetByOrder(authCaps, i); if (authScheme != rfbAuthUnixLogin && authScheme != rfbAuthVNC) continue; /* unknown scheme - cannot use it */ authScheme = Swap32IfLE(authScheme); if (!WriteExact(rfbsock, (char *)&authScheme, sizeof(authScheme))) return False; authScheme = Swap32IfLE(authScheme); /* convert it back */ if (authScheme == rfbAuthUnixLogin) { return AuthenticateUnixLogin(); } else if (authScheme == rfbAuthVNC) { return AuthenticateVNC(); } else { /* Should never happen. */ fprintf(stderr, "Assertion failed: unknown authentication scheme\n"); return False; } } fprintf(stderr, "No suitable authentication schemes offered by server\n"); return False; }
static void ReadConnFailedReason(void) { CARD32 reasonLen; char *reason = NULL; if (ReadFromRFBServer((char *)&reasonLen, sizeof(reasonLen))) { reasonLen = Swap32IfLE(reasonLen); if ((reason = malloc(reasonLen)) != NULL && ReadFromRFBServer(reason, reasonLen)) { fprintf(stderr,"VNC connection failed: %.*s\n", (int)reasonLen, reason); free(reason); return; } } fprintf(stderr, "VNC connection failed\n"); if (reason != NULL) free(reason); }
static Bool ReadCapabilityList(CapsContainer *caps, int count) { rfbCapabilityInfo msginfo; int i; for (i = 0; i < count; i++) { if (!ReadFromRFBServer((char *)&msginfo, sz_rfbCapabilityInfo)) return False; msginfo.code = Swap32IfLE(msginfo.code); CapsEnable(caps, &msginfo); } return True; }
Bool VNCViewer::HandleRREBPP (sgVNCViewer *ct, int rx, int ry, int rw, int rh) { rfbRREHeader hdr; int i; CARDBPP pix; rfbRectangle subrect; if (!ReadFromRFBServer((char *)&hdr, sz_rfbRREHeader)) return False; hdr.nSubrects = Swap32IfLE(hdr.nSubrects); if (!ReadFromRFBServer((char *)&pix, sizeof(pix))) return False; ct->FillToScreen(pix, rx, ry, rw, rh); for (i = 0; i < hdr.nSubrects; i++) { if (!ReadFromRFBServer((char *)&pix, sizeof(pix))) return False; if (!ReadFromRFBServer((char *)&subrect, sz_rfbRectangle)) return False; subrect.x = Swap16IfLE(subrect.x); subrect.y = Swap16IfLE(subrect.y); subrect.w = Swap16IfLE(subrect.w); subrect.h = Swap16IfLE(subrect.h); ct->FillToScreen(pix, rx + subrect.x, ry + subrect.y, subrect.w, subrect.h); } return True; }
static Bool ReadInteractionCaps(void) { rfbInteractionCapsMsg intr_caps; /* Read the counts of list items following */ if (!ReadFromRFBServer((char *)&intr_caps, sz_rfbInteractionCapsMsg)) return False; intr_caps.nServerMessageTypes = Swap16IfLE(intr_caps.nServerMessageTypes); intr_caps.nClientMessageTypes = Swap16IfLE(intr_caps.nClientMessageTypes); intr_caps.nEncodingTypes = Swap16IfLE(intr_caps.nEncodingTypes); /* Read the lists of server- and client-initiated messages */ return (ReadCapabilityList(serverMsgCaps, intr_caps.nServerMessageTypes) && ReadCapabilityList(clientMsgCaps, intr_caps.nClientMessageTypes) && ReadCapabilityList(encodingCaps, intr_caps.nEncodingTypes)); }
static Bool PerformAuthenticationTight(void) { rfbAuthenticationCapsMsg caps; CARD32 authScheme; int i; /* In protocols 3.7t/3.8t, the server informs us about supported authentication schemes. Here we read this information. */ if (!ReadFromRFBServer((char *)&caps, sz_rfbAuthenticationCapsMsg)) return False; caps.nAuthTypes = Swap32IfLE(caps.nAuthTypes); /* Special case - empty capability list stands for no authentication. */ if (!caps.nAuthTypes) return AuthenticateNone(); if (!ReadCapabilityList(authCaps, caps.nAuthTypes)) return False; /* Try server's preferred authentication scheme. */ for (i = 0; i < CapsNumEnabled(authCaps); i++) { authScheme = CapsGetByOrder(authCaps, i); if (authScheme != rfbAuthVNC && authScheme != rfbAuthNone) continue; /* unknown scheme - cannot use it */ authScheme = Swap32IfLE(authScheme); if (!WriteExact(rfbsock, (char *)&authScheme, sizeof(authScheme))) return False; authScheme = Swap32IfLE(authScheme); /* convert it back */ switch (authScheme) { case rfbAuthNone: return AuthenticateNone(); case rfbAuthVNC: return AuthenticateVNC(); default: /* should never happen */ fprintf(stderr, "Internal error: Invalid authentication type\n"); return False; } } fprintf(stderr, "No suitable authentication schemes offered by server\n"); return False; }
static bool handleRaw( rfbClient *c, int rx, int ry, int rw, int rh ) { int y=ry, h=rh; int bytesPerLine = rw * c->format.bitsPerPixel / 8; int linesToRead = RFB_BUFFER_SIZE / bytesPerLine; while( h > 0 ) { if( linesToRead > h ) linesToRead = h; if( !ReadFromRFBServer( c, c->buffer,bytesPerLine * linesToRead ) ) return false; CopyRectangle( c, (uint8_t *)c->buffer, rx, y, rw,linesToRead ); h -= linesToRead; y += linesToRead; } return true; }
static int ReadSecurityType(void) { CARD32 secType; /* Read the security type */ if (!ReadFromRFBServer((char *)&secType, sizeof(secType))) return rfbSecTypeInvalid; secType = Swap32IfLE(secType); if (secType == rfbSecTypeInvalid) { ReadConnFailedReason(); return rfbSecTypeInvalid; } if (secType != rfbSecTypeNone && secType != rfbSecTypeVncAuth) { fprintf(stderr, "Unknown security type from RFB server: %d\n", (int)secType); return rfbSecTypeInvalid; } return (int)secType; }
Bool HandleCursorShape(int xhot, int yhot, int width, int height, CARD32 enc) { int bytesPerPixel; size_t bytesPerRow, bytesMaskData; /* Drawable dr;*/ rfbXCursorColors rgb; CARD32 colors[2]; char *buf; CARD8 *ptr; int x, y, b; bytesPerPixel = myFormat.bitsPerPixel / 8; bytesPerRow = (width + 7) / 8; bytesMaskData = bytesPerRow * height; /* dr = DefaultRootWindow(dpy);*/ FreeSoftCursor(); if (width * height == 0) return True; /* Allocate memory for pixel data and temporary mask data. */ rcSource = malloc(width * height * bytesPerPixel); if (rcSource == NULL) return False; buf = malloc(bytesMaskData); if (buf == NULL) { free(rcSource); return False; } /* Read and decode cursor pixel data, depending on the encoding type. */ if (enc == rfbEncodingXCursor) { /* Read and convert background and foreground colors. */ if (!ReadFromRFBServer((char *)&rgb, sz_rfbXCursorColors)) { free(rcSource); free(buf); return False; } colors[0] = RGB24_TO_PIXEL(32, rgb.backRed, rgb.backGreen, rgb.backBlue); colors[1] = RGB24_TO_PIXEL(32, rgb.foreRed, rgb.foreGreen, rgb.foreBlue); /* Read 1bpp pixel data into a temporary buffer. */ if (!ReadFromRFBServer(buf, bytesMaskData)) { free(rcSource); free(buf); return False; } /* Convert 1bpp data to byte-wide color indices. */ ptr = rcSource; for (y = 0; y < height; y++) { for (x = 0; x < width / 8; x++) { for (b = 7; b >= 0; b--) { *ptr = buf[y * bytesPerRow + x] >> b & 1; ptr += bytesPerPixel; } } for (b = 7; b > 7 - width % 8; b--) { *ptr = buf[y * bytesPerRow + x] >> b & 1; ptr += bytesPerPixel; } } /* Convert indices into the actual pixel values. */ switch (bytesPerPixel) { case 1: for (x = 0; x < width * height; x++) rcSource[x] = (CARD8)colors[rcSource[x]]; break; case 2: for (x = 0; x < width * height; x++) ((CARD16 *)rcSource)[x] = (CARD16)colors[rcSource[x * 2]]; break; case 4: for (x = 0; x < width * height; x++) ((CARD32 *)rcSource)[x] = colors[rcSource[x * 4]]; break; } } else { /* enc == rfbEncodingRichCursor */ if (!ReadFromRFBServer((char *)rcSource, width * height * bytesPerPixel)) {
static Bool AuthenticateUnixLogin(void) { CARD32 loginLen, passwdLen, authResult; char *login; char *passwd; struct passwd *ps; fprintf(stderr, "Performing Unix login-style authentication\n"); if (appData.userLogin) { login = appData.userLogin; } else { ps = getpwuid(getuid()); login = ps->pw_name; } fprintf(stderr, "Using user name \"%s\"\n", login); if (appData.passwordDialog) { passwd = DoPasswordDialog(); } else { passwd = getpass("Password: "******"Reading password failed\n"); return False; } loginLen = Swap32IfLE((CARD32)strlen(login)); passwdLen = Swap32IfLE((CARD32)strlen(passwd)); if (!WriteExact(rfbsock, (char *)&loginLen, sizeof(loginLen)) || !WriteExact(rfbsock, (char *)&passwdLen, sizeof(passwdLen))) return False; if (!WriteExact(rfbsock, login, strlen(login)) || !WriteExact(rfbsock, passwd, strlen(passwd))) return False; /* Lose the password from memory */ memset(passwd, '\0', strlen(passwd)); if (!ReadFromRFBServer((char *)&authResult, sizeof(authResult))) return False; authResult = Swap32IfLE(authResult); switch (authResult) { case rfbVncAuthOK: fprintf(stderr, "Authentication succeeded\n"); break; case rfbVncAuthFailed: fprintf(stderr, "Authentication failed\n"); return False; case rfbVncAuthTooMany: fprintf(stderr, "Authentication failed - too many tries\n"); return False; default: fprintf(stderr, "Unknown authentication result: %d\n", (int)authResult); return False; } return True; }
static Bool AuthenticateVNC(void) { CARD32 authScheme, authResult; CARD8 challenge[CHALLENGESIZE]; char *passwd; char buffer[64]; char* cstatus; int len; fprintf(stderr, "Performing standard VNC authentication\n"); if (!ReadFromRFBServer((char *)challenge, CHALLENGESIZE)) return False; if (appData.passwordFile) { passwd = vncDecryptPasswdFromFile(appData.passwordFile); if (!passwd) { fprintf(stderr, "Cannot read valid password from file \"%s\"\n", appData.passwordFile); return False; } } else if (appData.autoPass) { passwd = buffer; cstatus = fgets(buffer, sizeof buffer, stdin); if (cstatus == NULL) buffer[0] = '\0'; else { len = strlen(buffer); if (len > 0 && buffer[len - 1] == '\n') buffer[len - 1] = '\0'; } } else if (appData.passwordDialog) { passwd = DoPasswordDialog(); } else { passwd = getpass("Password: "******"Reading password failed\n"); return False; } if (strlen(passwd) > 8) { passwd[8] = '\0'; } vncEncryptBytes(challenge, passwd); /* Lose the password from memory */ memset(passwd, '\0', strlen(passwd)); if (!WriteExact(rfbsock, (char *)challenge, CHALLENGESIZE)) return False; if (!ReadFromRFBServer((char *)&authResult, 4)) return False; authResult = Swap32IfLE(authResult); switch (authResult) { case rfbVncAuthOK: fprintf(stderr, "VNC authentication succeeded\n"); break; case rfbVncAuthFailed: fprintf(stderr, "VNC authentication failed\n"); return False; case rfbVncAuthTooMany: fprintf(stderr, "VNC authentication failed - too many tries\n"); return False; default: fprintf(stderr, "Unknown VNC authentication result: %d\n", (int)authResult); return False; } return True; }
Bool HandleRFBServerMessage() { rfbServerToClientMsg msg; if (!ReadFromRFBServer((char *)&msg, 1)) return False; switch (msg.type) { case rfbSetColourMapEntries: { fprintf(stderr, "Received unsupported rfbSetColourMapEntries\n"); return False; /* unsupported */ } case rfbFramebufferUpdate: { rfbFramebufferUpdateRectHeader rect; int linesToRead; int bytesPerLine; int i; if (!ReadFromRFBServer(((char *)&msg.fu) + 1, sz_rfbFramebufferUpdateMsg - 1)) return False; msg.fu.nRects = Swap16IfLE(msg.fu.nRects); for (i = 0; i < msg.fu.nRects; i++) { if (!ReadFromRFBServer((char *)&rect, sz_rfbFramebufferUpdateRectHeader)) return False; rect.r.x = Swap16IfLE(rect.r.x); rect.r.y = Swap16IfLE(rect.r.y); rect.r.w = Swap16IfLE(rect.r.w); rect.r.h = Swap16IfLE(rect.r.h); rect.encoding = Swap32IfLE(rect.encoding); if (rect.encoding == rfbEncodingXCursor) { if (!HandleCursorShape(rect.r.x, rect.r.y, rect.r.w, rect.r.h, rfbEncodingXCursor)) { return False; } continue; } if (rect.encoding == rfbEncodingRichCursor) { if (!HandleCursorShape(rect.r.x, rect.r.y, rect.r.w, rect.r.h, rfbEncodingRichCursor)) { return False; } continue; } if (rect.encoding == rfbEncodingPointerPos) { if (!HandleCursorPos(rect.r.x, rect.r.y)) { return False; } appData.gotCursorPos = 1; continue; } if ((rect.r.x + rect.r.w > si.framebufferWidth) || (rect.r.y + rect.r.h > si.framebufferHeight)) { fprintf(stderr,"Rect too large: %dx%d at (%d, %d)\n", rect.r.w, rect.r.h, rect.r.x, rect.r.y); return False; } if ((rect.r.h * rect.r.w) == 0) { fprintf(stderr,"Zero size rect - ignoring\n"); continue; } /* If RichCursor encoding is used, we should prevent collisions between framebuffer updates and cursor drawing operations. */ SoftCursorLockArea(rect.r.x, rect.r.y, rect.r.w, rect.r.h); switch (rect.encoding) { case rfbEncodingRaw: bytesPerLine = rect.r.w * myFormat.bitsPerPixel / 8; linesToRead = BUFFER_SIZE / bytesPerLine; while (rect.r.h > 0) { if (linesToRead > rect.r.h) linesToRead = rect.r.h; if (!ReadFromRFBServer(buffer,bytesPerLine * linesToRead)) return False; CopyDataToScreen(buffer, rect.r.x, rect.r.y, rect.r.w, linesToRead); rect.r.h -= linesToRead; rect.r.y += linesToRead; } break; case rfbEncodingCopyRect: { rfbCopyRect cr; char *buffer; if (!ReadFromRFBServer((char *)&cr, sz_rfbCopyRect)) return False; if (!BufferWritten()) { /* Ignore attempts to do copy-rect when we have nothing to * copy from. */ break; } cr.srcX = Swap16IfLE(cr.srcX); cr.srcY = Swap16IfLE(cr.srcY); /* If RichCursor encoding is used, we should extend our "cursor lock area" (previously set to destination rectangle) to the source rectangle as well. */ SoftCursorLockArea(cr.srcX, cr.srcY, rect.r.w, rect.r.h); buffer = CopyScreenToData(cr.srcX, cr.srcY, rect.r.w, rect.r.h); CopyDataToScreen(buffer, rect.r.x, rect.r.y, rect.r.w, rect.r.h); free(buffer); break; } case rfbEncodingRRE: { if (!HandleRRE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; } case rfbEncodingCoRRE: { if (!HandleCoRRE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; } case rfbEncodingHextile: { if (!HandleHextile32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; } case rfbEncodingZlib: { if (!HandleZlib32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; } case rfbEncodingTight: { if (!HandleTight32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; } case rfbEncodingZRLE: if (!zrleDecode(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; default: fprintf(stderr,"Unknown rect encoding %d\n", (int)rect.encoding); return False; } /* Now we may discard "soft cursor locks". */ SoftCursorUnlockScreen(); /* Done. Save the screen image. */ } /* RealVNC sometimes returns an initial black screen. */ if (BufferIsBlank() && appData.ignoreBlank) { if (!appData.quiet && appData.ignoreBlank != 1) { /* user did not specify either -quiet or -ignoreblank */ fprintf(stderr, "Warning: discarding received blank screen (use -allowblank to accept,\n or -ignoreblank to suppress this message)\n"); appData.ignoreBlank = 1; } RequestNewUpdate(); } else { return False; } break; } case rfbBell: /* ignore */ break; case rfbServerCutText: { if (!ReadFromRFBServer(((char *)&msg) + 1, sz_rfbServerCutTextMsg - 1)) return False; msg.sct.length = Swap32IfLE(msg.sct.length); if (serverCutText) free(serverCutText); serverCutText = malloc(msg.sct.length+1); if (!ReadFromRFBServer(serverCutText, msg.sct.length)) return False; serverCutText[msg.sct.length] = 0; newServerCutText = True; break; } default: fprintf(stderr,"Unknown message type %d from VNC server\n",msg.type); return False; } return True; }
static Bool HandleHextileBPP (int rx, int ry, int rw, int rh) { CARDBPP bg, fg; /* XGCValues gcv; */ int i; CARD8 *ptr; int x, y, w, h; int sx, sy, sw, sh; CARD8 subencoding; CARD8 nSubrects; for (y = ry; y < ry+rh; y += 16) { for (x = rx; x < rx+rw; x += 16) { w = h = 16; if (rx+rw - x < 16) w = rx+rw - x; if (ry+rh - y < 16) h = ry+rh - y; if (!ReadFromRFBServer((char *)&subencoding, 1)) return False; if (subencoding & rfbHextileRaw) { if (!ReadFromRFBServer(buffer, w * h * (BPP / 8))) return False; /* CopyDataToScreen(buffer, x, y, w, h); */ continue; } if (subencoding & rfbHextileBackgroundSpecified) if (!ReadFromRFBServer((char *)&bg, sizeof(bg))) return False; #if (BPP == 8) /* if (appData.useBGR233) gcv.foreground = BGR233ToPixel[bg]; else */ #endif /* gcv.foreground = bg; XChangeGC(dpy, gc, GCForeground, &gcv); XFillRectangle(dpy, desktopWin, gc, x, y, w, h); */ if (subencoding & rfbHextileForegroundSpecified) if (!ReadFromRFBServer((char *)&fg, sizeof(fg))) return False; if (!(subencoding & rfbHextileAnySubrects)) { continue; } if (!ReadFromRFBServer((char *)&nSubrects, 1)) return False; ptr = (CARD8 *)buffer; if (subencoding & rfbHextileSubrectsColoured) { if (!ReadFromRFBServer(buffer, nSubrects * (2 + (BPP / 8)))) return False; for (i = 0; i < nSubrects; i++) { GET_PIXEL(fg, ptr); sx = rfbHextileExtractX(*ptr); sy = rfbHextileExtractY(*ptr); ptr++; sw = rfbHextileExtractW(*ptr); sh = rfbHextileExtractH(*ptr); ptr++; #if (BPP == 8) /* if (appData.useBGR233) gcv.foreground = BGR233ToPixel[fg]; else */ #endif /* gcv.foreground = fg; XChangeGC(dpy, gc, GCForeground, &gcv); XFillRectangle(dpy, desktopWin, gc, x+sx, y+sy, sw, sh); */ } } else { if (!ReadFromRFBServer(buffer, nSubrects * 2)) return False; #if (BPP == 8) /* if (appData.useBGR233) gcv.foreground = BGR233ToPixel[fg]; else */ #endif /* gcv.foreground = fg; XChangeGC(dpy, gc, GCForeground, &gcv); */ for (i = 0; i < nSubrects; i++) { sx = rfbHextileExtractX(*ptr); sy = rfbHextileExtractY(*ptr); ptr++; sw = rfbHextileExtractW(*ptr); sh = rfbHextileExtractH(*ptr); ptr++; /* XFillRectangle(dpy, desktopWin, gc, x+sx, y+sy, sw, sh); */ } } } } return True; }
Bool InitialiseRFBConnection() { rfbProtocolVersionMsg pv; int major,minor; CARD32 authScheme, reasonLen, authResult; char *reason; CARD8 challenge[CHALLENGESIZE]; char *passwd; int i; rfbClientInitMsg ci; if (!ReadFromRFBServer(pv, sz_rfbProtocolVersionMsg)) return False; pv[sz_rfbProtocolVersionMsg] = 0; if (sscanf(pv,rfbProtocolVersionFormat,&major,&minor) != 2) { fprintf(stderr,"Not a valid VNC server\n"); return False; } if (!appData.quiet) { fprintf(stderr,"VNC server supports protocol version %d.%d (viewer %d.%d)\n", major, minor, rfbProtocolMajorVersion, rfbProtocolMinorVersion); } major = rfbProtocolMajorVersion; minor = rfbProtocolMinorVersion; sprintf(pv,rfbProtocolVersionFormat,major,minor); if (!WriteToRFBServer(pv, sz_rfbProtocolVersionMsg)) return False; if (!ReadFromRFBServer((char *)&authScheme, 4)) return False; authScheme = Swap32IfLE(authScheme); switch (authScheme) { case rfbConnFailed: if (!ReadFromRFBServer((char *)&reasonLen, 4)) return False; reasonLen = Swap32IfLE(reasonLen); reason = malloc(reasonLen); if (!ReadFromRFBServer(reason, reasonLen)) return False; fprintf(stderr,"VNC connection failed: %.*s\n",(int)reasonLen, reason); return False; case rfbNoAuth: if (!appData.quiet) { fprintf(stderr,"No authentication needed\n"); } break; case rfbVncAuth: if (!ReadFromRFBServer((char *)challenge, CHALLENGESIZE)) return False; if (appData.passwordFile) { passwd = vncDecryptPasswdFromFile(appData.passwordFile); if (!passwd) { fprintf(stderr,"Cannot read valid password from file \"%s\"\n", appData.passwordFile); return False; } /* added this to read the command line password */ } else if (appData.tpass) { passwd = appData.tpass; } else { passwd = getpass("Password: "******"Reading password failed\n"); return False; } if (strlen(passwd) > 8) { passwd[8] = '\0'; } vncEncryptBytes(challenge, passwd); /* Lose the password from memory */ for (i = strlen(passwd); i >= 0; i--) { passwd[i] = '\0'; } if (!WriteToRFBServer((char *)challenge, CHALLENGESIZE)) return False; if (!ReadFromRFBServer((char *)&authResult, 4)) return False; authResult = Swap32IfLE(authResult); switch (authResult) { case rfbVncAuthOK: if (!appData.quiet) { fprintf(stderr,"VNC authentication succeeded\n"); } break; case rfbVncAuthFailed: fprintf(stderr,"VNC authentication failed\n"); return False; case rfbVncAuthTooMany: fprintf(stderr,"VNC authentication failed - too many tries\n"); return False; default: fprintf(stderr,"Unknown VNC authentication result: %d\n", (int)authResult); return False; } break; default: fprintf(stderr,"Unknown authentication scheme from VNC server: %d\n", (int)authScheme); return False; } ci.shared = 1; if (!WriteToRFBServer((char *)&ci, sz_rfbClientInitMsg)) return False; if (!ReadFromRFBServer((char *)&si, sz_rfbServerInitMsg)) return False; si.framebufferWidth = Swap16IfLE(si.framebufferWidth); si.framebufferHeight = Swap16IfLE(si.framebufferHeight); si.format.redMax = Swap16IfLE(si.format.redMax); si.format.greenMax = Swap16IfLE(si.format.greenMax); si.format.blueMax = Swap16IfLE(si.format.blueMax); si.nameLength = Swap32IfLE(si.nameLength); desktopName = malloc(si.nameLength + 1); if (!desktopName) { fprintf(stderr, "Error allocating memory for desktop name, %lu bytes\n", (unsigned long)si.nameLength); return False; } if (!ReadFromRFBServer(desktopName, si.nameLength)) return False; desktopName[si.nameLength] = 0; if (!appData.quiet) { fprintf(stderr,"Desktop name \"%s\"\n",desktopName); fprintf(stderr,"Connected to VNC server, using protocol version %d.%d\n", rfbProtocolMajorVersion, rfbProtocolMinorVersion); fprintf(stderr,"VNC server default format:\n"); PrintPixelFormat(&si.format); } return True; }
Bool HandleXCursor(int xhot, int yhot, int width, int height) { rfbXCursorColors colors; size_t bytesPerRow, bytesData; char *buf = NULL; XColor bg, fg; Drawable dr; unsigned int wret = 0, hret = 0; Pixmap source, mask; Cursor cursor; int i; bytesPerRow = (width + 7) / 8; bytesData = bytesPerRow * height; dr = DefaultRootWindow(dpy); if (width * height) { if (!ReadFromRFBServer((char *)&colors, sz_rfbXCursorColors)) return False; buf = malloc(bytesData * 2); if (buf == NULL) return False; if (!ReadFromRFBServer(buf, bytesData * 2)) { free(buf); return False; } XQueryBestCursor(dpy, dr, width, height, &wret, &hret); } if (width * height == 0 || (int) wret < width || (int) hret < height) { /* Free resources */ if (buf != NULL) free(buf); FreeX11Cursor(); return True; } bg.red = (unsigned short)colors.backRed << 8 | colors.backRed; bg.green = (unsigned short)colors.backGreen << 8 | colors.backGreen; bg.blue = (unsigned short)colors.backBlue << 8 | colors.backBlue; fg.red = (unsigned short)colors.foreRed << 8 | colors.foreRed; fg.green = (unsigned short)colors.foreGreen << 8 | colors.foreGreen; fg.blue = (unsigned short)colors.foreBlue << 8 | colors.foreBlue; for (i = 0; (size_t) i < bytesData * 2; i++) buf[i] = (char)_reverse_byte[(int)buf[i] & 0xFF]; source = XCreateBitmapFromData(dpy, dr, buf, width, height); mask = XCreateBitmapFromData(dpy, dr, &buf[bytesData], width, height); cursor = XCreatePixmapCursor(dpy, source, mask, &fg, &bg, xhot, yhot); XFreePixmap(dpy, source); XFreePixmap(dpy, mask); free(buf); XDefineCursor(dpy, desktopWin, cursor); FreeX11Cursor(); prevXCursor = cursor; prevXCursorSet = True; 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; }
rfbBool HandleVeNCryptAuth(rfbClient* client) { uint8_t major, minor, status; uint32_t authScheme; rfbBool anonTLS; gnutls_certificate_credentials_t x509_cred = NULL; int ret; if (!InitializeTLS()) return FALSE; /* Read VeNCrypt version */ if (!ReadFromRFBServer(client, (char *)&major, 1) || !ReadFromRFBServer(client, (char *)&minor, 1)) { return FALSE; } rfbClientLog("Got VeNCrypt version %d.%d from server.\n", (int)major, (int)minor); if (major != 0 && minor != 2) { rfbClientLog("Unsupported VeNCrypt version.\n"); return FALSE; } if (!WriteToRFBServer(client, (char *)&major, 1) || !WriteToRFBServer(client, (char *)&minor, 1) || !ReadFromRFBServer(client, (char *)&status, 1)) { return FALSE; } if (status != 0) { rfbClientLog("Server refused VeNCrypt version %d.%d.\n", (int)major, (int)minor); return FALSE; } if (!ReadVeNCryptSecurityType(client, &authScheme)) return FALSE; if (!ReadFromRFBServer(client, (char *)&status, 1) || status != 1) { rfbClientLog("Server refused VeNCrypt authentication %d (%d).\n", authScheme, (int)status); return FALSE; } client->subAuthScheme = authScheme; /* Some VeNCrypt security types are anonymous TLS, others are X509 */ switch (authScheme) { case rfbVeNCryptTLSNone: case rfbVeNCryptTLSVNC: case rfbVeNCryptTLSPlain: anonTLS = TRUE; break; default: anonTLS = FALSE; break; } /* Get X509 Credentials if it's not anonymous */ if (!anonTLS) { rfbCredential *cred; if (!client->GetCredential) { rfbClientLog("GetCredential callback is not set.\n"); return FALSE; } cred = client->GetCredential(client, rfbCredentialTypeX509); if (!cred) { rfbClientLog("Reading credential failed\n"); return FALSE; } x509_cred = CreateX509CertCredential(cred); FreeX509Credential(cred); if (!x509_cred) return FALSE; } /* Start up the TLS session */ if (!InitializeTLSSession(client, anonTLS)) return FALSE; if (anonTLS) { if (!SetTLSAnonCredential(client)) return FALSE; } else { if ((ret = gnutls_credentials_set((gnutls_session_t)client->tlsSession, GNUTLS_CRD_CERTIFICATE, x509_cred)) < 0) { rfbClientLog("Cannot set x509 credential: %s.\n", gnutls_strerror(ret)); FreeTLS(client); return FALSE; } } if (!HandshakeTLS(client)) return FALSE; /* TODO: validate certificate */ /* We are done here. The caller should continue with client->subAuthScheme * to do actual sub authentication. */ return TRUE; }
Bool VNCViewer::HandleHextileBPP (sgVNCViewer *ct, int rx, int ry, int rw, int rh) { CARDBPP bg, fg; int i; CARD8 *ptr; int x, y, w, h; int sx, sy, sw, sh; CARD8 subencoding; CARD8 nSubrects; for (y = ry; y < ry+rh; y += 16) { for (x = rx; x < rx+rw; x += 16) { w = h = 16; if (rx+rw - x < 16) w = rx+rw - x; if (ry+rh - y < 16) h = ry+rh - y; if (!ReadFromRFBServer((char *)&subencoding, 1)) return False; if (subencoding & rfbHextileRaw) { if (!ReadFromRFBServer(buffer, w * h * (BPP / 8))) return False; ct->CopyDataToScreen(buffer, x, y, w, h); continue; } if (subencoding & rfbHextileBackgroundSpecified) if (!ReadFromRFBServer((char *)&bg, sizeof(bg))) return False; ct->FillToScreen(bg, x, y, w, h); if (subencoding & rfbHextileForegroundSpecified) if (!ReadFromRFBServer((char *)&fg, sizeof(fg))) return False; if (!(subencoding & rfbHextileAnySubrects)) { continue; } if (!ReadFromRFBServer((char *)&nSubrects, 1)) return False; ptr = (CARD8 *)buffer; if (subencoding & rfbHextileSubrectsColoured) { if (!ReadFromRFBServer(buffer, nSubrects * (2 + (BPP / 8)))) return False; for (i = 0; i < nSubrects; i++) { GET_PIXEL(fg, ptr); sx = rfbHextileExtractX(*ptr); sy = rfbHextileExtractY(*ptr); ptr++; sw = rfbHextileExtractW(*ptr); sh = rfbHextileExtractH(*ptr); ptr++; ct->FillToScreen(fg, x+sx, y+sy, sw, sh); } } else { if (!ReadFromRFBServer(buffer, nSubrects * 2)) return False; for (i = 0; i < nSubrects; i++) { sx = rfbHextileExtractX(*ptr); sy = rfbHextileExtractY(*ptr); ptr++; sw = rfbHextileExtractW(*ptr); sh = rfbHextileExtractH(*ptr); ptr++; ct->FillToScreen(fg, x+sx, y+sy, sw, sh); } } } } return True; }
Bool HandleRFBServerMessage() { rfbServerToClientMsg msg; if (!ReadFromRFBServer((char *)&msg, 1)) return False; switch (msg.type) { case rfbSetColourMapEntries: { int i; CARD16 rgb[3]; XColor xc; if (!ReadFromRFBServer(((char *)&msg) + 1, sz_rfbSetColourMapEntriesMsg - 1)) return False; msg.scme.firstColour = Swap16IfLE(msg.scme.firstColour); msg.scme.nColours = Swap16IfLE(msg.scme.nColours); for (i = 0; i < msg.scme.nColours; i++) { if (!ReadFromRFBServer((char *)rgb, 6)) return False; xc.pixel = msg.scme.firstColour + i; xc.red = Swap16IfLE(rgb[0]); xc.green = Swap16IfLE(rgb[1]); xc.blue = Swap16IfLE(rgb[2]); xc.flags = DoRed|DoGreen|DoBlue; XStoreColor(dpy, cmap, &xc); } break; } case rfbFramebufferUpdate: { rfbFramebufferUpdateRectHeader rect; int linesToRead; int bytesPerLine; int i; int usecs; if (!ReadFromRFBServer(((char *)&msg.fu) + 1, sz_rfbFramebufferUpdateMsg - 1)) return False; msg.fu.nRects = Swap16IfLE(msg.fu.nRects); for (i = 0; i < msg.fu.nRects; i++) { if (!ReadFromRFBServer((char *)&rect, sz_rfbFramebufferUpdateRectHeader)) return False; rect.encoding = Swap32IfLE(rect.encoding); if (rect.encoding == rfbEncodingLastRect) break; rect.r.x = Swap16IfLE(rect.r.x); rect.r.y = Swap16IfLE(rect.r.y); rect.r.w = Swap16IfLE(rect.r.w); rect.r.h = Swap16IfLE(rect.r.h); if (rect.encoding == rfbEncodingXCursor || rect.encoding == rfbEncodingRichCursor) { if (!HandleCursorShape(rect.r.x, rect.r.y, rect.r.w, rect.r.h, rect.encoding)) { return False; } continue; } if (rect.encoding == rfbEncodingPointerPos) { if (!HandleCursorPos(rect.r.x, rect.r.y)) { return False; } continue; } if ((rect.r.x + rect.r.w > si.framebufferWidth) || (rect.r.y + rect.r.h > si.framebufferHeight)) { fprintf(stderr,"Rect too large: %dx%d at (%d, %d)\n", rect.r.w, rect.r.h, rect.r.x, rect.r.y); return False; } if (rect.r.h * rect.r.w == 0) { fprintf(stderr,"Zero size rect - ignoring\n"); continue; } /* If RichCursor encoding is used, we should prevent collisions between framebuffer updates and cursor drawing operations. */ SoftCursorLockArea(rect.r.x, rect.r.y, rect.r.w, rect.r.h); switch (rect.encoding) { case rfbEncodingRaw: bytesPerLine = rect.r.w * myFormat.bitsPerPixel / 8; linesToRead = BUFFER_SIZE / bytesPerLine; while (rect.r.h > 0) { if (linesToRead > rect.r.h) linesToRead = rect.r.h; if (!ReadFromRFBServer(buffer,bytesPerLine * linesToRead)) return False; CopyDataToScreen(buffer, rect.r.x, rect.r.y, rect.r.w, linesToRead); rect.r.h -= linesToRead; rect.r.y += linesToRead; } break; case rfbEncodingCopyRect: { rfbCopyRect cr; if (!ReadFromRFBServer((char *)&cr, sz_rfbCopyRect)) return False; cr.srcX = Swap16IfLE(cr.srcX); cr.srcY = Swap16IfLE(cr.srcY); /* If RichCursor encoding is used, we should extend our "cursor lock area" (previously set to destination rectangle) to the source rectangle as well. */ SoftCursorLockArea(cr.srcX, cr.srcY, rect.r.w, rect.r.h); if (appData.copyRectDelay != 0) { XFillRectangle(dpy, desktopWin, srcGC, cr.srcX, cr.srcY, rect.r.w, rect.r.h); #if VNC_CAPTURE myxfillrec(dpy, srcGC, cr.srcX, cr.srcY, rect.r.w, rect.r.h); #endif XFillRectangle(dpy, desktopWin, dstGC, rect.r.x, rect.r.y, rect.r.w, rect.r.h); #if VNC_CAPTURE myxfillrec(dpy, dstGC, cr.srcX, cr.srcY, rect.r.w, rect.r.h); #endif XSync(dpy,False); usleep(appData.copyRectDelay * 1000); XFillRectangle(dpy, desktopWin, dstGC, rect.r.x, rect.r.y, rect.r.w, rect.r.h); #if VNC_CAPTURE myxfillrec(dpy, dstGC, rect.r.x, rect.r.y, rect.r.w, rect.r.h); #endif XFillRectangle(dpy, desktopWin, srcGC, cr.srcX, cr.srcY, rect.r.w, rect.r.h); #if VNC_CAPTURE myxfillrec(dpy, srcGC, cr.srcX, cr.srcY, rect.r.w, rect.r.h); #endif } XCopyArea(dpy, desktopWin, desktopWin, gc, cr.srcX, cr.srcY, rect.r.w, rect.r.h, rect.r.x, rect.r.y); #if VNC_CAPTURE myxcparea(dpy, gc, cr.srcX, cr.srcY, rect.r.w, rect.r.h,rect.r.x,rect.r.y); #endif break; } case rfbEncodingRRE: { switch (myFormat.bitsPerPixel) { case 8: if (!HandleRRE8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; case 16: if (!HandleRRE16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; case 32: if (!HandleRRE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; } break; } case rfbEncodingCoRRE: { switch (myFormat.bitsPerPixel) { case 8: if (!HandleCoRRE8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; case 16: if (!HandleCoRRE16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; case 32: if (!HandleCoRRE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; } break; } case rfbEncodingHextile: { switch (myFormat.bitsPerPixel) { case 8: if (!HandleHextile8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; case 16: if (!HandleHextile16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; case 32: if (!HandleHextile32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; } break; } case rfbEncodingZlib: { switch (myFormat.bitsPerPixel) { case 8: if (!HandleZlib8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; case 16: if (!HandleZlib16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; case 32: if (!HandleZlib32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; } break; } case rfbEncodingTight: { switch (myFormat.bitsPerPixel) { case 8: if (!HandleTight8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; case 16: if (!HandleTight16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; case 32: if (!HandleTight32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; } break; } default: fprintf(stderr,"Unknown rect encoding %d\n", (int)rect.encoding); return False; } /* Now we may discard "soft cursor locks". */ SoftCursorUnlockScreen(); } #ifdef MITSHM /* if using shared memory PutImage, make sure that the X server has updated its framebuffer before we reuse the shared memory. This is mainly to avoid copyrect using invalid screen contents - not sure if we'd need it otherwise. */ if (appData.useShm) XSync(dpy, False); #endif if (!SendIncrementalFramebufferUpdateRequest()) return False; break; } case rfbBell: { Window toplevelWin; XBell(dpy, 0); if (appData.raiseOnBeep) { toplevelWin = XtWindow(toplevel); XMapRaised(dpy, toplevelWin); } break; } case rfbServerCutText: { if (!ReadFromRFBServer(((char *)&msg) + 1, sz_rfbServerCutTextMsg - 1)) return False; msg.sct.length = Swap32IfLE(msg.sct.length); if (serverCutText) free(serverCutText); serverCutText = malloc(msg.sct.length+1); if (!ReadFromRFBServer(serverCutText, msg.sct.length)) return False; serverCutText[msg.sct.length] = 0; newServerCutText = True; break; } default: fprintf(stderr,"Unknown message type %d from VNC server\n",msg.type); return False; } return True; }
Bool InitialiseRFBConnection(void) { rfbProtocolVersionMsg pv; int server_major, server_minor; int viewer_major, viewer_minor; rfbClientInitMsg ci; int secType; /* if the connection is immediately closed, don't report anything, so that pmw's monitor can make test connections */ if (listenSpecified) errorMessageOnReadFailure = False; if (!ReadFromRFBServer(pv, sz_rfbProtocolVersionMsg)) return False; errorMessageOnReadFailure = True; pv[sz_rfbProtocolVersionMsg] = 0; if (sscanf(pv, rfbProtocolVersionFormat, &server_major, &server_minor) != 2) { fprintf(stderr,"Not a valid VNC server\n"); return False; } viewer_major = rfbProtocolMajorVersion; if (server_major == 3 && server_minor >= rfbProtocolMinorVersion) { /* the server supports at least the standard protocol 3.7 */ viewer_minor = rfbProtocolMinorVersion; } else { /* any other server version, request the standard 3.3 */ viewer_minor = rfbProtocolFallbackMinorVersion; } fprintf(stderr, "Connected to RFB server, using protocol version %d.%d\n", viewer_major, viewer_minor); sprintf(pv, rfbProtocolVersionFormat, viewer_major, viewer_minor); if (!WriteExact(rfbsock, pv, sz_rfbProtocolVersionMsg)) return False; /* Read or select the security type. */ if (viewer_minor == rfbProtocolMinorVersion) { secType = SelectSecurityType(); } else { secType = ReadSecurityType(); } if (secType == rfbSecTypeInvalid) return False; switch (secType) { case rfbSecTypeNone: fprintf(stderr, "No authentication needed\n"); break; case rfbSecTypeVncAuth: if (!AuthenticateVNC()) return False; break; case rfbSecTypeTight: tightVncProtocol = True; InitCapabilities(); if (!SetupTunneling()) return False; if (!PerformAuthenticationTight()) return False; break; default: /* should never happen */ fprintf(stderr, "Internal error: Invalid security type\n"); return False; } ci.shared = (appData.shareDesktop ? 1 : 0); if (!WriteExact(rfbsock, (char *)&ci, sz_rfbClientInitMsg)) return False; if (!ReadFromRFBServer((char *)&si, sz_rfbServerInitMsg)) return False; si.framebufferWidth = Swap16IfLE(si.framebufferWidth); si.framebufferHeight = Swap16IfLE(si.framebufferHeight); si.format.redMax = Swap16IfLE(si.format.redMax); si.format.greenMax = Swap16IfLE(si.format.greenMax); si.format.blueMax = Swap16IfLE(si.format.blueMax); si.nameLength = Swap32IfLE(si.nameLength); /* FIXME: Check arguments to malloc() calls. */ desktopName = malloc(si.nameLength + 1); if (!desktopName) { fprintf(stderr, "Error allocating memory for desktop name, %lu bytes\n", (unsigned long)si.nameLength); return False; } if (!ReadFromRFBServer(desktopName, si.nameLength)) return False; desktopName[si.nameLength] = 0; fprintf(stderr,"Desktop name \"%s\"\n",desktopName); fprintf(stderr,"VNC server default format:\n"); PrintPixelFormat(&si.format); if (tightVncProtocol) { /* Read interaction capabilities (protocol 3.7t) */ if (!ReadInteractionCaps()) return False; } 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; }
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; }