]> arthur.barton.de Git - ngircd.git/blobdiff - src/ngircd/channel.c
KICK: Fix denial of service bug
[ngircd.git] / src / ngircd / channel.c
index 59fe00229576d018900a600c548925fd4d9668cb..45bf615c29d604b453807e2a1e6c2b07c8c3f02c 100644 (file)
@@ -131,11 +131,11 @@ Channel_InitPredefined( void )
 
                new_chan = Channel_Create(conf_chan->name);
                if (!new_chan) {
-                       Log(LOG_ERR, "Can't create pre-defined channel \"%s\"",
+                       Log(LOG_ERR, "Can't create pre-defined channel \"%s\"!",
                                                        conf_chan->name);
                        continue;
                }
-               Log(LOG_INFO, "Created pre-defined channel \"%s\"",
+               Log(LOG_INFO, "Created pre-defined channel \"%s\".",
                                                conf_chan->name);
 
                Channel_ModeAdd(new_chan, 'P');
@@ -326,7 +326,26 @@ Channel_Kick(CLIENT *Peer, CLIENT *Target, CLIENT *Origin, const char *Name,
                }
        }
 
+       /* Check that the client to be kicked is on the specified channel */
+       if (!Channel_IsMemberOf(chan, Target)) {
+               IRC_WriteStrClient(Origin, ERR_USERNOTINCHANNEL_MSG,
+                                  Client_ID(Origin), Client_ID(Target), Name );
+               return;
+       }
+
        if(Client_Type(Peer) == CLIENT_USER) {
+               /* Channel mode 'Q' and user mode 'q' on target: nobody but
+                * IRC Operators and servers can kick the target user */
+               if ((strchr(Channel_Modes(chan), 'Q')
+                    || Client_HasMode(Target, 'q')
+                    || Client_Type(Target) == CLIENT_SERVICE)
+                   && !Client_HasMode(Origin, 'o')) {
+                       IRC_WriteStrClient(Origin, ERR_KICKDENY_MSG,
+                                          Client_ID(Origin), Name,
+                                          Client_ID(Target));
+                       return;
+               }
+
                /* Check if client has the rights to kick target */
                ptr = Channel_UserModes(chan, Peer);
                target_modes = Channel_UserModes(chan, Target);
@@ -364,19 +383,12 @@ Channel_Kick(CLIENT *Peer, CLIENT *Target, CLIENT *Origin, const char *Name,
                }
 
                if(!can_kick) {
-                       IRC_WriteStrClient(Origin, ERR_CHANOPPRIVTOLOW_MSG,
+                       IRC_WriteStrClient(Origin, ERR_CHANOPPRIVTOOLOW_MSG,
                                Client_ID(Origin), Name);
                        return;
                }
        }
 
-       /* Check that the client to be kicked is on the specified channel */
-       if (!Channel_IsMemberOf(chan, Target)) {
-               IRC_WriteStrClient(Origin, ERR_USERNOTINCHANNEL_MSG,
-                                  Client_ID(Origin), Client_ID(Target), Name );
-               return;
-       }
-
        /* Kick Client from channel */
        Remove_Client( REMOVE_KICK, chan, Target, Origin, Reason, true);
 } /* Channel_Kick */
@@ -906,7 +918,11 @@ Channel_Write(CHANNEL *Chan, CLIENT *From, CLIENT *Client, const char *Command,
        if (!Can_Send_To_Channel(Chan, From)) {
                if (! SendErrors)
                        return CONNECTED;       /* no error, see RFC 2812 */
-               return IRC_WriteStrClient(From, ERR_CANNOTSENDTOCHAN_MSG,
+               if (strchr(Channel_Modes(Chan), 'M'))
+                       return IRC_WriteStrClient(From, ERR_NEEDREGGEDNICK_MSG,
+                                                 Client_ID(From), Channel_Name(Chan));
+               else
+                       return IRC_WriteStrClient(From, ERR_CANNOTSENDTOCHAN_MSG,
                                          Client_ID(From), Channel_Name(Chan));
        }