summaryrefslogtreecommitdiff
path: root/packages/backend/src/server/ActivityPubServerService.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/backend/src/server/ActivityPubServerService.ts')
-rw-r--r--packages/backend/src/server/ActivityPubServerService.ts87
1 files changed, 34 insertions, 53 deletions
diff --git a/packages/backend/src/server/ActivityPubServerService.ts b/packages/backend/src/server/ActivityPubServerService.ts
index 3255d64621..753eaad047 100644
--- a/packages/backend/src/server/ActivityPubServerService.ts
+++ b/packages/backend/src/server/ActivityPubServerService.ts
@@ -3,11 +3,10 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
-import * as crypto from 'node:crypto';
import { IncomingMessage } from 'node:http';
import { Inject, Injectable } from '@nestjs/common';
import fastifyAccepts from '@fastify/accepts';
-import httpSignature from '@peertube/http-signature';
+import { verifyDigestHeader, parseRequestSignature } from '@misskey-dev/node-http-message-signatures';
import { Brackets, In, IsNull, LessThan, Not } from 'typeorm';
import accepts from 'accepts';
import vary from 'vary';
@@ -31,12 +30,17 @@ import { IActivity } from '@/core/activitypub/type.js';
import { isQuote, isRenote } from '@/misc/is-renote.js';
import type { FastifyInstance, FastifyRequest, FastifyReply, FastifyPluginOptions, FastifyBodyParser } from 'fastify';
import type { FindOptionsWhere } from 'typeorm';
+import { LoggerService } from '@/core/LoggerService.js';
+import Logger from '@/logger.js';
const ACTIVITY_JSON = 'application/activity+json; charset=utf-8';
const LD_JSON = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"; charset=utf-8';
@Injectable()
export class ActivityPubServerService {
+ private logger: Logger;
+ private inboxLogger: Logger;
+
constructor(
@Inject(DI.config)
private config: Config,
@@ -71,8 +75,11 @@ export class ActivityPubServerService {
private queueService: QueueService,
private userKeypairService: UserKeypairService,
private queryService: QueryService,
+ private loggerService: LoggerService,
) {
//this.createServer = this.createServer.bind(this);
+ this.logger = this.loggerService.getLogger('server-ap', 'gray');
+ this.inboxLogger = this.logger.createSubLogger('inbox', 'gray');
}
@bindThis
@@ -100,70 +107,44 @@ export class ActivityPubServerService {
}
@bindThis
- private inbox(request: FastifyRequest, reply: FastifyReply) {
- let signature;
-
- try {
- signature = httpSignature.parseRequest(request.raw, { 'headers': [] });
- } catch (e) {
- reply.code(401);
+ private async inbox(request: FastifyRequest, reply: FastifyReply) {
+ if (request.body == null) {
+ this.inboxLogger.warn('request body is empty');
+ reply.code(400);
return;
}
- if (signature.params.headers.indexOf('host') === -1
- || request.headers.host !== this.config.host) {
- // Host not specified or not match.
+ let signature: ReturnType<typeof parseRequestSignature>;
+
+ const verifyDigest = await verifyDigestHeader(request.raw, request.rawBody || '', true);
+ if (verifyDigest !== true) {
+ this.inboxLogger.warn('digest verification failed');
reply.code(401);
return;
}
- if (signature.params.headers.indexOf('digest') === -1) {
- // Digest not found.
- reply.code(401);
- } else {
- const digest = request.headers.digest;
-
- if (typeof digest !== 'string') {
- // Huh?
- reply.code(401);
- return;
- }
-
- const re = /^([a-zA-Z0-9\-]+)=(.+)$/;
- const match = digest.match(re);
-
- if (match == null) {
- // Invalid digest
- reply.code(401);
- return;
- }
-
- const algo = match[1].toUpperCase();
- const digestValue = match[2];
-
- if (algo !== 'SHA-256') {
- // Unsupported digest algorithm
- reply.code(401);
- return;
- }
+ try {
+ signature = parseRequestSignature(request.raw, {
+ requiredInputs: {
+ draft: ['(request-target)', 'digest', 'host', 'date'],
+ },
+ });
+ } catch (err) {
+ this.inboxLogger.warn('signature header parsing failed', { err });
- if (request.rawBody == null) {
- // Bad request
- reply.code(400);
+ if (typeof request.body === 'object' && 'signature' in request.body) {
+ // LD SignatureがあればOK
+ this.queueService.inbox(request.body as IActivity, null);
+ reply.code(202);
return;
}
- const hash = crypto.createHash('sha256').update(request.rawBody).digest('base64');
-
- if (hash !== digestValue) {
- // Invalid digest
- reply.code(401);
- return;
- }
+ this.inboxLogger.warn('signature header parsing failed and LD signature not found');
+ reply.code(401);
+ return;
}
this.queueService.inbox(request.body as IActivity, signature);
-
reply.code(202);
}
@@ -640,7 +621,7 @@ export class ActivityPubServerService {
if (this.userEntityService.isLocalUser(user)) {
reply.header('Cache-Control', 'public, max-age=180');
this.setResponseType(request, reply);
- return (this.apRendererService.addContext(this.apRendererService.renderKey(user, keypair)));
+ return (this.apRendererService.addContext(this.apRendererService.renderKey(user, keypair.publicKey)));
} else {
reply.code(400);
return;