]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_jumpserver.cpp
Use consistent numerics when a mode already exists or doesn't exist.
[user/henk/code/inspircd.git] / src / modules / m_jumpserver.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2007-2008 Craig Edwards <craigedwards@brainbox.cc>
5  *   Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
6  *   Copyright (C) 2007 Robin Burchell <robin+git@viroteck.net>
7  *
8  * This file is part of InspIRCd.  InspIRCd is free software: you can
9  * redistribute it and/or modify it under the terms of the GNU General Public
10  * License as published by the Free Software Foundation, version 2.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
15  * details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21
22 #include "inspircd.h"
23 #include "modules/ssl.h"
24
25 enum
26 {
27         // From ircd-ratbox.
28         RPL_REDIR = 10
29 };
30
31 /** Handle /JUMPSERVER
32  */
33 class CommandJumpserver : public Command
34 {
35  public:
36         bool redirect_new_users;
37         std::string redirect_to;
38         std::string reason;
39         int port;
40         int sslport;
41         UserCertificateAPI sslapi;
42
43         CommandJumpserver(Module* Creator)
44                 : Command(Creator, "JUMPSERVER", 0, 4)
45                 , sslapi(Creator)
46         {
47                 flags_needed = 'o';
48                 syntax = "[<server> <port>[:<sslport>] <+/-an> <reason>]";
49                 port = 0;
50                 sslport = 0;
51                 redirect_new_users = false;
52         }
53
54         CmdResult Handle(User* user, const Params& parameters) CXX11_OVERRIDE
55         {
56                 int n_done = 0;
57                 reason = (parameters.size() < 4) ? "Please use this server/port instead" : parameters[3];
58                 bool redirect_all_immediately = false;
59                 redirect_new_users = true;
60                 bool direction = true;
61                 std::string n_done_s;
62
63                 /* No parameters: jumpserver disabled */
64                 if (parameters.empty())
65                 {
66                         if (port)
67                                 user->WriteNotice("*** Disabled jumpserver (previously set to '" + redirect_to + ":" + ConvToStr(port) + "')");
68                         else
69                                 user->WriteNotice("*** Jumpserver was not enabled.");
70
71                         port = 0;
72                         sslport = 0;
73                         redirect_to.clear();
74                         return CMD_SUCCESS;
75                 }
76
77                 port = 0;
78                 redirect_to.clear();
79
80                 if (parameters.size() >= 3)
81                 {
82                         for (std::string::const_iterator n = parameters[2].begin(); n != parameters[2].end(); ++n)
83                         {
84                                 switch (*n)
85                                 {
86                                         case '+':
87                                                 direction = true;
88                                         break;
89                                         case '-':
90                                                 direction = false;
91                                         break;
92                                         case 'a':
93                                                 redirect_all_immediately = direction;
94                                         break;
95                                         case 'n':
96                                                 redirect_new_users = direction;
97                                         break;
98                                         default:
99                                                 user->WriteNotice("*** Invalid JUMPSERVER flag: " + ConvToStr(*n));
100                                                 return CMD_FAILURE;
101                                         break;
102                                 }
103                         }
104
105                         size_t delimpos = parameters[1].find(':');
106                         port = ConvToInt(parameters[1].substr(0, delimpos ? delimpos : std::string::npos));
107                         sslport = (delimpos == std::string::npos ? 0 : ConvToInt(parameters[1].substr(delimpos + 1)));
108
109                         if (parameters[1].find_first_not_of("0123456789:") != std::string::npos
110                                 || parameters[1].rfind(':') != delimpos
111                                 || port > 65535 || sslport > 65535)
112                         {
113                                 user->WriteNotice("*** Invalid port number");
114                                 return CMD_FAILURE;
115                         }
116
117                         if (redirect_all_immediately)
118                         {
119                                 /* Redirect everyone but the oper sending the command */
120                                 const UserManager::LocalList& list = ServerInstance->Users.GetLocalUsers();
121                                 for (UserManager::LocalList::const_iterator i = list.begin(); i != list.end(); )
122                                 {
123                                         // Quitting the user removes it from the list
124                                         LocalUser* t = *i;
125                                         ++i;
126                                         if (!t->IsOper())
127                                         {
128                                                 t->WriteNumeric(RPL_REDIR, parameters[0], GetPort(t), "Please use this Server/Port instead");
129                                                 ServerInstance->Users->QuitUser(t, reason);
130                                                 n_done++;
131                                         }
132                                 }
133                                 if (n_done)
134                                 {
135                                         n_done_s = ConvToStr(n_done);
136                                 }
137                         }
138
139                         if (redirect_new_users)
140                                 redirect_to = parameters[0];
141
142                         user->WriteNotice("*** Set jumpserver to server '" + parameters[0] + "' port '" + (port ? ConvToStr(port) : "Auto") + ", SSL " + (sslport ? ConvToStr(sslport) : "Auto") + "', flags '+" +
143                                 (redirect_all_immediately ? "a" : "") + (redirect_new_users ? "n'" : "'") +
144                                 (n_done ? " (" + n_done_s + "user(s) redirected): " : ": ") + reason);
145                 }
146
147                 return CMD_SUCCESS;
148         }
149
150         int GetPort(LocalUser* user)
151         {
152                 int p = (sslapi && sslapi->GetCertificate(user) ? sslport : port);
153                 if (p == 0)
154                         p = user->GetServerPort();
155                 return p;
156         }
157 };
158
159 class ModuleJumpServer : public Module
160 {
161         CommandJumpserver js;
162  public:
163         ModuleJumpServer() : js(this)
164         {
165         }
166
167         void OnModuleRehash(User* user, const std::string& param) CXX11_OVERRIDE
168         {
169                 if (irc::equals(param, "jumpserver") && js.redirect_new_users)
170                         js.redirect_new_users = false;
171         }
172
173         ModResult OnUserRegister(LocalUser* user) CXX11_OVERRIDE
174         {
175                 if (js.redirect_new_users)
176                 {
177                         int port = js.GetPort(user);
178                         user->WriteNumeric(RPL_REDIR, js.redirect_to, port, "Please use this Server/Port instead");
179                         ServerInstance->Users->QuitUser(user, js.reason);
180                         return MOD_RES_DENY;
181                 }
182                 return MOD_RES_PASSTHRU;
183         }
184
185         void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
186         {
187                 // Emergency way to unlock
188                 if (!status.srcuser)
189                         js.redirect_new_users = false;
190         }
191
192         Version GetVersion() CXX11_OVERRIDE
193         {
194                 return Version("Provides support for the RPL_REDIR numeric and the /JUMPSERVER command.", VF_VENDOR);
195         }
196 };
197
198 MODULE_INIT(ModuleJumpServer)