/[svn]/ircd-hybrid/branches/8.1.x/modules/core/m_nick.c
ViewVC logotype

Contents of /ircd-hybrid/branches/8.1.x/modules/core/m_nick.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2956 - (show annotations)
Tue Jan 28 16:41:18 2014 UTC (6 years, 9 months ago) by michael
File MIME type: text/x-chdr
File size: 30129 byte(s)
- register_remote_user(): removed unused realname/gecos parameter

1 /*
2 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 *
4 * Copyright (c) 1997-2014 ircd-hybrid development team
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 * USA
20 */
21
22 /*! \file m_nick.c
23 * \brief Includes required functions for processing the NICK command.
24 * \version $Id$
25 */
26
27 #include "stdinc.h"
28 #include "list.h"
29 #include "client.h"
30 #include "hash.h"
31 #include "fdlist.h"
32 #include "irc_string.h"
33 #include "ircd.h"
34 #include "numeric.h"
35 #include "conf.h"
36 #include "s_user.h"
37 #include "whowas.h"
38 #include "s_serv.h"
39 #include "send.h"
40 #include "channel.h"
41 #include "channel_mode.h"
42 #include "log.h"
43 #include "resv.h"
44 #include "parse.h"
45 #include "modules.h"
46 #include "packet.h"
47 #include "watch.h"
48 #include "s_misc.h"
49
50
51 /* check_clean_nick()
52 *
53 * input - pointer to source
54 * -
55 * - nickname
56 * - truncated nickname
57 * - origin of client
58 * - pointer to server nick is coming from
59 * output - none
60 * side effects - if nickname is erroneous, or a different length to
61 * truncated nickname, return 1
62 */
63 static int
64 check_clean_nick(struct Client *client_p, struct Client *source_p,
65 char *nick, struct Client *server_p)
66 {
67 /* the old code did some wacky stuff here, if the nick is invalid, kill it
68 * and dont bother messing at all
69 */
70 if (!valid_nickname(nick, 0))
71 {
72 ++ServerStats.is_kill;
73 sendto_realops_flags(UMODE_DEBUG, L_ALL, SEND_NOTICE,
74 "Bad/long Nick: %s From: %s(via %s)",
75 nick, server_p->name, client_p->name);
76
77 sendto_one(client_p, ":%s KILL %s :%s (Bad Nickname)",
78 me.name, nick, me.name);
79
80 /* bad nick change */
81 if (source_p != client_p)
82 {
83 kill_client_serv_butone(client_p, source_p,
84 "%s (Bad Nickname)",
85 me.name);
86 AddFlag(source_p, FLAGS_KILLED);
87 exit_client(source_p, &me, "Bad Nickname");
88 }
89
90 return 1;
91 }
92
93 return 0;
94 }
95
96 /* check_clean_user()
97 *
98 * input - pointer to client sending data
99 * - nickname
100 * - username to check
101 * - origin of NICK
102 * output - none
103 * side effects - if username is erroneous, return 1
104 */
105 static int
106 check_clean_user(struct Client *client_p, char *nick,
107 char *user, struct Client *server_p)
108 {
109 if (!valid_username(user, 0))
110 {
111 ++ServerStats.is_kill;
112 sendto_realops_flags(UMODE_DEBUG, L_ALL, SEND_NOTICE,
113 "Bad/Long Username: %s Nickname: %s From: %s(via %s)",
114 user, nick, server_p->name, client_p->name);
115 sendto_one(client_p, ":%s KILL %s :%s (Bad Username)",
116 me.name, nick, me.name);
117 return 1;
118 }
119
120 return 0;
121 }
122
123 /* check_clean_host()
124 *
125 * input - pointer to client sending us data
126 * - nickname
127 * - hostname to check
128 * - source name
129 * output - none
130 * side effects - if hostname is erroneous, return 1
131 */
132 static int
133 check_clean_host(struct Client *client_p, char *nick,
134 char *host, struct Client *server_p)
135 {
136 if (!valid_hostname(host))
137 {
138 ++ServerStats.is_kill;
139 sendto_realops_flags(UMODE_DEBUG, L_ALL, SEND_NOTICE,
140 "Bad/Long Hostname: %s Nickname: %s From: %s(via %s)",
141 host, nick, server_p->name, client_p->name);
142 sendto_one(client_p, ":%s KILL %s :%s (Bad Hostname)",
143 me.name, nick, me.name);
144 return 1;
145 }
146
147 return 0;
148 }
149
150 /* set_initial_nick()
151 *
152 * inputs
153 * output
154 * side effects -
155 *
156 * This function is only called to set up an initially registering
157 * client.
158 */
159 static void
160 set_initial_nick(struct Client *source_p, const char *nick)
161 {
162 /* Client setting NICK the first time */
163
164 /* This had to be copied here to avoid problems.. */
165 source_p->tsinfo = CurrentTime;
166 source_p->localClient->registration &= ~REG_NEED_NICK;
167
168 if (source_p->name[0])
169 hash_del_client(source_p);
170
171 strlcpy(source_p->name, nick, sizeof(source_p->name));
172 hash_add_client(source_p);
173
174 /* fd_desc is long enough */
175 fd_note(&source_p->localClient->fd, "Nick: %s", nick);
176
177 if (!source_p->localClient->registration)
178 register_local_user(source_p);
179 }
180
181 /* change_local_nick()
182 *
183 * inputs - pointer to server
184 * - pointer to client
185 * - nick
186 * output -
187 * side effects - changes nick of a LOCAL user
188 */
189 static void
190 change_local_nick(struct Client *source_p, const char *nick)
191 {
192 int samenick = 0;
193
194 assert(source_p->name[0] && !EmptyString(nick));
195 assert(MyConnect(source_p));
196
197 /*
198 * Client just changing his/her nick. If he/she is
199 * on a channel, send note of change to all clients
200 * on that channel. Propagate notice to other servers.
201 */
202 if ((source_p->localClient->last_nick_change +
203 ConfigFileEntry.max_nick_time) < CurrentTime)
204 source_p->localClient->number_of_nick_changes = 0;
205
206 if (ConfigFileEntry.anti_nick_flood &&
207 !HasUMode(source_p, UMODE_OPER) &&
208 source_p->localClient->number_of_nick_changes >
209 ConfigFileEntry.max_nick_changes)
210 {
211 sendto_one(source_p, form_str(ERR_NICKTOOFAST), me.name,
212 source_p->name, source_p->name, nick,
213 ConfigFileEntry.max_nick_time);
214 return;
215 }
216
217 source_p->localClient->last_nick_change = CurrentTime;
218 source_p->localClient->number_of_nick_changes++;
219
220 samenick = !irccmp(source_p->name, nick);
221
222 if (!samenick)
223 {
224 source_p->tsinfo = CurrentTime;
225 clear_ban_cache_client(source_p);
226 watch_check_hash(source_p, RPL_LOGOFF);
227
228 if (HasUMode(source_p, UMODE_REGISTERED))
229 {
230 unsigned int oldmodes = source_p->umodes;
231 char modebuf[IRCD_BUFSIZE] = { '\0' };
232
233 DelUMode(source_p, UMODE_REGISTERED);
234 send_umode(source_p, source_p, oldmodes, 0xffffffff, modebuf);
235 }
236 }
237
238 sendto_realops_flags(UMODE_NCHANGE, L_ALL, SEND_NOTICE,
239 "Nick change: From %s to %s [%s@%s]",
240 source_p->name, nick, source_p->username, source_p->host);
241 sendto_common_channels_local(source_p, 1, 0, ":%s!%s@%s NICK :%s",
242 source_p->name, source_p->username,
243 source_p->host, nick);
244 whowas_add_history(source_p, 1);
245
246 sendto_server(source_p, CAP_TS6, NOCAPS,
247 ":%s NICK %s :%lu",
248 ID(source_p), nick, (unsigned long)source_p->tsinfo);
249 sendto_server(source_p, NOCAPS, CAP_TS6,
250 ":%s NICK %s :%lu",
251 source_p->name, nick, (unsigned long)source_p->tsinfo);
252
253 hash_del_client(source_p);
254 strlcpy(source_p->name, nick, sizeof(source_p->name));
255 hash_add_client(source_p);
256
257 if (!samenick)
258 watch_check_hash(source_p, RPL_LOGON);
259
260 /* fd_desc is long enough */
261 fd_note(&source_p->localClient->fd, "Nick: %s", nick);
262 }
263
264 /*
265 * nick_from_server()
266 */
267 static void
268 nick_from_server(struct Client *client_p, struct Client *source_p, int parc,
269 char *parv[], time_t newts, const char *svsid, char *nick, char *ngecos)
270 {
271 int samenick = 0;
272
273 if (IsServer(source_p))
274 {
275 /* A server introducing a new client, change source */
276 source_p = make_client(client_p);
277 dlinkAdd(source_p, &source_p->node, &global_client_list);
278
279 if (parc > 2)
280 source_p->hopcount = atoi(parv[2]);
281 if (newts)
282 source_p->tsinfo = newts;
283 else
284 {
285 newts = source_p->tsinfo = CurrentTime;
286 ts_warn("Remote nick %s (%s) introduced without a TS", nick, parv[0]);
287 }
288
289 strlcpy(source_p->svid, svsid, sizeof(source_p->svid));
290 strlcpy(source_p->info, ngecos, sizeof(source_p->info));
291 /* copy the nick in place */
292 strlcpy(source_p->name, nick, sizeof(source_p->name));
293 hash_add_client(source_p);
294
295 if (parc > 8)
296 {
297 const char *m;
298
299 /* parse usermodes */
300 for (m = &parv[4][1]; *m; ++m)
301 {
302 unsigned int flag = user_modes[(unsigned char)*m];
303
304 if ((flag & UMODE_INVISIBLE) && !HasUMode(source_p, UMODE_INVISIBLE))
305 ++Count.invisi;
306 if ((flag & UMODE_OPER) && !HasUMode(source_p, UMODE_OPER))
307 ++Count.oper;
308
309 source_p->umodes |= flag & SEND_UMODES;
310 }
311
312 register_remote_user(source_p, parv[5], parv[6], parv[7]);
313 return;
314 }
315 }
316 else if (source_p->name[0])
317 {
318 samenick = !irccmp(source_p->name, nick);
319
320 /* Client changing their nick */
321 if (!samenick)
322 {
323 DelUMode(source_p, UMODE_REGISTERED);
324 watch_check_hash(source_p, RPL_LOGOFF);
325 source_p->tsinfo = newts ? newts : CurrentTime;
326 }
327
328 sendto_common_channels_local(source_p, 1, 0, ":%s!%s@%s NICK :%s",
329 source_p->name,source_p->username,
330 source_p->host, nick);
331
332 whowas_add_history(source_p, 1);
333 sendto_server(client_p, CAP_TS6, NOCAPS,
334 ":%s NICK %s :%lu",
335 ID(source_p), nick, (unsigned long)source_p->tsinfo);
336 sendto_server(client_p, NOCAPS, CAP_TS6,
337 ":%s NICK %s :%lu",
338 source_p->name, nick, (unsigned long)source_p->tsinfo);
339 }
340
341 /* set the new nick name */
342 if (source_p->name[0])
343 hash_del_client(source_p);
344
345 strlcpy(source_p->name, nick, sizeof(source_p->name));
346 hash_add_client(source_p);
347
348 if (!samenick)
349 watch_check_hash(source_p, RPL_LOGON);
350 }
351
352 /*
353 * client_from_server()
354 */
355 static void
356 uid_from_server(struct Client *client_p, struct Client *source_p, int parc,
357 char *parv[], time_t newts, const char *svsid, char *nick, char *ugecos)
358 {
359 const char *m = NULL;
360 const char *servername = source_p->name;
361
362 source_p = make_client(client_p);
363 dlinkAdd(source_p, &source_p->node, &global_client_list);
364
365 source_p->hopcount = atoi(parv[2]);
366 source_p->tsinfo = newts;
367 strlcpy(source_p->svid, svsid, sizeof(source_p->svid));
368
369 /* copy the nick in place */
370 strlcpy(source_p->name, nick, sizeof(source_p->name));
371 strlcpy(source_p->id, parv[8], sizeof(source_p->id));
372 strlcpy(source_p->sockhost, parv[7], sizeof(source_p->sockhost));
373 strlcpy(source_p->info, ugecos, sizeof(source_p->info));
374
375 hash_add_client(source_p);
376 hash_add_id(source_p);
377
378 /* parse usermodes */
379 for (m = &parv[4][1]; *m; ++m)
380 {
381 unsigned int flag = user_modes[(unsigned char)*m];
382
383 if ((flag & UMODE_INVISIBLE) && !HasUMode(source_p, UMODE_INVISIBLE))
384 ++Count.invisi;
385 if ((flag & UMODE_OPER) && !HasUMode(source_p, UMODE_OPER))
386 ++Count.oper;
387
388 source_p->umodes |= flag & SEND_UMODES;
389 }
390
391 register_remote_user(source_p, parv[5], parv[6], servername);
392 }
393
394 static void
395 perform_nick_collides(struct Client *source_p, struct Client *client_p,
396 struct Client *target_p, int parc, char *parv[],
397 time_t newts, const char *svsid, char *nick, char *gecos, char *uid)
398 {
399 int sameuser = 0;
400
401 /* Server introducing new nick */
402 if (IsServer(source_p))
403 {
404 /* If we don't have a TS, or their TS's are the same, kill both */
405 if (!newts || !target_p->tsinfo || (newts == target_p->tsinfo))
406 {
407 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
408 "Nick collision on %s(%s <- %s)(both killed)",
409 target_p->name, target_p->from->name,
410 client_p->name);
411
412 /* if we have a UID, issue a kill for it */
413 if (uid)
414 sendto_one(client_p, ":%s KILL %s :%s (Nick collision (new))",
415 me.id, uid, me.name);
416
417 kill_client_serv_butone(NULL, target_p,
418 "%s (Nick collision (new))", me.name);
419 ++ServerStats.is_kill;
420 sendto_one(target_p, form_str(ERR_NICKCOLLISION),
421 me.name, target_p->name, target_p->name);
422
423 AddFlag(target_p, FLAGS_KILLED);
424 exit_client(target_p, &me, "Nick collision (new)");
425 return;
426 }
427 /* the timestamps are different */
428 else
429 {
430 sameuser = !irccmp(target_p->username, parv[5]) &&
431 !irccmp(target_p->host, parv[6]);
432
433 /*
434 * If the users are the same (loaded a client on a different server)
435 * and the new users ts is older, or the users are different and the
436 * new users ts is newer, ignore the new client and let it do the kill
437 */
438 if ((sameuser && newts < target_p->tsinfo) ||
439 (!sameuser && newts > target_p->tsinfo))
440 {
441 if (uid)
442 sendto_one(client_p, ":%s KILL %s :%s (Nick collision (new))",
443 me.id, uid, me.name);
444 return;
445 }
446 else
447 {
448 if (sameuser)
449 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
450 "Nick collision on %s(%s <- %s)(older killed)",
451 target_p->name, target_p->from->name,
452 client_p->name);
453 else
454 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
455 "Nick collision on %s(%s <- %s)(newer killed)",
456 target_p->name, target_p->from->name,
457 client_p->name);
458
459 ++ServerStats.is_kill;
460 sendto_one(target_p, form_str(ERR_NICKCOLLISION),
461 me.name, target_p->name, target_p->name);
462
463 /* if it came from a LL server, itd have been source_p,
464 * so we dont need to mark target_p as known
465 */
466 kill_client_serv_butone(source_p, target_p,
467 "%s (Nick collision (new))", me.name);
468
469 AddFlag(target_p, FLAGS_KILLED);
470 exit_client(target_p, &me, "Nick collision");
471
472 if (!uid && (parc == 9 || parc == 10))
473 nick_from_server(client_p, source_p, parc, parv, newts, svsid, nick, gecos);
474 else if (uid && (parc == 10 || parc == 11))
475 uid_from_server(client_p, source_p, parc, parv, newts, svsid, nick, gecos);
476 return;
477 }
478 }
479 }
480
481 /* its a client changing nick and causing a collide */
482 if (!newts || !target_p->tsinfo || (newts == target_p->tsinfo))
483 {
484 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
485 "Nick change collision from %s to %s(%s <- %s)(both killed)",
486 source_p->name, target_p->name, target_p->from->name,
487 client_p->name);
488
489 sendto_one(target_p, form_str(ERR_NICKCOLLISION), me.name,
490 target_p->name, target_p->name);
491
492 ++ServerStats.is_kill;
493 kill_client_serv_butone(NULL, source_p, "%s (Nick change collision)",
494 me.name);
495
496 ++ServerStats.is_kill;
497 kill_client_serv_butone(NULL, target_p, "%s (Nick change collision)",
498 me.name);
499
500 AddFlag(target_p, FLAGS_KILLED);
501 exit_client(target_p, &me, "Nick collision (new)");
502
503 AddFlag(source_p, FLAGS_KILLED);
504 exit_client(source_p, &me, "Nick collision (old)");
505 return;
506 }
507 else
508 {
509 sameuser = !irccmp(target_p->username, source_p->username) &&
510 !irccmp(target_p->host, source_p->host);
511
512 if ((sameuser && newts < target_p->tsinfo) ||
513 (!sameuser && newts > target_p->tsinfo))
514 {
515 if (sameuser)
516 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
517 "Nick change collision from %s to %s(%s <- %s)(older killed)",
518 source_p->name, target_p->name, target_p->from->name,
519 client_p->name);
520 else
521 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
522 "Nick change collision from %s to %s(%s <- %s)(newer killed)",
523 source_p->name, target_p->name, target_p->from->name,
524 client_p->name);
525
526 ++ServerStats.is_kill;
527 kill_client_serv_butone(client_p, source_p,
528 "%s (Nick change collision)", me.name);
529 AddFlag(source_p, FLAGS_KILLED);
530
531 if (sameuser)
532 exit_client(source_p, &me, "Nick collision (old)");
533 else
534 exit_client(source_p, &me, "Nick collision (new)");
535 return;
536 }
537 else
538 {
539 if (sameuser)
540 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
541 "Nick collision on %s(%s <- %s)(older killed)",
542 target_p->name, target_p->from->name,
543 client_p->name);
544 else
545 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
546 "Nick collision on %s(%s <- %s)(newer killed)",
547 target_p->name, target_p->from->name,
548 client_p->name);
549
550 kill_client_serv_butone(source_p, target_p,
551 "%s (Nick collision)", me.name);
552
553 ++ServerStats.is_kill;
554 sendto_one(target_p, form_str(ERR_NICKCOLLISION),
555 me.name, target_p->name, target_p->name);
556
557 AddFlag(target_p, FLAGS_KILLED);
558 exit_client(target_p, &me, "Nick collision");
559 }
560 }
561
562 /*
563 * we should only ever call nick_from_server() here, as
564 * this is a client changing nick, not a new client
565 */
566 nick_from_server(client_p, source_p, parc, parv, newts, svsid, nick, gecos);
567 }
568
569 /*! \brief NICK command handler (called by unregistered,
570 * locally connected clients)
571 *
572 * \param client_p Pointer to allocated Client struct with physical connection
573 * to this server, i.e. with an open socket connected.
574 * \param source_p Pointer to allocated Client struct from which the message
575 * originally comes from. This can be a local or remote client.
576 * \param parc Integer holding the number of supplied arguments.
577 * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
578 * pointers.
579 * \note Valid arguments for this command are:
580 * - parv[0] = sender prefix
581 * - parv[1] = nickname
582 */
583 static int
584 mr_nick(struct Client *client_p, struct Client *source_p,
585 int parc, char *parv[])
586 {
587 char nick[NICKLEN + 1] = { '\0' };
588 struct Client *target_p = NULL;
589 struct MaskItem *conf = NULL;
590
591 if (parc < 2 || EmptyString(parv[1]))
592 {
593 sendto_one(source_p, form_str(ERR_NONICKNAMEGIVEN), me.name,
594 source_p->name[0] ? source_p->name : "*");
595 return 0;
596 }
597
598 /* Copy the nick and terminate it */
599 strlcpy(nick, parv[1], IRCD_MIN(sizeof(nick), ServerInfo.max_nick_length + 1));
600
601 /* Check the nickname is ok */
602 if (!valid_nickname(nick, 1))
603 {
604 sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME), me.name,
605 source_p->name[0] ? source_p->name : "*", parv[1],
606 "Erroneous Nickname");
607 return 0;
608 }
609
610 /* Check if the nick is resv'd */
611 if ((conf = find_matching_name_conf(CONF_NRESV, nick, NULL, NULL, 0)))
612 {
613 ++conf->count;
614 sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME), me.name,
615 source_p->name[0] ? source_p->name : "*", nick, conf->reason);
616 sendto_realops_flags(UMODE_REJ, L_ALL, SEND_NOTICE,
617 "Forbidding reserved nick %s from user %s",
618 nick, get_client_name(client_p, HIDE_IP));
619 return 0;
620 }
621
622 if ((target_p = hash_find_client(nick)) == NULL)
623 set_initial_nick(source_p, nick);
624 else if (source_p == target_p)
625 strlcpy(source_p->name, nick, sizeof(source_p->name));
626 else
627 sendto_one(source_p, form_str(ERR_NICKNAMEINUSE), me.name, "*", nick);
628 return 0;
629 }
630
631 /*! \brief NICK command handler (called by already registered,
632 * locally connected clients)
633 *
634 * \param client_p Pointer to allocated Client struct with physical connection
635 * to this server, i.e. with an open socket connected.
636 * \param source_p Pointer to allocated Client struct from which the message
637 * originally comes from. This can be a local or remote client.
638 * \param parc Integer holding the number of supplied arguments.
639 * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
640 * pointers.
641 * \note Valid arguments for this command are:
642 * - parv[0] = sender prefix
643 * - parv[1] = nickname
644 */
645 static int
646 m_nick(struct Client *client_p, struct Client *source_p,
647 int parc, char *parv[])
648 {
649 char nick[NICKLEN + 1] = { '\0' };
650 struct Client *target_p = NULL;
651 struct MaskItem *conf = NULL;
652
653 assert(source_p == client_p);
654
655 if (parc < 2 || EmptyString(parv[1]))
656 {
657 sendto_one(source_p, form_str(ERR_NONICKNAMEGIVEN),
658 me.name, source_p->name);
659 return 0;
660 }
661
662 /* mark end of grace period, to prevent nickflooding */
663 if (!IsFloodDone(source_p))
664 flood_endgrace(source_p);
665
666 /* terminate nick to NICKLEN */
667 strlcpy(nick, parv[1], IRCD_MIN(sizeof(nick), ServerInfo.max_nick_length + 1));
668
669 /* check the nickname is ok */
670 if (!valid_nickname(nick, 1))
671 {
672 sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME), me.name,
673 source_p->name, nick, "Erroneous Nickname");
674 return 0;
675 }
676
677 if (!IsExemptResv(source_p) &&
678 !(HasUMode(source_p, UMODE_OPER) && ConfigFileEntry.oper_pass_resv) &&
679 (conf = find_matching_name_conf(CONF_NRESV, nick, NULL, NULL, 0)))
680 {
681 ++conf->count;
682 sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME),
683 me.name, source_p->name, nick, conf->reason);
684 sendto_realops_flags(UMODE_REJ, L_ALL, SEND_NOTICE,
685 "Forbidding reserved nick %s from user %s",
686 nick, get_client_name(client_p, HIDE_IP));
687 return 0;
688 }
689
690 if ((target_p = hash_find_client(nick)) == NULL)
691 change_local_nick(source_p, nick);
692 else if (target_p == source_p)
693 {
694 /*
695 * If (target_p == source_p) the client is changing nicks between
696 * equivalent nicknames ie: [nick] -> {nick}
697 */
698
699 /* Check the nick isn't exactly the same */
700 if (strcmp(target_p->name, nick))
701 change_local_nick(source_p, nick);
702 }
703 else if (IsUnknown(target_p))
704 {
705 /*
706 * If the client that has the nick isn't registered yet (nick but no
707 * user) then drop the unregged client
708 */
709 exit_client(target_p, &me, "Overridden");
710 change_local_nick(source_p, nick);
711 }
712 else
713 sendto_one(source_p, form_str(ERR_NICKNAMEINUSE), me.name,
714 source_p->name, nick);
715 return 0;
716 }
717
718 /*! \brief NICK command handler (called by servers and remotely
719 * connected clients)
720 *
721 * \param client_p Pointer to allocated Client struct with physical connection
722 * to this server, i.e. with an open socket connected.
723 * \param source_p Pointer to allocated Client struct from which the message
724 * originally comes from. This can be a local or remote client.
725 * \param parc Integer holding the number of supplied arguments.
726 * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
727 * pointers.
728 * \note Valid arguments for this command are:
729 *
730 * server -> server nick change
731 * - parv[0] = sender prefix
732 * - parv[1] = nickname
733 * - parv[2] = TS when nick change
734 *
735 * server introducing new nick (without services support)
736 * - parv[0] = sender prefix
737 * - parv[1] = nickname
738 * - parv[2] = hop count
739 * - parv[3] = TS
740 * - parv[4] = umode
741 * - parv[5] = username
742 * - parv[6] = hostname
743 * - parv[7] = server
744 * - parv[8] = ircname
745 *
746 * server introducing new nick (with services support)
747 * - parv[0] = sender prefix
748 * - parv[1] = nickname
749 * - parv[2] = hop count
750 * - parv[3] = TS
751 * - parv[4] = umode
752 * - parv[5] = username
753 * - parv[6] = hostname
754 * - parv[7] = server
755 * - parv[8] = services id (timestamp)
756 * - parv[9] = ircname
757 */
758 static int
759 ms_nick(struct Client *client_p, struct Client *source_p,
760 int parc, char *parv[])
761 {
762 struct Client *target_p = NULL;
763 time_t newts = 0;
764 const char *svsid = "0";
765
766 if (parc < 3 || EmptyString(parv[parc - 1]))
767 return 0;
768
769 if (parc >= 9)
770 {
771 struct Client *server_p = hash_find_server(parv[7]);
772
773 if (server_p == NULL)
774 {
775 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
776 "Invalid server %s from %s for NICK %s",
777 parv[7], source_p->name, parv[1]);
778 sendto_one(client_p, ":%s KILL %s :%s (Server doesn't exist!)",
779 me.name, parv[1], me.name);
780 return 0;
781 }
782
783 if (check_clean_nick(client_p, source_p, parv[1], server_p) ||
784 check_clean_user(client_p, parv[1], parv[5], server_p) ||
785 check_clean_host(client_p, parv[1], parv[6], server_p))
786 return 0;
787
788 if (IsServer(source_p))
789 newts = atol(parv[3]);
790 if (IsServer(source_p) && parc == 10)
791 svsid = parv[8];
792 }
793 else if (parc == 3)
794 {
795 if (IsServer(source_p))
796 /* Servers can't change nicks.. */
797 return 0;
798
799 if (check_clean_nick(client_p, source_p, parv[1],
800 source_p->servptr))
801 return 0;
802
803 newts = atol(parv[2]);
804 }
805
806 /* If the nick doesnt exist, allow it and process like normal */
807 if ((target_p = hash_find_client(parv[1])) == NULL)
808 nick_from_server(client_p, source_p, parc, parv, newts, svsid, parv[1], parv[parc-1]);
809 else if (IsUnknown(target_p))
810 {
811 /* We're not living in the past anymore, an unknown client is local only. */
812 exit_client(target_p, &me, "Overridden");
813 nick_from_server(client_p, source_p, parc, parv, newts, svsid, parv[1], parv[parc-1]);
814 }
815 else if (target_p == source_p)
816 {
817 if (strcmp(target_p->name, parv[1]))
818 nick_from_server(client_p, source_p, parc, parv, newts, svsid, parv[1], parv[parc-1]);
819 }
820 else
821 perform_nick_collides(source_p, client_p, target_p, parc, parv,
822 newts, svsid, parv[1], parv[parc-1], NULL);
823 return 0;
824 }
825
826 /*! \brief UID command handler (called by servers)
827 *
828 * \param client_p Pointer to allocated Client struct with physical connection
829 * to this server, i.e. with an open socket connected.
830 * \param source_p Pointer to allocated Client struct from which the message
831 * originally comes from. This can be a local or remote client.
832 * \param parc Integer holding the number of supplied arguments.
833 * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
834 * pointers.
835 * \note Valid arguments for this command are:
836 *
837 * server introducing new nick (without services support)
838 * - parv[0] = sender prefix
839 * - parv[1] = nickname
840 * - parv[2] = hop count
841 * - parv[3] = TS
842 * - parv[4] = umode
843 * - parv[5] = username
844 * - parv[6] = hostname
845 * - parv[7] = ip
846 * - parv[8] = uid
847 * - parv[9] = ircname (gecos)
848 *
849 * server introducing new nick (with services support)
850 * - parv[ 0] = sender prefix
851 * - parv[ 1] = nickname
852 * - parv[ 2] = hop count
853 * - parv[ 3] = TS
854 * - parv[ 4] = umode
855 * - parv[ 5] = username
856 * - parv[ 6] = hostname
857 * - parv[ 7] = ip
858 * - parv[ 8] = uid
859 * - parv[ 9] = services id (timestamp)
860 * - parv[10] = ircname (gecos)
861 */
862 static int
863 ms_uid(struct Client *client_p, struct Client *source_p,
864 int parc, char *parv[])
865 {
866 struct Client *target_p = NULL;
867 time_t newts = 0;
868 const char *svsid = "0";
869
870 if (parc < 10 || EmptyString(parv[parc-1]))
871 return 0;
872
873 if (check_clean_nick(client_p, source_p, parv[1], source_p) ||
874 check_clean_user(client_p, parv[1], parv[5], source_p) ||
875 check_clean_host(client_p, parv[1], parv[6], source_p))
876 return 0;
877
878 newts = atol(parv[3]);
879 svsid = parc == 11 ? parv[9] : "0";
880
881 /*
882 * If there is an ID collision, kill our client, and kill theirs.
883 * This may generate 401's, but it ensures that both clients always
884 * go, even if the other server refuses to do the right thing.
885 */
886 if ((target_p = hash_find_id(parv[8])) != NULL)
887 {
888 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
889 "ID collision on %s(%s <- %s)(both killed)",
890 target_p->name, target_p->from->name,
891 client_p->name);
892 kill_client_serv_butone(NULL, target_p, "%s (ID collision)",
893 me.name);
894
895 ++ServerStats.is_kill;
896 AddFlag(target_p, FLAGS_KILLED);
897 exit_client(target_p, &me, "ID Collision");
898 return 0;
899 }
900
901 if ((target_p = hash_find_client(parv[1])) == NULL)
902 uid_from_server(client_p, source_p, parc, parv, newts, svsid, parv[1], parv[parc-1]);
903 else if (IsUnknown(target_p))
904 {
905 exit_client(target_p, &me, "Overridden");
906 uid_from_server(client_p, source_p, parc, parv, newts, svsid, parv[1], parv[parc-1]);
907 }
908 else
909 perform_nick_collides(source_p, client_p, target_p, parc, parv, newts, svsid, parv[1],
910 parv[parc-1], parv[8]);
911 return 0;
912 }
913
914 static struct Message nick_msgtab =
915 {
916 "NICK", 0, 0, 0, MAXPARA, MFLG_SLOW, 0,
917 { mr_nick, m_nick, ms_nick, m_ignore, m_nick, m_ignore }
918 };
919
920 static struct Message uid_msgtab =
921 {
922 "UID", 0, 0, 10, MAXPARA, MFLG_SLOW, 0,
923 { m_ignore, m_ignore, ms_uid, m_ignore, m_ignore, m_ignore }
924 };
925
926 static void
927 module_init(void)
928 {
929 mod_add_cmd(&uid_msgtab);
930 mod_add_cmd(&nick_msgtab);
931 }
932
933 static void
934 module_exit(void)
935 {
936 mod_del_cmd(&uid_msgtab);
937 mod_del_cmd(&nick_msgtab);
938 }
939
940 struct module module_entry =
941 {
942 .node = { NULL, NULL, NULL },
943 .name = NULL,
944 .version = "$Revision$",
945 .handle = NULL,
946 .modinit = module_init,
947 .modexit = module_exit,
948 .flags = MODULE_FLAG_CORE
949 };

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision

svnadmin@ircd-hybrid.org
ViewVC Help
Powered by ViewVC 1.1.28