From 802ad46df1e7da2195b6930e47a9435ead66bebf Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 30 Jan 2023 07:43:58 -0800 Subject: [PATCH 1/3] Encrypted pubkey for listening ports: - created option to add encrypted listeners with paired pubkeys in unordered_map, plus access verification - pubkeys stored in unordered set, changed lambda for listen_curve - pubkeys are comma-delimited and paired with bind address in config file --- llarp/config/config.cpp | 42 ++++++++++++++++++++++++++++++++++++++--- llarp/config/config.hpp | 4 +++- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/llarp/config/config.cpp b/llarp/config/config.cpp index eda628dda0..19526fde62 100644 --- a/llarp/config/config.cpp +++ b/llarp/config/config.cpp @@ -2,6 +2,7 @@ #include "definition.hpp" #include "ini.hpp" +#include #include #include #include @@ -1152,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"); + + auto key = arg.substr(0, pipe), values = arg.substr(pipe + 1, arg.npos); - // TODO: this was from pre-refactor: - // TODO: add pubkey to whitelist + 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..5b18636df8 100644 --- a/llarp/config/config.hpp +++ b/llarp/config/config.hpp @@ -2,8 +2,8 @@ #include "ini.hpp" #include "definition.hpp" +#include #include - #include #include #include @@ -26,6 +26,7 @@ #include #include #include +#include #include @@ -190,6 +191,7 @@ namespace llarp { bool m_enableRPCServer = false; std::vector m_rpcBindAddresses; + std::unordered_map> m_rpcEncryptedAddresses; void defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params); From c9c37c874b2b3ee13d2b82e0c74222ea846e0daf Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 14 Feb 2023 08:50:57 -0800 Subject: [PATCH 2/3] adding code that disappeared during sequential rebasing and squashing --- llarp/rpc/rpc_server.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/llarp/rpc/rpc_server.cpp b/llarp/rpc/rpc_server.cpp index 746557f63e..b33c8448e8 100644 --- a/llarp/rpc/rpc_server.cpp +++ b/llarp/rpc/rpc_server.cpp @@ -109,6 +109,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; + }); + } + AddCategories(); } From 29180a32a7ca8c8bbf964eede7fef7d2408443f4 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 14 Feb 2023 08:53:18 -0800 Subject: [PATCH 3/3] updated pk emplace loop to pre-parse key addr - error logging update to newer log::warning --- llarp/config/config.cpp | 4 +++- llarp/rpc/rpc_server.cpp | 22 ++++++++++++++-------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/llarp/config/config.cpp b/llarp/config/config.cpp index 19526fde62..a1f84f8893 100644 --- a/llarp/config/config.cpp +++ b/llarp/config/config.cpp @@ -3,6 +3,7 @@ #include "ini.hpp" #include +#include #include #include #include @@ -1174,9 +1175,10 @@ namespace llarp key = "tcp://" + key; auto pubkeys = split(values, ",", true); + oxenmq::address key_addr{key}; for (auto& pk : pubkeys) - m_rpcEncryptedAddresses[oxenmq::address{key}].emplace(pk); + m_rpcEncryptedAddresses[key_addr].emplace(pk); }, Comment{ "Specify encrypted listener addresses and comma-delimited public keys to be accepted ", diff --git a/llarp/rpc/rpc_server.cpp b/llarp/rpc/rpc_server.cpp index b33c8448e8..d3a56d18d1 100644 --- a/llarp/rpc/rpc_server.cpp +++ b/llarp/rpc/rpc_server.cpp @@ -1,5 +1,7 @@ #include "rpc_server.hpp" #include "llarp/rpc/rpc_request_definitions.hpp" +#include "llarp/util/logging.hpp" +#include "oxen/log.hpp" #include "rpc_request.hpp" #include "llarp/service/address.hpp" #include @@ -106,18 +108,22 @@ namespace llarp::rpc for (const auto& addr : r.GetConfig()->api.m_rpcBindAddresses) { m_LMQ->listen_plain(addr.zmq_address()); - LogInfo("Bound RPC server to ", addr.full_address()); + log::info(logcat, "Bound RPC server to {}", addr.full_address()); } - for (const auto& [address, allowed_keys] : r->GetConfig()->api.m_rpcEncryptedAddresses) + 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; + m_LMQ->listen_curve( + address.zmq_address(), [allowed_keys = allowed_keys](auto addr, auto pk, ...) { + if (allowed_keys.count(std::string{pk})) + return oxenmq::AuthLevel::admin; - LogInfo("Curve pubkey not found in whitelist"); - return oxenmq::AuthLevel::denied; - }); + log::warning( + logcat, + "Curve pubkey not in whitelist, denying incoming RPC connection from {}", + addr); + return oxenmq::AuthLevel::denied; + }); } AddCategories();