diff --git a/llarp/config/config.cpp b/llarp/config/config.cpp index c195753c10..fc021187bb 100644 --- a/llarp/config/config.cpp +++ b/llarp/config/config.cpp @@ -1,6 +1,7 @@ #include "config.hpp" #include "definition.hpp" #include "ini.hpp" +#include "oxenmq/address.h" #include #include @@ -1130,8 +1131,6 @@ namespace llarp "Determines whether or not the LMQ JSON API is enabled. Defaults ", }); - conf.defineOption(); - conf.defineOption( "api", "bind", @@ -1154,10 +1153,45 @@ namespace llarp "Recommend localhost-only for security purposes.", }); - conf.defineOption("api", "authkey", Deprecated); + conf.defineOption( + "api", + "bind_curve", + Default{""}, + MultiValue, + [this](std::string arg) mutable { + if (arg.empty()) + return; + + auto pipe = arg.find("|"); + + if (pipe == arg.npos) + throw std::invalid_argument( + "Addresses and whitelisted pubkeys must be pipe-delimited key:value pairs"); - // TODO: this was from pre-refactor: - // TODO: add pubkey to whitelist + auto key = arg.substr(0, pipe), values = arg.substr(pipe + 1, arg.npos); + + if (not starts_with(key, "tcp://")) + key = "tcp://" + key; + + auto pubkeys = split(values, ",", true); + + for (auto& pk : pubkeys) + m_rpcEncryptedAddresses[oxenmq::address{key}].emplace(pk); + }, + Comment{ + "Specify encrypted listener addresses and comma-delimited public keys to be accepted ", + "by exposed encrypted listener. Keys must be attached to a listener address.", + "", + "Example: ", + " bind_curve=tcp://0.0.0.0:1234|pubkeyA,pubkeyB", + " bind_curve=tcp://0.0.0.0:5678|pubkeyC,pubkeyD", + "", + "In the given example above, port 1234 is only accessible by whitelisted ", + "pubkeys A and B, while 5678 is accessible by C and D.", + "", + "Note: tcp addresses passed without \"tcp://\" prefix will have it prepended"}); + + conf.defineOption("api", "authkey", Deprecated); } void diff --git a/llarp/config/config.hpp b/llarp/config/config.hpp index 3165f03543..5e9284795d 100644 --- a/llarp/config/config.hpp +++ b/llarp/config/config.hpp @@ -1,6 +1,7 @@ #pragma once #include "ini.hpp" #include "definition.hpp" +#include "oxenmq/auth.h" #include @@ -26,6 +27,7 @@ #include #include #include +#include #include @@ -190,6 +192,7 @@ namespace llarp { bool m_enableRPCServer = false; std::vector m_rpcBindAddresses; + std::unordered_map> m_rpcEncryptedAddresses; void defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params); diff --git a/llarp/rpc/rpc_server.cpp b/llarp/rpc/rpc_server.cpp index 3cc05e8dbc..8102fa3640 100644 --- a/llarp/rpc/rpc_server.cpp +++ b/llarp/rpc/rpc_server.cpp @@ -13,6 +13,9 @@ #include #include #include +#include +#include "llarp/util/logging.hpp" +#include "oxenmq/auth.h" #include namespace @@ -31,6 +34,17 @@ namespace llarp::rpc LogInfo("Bound RPC server to ", addr.full_address()); } + for (const auto& [address, allowed_keys] : r->GetConfig()->api.m_rpcEncryptedAddresses) + { + m_LMQ->listen_curve(address.zmq_address(), [allowed_keys = allowed_keys](auto pk, ...) { + if (std::find(allowed_keys.begin(), allowed_keys.end(), pk) != allowed_keys.end()) + return oxenmq::AuthLevel::admin; + + LogInfo("Curve pubkey not found in whitelist"); + return oxenmq::AuthLevel::denied; + }); + } + this->AddRPCCategories(); } @@ -117,7 +131,7 @@ namespace llarp::rpc { return r->exitContext().GetExitEndpoint(name); } - + return r->hiddenServiceContext().GetEndpointByName(name); } @@ -410,7 +424,7 @@ namespace llarp::rpc { if (itr->is_array()) { - for (auto & kill_itr : *itr) + for (auto& kill_itr : *itr) { if (kill_itr.is_string()) kills.emplace(kill_itr.get());