]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_customtitle.cpp
Sync helpop chmodes s and p with docs
[user/henk/code/inspircd.git] / src / modules / m_customtitle.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2018 linuxdaemon <linuxdaemon.irc@gmail.com>
5  *   Copyright (C) 2013, 2017-2018, 2020 Sadie Powell <sadie@witchery.services>
6  *   Copyright (C) 2012, 2019 Robby <robby@chatbelgie.be>
7  *   Copyright (C) 2012, 2015-2016 Attila Molnar <attilamolnar@hush.com>
8  *   Copyright (C) 2010 Craig Edwards <brain@inspircd.org>
9  *   Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
10  *   Copyright (C) 2007 Robin Burchell <robin+git@viroteck.net>
11  *   Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
12  *
13  * This file is part of InspIRCd.  InspIRCd is free software: you can
14  * redistribute it and/or modify it under the terms of the GNU General Public
15  * License as published by the Free Software Foundation, version 2.
16  *
17  * This program is distributed in the hope that it will be useful, but WITHOUT
18  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
20  * details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
24  */
25
26
27 #include "inspircd.h"
28 #include "modules/whois.h"
29
30 enum
31 {
32         // From UnrealIRCd.
33         RPL_WHOISSPECIAL = 320
34 };
35
36 struct CustomTitle
37 {
38         const std::string name;
39         const std::string password;
40         const std::string hash;
41         const std::string host;
42         const std::string title;
43         const std::string vhost;
44
45         CustomTitle(const std::string& n, const std::string& p, const std::string& h, const std::string& hst, const std::string& t, const std::string& v)
46                 : name(n)
47                 , password(p)
48                 , hash(h)
49                 , host(hst)
50                 , title(t)
51                 , vhost(v)
52         {
53         }
54
55         bool MatchUser(User* user) const
56         {
57                 const std::string userHost = user->ident + "@" + user->GetRealHost();
58                 const std::string userIP = user->ident + "@" + user->GetIPString();
59                 return InspIRCd::MatchMask(host, userHost, userIP);
60         }
61
62         bool CheckPass(User* user, const std::string& pass) const
63         {
64                 return ServerInstance->PassCompare(user, password, pass, hash);
65         }
66 };
67
68 typedef std::multimap<std::string, CustomTitle> CustomVhostMap;
69 typedef std::pair<CustomVhostMap::iterator, CustomVhostMap::iterator> MatchingConfigs;
70
71 /** Handle /TITLE
72  */
73 class CommandTitle : public Command
74 {
75  public:
76         StringExtItem ctitle;
77         CustomVhostMap configs;
78
79         CommandTitle(Module* Creator) : Command(Creator,"TITLE", 2),
80                 ctitle("ctitle", ExtensionItem::EXT_USER, Creator)
81         {
82                 syntax = "<username> <password>";
83         }
84
85         CmdResult Handle(User* user, const Params& parameters) CXX11_OVERRIDE
86         {
87                 MatchingConfigs matching = configs.equal_range(parameters[0]);
88
89                 for (MatchingConfigs::first_type i = matching.first; i != matching.second; ++i)
90                 {
91                         CustomTitle config = i->second;
92                         if (config.MatchUser(user) && config.CheckPass(user, parameters[1]))
93                         {
94                                 ctitle.set(user, config.title);
95
96                                 ServerInstance->PI->SendMetaData(user, "ctitle", config.title);
97
98                                 if (!config.vhost.empty())
99                                         user->ChangeDisplayedHost(config.vhost);
100
101                                 user->WriteNotice("Custom title set to '" + config.title + "'");
102
103                                 return CMD_SUCCESS;
104                         }
105                 }
106
107                 user->WriteNotice("Invalid title credentials");
108                 return CMD_SUCCESS;
109         }
110
111 };
112
113 class ModuleCustomTitle : public Module, public Whois::LineEventListener
114 {
115         CommandTitle cmd;
116
117  public:
118         ModuleCustomTitle()
119                 : Whois::LineEventListener(this)
120                 , cmd(this)
121         {
122         }
123
124         void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
125         {
126                 ConfigTagList tags = ServerInstance->Config->ConfTags("title");
127                 CustomVhostMap newtitles;
128                 for (ConfigIter i = tags.first; i != tags.second; ++i)
129                 {
130                         reference<ConfigTag> tag = i->second;
131                         std::string name = tag->getString("name", "", 1);
132                         if (name.empty())
133                                 throw ModuleException("<title:name> is empty at " + tag->getTagLocation());
134
135                         std::string pass = tag->getString("password");
136                         if (pass.empty())
137                                 throw ModuleException("<title:password> is empty at " + tag->getTagLocation());
138
139                         const std::string hash = tag->getString("hash", "plaintext", 1);
140                         if (stdalgo::string::equalsci(hash, "plaintext"))
141                         {
142                                 ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "<title> tag for %s at %s contains an plain text password, this is insecure!",
143                                         name.c_str(), tag->getTagLocation().c_str());
144                         }
145
146                         std::string host = tag->getString("host", "*@*", 1);
147                         std::string title = tag->getString("title");
148                         std::string vhost = tag->getString("vhost");
149                         CustomTitle config(name, pass, hash, host, title, vhost);
150                         newtitles.insert(std::make_pair(name, config));
151                 }
152                 cmd.configs.swap(newtitles);
153         }
154
155         // :kenny.chatspike.net 320 Brain Azhrarn :is getting paid to play games.
156         ModResult OnWhoisLine(Whois::Context& whois, Numeric::Numeric& numeric) CXX11_OVERRIDE
157         {
158                 /* We use this and not OnWhois because this triggers for remote, too */
159                 if (numeric.GetNumeric() == 312)
160                 {
161                         /* Insert our numeric before 312 */
162                         const std::string* ctitle = cmd.ctitle.get(whois.GetTarget());
163                         if (ctitle)
164                         {
165                                 whois.SendLine(RPL_WHOISSPECIAL, ctitle);
166                         }
167                 }
168                 /* Don't block anything */
169                 return MOD_RES_PASSTHRU;
170         }
171
172         Version GetVersion() CXX11_OVERRIDE
173         {
174                 return Version("Allows the server administrator to define accounts which can grant a custom title in /WHOIS and an optional virtual host.", VF_OPTCOMMON | VF_VENDOR);
175         }
176 };
177
178 MODULE_INIT(ModuleCustomTitle)