diff options
author | Adam <Adam@anope.org> | 2011-03-22 23:58:53 -0400 |
---|---|---|
committer | Adam <Adam@anope.org> | 2011-03-22 23:58:53 -0400 |
commit | 451fb82e544fda19888c4d5bc250431a3197cef6 (patch) | |
tree | a41599e56a43f42d37bc6481fbb86f15b2d42d6b | |
parent | c02d51f52348758487223856e716261a734af8fc (diff) |
Bug #1203
-rw-r--r-- | data/example.conf | 14 | ||||
-rw-r--r-- | docs/XMLRPC/XMLRPC | 10 | ||||
-rw-r--r-- | docs/XMLRPC/xmlrpc.php | 20 | ||||
-rw-r--r-- | modules/extra/m_xmlrpc.cpp | 74 | ||||
-rw-r--r-- | modules/extra/m_xmlrpc_main.cpp | 27 | ||||
-rw-r--r-- | modules/extra/xmlrpc.h | 4 |
6 files changed, 78 insertions, 71 deletions
diff --git a/data/example.conf b/data/example.conf index ee624022e..7895f63ac 100644 --- a/data/example.conf +++ b/data/example.conf @@ -2111,24 +2111,22 @@ m_xmlrpc /* IP to listen on */ bindip = "127.0.0.1" /* Port to listen on */ - port = 16673 + port = 26673 /* Enable for IPv6 */ ipv6 = no - /* If enabled, requires m_ssl is loaded */ + /* If enabled, requires m_ssl to be loaded */ ssl = no /* IPs allowed to connect (separate with spaces), this should be secured. We also recommend you firewall this - * with an outside program to ensure security. + * with an outside program to increase security. */ - allowed = "127.0.0.1" - /* An optional username and password, if supplied clients using XMLRPC must authenticate first using it */ - username = "anope" - password = "mypass" + allowed = "127.0.0.0/24" } /* * m_xmlrpc_main * - * Main XMLRPC function, adds many core methods that may be required for XMLRPC to work right (such as login). + * Adds the main XMLRPC core functions. + * Requires m_xmlrpc. */ #module { name = "m_xmlrpc_main" } diff --git a/docs/XMLRPC/XMLRPC b/docs/XMLRPC/XMLRPC index dad7641e3..f710f1502 100644 --- a/docs/XMLRPC/XMLRPC +++ b/docs/XMLRPC/XMLRPC @@ -1,10 +1,7 @@ Starting with Anope 1.9.4 XMLRPC using PHP's xmlrpc_encode_request and xmlrpc_decode functions is supported. This allows external applications, such as websites, to execute remote procedure calls to Anope in real time. -Currently there are 6 supported XMLRPC calls, provided by m_xmlrpc_main: - -login - Takes two parameters, the username and password. Useful only if there is a username and password setting in - the XMLRPC configuration block. If there is, clients wanting to execute RPC calls must login first using this. +Currently there are 5 supported XMLRPC calls, provided by m_xmlrpc_main: checkAuthetication - Takes two parameters, an account name and a password. Checks if the account name is valid and the password is correct for the account name, useful for making login pages on websites. @@ -20,8 +17,9 @@ channel - Takes one parameter, a channel name, and returns real time information user - Takes one parameter, a user name, and returns real time information regarding that user. -XMLRPC was designed to be used with m_mysql and db_mysql, and will not return any information that can be pulled from the SQL -database, such as accounts and registered channel information. For examples on how to use these calls in PHP, see xmlrpc.php in docs/XMLRPC for an example PHP class. +XMLRPC was designed to be used with db_mysql, and will not return any information that can be pulled from the SQL +database, such as accounts and registered channel information. It is instead used for pulling realtime data such +as users and channels currently onlive. For examples on how to use these calls in PHP, see xmlrpc.php in docs/XMLRPC. Also note that the parameter named "id" is reserved for query ID. If you pass a query to Anope containing a value for id. it will be stored by Anope and the same id will be passed back in the result. diff --git a/docs/XMLRPC/xmlrpc.php b/docs/XMLRPC/xmlrpc.php index c75319259..cffc23a0c 100644 --- a/docs/XMLRPC/xmlrpc.php +++ b/docs/XMLRPC/xmlrpc.php @@ -1,5 +1,4 @@ <?php - /* XMLRPC Functions * * (C) 2003-2011 Anope Team @@ -9,29 +8,21 @@ class AnopeXMLRPC { - private $Host, $Bind, $Port, $Username, $Pass; + private $Host, $Bind, $Port; private $Socket; - function __construct($Host, $Port, $Bind = NULL, $Username = NULL, $Pass = NULL) + function __construct($Host, $Port, $Bind = NULL) { $this->Host = $Host; $this->Port = $Port; $this->Bind = $Bind; - $this->Username = $Username; - $this->Pass = $Pass; $this->Socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); if ($Bind && socket_bind($this->Socket, $this->Bind) == false) $his->Socket = false; if (socket_connect($this->Socket, $this->Host, $this->Port) == false) $this->Socket = false; - - if ($Username && $Pass) - { - /* Login to XMLRPC, if required */ - $this->RunXMLRPC("login", array($Username, $Pass)); - } } function __destruct() @@ -52,10 +43,11 @@ class AnopeXMLRPC socket_write($this->Socket, $xmlquery); $inbuf = socket_read($this->Socket, 4096); - $inxmlrpc = xmlrpc_decode($inbuf); + $inbuf = substr($inbuf, strpos($inbuf, "\r\n\r\n") + 4); + $response = xmlrpc_decode($inbuf); - if (isset($inxmlrpc[0])) - return $inxmlrpc[0]; + if (isset($response[0])) + return $response[0]; return NULL; } diff --git a/modules/extra/m_xmlrpc.cpp b/modules/extra/m_xmlrpc.cpp index b345ce183..db1242970 100644 --- a/modules/extra/m_xmlrpc.cpp +++ b/modules/extra/m_xmlrpc.cpp @@ -4,15 +4,20 @@ class MyXMLRPCClientSocket : public XMLRPCClientSocket { + /* Used to skip the (optional) HTTP header, which we really don't care about */ + bool in_query; public: - MyXMLRPCClientSocket(XMLRPCListenSocket *ls, int fd, const sockaddrs &addr) : XMLRPCClientSocket(ls, fd, addr) + MyXMLRPCClientSocket(XMLRPCListenSocket *ls, int fd, const sockaddrs &addr) : XMLRPCClientSocket(ls, fd, addr), in_query(false) { - if (ls->username.empty() && ls->password.empty()) - this->logged_in = true; } bool Read(const Anope::string &message) { + if (message.find("xml version") != Anope::string::npos) + this->in_query = true; + else if (!this->in_query) + return true; + this->query += message; Log(LOG_DEBUG) << "m_xmlrpc: " << message; @@ -20,8 +25,8 @@ class MyXMLRPCClientSocket : public XMLRPCClientSocket { Log(LOG_DEBUG) << "m_xmlrpc: Processing message"; this->HandleMessage(); - this->query.clear(); } + return true; } @@ -85,13 +90,29 @@ class MyXMLRPCListenSocket : public XMLRPCListenSocket ClientSocket *OnAccept(int fd, const sockaddrs &addr) { MyXMLRPCClientSocket *socket = new MyXMLRPCClientSocket(this, fd, addr); - if (std::find(this->allowed.begin(), this->allowed.end(), addr.addr()) != this->allowed.end()) - Log() << "m_xmlrpc: Accepted connection " << fd << " from " << addr.addr(); - else + + socket->SetFlag(SF_DEAD); + for (unsigned i = 0, j = this->allowed.size(); i < j; ++i) { - Log() << "m_xmlrpc: Dropping disallowed connection " << fd << " from " << addr.addr(); - socket->SetFlag(SF_DEAD); + try + { + cidr cidr_mask(this->allowed[i]); + if (cidr_mask.match(socket->clientaddr)) + { + Log() << "m_xmlrpc: Accepted connection " << fd << " from " << addr.addr(); + socket->UnsetFlag(SF_DEAD); + break; + } + } + catch (const SocketException &ex) + { + Log() << "m_xmlrpc: Error checking incoming connection against mask " << this->allowed[i] << ": " << ex.GetReason(); + } } + + if (socket->HasFlag(SF_DEAD)) + Log() << "m_xmlrpc: Dropping disallowed connection " << fd << " from " << addr.addr(); + return socket; } }; @@ -127,8 +148,17 @@ class MyXMLRPCServiceInterface : public XMLRPCServiceInterface reply += "<member>\n<name>" + it->first + "</name>\n<value>\n<string>" + this->Sanitize(it->second) + "</string>\n</value>\n</member>\n"; } reply += "</struct>\n</value>\n</param>\n</params>\n</methodCall>"; + + source->Write("HTTP/1.1 200 OK"); + source->Write("Connection: close"); + source->Write("Content-Type: text/xml"); + source->Write("Content-Length: " + stringify(reply.length())); + source->Write("Server: Anope IRC Services version " + Anope::VersionShort()); + source->Write(""); source->Write(reply); + + Log(LOG_DEBUG) << reply; } Anope::string Sanitize(const Anope::string &string) @@ -149,9 +179,9 @@ class MyXMLRPCServiceInterface : public XMLRPCServiceInterface special_chars("\n", "
"), special_chars("\002", ""), // bold special_chars("\003", ""), // color - special_chars("\35", ""), // italics - special_chars("\031", ""), // underline - special_chars("\26", ""), // reverses + special_chars("\035", ""), // italics + special_chars("\037", ""), // underline + special_chars("\026", ""), // reverses special_chars("", "") }; @@ -198,6 +228,23 @@ class ModuleXMLRPC : public Module ~ModuleXMLRPC() { + /* Clean up our sockets and our listening sockets */ + for (std::map<int, Socket *>::const_iterator it = SocketEngine->Sockets.begin(), it_end = SocketEngine->Sockets.end(); it != it_end; ++it) + { + Socket *s = it->second; + + if (s->Type == SOCKTYPE_CLIENT) + { + ClientSocket *cs = debug_cast<ClientSocket *>(s); + for (unsigned i = 0; i < this->listen_sockets.size(); ++i) + if (cs->LS == this->listen_sockets[i]) + { + delete cs; + break; + } + } + } + for (unsigned i = 0; i < this->listen_sockets.size(); ++i) delete this->listen_sockets[i]; this->listen_sockets.clear(); @@ -267,8 +314,7 @@ void MyXMLRPCClientSocket::HandleMessage() request.data.push_back(data); } - if (request.name == "login" || this->logged_in) - me->xmlrpcinterface.RunXMLRPC(this, &request); + me->xmlrpcinterface.RunXMLRPC(this, &request); } MODULE_INIT(ModuleXMLRPC) diff --git a/modules/extra/m_xmlrpc_main.cpp b/modules/extra/m_xmlrpc_main.cpp index 4efe230ad..33cf3818c 100644 --- a/modules/extra/m_xmlrpc_main.cpp +++ b/modules/extra/m_xmlrpc_main.cpp @@ -45,9 +45,7 @@ class MyXMLRPCEvent : public XMLRPCEvent public: void Run(XMLRPCServiceInterface *iface, XMLRPCClientSocket *source, XMLRPCRequest *request) { - if (request->name == "login") - this->DoLogin(iface, source, request); - else if (request->name == "command") + if (request->name == "command") this->DoCommand(iface, source, request); else if (request->name == "checkAuthentication") this->DoCheckAuthentication(iface, source, request); @@ -102,29 +100,6 @@ class MyXMLRPCEvent : public XMLRPCEvent } } - void DoLogin(XMLRPCServiceInterface *iface, XMLRPCClientSocket *source, XMLRPCRequest *request) - { - if (source->logged_in) - request->reply("result", "Logged in"); - else - { - XMLRPCListenSocket *ls = static_cast<XMLRPCListenSocket *>(source->LS); - - if (ls->username.empty() && ls->password.empty()) - { - request->reply("result", "Logged in"); - source->logged_in = true; - } - else if (request->data.size() > 1 && request->data[0] == ls->username && request->data[1] == ls->password) - { - request->reply("result", "Logged in"); - source->logged_in = true; - } - else - request->reply("error", "Invalid credentials"); - } - } - void DoCheckAuthentication(XMLRPCServiceInterface *iface, XMLRPCClientSocket *source, XMLRPCRequest *request) { Anope::string username = request->data.size() > 0 ? request->data[0] : ""; diff --git a/modules/extra/xmlrpc.h b/modules/extra/xmlrpc.h index 004d6aef5..38f548c4f 100644 --- a/modules/extra/xmlrpc.h +++ b/modules/extra/xmlrpc.h @@ -9,9 +9,7 @@ class XMLRPCClientSocket : public ClientSocket Anope::string query; public: - bool logged_in; - - XMLRPCClientSocket(ListenSocket *ls, int fd, const sockaddrs &addr) : ClientSocket(ls, fd, addr), logged_in(false) { } + XMLRPCClientSocket(ListenSocket *ls, int fd, const sockaddrs &addr) : ClientSocket(ls, fd, addr) { } virtual ~XMLRPCClientSocket() { } |