]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_sslmodes.cpp
Refactor the sslqueries mode handler.
[user/henk/code/inspircd.git] / src / modules / m_sslmodes.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2020 Matt Schatz <genius3000@g3k.solutions>
5  *   Copyright (C) 2013, 2017-2020 Sadie Powell <sadie@witchery.services>
6  *   Copyright (C) 2013 Shawn Smith <ShawnSmith0828@gmail.com>
7  *   Copyright (C) 2012-2014 Attila Molnar <attilamolnar@hush.com>
8  *   Copyright (C) 2012 Robby <robby@chatbelgie.be>
9  *   Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org>
10  *   Copyright (C) 2009 Uli Schlachter <psychon@inspircd.org>
11  *   Copyright (C) 2008 Robin Burchell <robin+git@viroteck.net>
12  *   Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
13  *   Copyright (C) 2006-2007, 2010 Craig Edwards <brain@inspircd.org>
14  *
15  * This file is part of InspIRCd.  InspIRCd is free software: you can
16  * redistribute it and/or modify it under the terms of the GNU General Public
17  * License as published by the Free Software Foundation, version 2.
18  *
19  * This program is distributed in the hope that it will be useful, but WITHOUT
20  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
21  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
22  * details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
26  */
27
28
29 #include "inspircd.h"
30 #include "modules/ctctags.h"
31 #include "modules/ssl.h"
32
33 enum
34 {
35         // From UnrealIRCd.
36         ERR_SECUREONLYCHAN = 489,
37
38         // InspIRCd-specific.
39         ERR_ALLMUSTSSL = 490
40 };
41
42 /** Handle channel mode +z
43  */
44 class SSLMode : public ModeHandler
45 {
46  private:
47         UserCertificateAPI& API;
48
49  public:
50         SSLMode(Module* Creator, UserCertificateAPI& api)
51                 : ModeHandler(Creator, "sslonly", 'z', PARAM_NONE, MODETYPE_CHANNEL)
52                 , API(api)
53         {
54         }
55
56         ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string& parameter, bool adding) CXX11_OVERRIDE
57         {
58                 if (adding)
59                 {
60                         if (!channel->IsModeSet(this))
61                         {
62                                 if (IS_LOCAL(source))
63                                 {
64                                         if (!API)
65                                         {
66                                                 source->WriteNumeric(ERR_ALLMUSTSSL, channel->name, "Unable to determine whether all members of the channel are connected via TLS (SSL)");
67                                                 return MODEACTION_DENY;
68                                         }
69
70                                         unsigned long nonssl = 0;
71                                         const Channel::MemberMap& userlist = channel->GetUsers();
72                                         for (Channel::MemberMap::const_iterator i = userlist.begin(); i != userlist.end(); ++i)
73                                         {
74                                                 ssl_cert* cert = API->GetCertificate(i->first);
75                                                 if (!cert && !i->first->server->IsULine())
76                                                         nonssl++;
77                                         }
78
79                                         if (nonssl)
80                                         {
81                                                 source->WriteNumeric(ERR_ALLMUSTSSL, channel->name, InspIRCd::Format("All members of the channel must be connected via TLS (SSL) (%lu/%lu are non-TLS (SSL))",
82                                                         nonssl, static_cast<unsigned long>(userlist.size())));
83                                                 return MODEACTION_DENY;
84                                         }
85                                 }
86                                 channel->SetMode(this, true);
87                                 return MODEACTION_ALLOW;
88                         }
89                         else
90                         {
91                                 return MODEACTION_DENY;
92                         }
93                 }
94                 else
95                 {
96                         if (channel->IsModeSet(this))
97                         {
98                                 channel->SetMode(this, false);
99                                 return MODEACTION_ALLOW;
100                         }
101
102                         return MODEACTION_DENY;
103                 }
104         }
105 };
106
107 /** Handle user mode +z
108 */
109 class SSLModeUser : public ModeHandler
110 {
111  private:
112         UserCertificateAPI& API;
113
114  public:
115         SSLModeUser(Module* Creator, UserCertificateAPI& api)
116                 : ModeHandler(Creator, "sslqueries", 'z', PARAM_NONE, MODETYPE_USER)
117                 , API(api)
118         {
119                 if (!ServerInstance->Config->ConfValue("sslmodes")->getBool("enableumode"))
120                         DisableAutoRegister();
121         }
122
123         ModeAction OnModeChange(User* user, User* dest, Channel* channel, std::string& parameter, bool adding) CXX11_OVERRIDE
124         {
125                 if (adding == dest->IsModeSet(this))
126                         return MODEACTION_DENY;
127
128                 if (adding && IS_LOCAL(user) && (!API || !API->GetCertificate(user)))
129                         return MODEACTION_DENY;
130
131                 dest->SetMode(this, adding);
132                 return MODEACTION_ALLOW;
133         }
134 };
135
136 class ModuleSSLModes
137         : public Module
138         , public CTCTags::EventListener
139 {
140  private:
141         UserCertificateAPI api;
142         SSLMode sslm;
143         SSLModeUser sslquery;
144
145  public:
146         ModuleSSLModes()
147                 : CTCTags::EventListener(this)
148                 , api(this)
149                 , sslm(this, api)
150                 , sslquery(this, api)
151         {
152         }
153
154         ModResult OnUserPreJoin(LocalUser* user, Channel* chan, const std::string& cname, std::string& privs, const std::string& keygiven) CXX11_OVERRIDE
155         {
156                 if(chan && chan->IsModeSet(sslm))
157                 {
158                         if (!api)
159                         {
160                                 user->WriteNumeric(ERR_SECUREONLYCHAN, cname, "Cannot join channel; unable to determine if you are a TLS (SSL) user (+z is set)");
161                                 return MOD_RES_DENY;
162                         }
163
164                         if (!api->GetCertificate(user))
165                         {
166                                 user->WriteNumeric(ERR_SECUREONLYCHAN, cname, "Cannot join channel; TLS (SSL) users only (+z is set)");
167                                 return MOD_RES_DENY;
168                         }
169                 }
170
171                 return MOD_RES_PASSTHRU;
172         }
173
174         ModResult HandleMessage(User* user, const MessageTarget& msgtarget)
175         {
176                 if (msgtarget.type != MessageTarget::TYPE_USER)
177                         return MOD_RES_PASSTHRU;
178
179                 User* target = msgtarget.Get<User>();
180
181                 /* If one or more of the parties involved is a ulined service, we won't stop it. */
182                 if (user->server->IsULine() || target->server->IsULine())
183                         return MOD_RES_PASSTHRU;
184
185                 /* If the target is +z */
186                 if (target->IsModeSet(sslquery))
187                 {
188                         if (!api || !api->GetCertificate(user))
189                         {
190                                 /* The sending user is not on an SSL connection */
191                                 user->WriteNumeric(Numerics::CannotSendTo(target, "messages", &sslquery));
192                                 return MOD_RES_DENY;
193                         }
194                 }
195                 /* If the user is +z */
196                 else if (user->IsModeSet(sslquery))
197                 {
198                         if (!api || !api->GetCertificate(target))
199                         {
200                                 user->WriteNumeric(Numerics::CannotSendTo(target, "messages", &sslquery, true));
201                                 return MOD_RES_DENY;
202                         }
203                 }
204
205                 return MOD_RES_PASSTHRU;
206         }
207
208         ModResult OnUserPreMessage(User* user, const MessageTarget& target, MessageDetails& details) CXX11_OVERRIDE
209         {
210                 return HandleMessage(user, target);
211         }
212
213         ModResult OnUserPreTagMessage(User* user, const MessageTarget& target, CTCTags::TagMessageDetails& details) CXX11_OVERRIDE
214         {
215                 return HandleMessage(user, target);
216         }
217
218         ModResult OnCheckBan(User *user, Channel *c, const std::string& mask) CXX11_OVERRIDE
219         {
220                 if ((mask.length() > 2) && (mask[0] == 'z') && (mask[1] == ':'))
221                 {
222                         const std::string fp = api ? api->GetFingerprint(user) : "";
223                         if (!fp.empty() && InspIRCd::Match(fp, mask.substr(2)))
224                                 return MOD_RES_DENY;
225                 }
226                 return MOD_RES_PASSTHRU;
227         }
228
229         void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
230         {
231                 tokens["EXTBAN"].push_back('z');
232         }
233
234         Version GetVersion() CXX11_OVERRIDE
235         {
236                 return Version("Adds channel mode z (sslonly) which prevents users who are not connecting using TLS (SSL) from joining the channel and user mode z (sslqueries) to prevent messages from non-TLS (SSL) users.", VF_VENDOR);
237         }
238 };
239
240 MODULE_INIT(ModuleSSLModes)