]> arthur.barton.de Git - ngircd.git/blobdiff - src/ngircd/irc-mode.c
Channel modes +k & +l: Always report an error when a parameter is missing
[ngircd.git] / src / ngircd / irc-mode.c
index 99255df14a5433f60b3ad56e35f7e8f802175916..4a26ef02f6cd32c9abd93a10d66864466e66d5c5 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001-2014 Alexander Barton (alex@barton.de) and Contributors.
+ * Copyright (c)2001-2023 Alexander Barton (alex@barton.de) and Contributors.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -281,7 +281,7 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target )
                        break;
                default:
                        if (Client_Type(Client) != CLIENT_SERVER) {
-                               Log(LOG_DEBUG,
+                               LogDebug(
                                    "Unknown mode \"%c%c\" from \"%s\"!?",
                                    set ? '+' : '-', *mode_ptr,
                                    Client_ID(Origin));
@@ -292,7 +292,7 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target )
                                                        *mode_ptr);
                                x[0] = '\0';
                        } else {
-                               Log(LOG_DEBUG,
+                               LogDebug(
                                    "Handling unknown mode \"%c%c\" from \"%s\" for \"%s\" ...",
                                    set ? '+' : '-', *mode_ptr,
                                    Client_ID(Origin), Client_ID(Target));
@@ -609,33 +609,31 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
                                                Channel_Name(Channel));
                                break;
                        }
-                       if (arg_arg > mode_arg) {
-                               if (is_oper || is_machine || is_owner ||
-                                   is_admin || is_op || is_halfop) {
-                                       Channel_ModeDel(Channel, 'k');
-                                       Channel_SetKey(Channel,
-                                                      Req->argv[arg_arg]);
-                                       strlcpy(argadd, Channel_Key(Channel),
-                                               sizeof(argadd));
-                                       x[0] = *mode_ptr;
-                               } else {
+                       if (arg_arg <= mode_arg) {
+                               if (is_machine)
+                                       Log(LOG_ERR,
+                                           "Got MODE +k without key for \"%s\" from \"%s\"! Ignored.",
+                                           Channel_Name(Channel), Client_ID(Origin));
+                               else
                                        connected = IRC_WriteErrClient(Origin,
-                                               ERR_CHANOPRIVSNEEDED_MSG,
-                                               Client_ID(Origin),
-                                               Channel_Name(Channel));
-                               }
-                               Req->argv[arg_arg][0] = '\0';
-                               arg_arg++;
+                                               ERR_NEEDMOREPARAMS_MSG,
+                                               Client_ID(Origin), Req->command);
+                               goto chan_exit;
+                       }
+                       if (is_oper || is_machine || is_owner ||
+                           is_admin || is_op || is_halfop) {
+                               Channel_ModeDel(Channel, 'k');
+                               Channel_SetKey(Channel, Req->argv[arg_arg]);
+                               strlcpy(argadd, Channel_Key(Channel), sizeof(argadd));
+                               x[0] = *mode_ptr;
                        } else {
-#ifdef STRICT_RFC
-                               /* Only send error message in "strict" mode,
-                                * this is how ircd2.11 and others behave ... */
                                connected = IRC_WriteErrClient(Origin,
-                                       ERR_NEEDMOREPARAMS_MSG,
-                                       Client_ID(Origin), Req->command);
-#endif
-                               goto chan_exit;
+                                       ERR_CHANOPRIVSNEEDED_MSG,
+                                       Client_ID(Origin),
+                                       Channel_Name(Channel));
                        }
+                       Req->argv[arg_arg][0] = '\0';
+                       arg_arg++;
                        break;
                case 'l': /* Member limit */
                        if (Mode_Limit_Reached(Client, mode_arg_count++))
@@ -651,35 +649,34 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
                                                Channel_Name(Channel));
                                break;
                        }
-                       if (arg_arg > mode_arg) {
-                               if (is_oper || is_machine || is_owner ||
-                                   is_admin || is_op || is_halfop) {
-                                       l = atol(Req->argv[arg_arg]);
-                                       if (l > 0 && l < 0xFFFF) {
-                                               Channel_ModeDel(Channel, 'l');
-                                               Channel_SetMaxUsers(Channel, l);
-                                               snprintf(argadd, sizeof(argadd),
-                                                        "%ld", l);
-                                               x[0] = *mode_ptr;
-                                       }
-                               } else {
+                       if (arg_arg <= mode_arg) {
+                               if (is_machine)
+                                       Log(LOG_ERR,
+                                           "Got MODE +l without limit for \"%s\" from \"%s\"! Ignored.",
+                                           Channel_Name(Channel), Client_ID(Origin));
+                               else
                                        connected = IRC_WriteErrClient(Origin,
-                                               ERR_CHANOPRIVSNEEDED_MSG,
-                                               Client_ID(Origin),
-                                               Channel_Name(Channel));
+                                               ERR_NEEDMOREPARAMS_MSG,
+                                               Client_ID(Origin), Req->command);
+                               goto chan_exit;
+                       }
+                       if (is_oper || is_machine || is_owner ||
+                           is_admin || is_op || is_halfop) {
+                               l = atol(Req->argv[arg_arg]);
+                               if (l > 0 && l < 0xFFFF) {
+                                       Channel_ModeDel(Channel, 'l');
+                                       Channel_SetMaxUsers(Channel, l);
+                                       snprintf(argadd, sizeof(argadd), "%ld", l);
+                                       x[0] = *mode_ptr;
                                }
-                               Req->argv[arg_arg][0] = '\0';
-                               arg_arg++;
                        } else {
-#ifdef STRICT_RFC
-                               /* Only send error message in "strict" mode,
-                                * this is how ircd2.11 and others behave ... */
                                connected = IRC_WriteErrClient(Origin,
-                                       ERR_NEEDMOREPARAMS_MSG,
-                                       Client_ID(Origin), Req->command);
-#endif
-                               goto chan_exit;
+                                       ERR_CHANOPRIVSNEEDED_MSG,
+                                       Client_ID(Origin),
+                                       Channel_Name(Channel));
                        }
+                       Req->argv[arg_arg][0] = '\0';
+                       arg_arg++;
                        break;
                case 'O': /* IRC operators only */
                        if (set) {
@@ -823,7 +820,7 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
                        break;
                default:
                        if (Client_Type(Client) != CLIENT_SERVER) {
-                               Log(LOG_DEBUG,
+                               LogDebug(
                                    "Unknown mode \"%c%c\" from \"%s\" on %s!?",
                                    set ? '+' : '-', *mode_ptr,
                                    Client_ID(Origin), Channel_Name(Channel));
@@ -833,7 +830,7 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
                                        Channel_Name(Channel));
                                x[0] = '\0';
                        } else {
-                               Log(LOG_DEBUG,
+                               LogDebug(
                                    "Handling unknown mode \"%c%c\" from \"%s\" on %s ...",
                                    set ? '+' : '-', *mode_ptr,
                                    Client_ID(Origin), Channel_Name(Channel));
@@ -904,7 +901,7 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
                if (Client_Type(Client) == CLIENT_SERVER) {
                        /* MODE requests for local channels from other servers
                         * are definitely invalid! */
-                       if (Channel_IsLocal(Channel)) {
+                       if (Channel_IsLocal(Channel) && Client != Client_ThisServer()) {
                                Log(LOG_ALERT, "Got remote MODE command for local channel!? Ignored.");
                                return CONNECTED;
                        }