Line data Source code
1 : #include "../burp.h"
2 : #include "../alloc.h"
3 : #include "../asfd.h"
4 : #include "../async.h"
5 : #include "../cmd.h"
6 : #include "../cntr.h"
7 : #include "../conf.h"
8 : #include "../handy.h"
9 : #include "../iobuf.h"
10 : #include "../log.h"
11 : #include "../prepend.h"
12 : #include "../run_script.h"
13 : #include "extra_comms.h"
14 : #include "monitor/status_server.h"
15 : #include "run_action.h"
16 :
17 : static struct asfd *wasfd=NULL;
18 :
19 45 : int write_status(enum cntr_status cntr_status,
20 : const char *path, struct cntr *cntr)
21 : {
22 45 : time_t now=0;
23 45 : time_t diff=0;
24 : static time_t lasttime=0;
25 : static size_t l=0;
26 : static struct iobuf *wbuf=NULL;
27 :
28 45 : if(!wasfd) return 0;
29 :
30 : // Only update every 2 seconds.
31 0 : now=time(NULL);
32 0 : diff=now-lasttime;
33 0 : if(diff<2)
34 : {
35 : // Might as well do this in case they fiddled their
36 : // clock back in time.
37 0 : if(diff<0) lasttime=now;
38 0 : return 0;
39 : }
40 0 : lasttime=now;
41 :
42 : // Only get a new string if we did not manage to write the previous
43 : // one.
44 0 : if(!l)
45 : {
46 0 : cntr->cntr_status=cntr_status;
47 0 : if(!(l=cntr_to_str(cntr, path))) goto error;
48 0 : if(!wbuf && !(wbuf=iobuf_alloc())) goto error;
49 0 : iobuf_set(wbuf, CMD_APPEND, cntr->str, l);
50 : }
51 :
52 0 : switch(wasfd->append_all_to_write_buffer(wasfd, wbuf))
53 : {
54 : case APPEND_OK:
55 0 : l=0; // Fall through.
56 : case APPEND_BLOCKED:
57 0 : return 0;
58 : default:
59 0 : break;
60 : }
61 : error:
62 0 : iobuf_free(&wbuf);
63 0 : return -1;
64 : }
65 :
66 0 : static int run_server_script(struct asfd *asfd,
67 : const char *pre_or_post,
68 : const char *script, struct strlist *script_arg,
69 : uint8_t notify, struct conf **cconfs, int backup_ret, int timer_ret)
70 : {
71 0 : int a=0;
72 0 : int ret=0;
73 0 : char *logbuf=NULL;
74 : const char *args[12];
75 0 : struct iobuf *rbuf=asfd->rbuf;
76 0 : const char *cname=get_string(cconfs[OPT_CNAME]);
77 :
78 0 : args[a++]=script;
79 0 : args[a++]=pre_or_post;
80 0 : args[a++]=rbuf->buf?rbuf->buf:"", // Action requested by client.
81 0 : args[a++]=cname;
82 0 : args[a++]=backup_ret?"1":"0", // Indicate success or failure.
83 : // Indicate whether the timer script said OK or not.
84 0 : args[a++]=timer_ret?"1":"0",
85 0 : args[a++]=NULL;
86 :
87 : // Do not have a client storage directory, so capture the
88 : // output in a buffer to pass to the notification script.
89 0 : if(run_script_to_buf(asfd, args, script_arg, cconfs, 1, 1, 0, &logbuf))
90 : {
91 : char msg[256];
92 : snprintf(msg, sizeof(msg),
93 : "server %s script %s returned an error",
94 0 : pre_or_post, script);
95 0 : log_and_send(asfd, msg);
96 0 : ret=-1;
97 0 : if(!notify) goto end;
98 :
99 0 : a=0;
100 0 : args[a++]=get_string(cconfs[OPT_N_FAILURE_SCRIPT]);
101 0 : args[a++]=cname;
102 : // magic - set basedir blank and the
103 : // notify script will know to get the content
104 : // from the next argument (usually storagedir)
105 0 : args[a++]=""; // usually basedir
106 0 : args[a++]=logbuf?logbuf:""; //usually storagedir
107 0 : args[a++]=""; // usually file
108 0 : args[a++]=""; // usually brv
109 0 : args[a++]=""; // usually warnings
110 0 : args[a++]=NULL;
111 0 : run_script(asfd, args, get_strlist(cconfs[OPT_N_FAILURE_ARG]),
112 0 : cconfs, 1, 1, 0);
113 : }
114 : end:
115 0 : if(logbuf) free(logbuf);
116 0 : return ret;
117 : }
118 :
119 0 : int child(struct async *as,
120 : int status_wfd, struct conf **confs, struct conf **cconfs)
121 : {
122 0 : int ret=-1;
123 0 : int srestore=0;
124 0 : int timer_ret=0;
125 0 : char *incexc=NULL;
126 : struct asfd *asfd;
127 0 : const char *confs_user=get_string(confs[OPT_USER]);
128 0 : const char *cconfs_user=get_string(cconfs[OPT_USER]);
129 0 : const char *confs_group=get_string(confs[OPT_GROUP]);
130 0 : const char *cconfs_group=get_string(cconfs[OPT_GROUP]);
131 0 : const char *s_script_pre=get_string(cconfs[OPT_S_SCRIPT_PRE]);
132 0 : const char *s_script_post=get_string(cconfs[OPT_S_SCRIPT_POST]);
133 :
134 : // If we are not a status server, we are a normal child - set up the
135 : // parent socket to write status to.
136 0 : if(status_wfd>0
137 0 : && !(wasfd=setup_asfd(as, "child status pipe", &status_wfd, NULL,
138 0 : ASFD_STREAM_STANDARD, ASFD_FD_CHILD_PIPE_WRITE, -1, cconfs)))
139 0 : goto end;
140 :
141 : /* Has to be before the chuser/chgrp stuff to allow clients to switch
142 : to different clients when both clients have different user/group
143 : settings. */
144 0 : if(extra_comms(as, &incexc, &srestore, confs, cconfs))
145 : {
146 0 : log_and_send(as->asfd, "running extra comms failed on server");
147 0 : goto end;
148 : }
149 :
150 : /* Now that the client conf is loaded, we might want to chuser or
151 : chgrp.
152 : The main process could have already done this, so we don't want
153 : to try doing it again if cconfs has the same values, because it
154 : will fail. */
155 0 : if( (!confs_user || (cconfs_user && strcmp(confs_user, cconfs_user)))
156 0 : ||(!confs_group ||(cconfs_group && strcmp(confs_group,cconfs_group))))
157 : {
158 0 : if(chuser_and_or_chgrp(cconfs_user, cconfs_group))
159 : {
160 : log_and_send(as->asfd,
161 0 : "chuser_and_or_chgrp failed on server");
162 0 : goto end;
163 : }
164 : }
165 :
166 0 : if(as->asfd->read(as->asfd)) goto end;
167 :
168 : // If this is a status server, run the status server.
169 0 : for(asfd=as->asfd; asfd; asfd=asfd->next)
170 : {
171 0 : if(asfd->fdtype!=ASFD_FD_CHILD_PIPE_READ) continue;
172 0 : ret=status_server(as, cconfs);
173 0 : goto end;
174 : }
175 :
176 0 : ret=0;
177 :
178 : // FIX THIS: Make the script components part of a struct, and just
179 : // pass in the correct struct. Same below.
180 0 : if(s_script_pre)
181 : ret=run_server_script(as->asfd, "pre",
182 : s_script_pre,
183 0 : get_strlist(cconfs[OPT_S_SCRIPT_PRE_ARG]),
184 0 : get_int(cconfs[OPT_S_SCRIPT_PRE_NOTIFY]),
185 0 : cconfs, ret, timer_ret);
186 :
187 0 : if(!ret)
188 0 : ret=run_action_server(as, incexc, srestore, &timer_ret, cconfs);
189 :
190 0 : if((!ret || get_int(cconfs[OPT_S_SCRIPT_POST_RUN_ON_FAIL]))
191 0 : && s_script_post)
192 : ret=run_server_script(as->asfd, "post",
193 : s_script_post,
194 0 : get_strlist(cconfs[OPT_S_SCRIPT_POST_ARG]),
195 0 : get_int(cconfs[OPT_S_SCRIPT_POST_NOTIFY]),
196 0 : cconfs, ret, timer_ret);
197 :
198 : end:
199 0 : return ret;
200 : }
|