diff options
Diffstat (limited to 'include/modules')
-rw-r--r-- | include/modules/account.h | 41 | ||||
-rw-r--r-- | include/modules/cap.h | 88 | ||||
-rw-r--r-- | include/modules/dns.h | 193 | ||||
-rw-r--r-- | include/modules/hash.h | 58 | ||||
-rw-r--r-- | include/modules/httpd.h | 239 | ||||
-rw-r--r-- | include/modules/ldap.h | 199 | ||||
-rw-r--r-- | include/modules/regex.h | 62 | ||||
-rw-r--r-- | include/modules/sasl.h | 31 | ||||
-rw-r--r-- | include/modules/spanningtree.h | 40 | ||||
-rw-r--r-- | include/modules/sql.h | 184 | ||||
-rw-r--r-- | include/modules/ssl.h | 246 |
11 files changed, 1381 insertions, 0 deletions
diff --git a/include/modules/account.h b/include/modules/account.h new file mode 100644 index 000000000..c00b044e4 --- /dev/null +++ b/include/modules/account.h @@ -0,0 +1,41 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2008 Craig Edwards <craigedwards@brainbox.cc> + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +#pragma once + +#include <map> +#include <string> + +class AccountEvent : public Event +{ + public: + User* const user; + const std::string account; + AccountEvent(Module* me, User* u, const std::string& name) + : Event(me, "account_login"), user(u), account(name) + { + } +}; + +typedef StringExtItem AccountExtItem; + +inline AccountExtItem* GetAccountExtItem() +{ + return static_cast<AccountExtItem*>(ServerInstance->Extensions.GetItem("accountname")); +} diff --git a/include/modules/cap.h b/include/modules/cap.h new file mode 100644 index 000000000..1b33e05bb --- /dev/null +++ b/include/modules/cap.h @@ -0,0 +1,88 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org> + * Copyright (C) 2008 Craig Edwards <craigedwards@brainbox.cc> + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +#pragma once + +class CapEvent : public Event +{ + public: + enum CapEventType + { + CAPEVENT_REQ, + CAPEVENT_LS, + CAPEVENT_LIST, + CAPEVENT_CLEAR + }; + + CapEventType type; + std::vector<std::string> wanted; + std::vector<std::string> ack; + User* user; + CapEvent(Module* sender, User* u, CapEventType capevtype) : Event(sender, "cap_request"), type(capevtype), user(u) {} +}; + +class GenericCap +{ + public: + LocalIntExt ext; + const std::string cap; + GenericCap(Module* parent, const std::string &Cap) : ext("cap_" + Cap, parent), cap(Cap) + { + } + + void HandleEvent(Event& ev) + { + if (ev.id != "cap_request") + return; + + CapEvent *data = static_cast<CapEvent*>(&ev); + if (data->type == CapEvent::CAPEVENT_REQ) + { + for (std::vector<std::string>::iterator it = data->wanted.begin(); it != data->wanted.end(); ++it) + { + if (it->empty()) + continue; + bool enablecap = ((*it)[0] != '-'); + if (((enablecap) && (*it == cap)) || (*it == "-" + cap)) + { + // we can handle this, so ACK it, and remove it from the wanted list + data->ack.push_back(*it); + data->wanted.erase(it); + ext.set(data->user, enablecap ? 1 : 0); + break; + } + } + } + else if (data->type == CapEvent::CAPEVENT_LS) + { + data->wanted.push_back(cap); + } + else if (data->type == CapEvent::CAPEVENT_LIST) + { + if (ext.get(data->user)) + data->wanted.push_back(cap); + } + else if (data->type == CapEvent::CAPEVENT_CLEAR) + { + data->ack.push_back("-" + cap); + ext.set(data->user, 0); + } + } +}; diff --git a/include/modules/dns.h b/include/modules/dns.h new file mode 100644 index 000000000..c76c53805 --- /dev/null +++ b/include/modules/dns.h @@ -0,0 +1,193 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2013 Adam <Adam@anope.org> + * Copyright (C) 2003-2013 Anope Team <team@anope.org> + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +namespace DNS +{ + /** Valid query types + */ + enum QueryType + { + /* Nothing */ + QUERY_NONE, + /* A simple A lookup */ + QUERY_A = 1, + /* A CNAME lookup */ + QUERY_CNAME = 5, + /* Reverse DNS lookup */ + QUERY_PTR = 12, + /* IPv6 AAAA lookup */ + QUERY_AAAA = 28 + }; + + /** Flags that can be AND'd into DNSPacket::flags to receive certain values + */ + enum + { + QUERYFLAGS_QR = 0x8000, + QUERYFLAGS_OPCODE = 0x7800, + QUERYFLAGS_AA = 0x400, + QUERYFLAGS_TC = 0x200, + QUERYFLAGS_RD = 0x100, + QUERYFLAGS_RA = 0x80, + QUERYFLAGS_Z = 0x70, + QUERYFLAGS_RCODE = 0xF + }; + + enum Error + { + ERROR_NONE, + ERROR_UNKNOWN, + ERROR_UNLOADED, + ERROR_TIMEDOUT, + ERROR_NOT_AN_ANSWER, + ERROR_NONSTANDARD_QUERY, + ERROR_FORMAT_ERROR, + ERROR_SERVER_FAILURE, + ERROR_DOMAIN_NOT_FOUND, + ERROR_NOT_IMPLEMENTED, + ERROR_REFUSED, + ERROR_NO_RECORDS, + ERROR_INVALIDTYPE + }; + + const int PORT = 53; + + /** + * The maximum value of a dns request id, + * 16 bits wide, 0xFFFF. + */ + const int MAX_REQUEST_ID = 0xFFFF; + + class Exception : public ModuleException + { + public: + Exception(const std::string& message) : ModuleException(message) { } + }; + + struct Question + { + std::string name; + QueryType type; + unsigned short qclass; + + Question() : type(QUERY_NONE), qclass(0) { } + Question(const std::string& n, QueryType t, unsigned short c = 1) : name(n), type(t), qclass(c) { } + inline bool operator==(const Question& other) const { return name == other.name && type == other.type && qclass == other.qclass; } + + struct hash + { + size_t operator()(const Question& question) const + { + return irc::insensitive()(question.name); + } + }; + }; + + struct ResourceRecord : Question + { + unsigned int ttl; + std::string rdata; + time_t created; + + ResourceRecord(const std::string& n, QueryType t, unsigned short c = 1) : Question(n, t, c), ttl(0), created(ServerInstance->Time()) { } + ResourceRecord(const Question& question) : Question(question), ttl(0), created(ServerInstance->Time()) { } + }; + + struct Query + { + std::vector<Question> questions; + std::vector<ResourceRecord> answers; + Error error; + bool cached; + + Query() : error(ERROR_NONE), cached(false) { } + Query(const Question& question) : error(ERROR_NONE), cached(false) { questions.push_back(question); } + }; + + class ReplySocket; + class Request; + + /** DNS manager + */ + class Manager : public DataProvider + { + public: + Manager(Module* mod) : DataProvider(mod, "DNS") { } + + virtual void Process(Request* req) = 0; + virtual void RemoveRequest(Request* req) = 0; + virtual std::string GetErrorStr(Error) = 0; + }; + + /** A DNS query. + */ + class Request : public Timer, public Question + { + protected: + Manager* const manager; + public: + /* Use result cache if available */ + bool use_cache; + /* Request id */ + unsigned short id; + /* Creator of this request */ + Module* const creator; + + Request(Manager* mgr, Module* mod, const std::string& addr, QueryType qt, bool usecache = true) + : Timer((ServerInstance->Config->dns_timeout ? ServerInstance->Config->dns_timeout : 5), ServerInstance->Time()) + , Question(addr, qt) + , manager(mgr) + , use_cache(usecache) + , id(0) + , creator(mod) + { + ServerInstance->Timers.AddTimer(this); + } + + virtual ~Request() + { + manager->RemoveRequest(this); + } + + /** Called when this request succeeds + * @param r The query sent back from the nameserver + */ + virtual void OnLookupComplete(const Query* req) = 0; + + /** Called when this request fails or times out. + * @param r The query sent back from the nameserver, check the error code. + */ + virtual void OnError(const Query* req) { } + + /** Used to time out the query, calls OnError and asks the TimerManager + * to delete this request + */ + bool Tick(time_t now) + { + Query rr(*this); + rr.error = ERROR_TIMEDOUT; + this->OnError(&rr); + delete this; + return false; + } + }; + +} // namespace DNS diff --git a/include/modules/hash.h b/include/modules/hash.h new file mode 100644 index 000000000..da04c45ba --- /dev/null +++ b/include/modules/hash.h @@ -0,0 +1,58 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2010 Daniel De Graaf <danieldg@inspircd.org> + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +#pragma once + +#include "modules.h" + +class HashProvider : public DataProvider +{ + public: + const unsigned int out_size; + const unsigned int block_size; + HashProvider(Module* mod, const std::string& Name, int osiz, int bsiz) + : DataProvider(mod, Name), out_size(osiz), block_size(bsiz) {} + virtual std::string sum(const std::string& data) = 0; + inline std::string hexsum(const std::string& data) + { + return BinToHex(sum(data)); + } + + inline std::string b64sum(const std::string& data) + { + return BinToBase64(sum(data), NULL, 0); + } + + /** HMAC algorithm, RFC 2104 */ + std::string hmac(const std::string& key, const std::string& msg) + { + std::string hmac1, hmac2; + std::string kbuf = key.length() > block_size ? sum(key) : key; + kbuf.resize(block_size); + + for (size_t n = 0; n < block_size; n++) + { + hmac1.push_back(static_cast<char>(kbuf[n] ^ 0x5C)); + hmac2.push_back(static_cast<char>(kbuf[n] ^ 0x36)); + } + hmac2.append(msg); + hmac1.append(sum(hmac2)); + return sum(hmac1); + } +}; diff --git a/include/modules/httpd.h b/include/modules/httpd.h new file mode 100644 index 000000000..86234d53f --- /dev/null +++ b/include/modules/httpd.h @@ -0,0 +1,239 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org> + * Copyright (C) 2008 Pippijn van Steenhoven <pip88nl@gmail.com> + * Copyright (C) 2007 John Brooks <john.brooks@dereferenced.net> + * Copyright (C) 2007 Dennis Friis <peavey@inspircd.org> + * Copyright (C) 2006 Craig Edwards <craigedwards@brainbox.cc> + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +#pragma once + +#include "base.h" + +#include <string> +#include <sstream> +#include <map> + +/** A modifyable list of HTTP header fields + */ +class HTTPHeaders +{ + protected: + std::map<std::string,std::string> headers; + public: + + /** Set the value of a header + * Sets the value of the named header. If the header is already present, it will be replaced + */ + void SetHeader(const std::string &name, const std::string &data) + { + headers[name] = data; + } + + /** Set the value of a header, only if it doesn't exist already + * Sets the value of the named header. If the header is already present, it will NOT be updated + */ + void CreateHeader(const std::string &name, const std::string &data) + { + if (!IsSet(name)) + SetHeader(name, data); + } + + /** Remove the named header + */ + void RemoveHeader(const std::string &name) + { + headers.erase(name); + } + + /** Remove all headers + */ + void Clear() + { + headers.clear(); + } + + /** Get the value of a header + * @return The value of the header, or an empty string + */ + std::string GetHeader(const std::string &name) + { + std::map<std::string,std::string>::iterator it = headers.find(name); + if (it == headers.end()) + return std::string(); + + return it->second; + } + + /** Check if the given header is specified + * @return true if the header is specified + */ + bool IsSet(const std::string &name) + { + std::map<std::string,std::string>::iterator it = headers.find(name); + return (it != headers.end()); + } + + /** Get all headers, formatted by the HTTP protocol + * @return Returns all headers, formatted according to the HTTP protocol. There is no request terminator at the end + */ + std::string GetFormattedHeaders() + { + std::string re; + + for (std::map<std::string,std::string>::iterator i = headers.begin(); i != headers.end(); i++) + re += i->first + ": " + i->second + "\r\n"; + + return re; + } +}; + +class HttpServerSocket; + +/** This class represents a HTTP request. + */ +class HTTPRequest : public Event +{ + protected: + std::string type; + std::string document; + std::string ipaddr; + std::string postdata; + + public: + + HTTPHeaders *headers; + int errorcode; + + /** A socket pointer, which you must return in your HTTPDocument class + * if you reply to this request. + */ + HttpServerSocket* sock; + + /** Initialize HTTPRequest. + * This constructor is called by m_httpd.so to initialize the class. + * @param request_type The request type, e.g. GET, POST, HEAD + * @param uri The URI, e.g. /page + * @param hdr The headers sent with the request + * @param opaque An opaque pointer used internally by m_httpd, which you must pass back to the module in your reply. + * @param ip The IP address making the web request. + * @param pdata The post data (content after headers) received with the request, up to Content-Length in size + */ + HTTPRequest(Module* me, const std::string &eventid, const std::string &request_type, const std::string &uri, + HTTPHeaders* hdr, HttpServerSocket* socket, const std::string &ip, const std::string &pdata) + : Event(me, eventid), type(request_type), document(uri), ipaddr(ip), postdata(pdata), headers(hdr), sock(socket) + { + } + + /** Get the post data (request content). + * All post data will be returned, including carriage returns and linefeeds. + * @return The postdata + */ + std::string& GetPostData() + { + return postdata; + } + + /** Get the request type. + * Any request type can be intercepted, even ones which are invalid in the HTTP/1.1 spec. + * @return The request type, e.g. GET, POST, HEAD + */ + std::string& GetType() + { + return type; + } + + /** Get URI. + * The URI string (URL minus hostname and scheme) will be provided by this function. + * @return The URI being requested + */ + std::string& GetURI() + { + return document; + } + + /** Get IP address of requester. + * The requesting system's ip address will be returned. + * @return The IP address as a string + */ + std::string& GetIP() + { + return ipaddr; + } +}; + +/** If you want to reply to HTTP requests, you must return a HTTPDocumentResponse to + * the httpd module via the HTTPdAPI. + * When you initialize this class you initialize it with all components required to + * form a valid HTTP response: the document data and a response code. + * You can add additional HTTP headers, if you want. + */ +class HTTPDocumentResponse +{ + public: + /** Module that generated this reply + */ + Module* const module; + + std::stringstream* document; + unsigned int responsecode; + + /** Any extra headers to include with the defaults + */ + HTTPHeaders headers; + + HTTPRequest& src; + + /** Initialize a HTTPDocumentResponse ready for sending to the httpd module. + * @param mod A pointer to the module who responded to the request + * @param req The request you obtained from the HTTPRequest at an earlier time + * @param doc A stringstream containing the document body + * @param response A valid HTTP/1.0 or HTTP/1.1 response code. The response text will be determined for you + * based upon the response code. + */ + HTTPDocumentResponse(Module* mod, HTTPRequest& req, std::stringstream* doc, unsigned int response) + : module(mod), document(doc), responsecode(response), src(req) + { + } +}; + +class HTTPdAPIBase : public DataProvider +{ + public: + HTTPdAPIBase(Module* parent) + : DataProvider(parent, "m_httpd_api") + { + } + + /** Answer an incoming HTTP request with the provided document + * @param response The response created by your module that will be sent to the client + */ + virtual void SendResponse(HTTPDocumentResponse& response) = 0; +}; + +/** The API provided by the httpd module that allows other modules to respond to incoming + * HTTP requests + */ +class HTTPdAPI : public dynamic_reference<HTTPdAPIBase> +{ + public: + HTTPdAPI(Module* parent) + : dynamic_reference<HTTPdAPIBase>(parent, "m_httpd_api") + { + } +}; diff --git a/include/modules/ldap.h b/include/modules/ldap.h new file mode 100644 index 000000000..75ab16077 --- /dev/null +++ b/include/modules/ldap.h @@ -0,0 +1,199 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2013 Adam <Adam@anope.org> + * Copyright (C) 2003-2013 Anope Team <team@anope.org> + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +typedef int LDAPQuery; + +class LDAPException : public ModuleException +{ + public: + LDAPException(const std::string& reason) : ModuleException(reason) { } + + virtual ~LDAPException() throw() { } +}; + +struct LDAPModification +{ + enum LDAPOperation + { + LDAP_ADD, + LDAP_DEL, + LDAP_REPLACE + }; + + LDAPOperation op; + std::string name; + std::vector<std::string> values; +}; + +typedef std::vector<LDAPModification> LDAPMods; + +struct LDAPAttributes : public std::map<std::string, std::vector<std::string> > +{ + size_t size(const std::string& attr) const + { + const std::vector<std::string>& array = this->getArray(attr); + return array.size(); + } + + const std::vector<std::string> keys() const + { + std::vector<std::string> k; + for (const_iterator it = this->begin(), it_end = this->end(); it != it_end; ++it) + k.push_back(it->first); + return k; + } + + const std::string& get(const std::string& attr) const + { + const std::vector<std::string>& array = this->getArray(attr); + if (array.empty()) + throw LDAPException("Empty attribute " + attr + " in LDAPResult::get"); + return array[0]; + } + + const std::vector<std::string>& getArray(const std::string& attr) const + { + const_iterator it = this->find(attr); + if (it == this->end()) + throw LDAPException("Unknown attribute " + attr + " in LDAPResult::getArray"); + return it->second; + } +}; + +struct LDAPResult +{ + std::vector<LDAPAttributes> messages; + std::string error; + + enum QueryType + { + QUERY_UNKNOWN, + QUERY_BIND, + QUERY_SEARCH, + QUERY_ADD, + QUERY_DELETE, + QUERY_MODIFY, + QUERY_COMPARE + }; + + QueryType type; + LDAPQuery id; + + LDAPResult() + : type(QUERY_UNKNOWN), id(-1) + { + } + + size_t size() const + { + return this->messages.size(); + } + + bool empty() const + { + return this->messages.empty(); + } + + const LDAPAttributes& get(size_t sz) const + { + if (sz >= this->messages.size()) + throw LDAPException("Index out of range"); + return this->messages[sz]; + } + + const std::string& getError() const + { + return this->error; + } +}; + +class LDAPInterface +{ + public: + ModuleRef creator; + + LDAPInterface(Module* m) : creator(m) { } + virtual ~LDAPInterface() { } + + virtual void OnResult(const LDAPResult& r) = 0; + virtual void OnError(const LDAPResult& err) = 0; +}; + +class LDAPProvider : public DataProvider +{ + public: + LDAPProvider(Module* Creator, const std::string& Name) + : DataProvider(Creator, Name) { } + + /** Attempt to bind to the LDAP server as a manager + * @param i The LDAPInterface the result is sent to + * @return The query ID + */ + virtual LDAPQuery BindAsManager(LDAPInterface *i) = 0; + + /** Bind to LDAP + * @param i The LDAPInterface the result is sent to + * @param who The binddn + * @param pass The password + * @return The query ID + */ + virtual LDAPQuery Bind(LDAPInterface* i, const std::string& who, const std::string& pass) = 0; + + /** Search ldap for the specified filter + * @param i The LDAPInterface the result is sent to + * @param base The base DN to search + * @param filter The filter to apply + * @return The query ID + */ + virtual LDAPQuery Search(LDAPInterface* i, const std::string& base, const std::string& filter) = 0; + + /** Add an entry to LDAP + * @param i The LDAPInterface the result is sent to + * @param dn The dn of the entry to add + * @param attributes The attributes + * @return The query ID + */ + virtual LDAPQuery Add(LDAPInterface* i, const std::string& dn, LDAPMods& attributes) = 0; + + /** Delete an entry from LDAP + * @param i The LDAPInterface the result is sent to + * @param dn The dn of the entry to delete + * @return The query ID + */ + virtual LDAPQuery Del(LDAPInterface* i, const std::string& dn) = 0; + + /** Modify an existing entry in LDAP + * @param i The LDAPInterface the result is sent to + * @param base The base DN to modify + * @param attributes The attributes to modify + * @return The query ID + */ + virtual LDAPQuery Modify(LDAPInterface* i, const std::string& base, LDAPMods& attributes) = 0; + + /** Compare an attribute in LDAP with our value + * @param i The LDAPInterface the result is sent to + * @param dn DN to use for comparing + * @param attr Attr of DN to compare with + * @param val value to compare attr of dn + * @return the query ID + */ + virtual LDAPQuery Compare(LDAPInterface* i, const std::string& dn, const std::string& attr, const std::string& val) = 0; +}; diff --git a/include/modules/regex.h b/include/modules/regex.h new file mode 100644 index 000000000..5ef00cdd0 --- /dev/null +++ b/include/modules/regex.h @@ -0,0 +1,62 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org> + * Copyright (C) 2008 Thomas Stagner <aquanight@inspircd.org> + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +#pragma once + +#include "inspircd.h" + +class Regex : public classbase +{ +protected: + /** The uncompiled regex string. */ + std::string regex_string; + + // Constructor may as well be protected, as this class is abstract. + Regex(const std::string& rx) : regex_string(rx) { } + +public: + + virtual ~Regex() { } + + virtual bool Matches(const std::string& text) = 0; + + const std::string& GetRegexString() const + { + return regex_string; + } +}; + +class RegexFactory : public DataProvider +{ + public: + RegexFactory(Module* Creator, const std::string& Name) : DataProvider(Creator, Name) { } + + virtual Regex* Create(const std::string& expr) = 0; +}; + +class RegexException : public ModuleException +{ + public: + RegexException(const std::string& regex, const std::string& error) + : ModuleException("Error in regex '" + regex + "': " + error) { } + + RegexException(const std::string& regex, const std::string& error, int offset) + : ModuleException("Error in regex '" + regex + "' at offset " + ConvToStr(offset) + ": " + error) { } +}; diff --git a/include/modules/sasl.h b/include/modules/sasl.h new file mode 100644 index 000000000..321711a68 --- /dev/null +++ b/include/modules/sasl.h @@ -0,0 +1,31 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2010 Daniel De Graaf <danieldg@inspircd.org> + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +#pragma once + +class SASLFallback : public Event +{ + public: + const parameterlist& params; + SASLFallback(Module* me, const parameterlist& p) + : Event(me, "sasl_fallback"), params(p) + { + Send(); + } +}; diff --git a/include/modules/spanningtree.h b/include/modules/spanningtree.h new file mode 100644 index 000000000..99f4f9fc4 --- /dev/null +++ b/include/modules/spanningtree.h @@ -0,0 +1,40 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org> + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +#pragma once + +struct AddServerEvent : public Event +{ + const std::string servername; + AddServerEvent(Module* me, const std::string& name) + : Event(me, "new_server"), servername(name) + { + Send(); + } +}; + +struct DelServerEvent : public Event +{ + const std::string servername; + DelServerEvent(Module* me, const std::string& name) + : Event(me, "lost_server"), servername(name) + { + Send(); + } +}; diff --git a/include/modules/sql.h b/include/modules/sql.h new file mode 100644 index 000000000..3f378d8b8 --- /dev/null +++ b/include/modules/sql.h @@ -0,0 +1,184 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2010 Daniel De Graaf <danieldg@inspircd.org> + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +#pragma once + +/** Defines the error types which SQLerror may be set to + */ +enum SQLerrorNum { SQL_NO_ERROR, SQL_BAD_DBID, SQL_BAD_CONN, SQL_QSEND_FAIL, SQL_QREPLY_FAIL }; + +/** A list of format parameters for an SQLquery object. + */ +typedef std::vector<std::string> ParamL; + +typedef std::map<std::string, std::string> ParamM; + +class SQLEntry +{ + public: + std::string value; + bool nul; + SQLEntry() : nul(true) {} + SQLEntry(const std::string& v) : value(v), nul(false) {} + inline operator std::string&() { return value; } +}; + +typedef std::vector<SQLEntry> SQLEntries; + +/** + * Result of an SQL query. Only valid inside OnResult + */ +class SQLResult : public classbase +{ + public: + /** + * Return the number of rows in the result. + * + * Note that if you have perfomed an INSERT or UPDATE query or other + * query which will not return rows, this will return the number of + * affected rows. In this case you SHOULD NEVER access any of the result + * set rows, as there aren't any! + * @returns Number of rows in the result set. + */ + virtual int Rows() = 0; + + /** + * Return a single row (result of the query). The internal row counter + * is incremented by one. + * + * @param result Storage for the result data. + * @returns true if there was a row, false if no row exists (end of + * iteration) + */ + virtual bool GetRow(SQLEntries& result) = 0; + + /** Returns column names for the items in this row + */ + virtual void GetCols(std::vector<std::string>& result) = 0; +}; + +/** SQLerror holds the error state of a request. + * The error string varies from database software to database software + * and should be used to display informational error messages to users. + */ +class SQLerror +{ + public: + /** The error id + */ + SQLerrorNum id; + + /** The error string + */ + std::string str; + + /** Initialize an SQLerror + * @param i The error ID to set + * @param s The (optional) error string to set + */ + SQLerror(SQLerrorNum i, const std::string &s = "") + : id(i), str(s) + { + } + + /** Return the error string for an error + */ + const char* Str() + { + if(str.length()) + return str.c_str(); + + switch(id) + { + case SQL_BAD_DBID: + return "Invalid database ID"; + case SQL_BAD_CONN: + return "Invalid connection"; + case SQL_QSEND_FAIL: + return "Sending query failed"; + case SQL_QREPLY_FAIL: + return "Getting query result failed"; + default: + return "Unknown error"; + } + } +}; + +/** + * Object representing an SQL query. This should be allocated on the heap and + * passed to an SQLProvider, which will free it when the query is complete or + * when the querying module is unloaded. + * + * You should store whatever information is needed to have the callbacks work in + * this object (UID of user, channel name, etc). + */ +class SQLQuery : public classbase +{ + public: + ModuleRef creator; + + SQLQuery(Module* Creator) : creator(Creator) {} + virtual ~SQLQuery() {} + + virtual void OnResult(SQLResult& result) = 0; + /** + * Called when the query fails + */ + virtual void OnError(SQLerror& error) { } +}; + +/** + * Provider object for SQL servers + */ +class SQLProvider : public DataProvider +{ + public: + SQLProvider(Module* Creator, const std::string& Name) : DataProvider(Creator, Name) {} + /** Submit an asynchronous SQL request + * @param callback The result reporting point + * @param query The hardcoded query string. If you have parameters to substitute, see below. + */ + virtual void submit(SQLQuery* callback, const std::string& query) = 0; + + /** Submit an asynchronous SQL request + * @param callback The result reporting point + * @param format The simple parameterized query string ('?' parameters) + * @param p Parameters to fill in for the '?' entries + */ + virtual void submit(SQLQuery* callback, const std::string& format, const ParamL& p) = 0; + + /** Submit an asynchronous SQL request. + * @param callback The result reporting point + * @param format The parameterized query string ('$name' parameters) + * @param p Parameters to fill in for the '$name' entries + */ + virtual void submit(SQLQuery* callback, const std::string& format, const ParamM& p) = 0; + + /** Convenience function to prepare a map from a User* */ + void PopulateUserInfo(User* user, ParamM& userinfo) + { + userinfo["nick"] = user->nick; + userinfo["host"] = user->host; + userinfo["ip"] = user->GetIPString(); + userinfo["gecos"] = user->fullname; + userinfo["ident"] = user->ident; + userinfo["server"] = user->server->GetName(); + userinfo["uuid"] = user->uuid; + } +}; diff --git a/include/modules/ssl.h b/include/modules/ssl.h new file mode 100644 index 000000000..0f58e0b7b --- /dev/null +++ b/include/modules/ssl.h @@ -0,0 +1,246 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org> + * Copyright (C) 2006 Craig Edwards <craigedwards@brainbox.cc> + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +#pragma once + +#include <string> +#include "iohook.h" + +/** ssl_cert is a class which abstracts SSL certificate + * and key information. + * + * Because gnutls and openssl represent key information in + * wildly different ways, this class allows it to be accessed + * in a unified manner. These classes are attached to ssl- + * connected local users using SSLCertExt + */ +class ssl_cert : public refcountbase +{ + public: + std::string dn; + std::string issuer; + std::string error; + std::string fingerprint; + bool trusted, invalid, unknownsigner, revoked; + + ssl_cert() : trusted(false), invalid(true), unknownsigner(true), revoked(false) {} + + /** Get certificate distinguished name + * @return Certificate DN + */ + const std::string& GetDN() + { + return dn; + } + + /** Get Certificate issuer + * @return Certificate issuer + */ + const std::string& GetIssuer() + { + return issuer; + } + + /** Get error string if an error has occured + * @return The error associated with this users certificate, + * or an empty string if there is no error. + */ + const std::string& GetError() + { + return error; + } + + /** Get key fingerprint. + * @return The key fingerprint as a hex string. + */ + const std::string& GetFingerprint() + { + return fingerprint; + } + + /** Get trust status + * @return True if this is a trusted certificate + * (the certificate chain validates) + */ + bool IsTrusted() + { + return trusted; + } + + /** Get validity status + * @return True if the certificate itself is + * correctly formed. + */ + bool IsInvalid() + { + return invalid; + } + + /** Get signer status + * @return True if the certificate appears to be + * self-signed. + */ + bool IsUnknownSigner() + { + return unknownsigner; + } + + /** Get revokation status. + * @return True if the certificate is revoked. + * Note that this only works properly for GnuTLS + * right now. + */ + bool IsRevoked() + { + return revoked; + } + + bool IsCAVerified() + { + return trusted && !invalid && !revoked && !unknownsigner && error.empty(); + } + + std::string GetMetaLine() + { + std::stringstream value; + bool hasError = !error.empty(); + value << (IsInvalid() ? "v" : "V") << (IsTrusted() ? "T" : "t") << (IsRevoked() ? "R" : "r") + << (IsUnknownSigner() ? "s" : "S") << (hasError ? "E" : "e") << " "; + if (hasError) + value << GetError(); + else + value << GetFingerprint() << " " << GetDN() << " " << GetIssuer(); + return value.str(); + } +}; + +class SSLIOHook : public IOHook +{ + protected: + /** Peer SSL certificate, set by the SSL module + */ + reference<ssl_cert> certificate; + + public: + SSLIOHook(IOHookProvider* hookprov) + : IOHook(hookprov) + { + } + + /** + * Get the certificate sent by this peer + * @return The SSL certificate sent by the peer, NULL if no cert was sent + */ + ssl_cert* GetCertificate() const + { + return certificate; + } + + /** + * Get the fingerprint of the peer's certificate + * @return The fingerprint of the SSL client certificate sent by the peer, + * empty if no cert was sent + */ + std::string GetFingerprint() const + { + ssl_cert* cert = GetCertificate(); + if (cert) + return cert->GetFingerprint(); + return ""; + } +}; + +/** Helper functions for obtaining SSL client certificates and key fingerprints + * from StreamSockets + */ +class SSLClientCert +{ + public: + /** + * Get the client certificate from a socket + * @param sock The socket to get the certificate from, the socket does not have to use SSL + * @return The SSL client certificate information, NULL if the peer is not using SSL + */ + static ssl_cert* GetCertificate(StreamSocket* sock) + { + IOHook* iohook = sock->GetIOHook(); + if ((!iohook) || (iohook->prov->type != IOHookProvider::IOH_SSL)) + return NULL; + + SSLIOHook* ssliohook = static_cast<SSLIOHook*>(iohook); + return ssliohook->GetCertificate(); + } + + /** + * Get the fingerprint of a client certificate from a socket + * @param sock The socket to get the certificate fingerprint from, the + * socket does not have to use SSL + * @return The key fingerprint from the SSL certificate sent by the peer, + * empty if no cert was sent or the peer is not using SSL + */ + static std::string GetFingerprint(StreamSocket* sock) + { + ssl_cert* cert = SSLClientCert::GetCertificate(sock); + if (cert) + return cert->GetFingerprint(); + return ""; + } +}; + +class UserCertificateAPIBase : public DataProvider +{ + public: + UserCertificateAPIBase(Module* parent) + : DataProvider(parent, "m_sslinfo_api") + { + } + + /** Get the SSL certificate of a user + * @param user The user whose certificate to get, user may be remote + * @return The SSL certificate of the user or NULL if the user is not using SSL + */ + virtual ssl_cert* GetCertificate(User* user) = 0; + + /** Get the key fingerprint from a user's certificate + * @param user The user whose key fingerprint to get, user may be remote + * @return The key fingerprint from the user's SSL certificate or an empty string + * if the user is not using SSL or did not provide a client certificate + */ + std::string GetFingerprint(User* user) + { + ssl_cert* cert = GetCertificate(user); + if (cert) + return cert->GetFingerprint(); + return ""; + } +}; + +/** API implemented by m_sslinfo that allows modules to retrive the SSL certificate + * information of local and remote users. It can also be used to find out whether a + * user is using SSL or not. + */ +class UserCertificateAPI : public dynamic_reference<UserCertificateAPIBase> +{ + public: + UserCertificateAPI(Module* parent) + : dynamic_reference<UserCertificateAPIBase>(parent, "m_sslinfo_api") + { + } +}; |