0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-06-08 21:18:57 +02:00

ircd:Ⓜ️:request: Support destination in X-Matrix authorization header.

This commit is contained in:
Jason Volk 2022-06-30 10:32:19 -07:00
parent bd00907922
commit fe199a8ed0
3 changed files with 54 additions and 18 deletions

View file

@ -70,6 +70,7 @@ struct ircd::m::request::x_matrix
string_view origin; string_view origin;
string_view key; string_view key;
string_view sig; string_view sig;
string_view destination;
x_matrix(const string_view &type, const string_view &values); x_matrix(const string_view &type, const string_view &values);
x_matrix(const pair<string_view> &authorization); x_matrix(const pair<string_view> &authorization);

View file

@ -100,15 +100,15 @@ ircd::m::request::operator()(const mutable_buffer &out,
const const
{ {
thread_local http::header header[headers_max]; thread_local http::header header[headers_max];
thread_local char authorization[2_KiB];
const ctx::critical_assertion ca; const ctx::critical_assertion ca;
size_t headers{0};
size_t headers{0};
header[headers++] = header[headers++] =
{ {
"User-Agent", info::user_agent "User-Agent", info::user_agent
}; };
thread_local char x_matrix[2_KiB];
if(startswith(json::at<"uri"_>(*this), "/_matrix/federation")) if(startswith(json::at<"uri"_>(*this), "/_matrix/federation"))
{ {
const json::string &origin const json::string &origin
@ -133,7 +133,7 @@ const
header[headers++] = header[headers++] =
{ {
"Authorization", generate(x_matrix, secret_key, public_key_id) "Authorization", generate(authorization, secret_key, public_key_id)
}; };
} }
@ -209,6 +209,11 @@ const
json::at<"origin"_>(*this) json::at<"origin"_>(*this)
}; };
const json::string &destination
{
json::at<"destination"_>(*this)
};
const auto &secret_key const auto &secret_key
{ {
m::secret_key(my(origin)) m::secret_key(my(origin))
@ -219,13 +224,17 @@ const
secret_key.sign(object) secret_key.sign(object)
}; };
assert(pkid);
assert(origin);
assert(destination);
char sigb64[128]; char sigb64[128];
return fmt::sprintf return fmt::sprintf
{ {
out, "X-Matrix origin=%s,key=\"%s\",sig=\"%s\"", out, "X-Matrix origin=%s,key=\"%s\",sig=\"%s\",destination=\"%s\"",
origin, origin,
pkid, pkid,
b64::encode_unpadded(sigb64, sig) b64::encode_unpadded(sigb64, sig),
destination,
}; };
} }
@ -275,7 +284,7 @@ const
}; };
assert(!empty(request_content_buf)); assert(!empty(request_content_buf));
const mutable_buffer buf mutable_buffer buf
{ {
request_content_buf request_content_buf
}; };
@ -305,7 +314,7 @@ const
const json::object object const json::object object
{ {
stringify(mutable_buffer{buf}, _this) json::stringify(buf, _this)
}; };
return verify(pk, sig, object); return verify(pk, sig, object);
@ -316,6 +325,11 @@ ircd::m::request::verify(const ed25519::pk &pk,
const ed25519::sig &sig, const ed25519::sig &sig,
const json::object &object) const json::object &object)
{ {
assert(object.has("destination"));
assert(object.has("method"));
assert(object.has("origin"));
assert(object.has("uri"));
return pk.verify(object, sig); return pk.verify(object, sig);
} }
@ -343,14 +357,16 @@ ircd::m::request::x_matrix::x_matrix(const pair<string_view> &authorization)
ircd::m::request::x_matrix::x_matrix(const string_view &type, ircd::m::request::x_matrix::x_matrix(const string_view &type,
const string_view &values) const string_view &values)
{ {
static const size_t tokens_max {8}, tokens_min {3};
// Assumes caller determined this is X-Matrix lest they suffer exception. // Assumes caller determined this is X-Matrix lest they suffer exception.
assert(iequals(type, "X-Matrix"_sv)); assert(iequals(type, "X-Matrix"_sv));
string_view tokens[3]; string_view tokens[tokens_max];
if(ircd::tokens(values, ',', tokens) != 3) if(unlikely(ircd::tokens(values, ',', tokens) < tokens_min))
throw std::out_of_range throw std::out_of_range
{ {
"The x_matrix header is malformed" "The x_matrix header is malformed."
}; };
for(const auto &token : tokens) for(const auto &token : tokens)
@ -367,25 +383,26 @@ ircd::m::request::x_matrix::x_matrix(const string_view &type,
switch(hash(key)) switch(hash(key))
{ {
case hash("origin"): this->origin = val; break; case hash("origin"): this->origin = val; break;
case hash("key"): this->key = val; break; case hash("key"): this->key = val; break;
case hash("sig"): this->sig = val; break; case hash("sig"): this->sig = val; break;
case hash("destination"): this->destination = val; break;
} }
} }
if(empty(origin)) if(unlikely(empty(origin)))
throw std::out_of_range throw std::out_of_range
{ {
"The x_matrix header is missing 'origin='" "The x_matrix header is missing 'origin='"
}; };
if(empty(key)) if(unlikely(empty(key)))
throw std::out_of_range throw std::out_of_range
{ {
"The x_matrix header is missing 'key='" "The x_matrix header is missing 'key='"
}; };
if(empty(sig)) if(unlikely(empty(sig)))
throw std::out_of_range throw std::out_of_range
{ {
"The x_matrix header is missing 'sig='" "The x_matrix header is missing 'sig='"

View file

@ -374,14 +374,32 @@ try
throw m::error throw m::error
{ {
http::UNAUTHORIZED, "M_NOT_MY_HOST", http::UNAUTHORIZED, "M_NOT_MY_HOST",
"The HTTP Host '%s' is not an authenticable destination here.",
request.head.host,
};
const auto head_host
{
rstrip(request.head.host, ":8448")
};
const auto auth_dest
{
rstrip(request.x_matrix.destination, ":8448")
};
if(x_matrix_verify_destination && auth_dest && head_host != auth_dest)
throw m::error
{
http::UNAUTHORIZED, "M_NOT_MY_DESTINATION",
"The X-Matrix Authorization destination '%s' is not recognized here.", "The X-Matrix Authorization destination '%s' is not recognized here.",
request.head.host auth_dest,
}; };
const m::request object const m::request object
{ {
request.x_matrix.origin, request.x_matrix.origin,
rstrip(request.head.host, ":8448"), head_host,
method.name, method.name,
request.head.uri, request.head.uri,
request.content request.content