1 #include "xprobe.h"
2 #include <stdarg.h>
3 #include "interface.h"
4 #include "cmd_opts.h"
5 #include "xprobe_module.h"
6 #include "log.h"
7 
write(const char * fmt,...)8 int Log::write(const char *fmt, ...) {
9 	va_list va;
10 
11 	va_start(va, fmt);
12 	if (logopened)
13 		return vfprintf(ofile, fmt, va);
14 	else
15 		return 0;
16 }
17 
open()18 int Log::open() {
19 	if ((ofile = fopen(logfile.c_str(), "w")) == NULL) {
20 		ui->msg("fopen(): %s\n", strerror(errno));
21 		return 1;
22 	}
23 	logopened = true;
24 	return 0;
25 }
26 
log(unsigned int type,const char * fmt,...)27 int XML_Log::log(unsigned int type, const char *fmt, ...) {
28 	va_list varg;
29 	va_start(varg, fmt);
30 	if (!is_opened())
31 		return 0;
32 	switch(type) {
33 		case XPROBELOG_XP_SESS_START:
34 			write_tabs();
35 			tags_opened++;
36 			log_start(fmt, varg);
37 			break;
38 		case XPROBELOG_MSG_RUN:
39 			write_tabs();
40 			log_run(fmt, varg);
41 			break;
42 		case XPROBELOG_MOD_SESS_START:
43 			write_tabs();
44 			tags_opened++;
45 			if (fmt)
46 				write("<modules caption=\"%s\">\n", fmt);
47 			break;
48 		case XPROBELOG_MSG_MODULE:
49 			write_tabs();
50 			log_module(fmt, varg);
51 			break;
52 		case XPROBELOG_MOD_SESS_END:
53 			tags_opened--;
54 			write_tabs();
55 			write("</modules>\n");
56 			break;
57 		case XPROBELOG_TG_SESS_START:
58 			write_tabs();
59 			tags_opened++;
60 			log_target(fmt, varg);
61 			break;
62 		case XPROBELOG_REACH_SESS_START:
63 			write_tabs();
64 			tags_opened++;
65 			write("<reachability>\n");
66 			break;
67 		case XPROBELOG_MSG_STATE:
68 			write_tabs();
69 			log_state(fmt, varg);
70 			break;
71 		case XPROBELOG_MSG_RTT:
72 			write_tabs();
73 			log_rtt(fmt, varg);
74 			break;
75 		case XPROBELOG_REACH_SESS_END:
76 			tags_opened--;
77 			write_tabs();
78 			write("</reachability>\n");
79 			break;
80 		case XPROBELOG_INFO_SESS_START:
81 			write_tabs();
82 			tags_opened++;
83 			write("<information_gathering>\n");
84 			break;
85 		case XPROBELOG_PS_SESS_START:
86 			write_tabs();
87 			tags_opened++;
88 			log_pscan(fmt, varg);
89 			break;
90 		case XPROBELOG_STATS_SESS_START:
91 			write_tabs();
92 			tags_opened++;
93 			write("<stats>\n");
94 			break;
95 		case XPROBELOG_MSG_PS_TCPST:
96 			write_tabs();
97 			log_port_stats(6, fmt, varg);
98 			break;
99 		case XPROBELOG_MSG_PS_UDPST:
100 			write_tabs();
101 			log_port_stats(17, fmt, varg);
102 			break;
103 		case XPROBELOG_STATS_SESS_END:
104 			tags_opened--;
105 			write_tabs();
106 			write("</stats>\n");
107 			break;
108 		case XPROBELOG_PSDET_SESS_START:
109 			write_tabs();
110 			tags_opened++;
111 			write("<details>\n");
112 			break;
113 		case XPROBELOG_MSG_PORT:
114 			write_tabs();
115 			log_port(fmt, varg);
116 			break;
117 		case XPROBELOG_PSDET_SESS_END:
118 			tags_opened--;
119 			write_tabs();
120 			write("</details>\n");
121 			break;
122 		case XPROBELOG_PS_SESS_END:
123 			tags_opened--;
124 			write_tabs();
125 			write("</portscan>\n");
126 			break;
127 		case XPROBELOG_INFO_SESS_END:
128 			tags_opened--;
129 			write_tabs();
130 			write("</information_gathering>\n");
131 			break;
132 		case XPROBELOG_GUESS_SESS_START:
133 			write_tabs();
134 			tags_opened++;
135 			write("<os_guess>\n");
136 			break;
137 		case XPROBELOG_MSG_PRIMARY:
138 		case XPROBELOG_MSG_SECONDARY:
139 			write_tabs();
140 			log_guess(type, fmt, varg);
141 			break;
142 		case XPROBELOG_GUESS_SESS_END:
143 			tags_opened--;
144 			write_tabs();
145 			write("</os_guess>\n");
146 			break;
147 		case XPROBELOG_TG_SESS_END:
148 			tags_opened--;
149 			write_tabs();
150 			write("</target>\n");
151 			break;
152 		case XPROBELOG_XP_SESS_END:
153 			tags_opened--;
154 			write_tabs();
155 			write("</Xprobe2>");
156 			break;
157 		case XPROBELOG_OTHER_TCPP:
158 		case XPROBELOG_OTHER_UDPP:
159 			write_tabs();
160 			log_other_ports(type, fmt, varg);
161 			break;
162 		default:
163 			ui->error("Unknown XML message type %d\n", type);
164 			return FAIL;
165 	}
166 	return OK;
167 }
168 
169 /* s-state */
log_other_ports(char type,const char * fmt,va_list varg)170 int XML_Log::log_other_ports(char type, const char *fmt, va_list varg) {
171 	int st=-1;
172 	const char *state=NULL;
173 
174 	while(*fmt)
175 		switch (*fmt++) {
176 			case 's':
177 				st = va_arg(varg, int);
178 				break;
179 		}
180 	if (st > -1) {
181 		switch(st) {
182 			case XPROBE_TARGETP_CLOSED:
183 				state="closed";
184 				break;
185 			case XPROBE_TARGETP_OPEN:
186 				state="open";
187 				break;
188 			case XPROBE_TARGETP_FILTERED:
189 				state="filtered";
190 				break;
191 			default:
192 				state = "unknown";
193 		}
194 		write("<other proto=\"%s\" state=\"%s\"/>\n", type == XPROBELOG_OTHER_TCPP ? "tcp" : "udp", state);
195 		return OK;
196 	} else
197 		return FAIL;
198 }
199 
200 /* p-probability, s-caption */
log_guess(int type,const char * fmt,va_list varg)201 int XML_Log::log_guess(int type, const char *fmt, va_list varg) {
202 	int prob=-1;
203 	char *os=NULL;
204 	const char *tp = type == XPROBELOG_MSG_PRIMARY ? "primary" : "secondary";
205 
206 	while(*fmt)
207 		switch(*fmt++) {
208 			case 'p':
209 				prob = va_arg(varg, int);
210 				break;
211 			case 's':
212 				os = va_arg(varg, char *);
213 				break;
214 		}
215 	if (os && prob > -1) {
216 		write("<%s probability=\"%d\" unit=\"percent\"> %s </%s>\n", tp, prob, os, tp);
217 		return OK;
218 	} else
219 		return FAIL;
220 }
221 
222 /*  n-number, p-proto, t-state, s-service */
log_port(const char * fmt,va_list varg)223 int XML_Log::log_port(const char *fmt, va_list varg) {
224 	int portnum=-1, proto=-1, st=-1;
225 	char *state=NULL, *service=NULL;
226 
227 	while (*fmt)
228 		switch(*fmt++) {
229 			case 'n':
230 				portnum = va_arg(varg, int);
231 				break;
232 			case 'p':
233 				proto = va_arg(varg, int);
234 				break;
235 			case 't':
236 				st= va_arg(varg, int);
237 				break;
238 			case 's':
239 				service = va_arg(varg, char *);
240 				break;
241 		}
242 	if (service && portnum > -1 && proto > -1 && st > -1) {
243 		switch(st) {
244 			case XPROBE_TARGETP_CLOSED:
245 				state="closed";
246 				break;
247 			case XPROBE_TARGETP_OPEN:
248 				state="open";
249 				break;
250 			case XPROBE_TARGETP_FILTERED:
251 				state="filtered";
252 				break;
253 			default:
254 				state="unknown";
255 		}
256 		write("<port number=\"%d\" proto=\"%s\" state=\"%s\" service=\"%s\" />\n", portnum, proto==IPPROTO_TCP ? "tcp" : "udp", state, service);
257 		return OK;
258 	} else
259 		return FAIL;
260 
261 }
262 
263 /* o-open, c-closed, f-filtered */
log_port_stats(char proto,const char * fmt,va_list varg)264 int XML_Log::log_port_stats(char proto, const char *fmt, va_list varg) {
265 	int opn=-1, closed=-1, filtered=-1;
266 
267 	while(*fmt)
268 		switch(*fmt++) {
269 			case 'o':
270 				opn = va_arg(varg, int);
271 				break;
272 			case 'c':
273 				closed = va_arg(varg, int);
274 				break;
275 			case 'f':
276 				filtered = va_arg(varg, int);
277 				break;
278 		}
279 	if (opn > -1 && closed > -1 && filtered > -1) {
280 		write("<%s open=\"%d\" closed=\"%d\" filtered=\"%d\"/>\n", proto == 6 ? "tcp" : "udp", opn, closed, filtered);
281 		return OK;
282 	} else
283 		return FAIL;
284 
285 }
286 
log_pscan(const char * fmt,va_list varg)287 int XML_Log::log_pscan(const char *fmt, va_list varg) {
288 	double duration=-1;
289 
290 	while(*fmt)
291 		switch(*fmt++) {
292 			case 'd':
293 				duration = va_arg(varg, double);
294 				break;
295 		}
296 	if (duration > -1) {
297 		write("<portscan duration=\"P%.5fS\">\n", duration);
298 		return OK;
299 	} else
300 		return FAIL;
301 }
302 
303 /* r-real, s-selected */
log_rtt(const char * fmt,va_list varg)304 int XML_Log::log_rtt(const char *fmt, va_list varg) {
305 	double real=-1, selected=-1;
306 
307 	while (*fmt)
308 		switch(*fmt++) {
309 			case 'r':
310 				real = va_arg(varg, double);
311 				break;
312 			case 's':
313 				selected = va_arg(varg, double);
314 				break;
315 		}
316 	if (real > -1 && selected > -1) {
317 		write("<rtt real=\"P%.5fS\" selected=\"P%.5fS\"/>\n", real, selected);
318 		return OK;
319 	} else
320 		return FAIL;
321 }
322 /* s-state,p-probability */
log_state(const char * fmt,va_list varg)323 int XML_Log::log_state(const char *fmt, va_list varg) {
324 	char *state=NULL;
325 	int prob=-1;
326 
327 	while(*fmt)
328 		switch(*fmt++) {
329 			case 's':
330 				state = va_arg(varg, char *);
331 				break;
332 			case 'p':
333 				prob = va_arg(varg, int);
334 				break;
335 		}
336 	if (state && prob> -1) {
337 		write("<state state=\"%s\" probability=\"%d\" unit=\"percent\"/>\n", state, prob);
338 		return OK;
339 	} else
340 		return FAIL;
341 }
342 
343 /* a-address */
log_target(const char * fmt,va_list varg)344 int XML_Log::log_target(const char *fmt, va_list varg) {
345 	char *addr=NULL;
346 
347 	while (*fmt)
348 		switch(*fmt++) {
349 			case 'a':
350 				addr = va_arg(varg, char *);
351 				break;
352 		}
353 	if (addr) {
354 		write("<target ip=\"%s\">\n", addr);
355 		return OK;
356 	} else
357 		return FAIL;
358 }
359 
360 /* t-type, n-name, d-modnumber, s-caption */
log_module(const char * fmt,va_list varg)361 int XML_Log::log_module(const char *fmt, va_list varg) {
362 	char *name=NULL, *caption=NULL;
363 	int modnum=-1, type=-1;
364 	const char *tp=NULL;
365 
366 	while (*fmt)
367 		switch(*fmt++) {
368 			case 't':
369 				type = va_arg(varg, int);
370 				break;
371 			case 'n':
372 				name = va_arg(varg, char *);
373 				break;
374 			case 'd':
375 				modnum = va_arg(varg, int);
376 				break;
377 			case 's':
378 				caption = va_arg(varg, char *);
379 				break;
380 		}
381 	if (type > -1 && name && caption && modnum > -1) {
382 		switch(type) {
383 			case XPROBE_MODULE_ALIVETEST:
384 				tp="reachability";
385 				break;
386 			case XPROBE_MODULE_OSTEST:
387 				tp ="fingerprinting";
388 				break;
389 			case XPROBE_MODULE_INFOGATHER:
390 				tp ="information gathering";
391 				break;
392 			default:
393 				tp="unknown";
394 		}
395 		write("<module type=\"%s\" name=\"%s\" number=\"%d\"> %s </module>\n", tp, name, modnum, caption);
396 		return OK;
397 	} else
398 		return FAIL;
399 }
400 
401 
402 /* c-count(argc), a-arguments(argv), d-datetime */
log_run(const char * fmt,va_list varg)403 int XML_Log::log_run(const char *fmt, va_list varg) {
404 	char **argv=NULL;
405    	time_t date=0;
406 	int argc=-1, k, hr, min;
407 	struct tm *tms=NULL;
408 
409 	while(*fmt)
410 		switch(*fmt++) {
411 			case 'c':
412 				argc = va_arg(varg, int);
413 				break;
414 			case 'a':
415 				argv = va_arg(varg, char **);
416 				break;
417 			case 'd':
418 				date = va_arg(varg, time_t);
419 		}
420 	if (argv && date && argc > -1) {
421 		write("<run arguments=\"");
422 		for (k=0; k < argc; k++)
423 			write("%s ", argv[k]);
424 		tms = localtime(&date);
425 		// 2003-04-02T14:39:01-05:00
426 		if (tms) {
427 			hr = (tms->tm_gmtoff / 60) / 60;
428 			min = (tms->tm_gmtoff / 60) % 60;
429 
430 			write("\" date=\"%d-%.2d-%.2dT%.2d:%.2d:%.2d%s%.2d:%.2d\"/>\n",
431 							tms->tm_year+1900, tms->tm_mon+1, tms->tm_mday,
432 							tms->tm_hour, tms->tm_min, tms->tm_sec,
433 							tms->tm_gmtoff < 0 ? "-" : "+", hr, min);
434 		}
435 		return OK;
436 	} else
437 		return FAIL;
438 }
439 
440 /* v-version; b-banner */
log_start(const char * fmt,va_list varg)441 int XML_Log::log_start(const char *fmt, va_list varg) {
442 	char *ver=NULL, *banner=NULL;
443 
444 	while (*fmt)
445 		switch(*fmt++) {
446 			case 'v': // version
447 				ver = va_arg(varg, char *);
448 				break;
449 			case 'b': // banner
450 				banner = va_arg(varg, char *);
451 				break;
452 		}
453 	if (ver && banner) {
454 		write("<?xml version=\"1.0\"?>\n<Xprobe2 version=\"%s\">\n<!-- %s -->\n", ver, banner);
455 		return OK;
456 	} else
457 		return FAIL;
458 }
459