ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/core/m_nick.c
Revision: 1734
Committed: Fri Jan 11 12:59:24 2013 UTC (13 years, 6 months ago) by michael
Content type: text/x-csrc
File size: 31116 byte(s)
Log Message:
- Add support for "away-notify" client capability

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

Properties

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