mirror of
https://github.com/matrix-construct/construct
synced 2025-01-13 16:33:53 +01:00
ircd:Ⓜ️ Rework/cleanup request/session related.
This commit is contained in:
parent
93364b6072
commit
617b0d0777
7 changed files with 419 additions and 327 deletions
|
@ -59,12 +59,8 @@ namespace ircd::m::io
|
|||
{
|
||||
struct sync;
|
||||
struct fetch;
|
||||
struct session;
|
||||
struct request;
|
||||
struct response;
|
||||
|
||||
bool verify_x_matrix_authorization(const string_view &authorization, const string_view &method, const string_view &uri, const string_view &content);
|
||||
|
||||
// Synchronous acquire many requests
|
||||
size_t acquire(vector_view<event::fetch>);
|
||||
size_t acquire(vector_view<room::fetch>);
|
||||
|
@ -86,8 +82,6 @@ namespace ircd::m::io
|
|||
namespace ircd::m
|
||||
{
|
||||
using io::get;
|
||||
using io::session;
|
||||
using io::request;
|
||||
using io::response;
|
||||
}
|
||||
|
||||
|
@ -227,62 +221,8 @@ struct ircd::m::room::state::fetch
|
|||
fetch() = default;
|
||||
};
|
||||
|
||||
struct ircd::m::io::request
|
||||
{
|
||||
struct authorization;
|
||||
struct keys;
|
||||
|
||||
string_view origin;
|
||||
string_view destination;
|
||||
string_view method;
|
||||
string_view path;
|
||||
string_view query;
|
||||
string_view fragment;
|
||||
std::string _content;
|
||||
json::object content;
|
||||
|
||||
string_view generate_authorization(const mutable_buffer &out) const;
|
||||
void operator()(server &, const vector_view<const http::header> & = {}) const;
|
||||
void operator()(const vector_view<const http::header> & = {}) const;
|
||||
|
||||
request(const string_view &method,
|
||||
const string_view &path,
|
||||
const string_view &query = {},
|
||||
json::members body = {})
|
||||
:method{method}
|
||||
,path{path}
|
||||
,query{query}
|
||||
,_content{json::strung(body)}
|
||||
,content{_content}
|
||||
{}
|
||||
|
||||
request(const string_view &method,
|
||||
const string_view &path,
|
||||
const string_view &query,
|
||||
const json::object &content)
|
||||
:method{method}
|
||||
,path{path}
|
||||
,query{query}
|
||||
,content{content}
|
||||
{}
|
||||
|
||||
request() = default;
|
||||
};
|
||||
|
||||
struct ircd::m::io::response
|
||||
:json::object
|
||||
{
|
||||
response(server &, parse::buffer &);
|
||||
};
|
||||
|
||||
struct ircd::m::io::session
|
||||
{
|
||||
ircd::server server;
|
||||
std::string destination;
|
||||
std::string access_token;
|
||||
|
||||
json::object operator()(parse::buffer &pb, request &);
|
||||
|
||||
session(const net::remote &);
|
||||
session() = default;
|
||||
response(server::request &, parse::buffer &);
|
||||
};
|
||||
|
|
|
@ -68,6 +68,8 @@ namespace ircd
|
|||
#include "query.h"
|
||||
#include "cursor.h"
|
||||
#include "room.h"
|
||||
#include "request.h"
|
||||
#include "session.h"
|
||||
#include "io.h"
|
||||
#include "vm.h"
|
||||
#include "user.h"
|
||||
|
|
129
include/ircd/m/request.h
Normal file
129
include/ircd/m/request.h
Normal file
|
@ -0,0 +1,129 @@
|
|||
// Matrix Construct
|
||||
//
|
||||
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
||||
// Copyright (C) 2016-2018 Jason Volk <jason@zemos.net>
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice is present in all copies. The
|
||||
// full license for this software is available in the LICENSE file.
|
||||
|
||||
#pragma once
|
||||
#define HAVE_IRCD_M_REQUEST_H
|
||||
|
||||
namespace ircd::m
|
||||
{
|
||||
struct request;
|
||||
}
|
||||
|
||||
/// Composes a matrix protocol request. This is a JSON tuple because the
|
||||
/// protocol uses a JSON authorization object to create the X-Matrix
|
||||
/// authorization header on federation requests.
|
||||
///
|
||||
struct ircd::m::request
|
||||
:json::tuple
|
||||
<
|
||||
json::property<name::content, json::object>,
|
||||
json::property<name::destination, string_view>,
|
||||
json::property<name::method, string_view>,
|
||||
json::property<name::origin, string_view>,
|
||||
json::property<name::uri, string_view>
|
||||
>
|
||||
{
|
||||
struct x_matrix;
|
||||
|
||||
static bool verify(const ed25519::pk &, const ed25519::sig &, const json::object &);
|
||||
bool verify(const ed25519::pk &, const ed25519::sig &) const;
|
||||
bool verify(const string_view &key, const string_view &sig) const;
|
||||
string_view generate(const mutable_buffer &out, const ed25519::sk &, const string_view &pkid) const;
|
||||
|
||||
string_view operator()(const mutable_buffer &out, const vector_view<const http::header> & = {}) const;
|
||||
|
||||
request(const string_view &origin,
|
||||
const string_view &destination,
|
||||
const string_view &method,
|
||||
const string_view &uri,
|
||||
const json::object &content);
|
||||
|
||||
request(const string_view &method,
|
||||
const string_view &uri,
|
||||
const json::object &content);
|
||||
|
||||
request(const string_view &method,
|
||||
const string_view &uri);
|
||||
|
||||
// stringifies content members into buf
|
||||
request(const string_view &method,
|
||||
const string_view &uri,
|
||||
const mutable_buffer &body_buf,
|
||||
const json::members &body);
|
||||
|
||||
using super_type::tuple;
|
||||
request() = default;
|
||||
};
|
||||
|
||||
struct ircd::m::request::x_matrix
|
||||
{
|
||||
string_view origin;
|
||||
string_view key;
|
||||
string_view sig;
|
||||
|
||||
x_matrix(const string_view &);
|
||||
x_matrix() = default;
|
||||
};
|
||||
|
||||
inline
|
||||
ircd::m::request::request(const string_view &method,
|
||||
const string_view &uri,
|
||||
const mutable_buffer &body_buf,
|
||||
const json::members &body)
|
||||
:request
|
||||
{
|
||||
my_host(),
|
||||
string_view{},
|
||||
method,
|
||||
uri,
|
||||
json::stringify(mutable_buffer{body_buf}, body)
|
||||
}
|
||||
{}
|
||||
|
||||
inline
|
||||
ircd::m::request::request(const string_view &method,
|
||||
const string_view &uri)
|
||||
:request
|
||||
{
|
||||
my_host(),
|
||||
string_view{},
|
||||
method,
|
||||
uri,
|
||||
json::object{}
|
||||
}
|
||||
{}
|
||||
|
||||
inline
|
||||
ircd::m::request::request(const string_view &method,
|
||||
const string_view &uri,
|
||||
const json::object &content)
|
||||
:request
|
||||
{
|
||||
my_host(),
|
||||
string_view{},
|
||||
method,
|
||||
uri,
|
||||
content
|
||||
}
|
||||
{}
|
||||
|
||||
inline
|
||||
ircd::m::request::request(const string_view &origin,
|
||||
const string_view &destination,
|
||||
const string_view &method,
|
||||
const string_view &uri,
|
||||
const json::object &content)
|
||||
{
|
||||
json::get<"origin"_>(*this) = origin;
|
||||
json::get<"destination"_>(*this) = destination;
|
||||
json::get<"method"_>(*this) = method;
|
||||
json::get<"uri"_>(*this) = uri;
|
||||
json::get<"content"_>(*this) = content;
|
||||
}
|
88
include/ircd/m/session.h
Normal file
88
include/ircd/m/session.h
Normal file
|
@ -0,0 +1,88 @@
|
|||
// Matrix Construct
|
||||
//
|
||||
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
||||
// Copyright (C) 2016-2018 Jason Volk <jason@zemos.net>
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice is present in all copies. The
|
||||
// full license for this software is available in the LICENSE file.
|
||||
|
||||
#pragma once
|
||||
#define HAVE_IRCD_M_SESSION_H
|
||||
|
||||
namespace ircd::m
|
||||
{
|
||||
struct session;
|
||||
}
|
||||
|
||||
struct ircd::m::session
|
||||
{
|
||||
net::remote remote;
|
||||
std::string access_token;
|
||||
|
||||
server::request operator()(const server::out &out, const server::in &in) const;
|
||||
template<class... args> server::request operator()(const mutable_buffer &buf, args&&...) const;
|
||||
|
||||
session(const net::remote &remote)
|
||||
:remote{remote}
|
||||
{}
|
||||
|
||||
session(const net::hostport &remote)
|
||||
:remote{remote}
|
||||
{}
|
||||
|
||||
session() = default;
|
||||
};
|
||||
|
||||
template<class... args>
|
||||
ircd::server::request
|
||||
ircd::m::session::operator()(const mutable_buffer &buf,
|
||||
args&&... a)
|
||||
const
|
||||
{
|
||||
m::request request
|
||||
{
|
||||
std::forward<args>(a)...
|
||||
};
|
||||
|
||||
if(!defined(json::get<"destination"_>(request)))
|
||||
json::get<"destination"_>(request) = remote.hostname;
|
||||
|
||||
if(!defined(json::get<"origin"_>(request)))
|
||||
json::get<"origin"_>(request) = my_host();
|
||||
|
||||
const auto head
|
||||
{
|
||||
request(buf)
|
||||
};
|
||||
|
||||
const server::out out
|
||||
{
|
||||
head
|
||||
};
|
||||
|
||||
const auto in_max
|
||||
{
|
||||
std::max(ssize_t(size(buf) - size(head)), ssize_t(0))
|
||||
};
|
||||
|
||||
assert(in_max >= ssize_t(size(buf) / 2));
|
||||
const server::in in
|
||||
{
|
||||
{ data(buf) + size(head), size_t(in_max) }
|
||||
};
|
||||
|
||||
return operator()(out, in);
|
||||
}
|
||||
|
||||
inline ircd::server::request
|
||||
ircd::m::session::operator()(const server::out &out,
|
||||
const server::in &in)
|
||||
const
|
||||
{
|
||||
return
|
||||
{
|
||||
remote, out, in
|
||||
};
|
||||
}
|
|
@ -78,6 +78,7 @@ libircd_la_SOURCES = \
|
|||
m/id.cc \
|
||||
m/io.cc \
|
||||
m/keys.cc \
|
||||
m/request.cc \
|
||||
m/room.cc \
|
||||
m/vm.cc \
|
||||
m/m.cc \
|
||||
|
|
266
ircd/m/io.cc
266
ircd/m/io.cc
|
@ -524,269 +524,3 @@ catch(const std::exception &e)
|
|||
tab.error = std::make_exception_ptr(e);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// m/session.h
|
||||
//
|
||||
|
||||
ircd::m::io::session::session(const net::remote &remote)
|
||||
:server{remote}
|
||||
,destination{remote.hostname}
|
||||
{
|
||||
}
|
||||
|
||||
ircd::json::object
|
||||
ircd::m::io::session::operator()(parse::buffer &pb,
|
||||
request &request)
|
||||
{
|
||||
request.destination = destination;
|
||||
request(server);
|
||||
return response
|
||||
{
|
||||
server, pb
|
||||
};
|
||||
}
|
||||
|
||||
ircd::m::io::response::response(server &server,
|
||||
parse::buffer &pb)
|
||||
{
|
||||
http::code status;
|
||||
json::object &object
|
||||
{
|
||||
static_cast<json::object &>(*this)
|
||||
};
|
||||
|
||||
parse::capstan pc
|
||||
{
|
||||
pb, read_closure(server)
|
||||
};
|
||||
|
||||
http::response
|
||||
{
|
||||
pc,
|
||||
nullptr,
|
||||
[&pc, &status, &object](const http::response::head &head)
|
||||
{
|
||||
status = http::status(head.status);
|
||||
object = http::response::content{pc, head};
|
||||
},
|
||||
[](const auto &header)
|
||||
{
|
||||
//std::cout << header.first << " :" << header.second << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
if(status < 200 || status >= 300)
|
||||
throw m::error(status, object);
|
||||
}
|
||||
|
||||
void
|
||||
ircd::m::io::request::operator()(const vector_view<const http::header> &addl_headers)
|
||||
const
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ircd::m::io::request::operator()(server &server,
|
||||
const vector_view<const http::header> &addl_headers)
|
||||
const
|
||||
{
|
||||
const size_t addl_headers_size
|
||||
{
|
||||
std::min(addl_headers.size(), size_t(64UL))
|
||||
};
|
||||
|
||||
size_t headers{1};
|
||||
http::line::header header[headers + addl_headers_size]
|
||||
{
|
||||
{ "User-Agent", BRANDING_NAME " (IRCd " BRANDING_VERSION ")" },
|
||||
};
|
||||
|
||||
for(size_t i(0); i < addl_headers_size; ++i)
|
||||
header[headers++] = addl_headers.at(i);
|
||||
|
||||
char x_matrix[1024];
|
||||
if(startswith(path, "_matrix/federation"))
|
||||
header[headers++] =
|
||||
{
|
||||
"Authorization", generate_authorization(x_matrix)
|
||||
};
|
||||
|
||||
static const auto content_type
|
||||
{
|
||||
"application/json; charset=utf-8"
|
||||
};
|
||||
|
||||
const unique_buffer<mutable_buffer> head_buf{8192};
|
||||
stream_buffer head{head_buf};
|
||||
http::request
|
||||
{
|
||||
head,
|
||||
destination,
|
||||
method,
|
||||
path,
|
||||
query,
|
||||
content.size(),
|
||||
content_type,
|
||||
{ header, headers }
|
||||
};
|
||||
|
||||
const ilist<const_buffer> vector
|
||||
{
|
||||
head.completed(),
|
||||
content
|
||||
};
|
||||
|
||||
write_closure(server)(vector);
|
||||
}
|
||||
|
||||
namespace ircd::m::name
|
||||
{
|
||||
// constexpr const char *const content {"content"};
|
||||
constexpr const char *const destination {"destination"};
|
||||
constexpr const char *const method {"method"};
|
||||
// constexpr const char *const origin {"origin"};
|
||||
constexpr const char *const uri {"uri"};
|
||||
}
|
||||
|
||||
struct ircd::m::io::request::authorization
|
||||
:json::tuple
|
||||
<
|
||||
json::property<name::content, string_view>,
|
||||
json::property<name::destination, string_view>,
|
||||
json::property<name::method, string_view>,
|
||||
json::property<name::origin, string_view>,
|
||||
json::property<name::uri, string_view>
|
||||
>
|
||||
{
|
||||
string_view generate(const mutable_buffer &out);
|
||||
|
||||
using super_type::tuple;
|
||||
};
|
||||
|
||||
ircd::string_view
|
||||
ircd::m::io::request::generate_authorization(const mutable_buffer &out)
|
||||
const
|
||||
{
|
||||
const fmt::bsprintf<2048> uri
|
||||
{
|
||||
"/%s%s%s", lstrip(path, '/'), query? "?" : "", query
|
||||
};
|
||||
|
||||
request::authorization authorization
|
||||
{
|
||||
json::members
|
||||
{
|
||||
{ "destination", destination },
|
||||
{ "method", method },
|
||||
{ "origin", my_host() },
|
||||
{ "uri", uri },
|
||||
}
|
||||
};
|
||||
|
||||
if(string_view{content}.size() > 2)
|
||||
json::get<"content"_>(authorization) = content;
|
||||
|
||||
return authorization.generate(out);
|
||||
}
|
||||
|
||||
ircd::string_view
|
||||
ircd::m::io::request::authorization::generate(const mutable_buffer &out)
|
||||
{
|
||||
// Any buffers here can be comfortably large if they're not on a stack and
|
||||
// nothing in this procedure has a yield which risks decohering static
|
||||
// buffers; the assertion is tripped if so.
|
||||
ctx::critical_assertion ca;
|
||||
|
||||
static fixed_buffer<mutable_buffer, 131072> request_object_buf;
|
||||
const auto request_object
|
||||
{
|
||||
json::stringify(request_object_buf, *this)
|
||||
};
|
||||
|
||||
const ed25519::sig sig
|
||||
{
|
||||
self::secret_key.sign(request_object)
|
||||
};
|
||||
|
||||
static fixed_buffer<mutable_buffer, 128> signature_buf;
|
||||
const auto x_matrix_len
|
||||
{
|
||||
fmt::sprintf(out, "X-Matrix origin=%s,key=\"%s\",sig=\"%s\"",
|
||||
unquote(string_view{at<"origin"_>(*this)}),
|
||||
self::public_key_id,
|
||||
b64encode_unpadded(signature_buf, sig))
|
||||
};
|
||||
|
||||
return
|
||||
{
|
||||
data(out), size_t(x_matrix_len)
|
||||
};
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::io::verify_x_matrix_authorization(const string_view &x_matrix,
|
||||
const string_view &method,
|
||||
const string_view &uri,
|
||||
const string_view &content)
|
||||
{
|
||||
string_view tokens[3], origin, key, sig;
|
||||
if(ircd::tokens(split(x_matrix, ' ').second, ',', tokens) != 3)
|
||||
return false;
|
||||
|
||||
for(const auto &token : tokens)
|
||||
{
|
||||
const auto &kv{split(token, '=')};
|
||||
const auto &val{unquote(kv.second)};
|
||||
switch(hash(kv.first))
|
||||
{
|
||||
case hash("origin"): origin = val; break;
|
||||
case hash("key"): key = val; break;
|
||||
case hash("sig"): sig = val; break;
|
||||
}
|
||||
}
|
||||
|
||||
request::authorization authorization
|
||||
{
|
||||
json::members
|
||||
{
|
||||
{ "destination", my_host() },
|
||||
{ "method", method },
|
||||
{ "origin", origin },
|
||||
{ "uri", uri },
|
||||
}
|
||||
};
|
||||
|
||||
if(content.size() > 2)
|
||||
json::get<"content"_>(authorization) = content;
|
||||
|
||||
//TODO: XXX
|
||||
const json::strung request_object
|
||||
{
|
||||
authorization
|
||||
};
|
||||
|
||||
const ed25519::sig _sig
|
||||
{
|
||||
[&sig](auto &buf)
|
||||
{
|
||||
b64decode(buf, sig);
|
||||
}
|
||||
};
|
||||
|
||||
const ed25519::pk pk
|
||||
{
|
||||
[&origin, &key](auto &buf)
|
||||
{
|
||||
m::keys::get(origin, key, [&buf]
|
||||
(const string_view &key)
|
||||
{
|
||||
b64decode(buf, unquote(key));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return pk.verify(const_raw_buffer{request_object}, _sig);
|
||||
}
|
||||
|
|
198
ircd/m/request.cc
Normal file
198
ircd/m/request.cc
Normal file
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Charybdis Development Team
|
||||
* Copyright (C) 2016 Jason Volk <jason@zemos.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice is present in all copies.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <ircd/m/m.h>
|
||||
|
||||
//
|
||||
// request
|
||||
//
|
||||
|
||||
ircd::string_view
|
||||
ircd::m::request::operator()(const mutable_buffer &out,
|
||||
const vector_view<const http::header> &addl_headers)
|
||||
const
|
||||
{
|
||||
const size_t addl_headers_size
|
||||
{
|
||||
std::min(addl_headers.size(), size_t(64UL))
|
||||
};
|
||||
|
||||
size_t headers{1};
|
||||
http::header header[headers + addl_headers_size]
|
||||
{
|
||||
{ "User-Agent", BRANDING_NAME " (IRCd " BRANDING_VERSION ")" },
|
||||
};
|
||||
|
||||
for(size_t i(0); i < addl_headers_size; ++i)
|
||||
header[headers++] = addl_headers.at(i);
|
||||
|
||||
thread_local char x_matrix[1_KiB];
|
||||
if(startswith(at<"uri"_>(*this), "/_matrix/federation"))
|
||||
{
|
||||
const auto &sk{self::secret_key};
|
||||
const auto &pkid{self::public_key_id};
|
||||
header[headers++] =
|
||||
{
|
||||
"Authorization", generate(x_matrix, sk, pkid)
|
||||
};
|
||||
}
|
||||
|
||||
static const string_view content_type
|
||||
{
|
||||
"application/json; charset=utf-8"_sv
|
||||
};
|
||||
|
||||
const auto content_length
|
||||
{
|
||||
string_view(json::get<"content"_>(*this)).size()
|
||||
};
|
||||
|
||||
stream_buffer sb{out};
|
||||
http::request
|
||||
{
|
||||
sb,
|
||||
at<"destination"_>(*this),
|
||||
at<"method"_>(*this),
|
||||
at<"uri"_>(*this),
|
||||
content_length,
|
||||
content_type,
|
||||
{ header, headers }
|
||||
};
|
||||
|
||||
return sb.completed();
|
||||
}
|
||||
|
||||
ircd::string_view
|
||||
ircd::m::request::generate(const mutable_buffer &out,
|
||||
const ed25519::sk &sk,
|
||||
const string_view &pkid)
|
||||
const
|
||||
{
|
||||
const json::strung object
|
||||
{
|
||||
*this,
|
||||
};
|
||||
|
||||
const ed25519::sig sig
|
||||
{
|
||||
self::secret_key.sign(const_buffer{object})
|
||||
};
|
||||
|
||||
const auto &origin
|
||||
{
|
||||
unquote(string_view{at<"origin"_>(*this)})
|
||||
};
|
||||
|
||||
thread_local char sigb64[1_KiB];
|
||||
return fmt::sprintf
|
||||
{
|
||||
out, "X-Matrix origin=%s,key=\"%s\",sig=\"%s\"",
|
||||
origin,
|
||||
pkid,
|
||||
b64encode_unpadded(sigb64, sig)
|
||||
};
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::request::verify(const string_view &key,
|
||||
const string_view &sig)
|
||||
const
|
||||
{
|
||||
const ed25519::sig _sig
|
||||
{
|
||||
[&sig](auto &buf)
|
||||
{
|
||||
b64decode(buf, sig);
|
||||
}
|
||||
};
|
||||
|
||||
const auto &origin
|
||||
{
|
||||
unquote(at<"origin"_>(*this))
|
||||
};
|
||||
|
||||
const ed25519::pk pk
|
||||
{
|
||||
[&origin, &key](auto &buf)
|
||||
{
|
||||
m::keys::get(origin, key, [&buf]
|
||||
(const string_view &key)
|
||||
{
|
||||
b64decode(buf, unquote(key));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return verify(pk, _sig);
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::request::verify(const ed25519::pk &pk,
|
||||
const ed25519::sig &sig)
|
||||
const
|
||||
{
|
||||
const json::strung object
|
||||
{
|
||||
*this
|
||||
};
|
||||
|
||||
return verify(pk, sig, object);
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::request::verify(const ed25519::pk &pk,
|
||||
const ed25519::sig &sig,
|
||||
const json::object &object)
|
||||
{
|
||||
return pk.verify(object, sig);
|
||||
}
|
||||
|
||||
//
|
||||
// x_matrix
|
||||
//
|
||||
|
||||
ircd::m::request::x_matrix::x_matrix(const string_view &input)
|
||||
{
|
||||
string_view tokens[3];
|
||||
if(ircd::tokens(split(input, ' ').second, ',', tokens) != 3)
|
||||
throw std::out_of_range{"The x_matrix header is malformed"};
|
||||
|
||||
for(const auto &token : tokens)
|
||||
{
|
||||
const auto &kv{split(token, '=')};
|
||||
const auto &val{unquote(kv.second)};
|
||||
switch(hash(kv.first))
|
||||
{
|
||||
case hash("origin"): origin = val; break;
|
||||
case hash("key"): key = val; break;
|
||||
case hash("sig"): sig = val; break;
|
||||
}
|
||||
}
|
||||
|
||||
if(empty(origin))
|
||||
throw std::out_of_range{"The x_matrix header is missing 'origin='"};
|
||||
|
||||
if(empty(key))
|
||||
throw std::out_of_range{"The x_matrix header is missing 'key='"};
|
||||
|
||||
if(empty(sig))
|
||||
throw std::out_of_range{"The x_matrix header is missing 'sig='"};
|
||||
}
|
Loading…
Reference in a new issue