1 /*
2  * Copyright (c) 2005 Novell, Inc.
3  * All Rights Reserved.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, contact Novell, Inc.
16  *
17  * To contact Novell about this file by physical or electronic mail,
18  * you may find current contact information at www.novell.com
19  *
20  * Author		: Rohit Kumar
21  * Email ID	: rokumar@novell.com
22  * Date		: 14th July 2005
23  */
24 
25 #include <pwd.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <dirent.h>
31 #include <pthread.h>
32 #include <sys/stat.h>
33 #include <sys/types.h>
34 #include <limits.h>
35 
36 #include <rfb/rfb.h>
37 #include "rfbtightproto.h"
38 #include "filetransfermsg.h"
39 #include "handlefiletransferrequest.h"
40 
41 
42 pthread_mutex_t fileDownloadMutex = PTHREAD_MUTEX_INITIALIZER;
43 
44 rfbBool fileTransferEnabled = TRUE;
45 rfbBool fileTransferInitted = FALSE;
46 char ftproot[PATH_MAX];
47 
48 
49 /******************************************************************************
50  * File Transfer Init methods. These methods are called for initializating
51  * File Transfer and setting ftproot.
52  ******************************************************************************/
53 
54 void InitFileTransfer();
55 int SetFtpRoot(char* path);
56 char* GetHomeDir(uid_t uid);
57 void FreeHomeDir(char *homedir);
58 
59 /*
60  * InitFileTransfer method is called before parsing the command-line options
61  * for Xvnc. This sets the ftproot to the Home dir of the user running the Xvnc
62  * server. In case of error ftproot is set to '\0' char.
63  */
64 
65 void
InitFileTransfer()66 InitFileTransfer()
67 {
68 	char* userHome = NULL;
69 	uid_t uid = geteuid();
70 
71 	if(fileTransferInitted)
72 		return;
73 
74 	rfbLog("tightvnc-filetransfer/InitFileTransfer\n");
75 
76 	memset(ftproot, 0, sizeof(ftproot));
77 
78 	userHome = GetHomeDir(uid);
79 
80 	if((userHome != NULL) && (strlen(userHome) != 0)) {
81 		SetFtpRoot(userHome);
82 		FreeHomeDir(userHome);
83 	}
84 
85 	fileTransferEnabled = TRUE;
86 	fileTransferInitted = TRUE;
87 }
88 
89 #ifndef __GNUC__
90 #define __FUNCTION__ "unknown"
91 #endif
92 
93 /*
94  *  This method is called from InitFileTransfer method and
95  *  if the command line option for ftproot is provided.
96  */
97 int
SetFtpRoot(char * path)98 SetFtpRoot(char* path)
99 {
100 	struct stat stat_buf;
101 	DIR* dir = NULL;
102 
103 	rfbLog("tightvnc-filetransfer/SetFtpRoot\n");
104 
105 	if((path == NULL) || (strlen(path) == 0) || (strlen(path) > (PATH_MAX - 1))) {
106 		rfbLog("File [%s]: Method [%s]: parameter passed is improper, ftproot"
107 				" not changed\n", __FILE__, __FUNCTION__);
108 		return FALSE;
109 	}
110 
111 	if(stat(path, &stat_buf) < 0) {
112 		rfbLog("File [%s]: Method [%s]: Reading stat for file %s failed\n",
113 				__FILE__, __FUNCTION__, path);
114 		return FALSE;
115 	}
116 
117 	if(S_ISDIR(stat_buf.st_mode) == 0) {
118 		rfbLog("File [%s]: Method [%s]: path specified is not a directory\n",
119 				__FILE__, __FUNCTION__);
120 		return FALSE;
121 	}
122 
123 	if((dir = opendir(path)) == NULL) {
124 		rfbLog("File [%s]: Method [%s]: Not able to open the directory\n",
125 				__FILE__, __FUNCTION__);
126 		return FALSE;
127 	}
128 	else {
129 		closedir(dir);
130 		dir = NULL;
131 	}
132 
133 
134 	memset(ftproot, 0, PATH_MAX);
135 	if(path[strlen(path)-1] == '/') {
136 		memcpy(ftproot, path, strlen(path)-1);
137 	}
138 	else
139 		memcpy(ftproot, path, strlen(path));
140 
141 
142 	return TRUE;
143 }
144 
145 
146 /*
147  * Get the home directory for the user name
148  * param: username - name of the user for whom the home directory is required.
149  * returns: returns the home directory for the user, or null in case the entry
150  * is not found or any error. The returned string must be freed by calling the
151  * freehomedir function.
152 */
153 char*
GetHomeDir(uid_t uid)154 GetHomeDir(uid_t uid)
155 {
156 	struct passwd *pwEnt = NULL;
157 	char *homedir = NULL;
158 
159 	pwEnt = getpwuid (uid);
160 	if (pwEnt == NULL)
161 		return NULL;
162 
163 	if(pwEnt->pw_dir != NULL) {
164 		homedir = strdup (pwEnt->pw_dir);
165 	}
166 
167 	return homedir;
168 }
169 
170 
171 /*
172  * Free the home directory allocated by a previous call to retrieve the home
173  * directory. param: homedir - the string returned by a previous call to
174  * retrieve home directory for a user.
175  */
176 void
FreeHomeDir(char * homedir)177 FreeHomeDir(char *homedir)
178 {
179     free (homedir);
180 }
181 
182 
183 /******************************************************************************
184  * General methods.
185  ******************************************************************************/
186 
187 /*
188  * When the console sends the File Transfer Request, it sends the file path with
189  * ftproot as "/". So on Agent, to get the absolute file path we need to prepend
190  * the ftproot to it.
191  */
192 char*
ConvertPath(char * path)193 ConvertPath(char* path)
194 {
195 	char p[PATH_MAX];
196 	memset(p, 0, PATH_MAX);
197 
198 	if( (path == NULL) ||
199 		(strlen(path) == 0) ||
200 		(strlen(path)+strlen(ftproot) > PATH_MAX - 1) ) {
201 
202 		rfbLog("File [%s]: Method [%s]: cannot create path for file transfer\n",
203 				__FILE__, __FUNCTION__);
204 		return NULL;
205 	}
206 
207 	memcpy(p, path, strlen(path));
208 	memset(path, 0, PATH_MAX);
209 	sprintf(path, "%s%s", ftproot, p);
210 
211 	return path;
212 }
213 
214 
215 void
EnableFileTransfer(rfbBool enable)216 EnableFileTransfer(rfbBool enable)
217 {
218 	fileTransferEnabled = enable;
219 }
220 
221 
222 rfbBool
IsFileTransferEnabled()223 IsFileTransferEnabled()
224 {
225 	return fileTransferEnabled;
226 }
227 
228 
229 char*
GetFtpRoot()230 GetFtpRoot()
231 {
232 	return ftproot;
233 }
234 
235 
236 /******************************************************************************
237  * Methods to Handle File List Request.
238  ******************************************************************************/
239 
240 /*
241  *  HandleFileListRequest method is called when the server receives
242  *  FileListRequest. In case of success a file list is sent to the client.
243  *  For File List Request there is no failure reason sent.So here in case of any
244  *  "unexpected" error no information will be sent. As these conditions should
245  *  never come. Lets hope it never arrives :)
246  *  In case of dir open failure an empty list will be sent, just the header of
247  *  the message filled up. So on console you will get an Empty listing.
248  */
249 void
HandleFileListRequest(rfbClientPtr cl,rfbTightClientRec * data)250 HandleFileListRequest(rfbClientPtr cl, rfbTightClientRec* data)
251 {
252 	rfbClientToServerTightMsg msg;
253 	int n = 0;
254 	char path[PATH_MAX]; /* PATH_MAX has the value 4096 and is defined in limits.h */
255 	FileTransferMsg fileListMsg;
256 
257 	memset(&msg, 0, sizeof(rfbClientToServerTightMsg));
258 	memset(path, 0, PATH_MAX);
259 	memset(&fileListMsg, 0, sizeof(FileTransferMsg));
260 
261 	if(cl == NULL) {
262 		rfbLog("File [%s]: Method [%s]: Unexpected error: rfbClientPtr is null\n",
263 				__FILE__, __FUNCTION__);
264 		return;
265 	}
266 
267 	if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileListRequestMsg-1)) <= 0) {
268 
269 		if (n < 0)
270 			rfbLog("File [%s]: Method [%s]: Socket error while reading dir name"
271 					" length\n", __FILE__, __FUNCTION__);
272 
273 	    rfbCloseClient(cl);
274 	    return;
275 	}
276 
277 	msg.flr.dirNameSize = Swap16IfLE(msg.flr.dirNameSize);
278 	if ((msg.flr.dirNameSize == 0) ||
279 		(msg.flr.dirNameSize > (PATH_MAX - 1))) {
280 
281 		rfbLog("File [%s]: Method [%s]: Unexpected error:: path length is "
282 				"greater that PATH_MAX\n", __FILE__, __FUNCTION__);
283 
284 		return;
285 	}
286 
287 	if((n = rfbReadExact(cl, path, msg.flr.dirNameSize)) <= 0) {
288 
289 		if (n < 0)
290 			rfbLog("File [%s]: Method [%s]: Socket error while reading dir name\n",
291 							__FILE__, __FUNCTION__);
292 
293 	    rfbCloseClient(cl);
294 	    return;
295 	}
296 
297 	if(ConvertPath(path) == NULL) {
298 
299 		/* The execution should never reach here */
300     	rfbLog("File [%s]: Method [%s]: Unexpected error: path is NULL",
301     			__FILE__, __FUNCTION__);
302     	return;
303 	}
304 
305     fileListMsg = GetFileListResponseMsg(path, (char) (msg.flr.flags));
306 
307     if((fileListMsg.data == NULL) || (fileListMsg.length == 0)) {
308 
309     	rfbLog("File [%s]: Method [%s]: Unexpected error:: Data to be sent is "
310     		"of Zero length\n",	__FILE__, __FUNCTION__);
311     	return;
312 	}
313 
314     rfbWriteExact(cl, fileListMsg.data, fileListMsg.length);
315 
316     FreeFileTransferMsg(fileListMsg);
317 }
318 
319 
320 /******************************************************************************
321  * Methods to Handle File Download Request.
322  ******************************************************************************/
323 
324 void HandleFileDownloadLengthError(rfbClientPtr cl, short fNameSize);
325 void SendFileDownloadLengthErrMsg(rfbClientPtr cl);
326 void HandleFileDownload(rfbClientPtr cl, rfbTightClientPtr data);
327 #ifdef TODO
328 void HandleFileDownloadRequest(rfbClientPtr cl);
329 void SendFileDownloadErrMsg(rfbClientPtr cl);
330 void* RunFileDownloadThread(void* client);
331 #endif
332 
333 /*
334  * HandleFileDownloadRequest method is called when the server receives
335  * rfbFileDownload request message.
336  */
337 void
HandleFileDownloadRequest(rfbClientPtr cl,rfbTightClientPtr rtcp)338 HandleFileDownloadRequest(rfbClientPtr cl, rfbTightClientPtr rtcp)
339 {
340 	int n = 0;
341 	char path[PATH_MAX]; /* PATH_MAX has the value 4096 and is defined in limits.h */
342 	rfbClientToServerTightMsg msg;
343 
344  	memset(path, 0, sizeof(path));
345 	memset(&msg, 0, sizeof(rfbClientToServerTightMsg));
346 
347 	if(cl == NULL) {
348 
349 		rfbLog("File [%s]: Method [%s]: Unexpected error:: rfbClientPtr is null\n",
350 				__FILE__, __FUNCTION__);
351 		return;
352 	}
353 
354 	if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileDownloadRequestMsg-1)) <= 0) {
355 
356 		if (n < 0)
357 			rfbLog("File [%s]: Method [%s]: Error while reading dir name length\n",
358 					__FILE__, __FUNCTION__);
359 
360 	    rfbCloseClient(cl);
361 	    return;
362 	}
363 
364 	msg.fdr.fNameSize = Swap16IfLE(msg.fdr.fNameSize);
365 	msg.fdr.position = Swap16IfLE(msg.fdr.position);
366 
367 	if ((msg.fdr.fNameSize == 0) ||
368 		(msg.fdr.fNameSize > (PATH_MAX - 1))) {
369 
370 		rfbLog("File [%s]: Method [%s]: Error: path length is greater than"
371 				" PATH_MAX\n", __FILE__, __FUNCTION__);
372 
373 		HandleFileDownloadLengthError(cl, msg.fdr.fNameSize);
374 		return;
375 	}
376 
377 	if((n = rfbReadExact(cl, rtcp->rcft.rcfd.fName, msg.fdr.fNameSize)) <= 0) {
378 
379 		if (n < 0)
380 			rfbLog("File [%s]: Method [%s]: Error while reading dir name length\n",
381 							__FILE__, __FUNCTION__);
382 
383 	    rfbCloseClient(cl);
384 	    return;
385 	}
386 	rtcp->rcft.rcfd.fName[msg.fdr.fNameSize] = '\0';
387 
388 	if(ConvertPath(rtcp->rcft.rcfd.fName) == NULL) {
389 
390     	rfbLog("File [%s]: Method [%s]: Unexpected error: path is NULL",
391     			__FILE__, __FUNCTION__);
392 
393 
394 		 /* This condition can come only if the file path is greater than
395 		    PATH_MAX. So sending file path length error msg back to client.
396 		 */
397 
398     	SendFileDownloadLengthErrMsg(cl);
399 	return;
400 	}
401 
402 	HandleFileDownload(cl, rtcp);
403 
404 }
405 
406 
407 void
HandleFileDownloadLengthError(rfbClientPtr cl,short fNameSize)408 HandleFileDownloadLengthError(rfbClientPtr cl, short fNameSize)
409 {
410 	char *path = NULL;
411 	int n = 0;
412 
413 	if((path = (char*) calloc(fNameSize, sizeof(char))) == NULL) {
414 		rfbLog("File [%s]: Method [%s]: Fatal Error: Alloc failed\n",
415 				__FILE__, __FUNCTION__);
416 		return;
417 	}
418 	if((n = rfbReadExact(cl, path, fNameSize)) <= 0) {
419 
420 		if (n < 0)
421 			rfbLog("File [%s]: Method [%s]: Error while reading dir name\n",
422 							__FILE__, __FUNCTION__);
423 
424 	    rfbCloseClient(cl);
425 
426 	    if(path != NULL) {
427 			free(path);
428 			path = NULL;
429 		}
430 
431 	    return;
432 	}
433 
434     if(path != NULL) {
435 		free(path);
436 		path = NULL;
437 	}
438 
439 	SendFileDownloadLengthErrMsg(cl);
440 }
441 
442 
443 void
SendFileDownloadLengthErrMsg(rfbClientPtr cl)444 SendFileDownloadLengthErrMsg(rfbClientPtr cl)
445 {
446 	FileTransferMsg fileDownloadErrMsg;
447 
448 	memset(&fileDownloadErrMsg, 0 , sizeof(FileTransferMsg));
449 
450 	fileDownloadErrMsg = GetFileDownloadLengthErrResponseMsg();
451 
452 	if((fileDownloadErrMsg.data == NULL) || (fileDownloadErrMsg.length == 0)) {
453 		rfbLog("File [%s]: Method [%s]: Unexpected error: fileDownloadErrMsg "
454 				"is null\n", __FILE__, __FUNCTION__);
455 		return;
456 	}
457 
458 	rfbWriteExact(cl, fileDownloadErrMsg.data, fileDownloadErrMsg.length);
459 
460 	FreeFileTransferMsg(fileDownloadErrMsg);
461 }
462 
463 extern rfbTightClientPtr rfbGetTightClientData(rfbClientPtr cl);
464 
465 void*
RunFileDownloadThread(void * client)466 RunFileDownloadThread(void* client)
467 {
468 	rfbClientPtr cl = (rfbClientPtr) client;
469 	rfbTightClientPtr rtcp = rfbGetTightClientData(cl);
470 	FileTransferMsg fileDownloadMsg;
471 
472 	if(rtcp == NULL)
473 		return NULL;
474 
475 	memset(&fileDownloadMsg, 0, sizeof(FileTransferMsg));
476 	do {
477 		pthread_mutex_lock(&fileDownloadMutex);
478 		fileDownloadMsg = GetFileDownloadResponseMsgInBlocks(cl, rtcp);
479 		pthread_mutex_unlock(&fileDownloadMutex);
480 
481 		if((fileDownloadMsg.data != NULL) && (fileDownloadMsg.length != 0)) {
482 			if(rfbWriteExact(cl, fileDownloadMsg.data, fileDownloadMsg.length) < 0)  {
483 				rfbLog("File [%s]: Method [%s]: Error while writing to socket \n"
484 						, __FILE__, __FUNCTION__);
485 
486 				if(cl != NULL) {
487 			    	rfbCloseClient(cl);
488 				CloseUndoneFileTransfer(cl, rtcp);
489 				}
490 
491 				FreeFileTransferMsg(fileDownloadMsg);
492 				return NULL;
493 			}
494 			FreeFileTransferMsg(fileDownloadMsg);
495 		}
496 	} while(rtcp->rcft.rcfd.downloadInProgress == TRUE);
497 	return NULL;
498 }
499 
500 
501 void
HandleFileDownload(rfbClientPtr cl,rfbTightClientPtr rtcp)502 HandleFileDownload(rfbClientPtr cl, rfbTightClientPtr rtcp)
503 {
504 	pthread_t fileDownloadThread;
505 	FileTransferMsg fileDownloadMsg;
506 
507 	memset(&fileDownloadMsg, 0, sizeof(FileTransferMsg));
508 	fileDownloadMsg = ChkFileDownloadErr(cl, rtcp);
509 	if((fileDownloadMsg.data != NULL) && (fileDownloadMsg.length != 0)) {
510 		rfbWriteExact(cl, fileDownloadMsg.data, fileDownloadMsg.length);
511 		FreeFileTransferMsg(fileDownloadMsg);
512 		return;
513 	}
514 	rtcp->rcft.rcfd.downloadInProgress = FALSE;
515 	rtcp->rcft.rcfd.downloadFD = -1;
516 
517 	if(pthread_create(&fileDownloadThread, NULL, RunFileDownloadThread, (void*)
518 	cl) != 0) {
519 		FileTransferMsg ftm = GetFileDownLoadErrMsg();
520 
521 		rfbLog("File [%s]: Method [%s]: Download thread creation failed\n",
522 				__FILE__, __FUNCTION__);
523 
524 		if((ftm.data != NULL) && (ftm.length != 0)) {
525 			rfbWriteExact(cl, ftm.data, ftm.length);
526 			FreeFileTransferMsg(ftm);
527 			return;
528 		}
529 
530 	}
531 
532 }
533 
534 
535 /******************************************************************************
536  * Methods to Handle File Download Cancel Request.
537  ******************************************************************************/
538 
539 
540 void
HandleFileDownloadCancelRequest(rfbClientPtr cl,rfbTightClientPtr rtcp)541 HandleFileDownloadCancelRequest(rfbClientPtr cl, rfbTightClientPtr rtcp)
542 {
543 	int n = 0;
544 	char *reason = NULL;
545 	rfbClientToServerTightMsg msg;
546 
547 	memset(&msg, 0, sizeof(rfbClientToServerTightMsg));
548 
549 	if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileDownloadCancelMsg-1)) <= 0) {
550 
551 		if (n < 0)
552 			rfbLog("File [%s]: Method [%s]: Error while reading "
553 					"FileDownloadCancelMsg\n", __FILE__, __FUNCTION__);
554 
555 	    rfbCloseClient(cl);
556 	    return;
557 	}
558 
559 	msg.fdc.reasonLen = Swap16IfLE(msg.fdc.reasonLen);
560 
561 	if(msg.fdc.reasonLen == 0) {
562 		rfbLog("File [%s]: Method [%s]: reason length received is Zero\n",
563 				__FILE__, __FUNCTION__);
564 		return;
565 	}
566 
567 	reason = (char*) calloc(msg.fdc.reasonLen + 1, sizeof(char));
568 	if(reason == NULL) {
569 		rfbLog("File [%s]: Method [%s]: Fatal Error: Memory alloc failed\n",
570 				__FILE__, __FUNCTION__);
571 		return;
572 	}
573 
574 	if((n = rfbReadExact(cl, reason, msg.fdc.reasonLen)) <= 0) {
575 
576 		if (n < 0)
577 			rfbLog("File [%s]: Method [%s]: Error while reading "
578 					"FileDownloadCancelMsg\n", __FILE__, __FUNCTION__);
579 
580 	    rfbCloseClient(cl);
581 	}
582 
583 	rfbLog("File [%s]: Method [%s]: File Download Cancel Request received:"
584 					" reason <%s>\n", __FILE__, __FUNCTION__, reason);
585 
586 	pthread_mutex_lock(&fileDownloadMutex);
587 	CloseUndoneFileTransfer(cl, rtcp);
588 	pthread_mutex_unlock(&fileDownloadMutex);
589 
590 	if(reason != NULL) {
591 		free(reason);
592 		reason = NULL;
593 	}
594 
595 }
596 
597 
598 /******************************************************************************
599  * Methods to Handle File upload request
600  ******************************************************************************/
601 
602 #ifdef TODO
603 void HandleFileUploadRequest(rfbClientPtr cl);
604 #endif
605 void HandleFileUpload(rfbClientPtr cl, rfbTightClientPtr data);
606 void HandleFileUploadLengthError(rfbClientPtr cl, short fNameSize);
607 void SendFileUploadLengthErrMsg(rfbClientPtr cl);
608 
609 
610 void
HandleFileUploadRequest(rfbClientPtr cl,rfbTightClientPtr rtcp)611 HandleFileUploadRequest(rfbClientPtr cl, rfbTightClientPtr rtcp)
612 {
613 	int n = 0;
614 	char path[PATH_MAX]; /* PATH_MAX has the value 4096 and is defined in limits.h */
615 	rfbClientToServerTightMsg msg;
616 
617 	memset(path, 0, PATH_MAX);
618 	memset(&msg, 0, sizeof(rfbClientToServerTightMsg));
619 
620 	if(cl == NULL) {
621 		rfbLog("File [%s]: Method [%s]: Unexpected error: rfbClientPtr is null\n",
622 				__FILE__, __FUNCTION__);
623 		return;
624 	}
625 
626 	if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileUploadRequestMsg-1)) <= 0) {
627 
628 		if (n < 0)
629 			rfbLog("File [%s]: Method [%s]: Error while reading FileUploadRequestMsg\n",
630 					__FILE__, __FUNCTION__);
631 
632 	    rfbCloseClient(cl);
633 	    return;
634 	}
635 
636 	msg.fupr.fNameSize = Swap16IfLE(msg.fupr.fNameSize);
637 	msg.fupr.position = Swap16IfLE(msg.fupr.position);
638 
639 	if ((msg.fupr.fNameSize == 0) ||
640 		(msg.fupr.fNameSize > (PATH_MAX - 1))) {
641 
642 		rfbLog("File [%s]: Method [%s]: error: path length is greater than PATH_MAX\n",
643 				__FILE__, __FUNCTION__);
644 		HandleFileUploadLengthError(cl, msg.fupr.fNameSize);
645 		return;
646 	}
647 
648 	if((n = rfbReadExact(cl, rtcp->rcft.rcfu.fName, msg.fupr.fNameSize)) <= 0) {
649 
650 		if (n < 0)
651 			rfbLog("File [%s]: Method [%s]: Error while reading FileUploadRequestMsg\n"
652 					__FILE__, __FUNCTION__);
653 
654 	    rfbCloseClient(cl);
655 	    return;
656 	}
657 	rtcp->rcft.rcfu.fName[msg.fupr.fNameSize] = '\0';
658 
659 	if(ConvertPath(rtcp->rcft.rcfu.fName) == NULL) {
660     	rfbLog("File [%s]: Method [%s]: Unexpected error: path is NULL\n",
661     			__FILE__, __FUNCTION__);
662 
663     	/* This may come if the path length exceeds PATH_MAX.
664     	   So sending path length error to client
665     	 */
666     	 SendFileUploadLengthErrMsg(cl);
667     	return;
668 	}
669 
670 	HandleFileUpload(cl, rtcp);
671 }
672 
673 
674 void
HandleFileUploadLengthError(rfbClientPtr cl,short fNameSize)675 HandleFileUploadLengthError(rfbClientPtr cl, short fNameSize)
676 {
677 	char *path = NULL;
678 	int n = 0;
679 
680 	if((path = (char*) calloc(fNameSize, sizeof(char))) == NULL) {
681 		rfbLog("File [%s]: Method [%s]: Fatal Error: Alloc failed\n",
682 				__FILE__, __FUNCTION__);
683 		return;
684 	}
685 	if((n = rfbReadExact(cl, path, fNameSize)) <= 0) {
686 
687 		if (n < 0)
688 			rfbLog("File [%s]: Method [%s]: Error while reading dir name\n",
689 							__FILE__, __FUNCTION__);
690 
691 	    rfbCloseClient(cl);
692 
693 	    if(path != NULL) {
694 			free(path);
695 			path = NULL;
696 		}
697 
698 	    return;
699 	}
700 
701 	rfbLog("File [%s]: Method [%s]: File Upload Length Error occured"
702 			"file path requested is <%s>\n", __FILE__, __FUNCTION__, path);
703 
704     if(path != NULL) {
705 		free(path);
706 		path = NULL;
707 	}
708 
709     SendFileUploadLengthErrMsg(cl);
710 }
711 
712 void
SendFileUploadLengthErrMsg(rfbClientPtr cl)713 SendFileUploadLengthErrMsg(rfbClientPtr cl)
714 {
715 
716 	FileTransferMsg fileUploadErrMsg;
717 
718 	memset(&fileUploadErrMsg, 0, sizeof(FileTransferMsg));
719 	fileUploadErrMsg = GetFileUploadLengthErrResponseMsg();
720 
721 	if((fileUploadErrMsg.data == NULL) || (fileUploadErrMsg.length == 0)) {
722 		rfbLog("File [%s]: Method [%s]: Unexpected error: fileUploadErrMsg is null\n",
723 				__FILE__, __FUNCTION__);
724 		return;
725 	}
726 
727 	rfbWriteExact(cl, fileUploadErrMsg.data, fileUploadErrMsg.length);
728 	FreeFileTransferMsg(fileUploadErrMsg);
729 }
730 
731 void
HandleFileUpload(rfbClientPtr cl,rfbTightClientPtr rtcp)732 HandleFileUpload(rfbClientPtr cl, rfbTightClientPtr rtcp)
733 {
734 	FileTransferMsg fileUploadErrMsg;
735 
736 	memset(&fileUploadErrMsg, 0, sizeof(FileTransferMsg));
737 
738 	rtcp->rcft.rcfu.uploadInProgress = FALSE;
739 	rtcp->rcft.rcfu.uploadFD = -1;
740 
741 	fileUploadErrMsg = ChkFileUploadErr(cl, rtcp);
742 	if((fileUploadErrMsg.data != NULL) && (fileUploadErrMsg.length != 0)) {
743 		rfbWriteExact(cl, fileUploadErrMsg.data, fileUploadErrMsg.length);
744 		FreeFileTransferMsg(fileUploadErrMsg);
745 	}
746 }
747 
748 
749 /******************************************************************************
750  * Methods to Handle File Upload Data Request
751  *****************************************************************************/
752 
753 void HandleFileUploadWrite(rfbClientPtr cl, rfbTightClientPtr rtcp, char* pBuf);
754 
755 
756 void
HandleFileUploadDataRequest(rfbClientPtr cl,rfbTightClientPtr rtcp)757 HandleFileUploadDataRequest(rfbClientPtr cl, rfbTightClientPtr rtcp)
758 {
759 	int n = 0;
760 	char* pBuf = NULL;
761 	rfbClientToServerTightMsg msg;
762 
763 	memset(&msg, 0, sizeof(rfbClientToServerTightMsg));
764 
765 	if(cl == NULL) {
766 		rfbLog("File [%s]: Method [%s]: Unexpected error: rfbClientPtr is null\n",
767 				__FILE__, __FUNCTION__);
768 		return;
769 	}
770 
771 	if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileUploadDataMsg-1)) <= 0) {
772 
773 		if (n < 0)
774 			rfbLog("File [%s]: Method [%s]: Error while reading FileUploadRequestMsg\n",
775 					__FILE__, __FUNCTION__);
776 
777 	    rfbCloseClient(cl);
778 	    return;
779 	}
780 
781 	msg.fud.realSize = Swap16IfLE(msg.fud.realSize);
782 	msg.fud.compressedSize = Swap16IfLE(msg.fud.compressedSize);
783 	if((msg.fud.realSize == 0) && (msg.fud.compressedSize == 0)) {
784 		if((n = rfbReadExact(cl, (char*)&(rtcp->rcft.rcfu.mTime), sizeof(unsigned
785 		long))) <= 0) {
786 
787 			if (n < 0)
788 				rfbLog("File [%s]: Method [%s]: Error while reading FileUploadRequestMsg\n",
789 						__FILE__, __FUNCTION__);
790 
791 		    rfbCloseClient(cl);
792 		    return;
793 		}
794 
795 		FileUpdateComplete(cl, rtcp);
796 		return;
797 	}
798 
799 	pBuf = (char*) calloc(msg.fud.compressedSize, sizeof(char));
800 	if(pBuf == NULL) {
801 		rfbLog("File [%s]: Method [%s]: Memory alloc failed\n", __FILE__, __FUNCTION__);
802 		return;
803 	}
804 	if((n = rfbReadExact(cl, pBuf, msg.fud.compressedSize)) <= 0) {
805 
806 		if (n < 0)
807 			rfbLog("File [%s]: Method [%s]: Error while reading FileUploadRequestMsg\n",
808 					__FILE__, __FUNCTION__);
809 
810 	    rfbCloseClient(cl);
811 
812 	    if(pBuf != NULL) {
813 	    	free(pBuf);
814 	    	pBuf = NULL;
815 		}
816 
817 	    return;
818 	}
819 	if(msg.fud.compressedLevel != 0) {
820 		FileTransferMsg ftm;
821 		memset(&ftm, 0, sizeof(FileTransferMsg));
822 
823 		ftm = GetFileUploadCompressedLevelErrMsg();
824 
825 		if((ftm.data != NULL) && (ftm.length != 0)) {
826 			rfbWriteExact(cl, ftm.data, ftm.length);
827 			FreeFileTransferMsg(ftm);
828 		}
829 
830 		CloseUndoneFileTransfer(cl, rtcp);
831 
832 	    if(pBuf != NULL) {
833 	    	free(pBuf);
834 	    	pBuf = NULL;
835 		}
836 
837 		return;
838 	}
839 
840 	rtcp->rcft.rcfu.fSize = msg.fud.compressedSize;
841 
842 	HandleFileUploadWrite(cl, rtcp, pBuf);
843 
844     if(pBuf != NULL) {
845     	free(pBuf);
846     	pBuf = NULL;
847 	}
848 
849 }
850 
851 
852 void
HandleFileUploadWrite(rfbClientPtr cl,rfbTightClientPtr rtcp,char * pBuf)853 HandleFileUploadWrite(rfbClientPtr cl, rfbTightClientPtr rtcp, char* pBuf)
854 {
855 	FileTransferMsg ftm;
856 	memset(&ftm, 0, sizeof(FileTransferMsg));
857 
858 	ftm = ChkFileUploadWriteErr(cl, rtcp, pBuf);
859 
860 	if((ftm.data != NULL) && (ftm.length != 0)) {
861 		rfbWriteExact(cl, ftm.data, ftm.length);
862 		FreeFileTransferMsg(ftm);
863 	}
864 }
865 
866 
867 /******************************************************************************
868  * Methods to Handle File Upload Failed Request.
869  ******************************************************************************/
870 
871 
872 void
HandleFileUploadFailedRequest(rfbClientPtr cl,rfbTightClientPtr rtcp)873 HandleFileUploadFailedRequest(rfbClientPtr cl, rfbTightClientPtr rtcp)
874 {
875 	int n = 0;
876 	char* reason = NULL;
877 	rfbClientToServerTightMsg msg;
878 
879 	memset(&msg, 0, sizeof(rfbClientToServerTightMsg));
880 
881 	if(cl == NULL) {
882 		rfbLog("File [%s]: Method [%s]: Unexpected error: rfbClientPtr is null\n",
883 				__FILE__, __FUNCTION__);
884 		return;
885 	}
886 
887 	if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileUploadFailedMsg-1)) <= 0) {
888 
889 		if (n < 0)
890 			rfbLog("File [%s]: Method [%s]: Error while reading FileUploadFailedMsg\n",
891 					__FILE__, __FUNCTION__);
892 
893 	    rfbCloseClient(cl);
894 	    return;
895 	}
896 
897 	msg.fuf.reasonLen = Swap16IfLE(msg.fuf.reasonLen);
898 	if(msg.fuf.reasonLen  == 0) {
899 		rfbLog("File [%s]: Method [%s]: reason length received is Zero\n",
900 				__FILE__, __FUNCTION__);
901 		return;
902 	}
903 
904 
905 	reason = (char*) calloc(msg.fuf.reasonLen + 1, sizeof(char));
906 	if(reason == NULL) {
907 		rfbLog("File [%s]: Method [%s]: Memory alloc failed\n", __FILE__, __FUNCTION__);
908 		return;
909 	}
910 
911 	if((n = rfbReadExact(cl, reason, msg.fuf.reasonLen)) <= 0) {
912 
913 		if (n < 0)
914 			rfbLog("File [%s]: Method [%s]: Error while reading FileUploadFailedMsg\n",
915 					__FILE__, __FUNCTION__);
916 
917 	    rfbCloseClient(cl);
918 
919 		if(reason != NULL) {
920 			free(reason);
921 			reason = NULL;
922 		}
923 
924 	    return;
925 	}
926 
927 	rfbLog("File [%s]: Method [%s]: File Upload Failed Request received:"
928 				" reason <%s>\n", __FILE__, __FUNCTION__, reason);
929 
930 	CloseUndoneFileTransfer(cl, rtcp);
931 
932 	if(reason != NULL) {
933 		free(reason);
934 		reason = NULL;
935 	}
936 
937 }
938 
939 
940 /******************************************************************************
941  * Methods to Handle File Create Request.
942  ******************************************************************************/
943 
944 
945 void
HandleFileCreateDirRequest(rfbClientPtr cl,rfbTightClientPtr rtcp)946 HandleFileCreateDirRequest(rfbClientPtr cl, rfbTightClientPtr rtcp)
947 {
948 	int n = 0;
949 	char dirName[PATH_MAX];
950 	rfbClientToServerTightMsg msg;
951 
952 	memset(dirName, 0, PATH_MAX);
953 	memset(&msg, 0, sizeof(rfbClientToServerTightMsg));
954 
955 	if(cl == NULL) {
956 		rfbLog("File [%s]: Method [%s]: Unexpected error: rfbClientPtr is null\n",
957 				__FILE__, __FUNCTION__);
958 		return;
959 	}
960 
961 	if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileCreateDirRequestMsg-1)) <= 0) {
962 
963 		if (n < 0)
964 			rfbLog("File [%s]: Method [%s]: Error while reading FileCreateDirRequestMsg\n",
965 					__FILE__, __FUNCTION__);
966 
967 	    rfbCloseClient(cl);
968 	    return;
969 	}
970 
971 	msg.fcdr.dNameLen = Swap16IfLE(msg.fcdr.dNameLen);
972 
973 	/* TODO :: chk if the dNameLen is greater than PATH_MAX */
974 
975 	if((n = rfbReadExact(cl, dirName, msg.fcdr.dNameLen)) <= 0) {
976 
977 		if (n < 0)
978 			rfbLog("File [%s]: Method [%s]: Error while reading FileUploadFailedMsg\n",
979 					__FILE__, __FUNCTION__);
980 
981 	    rfbCloseClient(cl);
982 	    return;
983 	}
984 
985 	if(ConvertPath(dirName) == NULL) {
986     	rfbLog("File [%s]: Method [%s]: Unexpected error: path is NULL\n",
987     			__FILE__, __FUNCTION__);
988 
989     	return;
990 	}
991 
992 	CreateDirectory(dirName);
993 }
994