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