fixed ssl.c bug when ssl backend returns IO_BLOCKED but IO engine doesn't get informe...
[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 ((chptr->mode.mode & MODE_SSLCHAN) && !IsSSL(sptr))
220         err = ERR_SSLCHANNEL;
221       else if (find_ban(sptr, chptr->banlist))
222         err = ERR_BANNEDFROMCHAN;
223       else if (*chptr->mode.key && (!key || strcmp(key, chptr->mode.key)))
224         err = ERR_BADCHANNELKEY;
225          
226           
227
228       /* An oper with WALK_LCHAN privilege can join a local channel
229        * he otherwise could not join by using "OVERRIDE" as the key.
230        * This will generate a HACK(4) notice, but fails if the oper
231        * could normally join the channel. */
232           if (HasPriv(sptr, PRIV_WALK_LCHAN) && HasFlag(sptr, FLAG_SECURITY_SERV) && key && !strcmp(key, "INVISIBLE")) {
233            sendto_opmask_butone(0, SNO_HACK4, "INVISIBLE JOIN: %C JOIN %H", sptr, chptr);
234            flags = CHFL_INVISIBLE;
235        err = 0;
236        override = 1;
237           }
238                   
239       if ((HasPriv(sptr, PRIV_WALK_LCHAN) && HasFlag(sptr, FLAG_SECURITY_SERV))
240           && !(flags & CHFL_CHANOP)
241           && key && !strcmp(key, "OVERRIDE"))
242       {
243         switch (err) {
244         case 0:
245           if (strcmp(chptr->mode.key, "OVERRIDE")
246               && strcmp(chptr->mode.apass, "OVERRIDE")
247               && strcmp(chptr->mode.upass, "OVERRIDE")) {
248             send_reply(sptr, ERR_DONTCHEAT, chptr->chname);
249             continue;
250           }
251           break;
252         case ERR_INVITEONLYCHAN: err = 'i'; break;
253         case ERR_CHANNELISFULL:  err = 'l'; break;
254         case ERR_BANNEDFROMCHAN: err = 'b'; break;
255         case ERR_BADCHANNELKEY:  err = 'k'; break;
256         case ERR_NEEDREGGEDNICK: err = 'r'; break;
257         case ERR_SSLCHANNEL:     err = 'S'; break;
258         default: err = '?'; break;
259         }
260         /* send accountability notice */
261         if (err)
262           sendto_opmask_butone(0, SNO_HACK4, "OPER JOIN: %C JOIN %H "
263                                "(overriding +%c)", sptr, chptr, err);
264         err = 0;
265         override = 1;
266       }
267       
268       if(!err && !override && !IsInvited(sptr, chptr) && chptr->mode.access && chptr->mode.access > 0 && chptr->mode.access <= 500 && feature_bool(FEAT_CHMODE_A_ENABLE)) {
269         //We have to check the users channel access...
270         struct Client *acptr;
271         if(feature_str(FEAT_CHMODE_A_TARGET) && (acptr = FindUser(feature_str(FEAT_CHMODE_A_TARGET))) && IsNetServ(acptr) && IsService(cli_user(acptr)->server)) {
272             sendcmdto_one(&me, CMD_RELAY, acptr, "%C JA %C %s %i %i", acptr, sptr, chptr->chname, chptr->mode.access, flags);
273             continue; // We can't do anything more here... We have to wait for the response...
274             } else {
275          if(feature_str(FEAT_CHMODE_A_TARGET)) 
276                   send_reply(sptr, ERR_SERVICESDOWN, feature_str(FEAT_CHMODE_A_TARGET));
277          err = ERR_JOINACCESS;
278         }
279       }
280
281       /* Is there some reason the user may not join? */
282           if(err && chptr->mode.altchan && IsChannelName(chptr->mode.altchan) && strIsIrcCh(chptr->mode.altchan)) {
283             char *altchan = chptr->mode.altchan;
284                 
285                 if (!(chptrb = FindChannel(altchan))) {
286           if (((altchan[0] == '&') && !feature_bool(FEAT_LOCAL_CHANNELS)) || strlen(altchan) > IRCD_MIN(CHANNELLEN, feature_int(FEAT_CHANNELLEN))) {
287             //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
288           } else if ((chptrb = get_channel(sptr, altchan, CGT_CREATE))) {
289             joinbuf_join(&create, chptrb, CHFL_CHANOP | CHFL_CHANNEL_MANAGER);
290                     do_names(sptr, chptrb, NAMES_ALL|NAMES_EON);
291                   }
292                 } else {
293           if(find_member_link(chptrb, sptr))
294             continue; //we have already joined this channel
295                   //first of all check if we may even join this channel
296                   int err2 = 0;
297                   if (chptrb->users == 0 && !chptrb->mode.apass[0] && !(chptrb->mode.mode & MODE_PERSIST)) {
298             /* Joining a zombie channel (zannel): give ops and increment TS. */
299             flags = CHFL_CHANOP;
300             chptrb->creationtime++;
301           } else if (IsInvited(sptr, chptrb)) {
302              /* Invites and key=OVERRIDE bypass these other checks. */
303           } else if (chptrb->mode.mode & MODE_INVITEONLY)
304             err2 = ERR_INVITEONLYCHAN;
305           else if (chptrb->mode.limit && (chptrb->users >= chptrb->mode.limit))
306             err2 = ERR_CHANNELISFULL;
307           else if ((chptrb->mode.mode & MODE_REGONLY) && !IsAccount(sptr))
308             err2 = ERR_NEEDREGGEDNICK;
309           else if ((chptrb->mode.mode & MODE_SSLCHAN) && !IsSSL(sptr))
310             err2 = ERR_SSLCHANNEL;
311           else if (find_ban(sptr, chptrb->banlist))
312             err2 = ERR_BANNEDFROMCHAN;
313           else if (*chptrb->mode.key && (!key || strcmp(key, chptrb->mode.key)))
314             err2 = ERR_BADCHANNELKEY;
315                   if(!err2) {
316                     joinbuf_join(&join, chptrb, flags);
317                     del_invite(sptr, chptrb);
318             if (chptrb->topic[0]) {
319               send_reply(sptr, RPL_TOPIC, chptrb->chname, chptrb->topic);
320               send_reply(sptr, RPL_TOPICWHOTIME, chptrb->chname, chptrb->topic_nick, chptrb->topic_time);
321             }
322             do_names(sptr, chptrb, NAMES_ALL|NAMES_EON|(((chptrb->mode.mode & MODE_AUDITORIUM) && !(flags & CHFL_CHANOP)) ? NAMES_OPS : 0)); /* send /names list */
323                   }
324             }
325           }
326           
327       if (err) {
328         const char *error = NULL;
329         if (err == ERR_CHANNELISFULL)
330             error = feature_str(FEAT_ERR_CHANNELISFULL);
331         else if (err == ERR_INVITEONLYCHAN)
332             error = feature_str(FEAT_ERR_INVITEONLYCHAN);
333         else if (err == ERR_BANNEDFROMCHAN)
334             error = feature_str(FEAT_ERR_BANNEDFROMCHAN);
335         else if (err == ERR_BADCHANNELKEY)
336             error = feature_str(FEAT_ERR_BADCHANNELKEY);
337         else if (err == ERR_NEEDREGGEDNICK)
338             error = feature_str(FEAT_ERR_NEEDREGGEDNICK);
339         else if (err == ERR_SSLCHANNEL)
340             error = feature_str(FEAT_ERR_SSLCHANNEL);
341         else if (err == ERR_JOINACCESS)
342             error = feature_str(FEAT_ERR_JOINACCESS);
343         
344         if (error)
345             send_reply(sptr, err, chptr->chname, error);
346         else
347             send_reply(sptr, err, chptr->chname);
348         continue;
349       }
350           
351       joinbuf_join(&join, chptr, flags);
352       if (flags & CHFL_CHANOP) {
353         struct ModeBuf mbuf;
354         /* Always let the server op him: this is needed on a net with older servers
355            because they 'destruct' channels immediately when they become empty without
356            sending out a DESTRUCT message. As a result, they would always bounce a mode
357            (as HACK(2)) when the user ops himself.
358            (There is also no particularly good reason to have the user op himself.)
359         */
360         modebuf_init(&mbuf, &me, cptr, chptr, MODEBUF_DEST_SERVER);
361         modebuf_mode_client(&mbuf, MODE_ADD | MODE_CHANOP, sptr,
362                             chptr->mode.apass[0] ? ((flags & CHFL_CHANNEL_MANAGER) ? 0 : 1) : MAXOPLEVEL);
363         modebuf_flush(&mbuf);
364       }
365     }
366
367     del_invite(sptr, chptr);
368
369     if (chptr->topic[0]) {
370       send_reply(sptr, RPL_TOPIC, chptr->chname, chptr->topic);
371       send_reply(sptr, RPL_TOPICWHOTIME, chptr->chname, chptr->topic_nick,
372                  chptr->topic_time);
373     }
374
375     do_names(sptr, chptr, NAMES_ALL|NAMES_EON|(((chptr->mode.mode & MODE_AUDITORIUM) && !(flags & CHFL_CHANOP)) ? NAMES_OPS : 0)); /* send /names list */
376   }
377
378   joinbuf_flush(&join); /* must be first, if there's a JOIN 0 */
379   joinbuf_flush(&create);
380
381   return 0;
382 }
383
384 /** Handle a JOIN message from a server connection.
385  * See @ref m_functions for discussion of the arguments.
386  * @param[in] cptr Client that sent us the message.
387  * @param[in] sptr Original source of message.
388  * @param[in] parc Number of arguments.
389  * @param[in] parv Argument vector.
390  */
391 int ms_join(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
392 {
393   struct Membership *member;
394   struct Channel *chptr;
395   struct JoinBuf join;
396   unsigned int flags;
397   unsigned int invisible;
398   time_t creation = 0;
399   char *p = 0;
400   char *chanlist;
401   char *name;
402
403   if (IsServer(sptr))
404   {
405     return protocol_violation(cptr,
406                               "%s tried to JOIN %s, duh!",
407                               cli_name(sptr),
408                               (parc < 2 || *parv[1] == '\0') ? "a channel" :
409                                                                parv[1]
410                               );
411   }
412
413   if (parc < 2 || *parv[1] == '\0')
414     return need_more_params(sptr, "JOIN");
415
416   if (parc > 2 && parv[2])
417     creation = atoi(parv[2]);
418   if (parc > 3 && parv[3])
419     invisible = atoi(parv[3]);
420
421   joinbuf_init(&join, sptr, cptr, JOINBUF_TYPE_JOIN, 0, 0);
422
423   chanlist = last0(cptr, sptr, parv[1]); /* find last "JOIN 0" */
424
425   for (name = ircd_strtok(&p, chanlist, ","); name;
426        name = ircd_strtok(&p, 0, ",")) {
427
428         if (invisible == 1) {
429     flags = CHFL_DEOPPED | CHFL_INVISIBLE;
430         } else {
431         flags = CHFL_DEOPPED;
432         }
433
434     if (IsLocalChannel(name) || !IsChannelName(name))
435     {
436       protocol_violation(cptr, "%s tried to join %s", cli_name(sptr), name);
437       continue;
438     }
439
440     if (!(chptr = FindChannel(name)))
441     {
442       /* No channel exists, so create one */
443       if (!(chptr = get_channel(sptr, name, CGT_CREATE)))
444       {
445         protocol_violation(sptr,"couldn't get channel %s for %s",
446                            name,cli_name(sptr));
447         continue;
448       }
449       flags |= HasFlag(sptr, FLAG_TS8) ? CHFL_SERVOPOK : 0;
450
451       chptr->creationtime = creation;
452           const struct User* user = cli_user(sptr);
453           if (IsAccount(sptr)) {
454             //chptr->chanowner = user->account;
455           }
456     }
457     else { /* We have a valid channel? */
458       if ((member = find_member_link(chptr, sptr)))
459       {
460         /* It is impossible to get here --Run */
461         if (!IsZombie(member)) /* already on channel */
462           continue;
463         if (invisible == 1) {
464          flags = member->status & (CHFL_DEOPPED | CHFL_SERVOPOK | CHFL_INVISIBLE);
465         } else {
466          flags = member->status & (CHFL_DEOPPED | CHFL_SERVOPOK);
467         }
468         remove_user_from_channel(sptr, chptr);
469         chptr = FindChannel(name);
470       }
471       else {
472                 flags |= HasFlag(sptr, FLAG_TS8) ? CHFL_SERVOPOK : 0;
473                 }
474       /* Always copy the timestamp when it is older, that is the only way to
475          ensure network-wide synchronization of creation times.
476          We now also copy a creation time that only 1 second younger...
477          this is needed because the timestamp must be incremented
478          by one when someone joins an existing, but empty, channel.
479          However, this is only necessary when the channel is still
480          empty (also here) and when this channel doesn't have +A set.
481
482          To prevent this from allowing net-rides on the channel, we
483          clear all modes from the channel.
484
485          (Scenario for a net ride: c1 - s1 - s2 - c2, with c1 the only
486          user in the channel; c1 parts and rejoins, gaining ops.
487          Before s2 sees c1's part, c2 joins the channel and parts
488          immediately.  s1 sees c1 part, c1 create, c2 join, c2 part;
489          c2's join resets the timestamp.  s2 sees c2 join, c2 part, c1
490          part, c1 create; but since s2 sees the channel as a zannel or
491          non-existent, it does not bounce the create with the newer
492          timestamp.)
493       */
494       if (creation && (creation < chptr->creationtime ||
495                        (!chptr->mode.apass[0] && !(chptr->mode.mode & MODE_PERSIST) && chptr->users == 0))) {
496         struct Membership *member;
497         struct ModeBuf mbuf;
498
499         chptr->creationtime = creation;
500         /* Wipe out the current modes on the channel. */
501         modebuf_init(&mbuf, sptr, cptr, chptr, MODEBUF_DEST_CHANNEL | MODEBUF_DEST_HACK3);
502
503         modebuf_mode(&mbuf, MODE_DEL | chptr->mode.mode);
504         chptr->mode.mode &= MODE_BURSTADDED | MODE_WASDELJOINS;
505
506         if (chptr->mode.limit) {
507           modebuf_mode_uint(&mbuf, MODE_DEL | MODE_LIMIT, chptr->mode.limit);
508           chptr->mode.limit = 0;
509         }
510
511         if (chptr->mode.key[0]) {
512           modebuf_mode_string(&mbuf, MODE_DEL | MODE_KEY, chptr->mode.key, 0);
513           chptr->mode.key[0] = '\0';
514         }
515
516         if (chptr->mode.upass[0]) {
517           modebuf_mode_string(&mbuf, MODE_DEL | MODE_UPASS, chptr->mode.upass, 0);
518           chptr->mode.upass[0] = '\0';
519         }
520
521         if (chptr->mode.apass[0]) {
522           modebuf_mode_string(&mbuf, MODE_DEL | MODE_APASS, chptr->mode.apass, 0);
523           chptr->mode.apass[0] = '\0';
524         }
525
526         for (member = chptr->members; member; member = member->next_member)
527         {
528           if (IsChanOp(member)) {
529             modebuf_mode_client(&mbuf, MODE_DEL | MODE_CHANOP, member->user, OpLevel(member));
530             member->status &= ~CHFL_CHANOP;
531           }
532           if (HasVoice(member)) {
533             modebuf_mode_client(&mbuf, MODE_DEL | MODE_VOICE, member->user, OpLevel(member));
534             member->status &= ~CHFL_VOICE;
535           }
536         }
537         modebuf_flush(&mbuf);
538       }
539     }
540
541     joinbuf_join(&join, chptr, flags);
542   }
543
544   joinbuf_flush(&join); /* flush joins... */
545
546   return 0;
547 }