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