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