]> jfr.im git - solanum.git/blob - modules/core/m_nick.c
Migrate remaining modules to AV2
[solanum.git] / modules / core / m_nick.c
1 /*
2 * ircd-ratbox: A slightly useful ircd.
3 * m_nick.c: Sets a users nick.
4 *
5 * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
6 * Copyright (C) 1996-2002 Hybrid Development Team
7 * Copyright (C) 2002-2005 ircd-ratbox development team
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 * USA
23 */
24
25 #include "stdinc.h"
26 #include "client.h"
27 #include "hash.h"
28 #include "match.h"
29 #include "ircd.h"
30 #include "numeric.h"
31 #include "s_conf.h"
32 #include "s_stats.h"
33 #include "s_user.h"
34 #include "hash.h"
35 #include "whowas.h"
36 #include "s_serv.h"
37 #include "send.h"
38 #include "channel.h"
39 #include "logger.h"
40 #include "msg.h"
41 #include "parse.h"
42 #include "modules.h"
43 #include "common.h"
44 #include "packet.h"
45 #include "scache.h"
46 #include "s_newconf.h"
47 #include "monitor.h"
48 #include "s_assert.h"
49
50 /* Give all UID nicks the same TS. This ensures nick TS is always the same on
51 * all servers for each nick-user pair, also if a user with a UID nick changes
52 * their nick but is collided again (the server detecting the collision will
53 * not propagate the nick change further). -- jilles
54 */
55 #define SAVE_NICKTS 100
56
57 static int mr_nick(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
58 static int m_nick(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
59 static int mc_nick(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
60 static int ms_nick(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
61 static int ms_uid(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
62 static int ms_euid(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
63 static int ms_save(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
64 static int can_save(struct Client *);
65 static void save_user(struct Client *, struct Client *, struct Client *);
66 static void bad_nickname(struct Client *, const char *);
67
68 struct Message nick_msgtab = {
69 "NICK", 0, 0, 0, 0,
70 {{mr_nick, 0}, {m_nick, 0}, {mc_nick, 3}, {ms_nick, 0}, mg_ignore, {m_nick, 0}}
71 };
72 struct Message uid_msgtab = {
73 "UID", 0, 0, 0, 0,
74 {mg_ignore, mg_ignore, mg_ignore, {ms_uid, 9}, mg_ignore, mg_ignore}
75 };
76 struct Message euid_msgtab = {
77 "EUID", 0, 0, 0, 0,
78 {mg_ignore, mg_ignore, mg_ignore, {ms_euid, 12}, mg_ignore, mg_ignore}
79 };
80 struct Message save_msgtab = {
81 "SAVE", 0, 0, 0, 0,
82 {mg_ignore, mg_ignore, mg_ignore, {ms_save, 3}, mg_ignore, mg_ignore}
83 };
84
85 mapi_clist_av1 nick_clist[] = { &nick_msgtab, &uid_msgtab, &euid_msgtab,
86 &save_msgtab, NULL };
87
88 DECLARE_MODULE_AV2(nick, NULL, NULL, nick_clist, NULL, NULL, NULL, NULL, NULL);
89
90 static int change_remote_nick(struct Client *, struct Client *, time_t,
91 const char *, int);
92
93 static int clean_username(const char *);
94 static int clean_host(const char *);
95 static int clean_uid(const char *uid, const char *sid);
96
97 static void set_initial_nick(struct Client *client_p, struct Client *source_p, char *nick);
98 static void change_local_nick(struct Client *client_p, struct Client *source_p, char *nick, int);
99 static int register_client(struct Client *client_p, struct Client *server,
100 const char *nick, time_t newts, int parc, const char *parv[]);
101
102 static int perform_nick_collides(struct Client *, struct Client *,
103 struct Client *, int, const char **,
104 time_t, const char *, const char *);
105 static int perform_nickchange_collides(struct Client *, struct Client *,
106 struct Client *, int, const char **, time_t, const char *);
107
108 /* mr_nick()
109 * parv[1] = nickname
110 */
111 static int
112 mr_nick(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
113 {
114 struct Client *target_p;
115 char nick[NICKLEN];
116
117 if (strlen(client_p->id) == 3)
118 {
119 exit_client(client_p, client_p, client_p, "Mixing client and server protocol");
120 return 0;
121 }
122
123 if(parc < 2 || EmptyString(parv[1]))
124 {
125 sendto_one(source_p, form_str(ERR_NONICKNAMEGIVEN),
126 me.name, EmptyString(source_p->name) ? "*" : source_p->name);
127 return 0;
128 }
129
130 /* copy the nick and terminate it */
131 rb_strlcpy(nick, parv[1], ConfigFileEntry.nicklen);
132
133 /* check the nickname is ok */
134 if(!clean_nick(nick, 1))
135 {
136 sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME),
137 me.name, EmptyString(source_p->name) ? "*" : source_p->name, parv[1]);
138 return 0;
139 }
140
141 /* check if the nick is resv'd */
142 if(find_nick_resv(nick))
143 {
144 sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME),
145 me.name, EmptyString(source_p->name) ? "*" : source_p->name, nick);
146 return 0;
147 }
148
149 if(rb_dictionary_find(nd_dict, nick))
150 {
151 sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
152 me.name, EmptyString(source_p->name) ? "*" : source_p->name, nick);
153 return 0;
154 }
155
156 if((target_p = find_named_client(nick)) == NULL)
157 set_initial_nick(client_p, source_p, nick);
158 else if(source_p == target_p)
159 strcpy(source_p->name, nick);
160 else
161 sendto_one(source_p, form_str(ERR_NICKNAMEINUSE), me.name, "*", nick);
162
163 return 0;
164 }
165
166 /* m_nick()
167 * parv[1] = nickname
168 */
169 static int
170 m_nick(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
171 {
172 struct Client *target_p;
173 char nick[NICKLEN];
174
175 if(parc < 2 || EmptyString(parv[1]))
176 {
177 sendto_one(source_p, form_str(ERR_NONICKNAMEGIVEN), me.name, source_p->name);
178 return 0;
179 }
180
181 /* mark end of grace period, to prevent nickflooding */
182 if(!IsFloodDone(source_p))
183 flood_endgrace(source_p);
184
185 /* terminate nick to NICKLEN, we dont want clean_nick() to error! */
186 rb_strlcpy(nick, parv[1], ConfigFileEntry.nicklen);
187
188 /* check the nickname is ok */
189 if(!clean_nick(nick, 1))
190 {
191 sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME), me.name, source_p->name, nick);
192 return 0;
193 }
194
195 if(!IsExemptResv(source_p) && find_nick_resv(nick))
196 {
197 sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME), me.name, source_p->name, nick);
198 return 0;
199 }
200
201 if(rb_dictionary_find(nd_dict, nick))
202 {
203 sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
204 me.name, EmptyString(source_p->name) ? "*" : source_p->name, nick);
205 return 0;
206 }
207
208 if((target_p = find_named_client(nick)))
209 {
210 /* If(target_p == source_p) the client is changing nicks between
211 * equivalent nicknames ie: [nick] -> {nick}
212 */
213 if(target_p == source_p)
214 {
215 /* check the nick isnt exactly the same */
216 if(strcmp(target_p->name, nick))
217 change_local_nick(client_p, source_p, nick, 1);
218
219 }
220
221 /* drop unregged client */
222 else if(IsUnknown(target_p))
223 {
224 exit_client(NULL, target_p, &me, "Overridden");
225 change_local_nick(client_p, source_p, nick, 1);
226 }
227 else
228 sendto_one(source_p, form_str(ERR_NICKNAMEINUSE), me.name, source_p->name, nick);
229
230 return 0;
231 }
232 else
233 change_local_nick(client_p, source_p, nick, 1);
234
235 return 0;
236 }
237
238 /* mc_nick()
239 *
240 * server -> server nick change
241 * parv[1] = nickname
242 * parv[2] = TS when nick change
243 */
244 static int
245 mc_nick(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
246 {
247 struct Client *target_p;
248 time_t newts = 0;
249
250 /* if nicks erroneous, or too long, kill */
251 if(!clean_nick(parv[1], 0))
252 {
253 bad_nickname(client_p, parv[1]);
254 return 0;
255 }
256
257 newts = atol(parv[2]);
258 target_p = find_named_client(parv[1]);
259
260 /* if the nick doesnt exist, allow it and process like normal */
261 if(target_p == NULL)
262 {
263 change_remote_nick(client_p, source_p, newts, parv[1], 1);
264 }
265 else if(IsUnknown(target_p))
266 {
267 exit_client(NULL, target_p, &me, "Overridden");
268 change_remote_nick(client_p, source_p, newts, parv[1], 1);
269 }
270 else if(target_p == source_p)
271 {
272 /* client changing case of nick */
273 if(strcmp(target_p->name, parv[1]))
274 change_remote_nick(client_p, source_p, newts, parv[1], 1);
275 }
276 /* we've got a collision! */
277 else
278 perform_nickchange_collides(source_p, client_p, target_p,
279 parc, parv, newts, parv[1]);
280
281 return 0;
282 }
283
284 static int
285 ms_nick(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
286 {
287 const char *nick, *server;
288
289 nick = parc > 1 ? parv[1] : "?";
290 server = parc > 7 ? parv[7] : "?";
291
292 sendto_wallops_flags(UMODE_WALLOP, &me,
293 "Link %s cancelled, TS5 nickname %s on %s introduced (old server?)",
294 client_p->name, nick, server);
295 sendto_server(NULL, NULL, CAP_TS6, NOCAPS,
296 ":%s WALLOPS :Link %s cancelled, TS5 nickname %s on %s introduced (old server?)",
297 me.id, client_p->name, nick, server);
298 ilog(L_SERVER, "Link %s cancelled, TS5 nickname %s on %s introduced (old server?)",
299 client_p->name, nick, server);
300
301 exit_client(client_p, client_p, &me, "TS5 nickname introduced");
302
303 return 0;
304 }
305
306 /* ms_uid()
307 * parv[1] - nickname
308 * parv[2] - hops
309 * parv[3] - TS
310 * parv[4] - umodes
311 * parv[5] - username
312 * parv[6] - hostname
313 * parv[7] - IP
314 * parv[8] - UID
315 * parv[9] - gecos
316 */
317 static int
318 ms_uid(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
319 {
320 struct Client *target_p;
321 time_t newts = 0;
322 char squitreason[120];
323
324 newts = atol(parv[3]);
325
326 if(parc != 10)
327 {
328 sendto_realops_snomask(SNO_GENERAL, L_ALL,
329 "Dropping server %s due to (invalid) command 'UID' "
330 "with %d arguments (expecting 10)", client_p->name, parc);
331 ilog(L_SERVER, "Excess parameters (%d) for command 'UID' from %s.",
332 parc, client_p->name);
333 snprintf(squitreason, sizeof squitreason,
334 "Excess parameters (%d) to %s command, expecting %d",
335 parc, "UID", 10);
336 exit_client(client_p, client_p, client_p, squitreason);
337 return 0;
338 }
339
340 /* if nicks erroneous, or too long, kill */
341 if(!clean_nick(parv[1], 0))
342 {
343 bad_nickname(client_p, parv[1]);
344 return 0;
345 }
346
347 if(!clean_uid(parv[8], source_p->id))
348 {
349 snprintf(squitreason, sizeof squitreason,
350 "Invalid UID %s for nick %s on %s/%s",
351 parv[8], parv[1], source_p->name, source_p->id);
352 exit_client(client_p, client_p, client_p, squitreason);
353 return 0;
354 }
355
356 if(!clean_username(parv[5]) || !clean_host(parv[6]))
357 {
358 ServerStats.is_kill++;
359 sendto_realops_snomask(SNO_DEBUG, L_ALL,
360 "Bad user@host: %s@%s From: %s(via %s)",
361 parv[5], parv[6], source_p->name, client_p->name);
362 sendto_one(client_p, ":%s KILL %s :%s (Bad user@host)", me.id, parv[8], me.name);
363 return 0;
364 }
365
366 /* check length of clients gecos */
367 if(strlen(parv[9]) > REALLEN)
368 {
369 char *s = LOCAL_COPY(parv[9]);
370 sendto_realops_snomask(SNO_GENERAL, L_ALL, "Long realname from server %s for %s",
371 source_p->name, parv[1]);
372 s[REALLEN] = '\0';
373 parv[9] = s;
374 }
375
376 target_p = find_named_client(parv[1]);
377
378 if(target_p == NULL)
379 {
380 register_client(client_p, source_p, parv[1], newts, parc, parv);
381 }
382 else if(IsUnknown(target_p))
383 {
384 exit_client(NULL, target_p, &me, "Overridden");
385 register_client(client_p, source_p, parv[1], newts, parc, parv);
386 }
387 /* we've got a collision! */
388 else
389 perform_nick_collides(source_p, client_p, target_p, parc, parv,
390 newts, parv[1], parv[8]);
391
392 return 0;
393 }
394
395 /* ms_euid()
396 * parv[1] - nickname
397 * parv[2] - hops
398 * parv[3] - TS
399 * parv[4] - umodes
400 * parv[5] - username
401 * parv[6] - hostname
402 * parv[7] - IP
403 * parv[8] - UID
404 * parv[9] - realhost
405 * parv[10] - account
406 * parv[11] - gecos
407 */
408 static int
409 ms_euid(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
410 {
411 struct Client *target_p;
412 time_t newts = 0;
413 char squitreason[120];
414
415 newts = atol(parv[3]);
416
417 if(parc != 12)
418 {
419 sendto_realops_snomask(SNO_GENERAL, L_ALL,
420 "Dropping server %s due to (invalid) command 'EUID' "
421 "with %d arguments (expecting 12)", client_p->name, parc);
422 ilog(L_SERVER, "Excess parameters (%d) for command 'EUID' from %s.",
423 parc, client_p->name);
424 snprintf(squitreason, sizeof squitreason,
425 "Excess parameters (%d) to %s command, expecting %d",
426 parc, "EUID", 12);
427 exit_client(client_p, client_p, client_p, squitreason);
428 return 0;
429 }
430
431 /* if nicks erroneous, or too long, kill */
432 if(!clean_nick(parv[1], 0))
433 {
434 bad_nickname(client_p, parv[1]);
435 return 0;
436 }
437
438 if(!clean_uid(parv[8], source_p->id))
439 {
440 snprintf(squitreason, sizeof squitreason,
441 "Invalid UID %s for nick %s on %s/%s",
442 parv[8], parv[1], source_p->name, source_p->id);
443 exit_client(client_p, client_p, client_p, squitreason);
444 return 0;
445 }
446
447 if(!clean_username(parv[5]) || !clean_host(parv[6]))
448 {
449 ServerStats.is_kill++;
450 sendto_realops_snomask(SNO_DEBUG, L_ALL,
451 "Bad user@host: %s@%s From: %s(via %s)",
452 parv[5], parv[6], source_p->name, client_p->name);
453 sendto_one(client_p, ":%s KILL %s :%s (Bad user@host)", me.id, parv[8], me.name);
454 return 0;
455 }
456
457 if(strcmp(parv[9], "*") && !clean_host(parv[9]))
458 {
459 ServerStats.is_kill++;
460 sendto_realops_snomask(SNO_DEBUG, L_ALL,
461 "Bad realhost: %s From: %s(via %s)",
462 parv[9], source_p->name, client_p->name);
463 sendto_one(client_p, ":%s KILL %s :%s (Bad user@host)", me.id, parv[8], me.name);
464 return 0;
465 }
466
467 /* check length of clients gecos */
468 if(strlen(parv[11]) > REALLEN)
469 {
470 char *s = LOCAL_COPY(parv[11]);
471 sendto_realops_snomask(SNO_GENERAL, L_ALL, "Long realname from server %s for %s",
472 source_p->name, parv[1]);
473 s[REALLEN] = '\0';
474 parv[11] = s;
475 }
476
477 target_p = find_named_client(parv[1]);
478
479 if(target_p == NULL)
480 {
481 register_client(client_p, source_p, parv[1], newts, parc, parv);
482 }
483 else if(IsUnknown(target_p))
484 {
485 exit_client(NULL, target_p, &me, "Overridden");
486 register_client(client_p, source_p, parv[1], newts, parc, parv);
487 }
488 /* we've got a collision! */
489 else
490 perform_nick_collides(source_p, client_p, target_p, parc, parv,
491 newts, parv[1], parv[8]);
492
493 return 0;
494 }
495
496 /* ms_save()
497 * parv[1] - UID
498 * parv[2] - TS
499 */
500 static int
501 ms_save(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
502 {
503 struct Client *target_p;
504
505 target_p = find_id(parv[1]);
506 if (target_p == NULL)
507 return 0;
508 if (!IsPerson(target_p))
509 sendto_realops_snomask(SNO_GENERAL, L_ALL,
510 "Ignored SAVE message for non-person %s from %s",
511 target_p->name, source_p->name);
512 else if (IsDigit(target_p->name[0]))
513 sendto_realops_snomask(SNO_DEBUG, L_ALL,
514 "Ignored noop SAVE message for %s from %s",
515 target_p->name, source_p->name);
516 else if (target_p->tsinfo == atol(parv[2]))
517 save_user(client_p, source_p, target_p);
518 else
519 sendto_realops_snomask(SNO_SKILL, L_ALL,
520 "Ignored SAVE message for %s from %s",
521 target_p->name, source_p->name);
522 return 0;
523 }
524
525 /* clean_username()
526 *
527 * input - username to check
528 * output - 0 if erroneous, else 0
529 * side effects -
530 */
531 static int
532 clean_username(const char *username)
533 {
534 int len = 0;
535
536 for(; *username; username++)
537 {
538 len++;
539
540 if(!IsUserChar(*username))
541 return 0;
542 }
543
544 if(len > USERLEN)
545 return 0;
546
547 return 1;
548 }
549
550 /* clean_host()
551 *
552 * input - host to check
553 * output - 0 if erroneous, else 0
554 * side effects -
555 */
556 static int
557 clean_host(const char *host)
558 {
559 int len = 0;
560
561 for(; *host; host++)
562 {
563 len++;
564
565 if(!IsHostChar(*host))
566 return 0;
567 }
568
569 if(len > HOSTLEN)
570 return 0;
571
572 return 1;
573 }
574
575 static int
576 clean_uid(const char *uid, const char *sid)
577 {
578 int len = 1;
579
580 if(strncmp(uid, sid, strlen(sid)))
581 return 0;
582
583 if(!IsDigit(*uid++))
584 return 0;
585
586 for(; *uid; uid++)
587 {
588 len++;
589
590 if(!IsIdChar(*uid))
591 return 0;
592 }
593
594 if(len != IDLEN - 1)
595 return 0;
596
597 return 1;
598 }
599
600 static void
601 set_initial_nick(struct Client *client_p, struct Client *source_p, char *nick)
602 {
603 char note[NICKLEN + 10];
604
605 /* This had to be copied here to avoid problems.. */
606 source_p->tsinfo = rb_current_time();
607 if(source_p->name[0])
608 del_from_client_hash(source_p->name, source_p);
609
610 strcpy(source_p->name, nick);
611 add_to_client_hash(nick, source_p);
612
613 snprintf(note, sizeof(note), "Nick: %s", nick);
614 rb_note(client_p->localClient->F, note);
615
616 if(source_p->flags & FLAGS_SENTUSER)
617 {
618 /* got user, heres nick. */
619 register_local_user(client_p, source_p);
620 }
621 }
622
623 static void
624 change_local_nick(struct Client *client_p, struct Client *source_p,
625 char *nick, int dosend)
626 {
627 struct Client *target_p;
628 rb_dlink_node *ptr, *next_ptr;
629 struct Channel *chptr;
630 char note[NICKLEN + 10];
631 int samenick;
632
633 if (dosend)
634 {
635 chptr = find_bannickchange_channel(source_p);
636 if (chptr != NULL)
637 {
638 sendto_one_numeric(source_p, ERR_BANNICKCHANGE,
639 form_str(ERR_BANNICKCHANGE),
640 nick, chptr->chname);
641 return;
642 }
643 if((source_p->localClient->last_nick_change + ConfigFileEntry.max_nick_time) < rb_current_time())
644 source_p->localClient->number_of_nick_changes = 0;
645
646 source_p->localClient->last_nick_change = rb_current_time();
647 source_p->localClient->number_of_nick_changes++;
648
649 if(ConfigFileEntry.anti_nick_flood && !IsOper(source_p) &&
650 source_p->localClient->number_of_nick_changes > ConfigFileEntry.max_nick_changes)
651 {
652 sendto_one(source_p, form_str(ERR_NICKTOOFAST),
653 me.name, source_p->name, source_p->name,
654 nick, ConfigFileEntry.max_nick_time);
655 return;
656 }
657 }
658
659 samenick = irccmp(source_p->name, nick) ? 0 : 1;
660
661 /* dont reset TS if theyre just changing case of nick */
662 if(!samenick)
663 {
664 /* force the TS to increase -- jilles */
665 if (source_p->tsinfo >= rb_current_time())
666 source_p->tsinfo++;
667 else
668 source_p->tsinfo = rb_current_time();
669 monitor_signoff(source_p);
670 /* we only do bancache for local users -- jilles */
671 if(source_p->user)
672 invalidate_bancache_user(source_p);
673 }
674
675 sendto_realops_snomask(SNO_NCHANGE, L_ALL,
676 "Nick change: From %s to %s [%s@%s]",
677 source_p->name, nick, source_p->username, source_p->host);
678
679 /* send the nick change to the users channels */
680 sendto_common_channels_local(source_p, NOCAPS, NOCAPS, ":%s!%s@%s NICK :%s",
681 source_p->name, source_p->username, source_p->host, nick);
682
683 /* send the nick change to servers.. */
684 if(source_p->user)
685 {
686 whowas_add_history(source_p, 1);
687
688 if (dosend)
689 {
690 sendto_server(client_p, NULL, CAP_TS6, NOCAPS, ":%s NICK %s :%ld",
691 use_id(source_p), nick, (long) source_p->tsinfo);
692 }
693 }
694
695 /* Finally, add to hash */
696 del_from_client_hash(source_p->name, source_p);
697 strcpy(source_p->name, nick);
698 add_to_client_hash(nick, source_p);
699
700 if(!samenick)
701 monitor_signon(source_p);
702
703 /* Make sure everyone that has this client on its accept list
704 * loses that reference.
705 */
706 /* we used to call del_all_accepts() here, but theres no real reason
707 * to clear a clients own list of accepted clients. So just remove
708 * them from everyone elses list --anfl
709 */
710 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, source_p->on_allow_list.head)
711 {
712 target_p = ptr->data;
713
714 rb_dlinkFindDestroy(source_p, &target_p->localClient->allow_list);
715 rb_dlinkDestroy(ptr, &source_p->on_allow_list);
716 }
717
718 snprintf(note, sizeof(note), "Nick: %s", nick);
719 rb_note(client_p->localClient->F, note);
720
721 return;
722 }
723
724 /*
725 * change_remote_nick()
726 */
727 static int
728 change_remote_nick(struct Client *client_p, struct Client *source_p,
729 time_t newts, const char *nick, int dosend)
730 {
731 struct nd_entry *nd;
732 int samenick = irccmp(source_p->name, nick) ? 0 : 1;
733
734 /* client changing their nick - dont reset ts if its same */
735 if(!samenick)
736 {
737 source_p->tsinfo = newts ? newts : rb_current_time();
738 monitor_signoff(source_p);
739 }
740
741 sendto_common_channels_local(source_p, NOCAPS, NOCAPS, ":%s!%s@%s NICK :%s",
742 source_p->name, source_p->username, source_p->host, nick);
743
744 if(source_p->user)
745 {
746 whowas_add_history(source_p, 1);
747 if (dosend)
748 {
749 sendto_server(client_p, NULL, CAP_TS6, NOCAPS, ":%s NICK %s :%ld",
750 use_id(source_p), nick, (long) source_p->tsinfo);
751 }
752 }
753
754 del_from_client_hash(source_p->name, source_p);
755
756 /* invalidate nick delay when a remote client uses the nick.. */
757 if((nd = rb_dictionary_retrieve(nd_dict, nick)))
758 free_nd_entry(nd);
759
760 strcpy(source_p->name, nick);
761 add_to_client_hash(nick, source_p);
762
763 if(!samenick)
764 monitor_signon(source_p);
765
766 /* remove all accepts pointing to the client */
767 del_all_accepts(source_p);
768
769 return 0;
770 }
771
772 static int
773 perform_nick_collides(struct Client *source_p, struct Client *client_p,
774 struct Client *target_p, int parc, const char *parv[],
775 time_t newts, const char *nick, const char *uid)
776 {
777 int sameuser;
778 int use_save;
779 const char *action;
780
781 use_save = ConfigFileEntry.collision_fnc && can_save(target_p) &&
782 uid != NULL && can_save(source_p);
783 action = use_save ? "saved" : "killed";
784
785 /* if we dont have a ts, or their TS's are the same, kill both */
786 if(!newts || !target_p->tsinfo || (newts == target_p->tsinfo))
787 {
788 sendto_realops_snomask(SNO_SKILL, L_ALL,
789 "Nick collision on %s(%s <- %s)(both %s)",
790 target_p->name, target_p->from->name, client_p->name, action);
791
792 if (use_save)
793 {
794 save_user(&me, &me, target_p);
795 ServerStats.is_save++;
796 sendto_one(client_p, ":%s SAVE %s %ld", me.id,
797 uid, (long)newts);
798 register_client(client_p, source_p,
799 uid, SAVE_NICKTS, parc, parv);
800 }
801 else
802 {
803 sendto_one_numeric(target_p, ERR_NICKCOLLISION,
804 form_str(ERR_NICKCOLLISION), target_p->name);
805
806 /* if the new client being introduced has a UID, we need to
807 * issue a KILL for it..
808 */
809 if(uid)
810 sendto_one(client_p, ":%s KILL %s :%s (Nick collision (new))",
811 me.id, uid, me.name);
812
813 /* we then need to KILL the old client everywhere */
814 kill_client_serv_butone(NULL, target_p, "%s (Nick collision (new))", me.name);
815 ServerStats.is_kill++;
816
817 target_p->flags |= FLAGS_KILLED;
818 exit_client(client_p, target_p, &me, "Nick collision (new)");
819 }
820 return 0;
821 }
822 /* the timestamps are different */
823 else
824 {
825 sameuser = (target_p->user) && !irccmp(target_p->username, parv[5])
826 && !irccmp(target_p->host, parv[6]);
827
828 if((sameuser && newts < target_p->tsinfo) ||
829 (!sameuser && newts > target_p->tsinfo))
830 {
831 /* if we have a UID, then we need to issue a KILL,
832 * otherwise we do nothing and hope that the other
833 * client will collide it..
834 */
835 if (use_save)
836 {
837 sendto_one(client_p, ":%s SAVE %s %ld", me.id,
838 uid, (long)newts);
839 register_client(client_p, source_p,
840 uid, SAVE_NICKTS, parc, parv);
841 }
842 else if(uid)
843 sendto_one(client_p,
844 ":%s KILL %s :%s (Nick collision (new))",
845 me.id, uid, me.name);
846 return 0;
847 }
848 else
849 {
850 if(sameuser)
851 sendto_realops_snomask(SNO_SKILL, L_ALL,
852 "Nick collision on %s(%s <- %s)(older %s)",
853 target_p->name, target_p->from->name,
854 client_p->name, action);
855 else
856 sendto_realops_snomask(SNO_SKILL, L_ALL,
857 "Nick collision on %s(%s <- %s)(newer %s)",
858 target_p->name, target_p->from->name,
859 client_p->name, action);
860
861 if (use_save)
862 {
863 ServerStats.is_save++;
864 save_user(&me, &me, target_p);
865 }
866 else
867 {
868 ServerStats.is_kill++;
869 sendto_one_numeric(target_p, ERR_NICKCOLLISION,
870 form_str(ERR_NICKCOLLISION), target_p->name);
871
872 /* now we just need to kill the existing client */
873 kill_client_serv_butone(client_p, target_p,
874 "%s (Nick collision (new))", me.name);
875
876 target_p->flags |= FLAGS_KILLED;
877 (void) exit_client(client_p, target_p, &me, "Nick collision");
878 }
879
880 register_client(client_p, source_p,
881 nick, newts, parc, parv);
882
883 return 0;
884 }
885 }
886 }
887
888
889 static int
890 perform_nickchange_collides(struct Client *source_p, struct Client *client_p,
891 struct Client *target_p, int parc,
892 const char *parv[], time_t newts, const char *nick)
893 {
894 int sameuser;
895 int use_save;
896 const char *action;
897
898 use_save = ConfigFileEntry.collision_fnc && can_save(target_p) &&
899 can_save(source_p);
900 action = use_save ? "saved" : "killed";
901
902 /* its a client changing nick and causing a collide */
903 if(!newts || !target_p->tsinfo || (newts == target_p->tsinfo) || !source_p->user)
904 {
905 sendto_realops_snomask(SNO_SKILL, L_ALL,
906 "Nick change collision from %s to %s(%s <- %s)(both %s)",
907 source_p->name, target_p->name, target_p->from->name,
908 client_p->name, action);
909
910 if (use_save)
911 {
912 ServerStats.is_save += 2;
913 save_user(&me, &me, target_p);
914 sendto_one(client_p, ":%s SAVE %s %ld", me.id,
915 source_p->id, (long)newts);
916 /* don't send a redundant nick change */
917 if (!IsDigit(source_p->name[0]))
918 change_remote_nick(client_p, source_p, SAVE_NICKTS, source_p->id, 1);
919 }
920 else
921 {
922 ServerStats.is_kill++;
923 sendto_one_numeric(target_p, ERR_NICKCOLLISION,
924 form_str(ERR_NICKCOLLISION), target_p->name);
925
926 kill_client_serv_butone(NULL, source_p, "%s (Nick change collision)", me.name);
927
928 ServerStats.is_kill++;
929
930 kill_client_serv_butone(NULL, target_p, "%s (Nick change collision)", me.name);
931
932 target_p->flags |= FLAGS_KILLED;
933 exit_client(NULL, target_p, &me, "Nick collision(new)");
934 source_p->flags |= FLAGS_KILLED;
935 exit_client(client_p, source_p, &me, "Nick collision(old)");
936 }
937 return 0;
938 }
939 else
940 {
941 sameuser = !irccmp(target_p->username, source_p->username) &&
942 !irccmp(target_p->host, source_p->host);
943
944 if((sameuser && newts < target_p->tsinfo) ||
945 (!sameuser && newts > target_p->tsinfo))
946 {
947 if(sameuser)
948 sendto_realops_snomask(SNO_SKILL, L_ALL,
949 "Nick change collision from %s to %s(%s <- %s)(older %s)",
950 source_p->name, target_p->name,
951 target_p->from->name, client_p->name, action);
952 else
953 sendto_realops_snomask(SNO_SKILL, L_ALL,
954 "Nick change collision from %s to %s(%s <- %s)(newer %s)",
955 source_p->name, target_p->name,
956 target_p->from->name, client_p->name, action);
957
958 if (use_save)
959 {
960 ServerStats.is_save++;
961 /* can't broadcast a SAVE because the
962 * nickchange has happened at client_p
963 * but not in other directions -- jilles */
964 sendto_one(client_p, ":%s SAVE %s %ld", me.id,
965 source_p->id, (long)newts);
966 /* send a :<id> NICK <id> <ts> (!) */
967 if (!IsDigit(source_p->name[0]))
968 change_remote_nick(client_p, source_p, SAVE_NICKTS, source_p->id, 1);
969 }
970 else
971 {
972 ServerStats.is_kill++;
973
974 sendto_one_numeric(source_p, ERR_NICKCOLLISION,
975 form_str(ERR_NICKCOLLISION), source_p->name);
976
977 /* kill the client issuing the nickchange */
978 kill_client_serv_butone(client_p, source_p,
979 "%s (Nick change collision)", me.name);
980
981 source_p->flags |= FLAGS_KILLED;
982
983 if(sameuser)
984 exit_client(client_p, source_p, &me, "Nick collision(old)");
985 else
986 exit_client(client_p, source_p, &me, "Nick collision(new)");
987 }
988 return 0;
989 }
990 else
991 {
992 if(sameuser)
993 sendto_realops_snomask(SNO_SKILL, L_ALL,
994 "Nick collision on %s(%s <- %s)(older %s)",
995 target_p->name, target_p->from->name,
996 client_p->name, action);
997 else
998 sendto_realops_snomask(SNO_SKILL, L_ALL,
999 "Nick collision on %s(%s <- %s)(newer %s)",
1000 target_p->name, target_p->from->name,
1001 client_p->name, action);
1002
1003 if (use_save)
1004 {
1005 ServerStats.is_save++;
1006 save_user(&me, &me, target_p);
1007 }
1008 else
1009 {
1010 sendto_one_numeric(target_p, ERR_NICKCOLLISION,
1011 form_str(ERR_NICKCOLLISION), target_p->name);
1012
1013 /* kill the client who existed before hand */
1014 kill_client_serv_butone(client_p, target_p, "%s (Nick collision)", me.name);
1015
1016 ServerStats.is_kill++;
1017
1018 target_p->flags |= FLAGS_KILLED;
1019 (void) exit_client(client_p, target_p, &me, "Nick collision");
1020 }
1021 }
1022 }
1023
1024 change_remote_nick(client_p, source_p, newts, nick, 1);
1025
1026 return 0;
1027 }
1028
1029 static int
1030 register_client(struct Client *client_p, struct Client *server,
1031 const char *nick, time_t newts, int parc, const char *parv[])
1032 {
1033 struct Client *source_p;
1034 struct User *user;
1035 struct nd_entry *nd;
1036 const char *m;
1037 int flag;
1038
1039 source_p = make_client(client_p);
1040 user = make_user(source_p);
1041 rb_dlinkAddTail(source_p, &source_p->node, &global_client_list);
1042
1043 source_p->hopcount = atoi(parv[2]);
1044 source_p->tsinfo = newts;
1045
1046 strcpy(source_p->name, nick);
1047 rb_strlcpy(source_p->username, parv[5], sizeof(source_p->username));
1048 rb_strlcpy(source_p->host, parv[6], sizeof(source_p->host));
1049 rb_strlcpy(source_p->orighost, source_p->host, sizeof(source_p->orighost));
1050
1051 if(parc == 12)
1052 {
1053 rb_strlcpy(source_p->info, parv[11], sizeof(source_p->info));
1054 rb_strlcpy(source_p->sockhost, parv[7], sizeof(source_p->sockhost));
1055 rb_strlcpy(source_p->id, parv[8], sizeof(source_p->id));
1056 add_to_id_hash(source_p->id, source_p);
1057 if (strcmp(parv[9], "*"))
1058 {
1059 rb_strlcpy(source_p->orighost, parv[9], sizeof(source_p->orighost));
1060 if (irccmp(source_p->host, source_p->orighost))
1061 SetDynSpoof(source_p);
1062 }
1063 if (strcmp(parv[10], "*"))
1064 rb_strlcpy(source_p->user->suser, parv[10], sizeof(source_p->user->suser));
1065 }
1066 else if(parc == 10)
1067 {
1068 rb_strlcpy(source_p->info, parv[9], sizeof(source_p->info));
1069 rb_strlcpy(source_p->sockhost, parv[7], sizeof(source_p->sockhost));
1070 rb_strlcpy(source_p->id, parv[8], sizeof(source_p->id));
1071 add_to_id_hash(source_p->id, source_p);
1072 }
1073 else
1074 {
1075 s_assert(0);
1076 }
1077
1078 /* remove any nd entries for this nick */
1079 if((nd = rb_dictionary_retrieve(nd_dict, nick)))
1080 free_nd_entry(nd);
1081
1082 add_to_client_hash(nick, source_p);
1083 add_to_hostname_hash(source_p->orighost, source_p);
1084 monitor_signon(source_p);
1085
1086 m = &parv[4][1];
1087 while(*m)
1088 {
1089 flag = user_modes[(unsigned char) *m];
1090
1091 if(flag & UMODE_SERVICE)
1092 {
1093 int hit = 0;
1094 rb_dlink_node *ptr;
1095
1096 RB_DLINK_FOREACH(ptr, service_list.head)
1097 {
1098 if(!irccmp((const char *) ptr->data, server->name))
1099 {
1100 hit++;
1101 break;
1102 }
1103 }
1104
1105 if(!hit)
1106 {
1107 m++;
1108 continue;
1109 }
1110 }
1111
1112 /* increment +i count if theyre invis */
1113 if(!(source_p->umodes & UMODE_INVISIBLE) && (flag & UMODE_INVISIBLE))
1114 Count.invisi++;
1115
1116 /* increment opered count if theyre opered */
1117 if(!(source_p->umodes & UMODE_OPER) && (flag & UMODE_OPER))
1118 Count.oper++;
1119
1120 source_p->umodes |= flag;
1121 m++;
1122 }
1123
1124 if(IsOper(source_p) && !IsService(source_p))
1125 rb_dlinkAddAlloc(source_p, &oper_list);
1126
1127 SetRemoteClient(source_p);
1128
1129 if(++Count.total > Count.max_tot)
1130 Count.max_tot = Count.total;
1131
1132 source_p->servptr = server;
1133
1134 rb_dlinkAdd(source_p, &source_p->lnode, &source_p->servptr->serv->users);
1135
1136 call_hook(h_new_remote_user, source_p);
1137
1138 return (introduce_client(client_p, source_p, user, nick, parc == 12));
1139 }
1140
1141 /* Check if we can do SAVE. target_p can be a client to save or a
1142 * server introducing a client -- jilles */
1143 static int
1144 can_save(struct Client *target_p)
1145 {
1146 struct Client *serv_p;
1147
1148 if (MyClient(target_p))
1149 return 1;
1150 if (!has_id(target_p))
1151 return 0;
1152 serv_p = IsServer(target_p) ? target_p : target_p->servptr;
1153 while (serv_p != NULL && serv_p != &me)
1154 {
1155 if (!(serv_p->serv->caps & CAP_SAVE))
1156 return 0;
1157 serv_p = serv_p->servptr;
1158 }
1159 return serv_p == &me;
1160 }
1161
1162 static void
1163 save_user(struct Client *client_p, struct Client *source_p,
1164 struct Client *target_p)
1165 {
1166 if (!MyConnect(target_p) && (!has_id(target_p) || !IsCapable(target_p->from, CAP_SAVE)))
1167 {
1168 /* This shouldn't happen */
1169 /* Note we only need SAVE support in this direction */
1170 sendto_realops_snomask(SNO_GENERAL, L_ALL,
1171 "Killed %s!%s@%s for nick collision detected by %s (%s does not support SAVE)",
1172 target_p->name, target_p->username, target_p->host, source_p->name, target_p->from->name);
1173 kill_client_serv_butone(NULL, target_p, "%s (Nick collision (no SAVE support))", me.name);
1174 ServerStats.is_kill++;
1175
1176 target_p->flags |= FLAGS_KILLED;
1177 (void) exit_client(NULL, target_p, &me, "Nick collision (no SAVE support)");
1178 return;
1179 }
1180 sendto_server(client_p, NULL, CAP_SAVE|CAP_TS6, NOCAPS, ":%s SAVE %s %ld",
1181 source_p->id, target_p->id, (long)target_p->tsinfo);
1182 sendto_server(client_p, NULL, CAP_TS6, CAP_SAVE, ":%s NICK %s :%ld",
1183 target_p->id, target_p->id, (long)SAVE_NICKTS);
1184 if (!IsMe(client_p))
1185 sendto_realops_snomask(SNO_SKILL, L_ALL,
1186 "Received SAVE message for %s from %s",
1187 target_p->name, source_p->name);
1188 if (MyClient(target_p))
1189 {
1190 sendto_one_numeric(target_p, RPL_SAVENICK,
1191 form_str(RPL_SAVENICK), target_p->id);
1192 change_local_nick(target_p, target_p, target_p->id, 0);
1193 target_p->tsinfo = SAVE_NICKTS;
1194 }
1195 else
1196 change_remote_nick(target_p, target_p, SAVE_NICKTS, target_p->id, 0);
1197 }
1198
1199 static void bad_nickname(struct Client *client_p, const char *nick)
1200 {
1201 char squitreason[100];
1202
1203 sendto_wallops_flags(UMODE_WALLOP, &me,
1204 "Squitting %s because of bad nickname %s (NICKLEN mismatch?)",
1205 client_p->name, nick);
1206 sendto_server(NULL, NULL, CAP_TS6, NOCAPS,
1207 ":%s WALLOPS :Squitting %s because of bad nickname %s (NICKLEN mismatch?)",
1208 me.id, client_p->name, nick);
1209 ilog(L_SERVER, "Link %s cancelled, bad nickname %s sent (NICKLEN mismatch?)",
1210 client_p->name, nick);
1211
1212 snprintf(squitreason, sizeof squitreason,
1213 "Bad nickname introduced [%s]", nick);
1214 exit_client(client_p, client_p, &me, squitreason);
1215 }