ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/core/m_nick.c
Revision: 1431
Committed: Sat Jun 9 19:15:10 2012 UTC (14 years, 1 month ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/modules/core/m_nick.c
File size: 30358 byte(s)
Log Message:
- NICKLEN definition no longer respects the trailing NUL character
  (reverts to old behavior)

File Contents

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

Properties

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