]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_flashpolicyd.cpp
Add a Flash Policy Daemon module
[user/henk/code/inspircd.git] / src / modules / m_flashpolicyd.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2013 Daniel Vassdal <shutter@canternet.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
22 class FlashPDSocket;
23
24 namespace
25 {
26         std::set<FlashPDSocket*> sockets;
27         std::string policy_reply;
28         const std::string expected_request("<policy-file-request/>\0", 23);
29 }
30
31 class FlashPDSocket : public BufferedSocket
32 {
33  public:
34         time_t created;
35
36         FlashPDSocket(int newfd)
37                 : BufferedSocket(newfd)
38                 , created(ServerInstance->Time())
39         {
40         }
41
42         ~FlashPDSocket()
43         {
44                 sockets.erase(this);
45         }
46
47         void OnError(BufferedSocketError) CXX11_OVERRIDE
48         {
49                 AddToCull();
50         }
51
52         void OnDataReady() CXX11_OVERRIDE
53         {
54                 if (recvq == expected_request)
55                         WriteData(policy_reply);
56                 AddToCull();
57         }
58
59         void AddToCull()
60         {
61                 if (created == 0)
62                         return;
63
64                 created = 0;
65                 Close();
66                 ServerInstance->GlobalCulls.AddItem(this);
67         }
68 };
69
70 class ModuleFlashPD : public Module
71 {
72         time_t timeout;
73
74  public:
75         void OnBackgroundTimer(time_t curtime) CXX11_OVERRIDE
76         {
77                 for (std::set<FlashPDSocket*>::const_iterator i = sockets.begin(); i != sockets.end(); ++i)
78                 {
79                         FlashPDSocket* sock = *i;
80                         if ((sock->created + timeout <= curtime) && (sock->created != 0))
81                                 sock->AddToCull();
82                 }
83         }
84
85         ModResult OnAcceptConnection(int nfd, ListenSocket* from, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server) CXX11_OVERRIDE
86         {
87                 if (from->bind_tag->getString("type") != "flashpolicyd")
88                         return MOD_RES_PASSTHRU;
89
90                 if (policy_reply.empty())
91                         return MOD_RES_DENY;
92
93                 sockets.insert(new FlashPDSocket(nfd));
94                 return MOD_RES_ALLOW;
95         }
96
97         void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
98         {
99                 ConfigTag* tag = ServerInstance->Config->ConfValue("flashpolicyd");
100                 timeout = tag->getInt("timeout", 5, 1);
101                 std::string file = tag->getString("file");
102
103                 if (!file.empty())
104                 {
105                         try
106                         {
107                                 FileReader reader(file);
108                                 policy_reply = reader.GetString();
109                         }
110                         catch (CoreException&)
111                         {
112                                 const std::string error_message = "A file was specified for FlashPD, but it could not be loaded.";
113                                 ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, error_message);
114                                 ServerInstance->SNO->WriteGlobalSno('a', error_message);
115                                 policy_reply.clear();
116                         }
117                         return;
118                 }
119
120                 // A file was not specified. Set the default setting.
121                 // We allow access to all client ports by default
122                 std::string to_ports;
123                 for (std::vector<ListenSocket*>::const_iterator i = ServerInstance->ports.begin(); i != ServerInstance->ports.end(); ++i)
124                 {
125                                 ListenSocket* ls = *i;
126                                 if (ls->bind_tag->getString("type", "clients") != "clients" || ls->bind_tag->getString("ssl", "plaintext") != "plaintext")
127                                         continue;
128
129                                 to_ports.append(ConvToStr(ls->bind_port)).push_back(',');
130                 }
131                 to_ports.erase(to_ports.size() - 1);
132
133                 policy_reply =
134 "<?xml version=\"1.0\"?>\
135 <!DOCTYPE cross-domain-policy SYSTEM \"/xml/dtds/cross-domain-policy.dtd\">\
136 <cross-domain-policy>\
137 <site-control permitted-cross-domain-policies=\"master-only\"/>\
138 <allow-access-from domain=\"*\" to-ports=\"" + to_ports + "\" />\
139 </cross-domain-policy>";
140         }
141
142         CullResult cull()
143         {
144                 for (std::set<FlashPDSocket*>::const_iterator i = sockets.begin(); i != sockets.end(); ++i)
145                 {
146                         FlashPDSocket* sock = *i;
147                         sock->AddToCull();
148                 }
149                 return Module::cull();
150         }
151
152         Version GetVersion() CXX11_OVERRIDE
153         {
154                 return Version("Flash Policy Daemon. Allows Flash IRC clients to connect", VF_VENDOR);
155         }
156 };
157
158 MODULE_INIT(ModuleFlashPD)