Line data Source code
1 : #include "../burp.h"
2 : #include "../conffile.h"
3 : #include "../action.h"
4 : #include "../asfd.h"
5 : #include "../async.h"
6 : #include "../cmd.h"
7 : #include "../cntr.h"
8 : #include "../fsops.h"
9 : #include "../handy.h"
10 : #include "../iobuf.h"
11 : #include "../log.h"
12 : #include "../run_script.h"
13 : #include "auth.h"
14 : #include "backup.h"
15 : #include "ca.h"
16 : #include "delete.h"
17 : #include "extra_comms.h"
18 : #include "list.h"
19 : #include "monitor.h"
20 : #include "find_logic.h"
21 : #include "monitor/status_client_ncurses.h"
22 : #include "restore.h"
23 : #include "main.h"
24 :
25 : #ifndef HAVE_WIN32
26 : #include <sys/utsname.h>
27 : #endif
28 :
29 : // These will also be used as the exit codes of the program and are therefore
30 : // unsigned integers.
31 : // Remember to update the man page if you update these.
32 : enum cliret
33 : {
34 : CLIENT_OK=0,
35 : CLIENT_ERROR=1,
36 : CLIENT_RESTORE_WARNINGS=2,
37 : CLIENT_SERVER_TIMER_NOT_MET=3,
38 : CLIENT_COULD_NOT_CONNECT=4,
39 : CLIENT_SERVER_MAX_PARALLEL_BACKUPS=5,
40 : // This one happens after a successful certificate signing request so
41 : // that it connects again straight away with the new key/certificate.
42 : CLIENT_RECONNECT=100
43 : };
44 :
45 : struct tchk
46 : {
47 : int resume;
48 : enum cliret ret;
49 : };
50 :
51 0 : static enum asl_ret maybe_check_timer_func(struct asfd *asfd,
52 : struct conf **confs, void *param)
53 : {
54 0 : int complen=0;
55 0 : struct tchk *tchk=(struct tchk *)param;
56 :
57 0 : if(!strcmp(asfd->rbuf->buf, "max parallel backups"))
58 : {
59 0 : logp("Max parallel backups reached\n");
60 0 : tchk->ret=CLIENT_SERVER_MAX_PARALLEL_BACKUPS;
61 0 : return ASL_END_OK;
62 0 : } else if(!strcmp(asfd->rbuf->buf, "timer conditions not met"))
63 : {
64 0 : logp("Timer conditions on the server were not met\n");
65 0 : tchk->ret=CLIENT_SERVER_TIMER_NOT_MET;
66 0 : return ASL_END_OK;
67 : }
68 0 : else if(!strcmp(asfd->rbuf->buf, "timer conditions met"))
69 : {
70 : // Only happens on 'timer check only'.
71 0 : logp("Timer conditions on the server were met\n");
72 0 : tchk->ret=CLIENT_OK;
73 0 : return ASL_END_OK;
74 : }
75 :
76 0 : if(!strncmp_w(asfd->rbuf->buf, "ok"))
77 : complen=3;
78 0 : else if(!strncmp_w(asfd->rbuf->buf, "resume"))
79 : {
80 0 : complen=7;
81 0 : tchk->resume=1;
82 0 : logp("server wants to resume previous backup.\n");
83 : }
84 : else
85 : {
86 0 : iobuf_log_unexpected(asfd->rbuf, __func__);
87 0 : return ASL_END_ERROR;
88 : }
89 :
90 : // The server now tells us the compression level in the OK response.
91 0 : if(strlen(asfd->rbuf->buf)>3)
92 0 : set_int(confs[OPT_COMPRESSION], atoi(asfd->rbuf->buf+complen));
93 0 : logp("Compression level: %d\n",
94 : get_int(confs[OPT_COMPRESSION]));
95 :
96 0 : return ASL_END_OK;
97 : }
98 :
99 0 : static enum cliret maybe_check_timer(struct asfd *asfd,
100 : const char *phase1str, struct conf **confs, int *resume)
101 : {
102 : struct tchk tchk;
103 0 : memset(&tchk, 0, sizeof(tchk));
104 0 : if(asfd->write_str(asfd, CMD_GEN, phase1str))
105 : return CLIENT_ERROR;
106 :
107 0 : if(asfd->simple_loop(asfd, confs, &tchk,
108 : __func__, maybe_check_timer_func)) return CLIENT_ERROR;
109 0 : *resume=tchk.resume;
110 0 : return tchk.ret;
111 : }
112 :
113 0 : static enum cliret backup_wrapper(struct asfd *asfd,
114 : enum action action, const char *phase1str,
115 : const char *incexc, struct conf **confs)
116 : {
117 0 : int resume=0;
118 0 : enum cliret ret=CLIENT_OK;
119 0 : const char *b_script_pre=get_string(confs[OPT_B_SCRIPT_PRE]);
120 0 : const char *b_script_post=get_string(confs[OPT_B_SCRIPT_POST]);
121 :
122 : // Set bulk packets quality of service flags on backup.
123 0 : if(incexc)
124 : {
125 0 : logp("Server is overriding the configuration\n");
126 0 : logp("with the following settings:\n");
127 0 : if(log_incexcs_buf(incexc)) goto error;
128 : }
129 0 : if(!get_strlist(confs[OPT_STARTDIR]))
130 : {
131 0 : logp("Found no include paths!\n");
132 0 : goto error;
133 : }
134 :
135 0 : switch(maybe_check_timer(asfd, phase1str, confs, &resume))
136 : {
137 : case CLIENT_OK:
138 0 : if(action==ACTION_TIMER_CHECK) goto end;
139 : break;
140 : case CLIENT_SERVER_TIMER_NOT_MET:
141 : goto timer_not_met;
142 : case CLIENT_SERVER_MAX_PARALLEL_BACKUPS:
143 : goto max_parallel_backups;
144 : default:
145 : goto error;
146 : }
147 :
148 0 : if(b_script_pre)
149 : {
150 0 : int a=0;
151 : const char *args[12];
152 0 : args[a++]=b_script_pre;
153 0 : if(get_int(confs[OPT_B_SCRIPT_RESERVED_ARGS]))
154 : {
155 0 : args[a++]="pre";
156 0 : args[a++]="reserved2";
157 0 : args[a++]="reserved3";
158 0 : args[a++]="reserved4";
159 0 : args[a++]="reserved5";
160 : }
161 0 : args[a++]=NULL;
162 0 : if(run_script(asfd,
163 : args, get_strlist(confs[OPT_B_SCRIPT_PRE_ARG]),
164 : confs, 1, 1, 1))
165 0 : ret=CLIENT_ERROR;
166 :
167 0 : if(get_int(confs[OPT_GLOB_AFTER_SCRIPT_PRE]))
168 : {
169 0 : if(reeval_glob(confs))
170 0 : ret=CLIENT_ERROR;
171 : }
172 : }
173 :
174 0 : if(ret==CLIENT_OK && do_backup_client(asfd,
175 0 : confs, action, resume)) ret=CLIENT_ERROR;
176 :
177 0 : if((ret==CLIENT_OK || get_int(confs[OPT_B_SCRIPT_POST_RUN_ON_FAIL]))
178 0 : && b_script_post)
179 : {
180 0 : int a=0;
181 : const char *args[12];
182 0 : args[a++]=b_script_post;
183 0 : if(get_int(confs[OPT_B_SCRIPT_RESERVED_ARGS]))
184 : {
185 0 : args[a++]="post";
186 : // Tell post script whether the restore failed.
187 0 : args[a++]=ret?"1":"0";
188 0 : args[a++]="reserved3";
189 0 : args[a++]="reserved4";
190 0 : args[a++]="reserved5";
191 : }
192 0 : args[a++]=NULL;
193 : // At this point, the server may have closed the connection,
194 : // so cannot log remotely.
195 0 : if(run_script(asfd,
196 : args, get_strlist(confs[OPT_B_SCRIPT_POST_ARG]),
197 : confs, 1, 1, /*log_remote*/ 0))
198 0 : ret=CLIENT_ERROR;
199 : }
200 :
201 0 : if(ret==CLIENT_OK) logp("backup finished ok\n");
202 :
203 : end:
204 : // The include_logic/exclude_logic cache may have been populated
205 : // during backup so we clean it here
206 0 : free_logic_cache();
207 0 : return ret;
208 : error:
209 0 : logp("error in backup\n");
210 0 : return CLIENT_ERROR;
211 : timer_not_met:
212 : return CLIENT_SERVER_TIMER_NOT_MET;
213 : max_parallel_backups:
214 0 : return CLIENT_SERVER_MAX_PARALLEL_BACKUPS;
215 : }
216 :
217 : static int s_server_session_id_context=1;
218 :
219 0 : static int ssl_setup(int *rfd, SSL **ssl, SSL_CTX **ctx,
220 : enum action action, struct conf **confs, const char *server,
221 : struct strlist *failover)
222 : {
223 0 : int ret=-1;
224 0 : int port=0;
225 0 : char portstr[8]="";
226 0 : BIO *sbio=NULL;
227 0 : ssl_load_globals();
228 0 : char *cp=NULL;
229 0 : char *server_copy=NULL;
230 : int ssl_ret;
231 :
232 0 : if(!(server_copy=strdup_w(server, __func__)))
233 : goto end;
234 :
235 0 : if(!(*ctx=ssl_initialise_ctx(confs)))
236 : {
237 0 : logp("error initialising ssl ctx\n");
238 : goto end;
239 : }
240 :
241 0 : if((cp=strrchr(server_copy, ':')))
242 : {
243 0 : *cp='\0';
244 0 : port=atoi(cp+1);
245 : }
246 :
247 0 : SSL_CTX_set_session_id_context(*ctx,
248 : (const uint8_t *)&s_server_session_id_context,
249 : sizeof(s_server_session_id_context));
250 :
251 0 : switch(action)
252 : {
253 : case ACTION_BACKUP:
254 : case ACTION_BACKUP_TIMED:
255 : case ACTION_TIMER_CHECK:
256 0 : if(get_int(confs[OPT_PORT_BACKUP]))
257 0 : port=get_int(confs[OPT_PORT_BACKUP]);
258 : break;
259 : case ACTION_RESTORE:
260 0 : if(get_int(confs[OPT_PORT_RESTORE]))
261 0 : port=get_int(confs[OPT_PORT_RESTORE]);
262 : break;
263 : case ACTION_VERIFY:
264 0 : if(get_int(confs[OPT_PORT_VERIFY]))
265 0 : port=get_int(confs[OPT_PORT_VERIFY]);
266 : break;
267 : case ACTION_LIST:
268 : case ACTION_LIST_LONG:
269 : case ACTION_LIST_PARSEABLE:
270 : case ACTION_DIFF:
271 : case ACTION_DIFF_LONG:
272 0 : if(get_int(confs[OPT_PORT_LIST]))
273 0 : port=get_int(confs[OPT_PORT_LIST]);
274 : break;
275 : case ACTION_DELETE:
276 0 : if(get_int(confs[OPT_PORT_DELETE]))
277 0 : port=get_int(confs[OPT_PORT_DELETE]);
278 : break;
279 : case ACTION_MONITOR:
280 : {
281 : struct strlist *s;
282 0 : if(!(s=get_strlist(confs[OPT_STATUS_PORT])))
283 : {
284 0 : logp("%s not set\n",
285 0 : confs[OPT_STATUS_PORT]->field);
286 : goto end;
287 : }
288 0 : port=atoi(s->path);
289 : break;
290 : }
291 : case ACTION_CHAMP_CHOOSER:
292 : case ACTION_ESTIMATE:
293 : case ACTION_STATUS:
294 : case ACTION_STATUS_SNAPSHOT:
295 : case ACTION_UNSET:
296 0 : logp("Unexpected action in %s: %d\n",
297 : __func__, action);
298 : goto end;
299 : }
300 :
301 0 : snprintf(portstr, sizeof(portstr), "%d", port);
302 0 : if((*rfd=init_client_socket(server_copy, portstr))<0)
303 : goto end;
304 :
305 0 : if(!(*ssl=SSL_new(*ctx))
306 0 : || !(sbio=BIO_new_socket(*rfd, BIO_NOCLOSE)))
307 : {
308 0 : logp_ssl_err("Problem joining SSL to the socket\n");
309 : goto end;
310 : }
311 0 : SSL_set_bio(*ssl, sbio, sbio);
312 0 : if((ssl_ret=SSL_connect(*ssl))<=0)
313 : {
314 0 : logp_ssl_err("SSL connect error: %d\n",
315 : SSL_get_error(*ssl, ssl_ret));
316 : goto end;
317 : }
318 :
319 : ret=0;
320 : end:
321 0 : free_w(&server_copy);
322 0 : return ret;
323 : }
324 :
325 0 : static enum cliret initial_comms(struct async *as,
326 : enum action *action, char **incexc, struct conf **confs,
327 : struct strlist *failover)
328 : {
329 : struct asfd *asfd;
330 0 : char *server_version=NULL;
331 0 : enum cliret ret=CLIENT_OK;
332 0 : asfd=as->asfd;
333 :
334 0 : if(authorise_client(asfd, &server_version,
335 0 : get_string(confs[OPT_CNAME]),
336 0 : get_string(confs[OPT_PASSWORD]),
337 : get_cntr(confs)))
338 : goto error;
339 :
340 0 : if(server_version)
341 : {
342 0 : logp("Server version: %s\n", server_version);
343 : // Servers before 1.3.2 did not tell us their versions.
344 : // 1.3.2 and above can do the automatic CA stuff that
345 : // follows.
346 0 : switch(ca_client_setup(asfd, confs))
347 : {
348 : case 0:
349 : break; // All OK.
350 : case 1:
351 : // Certificate signed successfully.
352 : // Everything is OK, but we will reconnect now,
353 : // in order to use the new keys/certificates.
354 : goto reconnect;
355 : default:
356 0 : logp("Error with cert signing request\n");
357 0 : goto error;
358 : }
359 : }
360 :
361 0 : if(ssl_check_cert(asfd->ssl, NULL, confs))
362 : {
363 0 : logp("check cert failed\n");
364 0 : goto error;
365 : }
366 :
367 0 : if(extra_comms_client(as, confs, action, failover, incexc))
368 : {
369 0 : logp("extra comms failed\n");
370 0 : goto error;
371 : }
372 :
373 : ret=CLIENT_OK; goto end;
374 : error:
375 : ret=CLIENT_ERROR; goto end;
376 : reconnect:
377 : ret=CLIENT_RECONNECT; goto end;
378 : end:
379 0 : free_w(&server_version);
380 0 : return ret;
381 : }
382 :
383 0 : static enum cliret restore_wrapper(struct asfd *asfd, enum action action,
384 : struct conf **confs)
385 : {
386 0 : enum cliret ret=CLIENT_OK;
387 0 : const char *r_script_pre=get_string(confs[OPT_R_SCRIPT_PRE]);
388 0 : const char *r_script_post=get_string(confs[OPT_R_SCRIPT_POST]);
389 :
390 0 : if(r_script_pre)
391 : {
392 0 : int a=0;
393 : const char *args[12];
394 0 : args[a++]=r_script_pre;
395 0 : if(get_int(confs[OPT_R_SCRIPT_RESERVED_ARGS]))
396 : {
397 0 : args[a++]="pre";
398 0 : args[a++]="reserved2";
399 0 : args[a++]="reserved3";
400 0 : args[a++]="reserved4";
401 0 : args[a++]="reserved5";
402 : }
403 0 : args[a++]=NULL;
404 0 : if(run_script(asfd,
405 : args, get_strlist(confs[OPT_R_SCRIPT_PRE_ARG]),
406 : confs, 1, 1, 1))
407 0 : ret=CLIENT_ERROR;
408 : }
409 0 : if(ret==CLIENT_OK)
410 : {
411 0 : if(do_restore_client(asfd, confs,
412 0 : action)) ret=CLIENT_ERROR;
413 : }
414 0 : if((ret==CLIENT_OK || get_int(confs[OPT_R_SCRIPT_POST_RUN_ON_FAIL]))
415 0 : && r_script_post)
416 : {
417 0 : int a=0;
418 : const char *args[12];
419 0 : args[a++]=r_script_post;
420 0 : if(get_int(confs[OPT_R_SCRIPT_RESERVED_ARGS]))
421 : {
422 0 : args[a++]="post";
423 : // Tell post script whether the restore failed.
424 0 : args[a++]=ret?"1":"0";
425 0 : args[a++]="reserved3";
426 0 : args[a++]="reserved4";
427 0 : args[a++]="reserved5";
428 : }
429 0 : args[a++]=NULL;
430 0 : if(run_script(asfd,
431 : args, get_strlist(confs[OPT_R_SCRIPT_POST_ARG]),
432 : confs, 1, 1, /*log_remote*/ 0))
433 0 : ret=CLIENT_ERROR;
434 : }
435 :
436 : // Return non-zero if there were warnings,
437 : // so that the test script can easily check.
438 0 : if(ret==CLIENT_OK && get_cntr(confs)->ent[CMD_WARNING]->count)
439 0 : ret=CLIENT_RESTORE_WARNINGS;
440 :
441 0 : return ret;
442 : }
443 :
444 0 : static enum cliret do_client(struct conf **confs,
445 : enum action action, const char *server,
446 : struct strlist *failover)
447 : {
448 0 : enum cliret ret=CLIENT_OK;
449 0 : int rfd=-1;
450 0 : SSL *ssl=NULL;
451 0 : SSL_CTX *ctx=NULL;
452 0 : struct cntr *cntr=NULL;
453 0 : char *incexc=NULL;
454 0 : enum action act=action;
455 0 : struct async *as=NULL;
456 0 : struct asfd *asfd=NULL;
457 :
458 : // as->settimers(0, 100);
459 :
460 : // logp("begin client\n");
461 : // logp("action %d\n", action);
462 :
463 : // Status monitor forks a child process instead of connecting to
464 : // the server directly.
465 0 : if(action==ACTION_STATUS
466 0 : || action==ACTION_STATUS_SNAPSHOT)
467 : {
468 : #ifdef HAVE_WIN32
469 : logp("Status mode not implemented on Windows.\n");
470 : goto error;
471 : #endif
472 0 : if(status_client_ncurses_init(act)
473 0 : || status_client_ncurses(confs)) ret=CLIENT_ERROR;
474 : goto end;
475 : }
476 :
477 0 : if(!(cntr=cntr_alloc())
478 0 : || cntr_init(cntr, get_string(confs[OPT_CNAME]), getpid()))
479 : goto error;
480 0 : set_cntr(confs[OPT_CNTR], cntr);
481 :
482 0 : if(act!=ACTION_ESTIMATE)
483 : {
484 0 : if(ssl_setup(&rfd,
485 : &ssl, &ctx, action, confs, server, failover))
486 : goto could_not_connect;
487 :
488 0 : if(!(as=async_alloc())
489 0 : || as->init(as, act==ACTION_ESTIMATE)
490 0 : || !(asfd=setup_asfd_ssl(as, "main socket", &rfd, ssl)))
491 : goto end;
492 0 : asfd->set_timeout(asfd, get_int(confs[OPT_NETWORK_TIMEOUT]));
493 0 : asfd->ratelimit=get_float(confs[OPT_RATELIMIT]);
494 :
495 : // Set quality of service bits on backup packets.
496 0 : if(act==ACTION_BACKUP
497 0 : || act==ACTION_BACKUP_TIMED
498 0 : || act==ACTION_TIMER_CHECK)
499 0 : as->asfd->set_bulk_packets(as->asfd);
500 :
501 0 : if((ret=initial_comms(as, &act, &incexc, confs, failover)))
502 : goto end;
503 : }
504 :
505 0 : rfd=-1;
506 0 : switch(act)
507 : {
508 : case ACTION_BACKUP:
509 0 : ret=backup_wrapper(asfd, act, "backupphase1",
510 : incexc, confs);
511 0 : break;
512 : case ACTION_BACKUP_TIMED:
513 0 : ret=backup_wrapper(asfd, act, "backupphase1timed",
514 : incexc, confs);
515 0 : break;
516 : case ACTION_TIMER_CHECK:
517 0 : ret=backup_wrapper(asfd, act, "backupphase1timedcheck",
518 : incexc, confs);
519 0 : break;
520 : case ACTION_RESTORE:
521 : case ACTION_VERIFY:
522 0 : ret=restore_wrapper(asfd, act, confs);
523 0 : break;
524 : case ACTION_ESTIMATE:
525 0 : if(do_backup_client(asfd, confs, act, 0))
526 : goto error;
527 : break;
528 : case ACTION_DELETE:
529 0 : if(do_delete_client(asfd, confs))
530 : goto error;
531 : break;
532 : case ACTION_MONITOR:
533 0 : if(do_monitor_client(asfd))
534 : goto error;
535 : break;
536 : case ACTION_DIFF:
537 : case ACTION_DIFF_LONG:
538 : /*
539 : if(!strcmp(get_string(confs[OPT_BACKUP2]), "n"))
540 : // Do a phase1 scan and diff that.
541 : ret=backup_wrapper(asfd, act,
542 : "backupphase1diff", incexc, confs);
543 : else
544 : */
545 : // Diff two backups that already exist.
546 : // Fall through, the list code is all we need
547 : // for simple diffs on the client side.
548 : case ACTION_LIST:
549 : case ACTION_LIST_LONG:
550 : case ACTION_LIST_PARSEABLE:
551 : default:
552 0 : if(do_list_client(asfd, act, confs)) goto error;
553 : break;
554 : }
555 :
556 0 : if(asfd_flush_asio(asfd))
557 0 : ret=CLIENT_ERROR;
558 :
559 : goto end;
560 : error:
561 : ret=CLIENT_ERROR; goto end;
562 : could_not_connect:
563 : ret=CLIENT_COULD_NOT_CONNECT;
564 : end:
565 0 : close_fd(&rfd);
566 0 : async_free(&as);
567 0 : asfd_free(&asfd);
568 0 : if(ctx) ssl_destroy_ctx(ctx);
569 0 : free_w(&incexc);
570 0 : set_cntr(confs[OPT_CNTR], NULL);
571 0 : cntr_free(&cntr);
572 :
573 : //logp("end client\n");
574 0 : return ret;
575 : }
576 :
577 0 : int client(struct conf **confs,
578 : enum action action)
579 : {
580 0 : int finished=0;
581 0 : enum cliret ret=CLIENT_OK;
582 0 : const char *server=NULL;
583 0 : struct strlist *failover=NULL;
584 :
585 0 : if(!get_int(confs[OPT_ENABLED]))
586 : {
587 0 : logp("Client not enabled\n");
588 0 : return ret;
589 : }
590 :
591 : #ifdef HAVE_WIN32
592 : // prevent sleep when idle
593 : SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED);
594 : #endif
595 0 : server=get_string(confs[OPT_SERVER]);
596 0 : failover=get_strlist(confs[OPT_SERVER_FAILOVER]);
597 :
598 0 : while(!finished)
599 : {
600 0 : ret=do_client(confs,
601 : action, server, failover);
602 0 : if(ret==CLIENT_RECONNECT)
603 : {
604 0 : logp("Re-opening connection to %s\n", server);
605 0 : sleep(5);
606 0 : ret=do_client(confs,
607 : action, server, failover);
608 : }
609 0 : switch(ret)
610 : {
611 : case CLIENT_OK:
612 : case CLIENT_SERVER_TIMER_NOT_MET:
613 : case CLIENT_SERVER_MAX_PARALLEL_BACKUPS:
614 : case CLIENT_RESTORE_WARNINGS:
615 0 : finished=1;
616 0 : break;
617 : case CLIENT_ERROR:
618 0 : if(action!=ACTION_BACKUP
619 0 : && action!=ACTION_BACKUP_TIMED)
620 : {
621 : finished=1;
622 : break;
623 : }
624 0 : if(!get_int(
625 : confs[OPT_FAILOVER_ON_BACKUP_ERROR]))
626 : {
627 : finished=1;
628 : break;
629 : }
630 : // Fall through to failover.
631 : case CLIENT_COULD_NOT_CONNECT:
632 0 : if(!failover)
633 : {
634 : finished=1;
635 : break;
636 : }
637 0 : logp("Failing over\n");
638 : // Use a failover server.
639 0 : server=failover->path;
640 0 : failover=failover->next;
641 0 : break;
642 : case CLIENT_RECONNECT:
643 0 : logp("Multiple reconnect requests to %s- this should not happen!", server);
644 0 : finished=1;
645 0 : break;
646 : }
647 : }
648 :
649 : #ifdef HAVE_WIN32
650 : // allow sleep when idle
651 : SetThreadExecutionState(ES_CONTINUOUS);
652 : #endif
653 :
654 : // See enum cliret for return codes.
655 0 : return (int)ret;
656 : }
|