ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/core/m_nick.c
Revision: 1751
Committed: Wed Jan 16 18:30:52 2013 UTC (13 years, 8 months ago) by michael
Content type: text/x-csrc
File size: 31220 byte(s)
Log Message:
- Forward-port -r1750 [IMPORTANT: nick and topic lengths are now configurable
  via ircd.conf. A max_nick_length, as well as a max_topic_length configuration
  option can now be found in the serverinfo{} block]
- OpenSSL 0.9.8s and higher is now required in order to enable ssl support

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

Properties

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