]>
Commit | Line | Data |
---|---|---|
0a30e865 SB |
1 | /* |
2 | * syn: a utility bot to manage IRC network access | |
3 | * Copyright (C) 2009-2016 Stephen Bennett | |
4 | * | |
5 | * This program is free software: you can redistribute it and/or modify | |
6 | * it under the terms of the GNU Affero General Public License as | |
7 | * published by the Free Software Foundation, either version 3 of the | |
8 | * License, or (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 Affero General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU Affero General Public License | |
16 | * along with this program. If not, see <https://www.gnu.org/licenses/>. | |
17 | */ | |
18 | ||
19 | ||
1686d5bf | 20 | #include "atheme.h" |
8e4107c1 | 21 | #include "uplink.h" |
1686d5bf SB |
22 | |
23 | #include "syn.h" | |
24 | ||
094d4924 | 25 | static void check_user(hook_user_nick_t *data, bool isnewuser); |
db50fe63 SB |
26 | static bool maybe_kline_user_host(user_t *u, const char *hostname); |
27 | ||
33ca2ed9 | 28 | static void check_all_users(void *v) |
1686d5bf SB |
29 | { |
30 | user_t *u; | |
31 | mowgli_patricia_iteration_state_t state; | |
32 | ||
33ca2ed9 SB |
33 | MOWGLI_PATRICIA_FOREACH(u, &state, userlist) |
34 | { | |
52b278d6 | 35 | hook_user_nick_t data = { .u = u }; |
094d4924 | 36 | check_user(&data, false); |
33ca2ed9 SB |
37 | } |
38 | } | |
39 | ||
094d4924 SB |
40 | static void gateway_newuser(hook_user_nick_t *data) |
41 | { | |
42 | check_user(data, true); | |
43 | } | |
44 | ||
492a4dc0 | 45 | static void mod_init(module_t *m) |
33ca2ed9 | 46 | { |
1686d5bf | 47 | use_syn_main_symbols(m); |
345beb92 | 48 | use_syn_util_symbols(m); |
1686d5bf SB |
49 | use_syn_kline_symbols(m); |
50 | ||
51 | hook_add_event("user_add"); | |
a3064be2 | 52 | hook_add_user_add(gateway_newuser); |
33ca2ed9 SB |
53 | hook_add_event("syn_kline_added"); |
54 | hook_add_hook("syn_kline_added", check_all_users); | |
41bf8d8d | 55 | hook_add_event("syn_kline_check"); |
1686d5bf | 56 | |
33ca2ed9 | 57 | check_all_users(NULL); |
1686d5bf SB |
58 | } |
59 | ||
492a4dc0 | 60 | static void mod_deinit(module_unload_intent_t intent) |
1686d5bf | 61 | { |
a3064be2 | 62 | hook_del_user_add(gateway_newuser); |
4c8b1a23 | 63 | hook_del_hook("syn_kline_added", check_all_users); |
db50fe63 SB |
64 | } |
65 | ||
66 | static bool maybe_kline_user_host(user_t *u, const char *hostname) | |
67 | { | |
68 | kline_t *k = syn_find_kline(NULL, hostname); | |
69 | ||
70 | if (k) | |
71 | { | |
72 | syn_report("Killing user %s; reported host [%s] matches K:line [%s@%s] (%s)", | |
73 | u->nick, hostname, k->user, k->host, k->reason); | |
74 | syn_kill(u, "Your reported hostname [%s] is banned: %s", hostname, k->reason); | |
75 | return true; | |
76 | } | |
77 | ||
78 | return false; | |
1686d5bf SB |
79 | } |
80 | ||
094d4924 | 81 | static void check_user(hook_user_nick_t *data, bool isnewuser) |
1686d5bf | 82 | { |
a3064be2 | 83 | user_t *u = data->u; |
1686d5bf | 84 | |
3cafe86e SB |
85 | /* If the user has already been killed, don't try to do anything */ |
86 | if (!u) | |
87 | return; | |
88 | ||
d2b5e766 SB |
89 | // If they've been marked as not having a decodeable IP address, don't try again. |
90 | if (u->flags & SYN_UF_NO_GATEWAY_IP) | |
91 | return; | |
92 | ||
b918d5d9 | 93 | const char *ident = u->user; |
1686d5bf SB |
94 | if (*ident == '~') |
95 | ++ident; | |
96 | ||
97 | const char *identhost = decode_hex_ip(ident); | |
98 | ||
c96aa998 | 99 | if (identhost && strcmp(identhost, u->ip) != 0) |
1686d5bf | 100 | { |
db50fe63 | 101 | if (maybe_kline_user_host(u, identhost)) |
1686d5bf | 102 | { |
3cafe86e | 103 | data->u = NULL; |
1686d5bf SB |
104 | return; |
105 | } | |
41bf8d8d SB |
106 | |
107 | // Ident not K:lined(yet); check whether it should be | |
108 | // Note that this happens after the K:line check; if this hook adds a | |
109 | // new kline, then we'll be called again through the syn_kline_add hook | |
e27c00bd | 110 | syn_kline_check_data_t d = { identhost, u, 0 }; |
41bf8d8d SB |
111 | hook_call_event("syn_kline_check", &d); |
112 | ||
e27c00bd SB |
113 | // If a kline was added by this, then we got called again and have already killed the user if we should. |
114 | // Don't do any more. | |
115 | if (d.added) | |
75e9e2a0 SB |
116 | { |
117 | // On the off-chance that a kline was added that doesn't in fact kill this user, this will cause | |
118 | // subsequent checks (facilities etc) to be skipped. That's better than crashing or running amok | |
119 | // because we tried to gateway-cloak an already-dead user, though. | |
2a50eb4a | 120 | data->u = NULL; |
e27c00bd | 121 | return; |
75e9e2a0 | 122 | } |
8e4107c1 | 123 | |
094d4924 SB |
124 | if (isnewuser) |
125 | { | |
126 | // They weren't already K:lined, and we didn't K:line them. BOPM may want to, though... | |
127 | sts(":%s ENCAP * SNOTE F :Client connecting: %s (%s@%s) [%s] {%s} [%s]", | |
128 | ME, u->nick, u->user, u->host, identhost, "?", u->gecos); | |
129 | } | |
1686d5bf | 130 | } |
d2b5e766 SB |
131 | else |
132 | { | |
133 | // Performance hack: if we can't decode a hex IP, assume that this user is not connecting through a | |
134 | // gateway that makes any attempt to identify them, and skip them for all future checks. | |
135 | u->flags |= SYN_UF_NO_GATEWAY_IP; | |
136 | return; | |
137 | } | |
00e3919f | 138 | |
41b17fdc SB |
139 | char gecos[GECOSLEN]; |
140 | strncpy(gecos, u->gecos, GECOSLEN); | |
00e3919f SB |
141 | char *p = strchr(gecos, ' '); |
142 | if (p != NULL) | |
143 | *p = '\0'; | |
144 | ||
145 | p = strchr(gecos, '/'); | |
146 | if (p != NULL) | |
147 | *p++ = '\0'; | |
148 | ||
db50fe63 | 149 | if (maybe_kline_user_host(u, gecos)) |
00e3919f | 150 | { |
3cafe86e | 151 | data->u = NULL; |
00e3919f SB |
152 | return; |
153 | } | |
db50fe63 | 154 | else if (p && maybe_kline_user_host(u, p)) |
00e3919f | 155 | { |
3cafe86e | 156 | data->u = NULL; |
00e3919f SB |
157 | return; |
158 | } | |
41bf8d8d SB |
159 | |
160 | // As above, but for gecos hostnames | |
161 | syn_kline_check_data_t d = { gecos, u }; | |
162 | hook_call_event("syn_kline_check", &d); | |
163 | d.ip = p; | |
164 | hook_call_event("syn_kline_check", &d); | |
1686d5bf | 165 | } |
db50fe63 | 166 | |
492a4dc0 JK |
167 | DECLARE_MODULE_V1 |
168 | ( | |
169 | "syn/gateways", false, mod_init, mod_deinit, | |
170 | "$Revision$", | |
171 | "Stephen Bennett <stephen -at- freenode.net>" | |
172 | ); |