Merge branch 'main' into quenting/optional-email

This commit is contained in:
Quentin Gliech
2025-01-20 11:31:48 +01:00
committed by GitHub
25 changed files with 76 additions and 96 deletions

14
.config/nextest.toml Normal file
View File

@@ -0,0 +1,14 @@
[test-groups]
database = { max-threads = 1 }
[profile.default]
retries = 1
# sqlx has a problem with nextest, as it uses a process-local semaphore to have
# tests use different databases. This doesn't work with nextest, as it has a
# process-per-test model, which is why we need to make sure only one test uses
# the database at a time.
# See https://github.com/launchbadge/sqlx/pull/3334
[[profile.default.overrides]]
filter = 'package(mas-handlers) or package(mas-storage-pg)'
test-group = 'database'

View File

@@ -61,7 +61,9 @@ jobs:
version: 0.13.0
- name: Install cargo-zigbuild
run: curl -L https://github.com/rust-cross/cargo-zigbuild/releases/download/v0.19.1/cargo-zigbuild-v0.19.1.x86_64-unknown-linux-musl.tar.gz | tar -z -x -C /usr/local/bin
uses: taiki-e/install-action@v2
with:
tool: cargo-zigbuild
- name: Install frontend Node
uses: actions/setup-node@v4.1.0

View File

@@ -263,7 +263,9 @@ jobs:
rustup default stable
- name: Install nextest
uses: taiki-e/install-action@nextest
uses: taiki-e/install-action@v2
with:
tool: cargo-nextest
- name: Setup sccache
uses: mozilla-actions/sccache-action@v0.0.7
@@ -290,7 +292,7 @@ jobs:
strategy:
matrix:
partition: [1, 2]
partition: [1, 2, 3]
services:
postgres:
@@ -313,7 +315,9 @@ jobs:
- run: mkdir -p ~/.cargo/bin
- name: Install nextest
uses: taiki-e/install-action@nextest
uses: taiki-e/install-action@v2
with:
tool: cargo-nextest
- name: Install Node
uses: actions/setup-node@v4.1.0
@@ -346,11 +350,9 @@ jobs:
env:
DATABASE_URL: postgresql://postgres:postgres@localhost/postgres
run: |
~/.cargo/bin/cargo-nextest nextest run --archive-file nextest-archive.tar.zst \
--partition count:${{ matrix.partition }}/2 \
--retries 1
# --retries is a workaround for sqlx not playing nice with nextest
# Waiting for https://github.com/launchbadge/sqlx/pull/3334
~/.cargo/bin/cargo-nextest nextest run \
--archive-file nextest-archive.tar.zst \
--partition count:${{ matrix.partition }}/3
syn2mas:
name: Check syn2mas

View File

@@ -141,11 +141,10 @@ jobs:
- name: Setup sccache
uses: mozilla-actions/sccache-action@v0.0.7
- name: Download grcov
run: |
mkdir -p "${HOME}/.local/bin"
curl -sL https://github.com/mozilla/grcov/releases/download/v0.8.19/grcov-x86_64-unknown-linux-gnu.tar.bz2 | tar jxf - -C "${HOME}/.local/bin"
echo "$HOME/.local/bin" >> $GITHUB_PATH
- name: Install grcov
uses: taiki-e/install-action@v2
with:
tool: grcov
- name: Run test suite with profiling enabled
run: |

View File

@@ -30,10 +30,10 @@ jobs:
- name: Setup sccache
uses: mozilla-actions/sccache-action@v0.0.7
- name: Setup mdBook
uses: peaceiris/actions-mdbook@v2.0.0
- name: Install mdbook
uses: taiki-e/install-action@v2
with:
mdbook-version: '0.4.37'
tool: mdbook
- name: Install Node
uses: actions/setup-node@v4.1.0

39
Cargo.lock generated
View File

@@ -3105,15 +3105,10 @@ dependencies = [
"async-trait",
"axum",
"axum-extra",
"bytes",
"chrono",
"data-encoding",
"futures-util",
"headers",
"http",
"http-body",
"http-body-util",
"hyper-util",
"icu_locid",
"mas-data-model",
"mas-http",
@@ -3129,11 +3124,9 @@ dependencies = [
"sentry",
"serde",
"serde_json",
"serde_urlencoded",
"serde_with",
"thiserror 2.0.9",
"tokio",
"tower",
"tracing",
"ulid",
"url",
@@ -3152,10 +3145,7 @@ dependencies = [
"dialoguer",
"dotenvy",
"figment",
"http",
"http-body",
"http-body-util",
"httpdate",
"hyper",
"ipnetwork",
"itertools 0.13.0",
@@ -3166,20 +3156,17 @@ dependencies = [
"mas-handlers",
"mas-http",
"mas-i18n",
"mas-iana",
"mas-keystore",
"mas-listener",
"mas-matrix",
"mas-matrix-synapse",
"mas-policy",
"mas-router",
"mas-spa",
"mas-storage",
"mas-storage-pg",
"mas-tasks",
"mas-templates",
"mas-tower",
"oauth2-types",
"opentelemetry",
"opentelemetry-http",
"opentelemetry-jaeger-propagator",
@@ -3237,7 +3224,6 @@ dependencies = [
"serde",
"serde_json",
"serde_with",
"thiserror 2.0.9",
"tokio",
"tracing",
"ulid",
@@ -3248,6 +3234,7 @@ dependencies = [
name = "mas-data-model"
version = "0.12.0"
dependencies = [
"base64ct",
"chrono",
"crc",
"mas-iana",
@@ -3270,7 +3257,6 @@ name = "mas-email"
version = "0.12.0"
dependencies = [
"async-trait",
"headers",
"lettre",
"mas-templates",
"thiserror 2.0.9",
@@ -3314,14 +3300,12 @@ dependencies = [
"mas-oidc-client",
"mas-policy",
"mas-router",
"mas-spa",
"mas-storage",
"mas-storage-pg",
"mas-templates",
"mime",
"minijinja",
"minijinja-contrib",
"nonzero_ext",
"oauth2-types",
"opentelemetry",
"opentelemetry-semantic-conventions",
@@ -3428,7 +3412,6 @@ dependencies = [
"camino",
"convert_case",
"csv",
"futures-util",
"reqwest",
"serde",
"tokio",
@@ -3463,7 +3446,6 @@ dependencies = [
"sha2",
"signature",
"thiserror 2.0.9",
"tracing",
"url",
]
@@ -3476,7 +3458,6 @@ dependencies = [
"chacha20poly1305",
"const-oid",
"der",
"ecdsa",
"elliptic-curve",
"generic-array",
"insta",
@@ -3506,7 +3487,6 @@ dependencies = [
"http-body",
"hyper",
"hyper-util",
"libc",
"pin-project-lite",
"rustls-pemfile",
"socket2",
@@ -3527,10 +3507,7 @@ version = "0.12.0"
dependencies = [
"anyhow",
"async-trait",
"http",
"serde",
"tokio",
"url",
]
[[package]]
@@ -3540,14 +3517,11 @@ dependencies = [
"anyhow",
"async-trait",
"http",
"mas-axum-utils",
"mas-http",
"mas-matrix",
"reqwest",
"serde",
"serde_json",
"thiserror 2.0.9",
"tower",
"tracing",
"url",
"urlencoding",
@@ -3575,8 +3549,6 @@ dependencies = [
"mime",
"oauth2-types",
"p256",
"pem-rfc7468",
"pkcs8",
"rand",
"rand_chacha",
"reqwest",
@@ -3633,7 +3605,6 @@ version = "0.12.0"
dependencies = [
"async-trait",
"chrono",
"cron",
"futures-util",
"mas-data-model",
"mas-iana",
@@ -3667,7 +3638,6 @@ dependencies = [
"rand_chacha",
"sea-query",
"sea-query-binder",
"serde",
"serde_json",
"sqlx",
"thiserror 2.0.9",
@@ -3682,12 +3652,9 @@ name = "mas-tasks"
version = "0.12.0"
dependencies = [
"anyhow",
"async-stream",
"async-trait",
"chrono",
"cron",
"event-listener 5.3.1",
"futures-lite",
"mas-data-model",
"mas-email",
"mas-i18n",
@@ -3696,7 +3663,6 @@ dependencies = [
"mas-storage",
"mas-storage-pg",
"mas-templates",
"mas-tower",
"opentelemetry",
"opentelemetry-semantic-conventions",
"rand",
@@ -3707,11 +3673,9 @@ dependencies = [
"thiserror 2.0.9",
"tokio",
"tokio-util",
"tower",
"tracing",
"tracing-opentelemetry",
"ulid",
"url",
]
[[package]]
@@ -4014,7 +3978,6 @@ dependencies = [
"assert_matches",
"chrono",
"data-encoding",
"http",
"language-tags",
"mas-iana",
"mas-jose",

View File

@@ -82,6 +82,10 @@ version = "0.7.9"
version = "0.9.6"
features = ["cookie-private", "cookie-key-expansion", "typed-header"]
# Constant-time base64
[workspace.dependencies.base64ct]
version = "1.6.0"
# Bytes
[workspace.dependencies.bytes]
version = "1.9.0"

View File

@@ -15,15 +15,10 @@ workspace = true
async-trait.workspace = true
axum.workspace = true
axum-extra.workspace = true
bytes.workspace = true
chrono.workspace = true
data-encoding = "2.6.0"
futures-util.workspace = true
headers.workspace = true
http.workspace = true
http-body.workspace = true
http-body-util.workspace = true
hyper-util.workspace = true
icu_locid = "1.4.0"
mime = "0.3.17"
rand.workspace = true
@@ -31,11 +26,9 @@ reqwest.workspace = true
sentry.workspace = true
serde.workspace = true
serde_with = "3.12.0"
serde_urlencoded = "0.7.1"
serde_json.workspace = true
thiserror.workspace = true
tokio.workspace = true
tower.workspace = true
tracing.workspace = true
url.workspace = true
ulid.workspace = true

View File

@@ -23,9 +23,6 @@ console = "0.15.10"
dialoguer = { version = "0.11.0", features = ["fuzzy-select"] }
dotenvy = "0.15.7"
figment.workspace = true
httpdate = "1.0.3"
http.workspace = true
http-body.workspace = true
http-body-util.workspace = true
hyper.workspace = true
ipnetwork = "0.20.0"
@@ -69,20 +66,17 @@ mas-email.workspace = true
mas-handlers.workspace = true
mas-http.workspace = true
mas-i18n.workspace = true
mas-iana.workspace = true
mas-keystore.workspace = true
mas-listener.workspace = true
mas-matrix.workspace = true
mas-matrix-synapse.workspace = true
mas-policy.workspace = true
mas-router.workspace = true
mas-spa.workspace = true
mas-storage.workspace = true
mas-storage-pg.workspace = true
mas-tasks.workspace = true
mas-templates.workspace = true
mas-tower.workspace = true
oauth2-types.workspace = true
[build-dependencies]
anyhow.workspace = true

View File

@@ -14,8 +14,6 @@ workspace = true
[dependencies]
tokio.workspace = true
tracing.workspace = true
thiserror.workspace = true
anyhow.workspace = true
camino = { workspace = true, features = ["serde1"] }

View File

@@ -12,6 +12,7 @@ publish = false
workspace = true
[dependencies]
base64ct.workspace = true
chrono.workspace = true
thiserror.workspace = true
serde.workspace = true

View File

@@ -4,6 +4,7 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Please see LICENSE in the repository root for full details.
use base64ct::{Base64Url, Encoding};
use chrono::{DateTime, Utc};
use crc::{Crc, CRC_32_ISO_HDLC};
use mas_iana::oauth::OAuthTokenTypeHint;
@@ -294,7 +295,7 @@ impl TokenType {
pub fn check(token: &str) -> Result<TokenType, TokenFormatError> {
// these are legacy tokens imported from Synapse
// we don't do any validation on them and continue as is
if token.starts_with("syt_") {
if token.starts_with("syt_") || is_likely_synapse_macaroon(token) {
return Ok(TokenType::CompatAccessToken);
}
if token.starts_with("syr_") {
@@ -344,6 +345,20 @@ impl PartialEq<OAuthTokenTypeHint> for TokenType {
}
}
/// Returns true if and only if a token looks like it may be a macaroon.
///
/// Macaroons are a standard for tokens that support attenuation.
/// Synapse used them for old sessions and for guest sessions.
///
/// We won't bother to decode them fully, but we can check to see if the first
/// constraint is the `location` constraint.
fn is_likely_synapse_macaroon(token: &str) -> bool {
let Ok(decoded) = Base64Url::decode_vec(token) else {
return false;
};
decoded.get(4..13) == Some(b"location ")
}
const NUM: [u8; 62] = *b"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
fn base62_encode(mut num: u32) -> String {
@@ -420,6 +435,25 @@ mod tests {
);
}
#[test]
fn test_is_likely_synapse_macaroon() {
// This is just the prefix of a Synapse macaroon, but it's enough to make the
// sniffing work
assert!(is_likely_synapse_macaroon(
"MDAxYmxvY2F0aW9uIGxpYnJlcHVzaC5uZXQKMDAx"
));
// Whilst this is a macaroon, it's not a Synapse macaroon
assert!(! is_likely_synapse_macaroon("MDAxY2xvY2F0aW9uIGh0dHA6Ly9teWJhbmsvCjAwMjZpZGVudGlmaWVyIHdlIHVzZWQgb3VyIHNlY3JldCBrZXkKMDAyZnNpZ25hdHVyZSDj2eApCFJsTAA5rhURQRXZf91ovyujebNCqvD2F9BVLwo"));
// None of these are macaroons
assert!(!is_likely_synapse_macaroon(
"eyJARTOhearotnaeisahtoarsnhiasra.arsohenaor.oarnsteao"
));
assert!(!is_likely_synapse_macaroon("...."));
assert!(!is_likely_synapse_macaroon("aaa"));
}
#[test]
fn test_generate_and_check() {
const COUNT: usize = 500; // Generate 500 of each token type

View File

@@ -13,7 +13,6 @@ workspace = true
[dependencies]
async-trait.workspace = true
headers.workspace = true
lettre.workspace = true
thiserror.workspace = true
tracing.workspace = true

View File

@@ -68,7 +68,7 @@ pbkdf2 = { version = "0.12.2", features = [
zeroize = "1.8.1"
# Various data types and utilities
base64ct = "1.6.0"
base64ct.workspace = true
camino.workspace = true
chrono.workspace = true
elliptic-curve.workspace = true
@@ -81,7 +81,6 @@ url.workspace = true
mime = "0.3.17"
minijinja.workspace = true
minijinja-contrib.workspace = true
nonzero_ext.workspace = true
rand.workspace = true
rand_chacha = "0.3.1"
headers.workspace = true
@@ -99,7 +98,6 @@ mas-matrix.workspace = true
mas-oidc-client.workspace = true
mas-policy.workspace = true
mas-router.workspace = true
mas-spa.workspace = true
mas-storage.workspace = true
mas-storage-pg.workspace = true
mas-templates.workspace = true

View File

@@ -17,7 +17,6 @@ async-trait.workspace = true
camino.workspace = true
convert_case = "0.6.0"
csv = "1.3.1"
futures-util.workspace = true
reqwest.workspace = true
serde.workspace = true
tokio.workspace = true

View File

@@ -32,7 +32,6 @@ serde_with = "3.12.0"
sha2 = { version = "0.10.8", features = ["oid"] }
signature = "2.2.0"
thiserror.workspace = true
tracing.workspace = true
url.workspace = true
mas-iana.workspace = true

View File

@@ -15,7 +15,6 @@ workspace = true
aead = { version = "0.5.2", features = ["std"] }
const-oid = { version = "0.9.6", features = ["std"] }
der = { version = "0.7.9", features = ["std"] }
ecdsa = { version = "0.16.9", features = ["std"] }
elliptic-curve.workspace = true
k256.workspace = true
p256.workspace = true

View File

@@ -17,7 +17,6 @@ futures-util.workspace = true
http-body.workspace = true
hyper = { workspace = true, features = ["server"] }
hyper-util.workspace = true
libc = "0.2.169"
pin-project-lite = "0.2.16"
socket2 = "0.5.8"
thiserror.workspace = true

View File

@@ -17,13 +17,10 @@ async-trait.workspace = true
http.workspace = true
reqwest.workspace = true
serde.workspace = true
serde_json.workspace = true
thiserror.workspace = true
tower.workspace = true
tracing.workspace = true
url.workspace = true
urlencoding = "2.1.3"
mas-axum-utils.workspace = true
mas-http.workspace = true
mas-matrix.workspace = true

View File

@@ -13,8 +13,5 @@ workspace = true
[dependencies]
anyhow.workspace = true
serde.workspace = true
async-trait.workspace = true
http.workspace = true
tokio.workspace = true
url.workspace = true

View File

@@ -12,7 +12,6 @@ repository.workspace = true
workspace = true
[dependencies]
http.workspace = true
serde.workspace = true
serde_json.workspace = true
language-tags = { version = "0.3.2", features = ["serde"] }

View File

@@ -21,8 +21,6 @@ headers.workspace = true
http.workspace = true
language-tags = "0.3.2"
mime = "0.3.17"
pem-rfc7468.workspace = true
pkcs8.workspace = true
p256.workspace = true
rand.workspace = true
reqwest.workspace = true

View File

@@ -17,7 +17,6 @@ sqlx.workspace = true
sea-query.workspace = true
sea-query-binder.workspace = true
chrono.workspace = true
serde.workspace = true
serde_json.workspace = true
thiserror.workspace = true
tracing.workspace = true

View File

@@ -14,7 +14,6 @@ workspace = true
[dependencies]
async-trait.workspace = true
chrono.workspace = true
cron.workspace = true
futures-util.workspace = true
opentelemetry.workspace = true
rand_core = "0.6.4"

View File

@@ -13,25 +13,20 @@ workspace = true
[dependencies]
anyhow.workspace = true
async-stream = "0.3.6"
async-trait.workspace = true
cron.workspace = true
chrono.workspace = true
event-listener = "5.3.1"
futures-lite = "2.5.0"
rand.workspace = true
rand_chacha = "0.3.1"
sqlx.workspace = true
thiserror.workspace = true
tokio.workspace = true
tokio-util.workspace = true
tower.workspace = true
tracing.workspace = true
tracing-opentelemetry.workspace = true
opentelemetry.workspace = true
opentelemetry-semantic-conventions.workspace = true
ulid.workspace = true
url.workspace = true
serde.workspace = true
serde_json.workspace = true
@@ -43,4 +38,3 @@ mas-router.workspace = true
mas-storage.workspace = true
mas-storage-pg.workspace = true
mas-templates.workspace = true
mas-tower.workspace = true