2009-05-10 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

Added BASIC authentication for XML-RPC. Added --xml-rpc-user and
	--xml-rpc-passwd option.
	* src/HttpServer.cc
	* src/HttpServer.h
	* src/HttpServerCommand.cc
	* src/OptionHandlerFactory.cc
	* src/prefs.cc
	* src/prefs.h
	* src/usage_text.h
pull/1/head
Tatsuhiro Tsujikawa 2009-05-09 15:38:23 +00:00
parent d237c5e442
commit 7aefbb7338
8 changed files with 112 additions and 3 deletions

View File

@ -1,3 +1,15 @@
2009-05-10 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Added BASIC authentication for XML-RPC. Added --xml-rpc-user and
--xml-rpc-passwd option.
* src/HttpServer.cc
* src/HttpServer.h
* src/HttpServerCommand.cc
* src/OptionHandlerFactory.cc
* src/prefs.cc
* src/prefs.h
* src/usage_text.h
2009-05-10 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Fixed the bug that SocketCore::isReadable() prevents aria2 from

View File

@ -44,6 +44,7 @@
#include "Util.h"
#include "LogFactory.h"
#include "Logger.h"
#include "Base64.h"
namespace aria2 {
@ -133,13 +134,28 @@ bool HttpServer::supportsPersistentConnection() const
void HttpServer::feedResponse(const std::string& text, const std::string& contentType)
{
std::string header = "HTTP/1.1 200 OK\r\n"
feedResponse("200 OK", "", text, contentType);
}
void HttpServer::feedResponse(const std::string& status,
const std::string& headers,
const std::string& text,
const std::string& contentType)
{
std::string header = "HTTP/1.1 "+status+"\r\n"
"Content-Type: "+contentType+"\r\n"
"Content-Length: "+Util::uitos(text.size())+"\r\n";
if(!supportsPersistentConnection()) {
header += "Connection: close\r\n";
}
if(!headers.empty()) {
header += headers;
if(!Util::endsWith(headers, "\r\n")) {
header += "\r\n";
}
}
header += "\r\n";
_logger->debug("HTTP Server sends response:\n%s", header.c_str());
@ -158,4 +174,23 @@ bool HttpServer::sendBufferIsEmpty() const
return _socketBuffer.sendBufferIsEmpty();
}
bool HttpServer::authenticate()
{
if(_username.empty()) {
return true;
}
std::string authHeader = _lastRequestHeader->getFirst("Authorization");
if(authHeader.empty()) {
return false;
}
std::pair<std::string, std::string> p = Util::split(authHeader, " ");
if(p.first != "Basic") {
return false;
}
std::string userpass = Base64::decode(p.second);
std::pair<std::string, std::string> userpassPair = Util::split(userpass, ":");
return _username == userpassPair.first && _password == userpassPair.second;
}
} // namespace aria2

View File

@ -62,6 +62,8 @@ private:
uint64_t _lastContentLength;
std::stringstream _lastBody;
bool _keepAlive;
std::string _username;
std::string _password;
public:
HttpServer(const SharedHandle<SocketCore>& socket, DownloadEngine* e);
@ -77,6 +79,20 @@ public:
void feedResponse(const std::string& text, const std::string& contentType);
void feedResponse(const std::string& status,
const std::string& headers,
const std::string& text,
const std::string& contentType);
bool authenticate();
void setUsernamePassword
(const std::string& username, const std::string& password)
{
_username = username;
_password = password;
}
ssize_t sendResponse();
bool sendBufferIsEmpty() const;
@ -86,6 +102,8 @@ public:
void enableKeepAlive() { _keepAlive = true; }
void disableKeepAlive() { _keepAlive = false; }
uint64_t getContentLength() const { return _lastContentLength; }
};
} // namespace aria2

View File

@ -41,7 +41,10 @@
#include "RequestGroup.h"
#include "RequestGroupMan.h"
#include "HttpServerBodyCommand.h"
#include "HttpServerResponseCommand.h"
#include "RecoverableException.h"
#include "prefs.h"
#include "Option.h"
namespace aria2 {
@ -53,6 +56,8 @@ HttpServerCommand::HttpServerCommand(int32_t cuid, DownloadEngine* e,
_httpServer(new HttpServer(socket, e))
{
_e->addSocketForReadCheck(_socket, this);
_httpServer->setUsernamePassword(_e->option->get(PREF_XML_RPC_USER),
_e->option->get(PREF_XML_RPC_PASSWD));
}
HttpServerCommand::HttpServerCommand(int32_t cuid,
@ -87,6 +92,18 @@ bool HttpServerCommand::execute()
e, cuid);
return true;
}
if(!_httpServer->authenticate()) {
_httpServer->disableKeepAlive();
_httpServer->feedResponse("401 Unauthorized",
"WWW-Authenticate: Basic realm=\"aria2\"",
"","text/html");
Command* command =
new HttpServerResponseCommand(cuid, _httpServer, _e, _socket);
command->setStatus(Command::STATUS_ONESHOT_REALTIME);
_e->commands.push_back(command);
_e->setNoWait(true);
return true;
}
if(header.isNull()) {
_e->commands.push_back(this);
return false;

View File

@ -364,6 +364,20 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
op->addTag(TAG_ADVANCED);
handlers.push_back(op);
}
{
SharedHandle<OptionHandler> op(new DefaultOptionHandler
(PREF_XML_RPC_USER,
TEXT_XML_RPC_USER));
op->addTag(TAG_ADVANCED);
handlers.push_back(op);
}
{
SharedHandle<OptionHandler> op(new DefaultOptionHandler
(PREF_XML_RPC_PASSWD,
TEXT_XML_RPC_PASSWD));
op->addTag(TAG_ADVANCED);
handlers.push_back(op);
}
#endif // ENABLE_XML_RPC
// HTTP/FTP options
{

View File

@ -163,6 +163,10 @@ const std::string PREF_RESET_URI("reset-uri");
const std::string PREF_DRY_RUN("dry-run");
// value: true | false
const std::string PREF_REUSE_URI("reuse-uri");
// value: string
const std::string PREF_XML_RPC_USER("xml-rpc-user");
// value: string
const std::string PREF_XML_RPC_PASSWD("xml-rpc-passwd");
/**
* FTP related preferences

View File

@ -167,6 +167,10 @@ extern const std::string PREF_RESET_URI;
extern const std::string PREF_DRY_RUN;
// value: true | false
extern const std::string PREF_REUSE_URI;
// value: string
extern const std::string PREF_XML_RPC_USER;
// value: string
extern const std::string PREF_XML_RPC_PASSWD;
/**
* FTP related preferences

View File

@ -481,10 +481,15 @@ _(" --event-poll=POLL Specify the method for polling events.")
#define TEXT_XML_RPC_LISTEN_PORT \
_(" --xml-rpc-listen-port=PORT Specify a port number for XML-RPC server to listen\n"\
" to.")
// Excluded from translation candidiates because it is subject to change.
#define TEXT_ENABLE_XML_RPC \
_(" --enable-xml-rpc[=true|false] Enable XML-RPC server.\n"\
" See also --xml-rpc-listen-port option.")
" It is strongly recommended to set username and\n"\
" password using --xml-rpc-user and --xml-rpc-passwd\n"\
" option. See also --xml-rpc-listen-port option.")
#define TEXT_XML_RPC_USER \
_(" --xml-rpc-user=USER Set XML-RPC user.")
#define TEXT_XML_RPC_PASSWD \
_(" --xml-rpc-passwd=PASSWD Set XML-RPC password.")
#define TEXT_BT_EXTERNAL_IP \
_(" --bt-external-ip=IPADDRESS Specify the external IP address to report to a\n"\
" BitTorrent tracker. Although this function is\n"\