1 #include <config.h>
2 
3 #include <unistd.h>
4 
5 #include <scan_progs/scanopts.h>
6 #include <scan_progs/scan_export.h>
7 #include <sqlinterface.h>
8 #include <settings.h>
9 #include <unilib/qfifo.h>
10 #include <unilib/output.h>
11 
12 static int db_disable=0;
13 static uint64_t scanid;
14 
15 static void database_walk_func(const void *);
16 
m_database_init(void)17 void m_database_init(void) {
18 	int results=0;
19 	char query[2048];
20 	seo_t scanopts;
21 
22 	if (s->verbose > 3) MSG(M_DBG1, "Database module is enabled");
23 
24 	if (initdb() < 0) {
25 		db_disable=1;
26 		return;
27 	}
28 
29 	CLEAR(query);
30 	if (get_scanopts(&scanopts) < 0) {
31 		MSG(M_ERR, "Serious problems getting scan options for insertion into database");
32 		_exit(1);
33 	}
34 	snprintf(query, sizeof(query) -1, "insert into scan(s_time, e_time, srcaddr, portstr, addrmin, addrmax, scanmode, pps, "
35 	"active_plgroups, pcapfilter, dronestr, fingerprint, iptos, ipttl, ipoffset, tcpflags, srcport, repeats)"
36 	" values(%lld, %lld, %llu, '%s', %llu, %llu, %u, %u, %u, '%s', '%s', %u, %u, %u, %u, %u, %d, %u); "
37 	"select currval('scan_id_seq') as myid;",
38 	(long long int)s->s_time, (long long int)0, (uint64_t )ntohl(s->vi->myaddr.sin_addr.s_addr), s->port_str,
39 	(uint64_t )s->_low_ip, (uint64_t )s->_high_ip, (uint8_t)s->mode, s->pps, s->payload_flags,
40 	(s->extra_pcapfilter != NULL ? s->extra_pcapfilter : "None"), s->drone_str,
41 	scanopts.fingerprint, scanopts.tos, scanopts.ttl, scanopts.ip_off, scanopts.tcphdrflgs, scanopts.src_port, s->repeats);
42 
43 	aquerydb(query);
44 	results=dbnumrows();
45 	if (results == 1) {
46 		char *res_ptr=NULL;
47 
48 		res_ptr=dbgetvalue(0, 0);
49 		if (sscanf(res_ptr, "%llu", &scanid) != 1) {
50 			MSG(M_ERR, "Malformed scanid from database");
51 			_exit(1);
52 		}
53 	}
54 	else {
55 			MSG(M_ERR, "Database is acting very weird, exiting");
56 			_exit(1);
57 	}
58 	aquerydb("begin;");
59 
60 	return;
61 }
62 
63 static char db_banner[256];
64 static char db_os[256];
65 
m_database_output(const void * r)66 int m_database_output(const void *r) {
67 	union {
68 		const ip_report_t *ir;
69 		const arp_report_t *ar;
70 		const void *ptr;
71 		const uint16_t *r_magic;
72 	} r_u;
73 	char query[2048];
74 	uint64_t sb_id=0;
75 	int results=0;
76 
77 	if (db_disable) return 1;
78 
79 	CLEAR(db_banner);
80 	CLEAR(db_os);
81 	CLEAR(query);
82 
83 	r_u.ptr=r;
84 	if (*r_u.r_magic != IP_REPORT_MAGIC) {
85 		return 0;
86 	}
87 
88 	fifo_walk(r_u.ir->od_q, &database_walk_func);
89 
90 	snprintf(query, sizeof(query) -1, "insert into scan_bucket(scan_id, protocol, type, subtype, dport, sport, ttl, host_addr, trace_addr, u_tstamp, u_utstamp) "
91 	"values(%lld, %u, %u, %u, %u, %u, %u, %u, %u, %lld, %llu); select currval('scan_bucket_id_seq') as myid;",
92 	scanid, r_u.ir->proto, r_u.ir->type, r_u.ir->subtype, r_u.ir->dport, r_u.ir->sport, r_u.ir->ttl,
93 	htonl(r_u.ir->host_addr), htonl(r_u.ir->trace_addr), (long long unsigned int )r_u.ir->recv_time.tv_sec,
94 	(long long unsigned int)r_u.ir->recv_time.tv_usec);
95 
96 	aquerydb(query);
97 	results=dbnumrows();
98 	if (results == 1) {
99 		char *res_ptr=NULL;
100 
101 		res_ptr=dbgetvalue(0, 0);
102 		if (sscanf(res_ptr, "%llu", &sb_id) != 1) {
103 			MSG(M_ERR, "Malformed scanid from database");
104 			db_disable=1;
105 			return 0;
106 		}
107 	}
108 
109 	if (strlen(db_banner)) {
110 		CLEAR(query);
111 		snprintf(query, sizeof(query) -1, "insert into banner(scan_bucket_id, banner) values(%llu, '%s');", sb_id, db_banner);
112 		aquerydb(query);
113 	}
114 	else {
115 		/*
116 		 * right about now, you are likely wondering why in gods name anyone would do this?
117 		 * well it turns out this is a hack, that was requested to make sure the views
118 		 * are more _portable_, even though the other db code is missing, it wont be for long.
119 		 */
120 		CLEAR(query);
121 		snprintf(query, sizeof(query) -1, "insert into banner(scan_bucket_id) values(%llu);", sb_id);
122 		aquery(query);
123 	}
124 
125 	if (strlen(db_os)) {
126 		CLEAR(query);
127 		snprintf(query, sizeof(query) -1, "insert into os_fingerprint(scan_bucket_id, os) values(%llu, '%s');", sb_id, db_os);
128 		aquerydb(query);
129 	}
130 	else {
131 		CLEAR(query);
132 		snprintf(query, sizeof(query) -1, "insert into os_fingerprint(scan_bucket_id) values(%llu);", sb_id);
133 		aquery(query);
134 	}
135 
136 	return 1;
137 }
138 
m_database_fini(void)139 void m_database_fini(void) {
140 	char query[512];
141 
142 	if (db_disable) return;
143 	CLEAR(query);
144 	snprintf(query, sizeof(query) -1, "update scan set e_time=%lld where scan_id=%lld;commit;", (long long int)s->e_time, scanid);
145 	aquerydb(query);
146 
147 	closedb();
148 
149 	return;
150 }
151 
database_walk_func(const void * item)152 static void database_walk_func(const void *item) {
153 	union {
154 		const void *ptr;
155 		const output_data_t *d;
156 	} d_u;
157 
158 	d_u.ptr=item;
159 	switch (d_u.d->type) {
160 		case OD_TYPE_BANNER:
161 			CLEAR(db_banner);
162 			snprintf(db_banner, sizeof(db_banner) -1, "%s", d_u.d->t_u.banner);
163 			break;
164 		case OD_TYPE_OS:
165 			CLEAR(db_os);
166 			snprintf(db_os, sizeof(db_os) -1, "%s", d_u.d->t_u.os);
167 			break;
168 		default:
169 			MSG(M_ERR, "Unknown output format type %d in database push", d_u.d->type);
170 			break;
171 	}
172 
173 	return;
174 }
175