don't forward users if they are already in the target channel (mode +F)
[ircu2.10.12-pk.git] / ircd / m_join.c
1 /*
2  * IRC - Internet Relay Chat, ircd/m_join.c
3  * Copyright (C) 1990 Jarkko Oikarinen and
4  *                    University of Oulu, Computing Center
5  *
6  * See file AUTHORS in IRC package for additional names of
7  * the programmers.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 1, or (at your option)
12  * any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  *
23  * $Id: m_join.c 1906 2009-02-09 03:39:42Z entrope $
24  */
25
26 #include "config.h"
27
28 #include "channel.h"
29 #include "class.h"
30 #include "client.h"
31 #include "gline.h"
32 #include "hash.h"
33 #include "ircd.h"
34 #include "ircd_chattr.h"
35 #include "ircd_features.h"
36 #include "ircd_log.h"
37 #include "ircd_reply.h"
38 #include "ircd_string.h"
39 #include "list.h"
40 #include "msg.h"
41 #include "numeric.h"
42 #include "numnicks.h"
43 #include "s_conf.h"
44 #include "s_debug.h"
45 #include "s_user.h"
46 #include "send.h"
47 #include "sys.h"
48
49 /* #include <assert.h> -- Now using assert in ircd_log.h */
50 #include <stdlib.h>
51 #include <string.h>
52
53 /** Searches for and handles a 0 in a join list.
54  * @param[in] cptr Client that sent us the message.
55  * @param[in] sptr Original source of message.
56  * @param[in] chanlist List of channels to join.
57  * @return First token in \a chanlist after the final 0 entry, which
58  * may be its nul terminator (if the final entry is a 0 entry).
59  */
60 static char *
61 last0(struct Client *cptr, struct Client *sptr, char *chanlist)
62 {
63   char *p;
64   int join0 = 0;
65
66   for (p = chanlist; p[0]; p++) /* find last "JOIN 0" */
67     if (p[0] == '0' && (p[1] == ',' || p[1] == '\0')) {
68       if (p[1] == ',')
69         p++;
70       chanlist = p + 1;
71       join0 = 1;
72     } else {
73       while (p[0] != ',' && p[0] != '\0') /* skip past channel name */
74         p++;
75
76       if (!p[0]) /* hit the end */
77         break;
78     }
79
80   if (join0) {
81     struct JoinBuf part;
82     struct Membership *member;
83
84     joinbuf_init(&part, sptr, cptr, JOINBUF_TYPE_PARTALL,
85                  "Left all channels", 0);
86
87     joinbuf_join(&part, 0, 0);
88
89     while ((member = cli_user(sptr)->channel))
90       joinbuf_join(&part, member->channel,
91                    IsZombie(member) ? CHFL_ZOMBIE :
92                    IsDelayedJoin(member) ? CHFL_DELAYED :
93                    0);
94
95     joinbuf_flush(&part);
96   }
97
98   return chanlist;
99 }
100
101 /** Handle a JOIN message from a client connection.
102  * See @ref m_functions for discussion of the arguments.
103  * @param[in] cptr Client that sent us the message.
104  * @param[in] sptr Original source of message.
105  * @param[in] parc Number of arguments.
106  * @param[in] parv Argument vector.
107  */
108 int m_join(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
109 {
110   struct Channel *chptr,*chptrb;
111   struct JoinBuf join;
112   struct JoinBuf create;
113   struct Gline *gline;
114   struct Membership *member;
115   char *p = 0;
116   char *chanlist;
117   char *name;
118   char *keys;
119   unsigned int maxchans;
120   const struct User* user = cli_user(sptr);
121
122   if (parc < 2 || *parv[1] == '\0')
123     return need_more_params(sptr, "JOIN");
124
125   joinbuf_init(&join, sptr, cptr, JOINBUF_TYPE_JOIN, 0, 0);
126   joinbuf_init(&create, sptr, cptr, JOINBUF_TYPE_CREATE, 0, TStime());
127
128   chanlist = last0(cptr, sptr, parv[1]); /* find last "JOIN 0" */
129
130   keys = parv[2]; /* remember where keys are */
131
132   for (name = ircd_strtok(&p, chanlist, ","); name;
133        name = ircd_strtok(&p, 0, ",")) {
134     char *key = 0;
135
136     /* If we have any more keys, take the first for this channel. */
137     if (!BadPtr(keys)
138         && (keys = strchr(key = keys, ',')))
139       *keys++ = '\0';
140
141     /* Empty keys are the same as no keys. */
142     if (key && !key[0])
143       key = 0;
144
145     if (!IsChannelName(name) || !strIsIrcCh(name))
146     {
147       /* bad channel name */
148       send_reply(sptr, ERR_NOSUCHCHANNEL, name);
149       continue;
150     }
151
152     maxchans = cli_confs(sptr)->value.aconf ? ConfMaxChannels(cli_confs(sptr)->value.aconf) : feature_int(FEAT_MAXCHANNELSPERUSER);
153     if(sptr->maxchans > 0)
154         maxchans = sptr->maxchans;
155     if (cli_user(sptr)->joined >= maxchans
156         && !HasPriv(sptr, PRIV_CHAN_LIMIT)) {
157       send_reply(sptr, ERR_TOOMANYCHANNELS, name);
158       break; /* no point processing the other channels */
159     }
160     
161         int flags = 0;
162         
163     /* BADCHANed channel */
164     if ((gline = gline_find(name, GLINE_BADCHAN)) &&
165         GlineIsActive(gline) && !IsAnOper(sptr)) {
166       send_reply(sptr, ERR_BADCHANNAME, name, GlineReason(gline));
167       continue;
168     }
169
170     if (!(chptr = FindChannel(name))) {
171       if (((name[0] == '&') && !feature_bool(FEAT_LOCAL_CHANNELS))
172           || strlen(name) > IRCD_MIN(CHANNELLEN, feature_int(FEAT_CHANNELLEN))) {
173         send_reply(sptr, ERR_NOSUCHCHANNEL, name);
174         continue;
175       }
176
177       if (!(chptr = get_channel(sptr, name, CGT_CREATE)))
178         continue;
179
180       /* Try to add the new channel as a recent target for the user. */
181       if (check_target_limit(sptr, chptr, chptr->chname, 0)) {
182         chptr->members = 0;
183         destruct_channel(chptr);
184         continue;
185       }
186
187       joinbuf_join(&create, chptr, CHFL_CHANOP | CHFL_CHANNEL_MANAGER);
188     } else if (member = find_member_link(chptr, sptr)) {
189           if(IsDelayedJoin(member) && IsInvisibleJoin(member)) {
190            ClearInvisibleJoin(member);
191            RevealDelayedJoinIfNeeded(sptr, chptr);
192           }
193       continue;
194     } else if (check_target_limit(sptr, chptr, chptr->chname, 0)) {
195       continue;
196     } else {
197       flags = CHFL_DEOPPED;
198       int err = 0;
199       int override = 0;
200
201       /* Check Apass/Upass -- since we only ever look at a single
202        * "key" per channel now, this hampers brute force attacks. */
203       if (key && !strcmp(key, chptr->mode.apass))
204         flags = CHFL_CHANOP | CHFL_CHANNEL_MANAGER;
205       else if (key && !strcmp(key, chptr->mode.upass))
206         flags = CHFL_CHANOP;
207       else if (chptr->users == 0 && !chptr->mode.apass[0] && !(chptr->mode.mode & MODE_PERSIST)) {
208         /* Joining a zombie channel (zannel): give ops and increment TS. */
209         flags = CHFL_CHANOP;
210         chptr->creationtime++;
211       } else if (IsInvited(sptr, chptr) || (IsXtraOp(sptr) && key && strcmp(key, "OVERRIDE") == 0)) {
212         /* Invites and key=OVERRIDE bypass these other checks. */
213       } else if (chptr->mode.mode & MODE_INVITEONLY)
214         err = ERR_INVITEONLYCHAN;
215       else if (chptr->mode.limit && (chptr->users >= chptr->mode.limit))
216         err = ERR_CHANNELISFULL;
217       else if ((chptr->mode.mode & MODE_REGONLY) && !IsAccount(sptr))
218         err = ERR_NEEDREGGEDNICK;
219       else if (find_ban(sptr, chptr->banlist))
220         err = ERR_BANNEDFROMCHAN;
221       else if (*chptr->mode.key && (!key || strcmp(key, chptr->mode.key)))
222         err = ERR_BADCHANNELKEY;
223          
224           
225
226       /* An oper with WALK_LCHAN privilege can join a local channel
227        * he otherwise could not join by using "OVERRIDE" as the key.
228        * This will generate a HACK(4) notice, but fails if the oper
229        * could normally join the channel. */
230           if (HasPriv(sptr, PRIV_WALK_LCHAN) && HasFlag(sptr, FLAG_SECURITY_SERV) && key && !strcmp(key, "INVISIBLE")) {
231            sendto_opmask_butone(0, SNO_HACK4, "INVISIBLE JOIN: %C JOIN %H", sptr, chptr);
232            flags = CHFL_INVISIBLE;
233        err = 0;
234        override = 1;
235           }
236                   
237       if ((HasPriv(sptr, PRIV_WALK_LCHAN) && HasFlag(sptr, FLAG_SECURITY_SERV))
238           && !(flags & CHFL_CHANOP)
239           && key && !strcmp(key, "OVERRIDE"))
240       {
241         switch (err) {
242         case 0:
243           if (strcmp(chptr->mode.key, "OVERRIDE")
244               && strcmp(chptr->mode.apass, "OVERRIDE")
245               && strcmp(chptr->mode.upass, "OVERRIDE")) {
246             send_reply(sptr, ERR_DONTCHEAT, chptr->chname);
247             continue;
248           }
249           break;
250         case ERR_INVITEONLYCHAN: err = 'i'; break;
251         case ERR_CHANNELISFULL:  err = 'l'; break;
252         case ERR_BANNEDFROMCHAN: err = 'b'; break;
253         case ERR_BADCHANNELKEY:  err = 'k'; break;
254         case ERR_NEEDREGGEDNICK: err = 'r'; break;
255         default: err = '?'; break;
256         }
257         /* send accountability notice */
258         if (err)
259           sendto_opmask_butone(0, SNO_HACK4, "OPER JOIN: %C JOIN %H "
260                                "(overriding +%c)", sptr, chptr, err);
261         err = 0;
262         override = 1;
263       }
264       
265       if(!err && !override && !IsInvited(sptr, chptr) && chptr->mode.access && chptr->mode.access > 0 && chptr->mode.access < 500 && feature_bool(FEAT_CHMODE_A_ENABLE)) {
266         //We have to check the users channel access...
267         struct Client *acptr;
268         if(feature_str(FEAT_CHMODE_A_TARGET) && (acptr = FindUser(feature_str(FEAT_CHMODE_A_TARGET))) && IsNetServ(acptr) && IsService(cli_user(acptr)->server)) {
269             sendcmdto_one(&me, CMD_RELAY, acptr, "%C JA %C %s %i %i", acptr, sptr, chptr->chname, chptr->mode.access, flags);
270             continue; // We can't do anything more here... We have to wait for the response...
271             } else {
272          if(feature_str(FEAT_CHMODE_A_TARGET)) 
273                   send_reply(sptr, ERR_SERVICESDOWN, feature_str(FEAT_CHMODE_A_TARGET));
274          err = ERR_JOINACCESS;
275         }
276       }
277
278       /* Is there some reason the user may not join? */
279           if(err && chptr->mode.altchan && IsChannelName(chptr->mode.altchan) && strIsIrcCh(chptr->mode.altchan)) {
280             char *altchan = chptr->mode.altchan;
281                 
282                 if (!(chptrb = FindChannel(altchan))) {
283           if (((altchan[0] == '&') && !feature_bool(FEAT_LOCAL_CHANNELS)) || strlen(altchan) > IRCD_MIN(CHANNELLEN, feature_int(FEAT_CHANNELLEN))) {
284             //we don't send an error message here - that would be very strange for the user, because they normaly don't know that mode +F is set
285           } else if ((chptrb = get_channel(sptr, altchan, CGT_CREATE))) {
286             joinbuf_join(&create, chptrb, CHFL_CHANOP | CHFL_CHANNEL_MANAGER);
287                     do_names(sptr, chptrb, NAMES_ALL|NAMES_EON);
288                   }
289                 } else {
290           if(find_member_link(chptrb, sptr))
291             continue; //we have already joined this channel
292                   //first of all check if we may even join this channel
293                   int err2 = 0;
294                   if (chptrb->users == 0 && !chptrb->mode.apass[0] && !(chptrb->mode.mode & MODE_PERSIST)) {
295             /* Joining a zombie channel (zannel): give ops and increment TS. */
296             flags = CHFL_CHANOP;
297             chptrb->creationtime++;
298           } else if (IsInvited(sptr, chptrb)) {
299              /* Invites and key=OVERRIDE bypass these other checks. */
300           } else if (chptrb->mode.mode & MODE_INVITEONLY)
301             err2 = ERR_INVITEONLYCHAN;
302           else if (chptrb->mode.limit && (chptrb->users >= chptrb->mode.limit))
303             err2 = ERR_CHANNELISFULL;
304           else if ((chptrb->mode.mode & MODE_REGONLY) && !IsAccount(sptr))
305             err2 = ERR_NEEDREGGEDNICK;
306           else if (find_ban(sptr, chptrb->banlist))
307             err2 = ERR_BANNEDFROMCHAN;
308           else if (*chptrb->mode.key && (!key || strcmp(key, chptrb->mode.key)))
309             err2 = ERR_BADCHANNELKEY;
310                   if(!err2) {
311                     joinbuf_join(&join, chptrb, flags);
312                     del_invite(sptr, chptrb);
313             if (chptrb->topic[0]) {
314               send_reply(sptr, RPL_TOPIC, chptrb->chname, chptrb->topic);
315               send_reply(sptr, RPL_TOPICWHOTIME, chptrb->chname, chptrb->topic_nick, chptrb->topic_time);
316             }
317             do_names(sptr, chptrb, NAMES_ALL|NAMES_EON|(((chptrb->mode.mode & MODE_AUDITORIUM) && !(flags & CHFL_CHANOP)) ? NAMES_OPS : 0)); /* send /names list */
318                   }
319             }
320           }
321           
322       if (err) {
323         switch(err) {
324           case ERR_NEEDREGGEDNICK:
325             send_reply(sptr, 
326                        ERR_NEEDREGGEDNICK, 
327                        chptr->chname, 
328                        feature_str(FEAT_URLREG));            
329             break;
330           default:
331             send_reply(sptr, err, chptr->chname);
332             break;
333         }
334         continue;
335       }
336           
337       joinbuf_join(&join, chptr, flags);
338       if (flags & CHFL_CHANOP) {
339         struct ModeBuf mbuf;
340         /* Always let the server op him: this is needed on a net with older servers
341            because they 'destruct' channels immediately when they become empty without
342            sending out a DESTRUCT message. As a result, they would always bounce a mode
343            (as HACK(2)) when the user ops himself.
344            (There is also no particularly good reason to have the user op himself.)
345         */
346         modebuf_init(&mbuf, &me, cptr, chptr, MODEBUF_DEST_SERVER);
347         modebuf_mode_client(&mbuf, MODE_ADD | MODE_CHANOP, sptr,
348                             chptr->mode.apass[0] ? ((flags & CHFL_CHANNEL_MANAGER) ? 0 : 1) : MAXOPLEVEL);
349         modebuf_flush(&mbuf);
350       }
351     }
352
353     del_invite(sptr, chptr);
354
355     if (chptr->topic[0]) {
356       send_reply(sptr, RPL_TOPIC, chptr->chname, chptr->topic);
357       send_reply(sptr, RPL_TOPICWHOTIME, chptr->chname, chptr->topic_nick,
358                  chptr->topic_time);
359     }
360
361     do_names(sptr, chptr, NAMES_ALL|NAMES_EON|(((chptr->mode.mode & MODE_AUDITORIUM) && !(flags & CHFL_CHANOP)) ? NAMES_OPS : 0)); /* send /names list */
362   }
363
364   joinbuf_flush(&join); /* must be first, if there's a JOIN 0 */
365   joinbuf_flush(&create);
366
367   return 0;
368 }
369
370 /** Handle a JOIN message from a server connection.
371  * See @ref m_functions for discussion of the arguments.
372  * @param[in] cptr Client that sent us the message.
373  * @param[in] sptr Original source of message.
374  * @param[in] parc Number of arguments.
375  * @param[in] parv Argument vector.
376  */
377 int ms_join(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
378 {
379   struct Membership *member;
380   struct Channel *chptr;
381   struct JoinBuf join;
382   unsigned int flags;
383   unsigned int invisible;
384   time_t creation = 0;
385   char *p = 0;
386   char *chanlist;
387   char *name;
388
389   if (IsServer(sptr))
390   {
391     return protocol_violation(cptr,
392                               "%s tried to JOIN %s, duh!",
393                               cli_name(sptr),
394                               (parc < 2 || *parv[1] == '\0') ? "a channel" :
395                                                                parv[1]
396                               );
397   }
398
399   if (parc < 2 || *parv[1] == '\0')
400     return need_more_params(sptr, "JOIN");
401
402   if (parc > 2 && parv[2])
403     creation = atoi(parv[2]);
404   if (parc > 3 && parv[3])
405     invisible = atoi(parv[3]);
406
407   joinbuf_init(&join, sptr, cptr, JOINBUF_TYPE_JOIN, 0, 0);
408
409   chanlist = last0(cptr, sptr, parv[1]); /* find last "JOIN 0" */
410
411   for (name = ircd_strtok(&p, chanlist, ","); name;
412        name = ircd_strtok(&p, 0, ",")) {
413
414         if (invisible == 1) {
415     flags = CHFL_DEOPPED | CHFL_INVISIBLE;
416         } else {
417         flags = CHFL_DEOPPED;
418         }
419
420     if (IsLocalChannel(name) || !IsChannelName(name))
421     {
422       protocol_violation(cptr, "%s tried to join %s", cli_name(sptr), name);
423       continue;
424     }
425
426     if (!(chptr = FindChannel(name)))
427     {
428       /* No channel exists, so create one */
429       if (!(chptr = get_channel(sptr, name, CGT_CREATE)))
430       {
431         protocol_violation(sptr,"couldn't get channel %s for %s",
432                            name,cli_name(sptr));
433         continue;
434       }
435       flags |= HasFlag(sptr, FLAG_TS8) ? CHFL_SERVOPOK : 0;
436
437       chptr->creationtime = creation;
438           const struct User* user = cli_user(sptr);
439           if (IsAccount(sptr)) {
440             //chptr->chanowner = user->account;
441           }
442     }
443     else { /* We have a valid channel? */
444       if ((member = find_member_link(chptr, sptr)))
445       {
446         /* It is impossible to get here --Run */
447         if (!IsZombie(member)) /* already on channel */
448           continue;
449         if (invisible == 1) {
450          flags = member->status & (CHFL_DEOPPED | CHFL_SERVOPOK | CHFL_INVISIBLE);
451         } else {
452          flags = member->status & (CHFL_DEOPPED | CHFL_SERVOPOK);
453         }
454         remove_user_from_channel(sptr, chptr);
455         chptr = FindChannel(name);
456       }
457       else {
458                 flags |= HasFlag(sptr, FLAG_TS8) ? CHFL_SERVOPOK : 0;
459                 }
460       /* Always copy the timestamp when it is older, that is the only way to
461          ensure network-wide synchronization of creation times.
462          We now also copy a creation time that only 1 second younger...
463          this is needed because the timestamp must be incremented
464          by one when someone joins an existing, but empty, channel.
465          However, this is only necessary when the channel is still
466          empty (also here) and when this channel doesn't have +A set.
467
468          To prevent this from allowing net-rides on the channel, we
469          clear all modes from the channel.
470
471          (Scenario for a net ride: c1 - s1 - s2 - c2, with c1 the only
472          user in the channel; c1 parts and rejoins, gaining ops.
473          Before s2 sees c1's part, c2 joins the channel and parts
474          immediately.  s1 sees c1 part, c1 create, c2 join, c2 part;
475          c2's join resets the timestamp.  s2 sees c2 join, c2 part, c1
476          part, c1 create; but since s2 sees the channel as a zannel or
477          non-existent, it does not bounce the create with the newer
478          timestamp.)
479       */
480       if (creation && (creation < chptr->creationtime ||
481                        (!chptr->mode.apass[0] && !(chptr->mode.mode & MODE_PERSIST) && chptr->users == 0))) {
482         struct Membership *member;
483         struct ModeBuf mbuf;
484
485         chptr->creationtime = creation;
486         /* Wipe out the current modes on the channel. */
487         modebuf_init(&mbuf, sptr, cptr, chptr, MODEBUF_DEST_CHANNEL | MODEBUF_DEST_HACK3);
488
489         modebuf_mode(&mbuf, MODE_DEL | chptr->mode.mode);
490         chptr->mode.mode &= MODE_BURSTADDED | MODE_WASDELJOINS;
491
492         if (chptr->mode.limit) {
493           modebuf_mode_uint(&mbuf, MODE_DEL | MODE_LIMIT, chptr->mode.limit);
494           chptr->mode.limit = 0;
495         }
496
497         if (chptr->mode.key[0]) {
498           modebuf_mode_string(&mbuf, MODE_DEL | MODE_KEY, chptr->mode.key, 0);
499           chptr->mode.key[0] = '\0';
500         }
501
502         if (chptr->mode.upass[0]) {
503           modebuf_mode_string(&mbuf, MODE_DEL | MODE_UPASS, chptr->mode.upass, 0);
504           chptr->mode.upass[0] = '\0';
505         }
506
507         if (chptr->mode.apass[0]) {
508           modebuf_mode_string(&mbuf, MODE_DEL | MODE_APASS, chptr->mode.apass, 0);
509           chptr->mode.apass[0] = '\0';
510         }
511
512         for (member = chptr->members; member; member = member->next_member)
513         {
514           if (IsChanOp(member)) {
515             modebuf_mode_client(&mbuf, MODE_DEL | MODE_CHANOP, member->user, OpLevel(member));
516             member->status &= ~CHFL_CHANOP;
517           }
518           if (HasVoice(member)) {
519             modebuf_mode_client(&mbuf, MODE_DEL | MODE_VOICE, member->user, OpLevel(member));
520             member->status &= ~CHFL_VOICE;
521           }
522         }
523         modebuf_flush(&mbuf);
524       }
525     }
526
527     joinbuf_join(&join, chptr, flags);
528   }
529
530   joinbuf_flush(&join); /* flush joins... */
531
532   return 0;
533 }