[backend] Consistently enforce https URIs
This commit is contained in:
parent
b43e81b834
commit
e391aebce5
3 changed files with 20 additions and 20 deletions
|
@ -82,7 +82,7 @@ public class SearchController(
|
||||||
|
|
||||||
if (search.Resolve)
|
if (search.Resolve)
|
||||||
{
|
{
|
||||||
if (search.Query!.StartsWith("https://") || search.Query.StartsWith("http://"))
|
if (search.Query!.StartsWith("https://"))
|
||||||
{
|
{
|
||||||
if (pagination.Offset is not null and not 0) return [];
|
if (pagination.Offset is not null and not 0) return [];
|
||||||
|
|
||||||
|
@ -146,7 +146,7 @@ public class SearchController(
|
||||||
{
|
{
|
||||||
var user = HttpContext.GetUserOrFail();
|
var user = HttpContext.GetUserOrFail();
|
||||||
|
|
||||||
if (search.Resolve && (search.Query!.StartsWith("https://") || search.Query.StartsWith("http://")))
|
if (search.Resolve && search.Query!.StartsWith("https://"))
|
||||||
{
|
{
|
||||||
if (pagination.Offset is not null and not 0) return [];
|
if (pagination.Offset is not null and not 0) return [];
|
||||||
|
|
||||||
|
|
|
@ -93,7 +93,7 @@ public class SearchController(
|
||||||
throw GracefulException.NotFound("No result found");
|
throw GracefulException.NotFound("No result found");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target.StartsWith("http://") || target.StartsWith("https://"))
|
if (target.StartsWith("https://"))
|
||||||
{
|
{
|
||||||
Note? noteHit = null;
|
Note? noteHit = null;
|
||||||
User? userHit = null;
|
User? userHit = null;
|
||||||
|
|
|
@ -42,11 +42,11 @@ public class WebFingerService(
|
||||||
|
|
||||||
public async Task<WebFingerResponse?> ResolveAsync(string query)
|
public async Task<WebFingerResponse?> ResolveAsync(string query)
|
||||||
{
|
{
|
||||||
(query, var proto, var domain) = ParseQuery(query);
|
(query, var domain) = ParseQuery(query);
|
||||||
if (domain == config.Value.WebDomain || domain == config.Value.AccountDomain)
|
if (domain == config.Value.WebDomain || domain == config.Value.AccountDomain)
|
||||||
throw new GracefulException(HttpStatusCode.BadRequest, "Can't run WebFinger for local user");
|
throw new GracefulException(HttpStatusCode.BadRequest, "Can't run WebFinger for local user");
|
||||||
|
|
||||||
var webFingerUrl = await GetWebFingerUrlAsync(query, proto, domain);
|
var webFingerUrl = await GetWebFingerUrlAsync(query, domain);
|
||||||
|
|
||||||
using var cts = CancellationTokenSource.CreateLinkedTokenSource(appLifetime.ApplicationStopping);
|
using var cts = CancellationTokenSource.CreateLinkedTokenSource(appLifetime.ApplicationStopping);
|
||||||
cts.CancelAfter(TimeSpan.FromSeconds(10));
|
cts.CancelAfter(TimeSpan.FromSeconds(10));
|
||||||
|
@ -73,20 +73,20 @@ public class WebFingerService(
|
||||||
throw new Exception("Failed to deserialize xml payload");
|
throw new Exception("Failed to deserialize xml payload");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static (string query, string proto, string domain) ParseQuery(string query)
|
public static (string query, string domain) ParseQuery(string query)
|
||||||
{
|
{
|
||||||
string domain;
|
string domain;
|
||||||
string proto;
|
|
||||||
query = query.StartsWith("acct:") ? $"@{query[5..]}" : query;
|
query = query.StartsWith("acct:") ? $"@{query[5..]}" : query;
|
||||||
if (query.StartsWith("http://") || query.StartsWith("https://"))
|
if (query.StartsWith("http://"))
|
||||||
|
throw GracefulException.BadRequest($"Invalid query scheme: {query}");
|
||||||
|
|
||||||
|
if (query.StartsWith("https://"))
|
||||||
{
|
{
|
||||||
var uri = new Uri(query);
|
var uri = new Uri(query);
|
||||||
domain = uri.Host;
|
domain = uri.Host;
|
||||||
proto = query.StartsWith("http://") ? "http" : "https";
|
|
||||||
}
|
}
|
||||||
else if (query.StartsWith('@'))
|
else if (query.StartsWith('@'))
|
||||||
{
|
{
|
||||||
proto = "https";
|
|
||||||
var split = query.Split('@');
|
var split = query.Split('@');
|
||||||
|
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
|
@ -103,14 +103,14 @@ public class WebFingerService(
|
||||||
throw new GracefulException(HttpStatusCode.BadRequest, $"Invalid query: {query}");
|
throw new GracefulException(HttpStatusCode.BadRequest, $"Invalid query: {query}");
|
||||||
}
|
}
|
||||||
|
|
||||||
return (query, proto, domain);
|
return (query, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> GetWebFingerUrlAsync(string query, string proto, string domain)
|
private async Task<string> GetWebFingerUrlAsync(string query, string domain)
|
||||||
{
|
{
|
||||||
var template = await GetWebFingerTemplateFromHostMetaXmlAsync(proto, domain) ??
|
var template = await GetWebFingerTemplateFromHostMetaXmlAsync(domain) ??
|
||||||
await GetWebFingerTemplateFromHostMetaJsonAsync(proto, domain) ??
|
await GetWebFingerTemplateFromHostMetaJsonAsync(domain) ??
|
||||||
$"{proto}://{domain}/.well-known/webfinger?resource={{uri}}";
|
$"https://{domain}/.well-known/webfinger?resource={{uri}}";
|
||||||
|
|
||||||
var finalQuery = query.StartsWith('@') ? $"acct:{query[1..]}" : query;
|
var finalQuery = query.StartsWith('@') ? $"acct:{query[1..]}" : query;
|
||||||
var encoded = UrlEncoder.Default.Encode(finalQuery);
|
var encoded = UrlEncoder.Default.Encode(finalQuery);
|
||||||
|
@ -118,11 +118,11 @@ public class WebFingerService(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Technically, we should be checking for rel=lrdd *and* type=application/jrd+json, but nearly all implementations break this, so we can't.
|
// Technically, we should be checking for rel=lrdd *and* type=application/jrd+json, but nearly all implementations break this, so we can't.
|
||||||
private async Task<string?> GetWebFingerTemplateFromHostMetaXmlAsync(string proto, string domain)
|
private async Task<string?> GetWebFingerTemplateFromHostMetaXmlAsync(string domain)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var hostMetaUrl = $"{proto}://{domain}/.well-known/host-meta";
|
var hostMetaUrl = $"https://{domain}/.well-known/host-meta";
|
||||||
using var res = await client.SendAsync(httpRqSvc.Get(hostMetaUrl, ["application/xrd+xml"]),
|
using var res = await client.SendAsync(httpRqSvc.Get(hostMetaUrl, ["application/xrd+xml"]),
|
||||||
HttpCompletionOption.ResponseHeadersRead);
|
HttpCompletionOption.ResponseHeadersRead);
|
||||||
await using var stream = await res.Content.ReadAsStreamAsync();
|
await using var stream = await res.Content.ReadAsStreamAsync();
|
||||||
|
@ -145,11 +145,11 @@ public class WebFingerService(
|
||||||
}
|
}
|
||||||
|
|
||||||
// See above comment as for why jrd+json is commented out.
|
// See above comment as for why jrd+json is commented out.
|
||||||
private async Task<string?> GetWebFingerTemplateFromHostMetaJsonAsync(string proto, string domain)
|
private async Task<string?> GetWebFingerTemplateFromHostMetaJsonAsync(string domain)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var hostMetaUrl = $"{proto}://{domain}/.well-known/host-meta.json";
|
var hostMetaUrl = $"https://{domain}/.well-known/host-meta.json";
|
||||||
using var res = await client.SendAsync(httpRqSvc.Get(hostMetaUrl, ["application/jrd+json"]),
|
using var res = await client.SendAsync(httpRqSvc.Get(hostMetaUrl, ["application/jrd+json"]),
|
||||||
HttpCompletionOption.ResponseHeadersRead);
|
HttpCompletionOption.ResponseHeadersRead);
|
||||||
var deserialized = await res.Content.ReadFromJsonAsync<HostMetaResponse>();
|
var deserialized = await res.Content.ReadFromJsonAsync<HostMetaResponse>();
|
||||||
|
@ -171,7 +171,7 @@ public class WebFingerService(
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var hostMetaUrl = $"{proto}://{domain}/.well-known/host-meta";
|
var hostMetaUrl = $"https://{domain}/.well-known/host-meta";
|
||||||
using var res = await client.SendAsync(httpRqSvc.Get(hostMetaUrl, ["application/jrd+json"]),
|
using var res = await client.SendAsync(httpRqSvc.Get(hostMetaUrl, ["application/jrd+json"]),
|
||||||
HttpCompletionOption.ResponseHeadersRead);
|
HttpCompletionOption.ResponseHeadersRead);
|
||||||
var deserialized = await res.Content.ReadFromJsonAsync<HostMetaResponse>();
|
var deserialized = await res.Content.ReadFromJsonAsync<HostMetaResponse>();
|
||||||
|
|
Loading…
Add table
Reference in a new issue