ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/core/m_nick.c
Revision: 1624
Committed: Thu Nov 1 13:27:04 2012 UTC (13 years, 8 months ago) by michael
Content type: text/x-csrc
File size: 31023 byte(s)
Log Message:
- Fixed compile warnings due to missing arguments to sendto_realops_flags()

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

Properties

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