]> jfr.im git - irc/freenode/syn.git/blame - gateways.c
Add IRCCloud cloaking type
[irc/freenode/syn.git] / gateways.c
CommitLineData
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 25static void check_user(hook_user_nick_t *data, bool isnewuser);
db50fe63
SB
26static bool maybe_kline_user_host(user_t *u, const char *hostname);
27
33ca2ed9 28static 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
40static void gateway_newuser(hook_user_nick_t *data)
41{
42 check_user(data, true);
43}
44
492a4dc0 45static 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 60static 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
66static 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 81static 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
167DECLARE_MODULE_V1
168(
169 "syn/gateways", false, mod_init, mod_deinit,
170 "$Revision$",
171 "Stephen Bennett <stephen -at- freenode.net>"
172);