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 /*
10 * ZBlacklist is a simple utility that (1) excludes IP addresses on a specified
11 * blacklist from being scanned, and (2) ensures the uniqueness of output
12 * addresses such that no host is scanned twice. ZBlacklist takes in a list
13 * of addresses on stdin and outputs addresses that are acceptable to scan
14 * on stdout. The utility uses the blacklist data structures from ZMap for
15 * checking scan eligibility and a paged bitmap for duplicate prevention.
16 */
17
18 #define _GNU_SOURCE
19
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <getopt.h>
25 #include <assert.h>
26 #include <sched.h>
27 #include <errno.h>
28 #include <pwd.h>
29 #include <time.h>
30
31 #include "../lib/includes.h"
32 #include "../lib/blacklist.h"
33 #include "../lib/logger.h"
34 #include "../lib/pbm.h"
35
36 #include "zbopt.h"
37
38
39 //struct zbl_stats {
40 // uint32_t cidr_entries;
41 // uint32_t allowed_addrs;
42 // uint32_t input_addrs;
43 // uint32_t uniq_input_addrs;
44 // uint32_t blocked_addrs;
45 // uint32_t output_addrs;
46 // uint32_t duplicates;
47 //};
48
49 #undef MIN
50 #define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
51
zmin(char * a,char * b)52 static inline char* zmin(char *a, char *b) {
53 if (a && !b)
54 return a;
55 else if (b && !a)
56 return b;
57 else
58 return MIN(a,b);
59 }
60
61 struct zbl_conf {
62 char *blacklist_filename;
63 char *whitelist_filename;
64 char *log_filename;
65 int check_duplicates;
66 int ignore_errors;
67 int verbosity;
68 //struct zbl_stats stats;
69 };
70
71 #define SET_IF_GIVEN(DST,ARG) \
72 { if (args.ARG##_given) { (DST) = args.ARG##_arg; }; }
73 #define SET_BOOL(DST,ARG) \
74 { if (args.ARG##_given) { (DST) = 1; }; }
75
main(int argc,char ** argv)76 int main(int argc, char **argv)
77 {
78 struct zbl_conf conf;
79 conf.verbosity = 3;
80 memset(&conf, 0, sizeof(struct zbl_conf));
81 int no_dupchk_pres = 0;
82 conf.ignore_errors = 0;
83
84 struct gengetopt_args_info args;
85 struct cmdline_parser_params *params;
86 params = cmdline_parser_params_create();
87 assert(params);
88 params->initialize = 1;
89 params->override = 0;
90 params->check_required = 0;
91
92 if (cmdline_parser_ext(argc, argv, &args, params) != 0) {
93 exit(EXIT_SUCCESS);
94 }
95
96 // Handle help text and version
97 if (args.help_given) {
98 cmdline_parser_print_help();
99 exit(EXIT_SUCCESS);
100 }
101 if (args.version_given) {
102 cmdline_parser_print_version();
103 exit(EXIT_SUCCESS);
104 }
105
106 // Set the log file and metadata file
107 if (args.log_file_given) {
108 conf.log_filename = strdup(args.log_file_arg);
109 }
110 if (args.verbosity_given) {
111 conf.verbosity = args.verbosity_arg;
112 }
113
114 // Blacklist and whitelist
115 if (args.blacklist_file_given) {
116 conf.blacklist_filename = strdup(args.blacklist_file_arg);
117 }
118 if (args.whitelist_file_given) {
119 conf.whitelist_filename = strdup(args.whitelist_file_arg);
120 }
121
122 // Read the boolean flags
123 SET_BOOL(no_dupchk_pres, no_duplicate_checking);
124 conf.check_duplicates = !no_dupchk_pres;
125 SET_BOOL(conf.ignore_errors, ignore_blacklist_errors);
126
127 // initialize logging
128 FILE *logfile = stderr;
129 if (conf.log_filename) {
130 logfile = fopen(conf.log_filename, "w");
131 if (!logfile) {
132 fprintf(stderr, "FATAL: unable to open specified logfile (%s)\n",
133 conf.log_filename);
134 exit(1);
135 }
136 }
137 if (log_init(logfile, conf.verbosity, 1, "zblacklist")) {
138 fprintf(stderr, "FATAL: unable able to initialize logging\n");
139 exit(1);
140 }
141
142 if (!conf.blacklist_filename && !conf.whitelist_filename) {
143 log_fatal("zblacklist", "must specify either a whitelist or blacklist file");
144 }
145
146 // parse blacklist
147 if (conf.blacklist_filename) {
148 log_debug("zblacklist", "blacklist file at %s to be used", conf.blacklist_filename);
149 } else {
150 log_debug("zblacklist", "no blacklist file specified");
151 }
152 if (conf.blacklist_filename && access(conf.blacklist_filename, R_OK) == -1) {
153 log_fatal("zblacklist", "unable to read specified blacklist file (%s)",
154 conf.blacklist_filename);
155 }
156 if (conf.whitelist_filename) {
157 log_debug("zblacklist", "whitelist file at %s to be used", conf.whitelist_filename);
158 } else {
159 log_debug("zblacklist", "no whitelist file specified");
160 }
161 if (conf.whitelist_filename && access(conf.whitelist_filename, R_OK) == -1) {
162 log_fatal("zblacklist", "unable to read specified whitelist file (%s)",
163 conf.whitelist_filename);
164 }
165
166 if (blacklist_init(conf.whitelist_filename, conf.blacklist_filename,
167 NULL, 0, NULL, 0, conf.ignore_errors)) {
168 log_fatal("zmap", "unable to initialize blacklist / whitelist");
169 }
170 // initialize paged bitmap
171 uint8_t **seen = NULL;
172 if (conf.check_duplicates) {
173 seen = pbm_init();
174 if (!seen) {
175 log_fatal("zblacklist", "unable to initialize paged bitmap");
176 }
177 }
178 // process addresses
179 char line[1000];
180 char original[1000];
181 while (fgets(line, 1000, stdin) != NULL) {
182 // remove new line
183 memcpy(original, line, strlen(line) + 1);
184 char *n = zmin(zmin(zmin(zmin(strchr(line, '\n'),
185 strchr(line, ',')),
186 strchr(line, '\t')),
187 strchr(line, ' ')),
188 strchr(line, '#'));
189 assert(n);
190 n[0] = 0;
191 log_trace("zblacklist", "input value %s", line);
192 // parse into int
193 struct in_addr addr;
194 if (!inet_aton(line, &addr)) {
195 log_warn("zblacklist", "invalid input address: %s", line);
196 }
197 if (conf.check_duplicates) {
198 if (pbm_check(seen, ntohl(addr.s_addr))) {
199 log_trace("zblacklist", "%s is a duplicate: skipped", line);
200 continue;
201 } else {
202 log_trace("zblacklist", "%s not a duplicate: skipped", line);
203 }
204 } else {
205 log_trace("zblacklist", "no duplicate checking for %s", line);
206 }
207 // check if in blacklist
208 if (blacklist_is_allowed(addr.s_addr)) {
209 if (conf.check_duplicates) {
210 if (!pbm_check(seen, ntohl(addr.s_addr))) {
211 pbm_set(seen, ntohl(addr.s_addr));
212 printf("%s", original);
213 }
214 } else {
215 printf("%s", original);
216 }
217 }
218 }
219 return EXIT_SUCCESS;
220 }
221