Skip to content

Commit

Permalink
validate join room from 3pid
Browse files Browse the repository at this point in the history
  • Loading branch information
ggazzo committed Dec 17, 2024
1 parent 6d3b6c6 commit 524c698
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 33 deletions.
2 changes: 2 additions & 0 deletions packages/core/src/events/m.room.member.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ declare module "./eventBase" {
age_ts: number;
};
content: {
join_authorised_via_users_server?: string;
membership: Membership;
};
};
Expand All @@ -25,6 +26,7 @@ export interface RoomMemberEvent extends EventBase {
type: "m.room.member";
content: {
membership: Membership;
join_authorised_via_users_server?: string;
};
state_key: string;
unsigned: {
Expand Down
8 changes: 5 additions & 3 deletions packages/homeserver/src/plugins/mongodb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ export const routerWithMongodb = (db: Db) =>
}
const [, publicKey] =
Object.entries(server.keys).find(
([protocolAndVersion, value]) => protocolAndVersion === key && value.validUntil > Date.now(),
([protocolAndVersion, value]) =>
protocolAndVersion === key && value.validUntil > Date.now(),
) ?? [];
return publicKey?.key;
};
Expand All @@ -145,8 +146,8 @@ export const routerWithMongodb = (db: Db) =>
key: value,
validUntil,
},
}
}
},
},
},
{ upsert: true },
);
Expand All @@ -171,4 +172,5 @@ export type Context = InferContext<ReturnType<typeof routerWithMongodb>>;
export type EventStore = {
_id: string;
event: EventBase;
staged?: true;
};
82 changes: 52 additions & 30 deletions packages/homeserver/src/routes/federation/sendTransaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
} from "../../procedures/getPublicKeyFromServer";
import { isConfigContext } from "../../plugins/isConfigContext";
import { MatrixError } from "../../errors";
import { isRoomMemberEvent } from "@hs/core/src/events/m.room.member";

export const sendTransactionRoute = new Elysia().put(
"/send/:txnId",
Expand Down Expand Up @@ -99,42 +100,63 @@ export const sendTransactionRoute = new Elysia().put(
}

const validatePdu = async (pdu: SignedJson<HashedEvent<EventBase>>) => {
const origin = pdu.sender.split(":").pop() as string;

if (!origin) {
throw new MatrixError("400", "Invalid origin");
const extractOrigin = (sender: string) =>
sender.split(":").pop() as string;

const isInviteVia3pid = (event: EventBase) =>
isRoomMemberEvent(event) &&
event.content.membership === "invite" &&
"third_party_invite" in event.content;

const origins = [
!isInviteVia3pid(pdu) && extractOrigin(pdu.sender),
// extractOrigin(pdu.sender) !== extractOrigin(pdu.event_id) &&
// extractOrigin(pdu.event_id),
isRoomMemberEvent(pdu) &&
pdu.content.join_authorised_via_users_server &&
extractOrigin(pdu.content.join_authorised_via_users_server),
].filter(Boolean) as string[];

if (!origins.length) {
throw new MatrixError("400", "Invalid Signature");
}
const [signature] = await getSignaturesFromRemote(pdu, origin);
const { signatures, unsigned, ...rest } = pdu;

const getPublicKeyFromServer = makeGetPublicKeyFromServerProcedure(
context.mongo.getValidPublicKeyFromLocal,
() =>
getPublicKeyFromRemoteServer(
origin,
config.name,
`${signature.algorithm}:${signature.version}`,
),
for await (const origin of origins) {
const { signatures, unsigned, ...rest } = pdu;

context.mongo.storePublicKey,
);
const [signature] = await getSignaturesFromRemote(pdu, origin);

const publicKey = await getPublicKeyFromServer(
origin,
`${signature.algorithm}:${signature.version}`,
);
const getPublicKeyFromServer = makeGetPublicKeyFromServerProcedure(
context.mongo.getValidPublicKeyFromLocal,
() =>
getPublicKeyFromRemoteServer(
origin,
config.name,
`${signature.algorithm}:${signature.version}`,
),

if (
!verifyJsonSignature(
pruneEventDict(rest),
context.mongo.storePublicKey,
);

const publicKey = await getPublicKeyFromServer(
origin,
Uint8Array.from(atob(signature.signature), (c) => c.charCodeAt(0)),
Uint8Array.from(atob(publicKey), (c) => c.charCodeAt(0)),
signature.algorithm,
signature.version,
)
) {
throw new MatrixError("400", "Invalid signature");
`${signature.algorithm}:${signature.version}`,
);

if (
!verifyJsonSignature(
pruneEventDict(rest),
origin,
Uint8Array.from(atob(signature.signature), (c) =>
c.charCodeAt(0),
),
Uint8Array.from(atob(publicKey), (c) => c.charCodeAt(0)),
signature.algorithm,
signature.version,
)
) {
throw new MatrixError("400", "Invalid signature");
}
}
};

Expand Down

0 comments on commit 524c698

Please sign in to comment.