2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1991-1999 University of Maryland at College Park
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of U.M. not be used in advertising or
11 * publicity pertaining to distribution of the software without specific,
12 * written prior permission. U.M. makes no representations about the
13 * suitability of this software for any purpose. It is provided "as is"
14 * without express or implied warranty.
16 * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
18 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 * Authors: the Amanda Development Team. Its members are listed in a
24 * file named AUTHORS, in the root directory of this distribution.
28 * $Id: amandad.c,v 1.18 2006/08/21 20:17:09 martinea Exp $
30 * handle client-host side of Amanda network communications, including
31 * security checks, execution of the proper service, and acking the
39 #include "amfeatures.h"
48 #define REP_TIMEOUT (6*60*60) /* secs for service to reply */
49 #define ACK_TIMEOUT 10 /* XXX should be configurable */
51 #define amandad_debug(i, ...) do { \
52 if ((i) <= debug_amandad) { \
53 dbprintf(__VA_ARGS__); \
58 * These are the actions for entering the state machine
60 typedef enum { A_START, A_RECVPKT, A_RECVREP, A_PENDING, A_FINISH, A_CONTINUE,
61 A_SENDNAK, A_TIMEOUT } action_t;
64 * This is a state in the state machine. It is a function pointer to
65 * the function that actually implements the state.
67 struct active_service;
68 typedef action_t (*state_t)(struct active_service *, action_t, pkt_t *);
71 * This structure describes an active running service.
73 * An active service is something running that we have received
74 * a request for. This structure holds info on that service, including
75 * file descriptors for data, etc, as well as the security handle
76 * for communications with the amanda server.
78 struct active_service {
79 char *cmd; /* name of command we ran */
80 char *arguments; /* arguments we sent it */
81 security_handle_t *security_handle; /* remote server */
82 state_t state; /* how far this has progressed */
83 pid_t pid; /* pid of subprocess */
84 int send_partial_reply; /* send PREP packet */
85 int reqfd; /* pipe to write requests */
86 int repfd; /* pipe to read replies */
87 event_handle_t *ev_repfd; /* read event handle for repfd */
88 event_handle_t *ev_reptimeout; /* timeout for rep data */
89 pkt_t rep_pkt; /* rep packet we're sending out */
90 char *repbuf; /* buffer to read the rep into */
91 size_t bufsize; /* length of repbuf */
92 size_t repbufsize; /* length of repbuf */
93 int repretry; /* times we'll retry sending the rep */
95 * General user streams to the process, and their equivalent
98 struct datafd_handle {
99 int fd_read; /* pipe to child process */
100 int fd_write; /* pipe to child process */
101 event_handle_t *ev_read; /* it's read event handle */
102 event_handle_t *ev_write; /* it's write event handle */
103 security_stream_t *netfd; /* stream to amanda server */
104 struct active_service *as; /* pointer back to our enclosure */
105 } data[DATA_FD_COUNT];
106 char databuf[NETWORK_BLOCK_BYTES]; /* buffer to relay netfd data in */
107 TAILQ_ENTRY(active_service) tq; /* queue handle */
111 * Here are the services that we allow.
113 static struct services {
124 #define NSERVICES (int)(sizeof(services) / sizeof(services[0]))
127 * Queue of outstanding requests that we are running.
130 TAILQ_HEAD(, active_service) tailq;
133 TAILQ_HEAD_INITIALIZER(serviceq.tailq), 0
136 static int wait_30s = 1;
137 static int exit_on_qlength = 1;
138 static char *auth = NULL;
139 static kencrypt_type amandad_kencrypt = KENCRYPT_NONE;
141 int main(int argc, char **argv);
143 static int allocstream(struct active_service *, int);
144 static void exit_check(void *);
145 static void protocol_accept(security_handle_t *, pkt_t *);
146 static void state_machine(struct active_service *, action_t, pkt_t *);
148 static action_t s_sendack(struct active_service *, action_t, pkt_t *);
149 static action_t s_repwait(struct active_service *, action_t, pkt_t *);
150 static action_t s_processrep(struct active_service *, action_t, pkt_t *);
151 static action_t s_sendrep(struct active_service *, action_t, pkt_t *);
152 static action_t s_ackwait(struct active_service *, action_t, pkt_t *);
154 static void repfd_recv(void *);
155 static void timeout_repfd(void *);
156 static void protocol_recv(void *, pkt_t *, security_status_t);
157 static void process_readnetfd(void *);
158 static void process_writenetfd(void *, void *, ssize_t);
159 static struct active_service *service_new(security_handle_t *,
160 const char *, const char *);
161 static void service_delete(struct active_service *);
162 static int writebuf(struct active_service *, const void *, size_t);
163 static ssize_t do_sendpkt(security_handle_t *handle, pkt_t *pkt);
164 static char *amandad_get_security_conf (char *, void *);
166 static const char *state2str(state_t);
167 static const char *action2str(action_t);
177 const security_driver_t *secdrv;
179 char *pgm = "amandad"; /* in case argv[0] is not set */
180 #if defined(USE_REUSEADDR)
186 * Configure program for internationalization:
187 * 1) Only set the message locale for now.
188 * 2) Set textdomain for all amanda related programs to "amanda"
189 * We don't want to be forced to support dozens of message catalogs.
191 setlocale(LC_MESSAGES, "C");
192 textdomain("amanda");
198 * When called via inetd, it is not uncommon to forget to put the
199 * argv[0] value on the config line. On some systems (e.g. Solaris)
200 * this causes argv and/or argv[0] to be NULL, so we have to be
201 * careful getting our name.
203 if ((argv == NULL) || (argv[0] == NULL)) {
204 pgm = "amandad"; /* in case argv[0] is not set */
206 pgm = basename(argv[0]); /* Strip of leading path get debug name */
209 dbopen(DBG_SUBDIR_AMANDAD);
212 error(_("argv == NULL\n"));
216 /* Don't die when child closes pipe */
217 signal(SIGPIPE, SIG_IGN);
219 config_init(CONFIG_INIT_CLIENT, NULL);
221 if (geteuid() == 0) {
222 check_running_as(RUNNING_AS_ROOT);
223 initgroups(CLIENT_LOGIN, get_client_gid());
224 setgid(get_client_gid());
225 setegid(get_client_gid());
226 seteuid(get_client_uid());
228 check_running_as(RUNNING_AS_CLIENT_LOGIN);
231 erroutput_type = (ERR_INTERACTIVE|ERR_SYSLOG);
234 * ad-hoc argument parsing
236 * We accept -auth=[authentication type]
240 * We also add a list of services that amandad can launch
243 in = 0; out = 1; /* default to stdin/stdout */
245 for (i = 1; i < argc; i++) {
247 * accept -krb4 as an alias for -auth=krb4 (for compatibility)
249 if (strcmp(argv[i], "-krb4") == 0) {
250 argv[i] = "-auth=krb4";
256 * Get a driver for a security type specified after -auth=
258 else if (strncmp(argv[i], "-auth=", strlen("-auth=")) == 0) {
259 argv[i] += strlen("-auth=");
260 secdrv = security_getdriver(argv[i]);
262 if (secdrv == NULL) {
263 error(_("no driver for security type '%s'\n"), argv[i]);
270 * If -no-exit is specified, always run even after requests have
273 else if (strcmp(argv[i], "-no-exit") == 0) {
279 * Allow us to directly bind to a udp port for debugging.
280 * This may only apply to some security types.
282 else if (strncmp(argv[i], "-udp=", strlen("-udp=")) == 0) {
284 struct sockaddr_in6 sin;
286 struct sockaddr_in sin;
289 argv[i] += strlen("-udp=");
291 in = out = socket(AF_INET6, SOCK_DGRAM, 0);
293 in = out = socket(AF_INET, SOCK_DGRAM, 0);
296 error(_("can't create dgram socket: %s\n"), strerror(errno));
300 r = setsockopt(in, SOL_SOCKET, SO_REUSEADDR,
301 (void *)&on, (socklen_t_equiv)sizeof(on));
303 dbprintf(_("amandad: setsockopt(SO_REUSEADDR) failed: %s\n"),
309 sin.sin6_family = (sa_family_t)AF_INET6;
310 sin.sin6_addr = in6addr_any;
311 sin.sin6_port = (in_port_t)htons((in_port_t)atoi(argv[i]));
313 sin.sin_family = (sa_family_t)AF_INET;
314 sin.sin_addr.s_addr = INADDR_ANY;
315 sin.sin_port = (in_port_t)htons((in_port_t)atoi(argv[i]));
317 if (bind(in, (struct sockaddr *)&sin, (socklen_t_equiv)sizeof(sin)) < 0) {
318 error(_("can't bind to port %d: %s\n"), atoi(argv[i]),
324 * Ditto for tcp ports.
326 else if (strncmp(argv[i], "-tcp=", strlen("-tcp=")) == 0) {
328 struct sockaddr_in6 sin;
330 struct sockaddr_in sin;
335 argv[i] += strlen("-tcp=");
337 sock = socket(AF_INET6, SOCK_STREAM, 0);
339 sock = socket(AF_INET, SOCK_STREAM, 0);
342 error(_("can't create tcp socket: %s\n"), strerror(errno));
346 r = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
347 (void *)&on, (socklen_t_equiv)sizeof(on));
349 dbprintf(_("amandad: setsockopt(SO_REUSEADDR) failed: %s\n"),
354 sin.sin6_family = (sa_family_t)AF_INET6;
355 sin.sin6_addr = in6addr_any;
356 sin.sin6_port = (in_port_t)htons((in_port_t)atoi(argv[i]));
358 sin.sin_family = (sa_family_t)AF_INET;
359 sin.sin_addr.s_addr = INADDR_ANY;
360 sin.sin_port = (in_port_t)htons((in_port_t)atoi(argv[i]));
362 if (bind(sock, (struct sockaddr *)&sin, (socklen_t_equiv)sizeof(sin)) < 0) {
363 error(_("can't bind to port %d: %s\n"), atoi(argv[i]),
368 n = (socklen_t_equiv)sizeof(sin);
369 in = out = accept(sock, (struct sockaddr *)&sin, &n);
372 * It must be a service name
375 /* clear all services */
377 for (j = 0; j < (int)NSERVICES; j++)
378 services[j].active = 0;
382 if(strcmp(argv[i],"amdump") == 0) {
383 services[0].active = 1;
384 services[1].active = 1;
385 services[2].active = 1;
386 services[3].active = 1;
389 for (j = 0; j < (int)NSERVICES; j++)
390 if (strcmp(services[j].name, argv[i]) == 0)
392 if (j == (int)NSERVICES) {
393 dbprintf(_("%s: invalid service\n"), argv[i]);
396 services[j].active = 1;
402 * If no security type specified, use BSD
404 if (secdrv == NULL) {
405 secdrv = security_getdriver("BSD");
407 if (secdrv == NULL) {
408 error(_("no driver for default security type 'BSD'\n"));
413 if(strcasecmp(auth, "rsh") == 0 ||
414 strcasecmp(auth, "ssh") == 0 ||
415 strcasecmp(auth, "bsdtcp") == 0) {
421 if (strcasecmp(auth, "krb5") != 0) {
422 error(_("Amanda must be run as user '%s' when using '%s' authetication"),
426 if (strcasecmp(auth, "krb5") == 0) {
427 error(_("Amanda must be run as user 'root' when using 'krb5' authetication"));
436 dbprintf(_("version %s\n"), version());
437 for (i = 0; version_info[i] != NULL; i++) {
438 dbprintf(" %s", version_info[i]);
441 if (! (argc >= 1 && argv != NULL && argv[0] != NULL)) {
442 dbprintf(_("WARNING: argv[0] not defined: check inetd.conf\n"));
445 /* krb5 require the euid to be 0 */
446 if (strcasecmp(auth, "krb5") == 0) {
451 * Schedule to call protocol_accept() when new security handles
452 * are created on stdin.
454 security_accept(secdrv, amandad_get_security_conf, in, out, protocol_accept, NULL);
457 * Schedule an event that will try to exit every 30 seconds if there
458 * are no requests outstanding.
461 (void)event_register((event_id_t)30, EV_TIME, exit_check, &no_exit);
464 * Call event_loop() with an arg of 0, telling it to block until all
465 * events are completed.
476 * This runs periodically and checks to see if we have any active services
477 * still running. If we don't, then we quit.
485 assert(cookie != NULL);
486 no_exit = *(int *)cookie;
489 * If things are still running, then don't exit.
491 if (serviceq.qlength > 0)
495 * If the caller asked us to never exit, then we're done
505 * Handles new incoming protocol handles. This is a callback for
506 * security_accept(), which gets called when new handles are detected.
510 security_handle_t * handle,
514 struct active_service *as;
515 char *pktbody, *tok, *service, *arguments;
516 char *service_path = NULL;
522 * If handle is NULL, then the connection is closed.
529 * If pkt is NULL, then there was a problem with the new connection.
532 dbprintf(_("accept error: %s\n"), security_geterror(handle));
533 pkt_init(&pkt_out, P_NAK, "ERROR %s\n", security_geterror(handle));
534 do_sendpkt(handle, &pkt_out);
535 amfree(pkt_out.body);
536 security_close(handle);
540 dbprintf(_("accept recv %s pkt:\n<<<<<\n%s>>>>>\n"),
541 pkt_type2str(pkt->type), pkt->body);
544 * If this is not a REQ packet, just forget about it.
546 if (pkt->type != P_REQ) {
547 dbprintf(_("received unexpected %s packet:\n<<<<<\n%s>>>>>\n\n"),
548 pkt_type2str(pkt->type), pkt->body);
549 security_close(handle);
553 pktbody = service = arguments = NULL;
557 * Parse out the service and arguments
560 pktbody = stralloc(pkt->body);
562 tok = strtok(pktbody, " ");
565 if (strcmp(tok, "SERVICE") != 0)
568 tok = strtok(NULL, " \n");
571 service = stralloc(tok);
573 /* we call everything else 'arguments' */
574 tok = strtok(NULL, "");
577 arguments = stralloc(tok);
579 /* see if it's one we allow */
580 for (i = 0; i < (int)NSERVICES; i++)
581 if (services[i].active == 1 && strcmp(services[i].name, service) == 0)
583 if (i == (int)NSERVICES) {
584 dbprintf(_("%s: invalid service\n"), service);
585 pkt_init(&pkt_out, P_NAK, _("ERROR %s: invalid service, add '%s' as argument to amandad\n"), service, service);
589 service_path = vstralloc(amlibexecdir, "/", service, versionsuffix(), NULL);
590 if (access(service_path, X_OK) < 0) {
591 dbprintf(_("can't execute %s: %s\n"), service_path, strerror(errno));
592 pkt_init(&pkt_out, P_NAK,
593 _("ERROR execute access to \"%s\" denied\n"),
598 /* see if its already running */
599 for (as = TAILQ_FIRST(&serviceq.tailq); as != NULL;
600 as = TAILQ_NEXT(as, tq)) {
601 if (strcmp(as->cmd, service_path) == 0 &&
602 strcmp(as->arguments, arguments) == 0) {
603 dbprintf(_("%s %s: already running, acking req\n"),
605 pkt_init_empty(&pkt_out, P_ACK);
606 goto send_pkt_out_no_delete;
611 * create a new service instance, and send the arguments down
614 dbprintf(_("creating new service: %s\n%s\n"), service, arguments);
615 as = service_new(handle, service_path, arguments);
616 if (writebuf(as, arguments, strlen(arguments)) < 0) {
617 const char *errmsg = strerror(errno);
618 dbprintf(_("error sending arguments to %s: %s\n"), service, errmsg);
619 pkt_init(&pkt_out, P_NAK, _("ERROR error writing arguments to %s: %s\n"),
627 amfree(service_path);
631 * Move to the sendack state, and start up the state
634 as->state = s_sendack;
635 state_machine(as, A_START, NULL);
639 pkt_init(&pkt_out, P_NAK, _("ERROR invalid REQ\n"));
640 dbprintf(_("received invalid %s packet:\n<<<<<\n%s>>>>>\n\n"),
641 pkt_type2str(pkt->type), pkt->body);
646 send_pkt_out_no_delete:
648 amfree(service_path);
651 do_sendpkt(handle, &pkt_out);
652 security_close(handle);
653 amfree(pkt_out.body);
657 * Handles incoming protocol packets. Routes responses to the proper
662 struct active_service * as,
670 amandad_debug(1, _("state_machine: %p entering\n"), as);
672 curstate = as->state;
673 amandad_debug(1, _("state_machine: %p curstate=%s action=%s\n"), as,
674 state2str(curstate), action2str(action));
675 retaction = (*curstate)(as, action, pkt);
676 amandad_debug(1, _("state_machine: %p curstate=%s returned %s (nextstate=%s)\n"),
677 as, state2str(curstate), action2str(retaction),
678 state2str(as->state));
682 * State has queued up and is now blocking on input.
685 amandad_debug(1, _("state_machine: %p leaving (A_PENDING)\n"), as);
689 * service has switched states. Loop.
695 * state has determined that the packet it received was bogus.
696 * Send a nak, and return.
699 dbprintf(_("received unexpected %s packet\n"),
700 pkt_type2str(pkt->type));
701 dbprintf(_("<<<<<\n%s----\n\n"), pkt->body);
702 pkt_init(&nak, P_NAK, _("ERROR unexpected packet type %s\n"),
703 pkt_type2str(pkt->type));
704 do_sendpkt(as->security_handle, &nak);
706 security_recvpkt(as->security_handle, protocol_recv, as, -1);
707 amandad_debug(1, _("state_machine: %p leaving (A_SENDNAK)\n"), as);
711 * Service is done. Remove it and finish.
714 amandad_debug(1, _("state_machine: %p leaving (A_FINISH)\n"), as);
727 * This state just sends an ack. After that, we move to the repwait
728 * state to wait for REP data to arrive from the subprocess.
732 struct active_service * as,
738 (void)action; /* Quiet unused parameter warning */
739 (void)pkt; /* Quiet unused parameter warning */
741 pkt_init_empty(&ack, P_ACK);
742 if (do_sendpkt(as->security_handle, &ack) < 0) {
743 dbprintf(_("error sending ACK: %s\n"),
744 security_geterror(as->security_handle));
751 * move to the repwait state
752 * Setup a listener for data on the reply fd, but also
753 * listen for packets over the wire, as the server may
754 * poll us if we take a long time.
755 * Setup a timeout that will fire if it takes too long to
758 as->state = s_repwait;
759 as->ev_repfd = event_register((event_id_t)as->repfd, EV_READFD, repfd_recv, as);
760 as->ev_reptimeout = event_register(REP_TIMEOUT, EV_TIME,
762 security_recvpkt(as->security_handle, protocol_recv, as, -1);
767 * This is the repwait state. We have responded to the initial REQ with
768 * an ACK, and we are now waiting for the process we spawned to pass us
769 * data to send in a REP.
773 struct active_service * as,
787 * We normally shouldn't receive any packets while waiting
788 * for our REP data, but in some cases we do.
790 if (action == A_RECVPKT) {
793 * Another req for something that's running. Just send an ACK
794 * and go back and wait for more data.
796 if (pkt->type == P_REQ) {
797 dbprintf(_("received dup P_REQ packet, ACKing it\n"));
798 amfree(as->rep_pkt.body);
799 pkt_init_empty(&as->rep_pkt, P_ACK);
800 do_sendpkt(as->security_handle, &as->rep_pkt);
801 security_recvpkt(as->security_handle, protocol_recv, as, -1);
804 /* something unexpected. Nak it */
808 if (action == A_TIMEOUT) {
809 amfree(as->rep_pkt.body);
810 pkt_init(&as->rep_pkt, P_NAK, _("ERROR timeout on reply pipe\n"));
811 dbprintf(_("%s timed out waiting for REP data\n"), as->cmd);
812 do_sendpkt(as->security_handle, &as->rep_pkt);
816 assert(action == A_RECVREP);
817 if(as->bufsize == 0) {
818 as->bufsize = NETWORK_BLOCK_BYTES;
819 as->repbuf = alloc(as->bufsize);
823 n = read(as->repfd, as->repbuf + as->repbufsize,
824 as->bufsize - as->repbufsize - 1);
825 } while ((n < 0) && ((errno == EINTR) || (errno == EAGAIN)));
827 const char *errstr = strerror(errno);
828 dbprintf(_("read error on reply pipe: %s\n"), errstr);
829 amfree(as->rep_pkt.body);
830 pkt_init(&as->rep_pkt, P_NAK, _("ERROR read error on reply pipe: %s\n"),
832 do_sendpkt(as->security_handle, &as->rep_pkt);
836 /* If end of service, wait for process status */
839 pid = waitpid(as->pid, &retstat, WNOHANG);
840 while (t<5 && pid == 0) {
843 pid = waitpid(as->pid, &retstat, WNOHANG);
848 if (! WIFEXITED(retstat)) {
850 code = WTERMSIG(retstat);
851 } else if (WEXITSTATUS(retstat) != 0) {
853 code = WEXITSTATUS(retstat);
856 dbprintf(_("service %s failed: pid %u exited with %s %d\n"),
857 (as->cmd)?as->cmd:_("??UNKONWN??"),
861 _("ERROR service %s failed: pid %u exited with %s %d\n"),
862 (as->cmd)?as->cmd:_("??UNKONWN??"), (unsigned)as->pid,
864 if (as->repbufsize + strlen(msg) >= (as->bufsize - 1)) {
866 repbuf_temp = alloc(as->bufsize);
867 memcpy(repbuf_temp, as->repbuf, as->repbufsize + 1);
869 as->repbuf = repbuf_temp;
871 strcpy(as->repbuf + as->repbufsize, msg);
872 as->repbufsize += strlen(msg);
878 * If we got some data, go back and wait for more, or EOF. Nul terminate
881 as->repbuf[n + as->repbufsize] = '\0';
884 if(as->repbufsize >= (as->bufsize - 1)) {
886 repbuf_temp = alloc(as->bufsize);
887 memcpy(repbuf_temp, as->repbuf, as->repbufsize + 1);
889 as->repbuf = repbuf_temp;
891 else if(as->send_partial_reply) {
892 amfree(as->rep_pkt.body);
893 pkt_init(&as->rep_pkt, P_PREP, "%s", as->repbuf);
894 do_sendpkt(as->security_handle, &as->rep_pkt);
895 amfree(as->rep_pkt.body);
896 pkt_init_empty(&as->rep_pkt, P_REP);
903 * If we got 0, then we hit EOF. Process the data and release
908 assert(as->ev_repfd != NULL);
909 event_release(as->ev_repfd);
912 assert(as->ev_reptimeout != NULL);
913 event_release(as->ev_reptimeout);
914 as->ev_reptimeout = NULL;
916 as->state = s_processrep;
922 * After we have read in all of the rep data, we process it and send
923 * it out as a REP packet.
927 struct active_service * as,
933 (void)action; /* Quiet unused parameter warning */
934 (void)pkt; /* Quiet unused parameter warning */
937 * Copy the rep lines into the outgoing packet.
939 * If this line is a CONNECT, translate it
940 * Format is "CONNECT <tag> <handle> <tag> <handle> etc...
943 * CONNECT DATA 4 MESG 5 INDEX 6
945 * The tags are arbitrary. The handles are in the DATA_FD pool.
946 * We need to map these to security streams and pass them back
947 * to the amanda server. If the handle is -1, then we don't map.
949 if (strncmp_const(as->repbuf,"KENCRYPT\n") == 0) {
950 amandad_kencrypt = KENCRYPT_WILL_DO;
951 repbuf = stralloc(as->repbuf + 9);
953 repbuf = stralloc(as->repbuf);
955 amfree(as->rep_pkt.body);
956 pkt_init_empty(&as->rep_pkt, P_REP);
957 tok = strtok(repbuf, " ");
960 if (strcmp(tok, "CONNECT") == 0) {
961 char *line, *nextbuf;
963 /* Save the entire line */
964 line = strtok(NULL, "\n");
965 /* Save the buf following the line */
966 nextbuf = strtok(NULL, "");
968 if (line == NULL || nextbuf == NULL)
971 pkt_cat(&as->rep_pkt, "CONNECT");
973 /* loop over the id/handle pairs */
976 tok = strtok(line, " ");
977 line = NULL; /* keep working from line */
980 pkt_cat(&as->rep_pkt, " %s", tok);
983 tok = strtok(NULL, " \n");
986 /* convert the handle into something the server can process */
987 pkt_cat(&as->rep_pkt, " %d", allocstream(as, atoi(tok)));
989 pkt_cat(&as->rep_pkt, "\n%s", nextbuf);
992 pkt_cat(&as->rep_pkt, "%s", as->repbuf);
996 * We've setup our REP packet in as->rep_pkt. Now move to the transmission
999 as->state = s_sendrep;
1000 as->repretry = getconf_int(CNF_REP_TRIES);
1002 return (A_CONTINUE);
1006 * This is the state where we send the REP we just collected from our child.
1010 struct active_service * as,
1014 (void)action; /* Quiet unused parameter warning */
1015 (void)pkt; /* Quiet unused parameter warning */
1018 * Transmit it and move to the ack state.
1020 do_sendpkt(as->security_handle, &as->rep_pkt);
1021 security_recvpkt(as->security_handle, protocol_recv, as, ACK_TIMEOUT);
1022 as->state = s_ackwait;
1027 * This is the state in which we wait for the server to ACK the REP
1032 struct active_service * as,
1036 struct datafd_handle *dh;
1040 * If we got a timeout, try again, but eventually give up.
1042 if (action == A_TIMEOUT) {
1043 if (--as->repretry > 0) {
1044 as->state = s_sendrep;
1045 return (A_CONTINUE);
1047 dbprintf(_("timeout waiting for ACK for our REP\n"));
1050 amandad_debug(1, _("received ACK, now opening streams\n"));
1052 assert(action == A_RECVPKT);
1054 if (pkt->type == P_REQ) {
1055 dbprintf(_("received dup P_REQ packet, resending REP\n"));
1056 as->state = s_sendrep;
1057 return (A_CONTINUE);
1060 if (pkt->type != P_ACK)
1063 if (amandad_kencrypt == KENCRYPT_WILL_DO) {
1064 amandad_kencrypt = KENCRYPT_YES;
1068 * Got the ack, now open the pipes
1070 for (dh = &as->data[0]; dh < &as->data[DATA_FD_COUNT]; dh++) {
1071 if (dh->netfd == NULL)
1073 if (security_stream_accept(dh->netfd) < 0) {
1074 dbprintf(_("stream %td accept failed: %s\n"),
1075 dh - &as->data[0], security_geterror(as->security_handle));
1076 security_stream_close(dh->netfd);
1080 /* setup an event for reads from it */
1081 dh->ev_read = event_register((event_id_t)dh->fd_read, EV_READFD,
1082 process_readnetfd, dh);
1084 security_stream_read(dh->netfd, process_writenetfd, dh);
1089 * Pipes are open, so auth them. Count them at the same time.
1091 for (npipes = 0, dh = &as->data[0]; dh < &as->data[DATA_FD_COUNT]; dh++) {
1092 if (dh->netfd == NULL)
1094 if (security_stream_auth(dh->netfd) < 0) {
1095 security_stream_close(dh->netfd);
1097 event_release(dh->ev_read);
1098 event_release(dh->ev_write);
1100 dh->ev_write = NULL;
1107 * If no pipes are open, then we're done. Otherwise, just start running.
1108 * The event handlers on all of the pipes will take it from here.
1110 amandad_debug(1, _("at end of s_ackwait, npipes is %d\n"), npipes);
1114 security_close(as->security_handle);
1115 as->security_handle = NULL;
1121 * Called when a repfd has received data
1127 struct active_service *as = cookie;
1130 assert(as->ev_repfd != NULL);
1132 state_machine(as, A_RECVREP, NULL);
1136 * Called when a repfd has timed out
1142 struct active_service *as = cookie;
1145 assert(as->ev_reptimeout != NULL);
1147 state_machine(as, A_TIMEOUT, NULL);
1151 * Called when a handle has received data
1157 security_status_t status)
1159 struct active_service *as = cookie;
1165 dbprintf(_("received %s pkt:\n<<<<<\n%s>>>>>\n"),
1166 pkt_type2str(pkt->type), pkt->body);
1167 state_machine(as, A_RECVPKT, pkt);
1170 dbprintf(_("timeout\n"));
1171 state_machine(as, A_TIMEOUT, NULL);
1174 dbprintf(_("receive error: %s\n"),
1175 security_geterror(as->security_handle));
1181 * This is a generic relay function that just reads data from one of
1182 * the process's pipes and passes it up the equivalent security_stream_t
1189 struct datafd_handle *dh = cookie;
1190 struct active_service *as = dh->as;
1196 n = read(dh->fd_read, as->databuf, SIZEOF(as->databuf));
1197 } while ((n < 0) && ((errno == EINTR) || (errno == EAGAIN)));
1203 pkt_init(&nak, P_NAK, _("A ERROR data descriptor %d broken: %s\n"),
1204 dh->fd_read, strerror(errno));
1208 * Process has closed the pipe. Just remove this event handler.
1209 * If all pipes are closed, shut down this service.
1212 event_release(dh->ev_read);
1214 if(dh->ev_write == NULL) {
1215 security_stream_close(dh->netfd);
1218 for (dh = &as->data[0]; dh < &as->data[DATA_FD_COUNT]; dh++) {
1219 if (dh->netfd != NULL)
1225 if (security_stream_write(dh->netfd, as->databuf, (size_t)n) < 0) {
1226 /* stream has croaked */
1227 pkt_init(&nak, P_NAK, _("ERROR write error on stream %d: %s\n"),
1228 security_stream_id(dh->netfd),
1229 security_stream_geterror(dh->netfd));
1235 do_sendpkt(as->security_handle, &nak);
1241 * This is a generic relay function that just read data from one of
1242 * the security_stream_t and passes it up the equivalent process's pipes
1250 struct datafd_handle *dh;
1252 assert(cookie != NULL);
1255 if (dh->fd_write <= 0) {
1256 dbprintf(_("process_writenetfd: dh->fd_write <= 0\n"));
1257 } else if (size > 0) {
1258 fullwrite(dh->fd_write, buf, (size_t)size);
1259 security_stream_read(dh->netfd, process_writenetfd, dh);
1262 aclose(dh->fd_write);
1268 * Convert a local stream handle (DATA_FD...) into something that
1269 * can be sent to the amanda server.
1271 * Returns a number that should be sent to the server in the REP packet.
1275 struct active_service * as,
1278 struct datafd_handle *dh;
1280 /* if the handle is -1, then we don't bother */
1284 /* make sure the handle's kosher */
1285 if (handle < DATA_FD_OFFSET || handle >= DATA_FD_OFFSET + DATA_FD_COUNT)
1288 /* get a pointer into our handle array */
1289 dh = &as->data[handle - DATA_FD_OFFSET];
1291 /* make sure we're not already using the net handle */
1292 if (dh->netfd != NULL)
1295 /* allocate a stream from the security layer and return */
1296 dh->netfd = security_stream_server(as->security_handle);
1297 if (dh->netfd == NULL) {
1298 dbprintf(_("couldn't open stream to server: %s\n"),
1299 security_geterror(as->security_handle));
1304 * convert the stream into a numeric id that can be sent to the
1307 return (security_stream_id(dh->netfd));
1311 * Create a new service instance
1313 static struct active_service *
1315 security_handle_t * security_handle,
1317 const char * arguments)
1320 int data_read[DATA_FD_COUNT + 1][2];
1321 int data_write[DATA_FD_COUNT + 1][2];
1322 struct active_service *as;
1326 assert(security_handle != NULL);
1327 assert(cmd != NULL);
1328 assert(arguments != NULL);
1330 /* a plethora of pipes */
1331 for (i = 0; i < DATA_FD_COUNT + 1; i++) {
1332 if (pipe(data_read[i]) < 0) {
1333 error(_("pipe: %s\n"), strerror(errno));
1336 if (pipe(data_write[i]) < 0) {
1337 error(_("pipe: %s\n"), strerror(errno));
1342 switch(pid = fork()) {
1344 error(_("could not fork service %s: %s\n"), cmd, strerror(errno));
1348 * The parent. Close the far ends of our pipes and return.
1350 as = alloc(SIZEOF(*as));
1351 as->cmd = stralloc(cmd);
1352 as->arguments = stralloc(arguments);
1353 as->security_handle = security_handle;
1356 as->send_partial_reply = 0;
1357 if(strcmp(cmd+(strlen(cmd)-8), "sendsize") == 0) {
1358 g_option_t *g_options;
1359 char *option_str, *p;
1361 option_str = stralloc(as->arguments+8);
1362 p = strchr(option_str,'\n');
1365 g_options = parse_g_options(option_str, 1);
1366 if(am_has_feature(g_options->features, fe_partial_estimate)) {
1367 as->send_partial_reply = 1;
1369 free_g_options(g_options);
1373 /* write to the request pipe */
1374 aclose(data_read[0][0]);
1375 as->reqfd = data_read[0][1];
1378 * read from the reply pipe
1380 as->repfd = data_write[0][0];
1381 aclose(data_write[0][1]);
1382 as->ev_repfd = NULL;
1387 as->rep_pkt.body = NULL;
1390 * read from the rest of the general-use pipes
1391 * (netfds are opened as the client requests them)
1393 for (i = 0; i < DATA_FD_COUNT; i++) {
1394 aclose(data_read[i + 1][1]);
1395 aclose(data_write[i + 1][0]);
1396 as->data[i].fd_read = data_read[i + 1][0];
1397 as->data[i].fd_write = data_write[i + 1][1];
1398 as->data[i].ev_read = NULL;
1399 as->data[i].ev_write = NULL;
1400 as->data[i].netfd = NULL;
1401 as->data[i].as = as;
1404 /* add it to the service queue */
1405 /* increment the active service count */
1406 TAILQ_INSERT_TAIL(&serviceq.tailq, as, tq);
1412 * The child. Put our pipes in their advertised locations
1417 * The data stream is stdin in the new process
1419 if (dup2(data_read[0][0], 0) < 0) {
1420 error(_("dup %d to %d failed: %s\n"), data_read[0][0], 0,
1424 aclose(data_read[0][0]);
1425 aclose(data_read[0][1]);
1428 * The reply stream is stdout
1430 if (dup2(data_write[0][1], 1) < 0) {
1431 error(_("dup %d to %d failed: %s\n"), data_write[0][1], 1,
1434 aclose(data_write[0][0]);
1435 aclose(data_write[0][1]);
1437 for (i = 0; i < DATA_FD_COUNT; i++) {
1438 aclose(data_read[i + 1][0]);
1439 aclose(data_write[i + 1][1]);
1443 * Make sure they are not open in the range DATA_FD_OFFSET to
1444 * DATA_FD_OFFSET + DATA_FD_COUNT*2 - 1
1446 for (i = 0; i < DATA_FD_COUNT; i++) {
1447 while(data_read[i + 1][1] >= DATA_FD_OFFSET &&
1448 data_read[i + 1][1] <= DATA_FD_OFFSET + DATA_FD_COUNT*2 - 1) {
1449 newfd = dup(data_read[i + 1][1]);
1451 error(_("Can't dup out off DATA_FD range"));
1452 data_read[i + 1][1] = newfd;
1454 while(data_write[i + 1][0] >= DATA_FD_OFFSET &&
1455 data_write[i + 1][0] <= DATA_FD_OFFSET + DATA_FD_COUNT*2 - 1) {
1456 newfd = dup(data_write[i + 1][0]);
1458 error(_("Can't dup out off DATA_FD range"));
1459 data_write[i + 1][0] = newfd;
1462 for (i = 0; i < DATA_FD_COUNT*2; i++)
1463 close(DATA_FD_OFFSET + i);
1466 * The rest start at the offset defined in amandad.h, and continue
1467 * through the internal defined.
1469 for (i = 0; i < DATA_FD_COUNT; i++) {
1470 if (dup2(data_read[i + 1][1], i*2 + DATA_FD_OFFSET) < 0) {
1471 error(_("dup %d to %d failed: %s\n"), data_read[i + 1][1],
1472 i + DATA_FD_OFFSET, strerror(errno));
1474 aclose(data_read[i + 1][1]);
1476 if (dup2(data_write[i + 1][0], i*2 + 1 + DATA_FD_OFFSET) < 0) {
1477 error(_("dup %d to %d failed: %s\n"), data_write[i + 1][0],
1478 i + DATA_FD_OFFSET, strerror(errno));
1480 aclose(data_write[i + 1][0]);
1483 /* close all unneeded fd */
1484 close(STDERR_FILENO);
1485 debug_dup_stderr_to_debug();
1486 safe_fd(DATA_FD_OFFSET, DATA_FD_COUNT*2);
1488 execle(cmd, cmd, "amandad", auth, (char *)NULL, safe_env());
1489 error(_("could not exec service %s: %s\n"), cmd, strerror(errno));
1496 * Unallocate a service instance
1500 struct active_service * as)
1503 struct datafd_handle *dh;
1505 amandad_debug(1, _("closing service: %s\n"),
1506 (as->cmd)?as->cmd:_("??UNKONWN??"));
1510 assert(as->cmd != NULL);
1513 assert(as->arguments != NULL);
1514 amfree(as->arguments);
1516 if (as->reqfd != -1)
1518 if (as->repfd != -1)
1521 if (as->ev_repfd != NULL)
1522 event_release(as->ev_repfd);
1523 if (as->ev_reptimeout != NULL)
1524 event_release(as->ev_reptimeout);
1526 for (i = 0; i < DATA_FD_COUNT; i++) {
1529 aclose(dh->fd_read);
1530 aclose(dh->fd_write);
1532 if (dh->netfd != NULL)
1533 security_stream_close(dh->netfd);
1535 if (dh->ev_read != NULL)
1536 event_release(dh->ev_read);
1537 if (dh->ev_write != NULL)
1538 event_release(dh->ev_write);
1541 if (as->security_handle != NULL)
1542 security_close(as->security_handle);
1544 assert(as->pid > 0);
1545 kill(as->pid, SIGTERM);
1546 waitpid(as->pid, NULL, WNOHANG);
1548 TAILQ_REMOVE(&serviceq.tailq, as, tq);
1549 assert(serviceq.qlength > 0);
1553 amfree(as->arguments);
1555 amfree(as->rep_pkt.body);
1558 if(exit_on_qlength == 0 && serviceq.qlength == 0) {
1565 * Like 'fullwrite', but does the work in a child process so pipelines
1570 struct active_service * as,
1577 switch (pid=fork()) {
1582 waitpid(pid, NULL, WNOHANG);
1583 return 0; /* this is the parent */
1585 case 0: /* this is the child */
1587 writesize = fullwrite(as->reqfd, bufp, size);
1588 exit(writesize != (ssize_t)size);
1596 security_handle_t * handle,
1599 dbprintf(_("sending %s pkt:\n<<<<<\n%s>>>>>\n"),
1600 pkt_type2str(pkt->type), pkt->body);
1602 return security_sendpkt(handle, pkt);
1608 * Convert a state into a string
1614 static const struct {
1618 #define X(state) { state, stringize(state) }
1628 for (i = 0; i < (int)(sizeof(states) / sizeof(states[0])); i++)
1629 if (state == states[i].state)
1630 return (states[i].str);
1631 return (_("INVALID STATE"));
1635 * Convert an action into a string
1641 static const struct {
1645 #define X(action) { action, stringize(action) }
1658 for (i = 0; i < (int)(sizeof(actions) / sizeof(actions[0])); i++)
1659 if (action == actions[i].action)
1660 return (actions[i].str);
1661 return (_("UNKNOWN ACTION"));
1665 amandad_get_security_conf(
1669 (void)arg; /* Quiet unused parameter warning */
1671 if (!string || !*string)
1674 if (strcmp(string, "kencrypt")==0) {
1675 if (amandad_kencrypt == KENCRYPT_YES)