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 :
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_connect(*ssl)<=0)
313 : {
314 0 : logp_ssl_err("SSL connect error\n");
315 : goto end;
316 : }
317 :
318 : ret=0;
319 : end:
320 0 : free_w(&server_copy);
321 0 : return ret;
322 : }
323 :
324 0 : static enum cliret initial_comms(struct async *as,
325 : enum action *action, char **incexc, struct conf **confs,
326 : struct strlist *failover)
327 : {
328 : struct asfd *asfd;
329 0 : char *server_version=NULL;
330 0 : enum cliret ret=CLIENT_OK;
331 0 : asfd=as->asfd;
332 :
333 0 : if(authorise_client(asfd, &server_version,
334 0 : get_string(confs[OPT_CNAME]),
335 0 : get_string(confs[OPT_PASSWORD]),
336 : get_cntr(confs)))
337 : goto error;
338 :
339 0 : if(server_version)
340 : {
341 0 : logp("Server version: %s\n", server_version);
342 : // Servers before 1.3.2 did not tell us their versions.
343 : // 1.3.2 and above can do the automatic CA stuff that
344 : // follows.
345 0 : switch(ca_client_setup(asfd, confs))
346 : {
347 : case 0:
348 : break; // All OK.
349 : case 1:
350 : // Certificate signed successfully.
351 : // Everything is OK, but we will reconnect now,
352 : // in order to use the new keys/certificates.
353 : goto reconnect;
354 : default:
355 0 : logp("Error with cert signing request\n");
356 0 : goto error;
357 : }
358 : }
359 :
360 0 : if(ssl_check_cert(asfd->ssl, NULL, confs))
361 : {
362 0 : logp("check cert failed\n");
363 0 : goto error;
364 : }
365 :
366 0 : if(extra_comms_client(as, confs, action, failover, incexc))
367 : {
368 0 : logp("extra comms failed\n");
369 0 : goto error;
370 : }
371 :
372 : ret=CLIENT_OK; goto end;
373 : error:
374 : ret=CLIENT_ERROR; goto end;
375 : reconnect:
376 : ret=CLIENT_RECONNECT; goto end;
377 : end:
378 0 : free_w(&server_version);
379 0 : return ret;
380 : }
381 :
382 0 : static enum cliret restore_wrapper(struct asfd *asfd, enum action action,
383 : struct conf **confs)
384 : {
385 0 : enum cliret ret=CLIENT_OK;
386 0 : const char *r_script_pre=get_string(confs[OPT_R_SCRIPT_PRE]);
387 0 : const char *r_script_post=get_string(confs[OPT_R_SCRIPT_POST]);
388 :
389 0 : if(r_script_pre)
390 : {
391 0 : int a=0;
392 : const char *args[12];
393 0 : args[a++]=r_script_pre;
394 0 : if(get_int(confs[OPT_R_SCRIPT_RESERVED_ARGS]))
395 : {
396 0 : args[a++]="pre";
397 0 : args[a++]="reserved2";
398 0 : args[a++]="reserved3";
399 0 : args[a++]="reserved4";
400 0 : args[a++]="reserved5";
401 : }
402 0 : args[a++]=NULL;
403 0 : if(run_script(asfd,
404 : args, get_strlist(confs[OPT_R_SCRIPT_PRE_ARG]),
405 : confs, 1, 1, 1))
406 0 : ret=CLIENT_ERROR;
407 : }
408 0 : if(ret==CLIENT_OK)
409 : {
410 0 : if(do_restore_client(asfd, confs,
411 0 : action)) ret=CLIENT_ERROR;
412 : }
413 0 : if((ret==CLIENT_OK || get_int(confs[OPT_R_SCRIPT_POST_RUN_ON_FAIL]))
414 0 : && r_script_post)
415 : {
416 0 : int a=0;
417 : const char *args[12];
418 0 : args[a++]=r_script_post;
419 0 : if(get_int(confs[OPT_R_SCRIPT_RESERVED_ARGS]))
420 : {
421 0 : args[a++]="post";
422 : // Tell post script whether the restore failed.
423 0 : args[a++]=ret?"1":"0";
424 0 : args[a++]="reserved3";
425 0 : args[a++]="reserved4";
426 0 : args[a++]="reserved5";
427 : }
428 0 : args[a++]=NULL;
429 0 : if(run_script(asfd,
430 : args, get_strlist(confs[OPT_R_SCRIPT_POST_ARG]),
431 : confs, 1, 1, /*log_remote*/ 0))
432 0 : ret=CLIENT_ERROR;
433 : }
434 :
435 : // Return non-zero if there were warnings,
436 : // so that the test script can easily check.
437 0 : if(ret==CLIENT_OK && get_cntr(confs)->ent[CMD_WARNING]->count)
438 0 : ret=CLIENT_RESTORE_WARNINGS;
439 :
440 0 : return ret;
441 : }
442 :
443 0 : static enum cliret do_client(struct conf **confs,
444 : enum action action, const char *server,
445 : struct strlist *failover)
446 : {
447 0 : enum cliret ret=CLIENT_OK;
448 0 : int rfd=-1;
449 0 : SSL *ssl=NULL;
450 0 : SSL_CTX *ctx=NULL;
451 0 : struct cntr *cntr=NULL;
452 0 : char *incexc=NULL;
453 0 : enum action act=action;
454 0 : struct async *as=NULL;
455 0 : struct asfd *asfd=NULL;
456 :
457 : // as->settimers(0, 100);
458 :
459 : // logp("begin client\n");
460 : // logp("action %d\n", action);
461 :
462 : // Status monitor forks a child process instead of connecting to
463 : // the server directly.
464 0 : if(action==ACTION_STATUS
465 0 : || action==ACTION_STATUS_SNAPSHOT)
466 : {
467 : #ifdef HAVE_WIN32
468 : logp("Status mode not implemented on Windows.\n");
469 : goto error;
470 : #endif
471 0 : if(status_client_ncurses_init(act)
472 0 : || status_client_ncurses(confs)) ret=CLIENT_ERROR;
473 : goto end;
474 : }
475 :
476 0 : if(!(cntr=cntr_alloc())
477 0 : || cntr_init(cntr, get_string(confs[OPT_CNAME]), getpid()))
478 : goto error;
479 0 : set_cntr(confs[OPT_CNTR], cntr);
480 :
481 0 : if(act!=ACTION_ESTIMATE)
482 : {
483 0 : if(ssl_setup(&rfd,
484 : &ssl, &ctx, action, confs, server, failover))
485 : goto could_not_connect;
486 :
487 0 : if(!(as=async_alloc())
488 0 : || as->init(as, act==ACTION_ESTIMATE)
489 0 : || !(asfd=setup_asfd_ssl(as, "main socket", &rfd, ssl)))
490 : goto end;
491 0 : asfd->set_timeout(asfd, get_int(confs[OPT_NETWORK_TIMEOUT]));
492 0 : asfd->ratelimit=get_float(confs[OPT_RATELIMIT]);
493 :
494 : // Set quality of service bits on backup packets.
495 0 : if(act==ACTION_BACKUP
496 0 : || act==ACTION_BACKUP_TIMED
497 0 : || act==ACTION_TIMER_CHECK)
498 0 : as->asfd->set_bulk_packets(as->asfd);
499 :
500 0 : if((ret=initial_comms(as, &act, &incexc, confs, failover)))
501 : goto end;
502 : }
503 :
504 0 : rfd=-1;
505 0 : switch(act)
506 : {
507 : case ACTION_BACKUP:
508 0 : ret=backup_wrapper(asfd, act, "backupphase1",
509 : incexc, confs);
510 0 : break;
511 : case ACTION_BACKUP_TIMED:
512 0 : ret=backup_wrapper(asfd, act, "backupphase1timed",
513 : incexc, confs);
514 0 : break;
515 : case ACTION_TIMER_CHECK:
516 0 : ret=backup_wrapper(asfd, act, "backupphase1timedcheck",
517 : incexc, confs);
518 0 : break;
519 : case ACTION_RESTORE:
520 : case ACTION_VERIFY:
521 0 : ret=restore_wrapper(asfd, act, confs);
522 0 : break;
523 : case ACTION_ESTIMATE:
524 0 : if(do_backup_client(asfd, confs, act, 0))
525 : goto error;
526 : break;
527 : case ACTION_DELETE:
528 0 : if(do_delete_client(asfd, confs))
529 : goto error;
530 : break;
531 : case ACTION_MONITOR:
532 0 : if(do_monitor_client(asfd))
533 : goto error;
534 : break;
535 : case ACTION_DIFF:
536 : case ACTION_DIFF_LONG:
537 : /*
538 : if(!strcmp(get_string(confs[OPT_BACKUP2]), "n"))
539 : // Do a phase1 scan and diff that.
540 : ret=backup_wrapper(asfd, act,
541 : "backupphase1diff", incexc, confs);
542 : else
543 : */
544 : // Diff two backups that already exist.
545 : // Fall through, the list code is all we need
546 : // for simple diffs on the client side.
547 : case ACTION_LIST:
548 : case ACTION_LIST_LONG:
549 : case ACTION_LIST_PARSEABLE:
550 : default:
551 0 : if(do_list_client(asfd, act, confs)) goto error;
552 : break;
553 : }
554 :
555 0 : if(asfd_flush_asio(asfd))
556 0 : ret=CLIENT_ERROR;
557 :
558 : goto end;
559 : error:
560 : ret=CLIENT_ERROR; goto end;
561 : could_not_connect:
562 : ret=CLIENT_COULD_NOT_CONNECT;
563 : end:
564 0 : close_fd(&rfd);
565 0 : async_free(&as);
566 0 : asfd_free(&asfd);
567 0 : if(ctx) ssl_destroy_ctx(ctx);
568 0 : free_w(&incexc);
569 0 : set_cntr(confs[OPT_CNTR], NULL);
570 0 : cntr_free(&cntr);
571 :
572 : //logp("end client\n");
573 0 : return ret;
574 : }
575 :
576 0 : int client(struct conf **confs,
577 : enum action action)
578 : {
579 0 : int finished=0;
580 0 : enum cliret ret=CLIENT_OK;
581 0 : const char *server=NULL;
582 0 : struct strlist *failover=NULL;
583 :
584 0 : if(!get_int(confs[OPT_ENABLED]))
585 : {
586 0 : logp("Client not enabled\n");
587 0 : return ret;
588 : }
589 :
590 : #ifdef HAVE_WIN32
591 : // prevent sleep when idle
592 : SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED);
593 : #endif
594 0 : server=get_string(confs[OPT_SERVER]);
595 0 : failover=get_strlist(confs[OPT_SERVER_FAILOVER]);
596 :
597 0 : while(!finished)
598 : {
599 0 : ret=do_client(confs,
600 : action, server, failover);
601 0 : if(ret==CLIENT_RECONNECT)
602 : {
603 0 : logp("Re-opening connection to %s\n", server);
604 0 : sleep(5);
605 0 : ret=do_client(confs,
606 : action, server, failover);
607 : }
608 0 : switch(ret)
609 : {
610 : case CLIENT_OK:
611 : case CLIENT_SERVER_TIMER_NOT_MET:
612 : case CLIENT_SERVER_MAX_PARALLEL_BACKUPS:
613 : case CLIENT_RESTORE_WARNINGS:
614 0 : finished=1;
615 0 : break;
616 : case CLIENT_ERROR:
617 0 : if(action!=ACTION_BACKUP
618 0 : && action!=ACTION_BACKUP_TIMED)
619 : {
620 : finished=1;
621 : break;
622 : }
623 0 : if(!get_int(
624 : confs[OPT_FAILOVER_ON_BACKUP_ERROR]))
625 : {
626 : finished=1;
627 : break;
628 : }
629 : // Fall through to failover.
630 : case CLIENT_COULD_NOT_CONNECT:
631 0 : if(!failover)
632 : {
633 : finished=1;
634 : break;
635 : }
636 0 : logp("Failing over\n");
637 : // Use a failover server.
638 0 : server=failover->path;
639 0 : failover=failover->next;
640 0 : break;
641 : case CLIENT_RECONNECT:
642 0 : logp("Multiple reconnect requests to %s- this should not happen!", server);
643 0 : finished=1;
644 0 : break;
645 : }
646 : }
647 :
648 : #ifdef HAVE_WIN32
649 : // allow sleep when idle
650 : SetThreadExecutionState(ES_CONTINUOUS);
651 : #endif
652 :
653 : // See enum cliret for return codes.
654 0 : return (int)ret;
655 : }
|