Line data Source code
1 : #include "burp.h"
2 : #include "base64.h"
3 : #include "cmd.h"
4 : #include "conf.h"
5 : #include "conffile.h"
6 : #include "client/main.h"
7 : #include "handy.h"
8 : #include "hexmap.h"
9 : #include "lock.h"
10 : #include "log.h"
11 : #include "strlist.h"
12 : #include "server/main.h"
13 : #include "server/protocol1/bedup.h"
14 : #include "server/protocol2/bsigs.h"
15 : #include "server/protocol2/bsparse.h"
16 : #include "server/protocol2/champ_chooser/champ_server.h"
17 :
18 0 : static void usage_server(void)
19 : {
20 : #ifndef HAVE_WIN32
21 0 : printf("\nThe configuration file specifies whether %s runs in server or client mode.\n", PACKAGE_TARNAME);
22 0 : printf("\nServer usage: %s [options]\n", progname());
23 0 : printf("\n");
24 0 : printf(" Options:\n");
25 0 : printf(" -a c Run as a stand-alone champion chooser.\n");
26 0 : printf(" -c <path> Path to conf file (default: %s).\n", config_default_path());
27 0 : printf(" -d <path> a single client in the status monitor.\n");
28 0 : printf(" -o <option> Override a given configuration option\n");
29 0 : printf(" (you can use this flag several times).\n");
30 0 : printf(" -F Stay in the foreground.\n");
31 0 : printf(" -g Generate initial CA certificates and exit.\n");
32 0 : printf(" -h|-? Print this text and exit.\n");
33 0 : printf(" -i Print index of symbols and exit.\n");
34 0 : printf(" -n Do not fork any children (implies '-F').\n");
35 0 : printf(" -Q Do not log to stdout\n");
36 0 : printf(" -t Dry-run to test config file syntax.\n");
37 0 : printf(" -v Log to stdout.\n");
38 0 : printf(" -V Print version and exit.\n");
39 0 : printf("Options to use with '-a c':\n");
40 0 : printf(" -C <client> Run as if forked via a connection from this client.\n");
41 0 : printf("\n");
42 : #endif
43 0 : }
44 :
45 0 : static void usage_client(void)
46 : {
47 0 : printf("\nClient usage: %s [options]\n", progname());
48 0 : printf("\n");
49 0 : printf(" Options:\n");
50 0 : printf(" -a <action> The action can be one of the following.\n");
51 0 : printf(" b: backup\n");
52 0 : printf(" delete: delete\n");
53 0 : printf(" d: diff\n");
54 0 : printf(" e: estimate\n");
55 0 : printf(" l: list (this is the default when an action is not given)\n");
56 0 : printf(" L: long list\n");
57 0 : printf(" m: monitor interface\n");
58 0 : printf(" p: parseable list\n");
59 0 : printf(" r: restore\n");
60 0 : printf(" R: Restore (matching ordered paths on stdin)\n");
61 : #ifndef HAVE_WIN32
62 0 : printf(" s: status monitor (ncurses)\n");
63 0 : printf(" S: status monitor snapshot\n");
64 : #endif
65 0 : printf(" t: timed backup\n");
66 0 : printf(" T: check backup timer, but do not actually backup\n");
67 0 : printf(" v: verify\n");
68 0 : printf(" V: Verify (matching ordered paths on stdin)\n");
69 0 : printf(" -b <number> Backup number (default: the most recent backup).\n");
70 0 : printf(" -c <path> Path to conf file (default: %s).\n", config_default_path());
71 0 : printf(" -d <directory> Directory to restore to, or directory to list.\n");
72 0 : printf(" -o <option> Override a given configuration option (you can use this flag several times).\n");
73 0 : printf(" -f Allow overwrite during restore.\n");
74 0 : printf(" -h|-? Print this text and exit.\n");
75 0 : printf(" -i Print index of symbols and exit.\n");
76 0 : printf(" -q <max secs> Randomised delay of starting a timed backup.\n");
77 0 : printf(" -Q Do not log to stdout\n");
78 0 : printf(" -r|-R <regex> Specify a regular expression (case sensitive or insensitive.\n");
79 0 : printf(" -s <number> Number of leading path components to strip during restore.\n");
80 0 : printf(" -t Dry-run to test config file syntax.\n");
81 0 : printf(" -V Print version and exit.\n");
82 0 : printf(" -v Log to stdout.\n");
83 : #ifdef HAVE_WIN32
84 : printf(" -X Do not use the Windows VSS API when restoring.\n");
85 : printf(" -x Do not use the Windows VSS API when restoring,\n");
86 : printf(" and strip out VSS data.\n");
87 : #else
88 0 : printf(" -x Strip Windows VSS data when restoring.\n");
89 0 : printf("Options to use with '-a S':\n");
90 0 : printf(" -C <client> Show a particular client.\n");
91 0 : printf(" -b <number> Show listable files in a particular backup (requires -C).\n");
92 0 : printf(" -d <path> Show a particular path in a backup (requires -C and -b).\n");
93 0 : printf(" -l <path> Log file for the status monitor.\n");
94 0 : printf(" -z <file> Dump a particular log file in a backup (requires -C and -b).\n");
95 : #endif
96 0 : printf("\n");
97 : #ifndef HAVE_WIN32
98 0 : printf(" See ");
99 : // Older versions of autoconf do not pick up PACKAGE_URL.
100 : #ifdef PACKAGE_URL
101 0 : printf("%s or ", PACKAGE_URL);
102 : #endif
103 0 : printf( "the man page ('man %s') for usage examples\n",
104 : PACKAGE_TARNAME);
105 0 : printf(" and additional configuration options.\n\n");
106 : #else
107 : printf(" See %s for usage examples and additional configuration\n",
108 : PACKAGE_TARNAME);
109 : printf(" options.\n\n");
110 : #endif
111 0 : }
112 :
113 0 : int reload(struct conf **confs, const char *conffile, bool firsttime)
114 : {
115 0 : if(!firsttime) logp("Reloading config\n");
116 :
117 0 : if(confs_init(confs)) return -1;
118 :
119 0 : if(conf_load_global_only(conffile, confs)) return -1;
120 :
121 0 : umask(get_mode_t(confs[OPT_UMASK]));
122 :
123 : // This will turn on syslogging which could not be turned on before
124 : // conf_load.
125 0 : log_fzp_set(NULL, confs);
126 :
127 : #ifndef HAVE_WIN32
128 0 : if(get_e_burp_mode(confs[OPT_BURP_MODE])==BURP_MODE_SERVER)
129 0 : setup_signals();
130 : #endif
131 :
132 : return 0;
133 : }
134 :
135 : static int replace_conf_str(struct conf *conf, const char *newval)
136 : {
137 0 : if(!newval) return 0;
138 0 : return set_string(conf, newval);
139 : }
140 :
141 : static void usage(void)
142 : {
143 0 : usage_server();
144 0 : usage_client();
145 : }
146 :
147 0 : static int parse_action(enum action *act, const char *optarg,
148 : struct strlist **cli_overrides)
149 : {
150 0 : if(!strncmp(optarg, "backup", 1))
151 0 : *act=ACTION_BACKUP;
152 0 : else if(!strncmp(optarg, "timedbackup", 1))
153 0 : *act=ACTION_BACKUP_TIMED;
154 0 : else if(!strncmp(optarg, "Timercheck", 1))
155 0 : *act=ACTION_TIMER_CHECK;
156 0 : else if(!strncmp(optarg, "restore", 1))
157 0 : *act=ACTION_RESTORE;
158 0 : else if(!strncmp(optarg, "Restore", 1))
159 : {
160 0 : *act=ACTION_RESTORE;
161 0 : strlist_add(cli_overrides, "restore_list=/dev/stdin", 0);
162 : }
163 0 : else if(!strncmp(optarg, "verify", 1))
164 0 : *act=ACTION_VERIFY;
165 0 : else if(!strncmp(optarg, "Verify", 1))
166 : {
167 0 : *act=ACTION_VERIFY;
168 0 : strlist_add(cli_overrides, "restore_list=/dev/stdin", 0);
169 : }
170 0 : else if(!strncmp(optarg, "list", 1))
171 0 : *act=ACTION_LIST;
172 0 : else if(!strncmp(optarg, "List", 1))
173 0 : *act=ACTION_LIST_LONG;
174 0 : else if(!strncmp(optarg, "parseablelist", 1))
175 0 : *act=ACTION_LIST_PARSEABLE;
176 0 : else if(!strncmp(optarg, "status", 1))
177 0 : *act=ACTION_STATUS;
178 0 : else if(!strncmp(optarg, "Status", 1))
179 0 : *act=ACTION_STATUS_SNAPSHOT;
180 0 : else if(!strncmp(optarg, "estimate", 1))
181 0 : *act=ACTION_ESTIMATE;
182 : // Make them spell 'delete' out fully so that it is less likely to be
183 : // used accidently.
184 0 : else if(!strncmp_w(optarg, "delete"))
185 0 : *act=ACTION_DELETE;
186 0 : else if(!strncmp(optarg, "champchooser", 1))
187 0 : *act=ACTION_CHAMP_CHOOSER;
188 0 : else if(!strncmp(optarg, "diff", 1))
189 0 : *act=ACTION_DIFF;
190 0 : else if(!strncmp(optarg, "Diff", 1))
191 0 : *act=ACTION_DIFF_LONG;
192 0 : else if(!strncmp(optarg, "monitor", 1))
193 0 : *act=ACTION_MONITOR;
194 : else
195 : {
196 : usage();
197 0 : return -1;
198 : }
199 : return 0;
200 : }
201 :
202 : #ifndef HAVE_WIN32
203 0 : static int run_champ_chooser(struct conf **confs)
204 : {
205 0 : const char *orig_client=get_string(confs[OPT_ORIG_CLIENT]);
206 0 : if(orig_client && *orig_client)
207 0 : return champ_chooser_server_standalone(confs);
208 0 : logp("No client name given for standalone champion chooser process.\n");
209 0 : logp("Try using the '-C' option.\n");
210 0 : return 1;
211 : }
212 :
213 0 : static int server_modes(enum action act,
214 : const char *conffile, struct lock *lock, int generate_ca_only,
215 : struct conf **confs)
216 : {
217 0 : switch(act)
218 : {
219 : case ACTION_CHAMP_CHOOSER:
220 : // We are running on the server machine, wanting to
221 : // be a standalone champion chooser process.
222 0 : return run_champ_chooser(confs);
223 : default:
224 0 : return server(confs, conffile, lock, generate_ca_only);
225 : }
226 : }
227 : #endif
228 :
229 0 : static void random_delay(struct conf **confs)
230 : {
231 : int delay;
232 0 : int randomise=get_int(confs[OPT_RANDOMISE]);
233 0 : if(!randomise) return;
234 0 : srand(getpid());
235 0 : delay=rand()%randomise;
236 0 : logp("Sleeping %d seconds\n", delay);
237 0 : sleep(delay);
238 : }
239 :
240 0 : static int run_test_confs(struct conf **confs, const char *client)
241 : {
242 0 : int ret=-1;
243 0 : struct conf **cconfs=NULL;
244 0 : if(!client)
245 : {
246 0 : confs_dump(confs, 0);
247 0 : ret=0;
248 0 : goto end;
249 : }
250 0 : if(!(cconfs=confs_alloc()))
251 : goto end;
252 0 : confs_init(cconfs);
253 0 : if(set_string(cconfs[OPT_CNAME], client)
254 0 : || set_string(cconfs[OPT_PEER_VERSION], PACKAGE_VERSION)
255 0 : || conf_load_clientconfdir(confs, cconfs))
256 : goto end;
257 0 : confs_dump(cconfs, CONF_FLAG_CC_OVERRIDE|CONF_FLAG_INCEXC);
258 :
259 : end:
260 0 : confs_free(&cconfs);
261 0 : return ret;
262 : }
263 :
264 0 : static struct lock *get_prog_lock(struct conf **confs)
265 : {
266 0 : struct lock *lock=NULL;
267 0 : const char *lockfile=confs_get_lockfile(confs);
268 0 : if(!(lock=lock_alloc_and_init(lockfile)))
269 : goto error;
270 0 : lock_get(lock);
271 0 : switch(lock->status)
272 : {
273 : case GET_LOCK_GOT:
274 : return lock;
275 : case GET_LOCK_NOT_GOT:
276 0 : logp("Could not get lockfile.\n");
277 0 : logp("Another process is probably running.\n");
278 0 : goto error;
279 : case GET_LOCK_ERROR:
280 : default:
281 0 : logp("Could not get lockfile.\n");
282 0 : logp("Maybe you do not have permissions to write to %s.\n", lockfile);
283 0 : goto error;
284 : }
285 : error:
286 0 : lock_free(&lock);
287 0 : return NULL;
288 : }
289 :
290 : #ifdef HAVE_WIN32
291 : #define main RealMain
292 : #endif
293 : #ifndef UTEST
294 : static
295 : #endif
296 0 : int real_main(int argc, char *argv[])
297 : {
298 0 : int ret=1;
299 0 : int option=0;
300 0 : int daemon=1;
301 0 : int forking=1;
302 0 : int strip=0;
303 0 : int randomise=0;
304 0 : struct lock *lock=NULL;
305 0 : struct conf **confs=NULL;
306 0 : int forceoverwrite=0;
307 0 : enum action act=ACTION_LIST;
308 0 : const char *backup=NULL;
309 0 : const char *backup2=NULL;
310 0 : char *restoreprefix=NULL;
311 0 : char *stripfrompath=NULL;
312 0 : const char *regex=NULL;
313 0 : const char *browsefile=NULL;
314 0 : char *browsedir=NULL;
315 0 : const char *conffile=config_default_path();
316 0 : const char *orig_client=NULL;
317 0 : const char *logfile=NULL;
318 : // The orig_client is the original client that the normal client
319 : // would like to restore from.
320 : #ifndef HAVE_WIN32
321 0 : int generate_ca_only=0;
322 : #endif
323 0 : enum vss_restore vss_restore=VSS_RESTORE_ON;
324 0 : int test_confs=0;
325 : enum burp_mode mode;
326 0 : struct strlist *cli_overrides=NULL;
327 0 : int keep_readall_caps=0;
328 0 : int regex_case_insensitive=0;
329 :
330 0 : log_init(argv[0]);
331 : #ifndef HAVE_WIN32
332 0 : if(!strcmp(prog, "bedup"))
333 0 : return run_bedup(argc, argv);
334 0 : if(!strcmp(prog, "bsigs"))
335 0 : return run_bsigs(argc, argv);
336 0 : if(!strcmp(prog, "bsparse"))
337 0 : return run_bsparse(argc, argv);
338 : #endif
339 :
340 0 : while((option=getopt(argc, argv, "a:b:C:c:d:o:Ffghijl:nQq:R:r:s:tVvXxz:?"))!=-1)
341 : {
342 0 : switch(option)
343 : {
344 : case 'a':
345 0 : if(parse_action(&act, optarg,
346 : &cli_overrides)) goto end;
347 : break;
348 : case 'b':
349 : // The diff command may have two backups
350 : // specified.
351 0 : if(!backup2 && backup) backup2=optarg;
352 0 : if(!backup) backup=optarg;
353 : break;
354 : case 'C':
355 0 : orig_client=optarg;
356 0 : break;
357 : case 'c':
358 0 : conffile=optarg;
359 0 : break;
360 : case 'd':
361 0 : restoreprefix=optarg; // for restores
362 0 : browsedir=optarg; // for lists
363 0 : break;
364 : case 'F':
365 : daemon=0;
366 : break;
367 : case 'f':
368 0 : forceoverwrite=1;
369 0 : break;
370 : case 'g':
371 : #ifndef HAVE_WIN32
372 0 : generate_ca_only=1;
373 : #endif
374 0 : break;
375 : case 'i':
376 0 : cmd_print_all();
377 0 : ret=0;
378 0 : goto end;
379 : case 'l':
380 0 : logfile=optarg;
381 0 : break;
382 : case 'n':
383 0 : forking=0;
384 0 : break;
385 : case 'o':
386 0 : strlist_add(&cli_overrides, optarg, 0);
387 0 : break;
388 : case 'Q':
389 0 : strlist_add(&cli_overrides, "progress_counter=0", 0);
390 0 : strlist_add(&cli_overrides, "stdout=0", 0);
391 0 : break;
392 : case 'q':
393 0 : randomise=atoi(optarg);
394 0 : break;
395 : case 'R':
396 0 : regex_case_insensitive=1;
397 0 : regex=optarg;
398 0 : break;
399 : case 'r':
400 0 : regex_case_insensitive=0;
401 0 : regex=optarg;
402 0 : break;
403 : case 's':
404 0 : strip=atoi(optarg);
405 0 : break;
406 : case 'V':
407 0 : printf("%s-%s\n", progname(), PACKAGE_VERSION);
408 0 : ret=0;
409 0 : goto end;
410 : case 'v':
411 0 : strlist_add(&cli_overrides, "stdout=1", 0);
412 0 : break;
413 : case 'X':
414 0 : vss_restore=VSS_RESTORE_OFF;
415 0 : break;
416 : case 'x':
417 0 : vss_restore=VSS_RESTORE_OFF_STRIP;
418 0 : break;
419 : case 't':
420 0 : test_confs=1;
421 0 : break;
422 : case 'z':
423 0 : browsefile=optarg;
424 0 : break;
425 : case 'h':
426 : case '?':
427 : default:
428 : usage();
429 : goto end;
430 : }
431 : }
432 0 : if(optind<argc)
433 : {
434 : usage();
435 : goto end;
436 : }
437 :
438 0 : if(act==ACTION_MONITOR)
439 : {
440 : // Try to output everything in JSON.
441 0 : log_set_json(1);
442 : // Need to do this so that processes reading stdout get the
443 : // result of the printfs of logp straight away.
444 0 : setvbuf(stdout, NULL, _IONBF, 0);
445 : }
446 :
447 0 : if(act==ACTION_LIST_PARSEABLE)
448 0 : strlist_add(&cli_overrides, "stdout=0", 0);
449 :
450 0 : conf_set_cli_overrides(cli_overrides);
451 0 : if(!(confs=confs_alloc()))
452 : goto end;
453 :
454 0 : if(reload(confs, conffile, 1))
455 : goto end;
456 :
457 : // Dry run to test config file syntax.
458 0 : if(test_confs)
459 : {
460 0 : ret=run_test_confs(confs, orig_client);
461 0 : goto end;
462 : }
463 :
464 0 : if(!backup) switch(act)
465 : {
466 : case ACTION_DELETE:
467 0 : logp("No backup specified for deletion.\n");
468 0 : goto end;
469 : case ACTION_RESTORE:
470 : case ACTION_VERIFY:
471 : case ACTION_DIFF:
472 : case ACTION_DIFF_LONG:
473 0 : logp("No backup specified. Using the most recent.\n");
474 0 : backup="0";
475 : default:
476 : break;
477 : }
478 0 : if(!backup2) switch(act)
479 : {
480 : case ACTION_DIFF:
481 : case ACTION_DIFF_LONG:
482 0 : logp("No second backup specified. Using file system scan.\n");
483 0 : backup2="n"; // For 'next'.
484 : default:
485 : break;
486 : }
487 :
488 : // The logfile option is only used for the status client stuff.
489 0 : if(logfile
490 0 : && (act!=ACTION_STATUS
491 0 : && act!=ACTION_STATUS_SNAPSHOT))
492 0 : logp("-l <logfile> option obsoleted\n");
493 :
494 0 : if(orig_client
495 0 : && *orig_client
496 0 : && set_string(confs[OPT_ORIG_CLIENT], orig_client))
497 : goto end;
498 :
499 : // The random delay needs to happen before the lock is got, otherwise
500 : // you would never be able to use burp by hand.
501 0 : if(randomise) set_int(confs[OPT_RANDOMISE], randomise);
502 0 : mode=get_e_burp_mode(confs[OPT_BURP_MODE]);
503 0 : if(mode==BURP_MODE_CLIENT
504 0 : && (act==ACTION_BACKUP_TIMED || act==ACTION_TIMER_CHECK))
505 0 : random_delay(confs);
506 :
507 0 : if(mode==BURP_MODE_SERVER)
508 : {
509 0 : switch(act)
510 : {
511 : case ACTION_CHAMP_CHOOSER:
512 : // Need to run without getting the lock.
513 : break;
514 : default:
515 0 : if(!(lock=get_prog_lock(confs)))
516 : goto end;
517 : break;
518 : }
519 : }
520 0 : else if(mode==BURP_MODE_CLIENT)
521 : {
522 0 : set_int(confs[OPT_VSS_RESTORE], vss_restore);
523 0 : switch(act)
524 : {
525 : case ACTION_BACKUP:
526 : case ACTION_BACKUP_TIMED:
527 : case ACTION_TIMER_CHECK:
528 : #ifdef ENABLE_KEEP_READALL_CAPS_SUPPORT
529 : keep_readall_caps=get_int(confs[OPT_READALL]);
530 : // readall=1 cannot work with atime=0 (O_NOATIME)
531 : if (keep_readall_caps)
532 : set_int(confs[OPT_ATIME], 1);
533 : #endif
534 : // Need to get the lock.
535 0 : if(!(lock=get_prog_lock(confs)))
536 : goto end;
537 : break;
538 : default:
539 : break;
540 : }
541 : }
542 :
543 : // Change privileges after having got the lock, for convenience.
544 0 : if(chuser_and_or_chgrp(
545 0 : get_string(confs[OPT_USER]), get_string(confs[OPT_GROUP]),
546 : keep_readall_caps))
547 : return -1;
548 :
549 0 : set_int(confs[OPT_OVERWRITE], forceoverwrite);
550 0 : set_int(confs[OPT_STRIP], strip);
551 0 : set_int(confs[OPT_FORK], forking);
552 0 : set_int(confs[OPT_DAEMON], daemon);
553 0 : set_int(confs[OPT_REGEX_CASE_INSENSITIVE], regex_case_insensitive);
554 :
555 0 : strip_trailing_slashes(&restoreprefix);
556 0 : strip_trailing_slashes(&browsedir);
557 0 : if(replace_conf_str(confs[OPT_BACKUP], backup)
558 0 : || replace_conf_str(confs[OPT_BACKUP2], backup2)
559 0 : || replace_conf_str(confs[OPT_RESTOREPREFIX], restoreprefix)
560 0 : || replace_conf_str(confs[OPT_STRIP_FROM_PATH], stripfrompath)
561 0 : || replace_conf_str(confs[OPT_REGEX], regex)
562 0 : || replace_conf_str(confs[OPT_BROWSEFILE], browsefile)
563 0 : || replace_conf_str(confs[OPT_BROWSEDIR], browsedir)
564 0 : || replace_conf_str(confs[OPT_MONITOR_LOGFILE], logfile))
565 : goto end;
566 :
567 0 : base64_init();
568 0 : hexmap_init();
569 :
570 0 : if(mode==BURP_MODE_SERVER)
571 : {
572 : #ifdef HAVE_WIN32
573 : logp("Sorry, server mode is not implemented for Windows.\n");
574 : #else
575 0 : ret=server_modes(act,
576 : conffile, lock, generate_ca_only, confs);
577 : #endif
578 : }
579 : else
580 : {
581 0 : ret=client(confs, act);
582 : }
583 :
584 : end:
585 0 : lock_release(lock);
586 0 : lock_free(&lock);
587 0 : confs_free(&confs);
588 0 : strlists_free(&cli_overrides);
589 0 : return ret;
590 : }
591 :
592 : #ifndef UTEST
593 : int main(int argc, char *argv[])
594 : {
595 : return real_main(argc, argv);
596 : }
597 : #endif
|