]> jfr.im git - irc/quakenet/snircd-patchqueue.git/blob - remotemode.patch
nickgline: include nick! bit in gline loggin
[irc/quakenet/snircd-patchqueue.git] / remotemode.patch
1 # HG changeset patch
2 # Parent 37c9c74606033a6520033f95aa61690a8e4bcadd
3
4 # add REMOTEMODE (P10 token RM) allowing a service do change certain modes on users
5 # <source numeric server> RM <target numeric user> <mode changes and arguments> (note: no : prefixing last parameter)
6 # only allow +-diwRnIx, allow +h <user@host> and -h (so we dont need remote sethost/SH token anymore), other modes are not allowed to be set remotely
7 # usermode x can only be set, not unset (same as normal)
8 # usermode h can only be unset, if the user is +rx (or +r and allowed to set +x) - this prevents exposing the realhost out of the blue
9 # easy to add/remove modes
10 # REMOTEMODE travels from source server to victim server, from where a normal usermode change is broadcasted to the network
11 # unfortunately the code is a bit messy because of the sethost stuff, should we in the future accept the sethost.patch (see queue), it can be cleaned up quite a bit
12 # after snircd1.3.5 this patch will be moved further down in the patch queue, to clean up the sethost part, and add other usermodes such as +q
13
14 diff -r 37c9c7460603 include/handlers.h
15 --- a/include/handlers.h
16 +++ b/include/handlers.h
17 @@ -225,6 +225,7 @@
18 extern int ms_privs(struct Client*, struct Client*, int, char*[]);
19 extern int ms_quit(struct Client*, struct Client*, int, char*[]);
20 extern int ms_reburst(struct Client*, struct Client*, int, char*[]);
21 +extern int ms_remotemode(struct Client*, struct Client*, int, char*[]);
22 extern int ms_rping(struct Client*, struct Client*, int, char*[]);
23 extern int ms_rpong(struct Client*, struct Client*, int, char*[]);
24 extern int ms_server(struct Client*, struct Client*, int, char*[]);
25 diff -r 37c9c7460603 include/msg.h
26 --- a/include/msg.h
27 +++ b/include/msg.h
28 @@ -368,6 +368,10 @@
29 #define TOK_REBURST "RB"
30 #define CMD_REBURST MSG_REBURST, TOK_REBURST
31
32 +#define MSG_REMOTEMODE "REMOTEMODE" /* REMOTEMODE */
33 +#define TOK_REMOTEMODE "RM"
34 +#define CMD_REMOTEMODE MSG_REMOTEMODE, TOK_REMOTEMODE
35 +
36 #define MSG_CAP "CAP"
37 #define TOK_CAP "CAP"
38 #define CMD_CAP MSG_CAP, TOK_CAP
39 diff -r 37c9c7460603 ircd/Makefile.in
40 --- a/ircd/Makefile.in
41 +++ b/ircd/Makefile.in
42 @@ -163,6 +163,7 @@
43 m_quit.c \
44 m_reburst.c \
45 m_rehash.c \
46 + m_remotemode.c \
47 m_reset.c \
48 m_restart.c \
49 m_rping.c \
50 diff -r 37c9c7460603 ircd/m_remotemode.c
51 --- /dev/null
52 +++ b/ircd/m_remotemode.c
53 @@ -0,0 +1,359 @@
54 +/*
55 + * IRC - Internet Relay Chat, ircd/m_mode.c
56 + * Copyright (C) 1990 Jarkko Oikarinen and
57 + * University of Oulu, Computing Center
58 + *
59 + * See file AUTHORS in IRC package for additional names of
60 + * the programmers.
61 + *
62 + * This program is free software; you can redistribute it and/or modify
63 + * it under the terms of the GNU General Public License as published by
64 + * the Free Software Foundation; either version 1, or (at your option)
65 + * any later version.
66 + *
67 + * This program is distributed in the hope that it will be useful,
68 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
69 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
70 + * GNU General Public License for more details.
71 + *
72 + * You should have received a copy of the GNU General Public License
73 + * along with this program; if not, write to the Free Software
74 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
75 + *
76 + * $Id: m_mode.c 1818 2007-07-14 02:40:01Z isomer $
77 + */
78 +
79 +/*
80 + * m_functions execute protocol messages on this server:
81 + *
82 + * cptr is always NON-NULL, pointing to a *LOCAL* client
83 + * structure (with an open socket connected!). This
84 + * identifies the physical socket where the message
85 + * originated (or which caused the m_function to be
86 + * executed--some m_functions may call others...).
87 + *
88 + * sptr is the source of the message, defined by the
89 + * prefix part of the message if present. If not
90 + * or prefix not found, then sptr==cptr.
91 + *
92 + * (!IsServer(cptr)) => (cptr == sptr), because
93 + * prefixes are taken *only* from servers...
94 + *
95 + * (IsServer(cptr))
96 + * (sptr == cptr) => the message didn't
97 + * have the prefix.
98 + *
99 + * (sptr != cptr && IsServer(sptr) means
100 + * the prefix specified servername. (?)
101 + *
102 + * (sptr != cptr && !IsServer(sptr) means
103 + * that message originated from a remote
104 + * user (not local).
105 + *
106 + * combining
107 + *
108 + * (!IsServer(sptr)) means that, sptr can safely
109 + * taken as defining the target structure of the
110 + * message in this server.
111 + *
112 + * *Always* true (if 'parse' and others are working correct):
113 + *
114 + * 1) sptr->from == cptr (note: cptr->from == cptr)
115 + *
116 + * 2) MyConnect(sptr) <=> sptr == cptr (e.g. sptr
117 + * *cannot* be a local connection, unless it's
118 + * actually cptr!). [MyConnect(x) should probably
119 + * be defined as (x == x->from) --msa ]
120 + *
121 + * parc number of variable parameter strings (if zero,
122 + * parv is allowed to be NULL)
123 + *
124 + * parv a NULL terminated list of parameter pointers,
125 + *
126 + * parv[0], sender (prefix string), if not present
127 + * this points to an empty string.
128 + * parv[1]...parv[parc-1]
129 + * pointers to additional parameters
130 + * parv[parc] == NULL, *always*
131 + *
132 + * note: it is guaranteed that parv[0]..parv[parc-1] are all
133 + * non-NULL pointers.
134 + */
135 +
136 +#include "config.h"
137 +
138 +#include "channel.h"
139 +#include "client.h"
140 +#include "ircd_features.h"
141 +#include "ircd_log.h"
142 +#include "ircd_reply.h"
143 +#include "ircd_string.h"
144 +#include "ircd_snprintf.h"
145 +#include "msg.h"
146 +#include "msgq.h"
147 +#include "numeric.h"
148 +#include "querycmds.h"
149 +#include "s_conf.h"
150 +#include "s_debug.h"
151 +#include "s_user.h"
152 +#include "send.h"
153 +#include "struct.h"
154 +#include "numnicks.h"
155 +
156 +#include <stdlib.h>
157 +
158 +/**
159 + * ms_remotemode - remotemode server message handler
160 + *
161 + * parv[0] = sender prefix
162 + * parv[1] = target user numeric
163 + * parv[2+] = mode and arguments
164 + *
165 + */
166 +int ms_remotemode(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
167 +{
168 + char *target;
169 + struct Client *acptr;
170 + struct Flags setflags;
171 + struct Membership *chan;
172 +
173 + char** p;
174 + char* m;
175 + char *hostmask;
176 + char *user = NULL;
177 + char *host = NULL;
178 + char hiddenhost[USERLEN + HOSTLEN + 2];
179 + int what = MODE_ADD;
180 + int do_host_hiding = 0;
181 + int do_set_host = 0;
182 +
183 + /* not from a server */
184 + if (!IsServer(sptr))
185 + return protocol_violation(cptr, "Received REMOTEMODE from user %C", sptr);
186 +
187 + /* check paramaters */
188 + if (parc < 3)
189 + return protocol_violation(cptr, "Received too few parameters for REMOTEMODE from %C (got %d - need at least 3)", parc, sptr);
190 +
191 + target = parv[1];
192 +
193 + /* find user */
194 + if(!(acptr = findNUser(target)))
195 + return 0;
196 +
197 + /* TODO: how to pass along all params in an easy way? */
198 + /* not for my user, pass it along */
199 + if (!MyConnect(acptr)) {
200 + sendcmdto_one(sptr, CMD_REMOTEMODE, acptr, "%C %s %s %s %s %s %s %s %s %s %s %s %s %s", acptr,
201 + parv[2],
202 + parc > 3 ? parv[3] : "",
203 + parc > 4 ? parv[4] : "",
204 + parc > 5 ? parv[5] : "",
205 + parc > 6 ? parv[6] : "",
206 + parc > 7 ? parv[7] : "",
207 + parc > 8 ? parv[8] : "",
208 + parc > 9 ? parv[9] : "",
209 + parc > 10 ? parv[10] : "",
210 + parc > 11 ? parv[11] : "",
211 + parc > 12 ? parv[12] : "",
212 + parc > 13 ? parv[13] : "",
213 + parc > 14 ? parv[14] : "");
214 + return 0;
215 + }
216 +
217 + /* backup flags */
218 + setflags = cli_flags(acptr);
219 +
220 + /* parse mode change string(s) */
221 + for (p = &parv[2]; *p && p<&parv[parc]; p++) { /* p is changed in loop too */
222 + for (m = *p; *m; m++) {
223 + switch (*m) {
224 + case '+':
225 + what = MODE_ADD;
226 + break;
227 + case '-':
228 + what = MODE_DEL;
229 + break;
230 + case 'w':
231 + if (what == MODE_ADD)
232 + SetWallops(acptr);
233 + else
234 + ClearWallops(acptr);
235 + break;
236 + case 'i':
237 + if (what == MODE_ADD)
238 + SetInvisible(acptr);
239 + else
240 + ClearInvisible(acptr);
241 + break;
242 + case 'd':
243 + if (what == MODE_ADD)
244 + SetDeaf(acptr);
245 + else
246 + ClearDeaf(acptr);
247 + break;
248 + case 'n':
249 + if (what == MODE_ADD)
250 + SetNoChan(acptr);
251 + else
252 + ClearNoChan(acptr);
253 + break;
254 + case 'I':
255 + if (what == MODE_ADD)
256 + SetNoIdle(acptr);
257 + else
258 + ClearNoIdle(acptr);
259 + break;
260 + case 'R':
261 + if (what == MODE_ADD)
262 + SetAccountOnly(acptr);
263 + else
264 + ClearAccountOnly(acptr);
265 + break;
266 + case 'x':
267 + if (what == MODE_ADD)
268 + do_host_hiding = 1;
269 + break;
270 + case 'h':
271 + if (what == MODE_ADD) {
272 + if (*(p + 1) && is_hostmask(*(p + 1))) {
273 + do_set_host = 1;
274 + hostmask = *++p;
275 + } else {
276 + if (!*(p+1))
277 + protocol_violation(sptr, "Received REMOTEMODE +h without host parameter for user %C", acptr);
278 + else {
279 + protocol_violation(sptr, "Received REMOTEMODE +h with invalid host parameter %s for user %C", *(p+1), acptr);
280 + p++; /* Swallow the arg anyway */
281 + }
282 + }
283 + } else { /* MODE_DEL */
284 + do_set_host = 1;
285 + hostmask = NULL;
286 + }
287 + break;
288 +
289 + default:
290 + protocol_violation(sptr, "Received REMOTEMODE %c%c unknown user mode flag or disallowed to set remotely for user %C",
291 + what == MODE_ADD ? '+' : '-', *m, acptr);
292 + break;
293 + }
294 + }
295 + }
296 +
297 + /* do host hiding for +x */
298 + if (!FlagHas(&setflags, FLAG_HIDDENHOST) && do_host_hiding)
299 + hide_hostmask(acptr, FLAG_HIDDENHOST);
300 +
301 + /* sanity checks for -h */
302 + if (do_set_host && !hostmask) {
303 + /* user has no sethost or has no account
304 + *
305 + * user has +h - their host is hidden, do not remove it
306 + * unless the user has an account set
307 + * we should not out of the blue expose the real host
308 + */
309 + if (!IsSetHost(acptr) || !IsAccount(acptr))
310 + do_set_host = 0;
311 +
312 + /* user not +x and not allowed to set it */
313 + else if (!IsHiddenHost(acptr) && !feature_bool(FEAT_HOST_HIDING))
314 + do_set_host = 0;
315 +
316 + /* set +x */
317 + else
318 + SetHiddenHost(acptr);
319 + }
320 +
321 + /* sanity checks for +h */
322 + if (do_set_host && hostmask) {
323 + if ((host = strrchr(hostmask, '@'))) {
324 + *host++ = '\0';
325 + user = hostmask;
326 + }
327 + else
328 + host = hostmask;
329 +
330 + /* check if new sethost is different from before */
331 + if (IsSetHost(acptr) &&
332 + (!user || strcmp(cli_user(acptr)->username, user) == 0) &&
333 + strcmp(cli_user(acptr)->host, host) == 0)
334 + do_set_host = 0;
335 + }
336 +
337 + /* do host hiding for +h/-h */
338 + if (do_set_host) {
339 +
340 + /* quit user from channel */
341 + sendcmdto_common_channels_butone(acptr, CMD_QUIT, acptr, ":Host change");
342 +
343 + /* set +h */
344 + if (host) {
345 + SetSetHost(acptr);
346 + /* clear +h in old flags so +h is sent out again with new sethost param */
347 + FlagClr(&setflags, FLAG_SETHOST);
348 + if (user)
349 + ircd_strncpy(cli_user(acptr)->username, user, USERLEN);
350 + ircd_strncpy(cli_user(acptr)->host, host, HOSTLEN);
351 +
352 + /* set -h */
353 + } else {
354 + ClearSetHost(acptr);
355 + ircd_strncpy(cli_user(acptr)->username, cli_user(acptr)->realusername, USERLEN);
356 + /* user is +rx - need to restore +x host */
357 + if (HasHiddenHost(acptr))
358 + ircd_snprintf(0, cli_user(acptr)->host, HOSTLEN, "%s.%s",
359 + cli_user(acptr)->account, feature_str(FEAT_HIDDEN_HOST));
360 + else
361 + ircd_strncpy(cli_user(acptr)->host, cli_user(acptr)->realhost, HOSTLEN);
362 + }
363 +
364 + /* inform user of hidden host */
365 + ircd_snprintf(0, hiddenhost, HOSTLEN + USERLEN + 2, "%s@%s",
366 + cli_user(acptr)->username, cli_user(acptr)->host);
367 + send_reply(acptr, RPL_HOSTHIDDEN, hiddenhost);
368 +
369 + /*
370 + * Go through all channels the client was on, rejoin him
371 + * and set the modes, if any
372 + */
373 + for (chan = cli_user(acptr)->channel; chan; chan = chan->next_channel) {
374 + /* Invalidate bans against the user so we check them again */
375 + ClearBanValid(chan);
376 + if (IsZombie(chan))
377 + continue;
378 + /* If this channel has delayed joins and the user has no modes, just set
379 + * the delayed join flag rather than showing the join, even if the user
380 + * was visible before */
381 + if (!IsChanOp(chan) && !HasVoice(chan)
382 + && (chan->channel->mode.mode & MODE_DELJOINS)) {
383 + SetDelayedJoin(chan);
384 + } else {
385 + sendcmdto_channel_butserv_butone(acptr, CMD_JOIN, chan->channel, acptr, 0,
386 + "%H", chan->channel);
387 + }
388 + if (IsChanOp(chan) && HasVoice(chan)) {
389 + sendcmdto_channel_butserv_butone(&his, CMD_MODE, chan->channel, acptr, 0,
390 + "%H +ov %C %C", chan->channel, acptr, acptr);
391 + } else if (IsChanOp(chan) || HasVoice(chan)) {
392 + sendcmdto_channel_butserv_butone(&his, CMD_MODE, chan->channel, acptr, 0,
393 + "%H +%c %C", chan->channel, IsChanOp(chan) ? 'o' : 'v', acptr);
394 + }
395 + }
396 + }
397 +
398 + /* adjust count for invisible/visible users */
399 + if (FlagHas(&setflags, FLAG_INVISIBLE) && !IsInvisible(acptr)) {
400 + assert(UserStats.inv_clients > 0);
401 + --UserStats.inv_clients;
402 + }
403 + if (!FlagHas(&setflags, FLAG_INVISIBLE) && IsInvisible(acptr)) {
404 + ++UserStats.inv_clients;
405 + }
406 + assert(UserStats.inv_clients <= UserStats.clients + UserStats.unknowns);
407 +
408 + /* send out the mode */
409 + send_umode_out(acptr, acptr, &setflags, 0);
410 +
411 + return 0;
412 +}
413 diff -r 37c9c7460603 ircd/parse.c
414 --- a/ircd/parse.c
415 +++ b/ircd/parse.c
416 @@ -548,6 +548,13 @@
417 { m_ignore, m_ignore, ms_reburst, m_ignore, m_ignore }
418 },
419 {
420 + MSG_REMOTEMODE,
421 + TOK_REMOTEMODE,
422 + 0, MAXPARA, MFLG_SLOW, 0, NULL,
423 + /* UNREG, CLIENT, SERVER, OPER, SERVICE */
424 + { m_ignore, m_ignore, ms_remotemode, m_ignore, m_ignore }
425 + },
426 + {
427 MSG_HASH,
428 TOK_HASH,
429 0, MAXPARA, MFLG_SLOW, 0, NULL,