]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_httpd_acl.cpp
Add support for blacklists and whitelists, just http password auth to go (the most...
[user/henk/code/inspircd.git] / src / modules / m_httpd_acl.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd: (C) 2002-2008 InspIRCd Development Team
6  * See: http://www.inspircd.org/wiki/index.php/Credits
7  *
8  * This program is free but copyrighted software; see
9  *          the file COPYING for details.
10  *
11  * ---------------------------------------------------
12  */
13
14 #include "inspircd.h"
15 #include "httpd.h"
16 #include "protocol.h"
17 #include "wildcard.h"
18
19 /* $ModDesc: Provides access control lists (passwording of resources, ip restrictions etc) to m_httpd.so dependent modules */
20 /* $ModDep: httpd.h */
21
22 class ACL : public Extensible
23 {
24  public:
25         std::string path;
26         std::string password;
27         std::string whitelist;
28         std::string blacklist;
29
30         ACL(const std::string &set_path, const std::string &set_password,
31                 const std::string &set_whitelist, const std::string &set_blacklist)
32                 : path(set_path), password(set_password), whitelist(set_whitelist),
33                 blacklist(set_blacklist) { }
34
35         ~ACL() { }
36 };
37
38 class ModuleHTTPAccessList : public Module
39 {
40         
41         std::string stylesheet;
42         bool changed;
43         std::vector<ACL> acl_list;
44
45  public:
46
47         void ReadConfig()
48         {
49                 acl_list.clear();
50                 ConfigReader c(ServerInstance);
51                 int n_items = c.Enumerate("httpacl");
52                 for (int i = 0; i < n_items; ++i)
53                 {
54                         std::string path = c.ReadValue("httpacl", "path", i);
55                         std::string types = c.ReadValue("httpacl", "types", i);
56                         irc::commasepstream sep(types);
57                         std::string type;
58                         std::string password;
59                         std::string whitelist;
60                         std::string blacklist;
61
62                         while (sep.GetToken(type))
63                         {
64                                 if (type == "password")
65                                 {
66                                         password = c.ReadValue("httpacl", "password", i);
67                                 }
68                                 else if (type == "whitelist")
69                                 {
70                                         whitelist = c.ReadValue("httpacl", "whitelist", i);
71                                 }
72                                 else if (type == "blacklist")
73                                 {
74                                         blacklist = c.ReadValue("httpacl", "blacklist", i);
75                                 }
76                                 else
77                                 {
78                                         throw ModuleException("Invalid HTTP ACL type '" + type + "'");
79                                 }
80                         }
81
82                         acl_list.push_back(ACL(path, password, whitelist, blacklist));
83                 }
84         }
85
86         ModuleHTTPAccessList(InspIRCd* Me) : Module(Me)
87         {
88                 ReadConfig();
89                 this->changed = true;
90                 Implementation eventlist[] = { I_OnEvent, I_OnRequest };
91                 ServerInstance->Modules->Attach(eventlist, this, 2);
92         }
93
94         void BlockAccess(HTTPRequest* http, Event* event)
95         {
96                 std::stringstream data("Access to this resource is denied by an access control list. Please contact your IRC administrator.");
97                 HTTPDocument response(http->sock, &data, 403);
98                 response.headers.SetHeader("X-Powered-By", "m_httpd_acl.so");
99                 Request req((char*)&response, (Module*)this, event->GetSource());
100                 req.Send();
101         }
102
103         void OnEvent(Event* event)
104         {
105                 std::stringstream data("");
106
107                 if (event->GetEventID() == "httpd_url")
108                 {
109                         ServerInstance->Logs->Log("m_http_stats", DEBUG,"Handling httpd event");
110                         HTTPRequest* http = (HTTPRequest*)event->GetData();
111
112                         for (std::vector<ACL>::const_iterator this_acl = acl_list.begin(); this_acl != acl_list.end(); ++this_acl)
113                         {
114                                 if (match(http->GetURI(), this_acl->path))
115                                 {
116                                         if (!this_acl->blacklist.empty())
117                                         {
118                                                 /* Blacklist */
119                                                 irc::commasepstream sep(this_acl->blacklist);
120                                                 std::string entry;
121
122                                                 while (sep.GetToken(entry))
123                                                 {
124                                                         if (match(http->GetIP(), entry))
125                                                         {
126                                                                 BlockAccess(http, event);
127                                                                 return;
128                                                         }
129                                                 }
130                                         }
131                                         if (!this_acl->whitelist.empty())
132                                         {
133                                                 /* Whitelist */
134                                                 irc::commasepstream sep(this_acl->whitelist);
135                                                 std::string entry;
136                                                 bool allow_access = false;
137
138                                                 while (sep.GetToken(entry))
139                                                 {
140                                                         if (match(http->GetIP(), entry))
141                                                                 allow_access = true;
142                                                 }
143
144                                                 if (!allow_access)
145                                                 {
146                                                         BlockAccess(http, event);
147                                                         return;
148                                                 }
149                                         }
150                                         if (!this_acl->password.empty())
151                                         {
152                                                 /* Password auth, first look to see if we have a basic authentication header */
153                                         }
154                                 }
155                         }
156                 }
157         }
158
159         const char* OnRequest(Request* request)
160         {
161                 return NULL;
162         }
163
164         virtual ~ModuleHTTPAccessList()
165         {
166         }
167
168         virtual Version GetVersion()
169         {
170                 return Version(1, 2, 0, 0, VF_VENDOR, API_VERSION);
171         }
172 };
173
174 MODULE_INIT(ModuleHTTPAccessList)