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