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