more auth shit

This commit is contained in:
Jeff Becker 2020-06-17 09:07:05 -04:00
parent 0d6e3bcd89
commit 3cdca30a74
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05
13 changed files with 145 additions and 45 deletions

View File

@ -4,46 +4,50 @@ import sys
from socket import AF_INET
import requests
import zmq
from pyroute2 import IPRoute
class LokinetRPC:
def __init__(self, url):
self._rpc_context = zmq.Context()
self._rpc_socket = self._rpc_context.socket(zmq.DEALER)
self._rpc_socket.setsockopt(zmq.CONNECT_TIMEOUT, 5000)
self._rpc_socket.setsockopt(zmq.HANDSHAKE_IVL, 5000)
self._rpc_socket.connect(url)
self._url = url
def _jsonrpc(self, method, params={}):
r = requests.post(
self._url,
headers={"Content-Type": "application/json", "Host": "localhost"},
json={
"jsonrpc": "2.0",
"id": "0",
"method": "{}".format(method),
"params": params,
},
)
return r.json()
def rpc(self, method):
self._rpc_socket.send_multipart([method.encode(), b'lokinet_vpn'+method.encode()])
if not self._rpc_socket.poll(timeout=50):
return
reply = self._rpc_socket.recv_multipart()
if len(reply) >= 3 and reply[0:2] == [b'REPLY', b'lokinet_vpn'+method.encode()]:
return reply[2].decode()
def get_first_hops(self):
data = self._jsonrpc("llarp.admin.dumpstate")
data = self.rpc("llarp.status")
for link in data['result']['links']['outbound']:
for session in link["sessions"]['established']:
yield session['remoteAddr']
def close(self):
self._rpc_socket.close(linger=0)
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--rpc", type=str, default='127.0.0.1:1190')
ap.add_argument("--rpc", type=str, default='tcp://127.0.0.1:1190')
ap.add_argument("--ifname", type=str, default="lokitun0")
ap.add_argument("--up", action='store_const', dest='action', const='up')
ap.add_argument("--down", action='store_const', dest='action', const='down')
args = ap.parse_args()
rpc = LokinetRPC('http://{}/jsonrpc'.format(args.rpc))
rpc = LokinetRPC(args.rpc)
hops = dict()
for hop in rpc.get_first_hops():
ip = hop.split(':')[0]
hops[ip] = 0
rpc.close()
if len(hops) == 0:
print("lokinet is not connected yet")
return 1

View File

@ -957,7 +957,9 @@ namespace libuv
return;
if (h->data && uv_is_active(h) && h->type != UV_TIMER && h->type != UV_POLL)
{
static_cast<glue*>(h->data)->Close();
auto glue = reinterpret_cast<libuv::glue*>(h->data);
if (glue)
glue->Close();
}
},
nullptr);

View File

@ -12,6 +12,22 @@
#include <algorithm>
#include <map>
constexpr uint32_t ipv6_flowlabel_mask = 0b00000000000011111111111111111111;
void
ipv6_header::FlowLabel(llarp::nuint32_t label)
{
// the ipv6 flow label is the last 20 bits in the first 32 bits of the header
preamble.flowlabel =
(htonl(ipv6_flowlabel_mask) & label.n) | (preamble.flowlabel & htonl(~ipv6_flowlabel_mask));
}
llarp::nuint32_t
ipv6_header::FlowLabel() const
{
return llarp::nuint32_t{preamble.flowlabel & htonl(ipv6_flowlabel_mask)};
}
namespace llarp
{
namespace net
@ -334,7 +350,7 @@ namespace llarp
}
void
IPPacket::UpdateIPv6Address(huint128_t src, huint128_t dst)
IPPacket::UpdateIPv6Address(huint128_t src, huint128_t dst, std::optional<nuint32_t> flowlabel)
{
const size_t ihs = 4 + 4 + 16 + 16;
@ -343,6 +359,11 @@ namespace llarp
return;
auto hdr = HeaderV6();
if (flowlabel.has_value())
{
// set flow label if desired
hdr->FlowLabel(*flowlabel);
}
const auto oldSrcIP = hdr->srcaddr;
const auto oldDstIP = hdr->dstaddr;
@ -420,7 +441,7 @@ namespace llarp
}
void
IPPacket::ZeroAddresses()
IPPacket::ZeroAddresses(std::optional<nuint32_t> flowlabel)
{
if (IsV4())
{
@ -428,12 +449,12 @@ namespace llarp
}
else if (IsV6())
{
UpdateIPv6Address({0}, {0});
UpdateIPv6Address({0}, {0}, flowlabel);
}
}
void
IPPacket::ZeroSourceAddress()
IPPacket::ZeroSourceAddress(std::optional<nuint32_t> flowlabel)
{
if (IsV4())
{
@ -441,9 +462,10 @@ namespace llarp
}
else if (IsV6())
{
UpdateIPv6Address({0}, {ntoh128(dstv6().h)});
UpdateIPv6Address({0}, {ntoh128(dstv6().h)}, flowlabel);
}
}
std::optional<IPPacket>
IPPacket::MakeICMPUnreachable() const
{

View File

@ -75,16 +75,33 @@ typedef struct ip_hdr
#define tot_len ip_total_length
#endif
struct ipv6_header
struct ipv6_header_preamble
{
unsigned char version : 4;
unsigned char pad_small : 4;
uint8_t pad[3];
};
struct ipv6_header
{
union {
ipv6_header_preamble preamble;
uint32_t flowlabel;
} preamble;
uint16_t payload_len;
uint8_t proto;
uint8_t hoplimit;
in6_addr srcaddr;
in6_addr dstaddr;
/// get 20 bit truncated flow label in network order
llarp::nuint32_t
FlowLabel() const;
/// put 20 bit truncated flow label network order
void
FlowLabel(llarp::nuint32_t flowlabel);
};
#include <memory>
@ -242,14 +259,16 @@ namespace llarp
UpdateIPv4Address(nuint32_t src, nuint32_t dst);
void
UpdateIPv6Address(huint128_t src, huint128_t dst);
UpdateIPv6Address(
huint128_t src, huint128_t dst, std::optional<nuint32_t> flowlabel = std::nullopt);
/// set addresses to zero and recacluate checksums
void
ZeroAddresses();
ZeroAddresses(std::optional<nuint32_t> flowlabel = std::nullopt);
/// zero out source address
void
ZeroSourceAddress();
ZeroSourceAddress(std::optional<nuint32_t> flowlabel = std::nullopt);
/// make an icmp unreachable reply packet based of this ip packet
std::optional<IPPacket>

View File

@ -36,21 +36,40 @@ namespace llarp::rpc
void
EndpointAuthRPC::AuthenticateAsync(
llarp::service::Address from,
llarp::service::ConvoTag,
std::shared_ptr<llarp::service::ProtocolMessage> msg,
std::function<void(service::AuthResult)> hook)
{
const auto from = msg->sender.Addr();
if (m_AuthWhitelist.count(from))
{
// explicitly whitelisted source
m_Endpoint->RouterLogic()->Call([hook]() { hook(service::AuthResult::eAuthAccepted); });
return;
}
if (not m_Conn.has_value())
{
// we don't have a connection to the backend so it's failed
m_Endpoint->RouterLogic()->Call([hook]() { hook(service::AuthResult::eAuthFailed); });
return;
}
// call method with 1 parameter: the loki address of the remote
if (msg->proto != llarp::service::eProtocolAuth)
{
// not an auth message, reject
m_Endpoint->RouterLogic()->Call([hook]() { hook(service::AuthResult::eAuthRejected); });
return;
}
const auto maybe = msg->MaybeEncodeAuthInfo();
if (not maybe.has_value())
{
// cannot generate meta info, failed
m_Endpoint->RouterLogic()->Call([hook]() { hook(service::AuthResult::eAuthFailed); });
return;
}
std::string_view metaInfo{(char*)maybe->data(), maybe->size()};
std::string_view payload{(char*)msg->payload.data(), msg->payload.size()};
// call method with 2 parameters: metainfo and userdata
m_LMQ->request(
*m_Conn,
m_AuthMethod,
@ -67,7 +86,8 @@ namespace llarp::rpc
}
self->m_Endpoint->RouterLogic()->Call([hook, result]() { hook(result); });
},
from.ToString());
metaInfo,
payload);
} // namespace llarp::rpc
} // namespace llarp::rpc

View File

@ -30,8 +30,7 @@ namespace llarp::rpc
void
AuthenticateAsync(
llarp::service::Address from,
service::ConvoTag tag,
std::shared_ptr<llarp::service::ProtocolMessage> msg,
std::function<void(service::AuthResult)> hook) override;
private:

View File

@ -35,6 +35,7 @@ namespace llarp::service
/// result later
virtual void
AuthenticateAsync(
service::Address from, service::ConvoTag tag, std::function<void(AuthResult)> hook) = 0;
std::shared_ptr<llarp::service::ProtocolMessage> msg,
std::function<void(AuthResult)> hook) = 0;
};
} // namespace llarp::service

View File

@ -854,11 +854,12 @@ namespace llarp
}
void
Endpoint::AsyncAuthConvoTag(Address addr, ConvoTag tag, std::function<void(AuthResult)> hook)
Endpoint::AsyncProcessAuthMessage(
std::shared_ptr<ProtocolMessage> msg, std::function<void(AuthResult)> hook)
{
if (m_AuthPolicy)
{
m_AuthPolicy->AuthenticateAsync(std::move(addr), std::move(tag), std::move(hook));
m_AuthPolicy->AuthenticateAsync(std::move(msg), std::move(hook));
}
else
{

View File

@ -355,7 +355,8 @@ namespace llarp
IntroSetPublished();
void
AsyncAuthConvoTag(Address addr, ConvoTag tag, std::function<void(AuthResult)> hook);
AsyncProcessAuthMessage(
std::shared_ptr<ProtocolMessage> msg, std::function<void(AuthResult)> hook);
void
SendAuthReject(path::Path_ptr path, PathID_t replyPath, ConvoTag tag, AuthResult st);

View File

@ -73,10 +73,13 @@ namespace llarp
return false;
if (!BEncodeWriteDictInt("a", proto, buf))
return false;
if (!bencode_write_bytestring(buf, "d", 1))
return false;
if (!bencode_write_bytestring(buf, payload.data(), payload.size()))
return false;
if (not payload.empty())
{
if (!bencode_write_bytestring(buf, "d", 1))
return false;
if (!bencode_write_bytestring(buf, payload.data(), payload.size()))
return false;
}
if (!BEncodeWriteDictEntry("i", introReply, buf))
return false;
if (!BEncodeWriteDictInt("n", seqno, buf))
@ -93,6 +96,32 @@ namespace llarp
return bencode_end(buf);
}
std::optional<std::vector<byte_t>>
ProtocolMessage::MaybeEncodeAuthInfo() const
{
std::array<byte_t, 1024> info;
llarp_buffer_t buf{info};
if (not bencode_start_dict(&buf))
return std::nullopt;
if (not BEncodeWriteDictInt("a", proto, &buf))
return std::nullopt;
if (not BEncodeWriteDictEntry("i", introReply, &buf))
return std::nullopt;
if (not BEncodeWriteDictEntry("s", sender, &buf))
return std::nullopt;
if (not BEncodeWriteDictEntry("t", tag, &buf))
return std::nullopt;
if (not BEncodeWriteDictInt("v", version, &buf))
return std::nullopt;
if (not bencode_end(&buf))
return std::nullopt;
const std::size_t encodedSize = buf.cur - buf.base;
std::vector<byte_t> data;
data.resize(encodedSize);
std::copy_n(buf.base, encodedSize, data.data());
return data;
}
ProtocolFrame::~ProtocolFrame() = default;
bool
@ -335,10 +364,8 @@ namespace llarp
path::Path_ptr path = std::move(self->path);
const PathID_t from = self->frame.F;
msg->handler = self->handler;
self->handler->AsyncAuthConvoTag(
msg->sender.Addr(),
msg->tag,
self->handler->AsyncProcessAuthMessage(
msg,
[path, msg, from, handler = self->handler, fromIntro = self->fromIntro, sharedKey](
AuthResult result) {
if (result == AuthResult::eAuthAccepted)

View File

@ -50,6 +50,10 @@ namespace llarp
uint64_t seqno = 0;
uint64_t version = LLARP_PROTO_VERSION;
/// maybe encode metainfo for lmq endpoint auth
std::optional<std::vector<byte_t>>
MaybeEncodeAuthInfo() const;
bool
DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val);

View File

@ -10,4 +10,5 @@ namespace llarp::service
constexpr ProtocolType eProtocolTrafficV4 = 1UL;
constexpr ProtocolType eProtocolTrafficV6 = 2UL;
constexpr ProtocolType eProtocolExit = 3UL;
constexpr ProtocolType eProtocolAuth = 4UL;
} // namespace llarp::service

View File

@ -142,7 +142,6 @@ RunIWPTest(Func_t test, Duration_t timeout = 1s)
{
// shut up logs
llarp::LogSilencer shutup;
// set up event loop
auto logic = std::make_shared<llarp::Logic>();
auto loop = llarp_make_ev_loop();