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