]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_starttls.cpp
09c9b4f0fff1b07a33a8949933ecda9fb8d6e96d
[user/henk/code/inspircd.git] / src / modules / m_starttls.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2014 Adam <Adam@anope.org>
5  *
6  * This file is part of InspIRCd.  InspIRCd is free software: you can
7  * redistribute it and/or modify it under the terms of the GNU General Public
8  * License as published by the Free Software Foundation, version 2.
9  *
10  * This program is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
13  * details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19
20 #include "inspircd.h"
21 #include "modules/ssl.h"
22 #include "modules/cap.h"
23
24 // From IRCv3 tls-3.1
25 enum
26 {
27         RPL_STARTTLS = 670,
28         ERR_STARTTLS = 691
29 };
30
31 class CommandStartTLS : public SplitCommand
32 {
33         dynamic_reference_nocheck<IOHook>& ssl;
34
35  public:
36         CommandStartTLS(Module* mod, dynamic_reference_nocheck<IOHook>& s)
37                 : SplitCommand(mod, "STARTTLS")
38                 , ssl(s)
39         {
40                 works_before_reg = true;
41         }
42
43         CmdResult HandleLocal(const std::vector<std::string>& parameters, LocalUser* user)
44         {
45                 if (!ssl)
46                 {
47                         user->WriteNumeric(ERR_STARTTLS, ":STARTTLS is not enabled");
48                         return CMD_FAILURE;
49                 }
50
51                 if (user->registered == REG_ALL)
52                 {
53                         user->WriteNumeric(ERR_STARTTLS, ":STARTTLS is not permitted after client registration is complete");
54                         return CMD_FAILURE;
55                 }
56
57                 if (user->eh.GetIOHook())
58                 {
59                         user->WriteNumeric(ERR_STARTTLS, ":STARTTLS failure");
60                         return CMD_FAILURE;
61                 }
62
63                 user->WriteNumeric(RPL_STARTTLS, ":STARTTLS successful, go ahead with TLS handshake");
64                 /* We need to flush the write buffer prior to adding the IOHook,
65                  * otherwise we'll be sending this line inside the SSL session - which
66                  * won't start its handshake until the client gets this line. Currently,
67                  * we assume the write will not block here; this is usually safe, as
68                  * STARTTLS is sent very early on in the registration phase, where the
69                  * user hasn't built up much sendq. Handling a blocked write here would
70                  * be very annoying.
71                  */
72                 user->eh.DoWrite();
73
74                 user->eh.AddIOHook(*ssl);
75                 ssl->OnStreamSocketAccept(&user->eh, NULL, NULL);
76
77                 return CMD_SUCCESS;
78         }
79 };
80
81 class ModuleStartTLS : public Module
82 {
83         CommandStartTLS starttls;
84         GenericCap tls;
85         dynamic_reference_nocheck<IOHook> ssl;
86
87  public:
88         ModuleStartTLS()
89                 : starttls(this, ssl)
90                 , tls(this, "tls")
91                 , ssl(this, "ssl")
92         {
93         }
94
95         void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
96         {
97                 ConfigTag* conf = ServerInstance->Config->ConfValue("starttls");
98
99                 std::string newprovider = conf->getString("provider");
100                 if (newprovider.empty())
101                         ssl.SetProvider("ssl");
102                 else
103                         ssl.SetProvider("ssl/" + newprovider);
104         }
105
106         void OnEvent(Event& ev) CXX11_OVERRIDE
107         {
108                 tls.HandleEvent(ev);
109         }
110
111         void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
112         {
113                 tokens["STARTTLS"];
114         }
115
116         Version GetVersion() CXX11_OVERRIDE
117         {
118                 return Version("Provides support for the STARTTLS command", VF_VENDOR);
119         }
120 };
121
122 MODULE_INIT(ModuleStartTLS)