1 /*
2  * ZMap Copyright 2013 Regents of the University of Michigan
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy
6  * of the License at http://www.apache.org/licenses/LICENSE-2.0
7  */
8 
9 #include "summary.h"
10 
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <assert.h>
15 #include <time.h>
16 #include <unistd.h>
17 
18 #include "../lib/includes.h"
19 #include "../lib/logger.h"
20 #include "../lib/blacklist.h"
21 
22 #include "state.h"
23 #include "probe_modules/probe_modules.h"
24 #include "output_modules/output_modules.h"
25 
26 #define STRTIME_LEN 1024
27 
28 #ifdef JSON
29 #include <json.h>
30 
json_metadata(FILE * file)31 void json_metadata(FILE *file)
32 {
33 	char send_start_time[STRTIME_LEN+1];
34 	assert(dstrftime(send_start_time, STRTIME_LEN, "%Y-%m-%dT%H:%M:%S%z", zsend.start));
35 	char send_end_time[STRTIME_LEN+1];
36 	assert(dstrftime(send_end_time, STRTIME_LEN, "%Y-%m-%dT%H:%M:%S%z", zsend.finish));
37 	char recv_start_time[STRTIME_LEN+1];
38 	assert(dstrftime(recv_start_time, STRTIME_LEN, "%Y-%m-%dT%H:%M:%S%z", zrecv.start));
39 	char recv_end_time[STRTIME_LEN+1];
40 	assert(dstrftime(recv_end_time, STRTIME_LEN, "%Y-%m-%dT%H:%M:%S%z", zrecv.finish));
41 	double hitrate = ((double) 100 * zrecv.success_unique)/((double)zsend.sent);
42 
43 	json_object *obj = json_object_new_object();
44 
45 	// scanner host name
46 	char hostname[1024];
47 	if (gethostname(hostname, 1023) < 0) {
48 		log_error("json_metadata", "unable to retrieve local hostname");
49 	} else {
50 		hostname[1023] = '\0';
51 		json_object_object_add(obj, "local_hostname",
52                 json_object_new_string(hostname));
53 		struct hostent* h = gethostbyname(hostname);
54 		if (h) {
55 			json_object_object_add(obj, "full_hostname",
56                     json_object_new_string(h->h_name));
57 		} else {
58 			log_error("json_metadata", "unable to retrieve complete hostname");
59 		}
60 	}
61 
62 	json_object_object_add(obj, "target_port",
63 			json_object_new_int(zconf.target_port));
64 	json_object_object_add(obj, "source_port_first",
65 			json_object_new_int(zconf.source_port_first));
66 	json_object_object_add(obj, "source_port_last",
67 			json_object_new_int(zconf.source_port_last));
68 	json_object_object_add(obj, "max_targets",
69             json_object_new_int(zconf.max_targets));
70 	json_object_object_add(obj, "max_runtime",
71             json_object_new_int(zconf.max_runtime));
72 	json_object_object_add(obj, "max_results",
73             json_object_new_int(zconf.max_results));
74 	if (zconf.iface) {
75 		json_object_object_add(obj, "iface",
76                 json_object_new_string(zconf.iface));
77 	}
78 	json_object_object_add(obj, "rate",
79             json_object_new_int(zconf.rate));
80 	json_object_object_add(obj, "bandwidth",
81             json_object_new_int(zconf.bandwidth));
82 	json_object_object_add(obj, "cooldown_secs",
83             json_object_new_int(zconf.cooldown_secs));
84 	json_object_object_add(obj, "senders",
85             json_object_new_int(zconf.senders));
86 	json_object_object_add(obj, "use_seed",
87             json_object_new_int(zconf.use_seed));
88 	json_object_object_add(obj, "seed",
89             json_object_new_int64(zconf.seed));
90 	json_object_object_add(obj, "generator",
91             json_object_new_int64(zconf.generator));
92 	json_object_object_add(obj, "hitrate",
93             json_object_new_double(hitrate));
94 	json_object_object_add(obj, "shard_num",
95             json_object_new_int(zconf.shard_num));
96 	json_object_object_add(obj, "total_shards",
97             json_object_new_int(zconf.total_shards));
98 
99 	json_object_object_add(obj, "min_hitrate",
100             json_object_new_double(zconf.min_hitrate));
101 	json_object_object_add(obj, "max_sendto_failures",
102             json_object_new_int(zconf.max_sendto_failures));
103 
104 
105 	json_object_object_add(obj, "syslog",
106             json_object_new_int(zconf.syslog));
107 	json_object_object_add(obj, "filter_duplicates",
108             json_object_new_int(zconf.filter_duplicates));
109 	json_object_object_add(obj, "filter_unsuccessful",
110             json_object_new_int(zconf.filter_unsuccessful));
111 
112 	json_object_object_add(obj, "pcap_recv",
113             json_object_new_int(zrecv.pcap_recv));
114 	json_object_object_add(obj, "pcap_drop",
115             json_object_new_int(zrecv.pcap_drop));
116 	json_object_object_add(obj, "pcap_ifdrop",
117             json_object_new_int(zrecv.pcap_ifdrop));
118 
119 	json_object_object_add(obj, "blacklist_total_allowed",
120 		json_object_new_int64(zconf.total_allowed));
121 	json_object_object_add(obj, "blacklist_total_not_allowed",
122 		json_object_new_int64(zconf.total_disallowed));
123 //	json_object_object_add(obj, "blacklisted",
124 //            json_object_new_int64(zsend.blacklisted));
125 //	json_object_object_add(obj, "whitelisted",
126 //            json_object_new_int64(zsend.whitelisted));
127 	json_object_object_add(obj, "first_scanned",
128             json_object_new_int64(zsend.first_scanned));
129 	json_object_object_add(obj, "send_to_failures",
130             json_object_new_int64(zsend.sendto_failures));
131 	json_object_object_add(obj, "total_sent",
132             json_object_new_int64(zsend.sent));
133 
134 	json_object_object_add(obj, "success_total",
135             json_object_new_int64(zrecv.success_total));
136 	json_object_object_add(obj, "success_unique",
137             json_object_new_int64(zrecv.success_unique));
138 	if (zconf.fsconf.app_success_index >= 0) {
139 		json_object_object_add(obj, "app_success_total",
140                 json_object_new_int64(zrecv.app_success_total));
141 		json_object_object_add(obj, "app_success_unique",
142                 json_object_new_int64(zrecv.app_success_unique));
143 	}
144 	json_object_object_add(obj, "success_cooldown_total",
145             json_object_new_int64(zrecv.cooldown_total));
146 	json_object_object_add(obj, "success_cooldown_unique",
147             json_object_new_int64(zrecv.cooldown_unique));
148 	json_object_object_add(obj, "failure_total",
149             json_object_new_int64(zrecv.failure_total));
150 
151 	json_object_object_add(obj, "packet_streams",
152 			json_object_new_int(zconf.packet_streams));
153 	json_object_object_add(obj, "probe_module",
154 			json_object_new_string(((probe_module_t *)zconf.probe_module)->name));
155 	json_object_object_add(obj, "output_module",
156 			json_object_new_string(((output_module_t *)zconf.output_module)->name));
157 
158 	json_object_object_add(obj, "send_start_time",
159 			json_object_new_string(send_start_time));
160 	json_object_object_add(obj, "send_end_time",
161 			json_object_new_string(send_end_time));
162 	json_object_object_add(obj, "recv_start_time",
163 			json_object_new_string(recv_start_time));
164 	json_object_object_add(obj, "recv_end_time",
165 			json_object_new_string(recv_end_time));
166 
167 	if (zconf.output_filter_str) {
168 		json_object_object_add(obj, "output_filter",
169 				json_object_new_string(zconf.output_filter_str));
170 	}
171 	if (zconf.log_file) {
172 		json_object_object_add(obj, "log_file",
173 				json_object_new_string(zconf.log_file));
174 	}
175 	if (zconf.log_directory) {
176 		json_object_object_add(obj, "log_directory",
177 				json_object_new_string(zconf.log_directory));
178 	}
179 
180 	if (zconf.destination_cidrs_len) {
181 		json_object *cli_dest_cidrs = json_object_new_array();
182 		for (int i=0; i < zconf.destination_cidrs_len; i++) {
183 			json_object_array_add(cli_dest_cidrs, json_object_new_string(zconf.destination_cidrs[i]));
184 		}
185 		json_object_object_add(obj, "cli_cidr_destinations",
186 				cli_dest_cidrs);
187 	}
188 	if (zconf.probe_args) {
189 		json_object_object_add(obj, "probe_args",
190 			json_object_new_string(zconf.probe_args));
191 	}
192 	if (zconf.output_args) {
193 		json_object_object_add(obj, "output_args",
194 			json_object_new_string(zconf.output_args));
195 	}
196 
197 	if (zconf.gw_mac) {
198 		char mac_buf[ (MAC_ADDR_LEN * 2) + (MAC_ADDR_LEN - 1) + 1 ];
199 		memset(mac_buf, 0, sizeof(mac_buf));
200 		char *p = mac_buf;
201 		for(int i=0; i < MAC_ADDR_LEN; i++) {
202 			if (i == MAC_ADDR_LEN-1) {
203 				snprintf(p, 3, "%.2x", zconf.gw_mac[i]);
204 				p += 2;
205 			} else {
206 				snprintf(p, 4, "%.2x:", zconf.gw_mac[i]);
207 				p += 3;
208 			}
209 		}
210 		json_object_object_add(obj, "gateway_mac", json_object_new_string(mac_buf));
211 	}
212 	if (zconf.gw_ip) {
213 		struct in_addr addr;
214 		addr.s_addr = zconf.gw_ip;
215 		json_object_object_add(obj, "gateway_ip", json_object_new_string(inet_ntoa(addr)));
216 	}
217 	if (zconf.hw_mac) {
218 		char mac_buf[(ETHER_ADDR_LEN * 2) + (ETHER_ADDR_LEN - 1) + 1];
219 		char *p = mac_buf;
220 		for(int i=0; i < ETHER_ADDR_LEN; i++) {
221 			if (i == ETHER_ADDR_LEN-1) {
222 				snprintf(p, 3, "%.2x", zconf.hw_mac[i]);
223 				p += 2;
224 			} else {
225 				snprintf(p, 4, "%.2x:", zconf.hw_mac[i]);
226 				p += 3;
227 			}
228 		}
229 		json_object_object_add(obj, "source_mac", json_object_new_string(mac_buf));
230 	}
231 
232 	json_object_object_add(obj, "source_ip_first",
233 			json_object_new_string(zconf.source_ip_first));
234 	json_object_object_add(obj, "source_ip_last",
235 			json_object_new_string(zconf.source_ip_last));
236 	if (zconf.output_filename) {
237 		json_object_object_add(obj, "output_filename",
238 				json_object_new_string(zconf.output_filename));
239 	}
240 	if (zconf.blacklist_filename) {
241 		json_object_object_add(obj,
242 			"blacklist_filename",
243 			json_object_new_string(zconf.blacklist_filename));
244 	}
245 	if (zconf.whitelist_filename) {
246 		json_object_object_add(obj,
247 			"whitelist_filename",
248 			json_object_new_string(zconf.whitelist_filename));
249 	}
250 	json_object_object_add(obj, "dryrun",
251             json_object_new_int(zconf.dryrun));
252 	json_object_object_add(obj, "quiet",
253             json_object_new_int(zconf.quiet));
254 	json_object_object_add(obj, "log_level",
255             json_object_new_int(zconf.log_level));
256 
257     // parse out JSON metadata that was supplied on the command-line
258     if (zconf.custom_metadata_str) {
259         json_object *user = json_tokener_parse(zconf.custom_metadata_str);
260         if (!user) {
261             log_error("json-metadata", "unable to parse user metadata");
262         } else {
263 	        json_object_object_add(obj, "user-metadata", user);
264         }
265     }
266 
267     if (zconf.notes) {
268         json_object_object_add(obj, "notes",
269                 json_object_new_string(zconf.notes));
270     }
271 
272 	// add blacklisted and whitelisted CIDR blocks
273 	bl_cidr_node_t *b = get_blacklisted_cidrs();
274 	if (b) {
275 		json_object *blacklisted_cidrs = json_object_new_array();
276 		do {
277 			char cidr[50];
278 			struct in_addr addr;
279 			addr.s_addr = b->ip_address;
280 			sprintf(cidr, "%s/%i", inet_ntoa(addr), b->prefix_len);
281 			json_object_array_add(blacklisted_cidrs,
282 					json_object_new_string(cidr));
283 		} while (b && (b = b->next));
284 		json_object_object_add(obj, "blacklisted_networks", blacklisted_cidrs);
285 	}
286 
287 	b = get_whitelisted_cidrs();
288 	if (b) {
289 		json_object *whitelisted_cidrs = json_object_new_array();
290 		do {
291 			char cidr[50];
292 			struct in_addr addr;
293 			addr.s_addr = b->ip_address;
294 			sprintf(cidr, "%s/%i", inet_ntoa(addr), b->prefix_len);
295 			json_object_array_add(whitelisted_cidrs,
296 					json_object_new_string(cidr));
297 		} while (b && (b = b->next));
298 		json_object_object_add(obj, "whitelisted_networks", whitelisted_cidrs);
299 	}
300 
301 	fprintf(file, "%s\n", json_object_to_json_string(obj));
302 	json_object_put(obj);
303 }
304 #else
json_metadata(FILE * file)305 void json_metadata(FILE *file)
306 {
307 	(void) file;
308 	log_error("metadata", "JSON support not compiled in");
309 }
310 #endif
311