1 /*
2 * ProFTPD: mod_geoip -- a module for looking up country/city/etc for clients
3 * Copyright (c) 2010-2017 TJ Saunders
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
18 *
19 * As a special exemption, TJ Saunders and other respective copyright holders
20 * give permission to link this program with OpenSSL, and distribute the
21 * resulting executable, without including the source code for OpenSSL in the
22 * source distribution.
23 *
24 * This is mod_geoip, contrib software for proftpd 1.3.x and above.
25 * For more information contact TJ Saunders <tj@castaglia.org>.
26 *
27 * --- DO NOT DELETE BELOW THIS LINE ----
28 * $Libraries: -lGeoIP$
29 */
30
31 #include "conf.h"
32 #include "privs.h"
33
34 /* A lot of ideas for this module were liberally borrowed from the mod_geoip
35 * module for Apache.
36 */
37
38 #define MOD_GEOIP_VERSION "mod_geoip/0.9"
39
40 /* Make sure the version of proftpd is as necessary. */
41 #if PROFTPD_VERSION_NUMBER < 0x0001030402
42 # error "ProFTPD 1.3.4rc2 or later required"
43 #endif
44
45 #include <GeoIP.h>
46 #include <GeoIPCity.h>
47
48 module geoip_module;
49
50 static int geoip_engine = FALSE;
51 static int geoip_logfd = -1;
52
53 static pool *geoip_pool = NULL;
54 static array_header *static_geoips = NULL;
55
56 /* The types of data that GeoIP can provide, and that we care about. */
57 static const char *geoip_city = NULL;
58 static const char *geoip_area_code = NULL;
59 static const char *geoip_postal_code = NULL;
60 static const char *geoip_latitude = NULL;
61 static const char *geoip_longitude = NULL;
62 static const char *geoip_isp = NULL;
63 static const char *geoip_org = NULL;
64 static const char *geoip_country_code2 = NULL;
65 static const char *geoip_country_code3 = NULL;
66 static const char *geoip_country_name = NULL;
67 static const char *geoip_region_code = NULL;
68 static const char *geoip_region_name = NULL;
69 static const char *geoip_continent_name = NULL;
70 static const char *geoip_network_speed = NULL;
71 static const char *geoip_asn = NULL;
72 static const char *geoip_proxy = NULL;
73 static const char *geoip_timezone = NULL;
74
75 /* Names of supported GeoIP values */
76 struct geoip_filter_key {
77 const char *filter_name;
78 int filter_id;
79 };
80
81 #define GEOIP_FILTER_KEY_COUNTRY_CODE 100
82 #define GEOIP_FILTER_KEY_COUNTRY_CODE3 101
83 #define GEOIP_FILTER_KEY_COUNTRY_NAME 102
84 #define GEOIP_FILTER_KEY_REGION_CODE 103
85 #define GEOIP_FILTER_KEY_REGION_NAME 104
86 #define GEOIP_FILTER_KEY_CONTINENT 105
87 #define GEOIP_FILTER_KEY_ISP 106
88 #define GEOIP_FILTER_KEY_ORGANIZATION 107
89 #define GEOIP_FILTER_KEY_NETWORK_SPEED 108
90 #define GEOIP_FILTER_KEY_CITY 109
91 #define GEOIP_FILTER_KEY_AREA_CODE 110
92 #define GEOIP_FILTER_KEY_POSTAL_CODE 111
93 #define GEOIP_FILTER_KEY_LATITUDE 112
94 #define GEOIP_FILTER_KEY_LONGITUDE 113
95 #define GEOIP_FILTER_KEY_ASN 114
96 #define GEOIP_FILTER_KEY_PROXY 115
97 #define GEOIP_FILTER_KEY_TIMEZONE 116
98
99 static struct geoip_filter_key geoip_filter_keys[] = {
100 { "CountryCode", GEOIP_FILTER_KEY_COUNTRY_CODE },
101 { "CountryCode3", GEOIP_FILTER_KEY_COUNTRY_CODE3 },
102 { "CountryName", GEOIP_FILTER_KEY_COUNTRY_NAME },
103 { "RegionCode", GEOIP_FILTER_KEY_REGION_CODE },
104 { "RegionName", GEOIP_FILTER_KEY_REGION_NAME },
105 { "Continent", GEOIP_FILTER_KEY_CONTINENT },
106 { "ISP", GEOIP_FILTER_KEY_ISP },
107 { "Organization", GEOIP_FILTER_KEY_ORGANIZATION },
108 { "NetworkSpeed", GEOIP_FILTER_KEY_NETWORK_SPEED },
109 { "City", GEOIP_FILTER_KEY_CITY },
110 { "AreaCode", GEOIP_FILTER_KEY_AREA_CODE },
111 { "PostalCode", GEOIP_FILTER_KEY_POSTAL_CODE },
112 { "Latitude", GEOIP_FILTER_KEY_LATITUDE },
113 { "Longitude", GEOIP_FILTER_KEY_LONGITUDE },
114 { "ASN", GEOIP_FILTER_KEY_ASN },
115 { "Proxy", GEOIP_FILTER_KEY_PROXY },
116 { "Timezone", GEOIP_FILTER_KEY_TIMEZONE },
117
118 { NULL, -1 }
119 };
120
121 #if PR_USE_REGEX
122 /* GeoIP filter */
123 struct geoip_filter {
124 int filter_id;
125 const char *filter_pattern;
126 pr_regex_t *filter_re;
127 };
128 #endif /* PR_USE_REGEX */
129
130 /* GeoIP policies */
131 typedef enum {
132 GEOIP_POLICY_ALLOW_DENY,
133 GEOIP_POLICY_DENY_ALLOW
134
135 } geoip_policy_e;
136
137 static geoip_policy_e geoip_policy = GEOIP_POLICY_ALLOW_DENY;
138
139 static const char *trace_channel = "geoip";
140
141 static const char *get_geoip_filter_name(int);
142 static const char *get_geoip_filter_value(int);
143
get_filter_id(const char * filter_name)144 static int get_filter_id(const char *filter_name) {
145 register unsigned int i;
146 int filter_id = -1;
147
148 for (i = 0; geoip_filter_keys[i].filter_name != NULL; i++) {
149 if (strcasecmp(filter_name, geoip_filter_keys[i].filter_name) == 0) {
150 filter_id = geoip_filter_keys[i].filter_id;
151 break;
152 }
153 }
154
155 return filter_id;
156 }
157
158 #if PR_USE_REGEX
get_filter(pool * p,const char * pattern,pr_regex_t ** pre)159 static int get_filter(pool *p, const char *pattern, pr_regex_t **pre) {
160 int res;
161
162 *pre = pr_regexp_alloc(&geoip_module);
163
164 res = pr_regexp_compile(*pre, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE);
165 if (res != 0) {
166 char errstr[256];
167
168 memset(errstr, '\0', sizeof(errstr));
169 pr_regexp_error(res, *pre, errstr, sizeof(errstr)-1);
170 pr_regexp_free(&geoip_module, *pre);
171 *pre = NULL;
172
173 pr_log_pri(PR_LOG_DEBUG, MOD_GEOIP_VERSION
174 ": pattern '%s' failed regex compilation: %s", pattern, errstr);
175 errno = EINVAL;
176 return -1;
177 }
178
179 return res;
180 }
181
make_filter(pool * p,const char * filter_name,const char * pattern)182 static struct geoip_filter *make_filter(pool *p, const char *filter_name,
183 const char *pattern) {
184 struct geoip_filter *filter;
185 int filter_id;
186 pr_regex_t *pre = NULL;
187
188 filter_id = get_filter_id(filter_name);
189 if (filter_id < 0) {
190 pr_log_debug(DEBUG0, MOD_GEOIP_VERSION ": unknown GeoIP filter name '%s'",
191 filter_name);
192 return NULL;
193 }
194
195 if (get_filter(p, pattern, &pre) < 0) {
196 return NULL;
197 }
198
199 filter = pcalloc(p, sizeof(struct geoip_filter));
200 filter->filter_id = filter_id;
201 filter->filter_pattern = pstrdup(p, pattern);
202 filter->filter_re = pre;
203
204 return filter;
205 }
206
get_sql_filters(pool * p,const char * query_name)207 static array_header *get_sql_filters(pool *p, const char *query_name) {
208 register unsigned int i;
209 cmdtable *sql_cmdtab = NULL;
210 cmd_rec *sql_cmd = NULL;
211 modret_t *sql_res = NULL;
212 array_header *sql_data = NULL;
213 const char **values = NULL;
214 array_header *sql_filters = NULL;
215
216 sql_cmdtab = pr_stash_get_symbol2(PR_SYM_HOOK, "sql_lookup", NULL, NULL,
217 NULL);
218 if (sql_cmdtab == NULL) {
219 (void) pr_log_writefile(geoip_logfd, MOD_GEOIP_VERSION,
220 "unable to execute SQLNamedQuery '%s': mod_sql not loaded", query_name);
221 errno = EPERM;
222 return NULL;
223 }
224
225 sql_cmd = pr_cmd_alloc(p, 2, "sql_lookup", query_name);
226
227 sql_res = pr_module_call(sql_cmdtab->m, sql_cmdtab->handler, sql_cmd);
228 if (sql_res == NULL ||
229 MODRET_ISERROR(sql_res)) {
230 (void) pr_log_writefile(geoip_logfd, MOD_GEOIP_VERSION,
231 "error processing SQLNamedQuery '%s'; check mod_sql logs for details",
232 query_name);
233 errno = EPERM;
234 return NULL;
235 }
236
237 sql_data = sql_res->data;
238 pr_trace_msg(trace_channel, 9, "SQLNamedQuery '%s' returned item count %d",
239 query_name, sql_data->nelts);
240
241 if (sql_data->nelts == 0) {
242 (void) pr_log_writefile(geoip_logfd, MOD_GEOIP_VERSION,
243 "SQLNamedQuery '%s' returned no values", query_name);
244 errno = ENOENT;
245 return NULL;
246 }
247
248 if (sql_data->nelts % 2 == 1) {
249 (void) pr_log_writefile(geoip_logfd, MOD_GEOIP_VERSION,
250 "SQLNamedQuery '%s' returned odd number of values (%d), "
251 "expected even number", query_name, sql_data->nelts);
252 errno = EINVAL;
253 return NULL;
254 }
255
256 values = sql_data->elts;
257 sql_filters = make_array(p, 0, sizeof(struct geoip_filter));
258
259 for (i = 0; i < sql_data->nelts; i += 2) {
260 const char *filter_name, *pattern = NULL;
261 struct geoip_filter *filter;
262
263 filter_name = values[i];
264 pattern = values[i+1];
265
266 filter = make_filter(p, filter_name, pattern);
267 if (filter == NULL) {
268 pr_trace_msg(trace_channel, 3, "unable to use '%s %s' as filter: %s",
269 filter_name, pattern, strerror(errno));
270 continue;
271 }
272
273 *((struct geoip_filter **) push_array(sql_filters)) = filter;
274 }
275
276 return sql_filters;
277 }
278 #endif /* PR_USE_REGEX */
279
resolve_deferred_patterns(pool * p,const char * directive)280 static void resolve_deferred_patterns(pool *p, const char *directive) {
281 #if PR_USE_REGEX
282 config_rec *c;
283
284 c = find_config(main_server->conf, CONF_PARAM, directive, FALSE);
285 while (c != NULL) {
286 register unsigned int i;
287 array_header *deferred_filters, *filters;
288
289 pr_signals_handle();
290
291 filters = c->argv[0];
292 deferred_filters = c->argv[1];
293
294 for (i = 0; i < deferred_filters->nelts; i++) {
295 const char *query_name;
296 array_header *sql_filters;
297
298 query_name = ((const char **) deferred_filters->elts)[i];
299
300 sql_filters = get_sql_filters(p, query_name);
301 if (sql_filters == NULL) {
302 continue;
303 }
304
305 array_cat(filters, sql_filters);
306 }
307
308 c = find_config_next(c, c->next, CONF_PARAM, directive, FALSE);
309 }
310 #endif /* PR_USE_REGEX */
311 }
312
resolve_deferred_filters(pool * p)313 static void resolve_deferred_filters(pool *p) {
314 resolve_deferred_patterns(p, "GeoIPAllowFilter");
315 resolve_deferred_patterns(p, "GeoIPDenyFilter");
316 }
317
check_geoip_filters(geoip_policy_e policy)318 static int check_geoip_filters(geoip_policy_e policy) {
319 int allow_conn = 0, matched_allow_filter = -1, matched_deny_filter = -1;
320 #if PR_USE_REGEX
321 config_rec *c;
322
323 c = find_config(main_server->conf, CONF_PARAM, "GeoIPAllowFilter", FALSE);
324 while (c != NULL) {
325 register unsigned int i;
326 int matched = TRUE;
327 array_header *filters;
328
329 pr_signals_handle();
330
331 if (matched_allow_filter == -1) {
332 matched_allow_filter = FALSE;
333 }
334
335 filters = c->argv[0];
336
337 for (i = 0; i < filters->nelts; i++) {
338 int filter_id, res;
339 struct geoip_filter *filter;
340 pr_regex_t *filter_re;
341 const char *filter_name, *filter_pattern, *filter_value;
342
343 filter = ((struct geoip_filter **) filters->elts)[i];
344 filter_id = filter->filter_id;
345 filter_pattern = filter->filter_pattern;
346 filter_re = filter->filter_re;
347
348 filter_value = get_geoip_filter_value(filter_id);
349 if (filter_value == NULL) {
350 matched = FALSE;
351 break;
352 }
353
354 filter_name = get_geoip_filter_name(filter_id);
355
356 res = pr_regexp_exec(filter_re, filter_value, 0, NULL, 0, 0, 0);
357 pr_trace_msg(trace_channel, 12,
358 "%s filter value %s %s GeoIPAllowFilter pattern '%s'",
359 filter_name, filter_value, res == 0 ? "matched" : "did not match",
360 filter_pattern);
361 if (res == 0) {
362 (void) pr_log_writefile(geoip_logfd, MOD_GEOIP_VERSION,
363 "%s filter value '%s' matched GeoIPAllowFilter pattern '%s'",
364 filter_name, filter_value, filter_pattern);
365
366 } else {
367 (void) pr_log_writefile(geoip_logfd, MOD_GEOIP_VERSION,
368 "%s filter value '%s' did not match GeoIPAllowFilter pattern '%s'",
369 filter_name, filter_value, filter_pattern);
370 matched = FALSE;
371 break;
372 }
373 }
374
375 if (matched == TRUE) {
376 matched_allow_filter = TRUE;
377 break;
378 }
379
380 c = find_config_next(c, c->next, CONF_PARAM, "GeoIPAllowFilter", FALSE);
381 }
382
383 c = find_config(main_server->conf, CONF_PARAM, "GeoIPDenyFilter", FALSE);
384 while (c != NULL) {
385 register unsigned int i;
386 int matched = TRUE;
387 array_header *filters;
388
389 pr_signals_handle();
390
391 if (matched_deny_filter == -1) {
392 matched_deny_filter = FALSE;
393 }
394
395 filters = c->argv[0];
396
397 for (i = 0; i < filters->nelts; i++) {
398 int filter_id, res;
399 struct geoip_filter *filter;
400 pr_regex_t *filter_re;
401 const char *filter_name, *filter_pattern, *filter_value;
402
403 filter = ((struct geoip_filter **) filters->elts)[i];
404 filter_id = filter->filter_id;
405 filter_pattern = filter->filter_pattern;
406 filter_re = filter->filter_re;
407
408 filter_value = get_geoip_filter_value(filter_id);
409 if (filter_value == NULL) {
410 matched = FALSE;
411 break;
412 }
413
414 filter_name = get_geoip_filter_name(filter_id);
415
416 res = pr_regexp_exec(filter_re, filter_value, 0, NULL, 0, 0, 0);
417 pr_trace_msg(trace_channel, 12,
418 "%s filter value %s %s GeoIPDenyFilter pattern '%s'",
419 filter_name, filter_value, res == 0 ? "matched" : "did not match",
420 filter_pattern);
421 if (res == 0) {
422 (void) pr_log_writefile(geoip_logfd, MOD_GEOIP_VERSION,
423 "%s filter value '%s' matched GeoIPDenyFilter pattern '%s'",
424 filter_name, filter_value, filter_pattern);
425 } else {
426 (void) pr_log_writefile(geoip_logfd, MOD_GEOIP_VERSION,
427 "%s filter value '%s' did not match GeoIPDenyFilter pattern '%s'",
428 filter_name, filter_value, filter_pattern);
429 matched = FALSE;
430 break;
431 }
432 }
433
434 if (matched == TRUE) {
435 matched_deny_filter = TRUE;
436 break;
437 }
438
439 c = find_config_next(c, c->next, CONF_PARAM, "GeoIPDenyFilter", FALSE);
440 }
441 #endif /* !HAVE_REGEX_H or !HAVE_REGCOMP */
442
443 switch (policy) {
444 case GEOIP_POLICY_ALLOW_DENY:
445 if (matched_deny_filter == TRUE &&
446 matched_allow_filter != TRUE) {
447 /* If we explicitly matched any deny filters AND have NOT explicitly
448 * matched any allow filters, the connection is rejected, otherwise,
449 * it is allowed.
450 */
451 (void) pr_log_writefile(geoip_logfd, MOD_GEOIP_VERSION,
452 "client matched GeoIPDenyFilter, rejecting connection");
453 allow_conn = -1;
454
455 } else {
456 pr_trace_msg(trace_channel, 9,
457 "allowing client connection (policy 'allow,deny')");
458 }
459 break;
460
461 case GEOIP_POLICY_DENY_ALLOW:
462 if (matched_allow_filter == FALSE) {
463 /* If we have not explicitly matched any allow filters, then
464 * reject the connection.
465 */
466 (void) pr_log_writefile(geoip_logfd, MOD_GEOIP_VERSION,
467 "client did not match any GeoIPAllowFilters, rejecting connection");
468 allow_conn = -1;
469
470 } else {
471 pr_trace_msg(trace_channel, 9,
472 "allowing client connection (policy 'deny,allow')");
473 }
474 break;
475 }
476
477 return allow_conn;
478 }
479
get_geoip_filter_name(int filter_id)480 static const char *get_geoip_filter_name(int filter_id) {
481 register unsigned int i;
482
483 for (i = 0; geoip_filter_keys[i].filter_name != NULL; i++) {
484 if (geoip_filter_keys[i].filter_id == filter_id) {
485 return geoip_filter_keys[i].filter_name;
486 }
487 }
488
489 errno = ENOENT;
490 return NULL;
491 }
492
get_geoip_filter_value(int filter_id)493 static const char *get_geoip_filter_value(int filter_id) {
494 switch (filter_id) {
495 case GEOIP_FILTER_KEY_COUNTRY_CODE:
496 if (geoip_country_code2 != NULL) {
497 return geoip_country_code2;
498 }
499 break;
500
501 case GEOIP_FILTER_KEY_COUNTRY_CODE3:
502 if (geoip_country_code3 != NULL) {
503 return geoip_country_code3;
504 }
505 break;
506
507 case GEOIP_FILTER_KEY_COUNTRY_NAME:
508 if (geoip_country_name != NULL) {
509 return geoip_country_name;
510 }
511 break;
512
513 case GEOIP_FILTER_KEY_REGION_CODE:
514 if (geoip_region_code != NULL) {
515 return geoip_region_code;
516 }
517 break;
518
519 case GEOIP_FILTER_KEY_REGION_NAME:
520 if (geoip_region_name != NULL) {
521 return geoip_region_name;
522 }
523 break;
524
525 case GEOIP_FILTER_KEY_CONTINENT:
526 if (geoip_continent_name != NULL) {
527 return geoip_continent_name;
528 }
529 break;
530
531 case GEOIP_FILTER_KEY_ISP:
532 if (geoip_isp != NULL) {
533 return geoip_isp;
534 }
535 break;
536
537 case GEOIP_FILTER_KEY_ORGANIZATION:
538 if (geoip_org != NULL) {
539 return geoip_org;
540 }
541 break;
542
543 case GEOIP_FILTER_KEY_NETWORK_SPEED:
544 if (geoip_network_speed != NULL) {
545 return geoip_network_speed;
546 }
547 break;
548
549 case GEOIP_FILTER_KEY_CITY:
550 if (geoip_city != NULL) {
551 return geoip_city;
552 }
553 break;
554
555 case GEOIP_FILTER_KEY_AREA_CODE:
556 if (geoip_area_code != NULL) {
557 return geoip_area_code;
558 }
559 break;
560
561 case GEOIP_FILTER_KEY_POSTAL_CODE:
562 if (geoip_postal_code != NULL) {
563 return geoip_postal_code;
564 }
565 break;
566
567 case GEOIP_FILTER_KEY_LATITUDE:
568 if (geoip_latitude != NULL) {
569 return geoip_latitude;
570 }
571 break;
572
573 case GEOIP_FILTER_KEY_LONGITUDE:
574 if (geoip_longitude != NULL) {
575 return geoip_longitude;
576 }
577 break;
578
579 case GEOIP_FILTER_KEY_ASN:
580 if (geoip_asn != NULL) {
581 return geoip_asn;
582 }
583 break;
584
585 case GEOIP_FILTER_KEY_PROXY:
586 if (geoip_proxy != NULL) {
587 return geoip_proxy;
588 }
589 break;
590
591 case GEOIP_FILTER_KEY_TIMEZONE:
592 if (geoip_timezone != NULL) {
593 return geoip_timezone;
594 }
595 break;
596 }
597
598 errno = ENOENT;
599 return NULL;
600 }
601
get_geoip_tables(array_header * geoips,int filter_flags,int skip_standard)602 static void get_geoip_tables(array_header *geoips, int filter_flags,
603 int skip_standard) {
604 config_rec *c;
605
606 c = find_config(main_server->conf, CONF_PARAM, "GeoIPTable", FALSE);
607 while (c) {
608 GeoIP *gi;
609 const char *path;
610 int flags, use_utf8 = FALSE;
611
612 pr_signals_handle();
613
614 path = c->argv[0];
615 flags = *((int *) c->argv[1]);
616 use_utf8 = *((int *) c->argv[2]);
617
618 /* Make sure we open tables that are marked with the default
619 * GEOIP_STANDARD flag, which has a value of zero.
620 */
621 if (flags == GEOIP_STANDARD && skip_standard == TRUE) {
622 pr_trace_msg(trace_channel, 15,
623 "skipping loading GeoIP table '%s'", path);
624 c = find_config_next(c, c->next, CONF_PARAM, "GeoIPTable", FALSE);
625 continue;
626 }
627
628 PRIVS_ROOT
629 gi = GeoIP_open(path, flags);
630 if (gi == NULL &&
631 (flags & GEOIP_INDEX_CACHE)) {
632 /* Per Bug#3975, a common cause of this error is the fact that some
633 * of the Maxmind GeoIP Lite database files simply do not have indexes.
634 * So try to open them as standard databases as a fallback.
635 */
636 pr_log_debug(DEBUG8, MOD_GEOIP_VERSION
637 ": unable to open GeoIPTable '%s' using the IndexCache flag "
638 "(database lacks index?), retrying without IndexCache flag", path);
639 flags &= ~GEOIP_INDEX_CACHE;
640 gi = GeoIP_open(path, flags);
641 }
642 PRIVS_RELINQUISH
643
644 if (gi != NULL) {
645 if (use_utf8) {
646 GeoIP_set_charset(gi, GEOIP_CHARSET_UTF8);
647 }
648
649 *((GeoIP **) push_array(geoips)) = gi;
650
651 pr_trace_msg(trace_channel, 15, "loaded GeoIP table '%s': %s (type %d)",
652 path, GeoIP_database_info(gi), GeoIP_database_edition(gi));
653
654 } else {
655 /* XXX Sigh. Stupid libGeoIP library logs to stdout/stderr, rather
656 * than providing a strerror function. Grr!
657 */
658
659 pr_log_pri(PR_LOG_WARNING, MOD_GEOIP_VERSION
660 ": warning: unable to open/use GeoIPTable '%s'", path);
661 }
662
663 c = find_config_next(c, c->next, CONF_PARAM, "GeoIPTable", FALSE);
664 }
665
666 if (geoips->nelts == 0 &&
667 static_geoips->nelts == 0 &&
668 ((filter_flags == GEOIP_STANDARD) ||
669 (filter_flags & GEOIP_CHECK_CACHE))) {
670 GeoIP *gi;
671
672 /* Let the library use its own default database file(s), if no others
673 * have been configured.
674 */
675
676 PRIVS_ROOT
677 gi = GeoIP_new(GEOIP_STANDARD);
678 PRIVS_RELINQUISH
679
680 if (gi != NULL) {
681 *((GeoIP **) push_array(geoips)) = gi;
682
683 pr_trace_msg(trace_channel, 15,
684 "loaded default GeoIP table: %s (type %d)",
685 GeoIP_database_info(gi), GeoIP_database_edition(gi));
686
687 } else {
688 pr_log_pri(PR_LOG_WARNING, MOD_GEOIP_VERSION
689 ": warning: unable to open/use default GeoIP library database file(s)");
690 }
691 }
692 }
693
remove_geoip_tables(array_header * geoips)694 static void remove_geoip_tables(array_header *geoips) {
695 register unsigned int i;
696 GeoIP **gis;
697
698 if (geoips == NULL ||
699 geoips->nelts == 0) {
700 return;
701 }
702
703 gis = geoips->elts;
704 for (i = 0; i < geoips->nelts; i++) {
705 if (gis[i] != NULL) {
706 GeoIP_delete(gis[i]);
707 gis[i] = NULL;
708 }
709 }
710 }
711
get_geoip_data(array_header * geoips,const char * ip_addr)712 static void get_geoip_data(array_header *geoips, const char *ip_addr) {
713 register unsigned int i;
714 GeoIP **gis;
715
716 gis = geoips->elts;
717 for (i = 0; i < geoips->nelts; i++) {
718 unsigned char db_type = -1;
719
720 if (gis[i] == NULL) {
721 continue;
722 }
723
724 db_type = GeoIP_database_edition(gis[i]);
725
726 /* These types are defined in <GeoIP.h>'s GeoIPDBTypes enum. */
727 switch (db_type) {
728 case GEOIP_COUNTRY_EDITION:
729 case GEOIP_COUNTRY_EDITION_V6: {
730 int geoip_id;
731
732 geoip_id = GeoIP_id_by_addr(gis[i], ip_addr);
733 #ifdef PR_USE_IPV6
734 if (geoip_id <= 0 &&
735 pr_netaddr_use_ipv6()) {
736
737 pr_trace_msg(trace_channel, 2,
738 "unable to find GeoIP country ID for IP address '%s', "
739 "attempting lookup as IPv6 address", ip_addr);
740
741 /* Try looking up the GeoIP ID using their IPv6 API. */
742 geoip_id = GeoIP_id_by_addr_v6(gis[i], ip_addr);
743 }
744 #endif /* PR_USE_IPV6 */
745
746 if (geoip_id <= 0) {
747 break;
748 }
749
750 geoip_continent_name = GeoIP_continent_by_id(geoip_id);
751 geoip_country_code2 = GeoIP_code_by_id(geoip_id);
752 geoip_country_code3 = GeoIP_code3_by_id(geoip_id);
753 geoip_country_name = GeoIP_name_by_id(geoip_id);
754
755 break;
756 }
757
758 case GEOIP_NETSPEED_EDITION: {
759 int geoip_id;
760
761 /* Apparently for NetSpeed database files, the GeoIP ID indicates
762 * the speed, via the GeoIPNetspeedValues enum.
763 */
764 geoip_id = GeoIP_id_by_addr(gis[i], ip_addr);
765 #ifdef PR_USE_IPV6
766 if (geoip_id <= 0 &&
767 pr_netaddr_use_ipv6()) {
768
769 pr_trace_msg(trace_channel, 2,
770 "unable to find GeoIP network speed ID for IP address '%s', "
771 "attempting lookup as IPv6 address", ip_addr);
772
773 /* Try looking up the GeoIP ID using their IPv6 API. */
774 geoip_id = GeoIP_id_by_addr_v6(gis[i], ip_addr);
775 }
776 #endif /* PR_USE_IPV6 */
777
778 switch (geoip_id) {
779 case GEOIP_UNKNOWN_SPEED:
780 geoip_network_speed = "unknown";
781 break;
782
783 case GEOIP_DIALUP_SPEED:
784 geoip_network_speed = "dialup";
785 break;
786
787 case GEOIP_CABLEDSL_SPEED:
788 geoip_network_speed = "cabledsl";
789 break;
790
791 case GEOIP_CORPORATE_SPEED:
792 geoip_network_speed = "corporate";
793 break;
794
795 default:
796 (void) pr_log_writefile(geoip_logfd, MOD_GEOIP_VERSION,
797 "unknown netspeed value (%d), ignoring", geoip_id);
798 break;
799 }
800
801 break;
802 }
803
804 case GEOIP_ASNUM_EDITION:
805 geoip_asn = GeoIP_name_by_addr(gis[i], ip_addr);
806 #ifdef PR_USE_IPV6
807 if (geoip_asn == NULL &&
808 pr_netaddr_use_ipv6()) {
809
810 (void) pr_log_writefile(geoip_logfd, MOD_GEOIP_VERSION,
811 "unable to find GeoIP ASN for IP address '%s', "
812 "attempting lookup as IPv6 address", ip_addr);
813
814 /* Try looking up the GeoIP ASN using their IPv6 API. */
815 geoip_asn = GeoIP_name_by_addr_v6(gis[i], ip_addr);
816 }
817 #endif /* PR_USE_IPV6 */
818 break;
819
820 case GEOIP_ORG_EDITION:
821 geoip_org = GeoIP_name_by_addr(gis[i], ip_addr);
822 #ifdef PR_USE_IPV6
823 if (geoip_org == NULL &&
824 pr_netaddr_use_ipv6()) {
825
826 (void) pr_log_writefile(geoip_logfd, MOD_GEOIP_VERSION,
827 "unable to find GeoIP organization for IP address '%s', "
828 "attempting lookup as IPv6 address", ip_addr);
829
830 /* Try looking up the GeoIP name using their IPv6 API. */
831 geoip_org = GeoIP_name_by_addr_v6(gis[i], ip_addr);
832 }
833 #endif /* PR_USE_IPV6 */
834 break;
835
836 case GEOIP_ISP_EDITION:
837 geoip_isp = GeoIP_name_by_addr(gis[i], ip_addr);
838 #ifdef PR_USE_IPV6
839 if (geoip_isp == NULL &&
840 pr_netaddr_use_ipv6()) {
841
842 pr_trace_msg(trace_channel, 2,
843 "unable to find GeoIP ISP for IP address '%s', "
844 "attempting lookup as IPv6 address", ip_addr);
845
846 /* Try looking up the GeoIP name using their IPv6 API. */
847 geoip_isp = GeoIP_name_by_addr_v6(gis[i], ip_addr);
848 }
849 #endif /* PR_USE_IPV6 */
850 break;
851
852 case GEOIP_REGION_EDITION_REV0:
853 case GEOIP_REGION_EDITION_REV1: {
854 GeoIPRegion *geoip_region = NULL;
855 const char *region_name = NULL, *tz = NULL;
856
857 geoip_region = GeoIP_region_by_addr(gis[i], ip_addr);
858 #ifdef PR_USE_IPV6
859 if (geoip_region == NULL &&
860 pr_netaddr_use_ipv6()) {
861
862 pr_trace_msg(trace_channel, 2,
863 "unable to find GeoIP region for IP address '%s', "
864 "attempting lookup as IPv6 address", ip_addr);
865
866 /* Try looking up the GeoIP region using their IPv6 API. */
867 geoip_region = GeoIP_region_by_addr_v6(gis[i], ip_addr);
868 }
869 #endif /* PR_USE_IPV6 */
870
871 if (geoip_region == NULL) {
872 break;
873 }
874
875 if (geoip_region->region[0]) {
876 geoip_region_code = pstrdup(session.pool, geoip_region->region);
877 }
878
879 region_name = GeoIP_region_name_by_code(geoip_region->country_code,
880 geoip_region->region);
881 if (region_name != NULL) {
882 geoip_region_name = pstrdup(session.pool, region_name);
883 }
884
885 tz = GeoIP_time_zone_by_country_and_region(geoip_region->country_code,
886 geoip_region->region);
887 if (tz != NULL) {
888 geoip_timezone = pstrdup(session.pool, tz);
889 }
890
891 GeoIPRegion_delete(geoip_region);
892 break;
893 }
894
895 case GEOIP_CITY_EDITION_REV0:
896 case GEOIP_CITY_EDITION_REV1: {
897 GeoIPRecord *geoip_record = NULL;
898 char area_code_str[32], lat_str[64], lon_str[64];
899
900 geoip_record = GeoIP_record_by_addr(gis[i], ip_addr);
901 #ifdef PR_USE_IPV6
902 if (geoip_record == NULL &&
903 pr_netaddr_use_ipv6()) {
904
905 pr_trace_msg(trace_channel, 2,
906 "unable to find GeoIP city record for IP address '%s', "
907 "attempting lookup as IPv6 address", ip_addr);
908
909 /* Try looking up the GeoIP record using their IPv6 API. */
910 geoip_record = GeoIP_record_by_addr_v6(gis[i], ip_addr);
911 }
912 #endif /* PR_USE_IPV6 */
913
914 if (geoip_record == NULL) {
915 break;
916 }
917
918 /* We use pstrdup() here on the fields of the retrieved record,
919 * since the record is going to be freed once we're done, and we
920 * don't want to be holding on to stale pointers.
921 */
922 geoip_continent_name = pstrdup(session.pool,
923 geoip_record->continent_code);
924 geoip_country_code2 = pstrdup(session.pool, geoip_record->country_code);
925 geoip_country_code3 = pstrdup(session.pool, geoip_record->country_code3);
926 geoip_country_name = pstrdup(session.pool, geoip_record->country_name);
927
928 if (geoip_record->city != NULL) {
929 geoip_city = pstrdup(session.pool, geoip_record->city);
930 }
931
932 if (geoip_record->postal_code != NULL) {
933 geoip_postal_code = pstrdup(session.pool, geoip_record->postal_code);
934 }
935
936 memset(area_code_str, '\0', sizeof(area_code_str));
937 pr_snprintf(area_code_str, sizeof(area_code_str)-1, "%d",
938 geoip_record->area_code);
939 geoip_area_code = pstrdup(session.pool, area_code_str);
940
941 memset(lat_str, '\0', sizeof(lat_str));
942 pr_snprintf(lat_str, sizeof(lat_str)-1, "%f", geoip_record->latitude);
943 geoip_latitude = pstrdup(session.pool, lat_str);
944
945 memset(lon_str, '\0', sizeof(lon_str));
946 pr_snprintf(lon_str, sizeof(lon_str)-1, "%f", geoip_record->longitude);
947 geoip_longitude = pstrdup(session.pool, lon_str);
948
949 if (geoip_record->region != NULL &&
950 geoip_record->region[0]) {
951 geoip_region_code = pstrdup(session.pool, geoip_record->region);
952 }
953
954 if (geoip_record->country_code != NULL) {
955 const char *region_name, *tz;
956
957 region_name = GeoIP_region_name_by_code(geoip_record->country_code,
958 geoip_record->region);
959 if (region_name != NULL) {
960 geoip_region_name = pstrdup(session.pool, region_name);
961 }
962
963 tz = GeoIP_time_zone_by_country_and_region(
964 geoip_record->country_code, geoip_record->region);
965 if (tz != NULL) {
966 geoip_timezone = pstrdup(session.pool, tz);
967 }
968 }
969
970 GeoIPRecord_delete(geoip_record);
971 break;
972 }
973
974 case GEOIP_PROXY_EDITION: {
975 int geoip_id;
976
977 geoip_id = GeoIP_id_by_addr(gis[i], ip_addr);
978 #ifdef PR_USE_IPV6
979 if (geoip_id <= 0 &&
980 pr_netaddr_use_ipv6()) {
981
982 pr_trace_msg(trace_channel, 2,
983 "unable to find GeoIP proxy ID for IP address '%s', "
984 "attempting lookup as IPv6 address", ip_addr);
985
986 /* Try looking up the GeoIP ID using their IPv6 API. */
987 geoip_id = GeoIP_id_by_addr_v6(gis[i], ip_addr);
988 }
989 #endif /* PR_USE_IPV6 */
990
991 if (geoip_id == 0) {
992 break;
993 }
994
995 switch (geoip_id) {
996 case GEOIP_ANON_PROXY:
997 geoip_proxy = "anonymous";
998 break;
999
1000 default:
1001 (void) pr_log_writefile(geoip_logfd, MOD_GEOIP_VERSION,
1002 "unknown proxy value (%d), ignoring", geoip_id);
1003 break;
1004 }
1005
1006 break;
1007 }
1008
1009 default:
1010 (void) pr_log_writefile(geoip_logfd, MOD_GEOIP_VERSION,
1011 "unknown database type (%d), skipping", db_type);
1012 break;
1013 }
1014 }
1015 }
1016
get_geoip_info(array_header * sess_geoips)1017 static void get_geoip_info(array_header *sess_geoips) {
1018 const char *ip_addr;
1019
1020 ip_addr = pr_netaddr_get_ipstr(session.c->remote_addr);
1021
1022 get_geoip_data(static_geoips, ip_addr);
1023 get_geoip_data(sess_geoips, ip_addr);
1024
1025 if (geoip_country_code2 != NULL) {
1026 pr_trace_msg(trace_channel, 8, "%s: 2-Letter country code: %s", ip_addr,
1027 geoip_country_code2);
1028 }
1029
1030 if (geoip_country_code3 != NULL) {
1031 pr_trace_msg(trace_channel, 8, "%s: 3-Letter country code: %s", ip_addr,
1032 geoip_country_code3);
1033 }
1034
1035 if (geoip_country_name != NULL) {
1036 pr_trace_msg(trace_channel, 8, "%s: Country name: %s", ip_addr,
1037 geoip_country_name);
1038 }
1039
1040 if (geoip_region_code != NULL) {
1041 pr_trace_msg(trace_channel, 8, "%s: Region code: %s", ip_addr,
1042 geoip_region_code);
1043 }
1044
1045 if (geoip_region_name != NULL) {
1046 pr_trace_msg(trace_channel, 8, "%s: Region name: %s", ip_addr,
1047 geoip_region_name);
1048 }
1049
1050 if (geoip_timezone != NULL) {
1051 pr_trace_msg(trace_channel, 8, "%s: Timezone: %s", ip_addr, geoip_timezone);
1052 }
1053
1054 if (geoip_continent_name != NULL) {
1055 pr_trace_msg(trace_channel, 8, "%s: Continent name: %s", ip_addr,
1056 geoip_continent_name);
1057 }
1058
1059 if (geoip_isp != NULL) {
1060 pr_trace_msg(trace_channel, 8, "%s: ISP: %s", ip_addr, geoip_isp);
1061 }
1062
1063 if (geoip_org != NULL) {
1064 pr_trace_msg(trace_channel, 8, "%s: Organization: %s", ip_addr, geoip_org);
1065 }
1066
1067 if (geoip_network_speed != NULL) {
1068 pr_trace_msg(trace_channel, 8, "%s: Network speed: %s", ip_addr,
1069 geoip_network_speed);
1070 }
1071
1072 if (geoip_city != NULL) {
1073 pr_trace_msg(trace_channel, 8, "%s: City: %s", ip_addr, geoip_city);
1074 }
1075
1076 if (geoip_area_code != NULL) {
1077 pr_trace_msg(trace_channel, 8, "%s: Area code: %s", ip_addr,
1078 geoip_area_code);
1079 }
1080
1081 if (geoip_postal_code != NULL) {
1082 pr_trace_msg(trace_channel, 8, "%s: Postal code: %s", ip_addr,
1083 geoip_postal_code);
1084 }
1085
1086 if (geoip_latitude != NULL) {
1087 pr_trace_msg(trace_channel, 8, "%s: Latitude: %s", ip_addr,
1088 geoip_latitude);
1089 }
1090
1091 if (geoip_longitude != NULL) {
1092 pr_trace_msg(trace_channel, 8, "%s: Longitude: %s", ip_addr,
1093 geoip_longitude);
1094 }
1095
1096 if (geoip_asn != NULL) {
1097 pr_trace_msg(trace_channel, 8, "%s: ASN: %s", ip_addr, geoip_asn);
1098 }
1099
1100 if (geoip_proxy != NULL) {
1101 pr_trace_msg(trace_channel, 8, "%s: Proxy: %s", ip_addr, geoip_proxy);
1102 }
1103 }
1104
set_geoip_value(const char * key,const char * value)1105 static void set_geoip_value(const char *key, const char *value) {
1106 int res;
1107
1108 res = pr_env_set(session.pool, key, value);
1109 if (res < 0) {
1110 (void) pr_log_writefile(geoip_logfd, MOD_GEOIP_VERSION,
1111 "error setting %s environment variable: %s", key, strerror(errno));
1112 }
1113
1114 res = pr_table_add_dup(session.notes, pstrdup(session.pool, key),
1115 (char *) value, 0);
1116 if (res < 0) {
1117 (void) pr_log_writefile(geoip_logfd, MOD_GEOIP_VERSION,
1118 "error adding %s session note: %s", key, strerror(errno));
1119 }
1120 }
1121
set_geoip_values(void)1122 static void set_geoip_values(void) {
1123
1124 if (geoip_country_code2 != NULL) {
1125 set_geoip_value("GEOIP_COUNTRY_CODE", geoip_country_code2);
1126 }
1127
1128 if (geoip_country_code3 != NULL) {
1129 set_geoip_value("GEOIP_COUNTRY_CODE3", geoip_country_code3);
1130 }
1131
1132 if (geoip_country_name != NULL) {
1133 set_geoip_value("GEOIP_COUNTRY_NAME", geoip_country_name);
1134 }
1135
1136 if (geoip_region_code != NULL) {
1137 set_geoip_value("GEOIP_REGION", geoip_region_code);
1138 }
1139
1140 if (geoip_region_name != NULL) {
1141 set_geoip_value("GEOIP_REGION_NAME", geoip_region_name);
1142 }
1143
1144 if (geoip_continent_name != NULL) {
1145 set_geoip_value("GEOIP_CONTINENT_CODE", geoip_continent_name);
1146 }
1147
1148 if (geoip_isp != NULL) {
1149 set_geoip_value("GEOIP_ISP", geoip_isp);
1150 }
1151
1152 if (geoip_org != NULL) {
1153 set_geoip_value("GEOIP_ORGANIZATION", geoip_org);
1154 }
1155
1156 if (geoip_network_speed != NULL) {
1157 set_geoip_value("GEOIP_NETSPEED", geoip_network_speed);
1158 }
1159
1160 if (geoip_city != NULL) {
1161 set_geoip_value("GEOIP_CITY", geoip_city);
1162 }
1163
1164 if (geoip_area_code != NULL) {
1165 set_geoip_value("GEOIP_AREA_CODE", geoip_area_code);
1166 }
1167
1168 if (geoip_postal_code != NULL) {
1169 set_geoip_value("GEOIP_POSTAL_CODE", geoip_postal_code);
1170 }
1171
1172 if (geoip_latitude != NULL) {
1173 set_geoip_value("GEOIP_LATITUDE", geoip_latitude);
1174 }
1175
1176 if (geoip_longitude != NULL) {
1177 set_geoip_value("GEOIP_LONGITUDE", geoip_longitude);
1178 }
1179
1180 if (geoip_asn != NULL) {
1181 set_geoip_value("GEOIP_ASN", geoip_asn);
1182 }
1183
1184 if (geoip_proxy != NULL) {
1185 set_geoip_value("GEOIP_PROXY", geoip_proxy);
1186 }
1187
1188 if (geoip_timezone != NULL) {
1189 set_geoip_value("GEOIP_TIMEZONE", geoip_timezone);
1190 }
1191
1192 }
1193
1194 /* Configuration handlers
1195 */
1196
1197 /* usage:
1198 * GeoIPAllowFilter key1 regex1 [key2 regex2 ...]
1199 * sql:/...
1200 * GeoIPDenyFilter key1 regex1 [key2 regex2 ...]
1201 * sql:/...
1202 */
set_geoipfilter(cmd_rec * cmd)1203 MODRET set_geoipfilter(cmd_rec *cmd) {
1204 #if PR_USE_REGEX
1205 config_rec *c;
1206 array_header *deferred_patterns, *filters;
1207
1208 CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1209
1210 if (cmd->argc == 1) {
1211 CONF_ERROR(cmd, "wrong number of parameters");
1212 }
1213
1214 /* IFF the first parameter starts with "sql:/", then we expect ONLY one
1215 * parameter. If not, then we expect an even number of parameters.
1216 */
1217
1218 if (strncmp(cmd->argv[1], "sql:/", 5) == 0) {
1219 if (cmd->argc > 2) {
1220 CONF_ERROR(cmd, "wrong number of parameters");
1221 }
1222
1223 } else {
1224 if ((cmd->argc-1) % 2 != 0) {
1225 CONF_ERROR(cmd, "wrong number of parameters");
1226 }
1227 }
1228
1229 c = add_config_param(cmd->argv[0], 2, NULL, NULL);
1230 filters = make_array(c->pool, 0, sizeof(struct geoip_filter *));
1231 deferred_patterns = make_array(c->pool, 0, sizeof(char *));
1232
1233 if (cmd->argc == 2) {
1234 const char *pattern;
1235
1236 pattern = cmd->argv[1];
1237
1238 /* Advance past the "sql:/" prefix. */
1239 *((char **) push_array(deferred_patterns)) = pstrdup(c->pool, pattern + 5);
1240
1241 } else {
1242 register unsigned int i;
1243
1244 for (i = 1; i < cmd->argc; i += 2) {
1245 const char *filter_name, *pattern = NULL;
1246 struct geoip_filter *filter;
1247
1248 filter_name = cmd->argv[i];
1249 pattern = cmd->argv[i+1];
1250
1251 filter = make_filter(c->pool, filter_name, pattern);
1252 if (filter == NULL) {
1253 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "unable to use '",
1254 filter_name, " ", pattern, "' as filter: ", strerror(errno), NULL));
1255 }
1256
1257 *((struct geoip_filter **) push_array(filters)) = filter;
1258 }
1259 }
1260
1261 c->argv[0] = filters;
1262 c->argv[1] = deferred_patterns;
1263 return PR_HANDLED(cmd);
1264
1265 #else /* no regular expression support at the moment */
1266 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "The ", cmd->argv[0],
1267 " directive cannot be used on this system, as you do not have POSIX "
1268 "compliant regex support", NULL));
1269 #endif
1270 }
1271
1272 /* usage: GeoIPEngine on|off */
set_geoipengine(cmd_rec * cmd)1273 MODRET set_geoipengine(cmd_rec *cmd) {
1274 int bool = -1;
1275 config_rec *c = NULL;
1276
1277 CHECK_ARGS(cmd, 1);
1278 CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1279
1280 bool = get_boolean(cmd, 1);
1281 if (bool == -1)
1282 CONF_ERROR(cmd, "expected Boolean parameter");
1283
1284 c = add_config_param(cmd->argv[0], 1, NULL);
1285 c->argv[0] = pcalloc(c->pool, sizeof(int));
1286 *((int *) c->argv[0]) = bool;
1287
1288 return PR_HANDLED(cmd);
1289 }
1290
1291 /* usage: GeoIPLog path|"none" */
set_geoiplog(cmd_rec * cmd)1292 MODRET set_geoiplog(cmd_rec *cmd) {
1293 CHECK_ARGS(cmd, 1);
1294 CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1295
1296 (void) add_config_param_str(cmd->argv[0], 1, cmd->argv[1]);
1297 return PR_HANDLED(cmd);
1298 }
1299
1300 /* usage: GeoIPPolicy "allow,deny"|"deny,allow" */
set_geoippolicy(cmd_rec * cmd)1301 MODRET set_geoippolicy(cmd_rec *cmd) {
1302 geoip_policy_e policy;
1303 config_rec *c;
1304
1305 CHECK_ARGS(cmd, 1);
1306 CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1307
1308 if (strcasecmp(cmd->argv[1], "allow,deny") == 0) {
1309 policy = GEOIP_POLICY_ALLOW_DENY;
1310
1311 } else if (strcasecmp(cmd->argv[1], "deny,allow") == 0) {
1312 policy = GEOIP_POLICY_DENY_ALLOW;
1313
1314 } else {
1315 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, ": '", cmd->argv[1],
1316 "' is not one of the approved GeoIPPolicy settings", NULL));
1317 }
1318
1319 c = add_config_param(cmd->argv[0], 1, NULL);
1320 c->argv[0] = pcalloc(c->pool, sizeof(geoip_policy_e));
1321 *((geoip_policy_e *) c->argv[0]) = policy;
1322
1323 return PR_HANDLED(cmd);
1324 }
1325
1326 /* usage: GeoIPTable path [flags] */
set_geoiptable(cmd_rec * cmd)1327 MODRET set_geoiptable(cmd_rec *cmd) {
1328 config_rec *c;
1329 int flags = GEOIP_STANDARD, use_utf8 = FALSE;
1330 char *path;
1331
1332 CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1333
1334 if (cmd->argc < 2) {
1335 CONF_ERROR(cmd, "wrong number of parameters");
1336 }
1337
1338 path = cmd->argv[1];
1339
1340 if (cmd->argc > 2) {
1341 register unsigned int i;
1342
1343 for (i = 2; i < cmd->argc; i++) {
1344 if (strcasecmp(cmd->argv[i], "Standard") == 0) {
1345 /* No-op. */
1346
1347 } else if (strcasecmp(cmd->argv[i], "MemoryCache") == 0) {
1348 flags |= GEOIP_MEMORY_CACHE;
1349
1350 } else if (strcasecmp(cmd->argv[i], "MMapCache") == 0) {
1351 flags |= GEOIP_MMAP_CACHE;
1352
1353 } else if (strcasecmp(cmd->argv[i], "IndexCache") == 0) {
1354 flags |= GEOIP_INDEX_CACHE;
1355
1356 } else if (strcasecmp(cmd->argv[i], "CheckCache") == 0) {
1357 flags |= GEOIP_CHECK_CACHE;
1358
1359 } else if (strcasecmp(cmd->argv[i], "UTF8") == 0) {
1360 use_utf8 = TRUE;
1361
1362 } else {
1363 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "unknown GeoIPTable flag '",
1364 cmd->argv[i], "'", NULL));
1365 }
1366 }
1367 }
1368
1369 c = add_config_param(cmd->argv[0], 3, NULL, NULL, NULL);
1370 c->argv[0] = pstrdup(c->pool, path);
1371 c->argv[1] = palloc(c->pool, sizeof(int));
1372 *((int *) c->argv[1]) = flags;
1373 c->argv[2] = palloc(c->pool, sizeof(int));
1374 *((int *) c->argv[2]) = use_utf8;
1375
1376 return PR_HANDLED(cmd);
1377 }
1378
1379 /* Command handlers
1380 */
1381
geoip_post_pass(cmd_rec * cmd)1382 MODRET geoip_post_pass(cmd_rec *cmd) {
1383 int res;
1384
1385 if (geoip_engine == FALSE) {
1386 return PR_DECLINED(cmd);
1387 }
1388
1389 /* Scan for any deferred GeoIP filters and resolve them. */
1390 resolve_deferred_filters(cmd->tmp_pool);
1391
1392 /* Modules such as mod_ifsession may have added new filters; check the
1393 * filters again.
1394 */
1395 res = check_geoip_filters(geoip_policy);
1396 if (res < 0) {
1397 (void) pr_log_writefile(geoip_logfd, MOD_GEOIP_VERSION,
1398 "connection from %s denied due to GeoIP filter/policy",
1399 pr_netaddr_get_ipstr(session.c->remote_addr));
1400 pr_log_pri(PR_LOG_NOTICE, MOD_GEOIP_VERSION
1401 ": Connection denied to %s due to GeoIP filter/policy",
1402 pr_netaddr_get_ipstr(session.c->remote_addr));
1403
1404 pr_event_generate("mod_geoip.connection-denied", NULL);
1405 pr_session_disconnect(&geoip_module, PR_SESS_DISCONNECT_CONFIG_ACL,
1406 "GeoIP Filters");
1407 }
1408
1409 return PR_DECLINED(cmd);
1410 }
1411
1412 /* Event handlers
1413 */
1414
1415 #if defined(PR_SHARED_MODULE)
geoip_mod_unload_ev(const void * event_data,void * user_data)1416 static void geoip_mod_unload_ev(const void *event_data, void *user_data) {
1417 if (strcmp("mod_geoip.c", (const char *) event_data) == 0) {
1418 remove_geoip_tables(static_geoips);
1419 destroy_pool(geoip_pool);
1420
1421 /* Unregister ourselves from all events. */
1422 pr_event_unregister(&geoip_module, NULL, NULL);
1423 }
1424 }
1425 #endif /* PR_SHARED_MODULE */
1426
geoip_postparse_ev(const void * event_data,void * user_data)1427 static void geoip_postparse_ev(const void *event_data, void *user_data) {
1428 int filter_flags;
1429
1430 filter_flags = GEOIP_MEMORY_CACHE|GEOIP_MMAP_CACHE|GEOIP_INDEX_CACHE;
1431
1432 pr_log_debug(DEBUG8, MOD_GEOIP_VERSION ": loading static GeoIP tables");
1433 get_geoip_tables(static_geoips, filter_flags, TRUE);
1434 }
1435
geoip_restart_ev(const void * event_data,void * user_data)1436 static void geoip_restart_ev(const void *event_data, void *user_data) {
1437 remove_geoip_tables(static_geoips);
1438
1439 destroy_pool(geoip_pool);
1440
1441 geoip_pool = make_sub_pool(permanent_pool);
1442 pr_pool_tag(geoip_pool, MOD_GEOIP_VERSION);
1443
1444 static_geoips = make_array(geoip_pool, 0, sizeof(GeoIP *));
1445 }
1446
1447 /* Initialization functions
1448 */
1449
geoip_init(void)1450 static int geoip_init(void) {
1451 geoip_pool = make_sub_pool(permanent_pool);
1452 pr_pool_tag(geoip_pool, MOD_GEOIP_VERSION);
1453
1454 static_geoips = make_array(geoip_pool, 0, sizeof(GeoIP *));
1455
1456 #if defined(PR_SHARED_MODULE)
1457 pr_event_register(&geoip_module, "core.module-unload", geoip_mod_unload_ev,
1458 NULL);
1459 #endif /* PR_SHARED_MODULE */
1460 pr_event_register(&geoip_module, "core.postparse", geoip_postparse_ev, NULL);
1461 pr_event_register(&geoip_module, "core.restart", geoip_restart_ev, NULL);
1462
1463 return 0;
1464 }
1465
geoip_sess_init(void)1466 static int geoip_sess_init(void) {
1467 config_rec *c;
1468 array_header *sess_geoips;
1469 int res;
1470 pool *tmp_pool;
1471
1472 c = find_config(main_server->conf, CONF_PARAM, "GeoIPEngine", FALSE);
1473 if (c) {
1474 geoip_engine = *((int *) c->argv[0]);
1475 }
1476
1477 if (geoip_engine == FALSE) {
1478 return 0;
1479 }
1480
1481 c = find_config(main_server->conf, CONF_PARAM, "GeoIPLog", FALSE);
1482 if (c) {
1483 char *path;
1484
1485 path = c->argv[0];
1486 if (strcasecmp(path, "none") != 0) {
1487 int xerrno;
1488
1489 pr_signals_block();
1490 PRIVS_ROOT
1491 res = pr_log_openfile(path, &geoip_logfd, PR_LOG_SYSTEM_MODE);
1492 xerrno = errno;
1493 PRIVS_RELINQUISH
1494 pr_signals_unblock();
1495
1496 if (res < 0) {
1497 if (res == -1) {
1498 pr_log_pri(PR_LOG_NOTICE, MOD_GEOIP_VERSION
1499 ": notice: unable to open GeoIPLog '%s': %s", path,
1500 strerror(xerrno));
1501
1502 } else if (res == PR_LOG_WRITABLE_DIR) {
1503 pr_log_pri(PR_LOG_WARNING, MOD_GEOIP_VERSION
1504 ": notice: unable to open GeoIPLog '%s': parent directory is "
1505 "world-writable", path);
1506
1507 } else if (res == PR_LOG_SYMLINK) {
1508 pr_log_pri(PR_LOG_WARNING, MOD_GEOIP_VERSION
1509 ": notice: unable to open GeoIPLog '%s': cannot log to a symlink",
1510 path);
1511 }
1512 }
1513 }
1514 }
1515
1516 tmp_pool = make_sub_pool(geoip_pool);
1517 pr_pool_tag(tmp_pool, "GeoIP Session Pool");
1518
1519 sess_geoips = make_array(tmp_pool, 0, sizeof(GeoIP *));
1520
1521 pr_log_debug(DEBUG8, MOD_GEOIP_VERSION ": loading session GeoIP tables");
1522 get_geoip_tables(sess_geoips, GEOIP_CHECK_CACHE, FALSE);
1523
1524 if (static_geoips->nelts == 0 &&
1525 sess_geoips->nelts == 0) {
1526 (void) pr_log_writefile(geoip_logfd, MOD_GEOIP_VERSION,
1527 "no usable GeoIPTable files found, skipping GeoIP lookups");
1528
1529 (void) close(geoip_logfd);
1530 destroy_pool(tmp_pool);
1531 return 0;
1532 }
1533
1534 get_geoip_info(sess_geoips);
1535
1536 c = find_config(main_server->conf, CONF_PARAM, "GeoIPPolicy", FALSE);
1537 if (c != NULL) {
1538 geoip_policy = *((geoip_policy_e *) c->argv[0]);
1539 }
1540
1541 switch (geoip_policy) {
1542 case GEOIP_POLICY_ALLOW_DENY:
1543 pr_trace_msg(trace_channel, 8,
1544 "using policy of allowing connections unless rejected by "
1545 "GeoIPDenyFilters");
1546 break;
1547
1548 case GEOIP_POLICY_DENY_ALLOW:
1549 pr_trace_msg(trace_channel, 8,
1550 "using policy of rejecting connections unless allowed by "
1551 "GeoIPAllowFilters");
1552 break;
1553 }
1554
1555 res = check_geoip_filters(geoip_policy);
1556 if (res < 0) {
1557 (void) pr_log_writefile(geoip_logfd, MOD_GEOIP_VERSION,
1558 "connection from %s denied due to GeoIP filter/policy",
1559 pr_netaddr_get_ipstr(session.c->remote_addr));
1560 pr_log_pri(PR_LOG_NOTICE, MOD_GEOIP_VERSION
1561 ": Connection denied to %s due to GeoIP filter/policy",
1562 pr_netaddr_get_ipstr(session.c->remote_addr));
1563
1564 pr_event_generate("mod_geoip.connection-denied", NULL);
1565
1566 /* XXX send_geoip_mesg(tmp_pool, mesg) */
1567 destroy_pool(tmp_pool);
1568
1569 errno = EACCES;
1570 return -1;
1571 }
1572
1573 set_geoip_values();
1574 remove_geoip_tables(sess_geoips);
1575
1576 destroy_pool(tmp_pool);
1577 return 0;
1578 }
1579
1580 /* Module API tables
1581 */
1582
1583 static conftable geoip_conftab[] = {
1584 { "GeoIPAllowFilter", set_geoipfilter, NULL },
1585 { "GeoIPDenyFilter", set_geoipfilter, NULL },
1586 { "GeoIPEngine", set_geoipengine, NULL },
1587 { "GeoIPLog", set_geoiplog, NULL },
1588 { "GeoIPPolicy", set_geoippolicy, NULL },
1589 { "GeoIPTable", set_geoiptable, NULL },
1590 { NULL }
1591 };
1592
1593 static cmdtable geoip_cmdtab[] = {
1594 { POST_CMD, C_PASS, G_NONE, geoip_post_pass, FALSE, FALSE },
1595 { 0, NULL },
1596 };
1597
1598 module geoip_module = {
1599 NULL, NULL,
1600
1601 /* Module API version 2.0 */
1602 0x20,
1603
1604 /* Module name */
1605 "geoip",
1606
1607 /* Module configuration handler table */
1608 geoip_conftab,
1609
1610 /* Module command handler table */
1611 geoip_cmdtab,
1612
1613 /* Module authentication handler table */
1614 NULL,
1615
1616 /* Module initialization function */
1617 geoip_init,
1618
1619 /* Session initialization function */
1620 geoip_sess_init,
1621
1622 /* Module version */
1623 MOD_GEOIP_VERSION
1624 };
1625