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 "iobuf.h"
8 #include "log.h"
9 #include "strlist.h"
10 #include "times.h"
11 
12 const char *prog="unknown";
13 const char *prog_long="unknown";
14 
15 static struct fzp *logfzp=NULL;
16 // Start with all logging on, so that something is said when initial startup
17 // goes wrong - for example, reading the conf file.
18 static int do_syslog=1;
19 static int do_stdout=1;
20 static int do_progress_counter=1;
21 static int syslog_opened=0;
22 static int json=0;
23 
log_init(char * progname)24 void log_init(char *progname)
25 {
26 	prog_long=progname;
27 	if((prog=strrchr(progname, '/'))) prog++;
28 	else prog=progname;
29 }
30 
logp(const char * fmt,...)31 void logp(const char *fmt, ...)
32 {
33 #ifndef UTEST
34 	int pid;
35 	char buf[512]="";
36 	va_list ap;
37 	va_start(ap, fmt);
38 	vsnprintf(buf, sizeof(buf), fmt, ap);
39 	pid=(int)getpid();
40 	if(logfzp)
41 		fzp_printf(logfzp, "%s: %s[%d] %s",
42 			gettimenow(), prog, pid, buf);
43 	else
44 	{
45 		if(do_syslog)
46 			syslog(LOG_INFO, "%s", buf);
47 		if(do_stdout)
48 		{
49 			if(json)
50 			{
51 				char *cp;
52 				// To help programs parsing the monitor output,
53 				// log things with simple JSON.
54 				// So do simple character substitution to have
55 				// a better chance of valid JSON.
56 				for(cp=buf; *cp; cp++)
57 				{
58 					if(*cp=='"')
59 						*cp='\'';
60 					else if(!isprint(*cp))
61 						*cp='.';
62 				}
63 				fprintf(stdout, "{ \"logline\": \"%s\" }\n", buf);
64 			}
65 			else
66 				fprintf(stdout, "%s: %s[%d] %s",
67 					gettimenow(), prog, pid, buf);
68 		}
69 	}
70 	va_end(ap);
71 #endif
72 }
73 
logp_ssl_err(const char * fmt,...)74 void logp_ssl_err(const char *fmt, ...)
75 {
76 	char buf[512]="";
77 	va_list ap;
78 	va_start(ap, fmt);
79 	vsnprintf(buf, sizeof(buf), fmt, ap);
80 	va_end(ap);
81 	logp("%s", buf);
82 	if(logfzp) fzp_ERR_print_errors_fp(logfzp);
83 	else
84 	{
85 		if(do_syslog)
86 		{
87 			// FIX THIS: How to send to syslog?
88 			static BIO *bio_err=NULL;
89 			if(!bio_err) bio_err=BIO_new_fp(stderr, BIO_NOCLOSE);
90 			ERR_print_errors(bio_err);
91 		}
92 		if(do_stdout)
93 		{
94 			if(!json)
95 			{
96 				static BIO *bio_err=NULL;
97 				if(!bio_err) bio_err=BIO_new_fp(stdout,
98 					BIO_NOCLOSE);
99 				ERR_print_errors(bio_err);
100 			}
101 		}
102 	}
103 }
104 
105 // For the counters.
logc(const char * fmt,...)106 void logc(const char *fmt, ...)
107 {
108 	char buf[512]="";
109 	va_list ap;
110 	va_start(ap, fmt);
111 	vsnprintf(buf, sizeof(buf), fmt, ap);
112 	if(logfzp)
113 		fzp_printf(logfzp, "%s", buf); // for the server side
114 	else
115 	{
116 		if(do_progress_counter
117 		  && do_stdout)
118 			fprintf(stdout, "%s", buf);
119 	}
120 	va_end(ap);
121 }
122 
logfmt(const char * fmt,...)123 void logfmt(const char *fmt, ...)
124 {
125 #ifndef UTEST
126 	if(do_stdout)
127 	{
128 		char buf[512]="";
129 		va_list ap;
130 		va_start(ap, fmt);
131 		vsnprintf(buf, sizeof(buf), fmt, ap);
132 		fprintf(stdout, "%s", buf);
133 	}
134 #endif
135 }
136 
progname(void)137 const char *progname(void)
138 {
139 	return prog;
140 }
141 
log_fzp_set(const char * path,struct conf ** confs)142 int log_fzp_set(const char *path, struct conf **confs)
143 {
144 	fzp_close(&logfzp);
145 	if(path)
146 	{
147 		logp("Logging to %s\n", path);
148 		if(!(logfzp=fzp_open(path, "ab"))) return -1;
149 	}
150 	if(logfzp) fzp_setlinebuf(logfzp);
151 	do_syslog=get_int(confs[OPT_SYSLOG]);
152 	do_stdout=get_int(confs[OPT_STDOUT]);
153 	do_progress_counter=get_int(confs[OPT_PROGRESS_COUNTER]);
154 
155 	if(syslog_opened)
156 	{
157 		closelog();
158 		syslog_opened=0;
159 	}
160 	if(do_syslog)
161 	{
162 		openlog(prog, LOG_PID, LOG_USER);
163 		syslog_opened++;
164 	}
165 	return 0;
166 }
167 
log_fzp_set_direct(struct fzp * fzp)168 void log_fzp_set_direct(struct fzp *fzp)
169 {
170 	fzp_close(&logfzp);
171 	logfzp=fzp;
172 }
173 
log_out_of_memory(const char * function)174 void log_out_of_memory(const char *function)
175 {
176 	if(function) logp("out of memory in %s()\n", function);
177 	else logp("out of memory in unknown function\n");
178 }
179 
log_restore_settings(struct conf ** cconfs,int srestore)180 void log_restore_settings(struct conf **cconfs, int srestore)
181 {
182 	struct strlist *l;
183 	logp("Restore settings:\n");
184 	if(get_string(cconfs[OPT_ORIG_CLIENT]))
185 		logp("orig_client = '%s'\n",
186 			get_string(cconfs[OPT_ORIG_CLIENT]));
187 	if(get_string(cconfs[OPT_BACKUP]))
188 		logp("backup = '%s'\n",
189 			get_string(cconfs[OPT_BACKUP]));
190 	logp("restore_list = %s\n",
191 		get_string(cconfs[OPT_RESTORE_LIST])?"true":"false");
192 	if(srestore)
193 	{
194 		// This are unknown unless doing a server initiated restore.
195 		logp("overwrite = %d\n", get_int(cconfs[OPT_OVERWRITE]));
196 		logp("strip = %d\n", get_int(cconfs[OPT_STRIP]));
197 	}
198 	if(get_string(cconfs[OPT_RESTOREPREFIX]))
199 		logp("restoreprefix = '%s'\n",
200 			get_string(cconfs[OPT_RESTOREPREFIX]));
201 	if(get_string(cconfs[OPT_STRIP_FROM_PATH]))
202 		logp("stripfrompath = '%s'\n",
203 			get_string(cconfs[OPT_STRIP_FROM_PATH]));
204 	if(get_string(cconfs[OPT_REGEX]))
205 		logp("regex = '%s'\n", get_string(cconfs[OPT_REGEX]));
206 	for(l=get_strlist(cconfs[OPT_INCLUDE]); l; l=l->next)
207 		logp("include = '%s'\n", l->path);
208 }
209 
logm(struct asfd * asfd,struct conf ** confs,const char * fmt,...)210 int logm(struct asfd *asfd, struct conf **confs, const char *fmt, ...)
211 {
212 	int r=0;
213 	char buf[512]="";
214 	va_list ap;
215 	va_start(ap, fmt);
216 	vsnprintf(buf, sizeof(buf), fmt, ap);
217 	if(asfd && asfd->as->doing_estimate) printf("\nMESSAGE: %s", buf);
218 	else
219 	{
220 		if(asfd
221 		  && get_int(confs[OPT_MESSAGE])) // Backwards compatibility
222 			r=asfd->write_str(asfd, CMD_MESSAGE, buf);
223 		logp("MESSAGE: %s", buf);
224 	}
225 	va_end(ap);
226 	if(confs) cntr_add(get_cntr(confs), CMD_MESSAGE, 1);
227 	return r;
228 }
229 
logw(struct asfd * asfd,struct cntr * cntr,const char * fmt,...)230 int logw(struct asfd *asfd, struct cntr *cntr, const char *fmt, ...)
231 {
232 	int r=0;
233 	char buf[512]="";
234 	va_list ap;
235 	va_start(ap, fmt);
236 	vsnprintf(buf, sizeof(buf), fmt, ap);
237 	if(asfd
238 	  && asfd->as
239 	  && asfd->as->doing_estimate)
240 		printf("\nWARNING: %s", buf);
241 	else
242 	{
243 		if(asfd)
244 			r=asfd->write_str(asfd, CMD_WARNING, buf);
245 		logp("WARNING: %s", buf);
246 	}
247 	va_end(ap);
248 	cntr_add(cntr, CMD_WARNING, 1);
249 	return r;
250 }
251 
log_and_send(struct asfd * asfd,const char * msg)252 void log_and_send(struct asfd *asfd, const char *msg)
253 {
254 	logp("%s\n", msg);
255 	if(asfd)
256 		asfd->write_str(asfd, CMD_ERROR, msg);
257 }
258 
log_and_send_oom(struct asfd * asfd)259 void log_and_send_oom(struct asfd *asfd)
260 {
261 	char m[256]="";
262         snprintf(m, sizeof(m), "out of memory in %s()\n", __func__);
263         logp("%s", m);
264         if(asfd)
265 		asfd->write_str(asfd, CMD_ERROR, m);
266 }
267 
log_set_json(int value)268 void log_set_json(int value)
269 {
270 	json=value;
271 }
272 
log_oom_w(const char * func,const char * orig_func)273 void log_oom_w(const char *func, const char *orig_func)
274 {
275 	logp("out of memory in %s, called from %s\n", func, orig_func);
276 }
277 
log_incexcs_buf(const char * incexc)278 int log_incexcs_buf(const char *incexc)
279 {
280 	char *tok=NULL;
281 	char *copy=NULL;
282 	if(!incexc || !*incexc) return 0;
283 	if(!(copy=strdup_w(incexc, __func__)))
284 		return -1;
285 	if(!(tok=strtok(copy, "\n")))
286 	{
287 		logp("unable to parse server incexc\n");
288 		free_w(&copy);
289 		return -1;
290 	}
291 	do
292 	{
293 		logp("%s\n", tok);
294 	} while((tok=strtok(NULL, "\n")));
295 	free_w(&copy);
296 	return 0;
297 }
298 
log_recvd(struct iobuf * iobuf,struct cntr * cntr,int print)299 void log_recvd(struct iobuf *iobuf, struct cntr *cntr, int print)
300 {
301 	int l;
302 	const char *prefix="unset";
303 	switch(iobuf->cmd)
304 	{
305 		case CMD_MESSAGE: prefix="MESSAGE"; break;
306 		case CMD_WARNING: prefix="WARNING"; break;
307 		default: break;
308 	}
309 	// Strip any trailing newlines.
310 	for(l=iobuf->len-1; l>=0; l--)
311 	{
312 		if(iobuf->buf[l]!='\n')
313 			break;
314 		iobuf->buf[l]='\0';
315 	}
316 	logp("%s: %s\n", prefix, iobuf->buf);
317 	cntr_add(cntr, iobuf->cmd, print);
318 }
319