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