1 #include "../burp.h"
2 #include "../alloc.h"
3 #include "../asfd.h"
4 #include "../async.h"
5 #include "../attribs.h"
6 #include "../berrno.h"
7 #include "../cmd.h"
8 #include "../cntr.h"
9 #include "../fsops.h"
10 #include "../handy.h"
11 #include "../pathcmp.h"
12 #include "../log.h"
13 #include "../prepend.h"
14 #include "../protocol2/blk.h"
15 #include "cvss.h"
16 #include "protocol1/restore.h"
17 #include "protocol2/restore.h"
18 #include "restore.h"
19 
restore_interrupt(struct asfd * asfd,struct sbuf * sb,const char * msg,struct cntr * cntr,enum protocol protocol)20 int restore_interrupt(struct asfd *asfd,
21 	struct sbuf *sb, const char *msg, struct cntr *cntr,
22 	enum protocol protocol)
23 {
24 	int ret=-1;
25 	char *path=NULL;
26 	struct iobuf *rbuf=asfd->rbuf;
27 
28 	if(cntr)
29 	{
30 		cntr_add(cntr, CMD_WARNING, 1);
31 		logp("WARNING: %s\n", msg);
32 		if(asfd->write_str(asfd, CMD_WARNING, msg))
33 			goto end;
34 	}
35 
36 	if(!iobuf_is_filedata(&sb->path)
37 	  && !iobuf_is_vssdata(&sb->path))
38 	{
39 		// Do not need to do anything.
40 		ret=0;
41 		goto end;
42 	}
43 
44 	// If it is file data, get the server
45 	// to interrupt the flow and move on.
46 
47 	if(protocol==PROTO_1)
48 		path=sb->protocol1->datapth.buf;
49 	else if(protocol==PROTO_2)
50 		path=sb->path.buf;
51 
52 	if(!path)
53 	{
54 		ret=0;
55 		goto end;
56 	}
57 
58 	if(asfd->write_str(asfd, CMD_INTERRUPT, path))
59 		goto end;
60 
61 	// Read to the end file marker.
62 	while(1)
63 	{
64 		iobuf_free_content(rbuf);
65 		if(asfd->read(asfd))
66 			goto end; // Error.
67 		if(!rbuf->len)
68 			continue;
69 
70 		switch(rbuf->cmd)
71 		{
72 			case CMD_APPEND:
73 			case CMD_DATA:
74 				continue;
75 			case CMD_END_FILE:
76 				ret=0;
77 				goto end;
78 			default:
79 				iobuf_log_unexpected(rbuf, __func__);
80 				goto end;
81 		}
82 	}
83 end:
84 	iobuf_free_content(rbuf);
85 	return ret;
86 }
87 
make_link(struct asfd * asfd,struct cntr * cntr,const char * fname,const char * lnk,enum cmd cmd,const char * restore_desired_dir)88 static int make_link(
89 #ifdef HAVE_WIN32
90 	struct asfd *asfd,
91 	struct cntr *cntr,
92 #endif
93 	const char *fname, const char *lnk,
94 	enum cmd cmd, const char *restore_desired_dir)
95 {
96 	int ret=-1;
97 
98 #ifdef HAVE_WIN32
99 	logw(asfd, cntr, "windows seems not to support hardlinks or symlinks\n");
100 #else
101 	unlink(fname);
102 	if(cmd==CMD_HARD_LINK)
103 	{
104 		char *flnk=NULL;
105 		if(!(flnk=prepend_s(restore_desired_dir, lnk)))
106 		{
107 			log_out_of_memory(__func__);
108 			return -1;
109 		}
110 		//printf("%s -> %s\n", fname, flnk);
111 		ret=link(flnk, fname);
112 		free_w(&flnk);
113 	}
114 	else if(cmd==CMD_SOFT_LINK)
115 	{
116 		//printf("%s -> %s\n", fname, lnk);
117 		ret=symlink(lnk, fname);
118 	}
119 	else
120 	{
121 		logp("unexpected link command: %c\n", cmd);
122 		ret=-1;
123 	}
124 #endif
125 
126 	if(ret) logp("could not %slink %s -> %s: %s\n",
127 		cmd==CMD_HARD_LINK?"hard":"sym",
128 		fname, lnk, strerror(errno));
129 
130 	return ret;
131 }
132 
133 // FIX THIS: Maybe should be in bfile.c.
open_for_restore(struct asfd * asfd,struct BFILE * bfd,const char * path,struct sbuf * sb,enum vss_restore vss_restore,struct cntr * cntr,enum protocol protocol)134 enum ofr_e open_for_restore(struct asfd *asfd,
135 	struct BFILE *bfd, const char *path,
136 	struct sbuf *sb, enum vss_restore vss_restore, struct cntr *cntr,
137 	enum protocol protocol)
138 {
139 	static int flags;
140         if(bfd->mode!=BF_CLOSED)
141         {
142 #ifdef HAVE_WIN32
143 		if(bfd->path && !strcmp(bfd->path, path))
144 		{
145 			// Already open after restoring the VSS data.
146 			// Time now for the actual file data.
147 			return OFR_OK;
148 		}
149 		else
150 		{
151 #endif
152 			if(bfd->close(bfd, asfd))
153 			{
154 				logp("error closing %s in %s()\n",
155 					path, __func__);
156 				return OFR_ERROR;
157 			}
158 #ifdef HAVE_WIN32
159 		}
160 #endif
161 	}
162 
163 #ifdef HAVE_WIN32
164 	// Some massive hacks to work around times that winattr was not
165 	// getting set correctly inside server side backups.
166 	// The EFS one will stop burp segfaulting when restoring affected
167 	// EFS files.
168 	if(sb->path.cmd==CMD_EFS_FILE)
169 		sb->winattr |= FILE_ATTRIBUTE_ENCRYPTED;
170 	if(S_ISDIR(sb->statp.st_mode))
171 		sb->winattr |= FILE_ATTRIBUTE_DIRECTORY;
172 #endif
173 
174 	bfile_init(bfd, sb->winattr, cntr);
175 	bfd->set_attribs_on_close=1;
176 	switch(vss_restore)
177 	{
178 		case VSS_RESTORE_OFF:
179 #ifdef HAVE_WIN32
180 			bfd->set_win32_api(bfd, 0);
181 #endif
182 			bfd->set_vss_strip(bfd, 0);
183 			break;
184 		case VSS_RESTORE_OFF_STRIP:
185 #ifdef HAVE_WIN32
186 			bfd->set_win32_api(bfd, 0);
187 #endif
188 			bfd->set_vss_strip(bfd, 1);
189 			break;
190 		case VSS_RESTORE_ON:
191 #ifdef HAVE_WIN32
192 			bfd->set_win32_api(bfd, 1);
193 #endif
194 			bfd->set_vss_strip(bfd, 0);
195 			break;
196 	}
197 	flags=O_WRONLY|O_BINARY
198 #ifdef O_NOFOLLOW
199 	|O_NOFOLLOW
200 #endif
201 	;
202 	if(S_ISDIR(sb->statp.st_mode))
203 	{
204 		// Windows directories are treated as having file data.
205 		mkdir(path, 0777);
206 	}
207 	else
208 	{
209 		flags|=O_CREAT|O_TRUNC;
210 
211 		// Unlink first, so that a new file is created instead of
212 		// overwriting an existing file in place. Should be safer in
213 		// cases where the old file was hardlinked everywhere.
214 		if(unlink(path) && errno!=ENOENT)
215 		{
216 			char msg[256]="";
217 			snprintf(msg, sizeof(msg),
218 				"Cannot unlink before restore: '%s': %s",
219 				path, strerror(errno));
220 			if(restore_interrupt(asfd, sb, msg, cntr, protocol))
221 				return OFR_ERROR;
222 			return OFR_CONTINUE;
223 		}
224 	}
225 
226 	if(bfd->open(bfd, asfd, path, flags, S_IRUSR | S_IWUSR))
227 	{
228 		struct berrno be;
229 		berrno_init(&be);
230 		char msg[256]="";
231 		snprintf(msg, sizeof(msg), "Could not open for writing %s: %s",
232 			path, berrno_bstrerror(&be, errno));
233 		if(restore_interrupt(asfd, sb, msg, cntr, protocol))
234 			return OFR_ERROR;
235 		return OFR_CONTINUE;
236 	}
237 	// Add attributes to bfd so that they can be set when it is closed.
238 	bfd->winattr=sb->winattr;
239 	memcpy(&bfd->statp, &sb->statp, sizeof(struct stat));
240 	return OFR_OK;
241 }
242 
build_msg(const char * text,const char * param)243 static char *build_msg(const char *text, const char *param)
244 {
245 	static char msg[256]="";
246 	snprintf(msg, sizeof(msg), text, param);
247 	return msg;
248 }
249 
250 #ifndef HAVE_WIN32
do_logw(struct asfd * asfd,struct cntr * cntr,const char * text,const char * param)251 static void do_logw(struct asfd *asfd, struct cntr *cntr,
252 	const char *text, const char *param)
253 {
254 	logw(asfd, cntr, "%s", build_msg(text, param));
255 }
256 #endif
257 
warn_and_interrupt(struct asfd * asfd,struct sbuf * sb,struct cntr * cntr,enum protocol protocol,const char * text,const char * param)258 static int warn_and_interrupt(struct asfd *asfd, struct sbuf *sb,
259 	struct cntr *cntr, enum protocol protocol,
260 	const char *text, const char *param)
261 {
262 	return restore_interrupt(asfd, sb, build_msg(text, param), cntr,
263 		protocol);
264 }
265 
restore_special(struct asfd * asfd,struct sbuf * sb,const char * fname,enum action act,struct cntr * cntr,enum protocol protocol)266 static int restore_special(struct asfd *asfd, struct sbuf *sb,
267 	const char *fname, enum action act, struct cntr *cntr,
268 	enum protocol protocol)
269 {
270 	int ret=0;
271 	char *rpath=NULL;
272 #ifdef HAVE_WIN32
273 	logw(asfd, cntr, "Cannot restore special files to Windows: %s\n", fname);
274 	goto end;
275 #else
276 	struct stat statp=sb->statp;
277 
278 	if(act==ACTION_VERIFY)
279 	{
280 		cntr_add(cntr, CMD_SPECIAL, 1);
281 		return 0;
282 	}
283 
284 	if(build_path(fname, "", &rpath, NULL))
285 	{
286 		// failed - do a warning
287 		if(restore_interrupt(asfd, sb,
288 			build_msg("build path failed: %s", fname),
289 			cntr, protocol))
290 				ret=-1;
291 		goto end;
292 	}
293 	if(S_ISFIFO(statp.st_mode))
294 	{
295 		if(mkfifo(rpath, statp.st_mode) && errno!=EEXIST)
296 			do_logw(asfd, cntr,
297 				"Cannot make fifo: %s\n", strerror(errno));
298 		else
299 		{
300 			attribs_set(asfd, rpath, &statp, sb->winattr, cntr);
301 			cntr_add(cntr, CMD_SPECIAL, 1);
302 		}
303 	}
304 	else if(S_ISSOCK(statp.st_mode))
305 	{
306 		if(mksock(rpath))
307 			do_logw(asfd, cntr,
308 				"Cannot make socket: %s\n", strerror(errno));
309 		else
310 		{
311 			attribs_set(asfd, rpath, &statp, sb->winattr, cntr);
312 			cntr_add(cntr, CMD_SPECIAL, 1);
313 		}
314 	}
315 #ifdef S_IFDOOR     // Solaris high speed RPC mechanism
316 	else if (S_ISDOOR(statp.st_mode))
317 		do_logw(asfd, cntr,
318 			"Skipping restore of door file: %s\n", fname);
319 #endif
320 #ifdef S_IFPORT     // Solaris event port for handling AIO
321 	else if (S_ISPORT(statp.st_mode))
322 		do_logw(asfd, cntr,
323 			"Skipping restore of event port file: %s\n", fname);
324 #endif
325 	else if(mknod(fname, statp.st_mode, statp.st_rdev) && errno!=EEXIST)
326 		do_logw(asfd, cntr, "Cannot make node: %s\n", strerror(errno));
327 	else
328 	{
329 		attribs_set(asfd, rpath, &statp, sb->winattr, cntr);
330 		cntr_add(cntr, CMD_SPECIAL, 1);
331 	}
332 #endif
333 end:
334 	free_w(&rpath);
335 	return ret;
336 }
337 
restore_dir(struct asfd * asfd,struct sbuf * sb,const char * dname,enum action act,struct cntr * cntr,enum protocol protocol)338 int restore_dir(struct asfd *asfd, struct sbuf *sb,
339 	const char *dname, enum action act, struct cntr *cntr,
340 	enum protocol protocol)
341 {
342 	int ret=0;
343 	char *rpath=NULL;
344 	if(act==ACTION_RESTORE)
345 	{
346 		if(build_path(dname, "", &rpath, NULL))
347 		{
348 			ret=warn_and_interrupt(asfd, sb, cntr, protocol,
349 				"build path failed: %s", dname);
350 			goto end;
351 		}
352 		else if(is_dir_lstat(rpath)<=0)
353 		{
354 			if(mkdir(rpath, 0777))
355 			{
356 				ret=warn_and_interrupt(asfd, sb, cntr, protocol,
357 					"mkdir error: %s", strerror(errno));
358 				goto end;
359 			}
360 		}
361 		attribs_set(asfd, rpath, &(sb->statp), sb->winattr, cntr);
362 		if(!ret) cntr_add(cntr, sb->path.cmd, 1);
363 	}
364 	else cntr_add(cntr, sb->path.cmd, 1);
365 end:
366 	free_w(&rpath);
367 	return ret;
368 }
369 
restore_link(struct asfd * asfd,struct sbuf * sb,const char * fname,enum action act,struct cntr * cntr,enum protocol protocol,const char * restore_desired_dir)370 static int restore_link(struct asfd *asfd, struct sbuf *sb,
371 	const char *fname, enum action act, struct cntr *cntr,
372 	enum protocol protocol, const char *restore_desired_dir)
373 {
374 	int ret=0;
375 
376 	if(act==ACTION_RESTORE)
377 	{
378 		char *rpath=NULL;
379 		if(build_path(fname, "", &rpath, NULL))
380 		{
381 			ret=warn_and_interrupt(asfd, sb, cntr, protocol,
382 				"build path failed: %s", fname);
383 			goto end;
384 		}
385 		else if(make_link(
386 #ifdef HAVE_WIN32
387 			asfd,
388 			cntr,
389 #endif
390 			fname, sb->link.buf,
391 			sb->link.cmd, restore_desired_dir))
392 		{
393 			ret=warn_and_interrupt(asfd, sb, cntr, protocol,
394 				"could not create link", "");
395 			goto end;
396 		}
397 		else if(!ret)
398 		{
399 			attribs_set(asfd, fname,
400 				&(sb->statp), sb->winattr, cntr);
401 			cntr_add(cntr, sb->path.cmd, 1);
402 		}
403 		free_w(&rpath);
404 	}
405 	else cntr_add(cntr, sb->path.cmd, 1);
406 end:
407 	return ret;
408 }
409 
strip_invalid_characters(char ** path)410 static void strip_invalid_characters(char **path)
411 {
412 #ifdef HAVE_WIN32
413       char *ch = *path;
414       if (ch[0] != 0 && ch[1] != 0) {
415          ch += 2;
416          while (*ch) {
417             switch (*ch) {
418             case ':':
419             case '<':
420             case '>':
421             case '*':
422             case '?':
423             case '|':
424                *ch = '_';
425                 break;
426             }
427             ch++;
428          }
429       }
430 #endif
431 }
432 
act_str(enum action act)433 static const char *act_str(enum action act)
434 {
435 	static const char *ret=NULL;
436 	if(act==ACTION_RESTORE) ret="restore";
437 	else ret="verify";
438 	return ret;
439 }
440 
441 #ifndef UTEST
442 static
443 #endif
strip_from_path(char * path,const char * strip)444 void strip_from_path(char *path, const char *strip)
445 {
446 	char *p;
447 	char *src;
448 	size_t len;
449 	if(!path
450 	  || !strip
451 	  || strlen(path)<=strlen(strip)
452 	  || !(p=strstr(path, strip)))
453 		return;
454 
455 	len=strlen(p)-strlen(strip)+1;
456 	src=p+strlen(strip);
457 	memmove(p, src, len);
458 }
459 
460 
461 // Return 1 for ok, -1 for error, 0 for too many components stripped.
strip_path_components(struct asfd * asfd,struct sbuf * sb,int strip,struct cntr * cntr,enum protocol protocol)462 static int strip_path_components(struct asfd *asfd,
463 	struct sbuf *sb, int strip, struct cntr *cntr, enum protocol protocol)
464 {
465 	int s=0;
466 	char *tmp=NULL;
467 	char *cp=sb->path.buf;
468 	char *dp=NULL;
469 	for(s=0; cp && *cp && s<strip; s++)
470 	{
471 		if(!(dp=strchr(cp, '/')))
472 		{
473 			char msg[256]="";
474 			snprintf(msg, sizeof(msg),
475 				"Stripped too many components: %s",
476 				iobuf_to_printable(&sb->path));
477 			if(restore_interrupt(asfd, sb, msg, cntr, protocol))
478 				return -1;
479 			return 0;
480 		}
481 		cp=dp+1;
482 	}
483 	if(!cp)
484 	{
485 		char msg[256]="";
486 		snprintf(msg, sizeof(msg),
487 			"Stripped too many components: %s",
488 			iobuf_to_printable(&sb->path));
489 		if(restore_interrupt(asfd, sb, msg, cntr, protocol))
490 			return -1;
491 		return 0;
492 	}
493 	if(!(tmp=strdup_w(cp, __func__)))
494 		return -1;
495 	free_w(&sb->path.buf);
496 	sb->path.buf=tmp;
497 	return 1;
498 }
499 
overwrite_ok(struct sbuf * sb,int overwrite,struct BFILE * bfd,const char * fullpath)500 static int overwrite_ok(struct sbuf *sb,
501 	int overwrite,
502 #ifdef HAVE_WIN32
503 	struct BFILE *bfd,
504 #endif
505 	const char *fullpath)
506 {
507 	struct stat checkstat;
508 
509 	// User specified overwrite is OK.
510 #ifdef HAVE_WIN32
511 	if(overwrite) return 1;
512 #else
513 	// User specified overwrite is OK,
514 	// UNLESS we are trying to overwrite the file with trailing VSS data.
515 	if(overwrite)
516 		return (sb->path.cmd!=CMD_VSS_T
517 			&& sb->path.cmd!=CMD_ENC_VSS_T);
518 #endif
519 
520 	if(!S_ISDIR(sb->statp.st_mode)
521 	  && sb->path.cmd!=CMD_METADATA
522 	  && sb->path.cmd!=CMD_ENC_METADATA
523 	  && sb->path.cmd!=CMD_VSS
524 	  && sb->path.cmd!=CMD_ENC_VSS)
525 	{
526 #ifdef HAVE_WIN32
527 		// If Windows previously got some VSS data, it needs to append
528 		// the file data to the already open bfd.
529 		// And trailing VSS data.
530 		if(bfd->mode!=BF_CLOSED
531 		  && (sb->path.cmd==CMD_FILE || sb->path.cmd==CMD_ENC_FILE
532 		      || sb->path.cmd==CMD_VSS_T || sb->path.cmd==CMD_ENC_VSS_T)
533 		  && bfd->path && !strcmp(bfd->path, fullpath))
534 			return 1;
535 #endif
536 		// If we have file data and the destination is
537 		// a fifo, it is OK to write to the fifo.
538 		if((sb->path.cmd==CMD_FILE || sb->path.cmd==CMD_ENC_FILE)
539 	  	  && S_ISFIFO(sb->statp.st_mode))
540 			return 1;
541 
542 		// File path exists. Do not overwrite.
543 		if(!lstat(fullpath, &checkstat)) return 0;
544 	}
545 
546 	return 1;
547 }
548 
549 #define RESTORE_STREAM	"restore_stream"
550 // Used to have "restore_spool". Removed for simplicity.
551 
552 static char *restore_style=NULL;
553 
restore_style_func(struct asfd * asfd,struct conf ** confs,void * param)554 static enum asl_ret restore_style_func(struct asfd *asfd,
555 	__attribute__ ((unused)) struct conf **confs,
556 	__attribute__ ((unused)) void *param)
557 {
558 	char msg[32]="";
559 	restore_style=NULL;
560 	if(strcmp(asfd->rbuf->buf, RESTORE_STREAM))
561 	{
562 		iobuf_log_unexpected(asfd->rbuf, __func__);
563 		return ASL_END_ERROR;
564 	}
565 	snprintf(msg, sizeof(msg), "%s_ok", asfd->rbuf->buf);
566 	if(asfd->write_str(asfd, CMD_GEN, msg))
567 		return ASL_END_ERROR;
568 	restore_style=asfd->rbuf->buf;
569 	iobuf_init(asfd->rbuf);
570 	return ASL_END_OK;
571 }
572 
get_restore_style(struct asfd * asfd,struct conf ** confs)573 static char *get_restore_style(struct asfd *asfd, struct conf **confs)
574 {
575 	if(get_protocol(confs)==PROTO_1)
576 		return strdup_w(RESTORE_STREAM, __func__);
577 	if(asfd->simple_loop(asfd, confs, NULL, __func__,
578 		restore_style_func)) return NULL;
579 	return restore_style;
580 }
581 
582 #ifdef HAVE_WIN32
583 #ifndef PATH_MAX
584 	#define PATH_MAX _MAX_PATH
585 #endif
586 #endif
587 
get_restore_desired_dir(const char * restoreprefix,struct asfd * asfd,struct cntr * cntr)588 static char *get_restore_desired_dir(
589 	const char *restoreprefix,
590 	struct asfd *asfd,
591 	struct cntr *cntr
592 ) {
593 	char *ret=NULL;
594 	char *path=NULL;
595 
596 	if(
597 #ifdef HAVE_WIN32
598 		isalpha(*restoreprefix) && *(restoreprefix+1)==':'
599 #else
600 		*restoreprefix=='/'
601 #endif
602 	) {
603 		if(!(path=strdup_w(restoreprefix, __func__)))
604 			return NULL;
605 	}
606 	else
607 	{
608 		static char d[PATH_MAX];
609 		if(!getcwd(d, sizeof(d)))
610 		{
611 			logw(asfd, cntr,
612 				"Could not get current working directory: %s\n",
613 				strerror(errno));
614 			return NULL;
615 		}
616 		if(!(path=prepend_s(d, restoreprefix)))
617 			return NULL;
618 	}
619 
620 	// Canonicalise the path so that we can protect against symlinks that
621 	// point outsired of the desired restore directory.
622 	if((ret=realpath(path, NULL)))
623 		goto end;
624 	if(errno!=ENOENT)
625 		goto realpath_error;
626 	// Try to create the directory if it did not exist, then try again.
627 	mkdir(path, 0777);
628 	if(!(ret=realpath(path, NULL)))
629 		goto realpath_error;
630 
631 end:
632 	free_w(&path);
633 	return ret;
634 
635 realpath_error:
636 	logp("%s: Could not get realpath in %s: %s\n",
637 		path, __func__, strerror(errno));
638 	free_w(&path);
639 	return NULL;
640 }
641 
642 // Seems that windows has no dirname(), so do something similar instead.
strip_trailing_component(char ** path)643 static int strip_trailing_component(char **path)
644 {
645 	char *cp=NULL;
646 
647 	if(**path=='/' && !*((*path)+1))
648 		return -1;
649 	if(!(cp=strrchr(*path, '/')))
650 		return -1;
651 	if(*path==cp)
652 		*(cp+1)='\0'; // Deal with '/somepath' in root, gives '/'.
653 	else
654 		*cp='\0'; // Deal with '/some/path', gives '/some'.
655 	return 0;
656 }
657 
canonicalise(struct asfd * asfd,struct sbuf * sb,struct cntr * cntr,enum protocol protocol,const char * restore_desired_dir,char ** fullpath)658 static int canonicalise(
659 	struct asfd *asfd,
660 	struct sbuf *sb,
661 	struct cntr *cntr,
662 	enum protocol protocol,
663 	const char *restore_desired_dir,
664 	char **fullpath
665 ) {
666 	int ret=-1;
667 	char *tmp=NULL;
668 	char *copy=NULL;
669 	char *canonical=NULL;
670 
671 	if(!(copy=strdup_w(*fullpath, __func__)))
672 		goto end;
673 
674 	// The realpath function does not work on entries that do not exist,
675 	// so we have to do complicated things.
676 	while(1)
677 	{
678 		if(strip_trailing_component(&copy))
679 		{
680 			char msg[512]="";
681 			snprintf(msg, sizeof(msg),
682 				"%s: Could not get dirname of '%s'",
683 				*fullpath, copy);
684 			if(restore_interrupt(asfd, sb, msg, cntr, protocol))
685 				goto end;
686 			ret=1;
687 			goto end;
688 		}
689 		if((canonical=realpath(copy, NULL)))
690 			break;
691 		if(errno!=ENOENT)
692 		{
693 			char msg[512]="";
694 			snprintf(msg, sizeof(msg),
695 				"%s: Could not get realpath of %s in %s: %s",
696 				*fullpath, copy, __func__, strerror(errno));
697 			if(restore_interrupt(asfd, sb, msg, cntr, protocol))
698 				goto end;
699 			ret=1;
700 			goto end;
701 		}
702 	}
703 
704 	// Protect against malicious servers trying to install a symlink and
705 	// then files over the top of it to directories outside of the
706 	// desired directory.
707 	if(!is_subdir(restore_desired_dir, canonical))
708 	{
709 		char msg[512]="";
710 		snprintf(msg, sizeof(msg),
711 			"%s: Is not in a subdir of '%s'",
712 			*fullpath,
713 			restore_desired_dir);
714 		if(restore_interrupt(asfd, sb, msg, cntr, protocol))
715 			goto end;
716 		ret=1;
717 		goto end;
718 	}
719 
720 	// Add the trailing content back onto the canonical path.
721 	if(!(tmp=prepend_s(canonical, (*fullpath)+strlen(copy))))
722 		goto end;
723 	free_w(fullpath);
724 	*fullpath=tmp;
725 
726 	ret=0;
727 end:
728 	// Cannot use free_w() because it was not allocated by alloc.c, and
729 	// I cannot implement realpath() it in alloc.c because I cannot get
730 	// Windows code to use alloc.c.
731 	if(canonical) free(canonical);
732 	free_w(&copy);
733 	return ret;
734 }
735 
do_restore_client(struct asfd * asfd,struct conf ** confs,enum action act)736 int do_restore_client(struct asfd *asfd,
737 	struct conf **confs, enum action act)
738 {
739 	int ret=-1;
740 	char msg[512]="";
741 	struct sbuf *sb=NULL;
742 	struct blk *blk=NULL;
743 	struct BFILE *bfd=NULL;
744 	char *fullpath=NULL;
745 	char *style=NULL;
746 	char *restore_desired_dir=NULL;
747 	struct cntr *cntr=get_cntr(confs);
748 	enum protocol protocol=get_protocol(confs);
749 	int strip=get_int(confs[OPT_STRIP]);
750 	int overwrite=get_int(confs[OPT_OVERWRITE]);
751 	const char *strip_path=get_string(confs[OPT_STRIP_FROM_PATH]);
752 	const char *backup=get_string(confs[OPT_BACKUP]);
753 	const char *regex=get_string(confs[OPT_REGEX]);
754 	const char *encryption_password=
755 		get_string(confs[OPT_ENCRYPTION_PASSWORD]);
756 	enum vss_restore vss_restore=
757 		(enum vss_restore)get_int(confs[OPT_VSS_RESTORE]);
758 	const char *restore_list=get_string(confs[OPT_RESTORE_LIST]);
759 
760 	if(act==ACTION_RESTORE)
761 	{
762 		const char *restore_prefix=get_string(confs[OPT_RESTOREPREFIX]);
763 		if(!restore_prefix)
764 		{
765 			logw(NULL, cntr,
766 				"You must specify a restore directory (-d)!\n");
767 			goto error;
768 		}
769 		if(!strcmp(restore_prefix, "/")) {
770 			// Special case to try to help Windows users that are
771 			// trying to do "bare metal" restores. Let them give
772 			// '/' as the restore prefix, and have it mean that
773 			// everything gets restored back to the original
774 			// locations (this would work on Linux *without* this
775 			// special case anyway, but hey-ho).
776 		}
777 		else if(!(restore_desired_dir=get_restore_desired_dir(
778 			restore_prefix, asfd, cntr)))
779 				goto error;
780 	}
781 
782 	if(!(bfd=bfile_alloc()))
783 		goto error;
784 
785 	bfile_init(bfd, 0, cntr);
786 	bfd->set_attribs_on_close=1;
787 
788 	snprintf(msg, sizeof(msg), "%s%s %s:%s",
789 		act_str(act),
790 		restore_list?" restore_list":"",
791 		backup?backup:"",
792 		regex?regex:"");
793 
794 	logp("Doing %s\n", msg);
795 	if(asfd->write_str(asfd, CMD_GEN, msg))
796 		goto error;
797 	if(restore_list)
798 	{
799 		if(!strcmp(restore_list, "-"))
800 			restore_list="/dev/stdin";
801 		logp("Reading from: '%s'\n", restore_list);
802 		if(asfd_read_expect(asfd, CMD_GEN, "ok restore_list"))
803 			goto error;
804 		if(send_a_file(asfd, restore_list, cntr))
805 			goto error;
806 	}
807 	else
808 	{
809 		if(asfd_read_expect(asfd, CMD_GEN, "ok"))
810 			goto error;
811 	}
812 	logp("Doing %s confirmed\n", act_str(act));
813 	if(act==ACTION_RESTORE)
814 		logp("Directory: '%s'\n",
815 		  restore_desired_dir ? restore_desired_dir : "/");
816 
817 #if defined(HAVE_WIN32)
818 	if(act==ACTION_RESTORE) win32_enable_backup_privileges();
819 #endif
820 
821 	logfmt("\n");
822 
823 	if(cntr_recv(asfd, confs))
824 		goto error;
825 
826 	if(!(style=get_restore_style(asfd, confs)))
827 		goto error;
828 
829 	if(!(sb=sbuf_alloc(protocol))
830 	  || (protocol==PROTO_2 && !(blk=blk_alloc())))
831 	{
832 		log_and_send_oom(asfd);
833 		goto error;
834 	}
835 
836 	while(1)
837 	{
838 		sbuf_free_content(sb);
839 		if(protocol==PROTO_1)
840 			sb->flags |= SBUF_CLIENT_RESTORE_HACK;
841 
842 		switch(sbuf_fill_from_net(sb, asfd, blk, cntr))
843 		{
844 			case 0: break;
845 			case 1: if(asfd->write_str(asfd, CMD_GEN,
846 				"restoreend ok")) goto error;
847 				goto end; // It was OK.
848 			default:
849 			case -1: goto error;
850 		}
851 
852 		if(protocol==PROTO_2)
853 		{
854 			if(blk->data)
855 			{
856 				int wret=0;
857 				if(act==ACTION_VERIFY)
858 					cntr_add(cntr, CMD_DATA, 1);
859 				else
860 					wret=write_protocol2_data(asfd,
861 						bfd, blk, vss_restore);
862 				blk_free_content(blk);
863 				blk->data=NULL;
864 				if(wret) goto error;
865 				continue;
866 			}
867 			else if(sb->endfile.buf)
868 			{
869 				continue;
870 			}
871 		}
872 
873 		switch(sb->path.cmd)
874 		{
875 			case CMD_DIRECTORY:
876 			case CMD_FILE:
877 			case CMD_ENC_FILE:
878 			case CMD_SOFT_LINK:
879 			case CMD_HARD_LINK:
880 			case CMD_SPECIAL:
881 			case CMD_METADATA:
882 			case CMD_ENC_METADATA:
883 			case CMD_VSS:
884 			case CMD_ENC_VSS:
885 			case CMD_VSS_T:
886 			case CMD_ENC_VSS_T:
887 			case CMD_EFS_FILE:
888 				if(strip)
889 				{
890 					int s;
891 					s=strip_path_components(asfd,
892 						sb, strip, cntr, protocol);
893 					if(s<0) goto error;
894 					if(s==0)
895 					{
896 						// Too many components stripped
897 						// - carry on.
898 						continue;
899 					}
900 					// It is OK, sb.path is now stripped.
901 				}
902 				if(strip_path)
903 				{
904 					strip_from_path(sb->path.buf,
905 						strip_path);
906 					// Strip links if their path is absolute
907 					if(sb->link.buf && !is_absolute(sb->link.buf))
908 						strip_from_path(sb->link.buf,
909 							strip_path);
910 				}
911 				free_w(&fullpath);
912 				if(!(fullpath=prepend_s(restore_desired_dir,
913 					sb->path.buf)))
914 				{
915 					log_and_send_oom(asfd);
916 					goto error;
917 				}
918 
919 				if(act==ACTION_RESTORE)
920 				{
921 				  strip_invalid_characters(&fullpath);
922 				  // canonicalise will fail on Windows split_vss
923 				  // restores if we do not make sure bfd is
924 				  // closed first.
925 				  if(bfd
926 					&& bfd->mode!=BF_CLOSED
927 					&& bfd->path
928 					&& strcmp(bfd->path, fullpath))
929 						bfd->close(bfd, asfd);
930 				  if(restore_desired_dir) {
931 					switch(canonicalise(
932 						asfd,
933 						sb,
934 						cntr,
935 						protocol,
936 						restore_desired_dir,
937 						&fullpath
938 					)) {
939 						case 0: break;
940 						case 1: continue;
941 						default: goto error;
942 					}
943 				  }
944 
945 				  if(!overwrite_ok(sb, overwrite,
946 #ifdef HAVE_WIN32
947 					bfd,
948 #endif
949 					fullpath))
950 				  {
951 					char msg[512]="";
952 					// Something exists at that path.
953 					snprintf(msg, sizeof(msg),
954 						"Path exists: %s\n", fullpath);
955 					if(restore_interrupt(asfd,
956 						sb, msg, cntr, protocol))
957 							goto error;
958 					continue;
959 				  }
960 				}
961 				break;
962 			case CMD_MESSAGE:
963 			case CMD_WARNING:
964 				log_recvd(&sb->path, cntr, 1);
965 				logfmt("\n");
966 				continue;
967 			default:
968 				break;
969 		}
970 
971 		switch(sb->path.cmd)
972 		{
973 			// These are the same in both protocol1 and protocol2.
974 			case CMD_DIRECTORY:
975 				if(restore_dir(asfd, sb, fullpath, act, cntr,
976 					protocol))
977 						goto error;
978 				continue;
979 			case CMD_SOFT_LINK:
980 			case CMD_HARD_LINK:
981 				if(restore_link(asfd, sb, fullpath, act, cntr,
982 					protocol, restore_desired_dir))
983 						goto error;
984 				continue;
985 			case CMD_SPECIAL:
986 				if(restore_special(asfd, sb,
987 					fullpath, act, cntr, protocol))
988 						goto error;
989 				continue;
990 			default:
991 				break;
992 		}
993 
994 		if(protocol==PROTO_2)
995 		{
996 			if(restore_switch_protocol2(asfd, sb, fullpath, act,
997 				bfd, vss_restore, cntr))
998 					goto error;
999 		}
1000 		else
1001 		{
1002 			if(restore_switch_protocol1(asfd, sb, fullpath, act,
1003 				bfd, vss_restore, cntr, encryption_password))
1004 					goto error;
1005 		}
1006 	}
1007 
1008 end:
1009 	ret=0;
1010 error:
1011 	// It is possible for a fd to still be open.
1012 	if(bfd)
1013 	{
1014 		bfd->close(bfd, asfd);
1015 		bfile_free(&bfd);
1016 	}
1017 
1018 	cntr_print_end(cntr);
1019 	cntr_set_bytes(cntr, asfd);
1020 	cntr_print(cntr, act);
1021 
1022 	if(!ret) logp("%s finished\n", act_str(act));
1023 	else logp("ret: %d\n", ret);
1024 
1025 	sbuf_free(&sb);
1026 	free_w(&style);
1027 	free_w(&fullpath);
1028 	blk_free(&blk);
1029 
1030 	// Cannot use free_w() because it was not allocated by alloc.c, and
1031 	// I cannot implement realpath() it in alloc.c because I cannot get
1032 	// Windows code to use alloc.c.
1033 	if(restore_desired_dir)
1034 		free(restore_desired_dir);
1035 
1036 	return ret;
1037 }
1038