Skip to content

Commit 9500b55

Browse files
committed
pair route middlewares with rc and matrix protocol
1 parent b93b9d0 commit 9500b55

File tree

5 files changed

+48
-9
lines changed

5 files changed

+48
-9
lines changed

packages/federation-sdk/src/services/event-authorization.service.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,23 @@ export class EventAuthorizationService {
251251
return false;
252252
}
253253

254+
async checkAclForInvite(roomId: string, senderServer: string): Promise<void> {
255+
const state = await this.stateService.getLatestRoomState(roomId);
256+
257+
const aclEvent = state.get('m.room.server_acl:');
258+
if (!aclEvent) {
259+
return;
260+
}
261+
262+
const isAllowed = await this.checkServerAcl(aclEvent, senderServer);
263+
if (!isAllowed) {
264+
this.logger.warn(
265+
`ACL check failed: sender server ${senderServer} is denied by room ACL for room ${roomId}`,
266+
);
267+
throw new Error('Sender server denied by room ACL');
268+
}
269+
}
270+
254271
async serverHasAccessToResource(
255272
roomId: string,
256273
serverName: string,

packages/federation-sdk/src/services/invite.service.ts

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
} from '@rocket.chat/federation-room';
1111
import { singleton } from 'tsyringe';
1212
import { ConfigService } from './config.service';
13+
import { EventAuthorizationService } from './event-authorization.service';
1314
import { EventService } from './event.service';
1415
import { FederationService } from './federation.service';
1516
import { StateService } from './state.service';
@@ -30,6 +31,7 @@ export class InviteService {
3031
private readonly federationService: FederationService,
3132
private readonly stateService: StateService,
3233
private readonly configService: ConfigService,
34+
private readonly eventAuthorizationService: EventAuthorizationService,
3335
) {}
3436

3537
/**
@@ -145,6 +147,7 @@ export class InviteService {
145147
roomId: RoomID,
146148
eventId: EventID,
147149
roomVersion: RoomVersion,
150+
authenticatedServer: string,
148151
) {
149152
// SPEC: when a user invites another user on a different homeserver, a request to that homeserver to have the event signed and verified must be made
150153

@@ -165,8 +168,12 @@ export class InviteService {
165168

166169
await this.stateService.signEvent(inviteEvent);
167170

171+
// we are the host of the server
168172
if (residentServer === this.configService.serverName) {
169-
// we are the host of the server
173+
await this.eventAuthorizationService.checkAclForInvite(
174+
roomId,
175+
authenticatedServer,
176+
);
170177

171178
// attempt to persist the invite event as we already have the state
172179

@@ -184,14 +191,24 @@ export class InviteService {
184191

185192
// are we already in the room?
186193
try {
187-
await this.stateService.getRoomInformation(roomId);
194+
await this.eventAuthorizationService.checkAclForInvite(
195+
roomId,
196+
authenticatedServer,
197+
);
188198

189199
// if we have the state we try to persist the invite event
190200
await this.stateService.handlePdu(inviteEvent);
191201
if (inviteEvent.rejected) {
192202
throw new Error(inviteEvent.rejectReason);
193203
}
194-
} catch {
204+
} catch (error) {
205+
// check if this is an ACL error or authorization error, rethrow if so
206+
if (
207+
error instanceof Error &&
208+
error.message.includes('Sender server denied by room ACL')
209+
) {
210+
throw error;
211+
}
195212
// don't have state copy yet
196213
// console.error(e);
197214
// typical noop, we sign and return the event, nothing to do

packages/homeserver/src/controllers/federation/invite.controller.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,17 @@ export const invitePlugin = (app: Elysia) => {
1414

1515
return app.use(isAuthenticatedMiddleware(eventAuthService)).put(
1616
'/_matrix/federation/v2/invite/:roomId/:eventId',
17-
async ({ body, params: { roomId, eventId } }) => {
17+
async ({ body, params: { roomId, eventId }, authenticatedServer }) => {
18+
if (!authenticatedServer) {
19+
throw new Error('Missing authenticated server from request');
20+
}
21+
1822
return inviteService.processInvite(
1923
body.event,
2024
roomId as RoomID,
2125
eventId as EventID,
2226
body.room_version,
27+
authenticatedServer,
2328
);
2429
},
2530
{

packages/homeserver/src/controllers/federation/transactions.controller.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ export const transactionsPlugin = (app: Elysia) => {
7575
};
7676
},
7777
{
78-
use: isAuthenticatedMiddleware(eventAuthService),
78+
use: canAccessResourceMiddleware(eventAuthService, 'event'),
7979
params: GetEventParamsDto,
8080
response: {
8181
200: GetEventResponseDto,
@@ -124,7 +124,7 @@ export const transactionsPlugin = (app: Elysia) => {
124124
}
125125
},
126126
{
127-
use: isAuthenticatedMiddleware(eventAuthService),
127+
use: canAccessResourceMiddleware(eventAuthService, 'room'),
128128
params: BackfillParamsDto,
129129
query: BackfillQueryDto,
130130
response: {

packages/homeserver/src/middlewares/isAuthenticated.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export const isAuthenticatedMiddleware = (
1616
if (!authorizationHeader) {
1717
set.status = 401;
1818
return {
19-
authenticatedServer: null,
19+
authenticatedServer: undefined,
2020
};
2121
}
2222

@@ -42,7 +42,7 @@ export const isAuthenticatedMiddleware = (
4242
if (!isValid) {
4343
set.status = 401;
4444
return {
45-
authenticatedServer: null,
45+
authenticatedServer: undefined,
4646
};
4747
}
4848

@@ -53,7 +53,7 @@ export const isAuthenticatedMiddleware = (
5353
console.error('Authentication error:', error);
5454
set.status = 500;
5555
return {
56-
authenticatedServer: null,
56+
authenticatedServer: undefined,
5757
};
5858
}
5959
})

0 commit comments

Comments
 (0)