summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2011-03-22 23:58:53 -0400
committerAdam <Adam@anope.org>2011-03-22 23:58:53 -0400
commit451fb82e544fda19888c4d5bc250431a3197cef6 (patch)
treea41599e56a43f42d37bc6481fbb86f15b2d42d6b
parentc02d51f52348758487223856e716261a734af8fc (diff)
Bug #1203
-rw-r--r--data/example.conf14
-rw-r--r--docs/XMLRPC/XMLRPC10
-rw-r--r--docs/XMLRPC/xmlrpc.php20
-rw-r--r--modules/extra/m_xmlrpc.cpp74
-rw-r--r--modules/extra/m_xmlrpc_main.cpp27
-rw-r--r--modules/extra/xmlrpc.h4
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", "&#xA;"),
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() { }