summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNils Maier <maierman@web.de>2014-05-17 17:31:21 +0200
committerNils Maier <maierman@web.de>2014-05-20 12:53:39 +0200
commit855dfa0e2f8ca7869d28d2afc21fed2e3790549a (patch)
treee156bebeee259fa0213611a54d3ed169c1c04ad7 /src
parent88b61f2eb97faa5fad1a0dd882ef1d1ade48c8df (diff)
Authorize RPC multicalls only once.
Cache the auth status afterwards and just assume the token still matches (within the same request, of course).
Diffstat (limited to 'src')
-rw-r--r--src/HttpServerBodyCommand.cc13
-rw-r--r--src/RpcMethod.cc4
-rw-r--r--src/RpcMethodImpl.cc12
-rw-r--r--src/RpcRequest.cc7
-rw-r--r--src/RpcRequest.h7
-rw-r--r--src/WebSocketSession.cc15
-rw-r--r--src/rpc_helper.cc8
-rw-r--r--src/rpc_helper.h6
8 files changed, 53 insertions, 19 deletions
diff --git a/src/HttpServerBodyCommand.cc b/src/HttpServerBodyCommand.cc
index 6c0b58e0..8479f3f8 100644
--- a/src/HttpServerBodyCommand.cc
+++ b/src/HttpServerBodyCommand.cc
@@ -243,6 +243,7 @@ bool HttpServerBodyCommand::execute()
case RPC_TYPE_JSONP: {
std::string callback;
std::unique_ptr<ValueBase> json;
+ auto preauthorized = rpc::RpcRequest::MUST_AUTHORIZE;
ssize_t error = 0;
if(httpServer_->getRequestType() == RPC_TYPE_JSONP) {
json::JsonGetParam param = json::decodeGetParams(query);
@@ -273,7 +274,8 @@ bool HttpServerBodyCommand::execute()
}
Dict* jsondict = downcast<Dict>(json);
if(jsondict) {
- rpc::RpcResponse res = rpc::processJsonRpcRequest(jsondict, e_);
+ rpc::RpcResponse res =
+ rpc::processJsonRpcRequest(jsondict, e_, preauthorized);
sendJsonRpcResponse(res, callback);
} else {
List* jsonlist = downcast<List>(json);
@@ -283,8 +285,13 @@ bool HttpServerBodyCommand::execute()
for(List::ValueType::const_iterator i = jsonlist->begin(),
eoi = jsonlist->end(); i != eoi; ++i) {
Dict* jsondict = downcast<Dict>(*i);
- if(jsondict) {
- results.push_back(rpc::processJsonRpcRequest(jsondict, e_));
+ if (jsondict) {
+ auto resp =
+ rpc::processJsonRpcRequest(jsondict, e_, preauthorized);
+ if (resp.code == 0) {
+ preauthorized = rpc::RpcRequest::PREAUTHORIZED;
+ }
+ results.push_back(std::move(resp));
}
}
sendJsonRpcBatchResponse(results, callback);
diff --git a/src/RpcMethod.cc b/src/RpcMethod.cc
index 1f7ea20b..ec424300 100644
--- a/src/RpcMethod.cc
+++ b/src/RpcMethod.cc
@@ -85,9 +85,11 @@ void RpcMethod::authorize(RpcRequest& req, DownloadEngine* e)
}
}
}
- if (!e || !e->validateToken(token)) {
+ if (!e || (req.authorization != RpcRequest::PREAUTHORIZED &&
+ !e->validateToken(token))) {
throw DL_ABORT_EX("Unauthorized");
}
+ req.authorization = RpcRequest::PREAUTHORIZED;
}
RpcResponse RpcMethod::execute(RpcRequest req, DownloadEngine* e)
diff --git a/src/RpcMethodImpl.cc b/src/RpcMethodImpl.cc
index 0ecf9f3e..91d5a2ed 100644
--- a/src/RpcMethodImpl.cc
+++ b/src/RpcMethodImpl.cc
@@ -1361,6 +1361,7 @@ std::unique_ptr<ValueBase> SystemMulticallRpcMethod::process
{
const List* methodSpecs = checkRequiredParam<List>(req, 0);
auto list = List::g();
+ auto auth = RpcRequest::MUST_AUTHORIZE;
for(auto & methodSpec : *methodSpecs) {
Dict* methodDict = downcast<Dict>(methodSpec);
if(!methodDict) {
@@ -1388,12 +1389,19 @@ std::unique_ptr<ValueBase> SystemMulticallRpcMethod::process
} else {
paramsList = List::g();
}
- RpcResponse res = getMethod(methodName->s())->execute
- ({methodName->s(), std::move(paramsList), nullptr, req.jsonRpc}, e);
+ RpcRequest r = {
+ methodName->s(),
+ std::move(paramsList),
+ nullptr,
+ auth,
+ req.jsonRpc
+ };
+ RpcResponse res = getMethod(methodName->s())->execute(std::move(r), e);
if(res.code == 0) {
auto l = List::g();
l->append(std::move(res.param));
list->append(std::move(l));
+ auth = RpcRequest::PREAUTHORIZED;
} else {
list->append(std::move(res.param));
}
diff --git a/src/RpcRequest.cc b/src/RpcRequest.cc
index c9b531f7..62dae2c7 100644
--- a/src/RpcRequest.cc
+++ b/src/RpcRequest.cc
@@ -39,21 +39,22 @@ namespace aria2 {
namespace rpc {
RpcRequest::RpcRequest()
- : jsonRpc{false}
+ : authorization{RpcRequest::MUST_AUTHORIZE}, jsonRpc{false}
{}
RpcRequest::RpcRequest(std::string methodName,
std::unique_ptr<List> params)
: methodName{std::move(methodName)}, params{std::move(params)},
- jsonRpc{false}
+ authorization{RpcRequest::MUST_AUTHORIZE}, jsonRpc{false}
{}
RpcRequest::RpcRequest(std::string methodName,
std::unique_ptr<List> params,
std::unique_ptr<ValueBase> id,
+ RpcRequest::authorization_t authorization,
bool jsonRpc)
: methodName{std::move(methodName)}, params{std::move(params)},
- id{std::move(id)}, jsonRpc{jsonRpc}
+ id{std::move(id)}, authorization{authorization}, jsonRpc{jsonRpc}
{}
} // namespace rpc
diff --git a/src/RpcRequest.h b/src/RpcRequest.h
index 87169c2d..c06e4424 100644
--- a/src/RpcRequest.h
+++ b/src/RpcRequest.h
@@ -46,9 +46,15 @@ namespace aria2 {
namespace rpc {
struct RpcRequest {
+ enum authorization_t {
+ MUST_AUTHORIZE,
+ PREAUTHORIZED
+ };
+
std::string methodName;
std::unique_ptr<List> params;
std::unique_ptr<ValueBase> id;
+ authorization_t authorization;
bool jsonRpc;
RpcRequest();
@@ -59,6 +65,7 @@ struct RpcRequest {
RpcRequest(std::string methodName,
std::unique_ptr<List> params,
std::unique_ptr<ValueBase> id,
+ authorization_t authorization,
bool jsonRpc = false);
};
diff --git a/src/WebSocketSession.cc b/src/WebSocketSession.cc
index 86fb08d2..aced5622 100644
--- a/src/WebSocketSession.cc
+++ b/src/WebSocketSession.cc
@@ -161,6 +161,7 @@ void onMsgRecvCallback(wslay_event_context_ptr wsctx,
// TODO Only process text frame
ssize_t error = 0;
auto json = wsSession->parseFinal(nullptr, 0, error);
+ auto preauthorized = RpcRequest::MUST_AUTHORIZE;
if(error < 0) {
A2_LOG_INFO("Failed to parse JSON-RPC request");
RpcResponse res
@@ -169,9 +170,10 @@ void onMsgRecvCallback(wslay_event_context_ptr wsctx,
return;
}
Dict* jsondict = downcast<Dict>(json);
+ auto e = wsSession->getDownloadEngine();
if(jsondict) {
- RpcResponse res = processJsonRpcRequest(jsondict,
- wsSession->getDownloadEngine());
+ RpcResponse res =
+ processJsonRpcRequest(jsondict, e, preauthorized);
addResponse(wsSession, res);
} else {
List* jsonlist = downcast<List>(json);
@@ -181,9 +183,12 @@ void onMsgRecvCallback(wslay_event_context_ptr wsctx,
for(List::ValueType::const_iterator i = jsonlist->begin(),
eoi = jsonlist->end(); i != eoi; ++i) {
Dict* jsondict = downcast<Dict>(*i);
- if(jsondict) {
- results.push_back(processJsonRpcRequest
- (jsondict, wsSession->getDownloadEngine()));
+ if (jsondict) {
+ auto resp = processJsonRpcRequest(jsondict, e, preauthorized);
+ if (resp.code == 0) {
+ preauthorized = RpcRequest::PREAUTHORIZED;
+ }
+ results.push_back(std::move(resp));
}
}
addResponse(wsSession, results);
diff --git a/src/rpc_helper.cc b/src/rpc_helper.cc
index d88ae529..a4c840e3 100644
--- a/src/rpc_helper.cc
+++ b/src/rpc_helper.cc
@@ -76,7 +76,8 @@ RpcResponse createJsonRpcErrorResponse(int code,
return rpc::RpcResponse{code, std::move(params), std::move(id)};
}
-RpcResponse processJsonRpcRequest(Dict* jsondict, DownloadEngine* e)
+RpcResponse processJsonRpcRequest(Dict* jsondict, DownloadEngine* e,
+ RpcRequest::authorization_t authorization)
{
auto id = jsondict->popValue("id");
if(!id) {
@@ -99,8 +100,9 @@ RpcResponse processJsonRpcRequest(Dict* jsondict, DownloadEngine* e)
std::move(id));
}
A2_LOG_INFO(fmt("Executing RPC method %s", methodName->s().c_str()));
- return getMethod(methodName->s())->execute
- ({methodName->s(), std::move(params), std::move(id), true}, e);
+ RpcRequest req =
+ {methodName->s(), std::move(params), std::move(id), authorization, true};
+ return getMethod(methodName->s())->execute(std::move(req), e);
}
} // namespace rpc
diff --git a/src/rpc_helper.h b/src/rpc_helper.h
index a1658af6..1b7f036f 100644
--- a/src/rpc_helper.h
+++ b/src/rpc_helper.h
@@ -41,6 +41,8 @@
#include <string>
#include <memory>
+#include "RpcRequest.h"
+
namespace aria2 {
class ValueBase;
@@ -49,7 +51,6 @@ class DownloadEngine;
namespace rpc {
-struct RpcRequest;
struct RpcResponse;
#ifdef ENABLE_XML_RPC
@@ -63,7 +64,8 @@ RpcResponse createJsonRpcErrorResponse(int code,
std::unique_ptr<ValueBase> id);
// Processes JSON-RPC request |jsondict| and returns the result.
-RpcResponse processJsonRpcRequest(Dict* jsondict, DownloadEngine* e);
+RpcResponse processJsonRpcRequest(Dict* jsondict, DownloadEngine* e,
+ RpcRequest::authorization_t authorization);
} // namespace rpc