From 387dc4bb4b57b5071de3f2180c591c42d3ddd5b3 Mon Sep 17 00:00:00 2001 From: dakkar Date: Sat, 23 Nov 2024 17:51:09 +0000 Subject: UNTESTED maybe laxer match on authority - fixes #815 --- packages/backend/src/core/UtilityService.ts | 9 +++++++++ .../backend/src/core/activitypub/ApRequestService.ts | 2 +- .../backend/src/core/activitypub/ApResolverService.ts | 2 +- .../backend/src/core/activitypub/models/ApNoteService.ts | 6 +++--- .../src/core/activitypub/models/ApPersonService.ts | 16 ++++++++-------- 5 files changed, 22 insertions(+), 13 deletions(-) (limited to 'packages/backend/src/core') diff --git a/packages/backend/src/core/UtilityService.ts b/packages/backend/src/core/UtilityService.ts index 4c6d539e16..c84e7f212b 100644 --- a/packages/backend/src/core/UtilityService.ts +++ b/packages/backend/src/core/UtilityService.ts @@ -7,6 +7,7 @@ import { URL } from 'node:url'; import { toASCII } from 'punycode'; import { Inject, Injectable } from '@nestjs/common'; import RE2 from 're2'; +import psl from 'psl'; import { DI } from '@/di-symbols.js'; import type { Config } from '@/config.js'; import { bindThis } from '@/decorators.js'; @@ -122,6 +123,14 @@ export class UtilityService { return host; } + @bindThis + public punyHostPSLDomain(url: string): string { + const urlObj = new URL(url); + const domain = psl.get(urlObj.hostname) ?? urlObj.hostname; + const host = `${this.toPuny(domain)}${urlObj.port.length > 0 ? ':' + urlObj.port : ''}`; + return host; + } + public isFederationAllowedHost(host: string): boolean { if (this.meta.federation === 'none') return false; if (this.meta.federation === 'specified' && !this.meta.federationHosts.some(x => `.${host.toLowerCase()}`.endsWith(`.${x}`))) return false; diff --git a/packages/backend/src/core/activitypub/ApRequestService.ts b/packages/backend/src/core/activitypub/ApRequestService.ts index eeff73385b..0dea615cb0 100644 --- a/packages/backend/src/core/activitypub/ApRequestService.ts +++ b/packages/backend/src/core/activitypub/ApRequestService.ts @@ -243,7 +243,7 @@ export class ApRequestService { if (alternate) { const href = alternate.getAttribute('href'); if (href) { - if (this.utilityService.punyHost(url) === this.utilityService.punyHost(href)) { + if (this.utilityService.punyHostPSLDomain(url) === this.utilityService.punyHostPSLDomain(href)) { return await this.signedGet(href, user, false); } } diff --git a/packages/backend/src/core/activitypub/ApResolverService.ts b/packages/backend/src/core/activitypub/ApResolverService.ts index d4964d544d..e56b9ebc99 100644 --- a/packages/backend/src/core/activitypub/ApResolverService.ts +++ b/packages/backend/src/core/activitypub/ApResolverService.ts @@ -131,7 +131,7 @@ export class Resolver { throw new UnrecoverableError(`invalid AP object ${value}: missing id`); } - if (this.utilityService.punyHost(object.id) !== this.utilityService.punyHost(value)) { + if (this.utilityService.punyHostPSLDomain(object.id) !== this.utilityService.punyHostPSLDomain(value)) { throw new UnrecoverableError(`invalid AP object ${value}: id ${object.id} has different host`); } diff --git a/packages/backend/src/core/activitypub/models/ApNoteService.ts b/packages/backend/src/core/activitypub/models/ApNoteService.ts index 3d4a33ded2..b8aa67e9ea 100644 --- a/packages/backend/src/core/activitypub/models/ApNoteService.ts +++ b/packages/backend/src/core/activitypub/models/ApNoteService.ts @@ -192,8 +192,8 @@ export class ApNoteService { throw new UnrecoverableError(`unexpected schema of note.url ${url} in ${entryUri}`); } - if (this.utilityService.punyHost(url) !== this.utilityService.punyHost(note.id)) { - throw new Error(`note url <> uri host mismatch: ${url} <> ${note.id} in ${entryUri}`); + if (this.utilityService.punyHostPSLDomain(url) !== this.utilityService.punyHostPSLDomain(note.id)) { + throw new UnrecoverableError(`note url <> uri host mismatch: ${url} <> ${note.id} in ${entryUri}`); } } @@ -444,7 +444,7 @@ export class ApNoteService { throw new UnrecoverableError(`unexpected schema of note.url ${url} in ${noteUri}`); } - if (this.utilityService.punyHost(url) !== this.utilityService.punyHost(note.id)) { + if (this.utilityService.punyHostPSLDomain(url) !== this.utilityService.punyHostPSLDomain(note.id)) { throw new UnrecoverableError(`note url <> id host mismatch: ${url} <> ${note.id} in ${noteUri}`); } } diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts index cd6078b2ed..598486cd84 100644 --- a/packages/backend/src/core/activitypub/models/ApPersonService.ts +++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts @@ -138,7 +138,7 @@ export class ApPersonService implements OnModuleInit { */ @bindThis private validateActor(x: IObject, uri: string): IActor { - const expectHost = this.utilityService.punyHost(uri); + const expectHost = this.utilityService.punyHostPSLDomain(uri); if (!isActor(x)) { throw new UnrecoverableError(`invalid Actor type '${x.type}' in ${uri}`); @@ -152,7 +152,7 @@ export class ApPersonService implements OnModuleInit { throw new UnrecoverableError(`invalid Actor ${uri} - wrong inbox type`); } - const inboxHost = this.utilityService.punyHost(x.inbox); + const inboxHost = this.utilityService.punyHostPSLDomain(x.inbox); if (inboxHost !== expectHost) { throw new UnrecoverableError(`invalid Actor ${uri} - wrong inbox ${inboxHost}`); } @@ -160,7 +160,7 @@ export class ApPersonService implements OnModuleInit { const sharedInboxObject = x.sharedInbox ?? (x.endpoints ? x.endpoints.sharedInbox : undefined); if (sharedInboxObject != null) { const sharedInbox = getApId(sharedInboxObject); - if (!(typeof sharedInbox === 'string' && sharedInbox.length > 0 && this.utilityService.punyHost(sharedInbox) === expectHost)) { + if (!(typeof sharedInbox === 'string' && sharedInbox.length > 0 && this.utilityService.punyHostPSLDomain(sharedInbox) === expectHost)) { throw new UnrecoverableError(`invalid Actor ${uri} - wrong shared inbox ${sharedInbox}`); } } @@ -170,7 +170,7 @@ export class ApPersonService implements OnModuleInit { if (xCollection != null) { const collectionUri = getApId(xCollection); if (typeof collectionUri === 'string' && collectionUri.length > 0) { - if (this.utilityService.punyHost(collectionUri) !== expectHost) { + if (this.utilityService.punyHostPSLDomain(collectionUri) !== expectHost) { throw new UnrecoverableError(`invalid Actor ${uri} - wrong ${collection} ${collectionUri}`); } } else if (collectionUri != null) { @@ -202,7 +202,7 @@ export class ApPersonService implements OnModuleInit { x.summary = truncate(x.summary, summaryLength); } - const idHost = this.utilityService.punyHost(x.id); + const idHost = this.utilityService.punyHostPSLDomain(x.id); if (idHost !== expectHost) { throw new UnrecoverableError(`invalid Actor ${uri} - wrong id ${x.id}`); } @@ -212,7 +212,7 @@ export class ApPersonService implements OnModuleInit { throw new UnrecoverableError(`invalid Actor ${uri} - wrong publicKey.id type`); } - const publicKeyIdHost = this.utilityService.punyHost(x.publicKey.id); + const publicKeyIdHost = this.utilityService.punyHostPSLDomain(x.publicKey.id); if (publicKeyIdHost !== expectHost) { throw new UnrecoverableError(`invalid Actor ${uri} - wrong publicKey.id ${x.publicKey.id}`); } @@ -351,7 +351,7 @@ export class ApPersonService implements OnModuleInit { throw new UnrecoverableError(`unexpected schema of person url ${url} in ${uri}`); } - if (this.utilityService.punyHost(url) !== this.utilityService.punyHost(person.id)) { + if (this.utilityService.punyHostPSLDomain(url) !== this.utilityService.punyHostPSLDomain(person.id)) { throw new UnrecoverableError(`person url <> uri host mismatch: ${url} <> ${person.id} in ${uri}`); } } @@ -563,7 +563,7 @@ export class ApPersonService implements OnModuleInit { throw new UnrecoverableError(`unexpected schema of person url ${url} in ${uri}`); } - if (this.utilityService.punyHost(url) !== this.utilityService.punyHost(person.id)) { + if (this.utilityService.punyHostPSLDomain(url) !== this.utilityService.punyHostPSLDomain(person.id)) { throw new UnrecoverableError(`person url <> uri host mismatch: ${url} <> ${person.id} in ${uri}`); } } -- cgit v1.2.3-freya