| 195 | } |
| 196 | |
| 197 | static void HTTPReq_JSONRPC(const std::any& context, HTTPRequest* req) |
| 198 | { |
| 199 | // JSONRPC handles only POST |
| 200 | if (req->GetRequestMethod() != HTTPRequestMethod::POST) { |
| 201 | req->WriteReply(HTTP_BAD_METHOD, "JSONRPC server handles only POST requests"); |
| 202 | return; |
| 203 | } |
| 204 | // Check authorization |
| 205 | std::pair<bool, std::string> authHeader = req->GetHeader("authorization"); |
| 206 | if (!authHeader.first) { |
| 207 | req->WriteHeader("WWW-Authenticate", WWW_AUTH_HEADER_DATA); |
| 208 | req->WriteReply(HTTP_UNAUTHORIZED); |
| 209 | return; |
| 210 | } |
| 211 | |
| 212 | JSONRPCRequest jreq; |
| 213 | jreq.context = context; |
| 214 | jreq.peerAddr = req->GetPeer().ToStringAddrPort(); |
| 215 | jreq.URI = req->GetURI(); |
| 216 | if (!RPCAuthorized(authHeader.second, jreq.authUser)) { |
| 217 | LogWarning("ThreadRPCServer incorrect password attempt from %s", jreq.peerAddr); |
| 218 | |
| 219 | /* Deter brute-forcing |
| 220 | If this results in a DoS the user really |
| 221 | shouldn't have their RPC port exposed. */ |
| 222 | UninterruptibleSleep(std::chrono::milliseconds{250}); |
| 223 | |
| 224 | req->WriteHeader("WWW-Authenticate", WWW_AUTH_HEADER_DATA); |
| 225 | req->WriteReply(HTTP_UNAUTHORIZED); |
| 226 | return; |
| 227 | } |
| 228 | |
| 229 | // Generate reply |
| 230 | HTTPStatusCode status; |
| 231 | UniValue reply; |
| 232 | UniValue request; |
| 233 | if (request.read(req->ReadBody())) { |
| 234 | reply = ExecuteHTTPRPC(request, jreq, status); |
| 235 | } else { |
| 236 | reply = JSONErrorReply(JSONRPCError(RPC_PARSE_ERROR, "Parse error"), jreq, status); |
| 237 | } |
| 238 | |
| 239 | // Write reply |
| 240 | if (reply.isNull()) { |
| 241 | // Error case or no-content notification reply. |
| 242 | req->WriteReply(status); |
| 243 | } else { |
| 244 | req->WriteHeader("Content-Type", "application/json"); |
| 245 | req->WriteReply(status, reply.write() + "\n"); |
| 246 | } |
| 247 | } |
| 248 | |
| 249 | static bool InitRPCAuthentication() |
| 250 | { |
no test coverage detected