ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.1.x/modules/core/m_nick.c
Revision: 2047
Committed: Wed May 15 15:50:53 2013 UTC (10 years, 10 months ago) by michael
Content type: text/x-csrc
File size: 30845 byte(s)
Log Message:
- m_nick.c: replaced few strcpy() with strlcpy()

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

Properties

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