1 /*
2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1991-1999 University of Maryland at College Park
4 * Copyright (c) 2007-2013 Zmanda, Inc. All Rights Reserved.
5 * All Rights Reserved.
6 *
7 * Permission to use, copy, modify, distribute, and sell this software and its
8 * documentation for any purpose is hereby granted without fee, provided that
9 * the above copyright notice appear in all copies and that both that
10 * copyright notice and this permission notice appear in supporting
11 * documentation, and that the name of U.M. not be used in advertising or
12 * publicity pertaining to distribution of the software without specific,
13 * written prior permission. U.M. makes no representations about the
14 * suitability of this software for any purpose. It is provided "as is"
15 * without express or implied warranty.
16 *
17 * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
19 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
21 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
22 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 *
24 * Authors: the Amanda Development Team. Its members are listed in a
25 * file named AUTHORS, in the root directory of this distribution.
26 */
27 /* $Id: dumper.c,v 1.190 2006/08/30 19:53:57 martinea Exp $
28 *
29 * requests remote amandad processes to dump filesystems
30 */
31 #include "amanda.h"
32 #include "amindex.h"
33 #include "arglist.h"
34 #include "clock.h"
35 #include "conffile.h"
36 #include "event.h"
37 #include "logfile.h"
38 #include "packet.h"
39 #include "protocol.h"
40 #include "security.h"
41 #include "stream.h"
42 #include "fileheader.h"
43 #include "amfeatures.h"
44 #include "server_util.h"
45 #include "util.h"
46 #include "timestamp.h"
47 #include "amxml.h"
48
49 #define dumper_debug(i,x) do { \
50 if ((i) <= debug_dumper) { \
51 dbprintf(x); \
52 } \
53 } while (0)
54
55 #ifndef SEEK_SET
56 #define SEEK_SET 0
57 #endif
58
59 #ifndef SEEK_CUR
60 #define SEEK_CUR 1
61 #endif
62
63 #define CONNECT_TIMEOUT 5*60
64
65 #define STARTUP_TIMEOUT 60
66
67 struct databuf {
68 int fd; /* file to flush to */
69 char *buf;
70 char *datain; /* data buffer markers */
71 char *dataout;
72 char *datalimit;
73 pid_t compresspid; /* valid if fd is pipe to compress */
74 pid_t encryptpid; /* valid if fd is pipe to encrypt */
75 };
76
77 struct databuf *g_databuf = NULL;
78
79 typedef struct filter_s {
80 int fd;
81 char *name;
82 char *buffer;
83 gint64 first; /* first byte used */
84 gint64 size; /* number of byte use in the buffer */
85 gint64 allocated_size ; /* allocated size of the buffer */
86 event_handle_t *event;
87 } filter_t;
88
89 static char *handle = NULL;
90
91 static char *errstr = NULL;
92 static off_t dumpbytes;
93 static off_t dumpsize, headersize, origsize;
94
95 static comp_t srvcompress = COMP_NONE;
96 char *srvcompprog = NULL;
97 char *clntcompprog = NULL;
98
99 static encrypt_t srvencrypt = ENCRYPT_NONE;
100 char *srv_encrypt = NULL;
101 char *clnt_encrypt = NULL;
102 char *srv_decrypt_opt = NULL;
103 char *clnt_decrypt_opt = NULL;
104 static kencrypt_type dumper_kencrypt;
105
106 static FILE *errf = NULL;
107 static char *hostname = NULL;
108 static char *maxdumps = NULL;
109 am_feature_t *their_features = NULL;
110 static char *diskname = NULL;
111 static char *qdiskname = NULL, *b64disk;
112 static char *device = NULL, *b64device;
113 static char *options = NULL;
114 static char *progname = NULL;
115 static char *amandad_path=NULL;
116 static char *client_username=NULL;
117 static char *client_port=NULL;
118 static char *ssh_keys=NULL;
119 static char *auth=NULL;
120 static data_path_t data_path=DATA_PATH_AMANDA;
121 static char *dataport_list = NULL;
122 static int level;
123 static char *dumpdate = NULL;
124 static char *dumper_timestamp = NULL;
125 static time_t conf_dtimeout;
126 static int indexfderror;
127 static int set_datafd;
128 static char *dle_str = NULL;
129 static char *errfname = NULL;
130 static int errf_lines = 0;
131 static int max_warnings = 0;
132 static char *state_filename = NULL;
133 static crc_t crc_data_in;
134 static crc_t crc_data_out;
135
136 static dumpfile_t file;
137
138 static struct {
139 const char *name;
140 security_stream_t *fd;
141 } streams[] = {
142 #define DATAFD 0
143 { "DATA", NULL },
144 #define MESGFD 1
145 { "MESG", NULL },
146 #define INDEXFD 2
147 { "INDEX", NULL },
148 };
149 #define NSTREAMS (int)(sizeof(streams) / sizeof(streams[0]))
150
151 static am_feature_t *our_features = NULL;
152 static char *our_feature_string = NULL;
153
154 /* buffer to keep partial line from the MESG stream */
155 static struct {
156 char *buf; /* buffer holding msg data */
157 size_t size; /* size of alloced buffer */
158 } msg = { NULL, 0 };
159
160
161 /* local functions */
162 int main(int, char **);
163 static int do_dump(struct databuf *);
164 static void check_options(char *);
165 static void xml_check_options(char *optionstr);
166 static void finish_tapeheader(dumpfile_t *);
167 static ssize_t write_tapeheader(int, dumpfile_t *);
168 static void databuf_init(struct databuf *, int);
169 static int databuf_write(struct databuf *, const void *, size_t);
170 static int databuf_flush(struct databuf *);
171 static void process_dumpeof(void);
172 static void process_dumpline(const char *);
173 static void add_msg_data(const char *, size_t);
174 static void parse_info_line(char *);
175 static int log_msgout(logtype_t);
176 static char * dumper_get_security_conf (char *, void *);
177
178 static int runcompress(int, pid_t *, comp_t, char *);
179 static int runencrypt(int, pid_t *, encrypt_t);
180
181 static void sendbackup_response(void *, pkt_t *, security_handle_t *);
182 static int startup_dump(const char *, const char *, const char *, int,
183 const char *, const char *, const char *,
184 const char *, const char *, const char *,
185 const char *, const char *);
186 static void stop_dump(void);
187
188 static void read_indexfd(void *, void *, ssize_t);
189 static void read_datafd(void *, void *, ssize_t);
190 static void read_mesgfd(void *, void *, ssize_t);
191 static void timeout(time_t);
192 static void timeout_callback(void *);
193
194 static void
check_options(char * options)195 check_options(
196 char *options)
197 {
198 char *compmode = NULL;
199 char *compend = NULL;
200 char *encryptmode = NULL;
201 char *encryptend = NULL;
202 char *decryptmode = NULL;
203 char *decryptend = NULL;
204
205 /* parse the compression option */
206 if (strstr(options, "srvcomp-best;") != NULL)
207 srvcompress = COMP_BEST;
208 else if (strstr(options, "srvcomp-fast;") != NULL)
209 srvcompress = COMP_FAST;
210 else if ((compmode = strstr(options, "srvcomp-cust=")) != NULL) {
211 compend = strchr(compmode, ';');
212 if (compend ) {
213 srvcompress = COMP_SERVER_CUST;
214 *compend = '\0';
215 srvcompprog = stralloc(compmode + strlen("srvcomp-cust="));
216 *compend = ';';
217 }
218 } else if ((compmode = strstr(options, "comp-cust=")) != NULL) {
219 compend = strchr(compmode, ';');
220 if (compend) {
221 srvcompress = COMP_CUST;
222 *compend = '\0';
223 clntcompprog = stralloc(compmode + strlen("comp-cust="));
224 *compend = ';';
225 }
226 }
227 else {
228 srvcompress = COMP_NONE;
229 }
230
231
232 /* now parse the encryption option */
233 if ((encryptmode = strstr(options, "encrypt-serv-cust=")) != NULL) {
234 encryptend = strchr(encryptmode, ';');
235 if (encryptend) {
236 srvencrypt = ENCRYPT_SERV_CUST;
237 *encryptend = '\0';
238 srv_encrypt = stralloc(encryptmode + strlen("encrypt-serv-cust="));
239 *encryptend = ';';
240 }
241 } else if ((encryptmode = strstr(options, "encrypt-cust=")) != NULL) {
242 encryptend = strchr(encryptmode, ';');
243 if (encryptend) {
244 srvencrypt = ENCRYPT_CUST;
245 *encryptend = '\0';
246 clnt_encrypt = stralloc(encryptmode + strlen("encrypt-cust="));
247 *encryptend = ';';
248 }
249 } else {
250 srvencrypt = ENCRYPT_NONE;
251 }
252 /* get the decryption option parameter */
253 if ((decryptmode = strstr(options, "server-decrypt-option=")) != NULL) {
254 decryptend = strchr(decryptmode, ';');
255 if (decryptend) {
256 *decryptend = '\0';
257 srv_decrypt_opt = stralloc(decryptmode + strlen("server-decrypt-option="));
258 *decryptend = ';';
259 }
260 } else if ((decryptmode = strstr(options, "client-decrypt-option=")) != NULL) {
261 decryptend = strchr(decryptmode, ';');
262 if (decryptend) {
263 *decryptend = '\0';
264 clnt_decrypt_opt = stralloc(decryptmode + strlen("client-decrypt-option="));
265 *decryptend = ';';
266 }
267 }
268
269 if (strstr(options, "kencrypt;") != NULL) {
270 dumper_kencrypt = KENCRYPT_WILL_DO;
271 } else {
272 dumper_kencrypt = KENCRYPT_NONE;
273 }
274 }
275
276
277 static void
xml_check_options(char * optionstr)278 xml_check_options(
279 char *optionstr)
280 {
281 char *o, *oo;
282 char *errmsg = NULL;
283 dle_t *dle;
284
285 o = oo = vstralloc("<dle>", strchr(optionstr,'<'), "</dle>", NULL);
286
287 dle = amxml_parse_node_CHAR(o, &errmsg);
288 if (dle == NULL) {
289 error("amxml_parse_node_CHAR failed: %s\n", errmsg);
290 }
291
292 if (dle->compress == COMP_SERVER_FAST) {
293 srvcompress = COMP_FAST;
294 } else if (dle->compress == COMP_SERVER_BEST) {
295 srvcompress = COMP_BEST;
296 } else if (dle->compress == COMP_SERVER_CUST) {
297 srvcompress = COMP_SERVER_CUST;
298 srvcompprog = g_strdup(dle->compprog);
299 } else if (dle->compress == COMP_CUST) {
300 srvcompress = COMP_CUST;
301 clntcompprog = g_strdup(dle->compprog);
302 } else {
303 srvcompress = COMP_NONE;
304 }
305
306 if (dle->encrypt == ENCRYPT_CUST) {
307 srvencrypt = ENCRYPT_CUST;
308 clnt_encrypt = g_strdup(dle->clnt_encrypt);
309 clnt_decrypt_opt = g_strdup(dle->clnt_decrypt_opt);
310 } else if (dle->encrypt == ENCRYPT_SERV_CUST) {
311 srvencrypt = ENCRYPT_SERV_CUST;
312 srv_encrypt = g_strdup(dle->srv_encrypt);
313 srv_decrypt_opt = g_strdup(dle->srv_decrypt_opt);
314 } else {
315 srvencrypt = ENCRYPT_NONE;
316 }
317
318 if (dle->kencrypt) {
319 dumper_kencrypt = KENCRYPT_WILL_DO;
320 } else {
321 dumper_kencrypt = KENCRYPT_NONE;
322 }
323
324 free_dle(dle);
325 amfree(o);
326 }
327
328
329 int
main(int argc,char ** argv)330 main(
331 int argc,
332 char ** argv)
333 {
334 static struct databuf db;
335 struct cmdargs *cmdargs = NULL;
336 int outfd = -1;
337 int rc;
338 in_port_t header_port;
339 char *q = NULL;
340 int a;
341 int res;
342 config_overrides_t *cfg_ovr = NULL;
343 char *cfg_opt = NULL;
344 int dumper_setuid;
345
346 if (argc > 1 && argv && argv[1] && g_str_equal(argv[1], "--version")) {
347 printf("dumper-%s\n", VERSION);
348 return (0);
349 }
350
351 /*
352 * Configure program for internationalization:
353 * 1) Only set the message locale for now.
354 * 2) Set textdomain for all amanda related programs to "amanda"
355 * We don't want to be forced to support dozens of message catalogs.
356 */
357 setlocale(LC_MESSAGES, "C");
358 textdomain("amanda");
359
360 /* drop root privileges */
361 dumper_setuid = set_root_privs(0);
362
363 safe_fd(-1, 0);
364
365 set_pname("dumper");
366
367 dbopen(DBG_SUBDIR_SERVER);
368
369 /* Don't die when child closes pipe */
370 signal(SIGPIPE, SIG_IGN);
371
372 add_amanda_log_handler(amanda_log_stderr);
373 add_amanda_log_handler(amanda_log_trace_log);
374
375 cfg_ovr = extract_commandline_config_overrides(&argc, &argv);
376 if (argc > 1)
377 cfg_opt = argv[1];
378 set_config_overrides(cfg_ovr);
379 config_init(CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_USE_CWD, cfg_opt);
380
381 if (!dumper_setuid) {
382 error(_("dumper must be run setuid root"));
383 }
384
385 if (config_errors(NULL) >= CFGERR_ERRORS) {
386 g_critical(_("errors processing config file"));
387 }
388
389 safe_cd(); /* do this *after* config_init() */
390 make_crc_table();
391
392 check_running_as(RUNNING_AS_ROOT | RUNNING_AS_UID_ONLY);
393
394 dbrename(get_config_name(), DBG_SUBDIR_SERVER);
395
396 our_features = am_init_feature_set();
397 our_feature_string = am_feature_to_string(our_features);
398
399 log_add(L_INFO, "%s pid %ld", get_pname(), (long)getpid());
400 g_fprintf(stderr,
401 _("%s: pid %ld executable %s version %s\n"),
402 get_pname(), (long) getpid(),
403 argv[0], VERSION);
404 fflush(stderr);
405
406 /* now, make sure we are a valid user */
407
408 signal(SIGPIPE, SIG_IGN);
409
410 conf_dtimeout = (time_t)getconf_int(CNF_DTIMEOUT);
411
412 protocol_init();
413
414 do {
415 if (cmdargs)
416 free_cmdargs(cmdargs);
417 cmdargs = getcmd();
418
419 amfree(errstr);
420 switch(cmdargs->cmd) {
421 case START:
422 if(cmdargs->argc < 2)
423 error(_("error [dumper START: not enough args: timestamp]"));
424 dumper_timestamp = newstralloc(dumper_timestamp, cmdargs->argv[1]);
425 break;
426
427 case ABORT:
428 break;
429
430 case QUIT:
431 break;
432
433 case PORT_DUMP:
434 /*
435 * PORT-DUMP
436 * handle
437 * port
438 * host
439 * features
440 * disk
441 * device
442 * level
443 * dumpdate
444 * progname
445 * amandad_path
446 * client_username
447 * client_port
448 * ssh_keys
449 * security_driver
450 * data_path
451 * dataport_list
452 * options
453 */
454 a = 1; /* skip "PORT-DUMP" */
455
456 if(a >= cmdargs->argc) {
457 error(_("error [dumper PORT-DUMP: not enough args: handle]"));
458 /*NOTREACHED*/
459 }
460 handle = newstralloc(handle, cmdargs->argv[a++]);
461
462 if(a >= cmdargs->argc) {
463 error(_("error [dumper PORT-DUMP: not enough args: port]"));
464 /*NOTREACHED*/
465 }
466 header_port = (in_port_t)atoi(cmdargs->argv[a++]);
467
468 if(a >= cmdargs->argc) {
469 error(_("error [dumper PORT-DUMP: not enough args: maxdumps]"));
470 /*NOTREACHED*/
471 }
472 maxdumps = newstralloc(maxdumps, cmdargs->argv[a++]);
473
474 if(a >= cmdargs->argc) {
475 error(_("error [dumper PORT-DUMP: not enough args: hostname]"));
476 /*NOTREACHED*/
477 }
478 hostname = newstralloc(hostname, cmdargs->argv[a++]);
479
480 if(a >= cmdargs->argc) {
481 error(_("error [dumper PORT-DUMP: not enough args: features]"));
482 /*NOTREACHED*/
483 }
484 am_release_feature_set(their_features);
485 their_features = am_string_to_feature(cmdargs->argv[a++]);
486
487 if(a >= cmdargs->argc) {
488 error(_("error [dumper PORT-DUMP: not enough args: diskname]"));
489 /*NOTREACHED*/
490 }
491 diskname = newstralloc(diskname, cmdargs->argv[a++]);
492 if (qdiskname != NULL)
493 amfree(qdiskname);
494 qdiskname = quote_string(diskname);
495 b64disk = amxml_format_tag("disk", diskname);
496
497 if(a >= cmdargs->argc) {
498 error(_("error [dumper PORT-DUMP: not enough args: device]"));
499 /*NOTREACHED*/
500 }
501 device = newstralloc(device, cmdargs->argv[a++]);
502 b64device = amxml_format_tag("diskdevice", device);
503 if(strcmp(device,"NODEVICE") == 0)
504 amfree(device);
505
506 if(a >= cmdargs->argc) {
507 error(_("error [dumper PORT-DUMP: not enough args: level]"));
508 /*NOTREACHED*/
509 }
510 level = atoi(cmdargs->argv[a++]);
511
512 if(a >= cmdargs->argc) {
513 error(_("error [dumper PORT-DUMP: not enough args: dumpdate]"));
514 /*NOTREACHED*/
515 }
516 dumpdate = newstralloc(dumpdate, cmdargs->argv[a++]);
517
518 if(a >= cmdargs->argc) {
519 error(_("error [dumper PORT-DUMP: not enough args: program]"));
520 /*NOTREACHED*/
521 }
522 progname = newstralloc(progname, cmdargs->argv[a++]);
523
524 if(a >= cmdargs->argc) {
525 error(_("error [dumper PORT-DUMP: not enough args: amandad_path]"));
526 /*NOTREACHED*/
527 }
528 amandad_path = newstralloc(amandad_path, cmdargs->argv[a++]);
529
530 if(a >= cmdargs->argc) {
531 error(_("error [dumper PORT-DUMP: not enough args: client_username]"));
532 }
533 client_username = newstralloc(client_username, cmdargs->argv[a++]);
534
535 if(a >= cmdargs->argc) {
536 error(_("error [dumper PORT-DUMP: not enough args: client_port]"));
537 }
538 client_port = newstralloc(client_port, cmdargs->argv[a++]);
539
540 if(a >= cmdargs->argc) {
541 error(_("error [dumper PORT-DUMP: not enough args: ssh_keys]"));
542 }
543 ssh_keys = newstralloc(ssh_keys, cmdargs->argv[a++]);
544
545 if(a >= cmdargs->argc) {
546 error(_("error [dumper PORT-DUMP: not enough args: auth]"));
547 }
548 auth = newstralloc(auth, cmdargs->argv[a++]);
549
550 if(a >= cmdargs->argc) {
551 error(_("error [dumper PORT-DUMP: not enough args: data_path]"));
552 }
553 data_path = data_path_from_string(cmdargs->argv[a++]);
554
555 if(a >= cmdargs->argc) {
556 error(_("error [dumper PORT-DUMP: not enough args: dataport_list]"));
557 }
558 dataport_list = newstralloc(dataport_list, cmdargs->argv[a++]);
559 if (data_path == DATA_PATH_DIRECTTCP && *dataport_list == '\0') {
560 error(_("error [dumper PORT-DUMP: dataport_list empty for DIRECTTCP]"));
561 }
562
563 if(a >= cmdargs->argc) {
564 error(_("error [dumper PORT-DUMP: not enough args: max_warnings]"));
565 }
566 max_warnings = atoi(cmdargs->argv[a++]);
567
568 if(a >= cmdargs->argc) {
569 error(_("error [dumper PORT-DUMP: not enough args: options]"));
570 }
571 options = newstralloc(options, cmdargs->argv[a++]);
572
573 if(a != cmdargs->argc) {
574 error(_("error [dumper PORT-DUMP: too many args: %d != %d]"),
575 cmdargs->argc, a);
576 /*NOTREACHED*/
577 }
578
579 /* Double-check that 'localhost' resolves properly */
580 if ((res = resolve_hostname("localhost", 0, NULL, NULL) != 0)) {
581 errstr = newvstrallocf(errstr,
582 _("could not resolve localhost: %s"),
583 gai_strerror(res));
584 q = quote_string(errstr);
585 putresult(FAILED, "%s %s\n", handle, q);
586 log_add(L_FAIL, "%s %s %s %d [%s]", hostname, qdiskname,
587 dumper_timestamp, level, errstr);
588 amfree(q);
589 break;
590 }
591
592 /* connect outf to chunker/taper port */
593
594 g_debug(_("Sending header to localhost:%d\n"), header_port);
595 outfd = stream_client("localhost", header_port,
596 STREAM_BUFSIZE, 0, NULL, 0);
597 if (outfd == -1) {
598
599 errstr = newvstrallocf(errstr, _("port open: %s"),
600 strerror(errno));
601 q = quote_string(errstr);
602 putresult(FAILED, "%s %s\n", handle, q);
603 log_add(L_FAIL, "%s %s %s %d [%s]", hostname, qdiskname,
604 dumper_timestamp, level, errstr);
605 amfree(q);
606 break;
607 }
608 databuf_init(&db, outfd);
609 g_databuf = &db;
610
611 if (am_has_feature(their_features, fe_req_xml))
612 xml_check_options(options); /* note: modifies globals */
613 else
614 check_options(options); /* note: modifies globals */
615
616 rc = startup_dump(hostname,
617 diskname,
618 device,
619 level,
620 dumpdate,
621 progname,
622 amandad_path,
623 client_username,
624 client_port,
625 ssh_keys,
626 auth,
627 options);
628 if (rc != 0) {
629 q = quote_string(errstr);
630 putresult(rc == 2? FAILED : TRYAGAIN, "%s %s\n",
631 handle, q);
632 if (rc == 2)
633 log_add(L_FAIL, "%s %s %s %d [%s]", hostname, qdiskname,
634 dumper_timestamp, level, errstr);
635 amfree(q);
636 } else {
637 do_dump(&db);
638 /* try to clean up any defunct processes, since Amanda doesn't
639 wait() for them explicitly */
640 while(waitpid(-1, NULL, WNOHANG)> 0);
641 }
642
643 amfree(amandad_path);
644 amfree(client_username);
645 amfree(client_port);
646 amfree(device);
647 amfree(b64device);
648 amfree(qdiskname);
649 amfree(b64disk);
650
651 break;
652
653 default:
654 if(cmdargs->argc >= 1) {
655 q = quote_string(cmdargs->argv[0]);
656 } else {
657 q = stralloc(_("(no input?)"));
658 }
659 putresult(BAD_COMMAND, "%s\n", q);
660 amfree(q);
661 break;
662 }
663
664 if (outfd != -1)
665 aclose(outfd);
666 } while(cmdargs->cmd != QUIT);
667 free_cmdargs(cmdargs);
668
669 log_add(L_INFO, "pid-done %ld", (long)getpid());
670
671 am_release_feature_set(our_features);
672 amfree(our_feature_string);
673 amfree(errstr);
674 amfree(dumper_timestamp);
675 amfree(handle);
676 amfree(hostname);
677 amfree(qdiskname);
678 amfree(diskname);
679 amfree(device);
680 amfree(dumpdate);
681 amfree(progname);
682 amfree(srvcompprog);
683 amfree(clntcompprog);
684 amfree(srv_encrypt);
685 amfree(clnt_encrypt);
686 amfree(srv_decrypt_opt);
687 amfree(clnt_decrypt_opt);
688 amfree(options);
689
690 dbclose();
691 return (0); /* exit */
692 }
693
694
695 /*
696 * Initialize a databuf. Takes a writeable file descriptor.
697 */
698 static void
databuf_init(struct databuf * db,int fd)699 databuf_init(
700 struct databuf * db,
701 int fd)
702 {
703
704 db->fd = fd;
705 db->datain = db->dataout = db->datalimit = NULL;
706 db->compresspid = -1;
707 db->encryptpid = -1;
708 }
709
710
711 /*
712 * Updates the buffer pointer for the input data buffer. The buffer is
713 * written regardless of how much data is present, since we know we
714 * are writing to a socket (to chunker) and there is no need to maintain
715 * any boundaries.
716 */
717 static int
databuf_write(struct databuf * db,const void * buf,size_t size)718 databuf_write(
719 struct databuf * db,
720 const void * buf,
721 size_t size)
722 {
723 db->buf = (char *)buf;
724 db->datain = db->datalimit = db->buf + size;
725 db->dataout = db->buf;
726 return databuf_flush(db);
727 }
728
729 /*
730 * Write out the buffer to chunker.
731 */
732 static int
databuf_flush(struct databuf * db)733 databuf_flush(
734 struct databuf * db)
735 {
736 size_t written;
737 char *m;
738
739 /*
740 * If there's no data, do nothing.
741 */
742 if (db->dataout >= db->datain) {
743 return 0;
744 }
745
746 /*
747 * Write out the buffer
748 */
749 written = full_write(db->fd, db->dataout,
750 (size_t)(db->datain - db->dataout));
751 if (written > 0) {
752 crc32_add((uint8_t *)db->dataout, written, &crc_data_out);
753 db->dataout += written;
754 dumpbytes += (off_t)written;
755 }
756 if (dumpbytes >= (off_t)1024) {
757 dumpsize += (dumpbytes / (off_t)1024);
758 dumpbytes %= (off_t)1024;
759 }
760 if (written == 0) {
761 int save_errno = errno;
762 m = vstrallocf(_("data write: %s"), strerror(save_errno));
763 amfree(errstr);
764 errstr = quote_string(m);
765 amfree(m);
766 errno = save_errno;
767 return -1;
768 }
769 db->datain = db->dataout = db->buf;
770 return 0;
771 }
772
773 static int dump_result;
774 static int status;
775 #define GOT_INFO_ENDLINE (1 << 0)
776 #define GOT_SIZELINE (1 << 1)
777 #define GOT_ENDLINE (1 << 2)
778 #define HEADER_DONE (1 << 3)
779
780
781 static void
process_dumpeof(void)782 process_dumpeof(void)
783 {
784 /* process any partial line in msgbuf? !!! */
785 add_msg_data(NULL, 0);
786 if(!ISSET(status, GOT_SIZELINE) && dump_result < 2) {
787 /* make a note if there isn't already a failure */
788 g_fprintf(errf,
789 _("? %s: strange [missing size line from sendbackup]\n"),
790 get_pname());
791 if(errstr == NULL) {
792 errstr = stralloc(_("missing size line from sendbackup"));
793 }
794 dump_result = max(dump_result, 2);
795 }
796
797 if(!ISSET(status, GOT_ENDLINE) && dump_result < 2) {
798 g_fprintf(errf,
799 _("? %s: strange [missing end line from sendbackup]\n"),
800 get_pname());
801 if(errstr == NULL) {
802 errstr = stralloc(_("missing end line from sendbackup"));
803 }
804 dump_result = max(dump_result, 2);
805 }
806 }
807
808 /*
809 * Parse an information line from the client.
810 * We ignore unknown parameters and only remember the last
811 * of any duplicates.
812 */
813 static void
parse_info_line(char * str)814 parse_info_line(
815 char *str)
816 {
817 static const struct {
818 const char *name;
819 char *value;
820 size_t len;
821 } fields[] = {
822 { "BACKUP", file.program, SIZEOF(file.program) },
823 { "APPLICATION", file.application, SIZEOF(file.application) },
824 { "RECOVER_CMD", file.recover_cmd, SIZEOF(file.recover_cmd) },
825 { "COMPRESS_SUFFIX", file.comp_suffix, SIZEOF(file.comp_suffix) },
826 { "SERVER_CUSTOM_COMPRESS", file.srvcompprog, SIZEOF(file.srvcompprog) },
827 { "CLIENT_CUSTOM_COMPRESS", file.clntcompprog, SIZEOF(file.clntcompprog) },
828 { "SERVER_ENCRYPT", file.srv_encrypt, SIZEOF(file.srv_encrypt) },
829 { "CLIENT_ENCRYPT", file.clnt_encrypt, SIZEOF(file.clnt_encrypt) },
830 { "SERVER_DECRYPT_OPTION", file.srv_decrypt_opt, SIZEOF(file.srv_decrypt_opt) },
831 { "CLIENT_DECRYPT_OPTION", file.clnt_decrypt_opt, SIZEOF(file.clnt_decrypt_opt) }
832 };
833 char *name, *value;
834 size_t i;
835
836 if (strcmp(str, "end") == 0) {
837 SET(status, GOT_INFO_ENDLINE);
838 return;
839 }
840
841 name = strtok(str, "=");
842 if (name == NULL)
843 return;
844 value = strtok(NULL, "");
845 if (value == NULL)
846 return;
847
848 for (i = 0; i < SIZEOF(fields) / SIZEOF(fields[0]); i++) {
849 if (strcmp(name, fields[i].name) == 0) {
850 strncpy(fields[i].value, value, fields[i].len - 1);
851 fields[i].value[fields[i].len - 1] = '\0';
852 break;
853 }
854 }
855 }
856
857 static void
process_dumpline(const char * str)858 process_dumpline(
859 const char * str)
860 {
861 char *buf, *tok;
862
863 buf = stralloc(str);
864
865 switch (*buf) {
866 case '|':
867 /* normal backup output line */
868 break;
869 case '?':
870 /* sendbackup detected something strange */
871 dump_result = max(dump_result, 1);
872 break;
873 case 's':
874 /* a sendbackup line, just check them all since there are only 5 */
875 tok = strtok(buf, " ");
876 if (tok == NULL || strcmp(tok, "sendbackup:") != 0)
877 goto bad_line;
878
879 tok = strtok(NULL, " ");
880 if (tok == NULL)
881 goto bad_line;
882
883 if (strcmp(tok, "start") == 0) {
884 break;
885 }
886
887 if (strcmp(tok, "size") == 0) {
888 tok = strtok(NULL, "");
889 if (tok != NULL) {
890 origsize = OFF_T_ATOI(tok);
891 SET(status, GOT_SIZELINE);
892 }
893 break;
894 }
895
896 if (strcmp(tok, "no-op") == 0) {
897 amfree(buf);
898 return;
899 }
900
901 if (g_str_equal(tok, "state")) {
902 FILE *statefile;
903 tok = strtok(NULL, "");
904 if (tok) {
905 statefile = fopen(state_filename, "a");
906 if (statefile) {
907 fprintf(statefile, "%s\n", tok);
908 fclose(statefile);
909 } else {
910 g_debug("Can't open statefile '%s': %s", state_filename, strerror(errno));
911 }
912 } else {
913 g_debug("Invalid state");
914 }
915 amfree(buf);
916 return;
917 }
918
919 if (strcmp(tok, "end") == 0) {
920 SET(status, GOT_ENDLINE);
921 break;
922 }
923
924 if (strcmp(tok, "warning") == 0) {
925 dump_result = max(dump_result, 1);
926 break;
927 }
928
929 if (strcmp(tok, "error") == 0) {
930 SET(status, GOT_ENDLINE);
931 dump_result = max(dump_result, 2);
932
933 tok = strtok(NULL, "");
934 if (!errstr) { /* report first error line */
935 if (tok == NULL || *tok != '[') {
936 errstr = newvstrallocf(errstr, _("bad remote error: %s"),
937 str);
938 } else {
939 char *enderr;
940
941 tok++; /* skip over '[' */
942 if ((enderr = strchr(tok, ']')) != NULL)
943 *enderr = '\0';
944 errstr = newstralloc(errstr, tok);
945 }
946 }
947 break;
948 }
949
950 if (strcmp(tok, "info") == 0) {
951 tok = strtok(NULL, "");
952 if (tok != NULL)
953 parse_info_line(tok);
954 break;
955 }
956 /* else we fall through to bad line */
957 default:
958 bad_line:
959 /* prefix with ?? */
960 g_fprintf(errf, "??");
961 dump_result = max(dump_result, 1);
962 break;
963 }
964 g_fprintf(errf, "%s\n", str);
965 errf_lines++;
966 amfree(buf);
967 }
968
969 static void
add_msg_data(const char * str,size_t len)970 add_msg_data(
971 const char * str,
972 size_t len)
973 {
974 char *line, *ch;
975 size_t buflen;
976
977 if (msg.buf != NULL)
978 buflen = strlen(msg.buf);
979 else
980 buflen = 0;
981
982 /*
983 * If our argument is NULL, then we need to flush out any remaining
984 * bits and return.
985 */
986 if (str == NULL) {
987 if (buflen == 0)
988 return;
989 g_fprintf(errf,_("? %s: error [partial line in msgbuf: %zu bytes]\n"),
990 get_pname(), buflen);
991 g_fprintf(errf,_("? %s: error [partial line in msgbuf: \"%s\"]\n"),
992 get_pname(), msg.buf);
993 msg.buf[0] = '\0';
994 return;
995 }
996
997 /*
998 * Expand the buffer if it can't hold the new contents.
999 */
1000 if ((buflen + len + 1) > msg.size) {
1001 char *newbuf;
1002 size_t newsize;
1003
1004 /* round up to next y, where y is a power of 2 */
1005 #define ROUND(x, y) (((x) + (y) - 1) & ~((y) - 1))
1006
1007 newsize = ROUND(buflen + (ssize_t)len + 1, 256);
1008 newbuf = alloc(newsize);
1009
1010 if (msg.buf != NULL) {
1011 strncpy(newbuf, msg.buf, newsize);
1012 amfree(msg.buf);
1013 } else
1014 newbuf[0] = '\0';
1015 msg.buf = newbuf;
1016 msg.size = newsize;
1017 }
1018
1019 /*
1020 * If there was a partial line from the last call, then
1021 * append the new data to the end.
1022 */
1023 strncat(msg.buf, str, len);
1024
1025 /*
1026 * Process all lines in the buffer
1027 * scanning line for unqouted newline.
1028 */
1029 for (ch = line = msg.buf; *ch != '\0'; ch++) {
1030 if (*ch == '\n') {
1031 /*
1032 * Found a newline. Terminate and process line.
1033 */
1034 *ch = '\0';
1035 process_dumpline(line);
1036 line = ch + 1;
1037 }
1038 }
1039
1040 /*
1041 * If we did not process all of the data, move it to the front
1042 * of the buffer so it is there next time.
1043 */
1044 if (*line != '\0') {
1045 buflen = strlen(line);
1046 memmove(msg.buf, line, (size_t)buflen + 1);
1047 } else {
1048 msg.buf[0] = '\0';
1049 }
1050 }
1051
1052
1053 static int
log_msgout(logtype_t typ)1054 log_msgout(
1055 logtype_t typ)
1056 {
1057 char *line;
1058 int count = 0;
1059 int to_unlink = 1;
1060
1061 fflush(errf);
1062 if (fseeko(errf, 0L, SEEK_SET) < 0) {
1063 dbprintf(_("log_msgout: warning - seek failed: %s\n"), strerror(errno));
1064 }
1065 while ((line = agets(errf)) != NULL) {
1066 if (max_warnings > 0 && errf_lines >= max_warnings && count >= max_warnings) {
1067 log_add(typ, "Look in the '%s' file for full error messages", errfname);
1068 to_unlink = 0;
1069 break;
1070 }
1071 if (line[0] != '\0') {
1072 log_add(typ, "%s", line);
1073 }
1074 amfree(line);
1075 count++;
1076 }
1077 amfree(line);
1078
1079 return to_unlink;
1080 }
1081
1082 /* ------------- */
1083
1084 /*
1085 * Fill in the rest of the tape header
1086 */
1087 static void
finish_tapeheader(dumpfile_t * file)1088 finish_tapeheader(
1089 dumpfile_t *file)
1090 {
1091
1092 assert(ISSET(status, HEADER_DONE));
1093
1094 file->type = F_DUMPFILE;
1095 strncpy(file->datestamp, dumper_timestamp, sizeof(file->datestamp) - 1);
1096 strncpy(file->name, hostname, SIZEOF(file->name) - 1);
1097 strncpy(file->disk, diskname, SIZEOF(file->disk) - 1);
1098 file->dumplevel = level;
1099 file->blocksize = DISK_BLOCK_BYTES;
1100
1101 /*
1102 * If we're doing the compression here, we need to override what
1103 * sendbackup told us the compression was.
1104 */
1105 if (srvcompress != COMP_NONE) {
1106 file->compressed = 1;
1107 #ifndef UNCOMPRESS_OPT
1108 #define UNCOMPRESS_OPT ""
1109 #endif
1110 if (srvcompress == COMP_SERVER_CUST) {
1111 g_snprintf(file->uncompress_cmd, SIZEOF(file->uncompress_cmd),
1112 " %s %s |", srvcompprog, "-d");
1113 strncpy(file->comp_suffix, "cust", SIZEOF(file->comp_suffix) - 1);
1114 file->comp_suffix[SIZEOF(file->comp_suffix) - 1] = '\0';
1115 strncpy(file->srvcompprog, srvcompprog, SIZEOF(file->srvcompprog) - 1);
1116 file->srvcompprog[SIZEOF(file->srvcompprog) - 1] = '\0';
1117 } else if ( srvcompress == COMP_CUST ) {
1118 g_snprintf(file->uncompress_cmd, SIZEOF(file->uncompress_cmd),
1119 " %s %s |", clntcompprog, "-d");
1120 strncpy(file->comp_suffix, "cust", SIZEOF(file->comp_suffix) - 1);
1121 file->comp_suffix[SIZEOF(file->comp_suffix) - 1] = '\0';
1122 strncpy(file->clntcompprog, clntcompprog, SIZEOF(file->clntcompprog));
1123 file->clntcompprog[SIZEOF(file->clntcompprog) - 1] = '\0';
1124 } else {
1125 g_snprintf(file->uncompress_cmd, SIZEOF(file->uncompress_cmd),
1126 " %s %s |", UNCOMPRESS_PATH, UNCOMPRESS_OPT);
1127 strncpy(file->comp_suffix, COMPRESS_SUFFIX,SIZEOF(file->comp_suffix) - 1);
1128 file->comp_suffix[SIZEOF(file->comp_suffix) - 1] = '\0';
1129 }
1130 } else {
1131 if (file->comp_suffix[0] == '\0') {
1132 file->compressed = 0;
1133 assert(SIZEOF(file->comp_suffix) >= 2);
1134 strncpy(file->comp_suffix, "N", SIZEOF(file->comp_suffix) - 1);
1135 file->comp_suffix[SIZEOF(file->comp_suffix) - 1] = '\0';
1136 } else {
1137 file->compressed = 1;
1138 }
1139 }
1140 /* take care of the encryption header here */
1141 if (srvencrypt != ENCRYPT_NONE) {
1142 file->encrypted= 1;
1143 if (srvencrypt == ENCRYPT_SERV_CUST) {
1144 if (srv_decrypt_opt) {
1145 g_snprintf(file->decrypt_cmd, SIZEOF(file->decrypt_cmd),
1146 " %s %s |", srv_encrypt, srv_decrypt_opt);
1147 strncpy(file->srv_decrypt_opt, srv_decrypt_opt, SIZEOF(file->srv_decrypt_opt) - 1);
1148 file->srv_decrypt_opt[SIZEOF(file->srv_decrypt_opt) - 1] = '\0';
1149 } else {
1150 g_snprintf(file->decrypt_cmd, SIZEOF(file->decrypt_cmd),
1151 " %s |", srv_encrypt);
1152 file->srv_decrypt_opt[0] = '\0';
1153 }
1154 strncpy(file->encrypt_suffix, "enc", SIZEOF(file->encrypt_suffix) - 1);
1155 file->encrypt_suffix[SIZEOF(file->encrypt_suffix) - 1] = '\0';
1156 strncpy(file->srv_encrypt, srv_encrypt, SIZEOF(file->srv_encrypt) - 1);
1157 file->srv_encrypt[SIZEOF(file->srv_encrypt) - 1] = '\0';
1158 } else if ( srvencrypt == ENCRYPT_CUST ) {
1159 if (clnt_decrypt_opt) {
1160 g_snprintf(file->decrypt_cmd, SIZEOF(file->decrypt_cmd),
1161 " %s %s |", clnt_encrypt, clnt_decrypt_opt);
1162 strncpy(file->clnt_decrypt_opt, clnt_decrypt_opt,
1163 SIZEOF(file->clnt_decrypt_opt));
1164 file->clnt_decrypt_opt[SIZEOF(file->clnt_decrypt_opt) - 1] = '\0';
1165 } else {
1166 g_snprintf(file->decrypt_cmd, SIZEOF(file->decrypt_cmd),
1167 " %s |", clnt_encrypt);
1168 file->clnt_decrypt_opt[0] = '\0';
1169 }
1170 g_snprintf(file->decrypt_cmd, SIZEOF(file->decrypt_cmd),
1171 " %s %s |", clnt_encrypt, clnt_decrypt_opt);
1172 strncpy(file->encrypt_suffix, "enc", SIZEOF(file->encrypt_suffix) - 1);
1173 file->encrypt_suffix[SIZEOF(file->encrypt_suffix) - 1] = '\0';
1174 strncpy(file->clnt_encrypt, clnt_encrypt, SIZEOF(file->clnt_encrypt) - 1);
1175 file->clnt_encrypt[SIZEOF(file->clnt_encrypt) - 1] = '\0';
1176 }
1177 } else {
1178 if (file->encrypt_suffix[0] == '\0') {
1179 file->encrypted = 0;
1180 assert(SIZEOF(file->encrypt_suffix) >= 2);
1181 strncpy(file->encrypt_suffix, "N", SIZEOF(file->encrypt_suffix) - 1);
1182 file->encrypt_suffix[SIZEOF(file->encrypt_suffix) - 1] = '\0';
1183 } else {
1184 file->encrypted= 1;
1185 }
1186 }
1187 if (dle_str)
1188 file->dle_str = stralloc(dle_str);
1189 else
1190 file->dle_str = NULL;
1191 }
1192
1193 /*
1194 * Send an Amanda dump header to the output file.
1195 */
1196 static ssize_t
write_tapeheader(int outfd,dumpfile_t * file)1197 write_tapeheader(
1198 int outfd,
1199 dumpfile_t *file)
1200 {
1201 char * buffer;
1202 size_t written;
1203
1204 if (debug_dumper > 1)
1205 dump_dumpfile_t(file);
1206 buffer = build_header(file, NULL, DISK_BLOCK_BYTES);
1207 if (!buffer) /* this shouldn't happen */
1208 error(_("header does not fit in %zd bytes"), (size_t)DISK_BLOCK_BYTES);
1209
1210 written = full_write(outfd, buffer, DISK_BLOCK_BYTES);
1211 amfree(buffer);
1212 if(written == DISK_BLOCK_BYTES)
1213 return 0;
1214
1215 return -1;
1216 }
1217
1218 int indexout = -1;
1219
1220 static int
do_dump(struct databuf * db)1221 do_dump(
1222 struct databuf *db)
1223 {
1224 char *indexfile_tmp = NULL;
1225 char *indexfile_real = NULL;
1226 char level_str[NUM_STR_SIZE];
1227 char *time_str;
1228 char *fn;
1229 char *q;
1230 times_t runtime;
1231 double dumptime; /* Time dump took in secs */
1232 pid_t indexpid = -1;
1233 char *m;
1234 int to_unlink = 1;
1235 char *shostname;
1236 char *sdiskname;
1237
1238 startclock();
1239
1240 if (msg.buf) msg.buf[0] = '\0'; /* reset msg buffer */
1241 status = 0;
1242 dump_result = 0;
1243 dumpbytes = dumpsize = headersize = origsize = (off_t)0;
1244 fh_init(&file);
1245
1246 g_snprintf(level_str, SIZEOF(level_str), "%d", level);
1247 time_str = get_timestamp_from_time(0);
1248 fn = sanitise_filename(diskname);
1249 errf_lines = 0;
1250 errfname = newvstralloc(errfname,
1251 AMANDA_DBGDIR,
1252 "/log.error", NULL);
1253 mkdir(errfname, 0700);
1254 errfname = newvstralloc(errfname,
1255 AMANDA_DBGDIR,
1256 "/log.error/", hostname,
1257 ".", fn,
1258 ".", level_str,
1259 ".", time_str,
1260 ".errout",
1261 NULL);
1262 amfree(fn);
1263 amfree(time_str);
1264 if((errf = fopen(errfname, "w+")) == NULL) {
1265 errstr = newvstrallocf(errstr, "errfile open \"%s\": %s",
1266 errfname, strerror(errno));
1267 amfree(errfname);
1268 goto failed;
1269 }
1270
1271 shostname = sanitise_filename(hostname);
1272 sdiskname = sanitise_filename(diskname);
1273 state_filename = g_strdup_printf("%s/%s/%s/%s_%d.state",
1274 getconf_str(CNF_INDEXDIR), shostname,
1275 sdiskname, dumper_timestamp, level);
1276 amfree(shostname);
1277 amfree(sdiskname);
1278
1279 if (streams[INDEXFD].fd != NULL) {
1280 indexfile_real = getindexfname(hostname, diskname, dumper_timestamp, level);
1281 indexfile_tmp = stralloc2(indexfile_real, ".tmp");
1282
1283 if (mkpdir(indexfile_tmp, 0755, (uid_t)-1, (gid_t)-1) == -1) {
1284 errstr = newvstrallocf(errstr,
1285 _("err create %s: %s"),
1286 indexfile_tmp,
1287 strerror(errno));
1288 amfree(indexfile_real);
1289 amfree(indexfile_tmp);
1290 goto failed;
1291 }
1292 indexout = open(indexfile_tmp, O_WRONLY | O_CREAT | O_TRUNC, 0600);
1293 if (indexout == -1) {
1294 errstr = newvstrallocf(errstr, _("err open %s: %s"),
1295 indexfile_tmp, strerror(errno));
1296 goto failed;
1297 } else {
1298 if (runcompress(indexout, &indexpid, COMP_BEST, "index compress") < 0) {
1299 aclose(indexout);
1300 goto failed;
1301 }
1302 }
1303 indexfderror = 0;
1304 /*
1305 * Schedule the indexfd for relaying to the index file
1306 */
1307 security_stream_read(streams[INDEXFD].fd, read_indexfd, &indexout);
1308 }
1309
1310 /*
1311 * We only need to process messages initially. Once we have done
1312 * the header, we will start processing data too.
1313 */
1314 security_stream_read(streams[MESGFD].fd, read_mesgfd, db);
1315 set_datafd = 0;
1316
1317 /*
1318 * Setup a read timeout
1319 */
1320 timeout(conf_dtimeout);
1321
1322 /*
1323 * Start the event loop. This will exit when all three events
1324 * (read the mesgfd, read the datafd, and timeout) are removed.
1325 */
1326 event_loop(0);
1327
1328 if (!ISSET(status, HEADER_DONE)) {
1329 dump_result = max(dump_result, 2);
1330 if (!errstr) errstr = stralloc(_("got no header information"));
1331 }
1332
1333 dumpsize -= headersize; /* don't count the header */
1334 if (dumpsize <= (off_t)0 && data_path == DATA_PATH_AMANDA) {
1335 dumpsize = (off_t)0;
1336 dump_result = max(dump_result, 2);
1337 if (!errstr) errstr = stralloc(_("got no data"));
1338 }
1339
1340 if (data_path == DATA_PATH_DIRECTTCP) {
1341 dumpsize = origsize;
1342 }
1343
1344 if (!ISSET(status, HEADER_DONE)) {
1345 dump_result = max(dump_result, 2);
1346 if (!errstr) errstr = stralloc(_("got no header information"));
1347 }
1348
1349 if (dumpsize == 0 && data_path == DATA_PATH_AMANDA) {
1350 dump_result = max(dump_result, 2);
1351 if (!errstr) errstr = stralloc(_("got no data"));
1352 }
1353
1354 if (indexfile_tmp) {
1355 amwait_t index_status;
1356
1357 /*@i@*/ aclose(indexout);
1358 waitpid(indexpid,&index_status,0);
1359 log_add(L_INFO, "pid-done %ld", (long)indexpid);
1360 if (rename(indexfile_tmp, indexfile_real) != 0) {
1361 log_add(L_WARNING, _("could not rename \"%s\" to \"%s\": %s"),
1362 indexfile_tmp, indexfile_real, strerror(errno));
1363 }
1364 amfree(indexfile_tmp);
1365 amfree(indexfile_real);
1366 }
1367
1368 /* copy the header in a file on the index dir */
1369 if (ISSET(status, HEADER_DONE)) {
1370 FILE *a;
1371 char *s;
1372 char *f = getheaderfname(hostname, diskname, dumper_timestamp, level);
1373 a = fopen(f,"w");
1374 if (a) {
1375 s = build_header(&file, NULL, DISK_BLOCK_BYTES);
1376 fprintf(a,"%s", s);
1377 g_free(s);
1378 fclose(a);
1379 }
1380 g_free(f);
1381 }
1382
1383 if (db->compresspid != -1 && dump_result < 2) {
1384 amwait_t wait_status;
1385 char *errmsg = NULL;
1386
1387 waitpid(db->compresspid, &wait_status, 0);
1388 if (WIFSIGNALED(wait_status)) {
1389 errmsg = g_strdup_printf(_("%s terminated with signal %d"),
1390 "compress", WTERMSIG(wait_status));
1391 } else if (WIFEXITED(wait_status)) {
1392 if (WEXITSTATUS(wait_status) != 0) {
1393 errmsg = g_strdup_printf(_("%s exited with status %d"),
1394 "compress", WEXITSTATUS(wait_status));
1395 }
1396 } else {
1397 errmsg = g_strdup_printf(_("%s got bad exit"),
1398 "compress");
1399 }
1400 if (errmsg) {
1401 g_fprintf(errf, _("? %s\n"), errmsg);
1402 g_debug("%s", errmsg);
1403 dump_result = max(dump_result, 2);
1404 if (!errstr)
1405 errstr = errmsg;
1406 else
1407 g_free(errmsg);
1408 }
1409 log_add(L_INFO, "pid-done %ld", (long)db->compresspid);
1410 db->compresspid = -1;
1411 }
1412
1413 if (db->encryptpid != -1 && dump_result < 2) {
1414 amwait_t wait_status;
1415 char *errmsg = NULL;
1416
1417 waitpid(db->encryptpid, &wait_status, 0);
1418 if (WIFSIGNALED(wait_status)) {
1419 errmsg = g_strdup_printf(_("%s terminated with signal %d"),
1420 "encrypt", WTERMSIG(wait_status));
1421 } else if (WIFEXITED(wait_status)) {
1422 if (WEXITSTATUS(wait_status) != 0) {
1423 errmsg = g_strdup_printf(_("%s exited with status %d"),
1424 "encrypt", WEXITSTATUS(wait_status));
1425 }
1426 } else {
1427 errmsg = g_strdup_printf(_("%s got bad exit"),
1428 "encrypt");
1429 }
1430 if (errmsg) {
1431 g_fprintf(errf, _("? %s\n"), errmsg);
1432 g_debug("%s", errmsg);
1433 dump_result = max(dump_result, 2);
1434 if (!errstr)
1435 errstr = errmsg;
1436 else
1437 g_free(errmsg);
1438 }
1439 log_add(L_INFO, "pid-done %ld", (long)db->encryptpid);
1440 db->encryptpid = -1;
1441 }
1442
1443 if (dump_result > 1)
1444 goto failed;
1445
1446 runtime = stopclock();
1447 dumptime = g_timeval_to_double(runtime);
1448
1449 amfree(errstr);
1450 errstr = alloc(128);
1451 g_snprintf(errstr, 128, _("sec %s kb %lld kps %3.1lf orig-kb %lld"),
1452 walltime_str(runtime),
1453 (long long)dumpsize,
1454 (isnormal(dumptime) ? ((double)dumpsize / (double)dumptime) : 0.0),
1455 (long long)origsize);
1456 m = vstrallocf("[%s]", errstr);
1457 q = quote_string(m);
1458 amfree(m);
1459 putresult(DONE, _("%s %lld %lld %lu %s\n"), handle,
1460 (long long)origsize,
1461 (long long)dumpsize,
1462 (unsigned long)((double)dumptime+0.5), q);
1463 amfree(q);
1464
1465 switch(dump_result) {
1466 case 0:
1467 log_add(L_SUCCESS, "%s %s %s %d [%s]", hostname, qdiskname, dumper_timestamp, level, errstr);
1468
1469 break;
1470
1471 case 1:
1472 log_start_multiline();
1473 log_add(L_STRANGE, "%s %s %d [%s]", hostname, qdiskname, level, errstr);
1474 to_unlink = log_msgout(L_STRANGE);
1475 log_end_multiline();
1476
1477 break;
1478 }
1479
1480 if (errf)
1481 afclose(errf);
1482 if (errfname) {
1483 if (to_unlink)
1484 unlink(errfname);
1485 amfree(errfname);
1486 }
1487
1488 if (data_path == DATA_PATH_AMANDA)
1489 aclose(db->fd);
1490
1491 amfree(state_filename);
1492 amfree(errstr);
1493 dumpfile_free_data(&file);
1494
1495 return 1;
1496
1497 failed:
1498 m = vstrallocf("[%s]", errstr);
1499 q = quote_string(m);
1500 putresult(FAILED, "%s %s\n", handle, q);
1501 amfree(q);
1502 amfree(m);
1503
1504 aclose(db->fd);
1505 /* kill all child process */
1506 if (db->compresspid != -1) {
1507 g_fprintf(stderr,_("%s: kill compress command\n"),get_pname());
1508 if (kill(db->compresspid, SIGTERM) < 0) {
1509 if (errno != ESRCH) {
1510 g_fprintf(stderr,_("%s: can't kill compress command: %s\n"),
1511 get_pname(), strerror(errno));
1512 } else {
1513 log_add(L_INFO, "pid-done %ld", (long)db->compresspid);
1514 }
1515 }
1516 else {
1517 waitpid(db->compresspid,NULL,0);
1518 log_add(L_INFO, "pid-done %ld", (long)db->compresspid);
1519 }
1520 }
1521
1522 if (db->encryptpid != -1) {
1523 g_fprintf(stderr,_("%s: kill encrypt command\n"),get_pname());
1524 if (kill(db->encryptpid, SIGTERM) < 0) {
1525 if (errno != ESRCH) {
1526 g_fprintf(stderr,_("%s: can't kill encrypt command: %s\n"),
1527 get_pname(), strerror(errno));
1528 } else {
1529 log_add(L_INFO, "pid-done %ld", (long)db->encryptpid);
1530 }
1531 }
1532 else {
1533 waitpid(db->encryptpid,NULL,0);
1534 log_add(L_INFO, "pid-done %ld", (long)db->encryptpid);
1535 }
1536 }
1537
1538 if (indexpid != -1) {
1539 g_fprintf(stderr,_("%s: kill index command\n"),get_pname());
1540 if (kill(indexpid, SIGTERM) < 0) {
1541 if (errno != ESRCH) {
1542 g_fprintf(stderr,_("%s: can't kill index command: %s\n"),
1543 get_pname(),strerror(errno));
1544 } else {
1545 log_add(L_INFO, "pid-done %ld", (long)indexpid);
1546 }
1547 }
1548 else {
1549 waitpid(indexpid,NULL,0);
1550 log_add(L_INFO, "pid-done %ld", (long)indexpid);
1551 }
1552 }
1553
1554 log_start_multiline();
1555 log_add(L_FAIL, _("%s %s %s %d [%s]"), hostname, qdiskname, dumper_timestamp,
1556 level, errstr);
1557 if (errf) {
1558 to_unlink = log_msgout(L_FAIL);
1559 }
1560 log_end_multiline();
1561
1562 if (errf)
1563 afclose(errf);
1564 if (errfname) {
1565 if (to_unlink)
1566 unlink(errfname);
1567 amfree(errfname);
1568 }
1569
1570 if (indexfile_tmp) {
1571 unlink(indexfile_tmp);
1572 amfree(indexfile_tmp);
1573 amfree(indexfile_real);
1574 }
1575
1576 amfree(errstr);
1577 dumpfile_free_data(&file);
1578
1579 return 0;
1580 }
1581
1582 /*
1583 * Callback for reads on the mesgfd stream
1584 */
1585 static void
read_mesgfd(void * cookie,void * buf,ssize_t size)1586 read_mesgfd(
1587 void * cookie,
1588 void * buf,
1589 ssize_t size)
1590 {
1591 struct databuf *db = cookie;
1592
1593 assert(db != NULL);
1594
1595 switch (size) {
1596 case -1:
1597 errstr = newvstrallocf(errstr, _("mesg read: %s"),
1598 security_stream_geterror(streams[MESGFD].fd));
1599 dump_result = 2;
1600 stop_dump();
1601 return;
1602
1603 case 0:
1604 /*
1605 * EOF. Just shut down the mesg stream.
1606 */
1607 process_dumpeof();
1608 security_stream_close(streams[MESGFD].fd);
1609 streams[MESGFD].fd = NULL;
1610 /*
1611 * If the data fd and index fd has also shut down, then we're done.
1612 */
1613 if ((set_datafd == 0 || streams[DATAFD].fd == NULL) &&
1614 streams[INDEXFD].fd == NULL)
1615 stop_dump();
1616 return;
1617
1618 default:
1619 assert(buf != NULL);
1620 add_msg_data(buf, (size_t)size);
1621 break;
1622 }
1623
1624 if (ISSET(status, GOT_INFO_ENDLINE) && !ISSET(status, HEADER_DONE)) {
1625 /* Use the first in the dataport_list */
1626 in_port_t data_port;
1627 char *data_host = g_strdup(dataport_list);
1628 char *s;
1629
1630 s = strchr(data_host, ',');
1631 if (s) *s = '\0'; /* use first data_port */
1632 s = strrchr(data_host, ':');
1633 *s = '\0';
1634 s++;
1635 data_port = atoi(s);
1636
1637 SET(status, HEADER_DONE);
1638 /* time to do the header */
1639 finish_tapeheader(&file);
1640 if (write_tapeheader(db->fd, &file)) {
1641 errstr = newvstrallocf(errstr, _("write_tapeheader: %s"),
1642 strerror(errno));
1643 dump_result = 2;
1644 amfree(data_host);
1645 stop_dump();
1646 return;
1647 }
1648 aclose(db->fd);
1649 if (data_path == DATA_PATH_AMANDA) {
1650 /* do indirecttcp */
1651 if (g_str_equal(data_host,"255.255.255.255")) {
1652 char buffer[32770];
1653 char *s;
1654 int size;
1655
1656 g_debug(_("Sendingd indirect data output stream: %s:%d\n"), data_host, data_port);
1657 db->fd = stream_client("localhost", data_port,
1658 STREAM_BUFSIZE, 0, NULL, 0);
1659 if (db->fd == -1) {
1660 g_free(errstr);
1661 errstr = g_strdup_printf(_("Can't open indirect data output stream: %s"),
1662 strerror(errno));
1663 dump_result = 2;
1664 amfree(data_host);
1665 stop_dump();
1666 return;
1667 }
1668 size = full_read(db->fd, buffer, 32768);
1669 if (size <= 0) {
1670 g_debug("Failed to read from indirect-direct-tcp port: %s",
1671 strerror(errno));
1672 close(db->fd);
1673 dump_result = 2;
1674 amfree(data_host);
1675 stop_dump();
1676 return;
1677 }
1678 aclose(db->fd);
1679 buffer[size++] = ' ';
1680 buffer[size] = '\0';
1681 if ((s = strchr(buffer, ':')) == NULL) {
1682 g_debug("Failed to parse indirect data output stream: %s", buffer);
1683 dump_result = 2;
1684 amfree(data_host);
1685 stop_dump();
1686 return;
1687 }
1688 *s++ = '\0';
1689 amfree(data_host);
1690 data_host = g_strdup(buffer);
1691 data_port = atoi(s);
1692 }
1693
1694 g_debug(_("Sending data to %s:%d\n"), data_host, data_port);
1695 db->fd = stream_client(data_host, data_port,
1696 STREAM_BUFSIZE, 0, NULL, 0);
1697 if (db->fd == -1) {
1698 errstr = newvstrallocf(errstr,
1699 _("Can't open data output stream: %s"),
1700 strerror(errno));
1701 dump_result = 2;
1702 amfree(data_host);
1703 stop_dump();
1704 return;
1705 }
1706 }
1707 amfree(data_host);
1708
1709 dumpsize += (off_t)DISK_BLOCK_KB;
1710 headersize += (off_t)DISK_BLOCK_KB;
1711
1712 if (srvencrypt == ENCRYPT_SERV_CUST) {
1713 if (runencrypt(db->fd, &db->encryptpid, srvencrypt) < 0) {
1714 dump_result = 2;
1715 stop_dump();
1716 return;
1717 }
1718 }
1719 /*
1720 * Now, setup the compress for the data output, and start
1721 * reading the datafd.
1722 */
1723 if ((srvcompress != COMP_NONE) && (srvcompress != COMP_CUST)) {
1724 if (runcompress(db->fd, &db->compresspid, srvcompress, "data compress") < 0) {
1725 dump_result = 2;
1726 stop_dump();
1727 return;
1728 }
1729 }
1730 if (data_path == DATA_PATH_AMANDA) {
1731 security_stream_read(streams[DATAFD].fd, read_datafd, db);
1732 set_datafd = 1;
1733 }
1734 }
1735
1736 /*
1737 * Reset the timeout for future reads
1738 */
1739 timeout(conf_dtimeout);
1740 }
1741
1742 /*
1743 * Callback for reads on the datafd stream
1744 */
1745 static void
read_datafd(void * cookie,void * buf,ssize_t size)1746 read_datafd(
1747 void * cookie,
1748 void * buf,
1749 ssize_t size)
1750 {
1751 struct databuf *db = cookie;
1752
1753 assert(db != NULL);
1754
1755 /*
1756 * The read failed. Error out
1757 */
1758 if (size < 0) {
1759 errstr = newvstrallocf(errstr, _("data read: %s"),
1760 security_stream_geterror(streams[DATAFD].fd));
1761 dump_result = 2;
1762 aclose(db->fd);
1763 stop_dump();
1764 return;
1765 }
1766
1767 /* The header had better be written at this point */
1768 assert(ISSET(status, HEADER_DONE));
1769
1770 /*
1771 * EOF. Stop and return.
1772 */
1773 if (size == 0) {
1774 databuf_flush(db);
1775 if (dumpbytes != (off_t)0) {
1776 dumpsize += (off_t)1;
1777 }
1778 security_stream_close(streams[DATAFD].fd);
1779 streams[DATAFD].fd = NULL;
1780 aclose(db->fd);
1781 g_debug("data in CRC: %08x:%lld",
1782 crc32_finish(&crc_data_in), (long long)crc_data_in.size);
1783 g_debug("data out CRC: %08x:%lld",
1784 crc32_finish(&crc_data_out), (long long)crc_data_out.size);
1785 /*
1786 * If the mesg fd and index fd has also shut down, then we're done.
1787 */
1788 if (streams[MESGFD].fd == NULL && streams[INDEXFD].fd == NULL)
1789 stop_dump();
1790 return;
1791 }
1792
1793 crc32_add(buf, size, &crc_data_in);
1794 if (debug_auth >= 3) {
1795 crc_data_in.crc = crc32_finish(&crc_data_in);
1796 g_debug("data in sum CRC: %08x:%lld",
1797 crc_data_in.crc, (long long)crc_data_in.size);
1798 crc_data_in.crc = crc32_finish(&crc_data_in);
1799 }
1800 /*
1801 * We read something. Add it to the databuf and reschedule for
1802 * more data.
1803 */
1804 assert(buf != NULL);
1805 if (databuf_write(db, buf, (size_t)size) < 0) {
1806 int save_errno = errno;
1807 errstr = newvstrallocf(errstr, _("data write: %s"), strerror(save_errno));
1808 dump_result = 2;
1809 stop_dump();
1810 return;
1811 }
1812
1813 /*
1814 * Reset the timeout for future reads
1815 */
1816 timeout(conf_dtimeout);
1817 }
1818
1819 /*
1820 * Callback for reads on the index stream
1821 */
1822 static void
read_indexfd(void * cookie,void * buf,ssize_t size)1823 read_indexfd(
1824 void * cookie,
1825 void * buf,
1826 ssize_t size)
1827 {
1828 int fd;
1829
1830 assert(cookie != NULL);
1831 fd = *(int *)cookie;
1832
1833 if (size < 0) {
1834 errstr = newvstrallocf(errstr, _("index read: %s"),
1835 security_stream_geterror(streams[INDEXFD].fd));
1836 dump_result = 2;
1837 stop_dump();
1838 return;
1839 }
1840
1841 /*
1842 * EOF. Stop and return.
1843 */
1844 if (size == 0) {
1845 security_stream_close(streams[INDEXFD].fd);
1846 streams[INDEXFD].fd = NULL;
1847 /*
1848 * If the mesg fd has also shut down, then we're done.
1849 */
1850 if ((set_datafd == 0 || streams[DATAFD].fd == NULL) &&
1851 streams[MESGFD].fd == NULL)
1852 stop_dump();
1853 aclose(indexout);
1854 return;
1855 }
1856
1857 assert(buf != NULL);
1858
1859 /*
1860 * We ignore error while writing to the index file.
1861 */
1862 if (full_write(fd, buf, (size_t)size) < (size_t)size) {
1863 /* Ignore error, but schedule another read. */
1864 if(indexfderror == 0) {
1865 indexfderror = 1;
1866 log_add(L_INFO, _("Index corrupted for %s:%s"), hostname, qdiskname);
1867 }
1868 }
1869 }
1870
1871 static void
handle_filter_stderr(void * cookie)1872 handle_filter_stderr(
1873 void *cookie)
1874 {
1875 filter_t *filter = cookie;
1876 ssize_t nread;
1877 char *b, *p;
1878 gint64 len;
1879
1880 if (filter->buffer == NULL) {
1881 /* allocate initial buffer */
1882 filter->buffer = g_malloc(2048);
1883 filter->first = 0;
1884 filter->size = 0;
1885 filter->allocated_size = 2048;
1886 } else if (filter->first > 0) {
1887 if (filter->allocated_size - filter->size - filter->first < 1024) {
1888 memmove(filter->buffer, filter->buffer + filter->first,
1889 filter->size);
1890 filter->first = 0;
1891 }
1892 } else if (filter->allocated_size - filter->size < 1024) {
1893 /* double the size of the buffer */
1894 filter->allocated_size *= 2;
1895 filter->buffer = g_realloc(filter->buffer, filter->allocated_size);
1896 }
1897
1898 nread = read(filter->fd, filter->buffer + filter->first + filter->size,
1899 filter->allocated_size - filter->first - filter->size - 2);
1900
1901 if (nread <= 0) {
1902 event_release(filter->event);
1903 aclose(filter->fd);
1904 if (filter->size > 0 && filter->buffer[filter->first + filter->size - 1] != '\n') {
1905 /* Add a '\n' at end of buffer */
1906 filter->buffer[filter->first + filter->size] = '\n';
1907 filter->size++;
1908 }
1909 } else {
1910 filter->size += nread;
1911 }
1912
1913 /* process all complete lines */
1914 b = filter->buffer + filter->first;
1915 filter->buffer[filter->first + filter->size] = '\0';
1916 while (b < filter->buffer + filter->first + filter->size &&
1917 (p = strchr(b, '\n')) != NULL) {
1918 *p = '\0';
1919 g_fprintf(errf, _("? %s: %s\n"), filter->name, b);
1920 if (errstr == NULL) {
1921 errstr = stralloc(b);
1922 }
1923 len = p - b + 1;
1924 filter->first += len;
1925 filter->size -= len;
1926 b = p + 1;
1927 dump_result = max(dump_result, 1);
1928 }
1929
1930 if (nread <= 0) {
1931 g_free(filter->buffer);
1932 g_free(filter);
1933 }
1934 }
1935
1936 /*
1937 * Startup a timeout in the event handler. If the arg is 0,
1938 * then remove the timeout.
1939 */
1940 static event_handle_t *ev_timeout = NULL;
1941 static time_t timeout_time;
1942
1943 static void
timeout(time_t seconds)1944 timeout(
1945 time_t seconds)
1946 {
1947 timeout_time = time(NULL) + seconds;
1948
1949 /*
1950 * remove a timeout if seconds is 0
1951 */
1952 if (seconds == 0) {
1953 if (ev_timeout != NULL) {
1954 event_release(ev_timeout);
1955 ev_timeout = NULL;
1956 }
1957 return;
1958 }
1959
1960 /*
1961 * schedule a timeout if it not already scheduled
1962 */
1963 if (ev_timeout == NULL) {
1964 ev_timeout = event_register((event_id_t)seconds, EV_TIME,
1965 timeout_callback, NULL);
1966 }
1967 }
1968
1969 /*
1970 * This is the callback for timeout(). If this is reached, then we
1971 * have a data timeout.
1972 */
1973 static void
timeout_callback(void * unused)1974 timeout_callback(
1975 void * unused)
1976 {
1977 time_t now = time(NULL);
1978 (void)unused; /* Quiet unused parameter warning */
1979
1980 if (ev_timeout != NULL) {
1981 event_release(ev_timeout);
1982 ev_timeout = NULL;
1983 }
1984
1985 if (timeout_time > now) { /* not a data timeout yet */
1986 ev_timeout = event_register((event_id_t)(timeout_time-now), EV_TIME,
1987 timeout_callback, NULL);
1988 return;
1989 }
1990
1991 assert(unused == NULL);
1992 errstr = newstralloc(errstr, _("data timeout"));
1993 dump_result = 2;
1994 stop_dump();
1995 }
1996
1997 /*
1998 * This is called when everything needs to shut down so event_loop()
1999 * will exit.
2000 */
2001 static void
stop_dump(void)2002 stop_dump(void)
2003 {
2004 int i;
2005 struct cmdargs *cmdargs = NULL;
2006
2007 /* Check if I have a pending ABORT command */
2008 cmdargs = get_pending_cmd();
2009 if (cmdargs) {
2010 if (cmdargs->cmd == QUIT) {
2011 g_debug("Got unexpected QUIT");
2012 log_add(L_FAIL, "%s %s %s %d [Killed while dumping]",
2013 hostname, qdiskname, dumper_timestamp, level);
2014 exit(1);
2015 }
2016 if (cmdargs->cmd != ABORT) {
2017 g_debug("Expected an ABORT command");
2018 exit(1);
2019 }
2020 amfree(errstr);
2021 errstr = stralloc(cmdargs->argv[1]);
2022 free_cmdargs(cmdargs);
2023 }
2024
2025 for (i = 0; i < NSTREAMS; i++) {
2026 if (streams[i].fd != NULL) {
2027 security_stream_close(streams[i].fd);
2028 streams[i].fd = NULL;
2029 }
2030 }
2031 aclose(indexout);
2032 aclose(g_databuf->fd);
2033 timeout(0);
2034 }
2035
2036
2037 /*
2038 * Runs compress with the first arg as its stdout. Returns
2039 * 0 on success or negative if error, and it's pid via the second
2040 * argument. The outfd arg is dup2'd to the pipe to the compress
2041 * process.
2042 */
2043 static int
runcompress(int outfd,pid_t * pid,comp_t comptype,char * name)2044 runcompress(
2045 int outfd,
2046 pid_t * pid,
2047 comp_t comptype,
2048 char *name)
2049 {
2050 int outpipe[2], rval;
2051 int errpipe[2];
2052 filter_t *filter;
2053
2054 assert(outfd >= 0);
2055 assert(pid != NULL);
2056
2057 /* outpipe[0] is pipe's stdin, outpipe[1] is stdout. */
2058 if (pipe(outpipe) < 0) {
2059 errstr = newvstrallocf(errstr, _("pipe: %s"), strerror(errno));
2060 return (-1);
2061 }
2062
2063 /* errpipe[0] is pipe's output, outpipe[1] is input. */
2064 if (pipe(errpipe) < 0) {
2065 errstr = newvstrallocf(errstr, _("pipe: %s"), strerror(errno));
2066 return (-1);
2067 }
2068
2069 if (comptype != COMP_SERVER_CUST) {
2070 g_debug("execute: %s %s", COMPRESS_PATH,
2071 comptype == COMP_BEST ? COMPRESS_BEST_OPT : COMPRESS_FAST_OPT);
2072 } else {
2073 g_debug("execute: %s", srvcompprog);
2074 }
2075 switch (*pid = fork()) {
2076 case -1:
2077 errstr = newvstrallocf(errstr, _("couldn't fork: %s"), strerror(errno));
2078 aclose(outpipe[0]);
2079 aclose(outpipe[1]);
2080 aclose(errpipe[0]);
2081 aclose(errpipe[1]);
2082 return (-1);
2083 default:
2084 rval = dup2(outpipe[1], outfd);
2085 if (rval < 0)
2086 errstr = newvstrallocf(errstr, _("couldn't dup2: %s"), strerror(errno));
2087 aclose(outpipe[1]);
2088 aclose(outpipe[0]);
2089 aclose(errpipe[1]);
2090 filter = g_new0(filter_t, 1);
2091 filter->fd = errpipe[0];
2092 filter->name = name;
2093 filter->buffer = NULL;
2094 filter->size = 0;
2095 filter->allocated_size = 0;
2096 filter->event = event_register((event_id_t)filter->fd, EV_READFD,
2097 handle_filter_stderr, filter);
2098 return (rval);
2099 case 0:
2100 close(outpipe[1]);
2101 close(errpipe[0]);
2102 if (dup2(outpipe[0], 0) < 0) {
2103 error(_("err dup2 in: %s"), strerror(errno));
2104 /*NOTREACHED*/
2105 }
2106 if (dup2(outfd, 1) == -1) {
2107 error(_("err dup2 out: %s"), strerror(errno));
2108 /*NOTREACHED*/
2109 }
2110 if (dup2(errpipe[1], 2) == -1) {
2111 error(_("err dup2 err: %s"), strerror(errno));
2112 /*NOTREACHED*/
2113 }
2114 if (comptype != COMP_SERVER_CUST) {
2115 char *base = stralloc(COMPRESS_PATH);
2116 log_add(L_INFO, "%s pid %ld", basename(base), (long)getpid());
2117 amfree(base);
2118 safe_fd(-1, 0);
2119 set_root_privs(-1);
2120 execlp(COMPRESS_PATH, COMPRESS_PATH, ( comptype == COMP_BEST ?
2121 COMPRESS_BEST_OPT : COMPRESS_FAST_OPT), (char *)NULL);
2122 error(_("error: couldn't exec %s: %s"), COMPRESS_PATH, strerror(errno));
2123 /*NOTREACHED*/
2124 } else if (*srvcompprog) {
2125 char *base = stralloc(srvcompprog);
2126 log_add(L_INFO, "%s pid %ld", basename(base), (long)getpid());
2127 amfree(base);
2128 safe_fd(-1, 0);
2129 set_root_privs(-1);
2130 execlp(srvcompprog, srvcompprog, (char *)0);
2131 error(_("error: couldn't exec server custom compression '%s'.\n"), srvcompprog);
2132 /*NOTREACHED*/
2133 }
2134 }
2135 /*NOTREACHED*/
2136 return (-1);
2137 }
2138
2139 /*
2140 * Runs encrypt with the first arg as its stdout. Returns
2141 * 0 on success or negative if error, and it's pid via the second
2142 * argument. The outfd arg is dup2'd to the pipe to the encrypt
2143 * process.
2144 */
2145 static int
runencrypt(int outfd,pid_t * pid,encrypt_t encrypttype)2146 runencrypt(
2147 int outfd,
2148 pid_t * pid,
2149 encrypt_t encrypttype)
2150 {
2151 int outpipe[2], rval;
2152 int errpipe[2];
2153 filter_t *filter;
2154
2155 assert(outfd >= 0);
2156 assert(pid != NULL);
2157
2158 /* outpipe[0] is pipe's stdin, outpipe[1] is stdout. */
2159 if (pipe(outpipe) < 0) {
2160 errstr = newvstrallocf(errstr, _("pipe: %s"), strerror(errno));
2161 return (-1);
2162 }
2163
2164 /* errpipe[0] is pipe's output, outpipe[1] is input. */
2165 if (pipe(errpipe) < 0) {
2166 errstr = newvstrallocf(errstr, _("pipe: %s"), strerror(errno));
2167 return (-1);
2168 }
2169
2170 g_debug("execute: %s", srv_encrypt);
2171 switch (*pid = fork()) {
2172 case -1:
2173 errstr = newvstrallocf(errstr, _("couldn't fork: %s"), strerror(errno));
2174 aclose(outpipe[0]);
2175 aclose(outpipe[1]);
2176 aclose(errpipe[0]);
2177 aclose(errpipe[1]);
2178 return (-1);
2179 default: {
2180 char *base;
2181 rval = dup2(outpipe[1], outfd);
2182 if (rval < 0)
2183 errstr = newvstrallocf(errstr, _("couldn't dup2: %s"), strerror(errno));
2184 aclose(outpipe[1]);
2185 aclose(outpipe[0]);
2186 aclose(errpipe[1]);
2187 filter = g_new0(filter_t, 1);
2188 filter->fd = errpipe[0];
2189 base = g_strdup(srv_encrypt);
2190 filter->name = g_strdup(basename(base));
2191 amfree(base);
2192 filter->buffer = NULL;
2193 filter->size = 0;
2194 filter->allocated_size = 0;
2195 filter->event = event_register((event_id_t)filter->fd, EV_READFD,
2196 handle_filter_stderr, filter);
2197 return (rval);
2198 }
2199 case 0: {
2200 char *base;
2201 if (dup2(outpipe[0], 0) < 0) {
2202 error(_("err dup2 in: %s"), strerror(errno));
2203 /*NOTREACHED*/
2204 }
2205 if (dup2(outfd, 1) < 0 ) {
2206 error(_("err dup2 out: %s"), strerror(errno));
2207 /*NOTREACHED*/
2208 }
2209 if (dup2(errpipe[1], 2) == -1) {
2210 error(_("err dup2 err: %s"), strerror(errno));
2211 /*NOTREACHED*/
2212 }
2213 close(errpipe[0]);
2214 base = stralloc(srv_encrypt);
2215 log_add(L_INFO, "%s pid %ld", basename(base), (long)getpid());
2216 amfree(base);
2217 safe_fd(-1, 0);
2218 if ((encrypttype == ENCRYPT_SERV_CUST) && *srv_encrypt) {
2219 set_root_privs(-1);
2220 execlp(srv_encrypt, srv_encrypt, (char *)0);
2221 error(_("error: couldn't exec server custom encryption '%s'.\n"), srv_encrypt);
2222 /*NOTREACHED*/
2223 }
2224 }
2225 }
2226 /*NOTREACHED*/
2227 return (-1);
2228 }
2229
2230
2231 /* -------------------- */
2232
2233 static void
sendbackup_response(void * datap,pkt_t * pkt,security_handle_t * sech)2234 sendbackup_response(
2235 void * datap,
2236 pkt_t * pkt,
2237 security_handle_t * sech)
2238 {
2239 int ports[NSTREAMS], *response_error = datap, i;
2240 char *p;
2241 char *tok;
2242 char *extra;
2243
2244 assert(response_error != NULL);
2245 assert(sech != NULL);
2246
2247 security_close_connection(sech, hostname);
2248
2249 if (pkt == NULL) {
2250 errstr = newvstrallocf(errstr, _("[request failed: %s]"),
2251 security_geterror(sech));
2252 *response_error = 1;
2253 return;
2254 }
2255
2256 extra = NULL;
2257 memset(ports, 0, SIZEOF(ports));
2258 if (pkt->type == P_NAK) {
2259 #if defined(PACKET_DEBUG)
2260 g_fprintf(stderr, _("got nak response:\n----\n%s\n----\n\n"), pkt->body);
2261 #endif
2262
2263 tok = strtok(pkt->body, " ");
2264 if (tok == NULL || strcmp(tok, "ERROR") != 0)
2265 goto bad_nak;
2266
2267 tok = strtok(NULL, "\n");
2268 if (tok != NULL) {
2269 errstr = newvstrallocf(errstr, "NAK: %s", tok);
2270 *response_error = 1;
2271 } else {
2272 bad_nak:
2273 errstr = newvstrallocf(errstr, "request NAK");
2274 *response_error = 2;
2275 }
2276 return;
2277 }
2278
2279 if (pkt->type != P_REP) {
2280 errstr = newvstrallocf(errstr, _("received strange packet type %s: %s"),
2281 pkt_type2str(pkt->type), pkt->body);
2282 *response_error = 1;
2283 return;
2284 }
2285
2286 dbprintf(_("got response:\n----\n%s\n----\n\n"), pkt->body);
2287
2288 for(i = 0; i < NSTREAMS; i++) {
2289 ports[i] = -1;
2290 streams[i].fd = NULL;
2291 }
2292
2293 p = pkt->body;
2294 while((tok = strtok(p, " \n")) != NULL) {
2295 p = NULL;
2296
2297 /*
2298 * Error response packets have "ERROR" followed by the error message
2299 * followed by a newline.
2300 */
2301 if (strcmp(tok, "ERROR") == 0) {
2302 tok = strtok(NULL, "\n");
2303 if (tok == NULL)
2304 tok = _("[bogus error packet]");
2305 errstr = newvstrallocf(errstr, "%s", tok);
2306 *response_error = 2;
2307 return;
2308 }
2309
2310 /*
2311 * Regular packets have CONNECT followed by three streams
2312 */
2313 if (strcmp(tok, "CONNECT") == 0) {
2314
2315 /*
2316 * Parse the three stream specifiers out of the packet.
2317 */
2318 for (i = 0; i < NSTREAMS; i++) {
2319 tok = strtok(NULL, " ");
2320 if (tok == NULL || strcmp(tok, streams[i].name) != 0) {
2321 extra = vstrallocf(
2322 _("CONNECT token is \"%s\": expected \"%s\""),
2323 tok ? tok : "(null)",
2324 streams[i].name);
2325 goto parse_error;
2326 }
2327 tok = strtok(NULL, " \n");
2328 if (tok == NULL || sscanf(tok, "%d", &ports[i]) != 1) {
2329 extra = vstrallocf(
2330 _("CONNECT %s token is \"%s\": expected a port number"),
2331 streams[i].name, tok ? tok : "(null)");
2332 goto parse_error;
2333 }
2334 }
2335 continue;
2336 }
2337
2338 /*
2339 * OPTIONS [options string] '\n'
2340 */
2341 if (strcmp(tok, "OPTIONS") == 0) {
2342 tok = strtok(NULL, "\n");
2343 if (tok == NULL) {
2344 extra = vstrallocf(_("OPTIONS token is missing"));
2345 goto parse_error;
2346 }
2347
2348 while((p = strchr(tok, ';')) != NULL) {
2349 char ch;
2350 *p++ = '\0';
2351 if(strncmp_const_skip(tok, "features=", tok, ch) == 0) {
2352 char *u = strchr(tok, ';');
2353 ch = ch;
2354 if (u)
2355 *u = '\0';
2356 am_release_feature_set(their_features);
2357 if((their_features = am_string_to_feature(tok)) == NULL) {
2358 errstr = newvstrallocf(errstr,
2359 _("OPTIONS: bad features value: %s"),
2360 tok);
2361 goto parse_error;
2362 }
2363 if (u)
2364 *u = ';';
2365 }
2366 tok = p;
2367 }
2368 continue;
2369 }
2370
2371 extra = vstrallocf(_("next token is \"%s\": expected \"CONNECT\", \"ERROR\" or \"OPTIONS\""),
2372 tok ? tok : "(null)");
2373 goto parse_error;
2374 }
2375
2376 if (dumper_kencrypt == KENCRYPT_WILL_DO)
2377 dumper_kencrypt = KENCRYPT_YES;
2378
2379 /*
2380 * Connect the streams to their remote ports
2381 */
2382 for (i = 0; i < NSTREAMS; i++) {
2383 if (ports[i] == -1)
2384 continue;
2385 streams[i].fd = security_stream_client(sech, ports[i]);
2386 if (streams[i].fd == NULL) {
2387 errstr = newvstrallocf(errstr,
2388 _("[could not connect %s stream: %s]"),
2389 streams[i].name,
2390 security_geterror(sech));
2391 goto connect_error;
2392 }
2393 }
2394
2395 /*
2396 * Authenticate the streams
2397 */
2398 for (i = 0; i < NSTREAMS; i++) {
2399 if (streams[i].fd == NULL)
2400 continue;
2401 if (security_stream_auth(streams[i].fd) < 0) {
2402 errstr = newvstrallocf(errstr,
2403 _("[could not authenticate %s stream: %s]"),
2404 streams[i].name,
2405 security_stream_geterror(streams[i].fd));
2406 goto connect_error;
2407 }
2408 }
2409
2410 /*
2411 * The MESGFD and DATAFD streams are mandatory. If we didn't get
2412 * them, complain.
2413 */
2414 if (streams[MESGFD].fd == NULL || streams[DATAFD].fd == NULL) {
2415 errstr = newvstrallocf(errstr, _("[couldn't open MESG or INDEX streams]"));
2416 goto connect_error;
2417 }
2418
2419 /* everything worked */
2420 *response_error = 0;
2421 return;
2422
2423 parse_error:
2424 errstr = newvstrallocf(errstr,
2425 _("[parse of reply message failed: %s]"),
2426 extra ? extra : _("(no additional information)"));
2427 amfree(extra);
2428 *response_error = 2;
2429 return;
2430
2431 connect_error:
2432 stop_dump();
2433 *response_error = 1;
2434 }
2435
2436 static char *
dumper_get_security_conf(char * string,void * arg)2437 dumper_get_security_conf(
2438 char * string,
2439 void * arg)
2440 {
2441 (void)arg; /* Quiet unused parameter warning */
2442
2443 if(!string || !*string)
2444 return(NULL);
2445
2446 if(strcmp(string, "krb5principal")==0) {
2447 return(getconf_str(CNF_KRB5PRINCIPAL));
2448 } else if(strcmp(string, "krb5keytab")==0) {
2449 return(getconf_str(CNF_KRB5KEYTAB));
2450 } else if(strcmp(string, "amandad_path")==0) {
2451 return (amandad_path);
2452 } else if(strcmp(string, "client_username")==0) {
2453 return (client_username);
2454 } else if(strcmp(string, "client_port")==0) {
2455 return (client_port);
2456 } else if(strcmp(string, "ssh_keys")==0) {
2457 return (ssh_keys);
2458 } else if(strcmp(string, "kencrypt")==0) {
2459 if (dumper_kencrypt == KENCRYPT_YES)
2460 return ("yes");
2461 else
2462 return (NULL);
2463 }
2464 return(NULL);
2465 }
2466
2467 static int
startup_dump(const char * hostname,const char * disk,const char * device,int level,const char * dumpdate,const char * progname,const char * amandad_path,const char * client_username,const char * client_port,const char * ssh_keys,const char * auth,const char * options)2468 startup_dump(
2469 const char *hostname,
2470 const char *disk,
2471 const char *device,
2472 int level,
2473 const char *dumpdate,
2474 const char *progname,
2475 const char *amandad_path,
2476 const char *client_username,
2477 const char *client_port,
2478 const char *ssh_keys,
2479 const char *auth,
2480 const char *options)
2481 {
2482 char level_string[NUM_STR_SIZE];
2483 char *req = NULL;
2484 int response_error;
2485 const security_driver_t *secdrv;
2486 char *application_api;
2487 int has_features;
2488 int has_maxdumps;
2489 int has_hostname;
2490 int has_device;
2491 int has_config;
2492
2493 (void)disk; /* Quiet unused parameter warning */
2494 (void)amandad_path; /* Quiet unused parameter warning */
2495 (void)client_username; /* Quiet unused parameter warning */
2496 (void)client_port; /* Quiet unused parameter warning */
2497 (void)ssh_keys; /* Quiet unused parameter warning */
2498 (void)auth; /* Quiet unused parameter warning */
2499
2500 has_features = am_has_feature(their_features, fe_req_options_features);
2501 has_hostname = am_has_feature(their_features, fe_req_options_hostname);
2502 has_maxdumps = am_has_feature(their_features, fe_req_options_maxdumps);
2503 has_config = am_has_feature(their_features, fe_req_options_config);
2504 has_device = am_has_feature(their_features, fe_sendbackup_req_device);
2505 crc32_init(&crc_data_in);
2506 crc32_init(&crc_data_out);
2507
2508 /*
2509 * Default to bsd authentication if none specified. This is gross.
2510 *
2511 * Options really need to be pre-parsed into some sort of structure
2512 * much earlier, and then flattened out again before transmission.
2513 */
2514
2515 g_snprintf(level_string, SIZEOF(level_string), "%d", level);
2516 if(strcmp(progname, "DUMP") == 0
2517 || strcmp(progname, "GNUTAR") == 0) {
2518 application_api = "";
2519 } else {
2520 application_api = "BACKUP ";
2521 }
2522 req = vstralloc("SERVICE sendbackup\n",
2523 "OPTIONS ",
2524 has_features ? "features=" : "",
2525 has_features ? our_feature_string : "",
2526 has_features ? ";" : "",
2527 has_maxdumps ? "maxdumps=" : "",
2528 has_maxdumps ? maxdumps : "",
2529 has_maxdumps ? ";" : "",
2530 has_hostname ? "hostname=" : "",
2531 has_hostname ? hostname : "",
2532 has_hostname ? ";" : "",
2533 has_config ? "config=" : "",
2534 has_config ? get_config_name() : "",
2535 has_config ? ";" : "",
2536 "\n",
2537 NULL);
2538
2539 amfree(dle_str);
2540 if (am_has_feature(their_features, fe_req_xml)) {
2541 char *p = NULL;
2542 char *pclean;
2543 vstrextend(&p, "<dle>\n", NULL);
2544 if (*application_api != '\0') {
2545 vstrextend(&p, " <program>APPLICATION</program>\n", NULL);
2546 } else {
2547 vstrextend(&p, " <program>", progname, "</program>\n", NULL);
2548 }
2549 vstrextend(&p, " ", b64disk, "\n", NULL);
2550 if (device && has_device) {
2551 vstrextend(&p, " ", b64device, "\n",
2552 NULL);
2553 }
2554 vstrextend(&p, " <level>", level_string, "</level>\n", NULL);
2555 vstrextend(&p, options+1, "</dle>\n", NULL);
2556 pclean = clean_dle_str_for_client(p, their_features);
2557 vstrextend(&req, pclean, NULL);
2558 amfree(pclean);
2559 dle_str = p;
2560 } else if (*application_api != '\0') {
2561 errstr = newvstrallocf(errstr,
2562 _("[does not support application-api]"));
2563 amfree(req);
2564 return 2;
2565 } else {
2566 if (auth == NULL) {
2567 auth = "BSD";
2568 }
2569 vstrextend(&req,
2570 progname,
2571 " ", qdiskname,
2572 " ", device && has_device ? device : "",
2573 " ", level_string,
2574 " ", dumpdate,
2575 " OPTIONS ", options,
2576 "\n",
2577 NULL);
2578 }
2579
2580 dbprintf(_("send request:\n----\n%s\n----\n\n"), req);
2581 secdrv = security_getdriver(auth);
2582 if (secdrv == NULL) {
2583 errstr = newvstrallocf(errstr,
2584 _("[could not find security driver '%s']"), auth);
2585 amfree(req);
2586 return 2;
2587 }
2588
2589 protocol_sendreq(hostname, secdrv, dumper_get_security_conf, req,
2590 STARTUP_TIMEOUT, sendbackup_response, &response_error);
2591
2592 amfree(req);
2593
2594 protocol_run();
2595 return (response_error);
2596 }
2597