mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Switch to rustls and webpki-roots (#30025)
This change replaces OpenSSL with rustls and also the manually curated CA certs file with webpki-roots (effectively the same thing, but as a crate). Generally speaking the design of the network stack is the same. Changes: - Code around certificate overrides needed to be refactored to work with rustls so the various thread-safe list of certificates is refactored into `CertificateErrorOverrideManager` - hyper-rustls takes care of setting ALPN protocols for HTTP requests, so for WebSockets this is moved to the WebSocket code. - The safe set of cypher suites is chosen, which seem to correspond to the "Modern" configuration from [1]. This can be adjusted later. - Instead of passing a string of PEM CA certificates around, an enum is used that includes parsed Certificates (or the default which reads them from webpki-roots). - Code for starting up an SSL server for testing is cleaned up a little, due to the fact that the certificates need to be overriden explicitly now. This is due to the fact that the `webpki` crate is more stringent with self-signed certificates than SSL (CA certificates cannot used as end-entity certificates). [2] 1. https://wiki.mozilla.org/Security/Server_Side_TLS 2. https://github.com/briansmith/webpki/issues/114 Fixes #7888. Fixes #13749. Fixes #26835. Fixes #29291.
This commit is contained in:
parent
ab0f48f8e8
commit
bce7622cde
31 changed files with 575 additions and 4399 deletions
199
Cargo.lock
generated
199
Cargo.lock
generated
|
@ -226,11 +226,11 @@ dependencies = [
|
||||||
"futures-io",
|
"futures-io",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"log",
|
"log",
|
||||||
"openssl",
|
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-openssl",
|
"tokio-rustls",
|
||||||
"tungstenite",
|
"tungstenite",
|
||||||
|
"webpki-roots",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1639,7 +1639,7 @@ dependencies = [
|
||||||
"futures-sink",
|
"futures-sink",
|
||||||
"nanorand",
|
"nanorand",
|
||||||
"pin-project",
|
"pin-project",
|
||||||
"spin",
|
"spin 0.9.8",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2715,21 +2715,19 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper-openssl"
|
name = "hyper-rustls"
|
||||||
version = "0.9.2"
|
version = "0.24.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d6ee5d7a8f718585d1c3c61dfde28ef5b0bb14734b4db13f5ada856cdc6c612b"
|
checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"futures-util",
|
||||||
"http",
|
"http",
|
||||||
"hyper",
|
"hyper",
|
||||||
"linked_hash_set",
|
"log",
|
||||||
"once_cell",
|
"rustls",
|
||||||
"openssl",
|
|
||||||
"openssl-sys",
|
|
||||||
"parking_lot 0.12.0",
|
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-openssl",
|
"tokio-rustls",
|
||||||
"tower-layer",
|
"webpki-roots",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3342,21 +3340,6 @@ dependencies = [
|
||||||
"vcpkg",
|
"vcpkg",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "linked-hash-map"
|
|
||||||
version = "0.5.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "linked_hash_set"
|
|
||||||
version = "0.1.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "47186c6da4d81ca383c7c47c1bfc80f4b95f4720514d860a5407aaf4233f9588"
|
|
||||||
dependencies = [
|
|
||||||
"linked-hash-map",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linux-raw-sys"
|
name = "linux-raw-sys"
|
||||||
version = "0.3.8"
|
version = "0.3.8"
|
||||||
|
@ -3849,7 +3832,7 @@ dependencies = [
|
||||||
"headers",
|
"headers",
|
||||||
"http",
|
"http",
|
||||||
"hyper",
|
"hyper",
|
||||||
"hyper-openssl",
|
"hyper-rustls",
|
||||||
"hyper_serde",
|
"hyper_serde",
|
||||||
"immeta",
|
"immeta",
|
||||||
"ipc-channel",
|
"ipc-channel",
|
||||||
|
@ -3862,12 +3845,12 @@ dependencies = [
|
||||||
"mime_guess",
|
"mime_guess",
|
||||||
"msg",
|
"msg",
|
||||||
"net_traits",
|
"net_traits",
|
||||||
"openssl",
|
|
||||||
"openssl-sys",
|
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"pixels",
|
"pixels",
|
||||||
"profile_traits",
|
"profile_traits",
|
||||||
"rayon",
|
"rayon",
|
||||||
|
"rustls",
|
||||||
|
"rustls-pemfile",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"servo_allocator",
|
"servo_allocator",
|
||||||
|
@ -3878,12 +3861,13 @@ dependencies = [
|
||||||
"std_test_override",
|
"std_test_override",
|
||||||
"time 0.1.45",
|
"time 0.1.45",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-openssl",
|
"tokio-rustls",
|
||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
"tokio-test",
|
"tokio-test",
|
||||||
"tungstenite",
|
"tungstenite",
|
||||||
"url",
|
"url",
|
||||||
"uuid 1.3.4",
|
"uuid 1.3.4",
|
||||||
|
"webpki-roots",
|
||||||
"webrender_api",
|
"webrender_api",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -3920,6 +3904,7 @@ dependencies = [
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"pixels",
|
"pixels",
|
||||||
|
"rustls",
|
||||||
"serde",
|
"serde",
|
||||||
"servo_arc",
|
"servo_arc",
|
||||||
"servo_rand",
|
"servo_rand",
|
||||||
|
@ -4202,44 +4187,6 @@ version = "0.2.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
|
checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "openssl"
|
|
||||||
version = "0.10.50"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7e30d8bc91859781f0a943411186324d580f2bbeb71b452fe91ae344806af3f1"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags 1.3.2",
|
|
||||||
"cfg-if 1.0.0",
|
|
||||||
"foreign-types",
|
|
||||||
"libc",
|
|
||||||
"once_cell",
|
|
||||||
"openssl-macros",
|
|
||||||
"openssl-sys",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "openssl-macros"
|
|
||||||
version = "0.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "openssl-sys"
|
|
||||||
version = "0.9.85"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0d3d193fb1488ad46ffe3aaabc912cc931d02ee8518fe2959aea8ef52718b0c0"
|
|
||||||
dependencies = [
|
|
||||||
"cc",
|
|
||||||
"libc",
|
|
||||||
"pkg-config",
|
|
||||||
"vcpkg",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "orbclient"
|
name = "orbclient"
|
||||||
version = "0.3.42"
|
version = "0.3.42"
|
||||||
|
@ -4881,6 +4828,21 @@ version = "0.6.28"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
|
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ring"
|
||||||
|
version = "0.16.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
"once_cell",
|
||||||
|
"spin 0.5.2",
|
||||||
|
"untrusted",
|
||||||
|
"web-sys",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rle-decode-fast"
|
name = "rle-decode-fast"
|
||||||
version = "1.0.3"
|
version = "1.0.3"
|
||||||
|
@ -4945,14 +4907,46 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls-pemfile"
|
name = "rustls"
|
||||||
version = "1.0.2"
|
version = "0.21.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b"
|
checksum = "1d1feddffcfcc0b33f5c6ce9a29e341e4cd59c3f78e7ee45f4a40c038b1d6cbb"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"ring",
|
||||||
|
"rustls-webpki 0.101.2",
|
||||||
|
"sct",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustls-pemfile"
|
||||||
|
version = "1.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.21.2",
|
"base64 0.21.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustls-webpki"
|
||||||
|
version = "0.100.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d6207cd5ed3d8dca7816f8f3725513a34609c0c765bf652b8c3cb4cfd87db46b"
|
||||||
|
dependencies = [
|
||||||
|
"ring",
|
||||||
|
"untrusted",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustls-webpki"
|
||||||
|
version = "0.101.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "513722fd73ad80a71f72b61009ea1b584bcfa1483ca93949c8f290298837fa59"
|
||||||
|
dependencies = [
|
||||||
|
"ring",
|
||||||
|
"untrusted",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustversion"
|
name = "rustversion"
|
||||||
version = "1.0.14"
|
version = "1.0.14"
|
||||||
|
@ -5180,6 +5174,16 @@ dependencies = [
|
||||||
"webxr-api",
|
"webxr-api",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sct"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
|
||||||
|
dependencies = [
|
||||||
|
"ring",
|
||||||
|
"untrusted",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sctk-adwaita"
|
name = "sctk-adwaita"
|
||||||
version = "0.5.3"
|
version = "0.5.3"
|
||||||
|
@ -5821,6 +5825,12 @@ version = "0.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b72d540d5c565dbe1f891d7e21ceb21d2649508306782f1066989fccb0b363d3"
|
checksum = "b72d540d5c565dbe1f891d7e21ceb21d2649508306782f1066989fccb0b363d3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spin"
|
||||||
|
version = "0.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spin"
|
name = "spin"
|
||||||
version = "0.9.8"
|
version = "0.9.8"
|
||||||
|
@ -6355,14 +6365,12 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-openssl"
|
name = "tokio-rustls"
|
||||||
version = "0.6.3"
|
version = "0.24.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c08f9ffb7809f1b20c1b398d92acf4cc719874b3b2b2d9ea2f09b4a80350878a"
|
checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-util",
|
"rustls",
|
||||||
"openssl",
|
|
||||||
"openssl-sys",
|
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -6413,12 +6421,6 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tower-layer"
|
|
||||||
version = "0.3.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "343bc9466d3fe6b0f960ef45960509f84480bf4fd96f92901afe7ff3df9d3a62"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tower-service"
|
name = "tower-service"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
|
@ -6486,10 +6488,12 @@ dependencies = [
|
||||||
"httparse",
|
"httparse",
|
||||||
"log",
|
"log",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
|
"rustls",
|
||||||
"sha1",
|
"sha1",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"url",
|
"url",
|
||||||
"utf-8",
|
"utf-8",
|
||||||
|
"webpki",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -6589,6 +6593,12 @@ version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "untrusted"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unwind-sys"
|
name = "unwind-sys"
|
||||||
version = "0.1.3"
|
version = "0.1.3"
|
||||||
|
@ -6957,6 +6967,25 @@ dependencies = [
|
||||||
"wgpu-types",
|
"wgpu-types",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "webpki"
|
||||||
|
version = "0.22.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd"
|
||||||
|
dependencies = [
|
||||||
|
"ring",
|
||||||
|
"untrusted",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "webpki-roots"
|
||||||
|
version = "0.23.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b03058f88386e5ff5310d9111d53f48b17d732b401aeb83a8d5190f2ac459338"
|
||||||
|
dependencies = [
|
||||||
|
"rustls-webpki 0.100.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webrender"
|
name = "webrender"
|
||||||
version = "0.61.0"
|
version = "0.61.0"
|
||||||
|
|
|
@ -12,6 +12,7 @@ exclude = [".cargo"]
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
accountable-refcell = "0.2.0"
|
accountable-refcell = "0.2.0"
|
||||||
app_units = "0.7"
|
app_units = "0.7"
|
||||||
|
async-tungstenite = { version = "0.22", features = ["tokio-rustls-webpki-roots"] }
|
||||||
atomic_refcell = "0.1.6"
|
atomic_refcell = "0.1.6"
|
||||||
arrayvec = "0.7"
|
arrayvec = "0.7"
|
||||||
backtrace = "0.3"
|
backtrace = "0.3"
|
||||||
|
@ -35,6 +36,7 @@ headers = "0.3"
|
||||||
html5ever = "0.26"
|
html5ever = "0.26"
|
||||||
http = "0.2"
|
http = "0.2"
|
||||||
hyper = "0.14"
|
hyper = "0.14"
|
||||||
|
hyper-rustls = { version = "0.24", default-features = false, features = ["webpki-tokio", "http1", "http2", "tls12", "logging", "acceptor"] }
|
||||||
hyper_serde = "0.13"
|
hyper_serde = "0.13"
|
||||||
image = "0.24"
|
image = "0.24"
|
||||||
indexmap = { version = "1.0.2", features = ["std"] }
|
indexmap = { version = "1.0.2", features = ["std"] }
|
||||||
|
@ -57,6 +59,8 @@ quote = "1"
|
||||||
rand = "0.7"
|
rand = "0.7"
|
||||||
rayon = "1"
|
rayon = "1"
|
||||||
regex = "1.1"
|
regex = "1.1"
|
||||||
|
rustls = { version = "0.21.5", features = ["dangerous_configuration"] }
|
||||||
|
rustls-pemfile = "1.0.3"
|
||||||
serde = "1.0.60"
|
serde = "1.0.60"
|
||||||
serde_bytes = "0.11"
|
serde_bytes = "0.11"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
@ -73,11 +77,15 @@ surfman-chains-api = "0.2"
|
||||||
thin-slice = "0.1.0"
|
thin-slice = "0.1.0"
|
||||||
time = "0.1.41"
|
time = "0.1.41"
|
||||||
tokio = "1"
|
tokio = "1"
|
||||||
|
tokio-rustls = "0.24"
|
||||||
|
tungstenite = "0.19"
|
||||||
unicode-bidi = "0.3.4"
|
unicode-bidi = "0.3.4"
|
||||||
unicode-script = "0.5"
|
unicode-script = "0.5"
|
||||||
url = "2.0"
|
url = "2.0"
|
||||||
uuid = { version = "1.3.4", features = ["v4"] }
|
uuid = { version = "1.3.4", features = ["v4"] }
|
||||||
webdriver = "0.48.0"
|
webdriver = "0.48.0"
|
||||||
|
webpki-roots = "0.23"
|
||||||
|
webpki = "0.22"
|
||||||
webrender = { git = "https://github.com/servo/webrender", features = ["capture"] }
|
webrender = { git = "https://github.com/servo/webrender", features = ["capture"] }
|
||||||
webrender_api = { git = "https://github.com/servo/webrender" }
|
webrender_api = { git = "https://github.com/servo/webrender" }
|
||||||
winapi = "0.3"
|
winapi = "0.3"
|
||||||
|
|
|
@ -113,9 +113,14 @@ pub struct Opts {
|
||||||
/// Print the version and exit.
|
/// Print the version and exit.
|
||||||
pub is_printing_version: bool,
|
pub is_printing_version: bool,
|
||||||
|
|
||||||
/// Path to SSL certificates.
|
/// Path to PEM encoded SSL CA certificate store.
|
||||||
pub certificate_path: Option<String>,
|
pub certificate_path: Option<String>,
|
||||||
|
|
||||||
|
/// Whether or not to completely ignore SSL certificate validation errors.
|
||||||
|
/// TODO: We should see if we can eliminate the need for this by fixing
|
||||||
|
/// https://github.com/servo/servo/issues/30080.
|
||||||
|
pub ignore_certificate_errors: bool,
|
||||||
|
|
||||||
/// Unminify Javascript.
|
/// Unminify Javascript.
|
||||||
pub unminify_js: bool,
|
pub unminify_js: bool,
|
||||||
|
|
||||||
|
@ -408,6 +413,7 @@ pub fn default_opts() -> Opts {
|
||||||
is_printing_version: false,
|
is_printing_version: false,
|
||||||
shaders_dir: None,
|
shaders_dir: None,
|
||||||
certificate_path: None,
|
certificate_path: None,
|
||||||
|
ignore_certificate_errors: false,
|
||||||
unminify_js: false,
|
unminify_js: false,
|
||||||
local_script_source: None,
|
local_script_source: None,
|
||||||
print_pwm: false,
|
print_pwm: false,
|
||||||
|
@ -524,6 +530,11 @@ pub fn from_cmdline_args(mut opts: Options, args: &[String]) -> ArgumentParsingR
|
||||||
"Path to find SSL certificates",
|
"Path to find SSL certificates",
|
||||||
"/home/servo/resources/certs",
|
"/home/servo/resources/certs",
|
||||||
);
|
);
|
||||||
|
opts.optflag(
|
||||||
|
"",
|
||||||
|
"ignore-certificate-errors",
|
||||||
|
"Whether or not to completely ignore certificate errors",
|
||||||
|
);
|
||||||
opts.optopt(
|
opts.optopt(
|
||||||
"",
|
"",
|
||||||
"content-process",
|
"content-process",
|
||||||
|
@ -767,6 +778,7 @@ pub fn from_cmdline_args(mut opts: Options, args: &[String]) -> ArgumentParsingR
|
||||||
is_printing_version,
|
is_printing_version,
|
||||||
shaders_dir: opt_match.opt_str("shaders").map(Into::into),
|
shaders_dir: opt_match.opt_str("shaders").map(Into::into),
|
||||||
certificate_path: opt_match.opt_str("certificate-path"),
|
certificate_path: opt_match.opt_str("certificate-path"),
|
||||||
|
ignore_certificate_errors: opt_match.opt_present("ignore-certificate-errors"),
|
||||||
unminify_js: opt_match.opt_present("unminify-js"),
|
unminify_js: opt_match.opt_present("unminify-js"),
|
||||||
local_script_source: opt_match.opt_str("local-script-source"),
|
local_script_source: opt_match.opt_str("local-script-source"),
|
||||||
print_pwm: opt_match.opt_present("print-pwm"),
|
print_pwm: opt_match.opt_present("print-pwm"),
|
||||||
|
|
|
@ -6,7 +6,6 @@ license = "MPL-2.0"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
publish = false
|
publish = false
|
||||||
autotests = false # Inhibit lookup for tests/*.rs without [[test]] sections
|
autotests = false # Inhibit lookup for tests/*.rs without [[test]] sections
|
||||||
build = "build.rs"
|
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "net"
|
name = "net"
|
||||||
|
@ -16,7 +15,7 @@ doctest = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
async-recursion = "0.3.2"
|
async-recursion = "0.3.2"
|
||||||
async-tungstenite = { version = "0.22", features = ["tokio-openssl"] }
|
async-tungstenite = { workspace = true }
|
||||||
base64 = { workspace = true }
|
base64 = { workspace = true }
|
||||||
brotli = "3"
|
brotli = "3"
|
||||||
bytes = "1"
|
bytes = "1"
|
||||||
|
@ -33,7 +32,7 @@ generic-array = "0.14"
|
||||||
headers = { workspace = true }
|
headers = { workspace = true }
|
||||||
http = { workspace = true }
|
http = { workspace = true }
|
||||||
hyper = { workspace = true, features = ["client", "http1", "http2", "tcp", "stream"] }
|
hyper = { workspace = true, features = ["client", "http1", "http2", "tcp", "stream"] }
|
||||||
hyper-openssl = "0.9.1"
|
hyper-rustls = { workspace = true }
|
||||||
hyper_serde = { workspace = true }
|
hyper_serde = { workspace = true }
|
||||||
immeta = "0.4"
|
immeta = "0.4"
|
||||||
ipc-channel = { workspace = true }
|
ipc-channel = { workspace = true }
|
||||||
|
@ -46,12 +45,12 @@ mime = { workspace = true }
|
||||||
mime_guess = { workspace = true }
|
mime_guess = { workspace = true }
|
||||||
msg = { path = "../msg" }
|
msg = { path = "../msg" }
|
||||||
net_traits = { path = "../net_traits" }
|
net_traits = { path = "../net_traits" }
|
||||||
openssl = "0.10"
|
|
||||||
openssl-sys = "0.9"
|
|
||||||
percent-encoding = { workspace = true }
|
percent-encoding = { workspace = true }
|
||||||
pixels = { path = "../pixels" }
|
pixels = { path = "../pixels" }
|
||||||
profile_traits = { path = "../profile_traits" }
|
profile_traits = { path = "../profile_traits" }
|
||||||
rayon = { workspace = true }
|
rayon = { workspace = true }
|
||||||
|
rustls = { workspace = true }
|
||||||
|
rustls-pemfile = { workspace = true }
|
||||||
serde = { workspace = true }
|
serde = { workspace = true }
|
||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
servo_allocator = { path = "../allocator" }
|
servo_allocator = { path = "../allocator" }
|
||||||
|
@ -61,16 +60,17 @@ servo_url = { path = "../url" }
|
||||||
sha2 = "0.10"
|
sha2 = "0.10"
|
||||||
time = { workspace = true }
|
time = { workspace = true }
|
||||||
tokio = { workspace = true, features = ["sync", "macros", "rt-multi-thread"] }
|
tokio = { workspace = true, features = ["sync", "macros", "rt-multi-thread"] }
|
||||||
|
tokio-rustls = { workspace = true }
|
||||||
tokio-stream = "0.1"
|
tokio-stream = "0.1"
|
||||||
tungstenite = "0.19"
|
tungstenite = { workspace = true }
|
||||||
url = { workspace = true }
|
url = { workspace = true }
|
||||||
uuid = { workspace = true }
|
uuid = { workspace = true }
|
||||||
webrender_api = { workspace = true }
|
webrender_api = { workspace = true }
|
||||||
|
webpki-roots = { workspace = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
futures = {version = "0.3", features = ["compat"]}
|
futures = {version = "0.3", features = ["compat"]}
|
||||||
std_test_override = { path = "../std_test_override" }
|
std_test_override = { path = "../std_test_override" }
|
||||||
tokio-openssl = "0.6"
|
|
||||||
tokio-test = "0.4"
|
tokio-test = "0.4"
|
||||||
tokio-stream = { version = "0.1", features = ["net"] }
|
tokio-stream = { version = "0.1", features = ["net"] }
|
||||||
hyper = { workspace = true, features = ["full"] }
|
hyper = { workspace = true, features = ["full"] }
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let version =
|
|
||||||
std::env::var("DEP_OPENSSL_VERSION_NUMBER").expect("missing DEP_OPENSSL_VERSION_NUMBER");
|
|
||||||
let actual = u64::from_str_radix(&version, 16).unwrap();
|
|
||||||
let minimum = 0x10101000;
|
|
||||||
if actual < minimum {
|
|
||||||
panic!(
|
|
||||||
"Your OpenSSL version is older than 1.1.1 ({:x}), you have: {:x}",
|
|
||||||
minimum, actual
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -9,80 +9,30 @@ use http::uri::{Authority, Uri as Destination};
|
||||||
use hyper::client::HttpConnector as HyperHttpConnector;
|
use hyper::client::HttpConnector as HyperHttpConnector;
|
||||||
use hyper::rt::Executor;
|
use hyper::rt::Executor;
|
||||||
use hyper::{service::Service, Body, Client};
|
use hyper::{service::Service, Body, Client};
|
||||||
use hyper_openssl::HttpsConnector;
|
use hyper_rustls::HttpsConnector as HyperRustlsHttpsConnector;
|
||||||
use openssl::ex_data::Index;
|
use rustls::client::WebPkiVerifier;
|
||||||
use openssl::ssl::{
|
use rustls::{Certificate, ClientConfig, OwnedTrustAnchor, RootCertStore, ServerName};
|
||||||
Ssl, SslConnector, SslConnectorBuilder, SslContext, SslMethod, SslOptions, SslVerifyMode,
|
use std::collections::hash_map::HashMap;
|
||||||
};
|
use std::convert::TryFrom;
|
||||||
use openssl::x509::{self, X509StoreContext};
|
|
||||||
use std::collections::hash_map::{Entry, HashMap};
|
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
pub const BUF_SIZE: usize = 32768;
|
pub const BUF_SIZE: usize = 32768;
|
||||||
pub const ALPN_H2_H1: &'static [u8] = b"\x02h2\x08http/1.1";
|
|
||||||
pub const ALPN_H1: &'static [u8] = b"\x08http/1.1";
|
|
||||||
|
|
||||||
// See https://wiki.mozilla.org/Security/Server_Side_TLS for orientation.
|
|
||||||
const TLS1_2_CIPHERSUITES: &'static str = concat!(
|
|
||||||
"ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:",
|
|
||||||
"ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:",
|
|
||||||
"ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:",
|
|
||||||
"ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA@SECLEVEL=2"
|
|
||||||
);
|
|
||||||
const SIGNATURE_ALGORITHMS: &'static str = concat!(
|
|
||||||
"ed448:ed25519:",
|
|
||||||
"ECDSA+SHA384:ECDSA+SHA256:",
|
|
||||||
"RSA-PSS+SHA512:RSA-PSS+SHA384:RSA-PSS+SHA256:",
|
|
||||||
"RSA+SHA512:RSA+SHA384:RSA+SHA256"
|
|
||||||
);
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ConnectionCerts {
|
pub struct ServoHttpConnector {
|
||||||
certs: Arc<Mutex<HashMap<String, (Vec<u8>, u32)>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ConnectionCerts {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
certs: Arc::new(Mutex::new(HashMap::new())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn store(&self, host: String, cert_bytes: Vec<u8>) {
|
|
||||||
let mut certs = self.certs.lock().unwrap();
|
|
||||||
let entry = certs.entry(host).or_insert((cert_bytes, 0));
|
|
||||||
entry.1 += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn remove(&self, host: String) -> Option<Vec<u8>> {
|
|
||||||
match self.certs.lock().unwrap().entry(host) {
|
|
||||||
Entry::Vacant(_) => return None,
|
|
||||||
Entry::Occupied(mut e) => {
|
|
||||||
e.get_mut().1 -= 1;
|
|
||||||
if e.get().1 == 0 {
|
|
||||||
return Some((e.remove_entry().1).0);
|
|
||||||
}
|
|
||||||
Some(e.get().0.clone())
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct HttpConnector {
|
|
||||||
inner: HyperHttpConnector,
|
inner: HyperHttpConnector,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HttpConnector {
|
impl ServoHttpConnector {
|
||||||
fn new() -> HttpConnector {
|
fn new() -> ServoHttpConnector {
|
||||||
let mut inner = HyperHttpConnector::new();
|
let mut inner = HyperHttpConnector::new();
|
||||||
inner.enforce_http(false);
|
inner.enforce_http(false);
|
||||||
inner.set_happy_eyeballs_timeout(None);
|
inner.set_happy_eyeballs_timeout(None);
|
||||||
HttpConnector { inner }
|
ServoHttpConnector { inner }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Service<Destination> for HttpConnector {
|
impl Service<Destination> for ServoHttpConnector {
|
||||||
type Response = <HyperHttpConnector as Service<Destination>>::Response;
|
type Response = <HyperHttpConnector as Service<Destination>>::Response;
|
||||||
type Error = <HyperHttpConnector as Service<Destination>>::Error;
|
type Error = <HyperHttpConnector as Service<Destination>>::Error;
|
||||||
type Future = <HyperHttpConnector as Service<Destination>>::Future;
|
type Future = <HyperHttpConnector as Service<Destination>>::Future;
|
||||||
|
@ -118,119 +68,85 @@ impl Service<Destination> for HttpConnector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Connector = HttpsConnector<HttpConnector>;
|
pub type Connector = HyperRustlsHttpsConnector<ServoHttpConnector>;
|
||||||
pub type TlsConfig = SslConnectorBuilder;
|
pub type TlsConfig = ClientConfig;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct ExtraCerts(Arc<Mutex<Vec<Vec<u8>>>>);
|
struct CertificateErrorOverrideManagerInternal {
|
||||||
|
/// A mapping of certificates and their hosts, which have seen certificate errors.
|
||||||
|
/// This is used to later create an override in this [CertificateErrorOverrideManager].
|
||||||
|
certificates_failing_to_verify: HashMap<ServerName, Certificate>,
|
||||||
|
/// A list of certificates that should be accepted despite encountering verification
|
||||||
|
/// errors.
|
||||||
|
overrides: Vec<Certificate>,
|
||||||
|
}
|
||||||
|
|
||||||
impl ExtraCerts {
|
/// This data structure is used to track certificate verification errors and overrides.
|
||||||
|
/// It tracks:
|
||||||
|
/// - A list of [Certificate]s with verification errors mapped by their [ServerName]
|
||||||
|
/// - A list of [Certificate]s for which to ignore verification errors.
|
||||||
|
#[derive(Clone, Debug, Default)]
|
||||||
|
pub struct CertificateErrorOverrideManager(Arc<Mutex<CertificateErrorOverrideManagerInternal>>);
|
||||||
|
|
||||||
|
impl CertificateErrorOverrideManager {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self(Arc::new(Mutex::new(vec![])))
|
Self(Default::default())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add(&self, bytes: Vec<u8>) {
|
/// Add a certificate to this manager's list of certificates for which to ignore
|
||||||
self.0.lock().unwrap().push(bytes);
|
/// validation errors.
|
||||||
|
pub fn add_override(&self, certificate: &Certificate) {
|
||||||
|
self.0.lock().unwrap().overrides.push(certificate.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Given the a string representation of a sever host name, remove information about
|
||||||
|
/// a [Certificate] with verification errors. If a certificate with
|
||||||
|
/// verification errors was found, return it, otherwise None.
|
||||||
|
pub(crate) fn remove_certificate_failing_verification(
|
||||||
|
&self,
|
||||||
|
host: &str,
|
||||||
|
) -> Option<Certificate> {
|
||||||
|
let server_name = match ServerName::try_from(host) {
|
||||||
|
Ok(name) => name,
|
||||||
|
Err(error) => {
|
||||||
|
warn!("Could not convert host string into RustTLS ServerName: {error:?}");
|
||||||
|
return None;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
self.0
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.certificates_failing_to_verify
|
||||||
|
.remove(&server_name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Host(String);
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum CACertificates {
|
||||||
lazy_static! {
|
Default,
|
||||||
static ref EXTRA_INDEX: Index<SslContext, ExtraCerts> = SslContext::new_ex_index().unwrap();
|
Override(RootCertStore),
|
||||||
static ref CONNECTION_INDEX: Index<SslContext, ConnectionCerts> =
|
|
||||||
SslContext::new_ex_index().unwrap();
|
|
||||||
static ref HOST_INDEX: Index<Ssl, Host> = Ssl::new_ex_index().unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a [TlsConfig] to use for managing a HTTP connection. This currently creates
|
||||||
|
/// a rustls [ClientConfig].
|
||||||
|
///
|
||||||
|
/// FIXME: The `ignore_certificate_errors` argument ignores all certificate errors. This
|
||||||
|
/// is used when running the WPT tests, because rustls currently rejects the WPT certificiate.
|
||||||
|
/// See https://github.com/servo/servo/issues/30080
|
||||||
pub fn create_tls_config(
|
pub fn create_tls_config(
|
||||||
certs: &str,
|
ca_certificates: CACertificates,
|
||||||
alpn: &[u8],
|
ignore_certificate_errors: bool,
|
||||||
extra_certs: ExtraCerts,
|
override_manager: CertificateErrorOverrideManager,
|
||||||
connection_certs: ConnectionCerts,
|
|
||||||
) -> TlsConfig {
|
) -> TlsConfig {
|
||||||
// certs include multiple certificates. We could add all of them at once,
|
let verifier = CertificateVerificationOverrideVerifier::new(
|
||||||
// but if any of them were already added, openssl would fail to insert all
|
ca_certificates,
|
||||||
// of them.
|
ignore_certificate_errors,
|
||||||
let mut certs = certs;
|
override_manager,
|
||||||
let mut cfg = SslConnector::builder(SslMethod::tls()).unwrap();
|
|
||||||
loop {
|
|
||||||
let token = "-----END CERTIFICATE-----";
|
|
||||||
if let Some(index) = certs.find(token) {
|
|
||||||
let (cert, rest) = certs.split_at(index + token.len());
|
|
||||||
certs = rest;
|
|
||||||
let cert = x509::X509::from_pem(cert.as_bytes()).unwrap();
|
|
||||||
cfg.cert_store_mut()
|
|
||||||
.add_cert(cert)
|
|
||||||
.or_else(|e| {
|
|
||||||
let v: Option<Option<&str>> = e.errors().iter().nth(0).map(|e| e.reason());
|
|
||||||
if v == Some(Some("cert already in hash table")) {
|
|
||||||
warn!("Cert already in hash table. Ignoring.");
|
|
||||||
// Ignore error X509_R_CERT_ALREADY_IN_HASH_TABLE which means the
|
|
||||||
// certificate is already in the store.
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(e)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.expect("could not set CA file");
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cfg.set_alpn_protos(alpn)
|
|
||||||
.expect("could not set alpn protocols");
|
|
||||||
cfg.set_cipher_list(TLS1_2_CIPHERSUITES)
|
|
||||||
.expect("could not set TLS 1.2 ciphersuites");
|
|
||||||
cfg.set_sigalgs_list(SIGNATURE_ALGORITHMS)
|
|
||||||
.expect("could not set signature algorithms");
|
|
||||||
cfg.set_options(
|
|
||||||
SslOptions::NO_SSLV2 |
|
|
||||||
SslOptions::NO_SSLV3 |
|
|
||||||
SslOptions::NO_TLSV1 |
|
|
||||||
SslOptions::NO_TLSV1_1 |
|
|
||||||
SslOptions::NO_COMPRESSION,
|
|
||||||
);
|
);
|
||||||
|
rustls::ClientConfig::builder()
|
||||||
cfg.set_ex_data(*EXTRA_INDEX, extra_certs);
|
.with_safe_defaults()
|
||||||
cfg.set_ex_data(*CONNECTION_INDEX, connection_certs);
|
.with_custom_certificate_verifier(Arc::new(verifier))
|
||||||
cfg.set_verify_callback(SslVerifyMode::PEER, |verified, x509_store_context| {
|
.with_no_client_auth()
|
||||||
if verified {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
let ssl_idx = X509StoreContext::ssl_idx().unwrap();
|
|
||||||
let ssl = x509_store_context.ex_data(ssl_idx).unwrap();
|
|
||||||
|
|
||||||
// Obtain the cert bytes for this connection.
|
|
||||||
let cert = match x509_store_context.current_cert() {
|
|
||||||
Some(cert) => cert,
|
|
||||||
None => return false,
|
|
||||||
};
|
|
||||||
let pem = match cert.to_pem() {
|
|
||||||
Ok(pem) => pem,
|
|
||||||
Err(_) => return false,
|
|
||||||
};
|
|
||||||
|
|
||||||
let ssl_context = ssl.ssl_context();
|
|
||||||
|
|
||||||
// Ensure there's an entry stored in the set of known connection certs for this connection.
|
|
||||||
if let Some(host) = ssl.ex_data(*HOST_INDEX) {
|
|
||||||
let connection_certs = ssl_context.ex_data(*CONNECTION_INDEX).unwrap();
|
|
||||||
connection_certs.store((*host).0.clone(), pem.clone());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fall back to the dynamic set of allowed certs.
|
|
||||||
let extra_certs = ssl_context.ex_data(*EXTRA_INDEX).unwrap();
|
|
||||||
for cert in &*extra_certs.0.lock().unwrap() {
|
|
||||||
if pem == *cert {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
false
|
|
||||||
});
|
|
||||||
|
|
||||||
cfg
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TokioExecutor {}
|
struct TokioExecutor {}
|
||||||
|
@ -244,14 +160,95 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_http_client(tls_config: TlsConfig) -> Client<Connector, Body> {
|
struct CertificateVerificationOverrideVerifier {
|
||||||
let mut connector = HttpsConnector::with_connector(HttpConnector::new(), tls_config).unwrap();
|
webpki_verifier: WebPkiVerifier,
|
||||||
connector.set_callback(|configuration, destination| {
|
ignore_certificate_errors: bool,
|
||||||
if let Some(host) = destination.host() {
|
override_manager: CertificateErrorOverrideManager,
|
||||||
configuration.set_ex_data(*HOST_INDEX, Host(host.to_owned()));
|
}
|
||||||
|
|
||||||
|
impl CertificateVerificationOverrideVerifier {
|
||||||
|
fn new(
|
||||||
|
ca_certficates: CACertificates,
|
||||||
|
ignore_certificate_errors: bool,
|
||||||
|
override_manager: CertificateErrorOverrideManager,
|
||||||
|
) -> Self {
|
||||||
|
let root_cert_store = match ca_certficates {
|
||||||
|
CACertificates::Default => {
|
||||||
|
let mut root_cert_store = rustls::RootCertStore::empty();
|
||||||
|
root_cert_store.add_trust_anchors(webpki_roots::TLS_SERVER_ROOTS.0.iter().map(
|
||||||
|
|trust_anchor| {
|
||||||
|
OwnedTrustAnchor::from_subject_spki_name_constraints(
|
||||||
|
trust_anchor.subject,
|
||||||
|
trust_anchor.spki,
|
||||||
|
trust_anchor.name_constraints,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
));
|
||||||
|
root_cert_store
|
||||||
|
},
|
||||||
|
CACertificates::Override(root_cert_store) => root_cert_store,
|
||||||
|
};
|
||||||
|
|
||||||
|
Self {
|
||||||
|
// See https://github.com/rustls/rustls/blame/v/0.21.6/rustls/src/client/builder.rs#L141
|
||||||
|
// This is the default verifier for Rustls that we are wrapping.
|
||||||
|
webpki_verifier: WebPkiVerifier::new(root_cert_store, None),
|
||||||
|
ignore_certificate_errors,
|
||||||
|
override_manager,
|
||||||
}
|
}
|
||||||
Ok(())
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
impl rustls::client::ServerCertVerifier for CertificateVerificationOverrideVerifier {
|
||||||
|
fn verify_server_cert(
|
||||||
|
&self,
|
||||||
|
end_entity: &Certificate,
|
||||||
|
intermediates: &[Certificate],
|
||||||
|
server_name: &ServerName,
|
||||||
|
scts: &mut dyn Iterator<Item = &[u8]>,
|
||||||
|
ocsp_response: &[u8],
|
||||||
|
now: std::time::SystemTime,
|
||||||
|
) -> Result<rustls::client::ServerCertVerified, rustls::Error> {
|
||||||
|
let error = match self.webpki_verifier.verify_server_cert(
|
||||||
|
end_entity,
|
||||||
|
intermediates,
|
||||||
|
server_name,
|
||||||
|
scts,
|
||||||
|
ocsp_response,
|
||||||
|
now,
|
||||||
|
) {
|
||||||
|
Ok(result) => return Ok(result),
|
||||||
|
Err(error) => error,
|
||||||
|
};
|
||||||
|
|
||||||
|
if self.ignore_certificate_errors {
|
||||||
|
warn!("Ignoring certficate error: {error:?}");
|
||||||
|
return Ok(rustls::client::ServerCertVerified::assertion());
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there's an override for this certificate, just accept it.
|
||||||
|
for cert_with_exception in &*self.override_manager.0.lock().unwrap().overrides {
|
||||||
|
if *end_entity == *cert_with_exception {
|
||||||
|
return Ok(rustls::client::ServerCertVerified::assertion());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.override_manager
|
||||||
|
.0
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.certificates_failing_to_verify
|
||||||
|
.insert(server_name.clone(), end_entity.clone());
|
||||||
|
Err(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_http_client(tls_config: TlsConfig) -> Client<Connector, Body> {
|
||||||
|
let connector = hyper_rustls::HttpsConnectorBuilder::new()
|
||||||
|
.with_tls_config(tls_config)
|
||||||
|
.https_or_http()
|
||||||
|
.enable_http1()
|
||||||
|
.enable_http2()
|
||||||
|
.wrap_connector(ServoHttpConnector::new());
|
||||||
|
|
||||||
Client::builder()
|
Client::builder()
|
||||||
.http1_title_case_headers(true)
|
.http1_title_case_headers(true)
|
||||||
|
|
|
@ -9,7 +9,7 @@ use crate::filemanager_thread::{FileManager, FILE_CHUNK_SIZE};
|
||||||
use crate::http_loader::{determine_requests_referrer, http_fetch, HttpState};
|
use crate::http_loader::{determine_requests_referrer, http_fetch, HttpState};
|
||||||
use crate::http_loader::{set_default_accept, set_default_accept_language};
|
use crate::http_loader::{set_default_accept, set_default_accept_language};
|
||||||
use crate::subresource_integrity::is_response_integrity_valid;
|
use crate::subresource_integrity::is_response_integrity_valid;
|
||||||
use base64::Engine;
|
use base64::{engine::general_purpose, Engine as _};
|
||||||
use content_security_policy as csp;
|
use content_security_policy as csp;
|
||||||
use crossbeam_channel::Sender;
|
use crossbeam_channel::Sender;
|
||||||
use devtools_traits::DevtoolsControlMsg;
|
use devtools_traits::DevtoolsControlMsg;
|
||||||
|
@ -31,11 +31,12 @@ use net_traits::request::{
|
||||||
use net_traits::response::{Response, ResponseBody, ResponseType};
|
use net_traits::response::{Response, ResponseBody, ResponseType};
|
||||||
use net_traits::{FetchTaskTarget, NetworkError, ReferrerPolicy, ResourceFetchTiming};
|
use net_traits::{FetchTaskTarget, NetworkError, ReferrerPolicy, ResourceFetchTiming};
|
||||||
use net_traits::{ResourceAttribute, ResourceTimeValue, ResourceTimingType};
|
use net_traits::{ResourceAttribute, ResourceTimeValue, ResourceTimingType};
|
||||||
|
use rustls::Certificate;
|
||||||
use servo_arc::Arc as ServoArc;
|
use servo_arc::Arc as ServoArc;
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{BufReader, Seek, SeekFrom};
|
use std::io::{self, BufReader, Seek, SeekFrom};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::Bound;
|
use std::ops::Bound;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
@ -627,6 +628,48 @@ fn create_blank_reply(url: ServoUrl, timing_type: ResourceTimingType) -> Respons
|
||||||
response
|
response
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Handle a request from the user interface to ignore validation errors for a certificate.
|
||||||
|
fn handle_allowcert_request(request: &mut Request, context: &FetchContext) -> io::Result<()> {
|
||||||
|
let error = |string| Err(io::Error::new(io::ErrorKind::Other, string));
|
||||||
|
|
||||||
|
let body = match request.body.as_mut() {
|
||||||
|
Some(body) => body,
|
||||||
|
None => return error("No body found"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let stream = body.take_stream();
|
||||||
|
let stream = stream.lock().unwrap();
|
||||||
|
let (body_chan, body_port) = ipc::channel().unwrap();
|
||||||
|
let _ = stream.send(BodyChunkRequest::Connect(body_chan));
|
||||||
|
let _ = stream.send(BodyChunkRequest::Chunk);
|
||||||
|
let body_bytes = match body_port.recv().ok() {
|
||||||
|
Some(BodyChunkResponse::Chunk(bytes)) => bytes,
|
||||||
|
_ => return error("Certificate not sent in a single chunk"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let split_idx = match body_bytes.iter().position(|b| *b == b'&') {
|
||||||
|
Some(split_idx) => split_idx,
|
||||||
|
None => return error("Could not find ampersand in data"),
|
||||||
|
};
|
||||||
|
let (secret, cert_base64) = body_bytes.split_at(split_idx);
|
||||||
|
|
||||||
|
let secret = str::from_utf8(secret).ok().and_then(|s| s.parse().ok());
|
||||||
|
if secret != Some(*net_traits::PRIVILEGED_SECRET) {
|
||||||
|
return error("Invalid secret sent. Ignoring request");
|
||||||
|
}
|
||||||
|
|
||||||
|
let cert_bytes = match general_purpose::STANDARD_NO_PAD.decode(&cert_base64[1..]) {
|
||||||
|
Ok(bytes) => bytes,
|
||||||
|
Err(_) => return error("Could not decode certificate base64"),
|
||||||
|
};
|
||||||
|
|
||||||
|
context
|
||||||
|
.state
|
||||||
|
.override_manager
|
||||||
|
.add_override(&Certificate(cert_bytes));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// [Scheme fetch](https://fetch.spec.whatwg.org#scheme-fetch)
|
/// [Scheme fetch](https://fetch.spec.whatwg.org#scheme-fetch)
|
||||||
async fn scheme_fetch(
|
async fn scheme_fetch(
|
||||||
request: &mut Request,
|
request: &mut Request,
|
||||||
|
@ -641,32 +684,9 @@ async fn scheme_fetch(
|
||||||
"about" if url.path() == "blank" => create_blank_reply(url, request.timing_type()),
|
"about" if url.path() == "blank" => create_blank_reply(url, request.timing_type()),
|
||||||
|
|
||||||
"chrome" if url.path() == "allowcert" => {
|
"chrome" if url.path() == "allowcert" => {
|
||||||
let data = request.body.as_mut().and_then(|body| {
|
if let Err(error) = handle_allowcert_request(request, context) {
|
||||||
let stream = body.take_stream();
|
warn!("Could not handle allowcert request: {error}");
|
||||||
let stream = stream.lock().unwrap();
|
|
||||||
let (body_chan, body_port) = ipc::channel().unwrap();
|
|
||||||
let _ = stream.send(BodyChunkRequest::Connect(body_chan));
|
|
||||||
let _ = stream.send(BodyChunkRequest::Chunk);
|
|
||||||
match body_port.recv().ok() {
|
|
||||||
Some(BodyChunkResponse::Chunk(bytes)) => Some(bytes),
|
|
||||||
_ => panic!("cert should be sent in a single chunk."),
|
|
||||||
}
|
|
||||||
});
|
|
||||||
let data = data.as_ref().and_then(|b| {
|
|
||||||
let idx = b.iter().position(|b| *b == b'&')?;
|
|
||||||
Some(b.split_at(idx))
|
|
||||||
});
|
|
||||||
|
|
||||||
if let Some((secret, bytes)) = data {
|
|
||||||
let secret = str::from_utf8(secret).ok().and_then(|s| s.parse().ok());
|
|
||||||
if secret == Some(*net_traits::PRIVILEGED_SECRET) {
|
|
||||||
if let Ok(bytes) = base64::engine::general_purpose::STANDARD.decode(&bytes[1..])
|
|
||||||
{
|
|
||||||
context.state.extra_certs.add(bytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
create_blank_reply(url, request.timing_type())
|
create_blank_reply(url, request.timing_type())
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,10 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use crate::connector::{create_http_client, ConnectionCerts, Connector, ExtraCerts, TlsConfig};
|
use crate::connector::{
|
||||||
|
create_http_client, create_tls_config, CACertificates, CertificateErrorOverrideManager,
|
||||||
|
Connector,
|
||||||
|
};
|
||||||
use crate::cookie;
|
use crate::cookie;
|
||||||
use crate::cookie_storage::CookieStorage;
|
use crate::cookie_storage::CookieStorage;
|
||||||
use crate::decoder::Decoder;
|
use crate::decoder::Decoder;
|
||||||
|
@ -98,12 +101,12 @@ pub struct HttpState {
|
||||||
pub auth_cache: RwLock<AuthCache>,
|
pub auth_cache: RwLock<AuthCache>,
|
||||||
pub history_states: RwLock<HashMap<HistoryStateId, Vec<u8>>>,
|
pub history_states: RwLock<HashMap<HistoryStateId, Vec<u8>>>,
|
||||||
pub client: Client<Connector, Body>,
|
pub client: Client<Connector, Body>,
|
||||||
pub extra_certs: ExtraCerts,
|
pub override_manager: CertificateErrorOverrideManager,
|
||||||
pub connection_certs: ConnectionCerts,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HttpState {
|
impl HttpState {
|
||||||
pub fn new(tls_config: TlsConfig) -> HttpState {
|
pub fn new() -> HttpState {
|
||||||
|
let override_manager = CertificateErrorOverrideManager::new();
|
||||||
HttpState {
|
HttpState {
|
||||||
hsts_list: RwLock::new(HstsList::new()),
|
hsts_list: RwLock::new(HstsList::new()),
|
||||||
cookie_jar: RwLock::new(CookieStorage::new(150)),
|
cookie_jar: RwLock::new(CookieStorage::new(150)),
|
||||||
|
@ -111,9 +114,12 @@ impl HttpState {
|
||||||
history_states: RwLock::new(HashMap::new()),
|
history_states: RwLock::new(HashMap::new()),
|
||||||
http_cache: RwLock::new(HttpCache::new()),
|
http_cache: RwLock::new(HttpCache::new()),
|
||||||
http_cache_state: Mutex::new(HashMap::new()),
|
http_cache_state: Mutex::new(HashMap::new()),
|
||||||
client: create_http_client(tls_config),
|
client: create_http_client(create_tls_config(
|
||||||
extra_certs: ExtraCerts::new(),
|
CACertificates::Default,
|
||||||
connection_certs: ConnectionCerts::new(),
|
false, /* ignore_certificate_errors */
|
||||||
|
override_manager.clone(),
|
||||||
|
)),
|
||||||
|
override_manager,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -652,18 +658,12 @@ async fn obtain_response(
|
||||||
let send_start = precise_time_ms();
|
let send_start = precise_time_ms();
|
||||||
|
|
||||||
let host = request.uri().host().unwrap_or("").to_owned();
|
let host = request.uri().host().unwrap_or("").to_owned();
|
||||||
let host_clone = request.uri().host().unwrap_or("").to_owned();
|
let override_manager = context.state.override_manager.clone();
|
||||||
let connection_certs = context.state.connection_certs.clone();
|
|
||||||
let connection_certs_clone = context.state.connection_certs.clone();
|
|
||||||
|
|
||||||
let headers = headers.clone();
|
let headers = headers.clone();
|
||||||
|
|
||||||
client
|
client
|
||||||
.request(request)
|
.request(request)
|
||||||
.and_then(move |res| {
|
.and_then(move |res| {
|
||||||
// We no longer need to track the cert for this connection.
|
|
||||||
connection_certs.remove(host);
|
|
||||||
|
|
||||||
let send_end = precise_time_ms();
|
let send_end = precise_time_ms();
|
||||||
|
|
||||||
// TODO(#21271) response_start: immediately after receiving first byte of response
|
// TODO(#21271) response_start: immediately after receiving first byte of response
|
||||||
|
@ -696,8 +696,11 @@ async fn obtain_response(
|
||||||
};
|
};
|
||||||
future::ready(Ok((Decoder::detect(res), msg)))
|
future::ready(Ok((Decoder::detect(res), msg)))
|
||||||
})
|
})
|
||||||
.map_err(move |e| {
|
.map_err(move |error| {
|
||||||
NetworkError::from_hyper_error(&e, connection_certs_clone.remove(host_clone))
|
NetworkError::from_hyper_error(
|
||||||
|
&error,
|
||||||
|
override_manager.remove_certificate_failing_verification(host.as_str()),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,3 @@ pub mod test {
|
||||||
pub use crate::hosts::{parse_hostsfile, replace_host_table};
|
pub use crate::hosts::{parse_hostsfile, replace_host_table};
|
||||||
pub use crate::http_loader::HttpState;
|
pub use crate::http_loader::HttpState;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This dependency gives `build.rs` access to the `DEP_OPENSSL_VERSION_NUMBER` env variable.
|
|
||||||
use openssl_sys as _;
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
//! A thread that takes a URL and streams back the binary data.
|
//! A thread that takes a URL and streams back the binary data.
|
||||||
|
|
||||||
use crate::connector::{
|
use crate::connector::{
|
||||||
create_http_client, create_tls_config, ConnectionCerts, ExtraCerts, ALPN_H2_H1,
|
create_http_client, create_tls_config, CACertificates, CertificateErrorOverrideManager,
|
||||||
};
|
};
|
||||||
use crate::cookie;
|
use crate::cookie;
|
||||||
use crate::cookie_storage::CookieStorage;
|
use crate::cookie_storage::CookieStorage;
|
||||||
|
@ -19,7 +19,6 @@ use crate::storage_thread::StorageThreadFactory;
|
||||||
use crate::websocket_loader;
|
use crate::websocket_loader;
|
||||||
use crossbeam_channel::Sender;
|
use crossbeam_channel::Sender;
|
||||||
use devtools_traits::DevtoolsControlMsg;
|
use devtools_traits::DevtoolsControlMsg;
|
||||||
use embedder_traits::resources::{self, Resource};
|
|
||||||
use embedder_traits::EmbedderProxy;
|
use embedder_traits::EmbedderProxy;
|
||||||
use hyper_serde::Serde;
|
use hyper_serde::Serde;
|
||||||
use ipc_channel::ipc::{self, IpcReceiver, IpcReceiverSet, IpcSender};
|
use ipc_channel::ipc::{self, IpcReceiver, IpcReceiverSet, IpcSender};
|
||||||
|
@ -39,19 +38,30 @@ use net_traits::{ResourceThreads, WebSocketDomAction};
|
||||||
use profile_traits::mem::ProfilerChan as MemProfilerChan;
|
use profile_traits::mem::ProfilerChan as MemProfilerChan;
|
||||||
use profile_traits::mem::{Report, ReportKind, ReportsChan};
|
use profile_traits::mem::{Report, ReportKind, ReportsChan};
|
||||||
use profile_traits::time::ProfilerChan;
|
use profile_traits::time::ProfilerChan;
|
||||||
|
use rustls::RootCertStore;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use servo_arc::Arc as ServoArc;
|
use servo_arc::Arc as ServoArc;
|
||||||
use servo_url::{ImmutableOrigin, ServoUrl};
|
use servo_url::{ImmutableOrigin, ServoUrl};
|
||||||
use std::borrow::{Cow, ToOwned};
|
use std::borrow::{Cow, ToOwned};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fs::{self, File};
|
use std::fs::File;
|
||||||
use std::io::prelude::*;
|
use std::io::{self, prelude::*, BufReader};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::{Arc, Mutex, RwLock};
|
use std::sync::{Arc, Mutex, RwLock};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
/// Load a file with CA certificate and produce a RootCertStore with the results.
|
||||||
|
fn load_root_cert_store_from_file(file_path: String) -> io::Result<RootCertStore> {
|
||||||
|
let mut root_cert_store = RootCertStore::empty();
|
||||||
|
|
||||||
|
let mut pem = BufReader::new(File::open(file_path)?);
|
||||||
|
let certs = rustls_pemfile::certs(&mut pem)?;
|
||||||
|
root_cert_store.add_parsable_certificates(&certs);
|
||||||
|
Ok(root_cert_store)
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns a tuple of (public, private) senders to the new threads.
|
/// Returns a tuple of (public, private) senders to the new threads.
|
||||||
pub fn new_resource_threads(
|
pub fn new_resource_threads(
|
||||||
user_agent: Cow<'static, str>,
|
user_agent: Cow<'static, str>,
|
||||||
|
@ -61,7 +71,19 @@ pub fn new_resource_threads(
|
||||||
embedder_proxy: EmbedderProxy,
|
embedder_proxy: EmbedderProxy,
|
||||||
config_dir: Option<PathBuf>,
|
config_dir: Option<PathBuf>,
|
||||||
certificate_path: Option<String>,
|
certificate_path: Option<String>,
|
||||||
|
ignore_certificate_errors: bool,
|
||||||
) -> (ResourceThreads, ResourceThreads) {
|
) -> (ResourceThreads, ResourceThreads) {
|
||||||
|
let ca_certificates = match certificate_path {
|
||||||
|
Some(path) => match load_root_cert_store_from_file(path) {
|
||||||
|
Ok(root_cert_store) => CACertificates::Override(root_cert_store),
|
||||||
|
Err(error) => {
|
||||||
|
warn!("Could not load CA file. Falling back to defaults. {error:?}");
|
||||||
|
CACertificates::Default
|
||||||
|
},
|
||||||
|
},
|
||||||
|
None => CACertificates::Default,
|
||||||
|
};
|
||||||
|
|
||||||
let (public_core, private_core) = new_core_resource_thread(
|
let (public_core, private_core) = new_core_resource_thread(
|
||||||
user_agent,
|
user_agent,
|
||||||
devtools_sender,
|
devtools_sender,
|
||||||
|
@ -69,7 +91,8 @@ pub fn new_resource_threads(
|
||||||
mem_profiler_chan,
|
mem_profiler_chan,
|
||||||
embedder_proxy,
|
embedder_proxy,
|
||||||
config_dir.clone(),
|
config_dir.clone(),
|
||||||
certificate_path,
|
ca_certificates,
|
||||||
|
ignore_certificate_errors,
|
||||||
);
|
);
|
||||||
let storage: IpcSender<StorageThreadMsg> = StorageThreadFactory::new(config_dir);
|
let storage: IpcSender<StorageThreadMsg> = StorageThreadFactory::new(config_dir);
|
||||||
(
|
(
|
||||||
|
@ -86,7 +109,8 @@ pub fn new_core_resource_thread(
|
||||||
mem_profiler_chan: MemProfilerChan,
|
mem_profiler_chan: MemProfilerChan,
|
||||||
embedder_proxy: EmbedderProxy,
|
embedder_proxy: EmbedderProxy,
|
||||||
config_dir: Option<PathBuf>,
|
config_dir: Option<PathBuf>,
|
||||||
certificate_path: Option<String>,
|
ca_certificates: CACertificates,
|
||||||
|
ignore_certificate_errors: bool,
|
||||||
) -> (CoreResourceThread, CoreResourceThread) {
|
) -> (CoreResourceThread, CoreResourceThread) {
|
||||||
let (public_setup_chan, public_setup_port) = ipc::channel().unwrap();
|
let (public_setup_chan, public_setup_port) = ipc::channel().unwrap();
|
||||||
let (private_setup_chan, private_setup_port) = ipc::channel().unwrap();
|
let (private_setup_chan, private_setup_port) = ipc::channel().unwrap();
|
||||||
|
@ -100,13 +124,15 @@ pub fn new_core_resource_thread(
|
||||||
devtools_sender,
|
devtools_sender,
|
||||||
time_profiler_chan,
|
time_profiler_chan,
|
||||||
embedder_proxy,
|
embedder_proxy,
|
||||||
certificate_path.clone(),
|
ca_certificates.clone(),
|
||||||
|
ignore_certificate_errors,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut channel_manager = ResourceChannelManager {
|
let mut channel_manager = ResourceChannelManager {
|
||||||
resource_manager,
|
resource_manager,
|
||||||
config_dir,
|
config_dir,
|
||||||
certificate_path,
|
ca_certificates,
|
||||||
|
ignore_certificate_errors,
|
||||||
};
|
};
|
||||||
|
|
||||||
mem_profiler_chan.run_with_memory_reporting(
|
mem_profiler_chan.run_with_memory_reporting(
|
||||||
|
@ -123,12 +149,14 @@ pub fn new_core_resource_thread(
|
||||||
struct ResourceChannelManager {
|
struct ResourceChannelManager {
|
||||||
resource_manager: CoreResourceManager,
|
resource_manager: CoreResourceManager,
|
||||||
config_dir: Option<PathBuf>,
|
config_dir: Option<PathBuf>,
|
||||||
certificate_path: Option<String>,
|
ca_certificates: CACertificates,
|
||||||
|
ignore_certificate_errors: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_http_states(
|
fn create_http_states(
|
||||||
config_dir: Option<&Path>,
|
config_dir: Option<&Path>,
|
||||||
certificate_path: Option<String>,
|
ca_certificates: CACertificates,
|
||||||
|
ignore_certificate_errors: bool,
|
||||||
) -> (Arc<HttpState>, Arc<HttpState>) {
|
) -> (Arc<HttpState>, Arc<HttpState>) {
|
||||||
let mut hsts_list = HstsList::from_servo_preload();
|
let mut hsts_list = HstsList::from_servo_preload();
|
||||||
let mut auth_cache = AuthCache::new();
|
let mut auth_cache = AuthCache::new();
|
||||||
|
@ -140,14 +168,7 @@ fn create_http_states(
|
||||||
read_json_from_file(&mut cookie_jar, config_dir, "cookie_jar.json");
|
read_json_from_file(&mut cookie_jar, config_dir, "cookie_jar.json");
|
||||||
}
|
}
|
||||||
|
|
||||||
let certs = match certificate_path {
|
let override_manager = CertificateErrorOverrideManager::new();
|
||||||
Some(ref path) => fs::read_to_string(path).expect("Couldn't not find certificate file"),
|
|
||||||
None => resources::read_string(Resource::SSLCertificates),
|
|
||||||
};
|
|
||||||
|
|
||||||
let extra_certs = ExtraCerts::new();
|
|
||||||
let connection_certs = ConnectionCerts::new();
|
|
||||||
|
|
||||||
let http_state = HttpState {
|
let http_state = HttpState {
|
||||||
hsts_list: RwLock::new(hsts_list),
|
hsts_list: RwLock::new(hsts_list),
|
||||||
cookie_jar: RwLock::new(cookie_jar),
|
cookie_jar: RwLock::new(cookie_jar),
|
||||||
|
@ -156,18 +177,14 @@ fn create_http_states(
|
||||||
http_cache: RwLock::new(http_cache),
|
http_cache: RwLock::new(http_cache),
|
||||||
http_cache_state: Mutex::new(HashMap::new()),
|
http_cache_state: Mutex::new(HashMap::new()),
|
||||||
client: create_http_client(create_tls_config(
|
client: create_http_client(create_tls_config(
|
||||||
&certs,
|
ca_certificates.clone(),
|
||||||
ALPN_H2_H1,
|
ignore_certificate_errors,
|
||||||
extra_certs.clone(),
|
override_manager.clone(),
|
||||||
connection_certs.clone(),
|
|
||||||
)),
|
)),
|
||||||
extra_certs,
|
override_manager,
|
||||||
connection_certs,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let extra_certs = ExtraCerts::new();
|
let override_manager = CertificateErrorOverrideManager::new();
|
||||||
let connection_certs = ConnectionCerts::new();
|
|
||||||
|
|
||||||
let private_http_state = HttpState {
|
let private_http_state = HttpState {
|
||||||
hsts_list: RwLock::new(HstsList::from_servo_preload()),
|
hsts_list: RwLock::new(HstsList::from_servo_preload()),
|
||||||
cookie_jar: RwLock::new(CookieStorage::new(150)),
|
cookie_jar: RwLock::new(CookieStorage::new(150)),
|
||||||
|
@ -176,13 +193,11 @@ fn create_http_states(
|
||||||
http_cache: RwLock::new(HttpCache::new()),
|
http_cache: RwLock::new(HttpCache::new()),
|
||||||
http_cache_state: Mutex::new(HashMap::new()),
|
http_cache_state: Mutex::new(HashMap::new()),
|
||||||
client: create_http_client(create_tls_config(
|
client: create_http_client(create_tls_config(
|
||||||
&certs,
|
ca_certificates,
|
||||||
ALPN_H2_H1,
|
ignore_certificate_errors,
|
||||||
extra_certs.clone(),
|
override_manager.clone(),
|
||||||
connection_certs.clone(),
|
|
||||||
)),
|
)),
|
||||||
extra_certs,
|
override_manager,
|
||||||
connection_certs,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
(Arc::new(http_state), Arc::new(private_http_state))
|
(Arc::new(http_state), Arc::new(private_http_state))
|
||||||
|
@ -198,7 +213,8 @@ impl ResourceChannelManager {
|
||||||
) {
|
) {
|
||||||
let (public_http_state, private_http_state) = create_http_states(
|
let (public_http_state, private_http_state) = create_http_states(
|
||||||
self.config_dir.as_ref().map(Deref::deref),
|
self.config_dir.as_ref().map(Deref::deref),
|
||||||
self.certificate_path.clone(),
|
self.ca_certificates.clone(),
|
||||||
|
self.ignore_certificate_errors,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut rx_set = IpcReceiverSet::new().unwrap();
|
let mut rx_set = IpcReceiverSet::new().unwrap();
|
||||||
|
@ -455,7 +471,8 @@ pub struct CoreResourceManager {
|
||||||
sw_managers: HashMap<ImmutableOrigin, IpcSender<CustomResponseMediator>>,
|
sw_managers: HashMap<ImmutableOrigin, IpcSender<CustomResponseMediator>>,
|
||||||
filemanager: FileManager,
|
filemanager: FileManager,
|
||||||
thread_pool: Arc<CoreResourceThreadPool>,
|
thread_pool: Arc<CoreResourceThreadPool>,
|
||||||
certificate_path: Option<String>,
|
ca_certificates: CACertificates,
|
||||||
|
ignore_certificate_errors: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The state of the thread-pool used by CoreResource.
|
/// The state of the thread-pool used by CoreResource.
|
||||||
|
@ -589,7 +606,8 @@ impl CoreResourceManager {
|
||||||
devtools_sender: Option<Sender<DevtoolsControlMsg>>,
|
devtools_sender: Option<Sender<DevtoolsControlMsg>>,
|
||||||
_profiler_chan: ProfilerChan,
|
_profiler_chan: ProfilerChan,
|
||||||
embedder_proxy: EmbedderProxy,
|
embedder_proxy: EmbedderProxy,
|
||||||
certificate_path: Option<String>,
|
ca_certificates: CACertificates,
|
||||||
|
ignore_certificate_errors: bool,
|
||||||
) -> CoreResourceManager {
|
) -> CoreResourceManager {
|
||||||
let pool = CoreResourceThreadPool::new(16);
|
let pool = CoreResourceThreadPool::new(16);
|
||||||
let pool_handle = Arc::new(pool);
|
let pool_handle = Arc::new(pool);
|
||||||
|
@ -599,7 +617,8 @@ impl CoreResourceManager {
|
||||||
sw_managers: Default::default(),
|
sw_managers: Default::default(),
|
||||||
filemanager: FileManager::new(embedder_proxy, Arc::downgrade(&pool_handle)),
|
filemanager: FileManager::new(embedder_proxy, Arc::downgrade(&pool_handle)),
|
||||||
thread_pool: pool_handle,
|
thread_pool: pool_handle,
|
||||||
certificate_path,
|
ca_certificates,
|
||||||
|
ignore_certificate_errors,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -725,7 +744,8 @@ impl CoreResourceManager {
|
||||||
event_sender,
|
event_sender,
|
||||||
action_receiver,
|
action_receiver,
|
||||||
http_state.clone(),
|
http_state.clone(),
|
||||||
self.certificate_path.clone(),
|
self.ca_certificates.clone(),
|
||||||
|
self.ignore_certificate_errors,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@ use hyper::Body;
|
||||||
use hyper::{Request as HyperRequest, Response as HyperResponse};
|
use hyper::{Request as HyperRequest, Response as HyperResponse};
|
||||||
use mime::{self, Mime};
|
use mime::{self, Mime};
|
||||||
use msg::constellation_msg::TEST_PIPELINE_ID;
|
use msg::constellation_msg::TEST_PIPELINE_ID;
|
||||||
use net::connector::{create_tls_config, ConnectionCerts, ExtraCerts, ALPN_H2_H1};
|
|
||||||
use net::fetch::cors_cache::CorsCache;
|
use net::fetch::cors_cache::CorsCache;
|
||||||
use net::fetch::methods::{self, CancellationListener, FetchContext};
|
use net::fetch::methods::{self, CancellationListener, FetchContext};
|
||||||
use net::filemanager_thread::FileManager;
|
use net::filemanager_thread::FileManager;
|
||||||
|
@ -756,24 +755,10 @@ fn test_fetch_with_hsts() {
|
||||||
*response.body_mut() = MESSAGE.to_vec().into();
|
*response.body_mut() = MESSAGE.to_vec().into();
|
||||||
};
|
};
|
||||||
|
|
||||||
let cert_path = Path::new("../../resources/self_signed_certificate_for_testing.crt")
|
let (server, url) = make_ssl_server(handler);
|
||||||
.canonicalize()
|
|
||||||
.unwrap();
|
|
||||||
let key_path = Path::new("../../resources/privatekey_for_testing.key")
|
|
||||||
.canonicalize()
|
|
||||||
.unwrap();
|
|
||||||
let (server, url) = make_ssl_server(handler, cert_path.clone(), key_path.clone());
|
|
||||||
|
|
||||||
let certs = fs::read_to_string(cert_path).expect("Couldn't find certificate file");
|
|
||||||
let tls_config = create_tls_config(
|
|
||||||
&certs,
|
|
||||||
ALPN_H2_H1,
|
|
||||||
ExtraCerts::new(),
|
|
||||||
ConnectionCerts::new(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut context = FetchContext {
|
let mut context = FetchContext {
|
||||||
state: Arc::new(HttpState::new(tls_config)),
|
state: Arc::new(HttpState::new()),
|
||||||
user_agent: DEFAULT_USER_AGENT.into(),
|
user_agent: DEFAULT_USER_AGENT.into(),
|
||||||
devtools_chan: None,
|
devtools_chan: None,
|
||||||
filemanager: Arc::new(Mutex::new(FileManager::new(
|
filemanager: Arc::new(Mutex::new(FileManager::new(
|
||||||
|
@ -787,6 +772,12 @@ fn test_fetch_with_hsts() {
|
||||||
))),
|
))),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// The server certificate is self-signed, so we need to add an override
|
||||||
|
// so that the connection works properly.
|
||||||
|
for certificate in server.certificates.as_ref().unwrap().iter() {
|
||||||
|
context.state.override_manager.add_override(certificate);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut list = context.state.hsts_list.write().unwrap();
|
let mut list = context.state.hsts_list.write().unwrap();
|
||||||
list.push(
|
list.push(
|
||||||
|
@ -821,25 +812,12 @@ fn test_load_adds_host_to_hsts_list_when_url_is_https() {
|
||||||
));
|
));
|
||||||
*response.body_mut() = b"Yay!".to_vec().into();
|
*response.body_mut() = b"Yay!".to_vec().into();
|
||||||
};
|
};
|
||||||
let cert_path = Path::new("../../resources/self_signed_certificate_for_testing.crt")
|
|
||||||
.canonicalize()
|
let (server, mut url) = make_ssl_server(handler);
|
||||||
.unwrap();
|
|
||||||
let key_path = Path::new("../../resources/privatekey_for_testing.key")
|
|
||||||
.canonicalize()
|
|
||||||
.unwrap();
|
|
||||||
let (server, mut url) = make_ssl_server(handler, cert_path.clone(), key_path.clone());
|
|
||||||
url.as_mut_url().set_scheme("https").unwrap();
|
url.as_mut_url().set_scheme("https").unwrap();
|
||||||
|
|
||||||
let certs = fs::read_to_string(cert_path).expect("Couldn't find certificate file");
|
|
||||||
let tls_config = create_tls_config(
|
|
||||||
&certs,
|
|
||||||
ALPN_H2_H1,
|
|
||||||
ExtraCerts::new(),
|
|
||||||
ConnectionCerts::new(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut context = FetchContext {
|
let mut context = FetchContext {
|
||||||
state: Arc::new(HttpState::new(tls_config)),
|
state: Arc::new(HttpState::new()),
|
||||||
user_agent: DEFAULT_USER_AGENT.into(),
|
user_agent: DEFAULT_USER_AGENT.into(),
|
||||||
devtools_chan: None,
|
devtools_chan: None,
|
||||||
filemanager: Arc::new(Mutex::new(FileManager::new(
|
filemanager: Arc::new(Mutex::new(FileManager::new(
|
||||||
|
@ -853,6 +831,12 @@ fn test_load_adds_host_to_hsts_list_when_url_is_https() {
|
||||||
))),
|
))),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// The server certificate is self-signed, so we need to add an override
|
||||||
|
// so that the connection works properly.
|
||||||
|
for certificate in server.certificates.as_ref().unwrap().iter() {
|
||||||
|
context.state.override_manager.add_override(certificate);
|
||||||
|
}
|
||||||
|
|
||||||
let mut request = RequestBuilder::new(url.clone(), Referrer::NoReferrer)
|
let mut request = RequestBuilder::new(url.clone(), Referrer::NoReferrer)
|
||||||
.method(Method::GET)
|
.method(Method::GET)
|
||||||
.body(None)
|
.body(None)
|
||||||
|
@ -885,29 +869,12 @@ fn test_fetch_self_signed() {
|
||||||
let handler = move |_: HyperRequest<Body>, response: &mut HyperResponse<Body>| {
|
let handler = move |_: HyperRequest<Body>, response: &mut HyperResponse<Body>| {
|
||||||
*response.body_mut() = b"Yay!".to_vec().into();
|
*response.body_mut() = b"Yay!".to_vec().into();
|
||||||
};
|
};
|
||||||
let client_cert_path = Path::new("../../resources/certs").canonicalize().unwrap();
|
|
||||||
let cert_path = Path::new("../../resources/self_signed_certificate_for_testing.crt")
|
let (server, mut url) = make_ssl_server(handler);
|
||||||
.canonicalize()
|
|
||||||
.unwrap();
|
|
||||||
let key_path = Path::new("../../resources/privatekey_for_testing.key")
|
|
||||||
.canonicalize()
|
|
||||||
.unwrap();
|
|
||||||
let (_server, mut url) = make_ssl_server(handler, cert_path.clone(), key_path.clone());
|
|
||||||
url.as_mut_url().set_scheme("https").unwrap();
|
url.as_mut_url().set_scheme("https").unwrap();
|
||||||
|
|
||||||
let cert_data = fs::read_to_string(cert_path.clone()).expect("Couldn't find certificate file");
|
|
||||||
let client_cert_data =
|
|
||||||
fs::read_to_string(client_cert_path.clone()).expect("Couldn't find certificate file");
|
|
||||||
let extra_certs = ExtraCerts::new();
|
|
||||||
let tls_config = create_tls_config(
|
|
||||||
&client_cert_data,
|
|
||||||
ALPN_H2_H1,
|
|
||||||
extra_certs.clone(),
|
|
||||||
ConnectionCerts::new(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut context = FetchContext {
|
let mut context = FetchContext {
|
||||||
state: Arc::new(HttpState::new(tls_config)),
|
state: Arc::new(HttpState::new()),
|
||||||
user_agent: DEFAULT_USER_AGENT.into(),
|
user_agent: DEFAULT_USER_AGENT.into(),
|
||||||
devtools_chan: None,
|
devtools_chan: None,
|
||||||
filemanager: Arc::new(Mutex::new(FileManager::new(
|
filemanager: Arc::new(Mutex::new(FileManager::new(
|
||||||
|
@ -936,16 +903,11 @@ fn test_fetch_self_signed() {
|
||||||
Some(NetworkError::SslValidation(..))
|
Some(NetworkError::SslValidation(..))
|
||||||
));
|
));
|
||||||
|
|
||||||
extra_certs.add(cert_data.as_bytes().into());
|
// The server certificate is self-signed, so we need to add an override
|
||||||
|
// so that the connection works properly.
|
||||||
// FIXME: something weird happens inside the SSL server after the first
|
for certificate in server.certificates.as_ref().unwrap().iter() {
|
||||||
// connection encounters a verification error, and it no longer
|
context.state.override_manager.add_override(certificate);
|
||||||
// accepts new connections that should work fine. We are forced
|
}
|
||||||
// to start a new server and connect to that to verfiy that
|
|
||||||
// the self-signed cert is now accepted.
|
|
||||||
|
|
||||||
let (server, mut url) = make_ssl_server(handler, cert_path.clone(), key_path.clone());
|
|
||||||
url.as_mut_url().set_scheme("https").unwrap();
|
|
||||||
|
|
||||||
let mut request = RequestBuilder::new(url.clone(), Referrer::NoReferrer)
|
let mut request = RequestBuilder::new(url.clone(), Referrer::NoReferrer)
|
||||||
.method(Method::GET)
|
.method(Method::GET)
|
||||||
|
|
|
@ -22,10 +22,8 @@ mod resource_thread;
|
||||||
mod subresource_integrity;
|
mod subresource_integrity;
|
||||||
|
|
||||||
use core::convert::Infallible;
|
use core::convert::Infallible;
|
||||||
use core::pin::Pin;
|
|
||||||
use crossbeam_channel::{unbounded, Sender};
|
use crossbeam_channel::{unbounded, Sender};
|
||||||
use devtools_traits::DevtoolsControlMsg;
|
use devtools_traits::DevtoolsControlMsg;
|
||||||
use embedder_traits::resources::{self, Resource};
|
|
||||||
use embedder_traits::{EmbedderProxy, EventLoopWaker};
|
use embedder_traits::{EmbedderProxy, EventLoopWaker};
|
||||||
use futures::future::ready;
|
use futures::future::ready;
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
|
@ -33,7 +31,6 @@ use hyper::server::conn::Http;
|
||||||
use hyper::server::Server as HyperServer;
|
use hyper::server::Server as HyperServer;
|
||||||
use hyper::service::{make_service_fn, service_fn};
|
use hyper::service::{make_service_fn, service_fn};
|
||||||
use hyper::{Body, Request as HyperRequest, Response as HyperResponse};
|
use hyper::{Body, Request as HyperRequest, Response as HyperResponse};
|
||||||
use net::connector::{create_tls_config, ConnectionCerts, ExtraCerts, ALPN_H2_H1};
|
|
||||||
use net::fetch::cors_cache::CorsCache;
|
use net::fetch::cors_cache::CorsCache;
|
||||||
use net::fetch::methods::{self, CancellationListener, FetchContext};
|
use net::fetch::methods::{self, CancellationListener, FetchContext};
|
||||||
use net::filemanager_thread::FileManager;
|
use net::filemanager_thread::FileManager;
|
||||||
|
@ -43,16 +40,19 @@ use net_traits::filemanager_thread::FileTokenCheck;
|
||||||
use net_traits::request::Request;
|
use net_traits::request::Request;
|
||||||
use net_traits::response::Response;
|
use net_traits::response::Response;
|
||||||
use net_traits::{FetchTaskTarget, ResourceFetchTiming, ResourceTimingType};
|
use net_traits::{FetchTaskTarget, ResourceFetchTiming, ResourceTimingType};
|
||||||
use openssl::ssl::{Ssl, SslAcceptor, SslFiletype, SslMethod};
|
use rustls::{self, Certificate, PrivateKey};
|
||||||
|
use rustls_pemfile::{certs, pkcs8_private_keys};
|
||||||
use servo_arc::Arc as ServoArc;
|
use servo_arc::Arc as ServoArc;
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::{self, BufReader};
|
||||||
use std::net::TcpListener as StdTcpListener;
|
use std::net::TcpListener as StdTcpListener;
|
||||||
use std::path::PathBuf;
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::{Arc, Mutex, Weak};
|
use std::sync::{Arc, Mutex, Weak};
|
||||||
use tokio::net::TcpListener;
|
use tokio::net::TcpListener;
|
||||||
use tokio::net::TcpStream;
|
use tokio::net::TcpStream;
|
||||||
use tokio::runtime::{Builder, Runtime};
|
use tokio::runtime::{Builder, Runtime};
|
||||||
use tokio_openssl::SslStream;
|
use tokio_rustls::{self, TlsAcceptor};
|
||||||
use tokio_stream::wrappers::TcpListenerStream;
|
use tokio_stream::wrappers::TcpListenerStream;
|
||||||
use tokio_test::block_on;
|
use tokio_test::block_on;
|
||||||
|
|
||||||
|
@ -102,17 +102,10 @@ fn new_fetch_context(
|
||||||
fc: Option<EmbedderProxy>,
|
fc: Option<EmbedderProxy>,
|
||||||
pool_handle: Option<Weak<CoreResourceThreadPool>>,
|
pool_handle: Option<Weak<CoreResourceThreadPool>>,
|
||||||
) -> FetchContext {
|
) -> FetchContext {
|
||||||
let certs = resources::read_string(Resource::SSLCertificates);
|
|
||||||
let tls_config = create_tls_config(
|
|
||||||
&certs,
|
|
||||||
ALPN_H2_H1,
|
|
||||||
ExtraCerts::new(),
|
|
||||||
ConnectionCerts::new(),
|
|
||||||
);
|
|
||||||
let sender = fc.unwrap_or_else(|| create_embedder_proxy());
|
let sender = fc.unwrap_or_else(|| create_embedder_proxy());
|
||||||
|
|
||||||
FetchContext {
|
FetchContext {
|
||||||
state: Arc::new(HttpState::new(tls_config)),
|
state: Arc::new(HttpState::new()),
|
||||||
user_agent: DEFAULT_USER_AGENT.into(),
|
user_agent: DEFAULT_USER_AGENT.into(),
|
||||||
devtools_chan: dc.map(|dc| Arc::new(Mutex::new(dc))),
|
devtools_chan: dc.map(|dc| Arc::new(Mutex::new(dc))),
|
||||||
filemanager: Arc::new(Mutex::new(FileManager::new(
|
filemanager: Arc::new(Mutex::new(FileManager::new(
|
||||||
|
@ -167,6 +160,7 @@ fn fetch_with_cors_cache(request: &mut Request, cache: &mut CorsCache) -> Respon
|
||||||
|
|
||||||
pub(crate) struct Server {
|
pub(crate) struct Server {
|
||||||
pub close_channel: tokio::sync::oneshot::Sender<()>,
|
pub close_channel: tokio::sync::oneshot::Sender<()>,
|
||||||
|
pub certificates: Option<Vec<Certificate>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Server {
|
impl Server {
|
||||||
|
@ -205,11 +199,39 @@ where
|
||||||
};
|
};
|
||||||
|
|
||||||
HANDLE.lock().unwrap().spawn(server);
|
HANDLE.lock().unwrap().spawn(server);
|
||||||
let server = Server { close_channel: tx };
|
(
|
||||||
(server, url)
|
Server {
|
||||||
|
close_channel: tx,
|
||||||
|
certificates: None,
|
||||||
|
},
|
||||||
|
url,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_ssl_server<H>(handler: H, cert_path: PathBuf, key_path: PathBuf) -> (Server, ServoUrl)
|
/// Given a path to a file containing PEM certificates, load and parse them into
|
||||||
|
/// a vector of RusTLS [Certificate]s.
|
||||||
|
fn load_certificates_from_pem(path: &PathBuf) -> std::io::Result<Vec<Certificate>> {
|
||||||
|
let file = File::open(path)?;
|
||||||
|
let mut reader = BufReader::new(file);
|
||||||
|
let certs = certs(&mut reader)?;
|
||||||
|
Ok(certs.into_iter().map(Certificate).collect())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Given a path to a file containing PEM keys, load and parse them into
|
||||||
|
/// a vector of RusTLS [PrivateKey]s.
|
||||||
|
fn load_private_key_from_file(path: &PathBuf) -> Result<PrivateKey, Box<dyn std::error::Error>> {
|
||||||
|
let file = File::open(&path)?;
|
||||||
|
let mut reader = BufReader::new(file);
|
||||||
|
let mut keys = pkcs8_private_keys(&mut reader)?;
|
||||||
|
|
||||||
|
match keys.len() {
|
||||||
|
0 => Err(format!("No PKCS8-encoded private key found in {path:?}").into()),
|
||||||
|
1 => Ok(PrivateKey(keys.remove(0))),
|
||||||
|
_ => Err(format!("More than one PKCS8-encoded private key found in {path:?}").into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_ssl_server<H>(handler: H) -> (Server, ServoUrl)
|
||||||
where
|
where
|
||||||
H: Fn(HyperRequest<Body>, &mut HyperResponse<Body>) + Send + Sync + 'static,
|
H: Fn(HyperRequest<Body>, &mut HyperResponse<Body>) + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
|
@ -219,13 +241,28 @@ where
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.block_on(async move { TcpListener::from_std(listener).unwrap() });
|
.block_on(async move { TcpListener::from_std(listener).unwrap() });
|
||||||
|
|
||||||
let url_string = format!("http://localhost:{}", listener.local_addr().unwrap().port());
|
let url_string = format!("http://localhost:{}", listener.local_addr().unwrap().port());
|
||||||
let mut listener = TcpListenerStream::new(listener);
|
|
||||||
|
|
||||||
let url = ServoUrl::parse(&url_string).unwrap();
|
let url = ServoUrl::parse(&url_string).unwrap();
|
||||||
let (tx, mut rx) = tokio::sync::oneshot::channel::<()>();
|
|
||||||
|
|
||||||
|
let cert_path = Path::new("../../resources/self_signed_certificate_for_testing.crt")
|
||||||
|
.canonicalize()
|
||||||
|
.unwrap();
|
||||||
|
let key_path = Path::new("../../resources/privatekey_for_testing.key")
|
||||||
|
.canonicalize()
|
||||||
|
.unwrap();
|
||||||
|
let certificates = load_certificates_from_pem(&cert_path).expect("Invalid certificate");
|
||||||
|
let key = load_private_key_from_file(&key_path).expect("Invalid key");
|
||||||
|
|
||||||
|
let config = rustls::ServerConfig::builder()
|
||||||
|
.with_safe_defaults()
|
||||||
|
.with_no_client_auth()
|
||||||
|
.with_single_cert(certificates.clone(), key)
|
||||||
|
.map_err(|err| io::Error::new(io::ErrorKind::InvalidInput, err))
|
||||||
|
.expect("Could not create rustls ServerConfig");
|
||||||
|
let acceptor = TlsAcceptor::from(Arc::new(config));
|
||||||
|
|
||||||
|
let mut listener = TcpListenerStream::new(listener);
|
||||||
|
let (tx, mut rx) = tokio::sync::oneshot::channel::<()>();
|
||||||
let server = async move {
|
let server = async move {
|
||||||
loop {
|
loop {
|
||||||
let stream = tokio::select! {
|
let stream = tokio::select! {
|
||||||
|
@ -244,22 +281,16 @@ where
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let stream = TcpStream::from_std(stream).unwrap();
|
let stream = TcpStream::from_std(stream).unwrap();
|
||||||
|
|
||||||
let mut tls_server_config =
|
|
||||||
SslAcceptor::mozilla_intermediate_v5(SslMethod::tls()).unwrap();
|
|
||||||
tls_server_config
|
|
||||||
.set_certificate_file(&cert_path, SslFiletype::PEM)
|
|
||||||
.unwrap();
|
|
||||||
tls_server_config
|
|
||||||
.set_private_key_file(&key_path, SslFiletype::PEM)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let tls_server_config = tls_server_config.build();
|
|
||||||
let ssl = Ssl::new(tls_server_config.context()).unwrap();
|
|
||||||
let mut stream = SslStream::new(ssl, stream).unwrap();
|
|
||||||
|
|
||||||
let _ = Pin::new(&mut stream).accept().await;
|
|
||||||
|
|
||||||
let handler = handler.clone();
|
let handler = handler.clone();
|
||||||
|
let acceptor = acceptor.clone();
|
||||||
|
|
||||||
|
let stream = match acceptor.accept(stream).await {
|
||||||
|
Ok(stream) => stream,
|
||||||
|
Err(_) => {
|
||||||
|
eprintln!("Error handling TLS stream.");
|
||||||
|
continue;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
let _ = Http::new()
|
let _ = Http::new()
|
||||||
.serve_connection(
|
.serve_connection(
|
||||||
|
@ -276,6 +307,11 @@ where
|
||||||
|
|
||||||
HANDLE.lock().unwrap().spawn(server);
|
HANDLE.lock().unwrap().spawn(server);
|
||||||
|
|
||||||
let server = Server { close_channel: tx };
|
(
|
||||||
(server, url)
|
Server {
|
||||||
|
close_channel: tx,
|
||||||
|
certificates: Some(certificates),
|
||||||
|
},
|
||||||
|
url,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
use crate::create_embedder_proxy;
|
use crate::create_embedder_proxy;
|
||||||
use ipc_channel::ipc;
|
use ipc_channel::ipc;
|
||||||
|
use net::connector::CACertificates;
|
||||||
use net::resource_thread::new_core_resource_thread;
|
use net::resource_thread::new_core_resource_thread;
|
||||||
use net::test::parse_hostsfile;
|
use net::test::parse_hostsfile;
|
||||||
use net_traits::CoreResourceMsg;
|
use net_traits::CoreResourceMsg;
|
||||||
|
@ -27,7 +28,8 @@ fn test_exit() {
|
||||||
MemProfilerChan(mtx),
|
MemProfilerChan(mtx),
|
||||||
create_embedder_proxy(),
|
create_embedder_proxy(),
|
||||||
None,
|
None,
|
||||||
None,
|
CACertificates::Default,
|
||||||
|
false, /* ignore_certificate_errors */
|
||||||
);
|
);
|
||||||
resource_thread.send(CoreResourceMsg::Exit(sender)).unwrap();
|
resource_thread.send(CoreResourceMsg::Exit(sender)).unwrap();
|
||||||
receiver.recv().unwrap();
|
receiver.recv().unwrap();
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
//! over events from the network and events from the DOM, using async/await to avoid
|
//! over events from the network and events from the DOM, using async/await to avoid
|
||||||
//! the need for a dedicated thread per websocket.
|
//! the need for a dedicated thread per websocket.
|
||||||
|
|
||||||
use crate::connector::{create_tls_config, ALPN_H1};
|
use crate::connector::{create_tls_config, CACertificates, TlsConfig};
|
||||||
use crate::cookie::Cookie;
|
use crate::cookie::Cookie;
|
||||||
use crate::fetch::methods::should_be_blocked_due_to_bad_port;
|
use crate::fetch::methods::should_be_blocked_due_to_bad_port;
|
||||||
use crate::hosts::replace_host;
|
use crate::hosts::replace_host;
|
||||||
|
@ -19,7 +19,6 @@ use crate::http_loader::HttpState;
|
||||||
use async_tungstenite::tokio::{client_async_tls_with_connector_and_config, ConnectStream};
|
use async_tungstenite::tokio::{client_async_tls_with_connector_and_config, ConnectStream};
|
||||||
use async_tungstenite::WebSocketStream;
|
use async_tungstenite::WebSocketStream;
|
||||||
use base64::Engine;
|
use base64::Engine;
|
||||||
use embedder_traits::resources::{self, Resource};
|
|
||||||
use futures::future::TryFutureExt;
|
use futures::future::TryFutureExt;
|
||||||
use futures::sink::SinkExt;
|
use futures::sink::SinkExt;
|
||||||
use futures::stream::StreamExt;
|
use futures::stream::StreamExt;
|
||||||
|
@ -29,15 +28,14 @@ use ipc_channel::router::ROUTER;
|
||||||
use net_traits::request::{RequestBuilder, RequestMode};
|
use net_traits::request::{RequestBuilder, RequestMode};
|
||||||
use net_traits::{CookieSource, MessageData};
|
use net_traits::{CookieSource, MessageData};
|
||||||
use net_traits::{WebSocketDomAction, WebSocketNetworkEvent};
|
use net_traits::{WebSocketDomAction, WebSocketNetworkEvent};
|
||||||
use openssl::ssl::ConnectConfiguration;
|
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
use std::fs;
|
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use tokio::net::TcpStream;
|
use tokio::net::TcpStream;
|
||||||
use tokio::runtime::Runtime;
|
use tokio::runtime::Runtime;
|
||||||
use tokio::select;
|
use tokio::select;
|
||||||
use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver};
|
use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver};
|
||||||
|
use tokio_rustls::TlsConnector;
|
||||||
use tungstenite::error::Result as WebSocketResult;
|
use tungstenite::error::Result as WebSocketResult;
|
||||||
use tungstenite::error::{Error, ProtocolError, UrlError};
|
use tungstenite::error::{Error, ProtocolError, UrlError};
|
||||||
use tungstenite::handshake::client::{Request, Response};
|
use tungstenite::handshake::client::{Request, Response};
|
||||||
|
@ -302,7 +300,7 @@ async fn start_websocket(
|
||||||
resource_event_sender: IpcSender<WebSocketNetworkEvent>,
|
resource_event_sender: IpcSender<WebSocketNetworkEvent>,
|
||||||
protocols: Vec<String>,
|
protocols: Vec<String>,
|
||||||
client: Request,
|
client: Request,
|
||||||
tls_config: ConnectConfiguration,
|
tls_config: TlsConfig,
|
||||||
dom_action_receiver: IpcReceiver<WebSocketDomAction>,
|
dom_action_receiver: IpcReceiver<WebSocketDomAction>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
trace!("starting WS connection to {}", url);
|
trace!("starting WS connection to {}", url);
|
||||||
|
@ -330,8 +328,10 @@ async fn start_websocket(
|
||||||
|
|
||||||
let try_socket = TcpStream::connect((&*domain.to_string(), port)).await;
|
let try_socket = TcpStream::connect((&*domain.to_string(), port)).await;
|
||||||
let socket = try_socket.map_err(Error::Io)?;
|
let socket = try_socket.map_err(Error::Io)?;
|
||||||
|
let connector = TlsConnector::from(Arc::new(tls_config));
|
||||||
|
|
||||||
let (stream, response) =
|
let (stream, response) =
|
||||||
client_async_tls_with_connector_and_config(client, socket, Some(tls_config), None).await?;
|
client_async_tls_with_connector_and_config(client, socket, Some(connector), None).await?;
|
||||||
|
|
||||||
let protocol_in_use = process_ws_response(&http_state, &response, &url, &protocols)?;
|
let protocol_in_use = process_ws_response(&http_state, &response, &url, &protocols)?;
|
||||||
|
|
||||||
|
@ -357,7 +357,8 @@ fn connect(
|
||||||
resource_event_sender: IpcSender<WebSocketNetworkEvent>,
|
resource_event_sender: IpcSender<WebSocketNetworkEvent>,
|
||||||
dom_action_receiver: IpcReceiver<WebSocketDomAction>,
|
dom_action_receiver: IpcReceiver<WebSocketDomAction>,
|
||||||
http_state: Arc<HttpState>,
|
http_state: Arc<HttpState>,
|
||||||
certificate_path: Option<String>,
|
ca_certificates: CACertificates,
|
||||||
|
ignore_certificate_errors: bool,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
let protocols = match req_builder.mode {
|
let protocols = match req_builder.mode {
|
||||||
RequestMode::WebSocket { protocols } => protocols,
|
RequestMode::WebSocket { protocols } => protocols,
|
||||||
|
@ -382,11 +383,6 @@ fn connect(
|
||||||
return Err("Port blocked".to_string());
|
return Err("Port blocked".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
let certs = match certificate_path {
|
|
||||||
Some(ref path) => fs::read_to_string(path).map_err(|e| e.to_string())?,
|
|
||||||
None => resources::read_string(Resource::SSLCertificates),
|
|
||||||
};
|
|
||||||
|
|
||||||
let client = match create_request(
|
let client = match create_request(
|
||||||
&req_url,
|
&req_url,
|
||||||
&req_builder.origin.ascii_serialization(),
|
&req_builder.origin.ascii_serialization(),
|
||||||
|
@ -397,16 +393,12 @@ fn connect(
|
||||||
Err(e) => return Err(e.to_string()),
|
Err(e) => return Err(e.to_string()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let tls_config = create_tls_config(
|
let mut tls_config = create_tls_config(
|
||||||
&certs,
|
ca_certificates,
|
||||||
ALPN_H1,
|
ignore_certificate_errors,
|
||||||
http_state.extra_certs.clone(),
|
http_state.override_manager.clone(),
|
||||||
http_state.connection_certs.clone(),
|
|
||||||
);
|
);
|
||||||
let tls_config = match tls_config.build().configure() {
|
tls_config.alpn_protocols = vec!["h2".to_string().into(), "http/1.1".to_string().into()];
|
||||||
Ok(c) => c,
|
|
||||||
Err(e) => return Err(e.to_string()),
|
|
||||||
};
|
|
||||||
|
|
||||||
let resource_event_sender2 = resource_event_sender.clone();
|
let resource_event_sender2 = resource_event_sender.clone();
|
||||||
match HANDLE.lock().unwrap().as_mut() {
|
match HANDLE.lock().unwrap().as_mut() {
|
||||||
|
@ -436,7 +428,8 @@ pub fn init(
|
||||||
resource_event_sender: IpcSender<WebSocketNetworkEvent>,
|
resource_event_sender: IpcSender<WebSocketNetworkEvent>,
|
||||||
dom_action_receiver: IpcReceiver<WebSocketDomAction>,
|
dom_action_receiver: IpcReceiver<WebSocketDomAction>,
|
||||||
http_state: Arc<HttpState>,
|
http_state: Arc<HttpState>,
|
||||||
certificate_path: Option<String>,
|
ca_certificates: CACertificates,
|
||||||
|
ignore_certificate_errors: bool,
|
||||||
) {
|
) {
|
||||||
let resource_event_sender2 = resource_event_sender.clone();
|
let resource_event_sender2 = resource_event_sender.clone();
|
||||||
if let Err(e) = connect(
|
if let Err(e) = connect(
|
||||||
|
@ -444,7 +437,8 @@ pub fn init(
|
||||||
resource_event_sender,
|
resource_event_sender,
|
||||||
dom_action_receiver,
|
dom_action_receiver,
|
||||||
http_state,
|
http_state,
|
||||||
certificate_path,
|
ca_certificates,
|
||||||
|
ignore_certificate_errors,
|
||||||
) {
|
) {
|
||||||
warn!("Error starting websocket: {}", e);
|
warn!("Error starting websocket: {}", e);
|
||||||
let _ = resource_event_sender2.send(WebSocketNetworkEvent::Fail);
|
let _ = resource_event_sender2.send(WebSocketNetworkEvent::Fail);
|
||||||
|
|
|
@ -31,6 +31,7 @@ msg = { path = "../msg" }
|
||||||
num-traits = { workspace = true }
|
num-traits = { workspace = true }
|
||||||
percent-encoding = { workspace = true }
|
percent-encoding = { workspace = true }
|
||||||
pixels = { path = "../pixels" }
|
pixels = { path = "../pixels" }
|
||||||
|
rustls = { workspace = true }
|
||||||
serde = { workspace = true }
|
serde = { workspace = true }
|
||||||
servo_arc = { path = "../servo_arc" }
|
servo_arc = { path = "../servo_arc" }
|
||||||
servo_rand = { path = "../rand" }
|
servo_rand = { path = "../rand" }
|
||||||
|
|
|
@ -30,6 +30,7 @@ use ipc_channel::router::ROUTER;
|
||||||
use ipc_channel::Error as IpcError;
|
use ipc_channel::Error as IpcError;
|
||||||
use mime::Mime;
|
use mime::Mime;
|
||||||
use msg::constellation_msg::HistoryStateId;
|
use msg::constellation_msg::HistoryStateId;
|
||||||
|
use rustls::Certificate;
|
||||||
use servo_rand::RngCore;
|
use servo_rand::RngCore;
|
||||||
use servo_url::{ImmutableOrigin, ServoUrl};
|
use servo_url::{ImmutableOrigin, ServoUrl};
|
||||||
use time::precise_time_ns;
|
use time::precise_time_ns;
|
||||||
|
@ -762,12 +763,11 @@ pub enum NetworkError {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NetworkError {
|
impl NetworkError {
|
||||||
pub fn from_hyper_error(error: &HyperError, cert_bytes: Option<Vec<u8>>) -> Self {
|
pub fn from_hyper_error(error: &HyperError, certificate: Option<Certificate>) -> Self {
|
||||||
let s = error.to_string();
|
let error_string = error.to_string();
|
||||||
if s.to_lowercase().contains("ssl") {
|
match certificate {
|
||||||
NetworkError::SslValidation(s, cert_bytes.unwrap_or_default())
|
Some(certificate) => NetworkError::SslValidation(error_string, certificate.0),
|
||||||
} else {
|
_ => NetworkError::Internal(error_string),
|
||||||
NetworkError::Internal(s)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ use crate::dom::virtualmethods::vtable_for;
|
||||||
use crate::network_listener::PreInvoke;
|
use crate::network_listener::PreInvoke;
|
||||||
use crate::realms::enter_realm;
|
use crate::realms::enter_realm;
|
||||||
use crate::script_thread::ScriptThread;
|
use crate::script_thread::ScriptThread;
|
||||||
|
use base64::{engine::general_purpose, Engine as _};
|
||||||
use content_security_policy::{self as csp, CspList};
|
use content_security_policy::{self as csp, CspList};
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use embedder_traits::resources::{self, Resource};
|
use embedder_traits::resources::{self, Resource};
|
||||||
|
@ -880,8 +881,8 @@ impl FetchResponseListener for ParserContext {
|
||||||
self.is_synthesized_document = true;
|
self.is_synthesized_document = true;
|
||||||
let page = resources::read_string(Resource::BadCertHTML);
|
let page = resources::read_string(Resource::BadCertHTML);
|
||||||
let page = page.replace("${reason}", &reason);
|
let page = page.replace("${reason}", &reason);
|
||||||
let page =
|
let encoded_bytes = general_purpose::STANDARD_NO_PAD.encode(&bytes);
|
||||||
page.replace("${bytes}", std::str::from_utf8(&bytes).unwrap_or_default());
|
let page = page.replace("${bytes}", encoded_bytes.as_str());
|
||||||
let page =
|
let page =
|
||||||
page.replace("${secret}", &net_traits::PRIVILEGED_SECRET.to_string());
|
page.replace("${secret}", &net_traits::PRIVILEGED_SECRET.to_string());
|
||||||
parser.push_string_input_chunk(page);
|
parser.push_string_input_chunk(page);
|
||||||
|
|
|
@ -857,6 +857,7 @@ fn create_constellation(
|
||||||
embedder_proxy.clone(),
|
embedder_proxy.clone(),
|
||||||
config_dir,
|
config_dir,
|
||||||
opts.certificate_path.clone(),
|
opts.certificate_path.clone(),
|
||||||
|
opts.ignore_certificate_errors,
|
||||||
);
|
);
|
||||||
|
|
||||||
let font_cache_thread = FontCacheThread::new(
|
let font_cache_thread = FontCacheThread::new(
|
||||||
|
|
|
@ -1,75 +0,0 @@
|
||||||
// XPCShell script for generating a single file containing all certificates in PEM
|
|
||||||
// format. You may run this in the browser toolbox's console
|
|
||||||
// (Firefox -> devtools -> settings -> enable remote/chrome debugging,
|
|
||||||
// followed by settings -> devtools menu -> browser toolbox) or the
|
|
||||||
// xpcshell runner that comes with a built Firefox (./run-mozilla.sh ./xpcshell).
|
|
||||||
// The variable `certstring` contains the final pem file. You can use `save(path)` to
|
|
||||||
// save it to a file. `certlist` contains an array with the PEM certs as well as their names if you
|
|
||||||
// want to filter them.
|
|
||||||
|
|
||||||
|
|
||||||
// http://mxr.mozilla.org/mozilla-central/source/security/manager/pki/resources/content/pippki.js
|
|
||||||
function getDERString(cert)
|
|
||||||
{
|
|
||||||
var length = {};
|
|
||||||
var derArray = cert.getRawDER(length);
|
|
||||||
var derString = '';
|
|
||||||
for (var i = 0; i < derArray.length; i++) {
|
|
||||||
derString += String.fromCharCode(derArray[i]);
|
|
||||||
}
|
|
||||||
return derString;
|
|
||||||
}
|
|
||||||
|
|
||||||
// http://mxr.mozilla.org/mozilla-central/source/security/manager/pki/resources/content/pippki.js
|
|
||||||
function getPEMString(cert)
|
|
||||||
{
|
|
||||||
var derb64 = btoa(getDERString(cert));
|
|
||||||
// Wrap the Base64 string into lines of 64 characters,
|
|
||||||
// with CRLF line breaks (as specified in RFC 1421).
|
|
||||||
var wrapped = derb64.replace(/(\S{64}(?!$))/g, "$1\r\n");
|
|
||||||
return "-----BEGIN CERTIFICATE-----\r\n"
|
|
||||||
+ wrapped
|
|
||||||
+ "\r\n-----END CERTIFICATE-----\r\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
let certdb = Components.classes["@mozilla.org/security/x509certdb;1"].createInstance(Ci.nsIX509CertDB);
|
|
||||||
let enumerator = certdb.getCerts().getEnumerator();
|
|
||||||
let certlist = [];
|
|
||||||
let certstring="";
|
|
||||||
while(enumerator.hasMoreElements()){
|
|
||||||
let cert = enumerator.getNext().QueryInterface(Ci.nsIX509Cert);
|
|
||||||
let pem = getPEMString(cert);
|
|
||||||
let trusted = certdb.isCertTrusted(cert, Ci.nsIX509Cert.CA_CERT, Ci.nsIX509CertDB.TRUSTED_SSL);
|
|
||||||
certlist.push({name: cert.commonName, pem: pem, trusted: trusted});
|
|
||||||
if (trusted) {
|
|
||||||
certstring+=pem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function save(path) {
|
|
||||||
// https://developer.mozilla.org/en-US/Add-ons/Code_snippets/File_I_O
|
|
||||||
Components.utils.import("resource://gre/modules/FileUtils.jsm");
|
|
||||||
var file = new FileUtils.File(path);
|
|
||||||
Components.utils.import("resource://gre/modules/NetUtil.jsm");
|
|
||||||
|
|
||||||
// file is nsIFile, data is a string
|
|
||||||
|
|
||||||
// You can also optionally pass a flags parameter here. It defaults to
|
|
||||||
// FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE | FileUtils.MODE_TRUNCATE;
|
|
||||||
var ostream = FileUtils.openSafeFileOutputStream(file);
|
|
||||||
|
|
||||||
var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"].
|
|
||||||
createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
|
|
||||||
converter.charset = "UTF-8";
|
|
||||||
var istream = converter.convertToInputStream(certstring);
|
|
||||||
|
|
||||||
// The last argument (the callback) is optional.
|
|
||||||
NetUtil.asyncCopy(istream, ostream, function(status) {
|
|
||||||
if (!Components.isSuccessCode(status)) {
|
|
||||||
// Handle error!
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Data has been written to the file.
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
set -o errexit
|
|
||||||
set -o nounset
|
|
||||||
set -o pipefail
|
|
||||||
|
|
||||||
# https://wiki.mozilla.org/CA/Included_Certificates
|
|
||||||
# 1. Mozilla's official CA database CSV file is downloaded with curl
|
|
||||||
# and processed with awk.
|
|
||||||
# 2. Rows end with `"\n`.
|
|
||||||
# 3. Each row is split by ^" and "," into columns.
|
|
||||||
# 4. Single and double quotes are removed from column 32.
|
|
||||||
# 5. If column 13 (12 in the csv file) contains `Websites`
|
|
||||||
# (some are Email-only), column 32 is printed, the raw certificate.
|
|
||||||
# 6. All CA certs trusted for Websites are stored into the `certs` file.
|
|
||||||
|
|
||||||
url="https://ccadb-public.secure.force.com/mozilla/IncludedCACertificateReportPEMCSV"
|
|
||||||
curl "${url}" -sSf | gawk -v RS="\"\n" -F'","|^"' \
|
|
||||||
'{gsub("\047","",$(32));gsub("\"","",$(32));if($(13)~/Websites/)print $(32)}' \
|
|
||||||
> ../resources/certs
|
|
|
@ -188,15 +188,10 @@ class MachCommands(CommandBase):
|
||||||
)
|
)
|
||||||
assert os.path.exists(servo_exe_dir)
|
assert os.path.exists(servo_exe_dir)
|
||||||
|
|
||||||
# on msvc, we need to copy in some DLLs in to the servo.exe dir and the directory for unit tests.
|
|
||||||
for ssl_lib in ["libssl.dll", "libcrypto.dll"]:
|
|
||||||
ssl_path = path.join(env['OPENSSL_LIB_DIR'], "../bin", ssl_lib)
|
|
||||||
shutil.copy(ssl_path, servo_exe_dir)
|
|
||||||
shutil.copy(ssl_path, path.join(servo_exe_dir, "deps"))
|
|
||||||
|
|
||||||
build_path = path.join(servo_exe_dir, "build")
|
build_path = path.join(servo_exe_dir, "build")
|
||||||
assert os.path.exists(build_path)
|
assert os.path.exists(build_path)
|
||||||
|
|
||||||
|
# on msvc, we need to copy in some DLLs in to the servo.exe dir and the directory for unit tests.
|
||||||
def package_generated_shared_libraries(libs, build_path, servo_exe_dir):
|
def package_generated_shared_libraries(libs, build_path, servo_exe_dir):
|
||||||
for root, dirs, files in os.walk(build_path):
|
for root, dirs, files in os.walk(build_path):
|
||||||
remaining_libs = list(libs)
|
remaining_libs = list(libs)
|
||||||
|
@ -265,16 +260,6 @@ class MachCommands(CommandBase):
|
||||||
if not self.is_android_build:
|
if not self.is_android_build:
|
||||||
return
|
return
|
||||||
|
|
||||||
openssl_dir = os.path.join(self.target_path, "native", "openssl")
|
|
||||||
if not os.path.exists(openssl_dir):
|
|
||||||
os.makedirs(openssl_dir)
|
|
||||||
shutil.copy(os.path.join(self.android_support_dir(), "openssl.makefile"), openssl_dir)
|
|
||||||
shutil.copy(os.path.join(self.android_support_dir(), "openssl.sh"), openssl_dir)
|
|
||||||
|
|
||||||
status = call(["make", "-f", "openssl.makefile"], env=env, cwd=openssl_dir)
|
|
||||||
if status:
|
|
||||||
return status
|
|
||||||
|
|
||||||
# Build the name of the package containing all GStreamer dependencies
|
# Build the name of the package containing all GStreamer dependencies
|
||||||
# according to the build target.
|
# according to the build target.
|
||||||
android_lib = self.config["android"]["lib"]
|
android_lib = self.config["android"]["lib"]
|
||||||
|
|
|
@ -500,19 +500,6 @@ class CommandBase(object):
|
||||||
env.setdefault("CC", "clang-cl.exe")
|
env.setdefault("CC", "clang-cl.exe")
|
||||||
env.setdefault("CXX", "clang-cl.exe")
|
env.setdefault("CXX", "clang-cl.exe")
|
||||||
|
|
||||||
arch = effective_target.split('-')[0]
|
|
||||||
vcpkg_arch = {
|
|
||||||
"x86_64": "x64-windows",
|
|
||||||
"i686": "x86-windows",
|
|
||||||
"aarch64": "arm64-windows",
|
|
||||||
}
|
|
||||||
target_arch = vcpkg_arch[arch]
|
|
||||||
openssl_base_dir = path.join(self.msvc_package_dir("openssl"), target_arch)
|
|
||||||
|
|
||||||
# Link openssl
|
|
||||||
env["OPENSSL_INCLUDE_DIR"] = path.join(openssl_base_dir, "include")
|
|
||||||
env["OPENSSL_LIB_DIR"] = path.join(openssl_base_dir, "lib")
|
|
||||||
env["OPENSSL_LIBS"] = "libssl:libcrypto"
|
|
||||||
# Link moztools, used for building SpiderMonkey
|
# Link moztools, used for building SpiderMonkey
|
||||||
moztools_paths = [
|
moztools_paths = [
|
||||||
path.join(self.msvc_package_dir("moztools"), "bin"),
|
path.join(self.msvc_package_dir("moztools"), "bin"),
|
||||||
|
@ -625,9 +612,6 @@ class CommandBase(object):
|
||||||
android_lib = self.config["android"]["lib"]
|
android_lib = self.config["android"]["lib"]
|
||||||
android_arch = self.config["android"]["arch"]
|
android_arch = self.config["android"]["arch"]
|
||||||
|
|
||||||
# Build OpenSSL for android
|
|
||||||
env["OPENSSL_VERSION"] = "1.1.1d"
|
|
||||||
|
|
||||||
# Check if the NDK version is 15
|
# Check if the NDK version is 15
|
||||||
if not os.path.isfile(path.join(env["ANDROID_NDK"], 'source.properties')):
|
if not os.path.isfile(path.join(env["ANDROID_NDK"], 'source.properties')):
|
||||||
print("ANDROID_NDK should have file `source.properties`.")
|
print("ANDROID_NDK should have file `source.properties`.")
|
||||||
|
@ -639,11 +623,6 @@ class CommandBase(object):
|
||||||
print("Currently only support NDK 15. Please re-run `./mach bootstrap-android`.")
|
print("Currently only support NDK 15. Please re-run `./mach bootstrap-android`.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
openssl_dir = path.join(
|
|
||||||
self.target_path, "native", "openssl", "openssl-{}".format(env["OPENSSL_VERSION"]))
|
|
||||||
env['OPENSSL_LIB_DIR'] = openssl_dir
|
|
||||||
env['OPENSSL_INCLUDE_DIR'] = path.join(openssl_dir, "include")
|
|
||||||
env['OPENSSL_STATIC'] = 'TRUE'
|
|
||||||
# Android builds also require having the gcc bits on the PATH and various INCLUDE
|
# Android builds also require having the gcc bits on the PATH and various INCLUDE
|
||||||
# path munging if you do not want to install a standalone NDK. See:
|
# path munging if you do not want to install a standalone NDK. See:
|
||||||
# https://dxr.mozilla.org/mozilla-central/source/build/autoconf/android.m4#139-161
|
# https://dxr.mozilla.org/mozilla-central/source/build/autoconf/android.m4#139-161
|
||||||
|
|
|
@ -19,8 +19,7 @@ from .base import Base
|
||||||
# Please keep these in sync with the packages in README.md
|
# Please keep these in sync with the packages in README.md
|
||||||
APT_PKGS = ['git', 'curl', 'autoconf', 'libx11-dev', 'libfreetype6-dev',
|
APT_PKGS = ['git', 'curl', 'autoconf', 'libx11-dev', 'libfreetype6-dev',
|
||||||
'libgl1-mesa-dri', 'libglib2.0-dev', 'xorg-dev', 'gperf', 'g++',
|
'libgl1-mesa-dri', 'libglib2.0-dev', 'xorg-dev', 'gperf', 'g++',
|
||||||
'build-essential', 'cmake', 'libssl-dev',
|
'build-essential', 'cmake', 'liblzma-dev', 'libxmu6', 'libxmu-dev',
|
||||||
'liblzma-dev', 'libxmu6', 'libxmu-dev',
|
|
||||||
"libxcb-render0-dev", "libxcb-shape0-dev", "libxcb-xfixes0-dev",
|
"libxcb-render0-dev", "libxcb-shape0-dev", "libxcb-xfixes0-dev",
|
||||||
'libgles2-mesa-dev', 'libegl1-mesa-dev', 'libdbus-1-dev',
|
'libgles2-mesa-dev', 'libegl1-mesa-dev', 'libdbus-1-dev',
|
||||||
'libharfbuzz-dev', 'ccache', 'clang', 'libunwind-dev',
|
'libharfbuzz-dev', 'ccache', 'clang', 'libunwind-dev',
|
||||||
|
@ -31,8 +30,7 @@ DNF_PKGS = ['libtool', 'gcc-c++', 'libXi-devel', 'freetype-devel',
|
||||||
'libunwind-devel', 'mesa-libGL-devel', 'mesa-libEGL-devel',
|
'libunwind-devel', 'mesa-libGL-devel', 'mesa-libEGL-devel',
|
||||||
'glib2-devel', 'libX11-devel', 'libXrandr-devel', 'gperf',
|
'glib2-devel', 'libX11-devel', 'libXrandr-devel', 'gperf',
|
||||||
'fontconfig-devel', 'cabextract', 'ttmkfdir', 'expat-devel',
|
'fontconfig-devel', 'cabextract', 'ttmkfdir', 'expat-devel',
|
||||||
'rpm-build', 'openssl-devel', 'cmake',
|
'rpm-build', 'cmake', 'libXcursor-devel', 'libXmu-devel',
|
||||||
'libXcursor-devel', 'libXmu-devel',
|
|
||||||
'dbus-devel', 'ncurses-devel', 'harfbuzz-devel', 'ccache',
|
'dbus-devel', 'ncurses-devel', 'harfbuzz-devel', 'ccache',
|
||||||
'clang', 'clang-libs', 'llvm', 'autoconf213', 'python3-devel',
|
'clang', 'clang-libs', 'llvm', 'autoconf213', 'python3-devel',
|
||||||
'gstreamer1-devel', 'gstreamer1-plugins-base-devel',
|
'gstreamer1-devel', 'gstreamer1-plugins-base-devel',
|
||||||
|
|
|
@ -21,7 +21,6 @@ DEPS_URL = "https://github.com/servo/servo-build-deps/releases/download/msvc-dep
|
||||||
DEPENDENCIES = {
|
DEPENDENCIES = {
|
||||||
"llvm": "15.0.5",
|
"llvm": "15.0.5",
|
||||||
"moztools": "3.2",
|
"moztools": "3.2",
|
||||||
"openssl": "111.3.0+1.1.1c-vs2017-2019-09-18",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
URL_BASE = "https://gstreamer.freedesktop.org/data/pkg/windows/1.16.0/"
|
URL_BASE = "https://gstreamer.freedesktop.org/data/pkg/windows/1.16.0/"
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<p>${reason}</p>
|
<p>${reason}</p>
|
||||||
<button id="leave" onclick="history.back()">Go back (recommended)</button>
|
<button id="leave" onclick="history.back()">Go back (recommended)</button>
|
||||||
<button id="allow">Allow certificate temporarily</button>
|
<button id="allow">Allow certificate temporarily</button>
|
||||||
<pre id="bytes">${bytes}</pre>
|
<div style="word-break: break-all; font-family: monospace" id="bytes">${bytes}</div>
|
||||||
<script>
|
<script>
|
||||||
let bytes = document.getElementById('bytes').textContent;
|
let bytes = document.getElementById('bytes').textContent;
|
||||||
let button = document.getElementById('allow');
|
let button = document.getElementById('allow');
|
||||||
|
@ -18,7 +18,7 @@
|
||||||
xhr.onloadend = function() {
|
xhr.onloadend = function() {
|
||||||
location.reload(true);
|
location.reload(true);
|
||||||
};
|
};
|
||||||
xhr.send("${secret}&" + btoa(bytes));
|
xhr.send("${secret}&${bytes}");
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
button.style.display = "none";
|
button.style.display = "none";
|
||||||
|
|
3501
resources/certs
3501
resources/certs
File diff suppressed because it is too large
Load diff
|
@ -48,6 +48,12 @@ packages = [
|
||||||
"wayland-sys",
|
"wayland-sys",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
|
|
||||||
|
# Duplicated by rustls and image.
|
||||||
|
"spin",
|
||||||
|
|
||||||
|
# Duplicated by rustls and the version of webpki-roots required by async_tungstenite.
|
||||||
|
"rustls-webpki",
|
||||||
|
|
||||||
# https://github.com/servo/servo/issues/26933
|
# https://github.com/servo/servo/issues/26933
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures",
|
"futures",
|
||||||
|
@ -112,7 +118,6 @@ files = [
|
||||||
# Long encoded string
|
# Long encoded string
|
||||||
"./tests/wpt/mozilla/tests/mozilla/resources/brotli.py",
|
"./tests/wpt/mozilla/tests/mozilla/resources/brotli.py",
|
||||||
"./tests/wpt/webgl/meta/MANIFEST.json",
|
"./tests/wpt/webgl/meta/MANIFEST.json",
|
||||||
"./support/android/openssl.sh",
|
|
||||||
# Upstream code from Khronos/WebGL uses tabs for indentation
|
# Upstream code from Khronos/WebGL uses tabs for indentation
|
||||||
"./tests/wpt/webgl/tests",
|
"./tests/wpt/webgl/tests",
|
||||||
# Vendored from upstream
|
# Vendored from upstream
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
.PHONY: all
|
|
||||||
all: openssl
|
|
||||||
@: # No-op to silence the "make: Nothing to be done for 'all'." message.
|
|
||||||
|
|
||||||
# From https://wiki.openssl.org/index.php/Android
|
|
||||||
.PHONY: openssl
|
|
||||||
openssl: openssl-${OPENSSL_VERSION}/libssl.so
|
|
||||||
|
|
||||||
openssl-${OPENSSL_VERSION}/libssl.so: openssl-${OPENSSL_VERSION}/Configure
|
|
||||||
./openssl.sh ${ANDROID_NDK} ${OPENSSL_VERSION}
|
|
||||||
|
|
||||||
openssl-${OPENSSL_VERSION}/Configure:
|
|
||||||
URL=https://servo-deps-2.s3.amazonaws.com/android-deps/openssl-${OPENSSL_VERSION}.tar.gz; \
|
|
||||||
curl $$URL | tar xzf -
|
|
|
@ -1,246 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
# Cross-compile environment for Android on ARMv7 and x86
|
|
||||||
#
|
|
||||||
# Contents licensed under the terms of the OpenSSL license
|
|
||||||
# http://www.openssl.org/source/license.html
|
|
||||||
#
|
|
||||||
# See http://wiki.openssl.org/index.php/FIPS_Library_and_Android
|
|
||||||
# and http://wiki.openssl.org/index.php/Android
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
|
|
||||||
# Set ANDROID_NDK_ROOT to you NDK location. For example,
|
|
||||||
# /opt/android-ndk-r8e or /opt/android-ndk-r9. This can be done in a
|
|
||||||
# login script. If ANDROID_NDK_ROOT is not specified, the script will
|
|
||||||
# try to pick it up with the value of _ANDROID_NDK_ROOT below. If
|
|
||||||
# ANDROID_NDK_ROOT is set, then the value is ignored.
|
|
||||||
# _ANDROID_NDK="android-ndk-r8e"
|
|
||||||
_ANDROID_NDK="android-ndk-r9"
|
|
||||||
# _ANDROID_NDK="android-ndk-r10"
|
|
||||||
|
|
||||||
# Set _ANDROID_EABI to the EABI you want to use. You can find the
|
|
||||||
# list in $ANDROID_NDK_ROOT/toolchains. This value is always used.
|
|
||||||
# _ANDROID_EABI="x86-4.6"
|
|
||||||
# _ANDROID_EABI="arm-linux-androideabi-4.6"
|
|
||||||
|
|
||||||
# Set _ANDROID_ARCH to the architecture you are building for.
|
|
||||||
# This value is always used.
|
|
||||||
# _ANDROID_ARCH=arch-x86
|
|
||||||
|
|
||||||
|
|
||||||
case $RUST_TARGET in
|
|
||||||
armv7*)
|
|
||||||
_ANDROID_TARGET="arm-linux-androideabi"
|
|
||||||
_ANDROID_ARCH="arch-arm"
|
|
||||||
_ANDROID_GCC="arm-linux-androideabi"
|
|
||||||
_OPENSSL_MACHINE="armv7"
|
|
||||||
_OPENSSL_ARCH="arm"
|
|
||||||
_OPENSSL_CONFIG="linux-generic32"
|
|
||||||
;;
|
|
||||||
arm*)
|
|
||||||
_ANDROID_TARGET=$RUST_TARGET
|
|
||||||
_ANDROID_ARCH="arch-arm"
|
|
||||||
_ANDROID_GCC="arm-linux-androideabi"
|
|
||||||
_OPENSSL_MACHINE="arm"
|
|
||||||
_OPENSSL_ARCH="arm"
|
|
||||||
_OPENSSL_CONFIG="linux-generic32"
|
|
||||||
;;
|
|
||||||
aarch64*)
|
|
||||||
_ANDROID_TARGET=$RUST_TARGET
|
|
||||||
_ANDROID_ARCH="arch-arm64"
|
|
||||||
_ANDROID_GCC="aarch64-linux-android"
|
|
||||||
_OPENSSL_MACHINE="armv7"
|
|
||||||
_OPENSSL_ARCH="arm64"
|
|
||||||
_OPENSSL_CONFIG="linux-generic64 -DB_ENDIAN"
|
|
||||||
;;
|
|
||||||
x86* | i686*)
|
|
||||||
_ANDROID_TARGET=$RUST_TARGET
|
|
||||||
_ANDROID_ARCH="arch-x86"
|
|
||||||
_ANDROID_GCC="x86"
|
|
||||||
_OPENSSL_MACHINE="x86"
|
|
||||||
_OPENSSL_ARCH="x86"
|
|
||||||
_OPENSSL_CONFIG="linux-generic32"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Error: Invalid TARGET platform: $RUST_TARGET"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
_ANDROID_EABI="llvm"
|
|
||||||
|
|
||||||
|
|
||||||
# Set _ANDROID_API to the API you want to use. You should set it
|
|
||||||
# to one of: android-14, android-9, android-8, android-14, android-5
|
|
||||||
# android-4, or android-3. You can't set it to the latest (for
|
|
||||||
# example, API-17) because the NDK does not supply the platform. At
|
|
||||||
# Android 5.0, there will likely be another platform added (android-22?).
|
|
||||||
# This value is always used.
|
|
||||||
# _ANDROID_API="android-14"
|
|
||||||
_ANDROID_API="$ANDROID_PLATFORM"
|
|
||||||
# _ANDROID_API="android-19"
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
|
|
||||||
# If the user did not specify the NDK location, try and pick it up.
|
|
||||||
# We expect something like ANDROID_NDK_ROOT=/opt/android-ndk-r8e
|
|
||||||
# or ANDROID_NDK_ROOT=/usr/local/android-ndk-r8e.
|
|
||||||
export ANDROID_NDK_ROOT=$1
|
|
||||||
echo $ANDROID_NDK_ROOT
|
|
||||||
# Error checking
|
|
||||||
# ANDROID_NDK_ROOT should always be set by the user (even when not running this script)
|
|
||||||
# http://groups.google.com/group/android-ndk/browse_thread/thread/a998e139aca71d77
|
|
||||||
if [ -z "$ANDROID_NDK_ROOT" ] || [ ! -d "$ANDROID_NDK_ROOT" ]; then
|
|
||||||
echo "Error: ANDROID_NDK_ROOT is not a valid path. Please edit this script."
|
|
||||||
echo "$ANDROID_NDK_ROOT"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Error checking
|
|
||||||
if [ ! -d "$ANDROID_NDK_ROOT/toolchains" ]; then
|
|
||||||
echo "Error: ANDROID_NDK_ROOT/toolchains is not a valid path. Please edit this script."
|
|
||||||
echo "$ANDROID_NDK_ROOT/toolchains"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Error checking
|
|
||||||
if [ ! -d "$ANDROID_NDK_ROOT/toolchains/$_ANDROID_EABI" ]; then
|
|
||||||
echo "Error: ANDROID_EABI is not a valid path. Please edit this script."
|
|
||||||
echo "$ANDROID_NDK_ROOT/toolchains/$_ANDROID_EABI"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
|
|
||||||
# Based on ANDROID_NDK_ROOT, try and pick up the required toolchain. We expect something like:
|
|
||||||
# /opt/android-ndk-r83/toolchains/arm-linux-androideabi-4.7/prebuilt/linux-x86_64/bin
|
|
||||||
# Once we locate the toolchain, we add it to the PATH. Note: this is the 'hard way' of
|
|
||||||
# doing things according to the NDK documentation for Ice Cream Sandwich.
|
|
||||||
# https://android.googlesource.com/platform/ndk/+/ics-mr0/docs/STANDALONE-TOOLCHAIN.html
|
|
||||||
|
|
||||||
ANDROID_TOOLCHAIN=""
|
|
||||||
ANDROID_GCC_TOOLCHAIN=""
|
|
||||||
for host in "linux-x86_64" "linux-x86" "darwin-x86_64" "darwin-x86"
|
|
||||||
do
|
|
||||||
if [ -d "$ANDROID_NDK_ROOT/toolchains/$_ANDROID_EABI/prebuilt/$host/bin" ]; then
|
|
||||||
ANDROID_TOOLCHAIN="$ANDROID_NDK_ROOT/toolchains/$_ANDROID_EABI/prebuilt/$host/bin"
|
|
||||||
ANDROID_GCC_TOOLCHAIN="$ANDROID_NDK_ROOT/toolchains/$_ANDROID_GCC-4.9/prebuilt/$host/$_ANDROID_TARGET/bin"
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# Error checking
|
|
||||||
if [ -z "$ANDROID_TOOLCHAIN" ] || [ ! -d "$ANDROID_TOOLCHAIN" ]; then
|
|
||||||
echo "Error: ANDROID_TOOLCHAIN is not valid. Please edit this script."
|
|
||||||
echo "$ANDROID_TOOLCHAIN"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
ANDROID_TOOLS="clang"
|
|
||||||
|
|
||||||
for tool in $ANDROID_TOOLS
|
|
||||||
do
|
|
||||||
# Error checking
|
|
||||||
if [ ! -e "$ANDROID_TOOLCHAIN/$tool" ]; then
|
|
||||||
echo "Error: Failed to find $tool. Please edit this script."
|
|
||||||
echo "$ANDROID_TOOLCHAIN/$tool"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
GCC_TOOLS="ar ranlib ld"
|
|
||||||
|
|
||||||
for tool in $GCC_TOOLS
|
|
||||||
do
|
|
||||||
# Error checking
|
|
||||||
if [ ! -e "$ANDROID_GCC_TOOLCHAIN/$tool" ]; then
|
|
||||||
echo "Error: Failed to find $tool. Please edit this script."
|
|
||||||
echo "$ANDROID_GCC_TOOLCHAIN/$tool"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# Only modify/export PATH if ANDROID_TOOLCHAIN good
|
|
||||||
if [ ! -z "$ANDROID_TOOLCHAIN" ]; then
|
|
||||||
export ANDROID_TOOLCHAIN="$ANDROID_TOOLCHAIN"
|
|
||||||
export PATH="$ANDROID_TOOLCHAIN":"$ANDROID_GCC_TOOLCHAIN":"$PATH"
|
|
||||||
fi
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
|
|
||||||
# For the Android SYSROOT. Can be used on the command line with --sysroot
|
|
||||||
# https://android.googlesource.com/platform/ndk/+/ics-mr0/docs/STANDALONE-TOOLCHAIN.html
|
|
||||||
export ANDROID_SYSROOT="$ANDROID_NDK_ROOT/sysroot"
|
|
||||||
export SYSROOT="$ANDROID_SYSROOT"
|
|
||||||
export NDK_SYSROOT="$ANDROID_SYSROOT"
|
|
||||||
|
|
||||||
# Error checking
|
|
||||||
if [ -z "$ANDROID_SYSROOT" ] || [ ! -d "$ANDROID_SYSROOT" ]; then
|
|
||||||
echo "Error: ANDROID_SYSROOT is not valid. Please edit this script."
|
|
||||||
echo "$ANDROID_SYSROOT"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
|
|
||||||
# Most of these should be OK (MACHINE, SYSTEM, ARCH). RELEASE is ignored.
|
|
||||||
export MACHINE=$_OPENSSL_MACHINE
|
|
||||||
export RELEASE=2.6.37
|
|
||||||
export SYSTEM=android
|
|
||||||
export ARCH=$_OPENSSL_ARCH
|
|
||||||
#export CROSS_COMPILE="$_ANDROID_TARGET-"
|
|
||||||
|
|
||||||
# For the Android toolchain
|
|
||||||
# https://android.googlesource.com/platform/ndk/+/ics-mr0/docs/STANDALONE-TOOLCHAIN.html
|
|
||||||
export SYSROOT="$ANDROID_SYSROOT"
|
|
||||||
#export CROSS_SYSROOT="$ANDROID_SYSROOT"
|
|
||||||
export NDK_SYSROOT="$ANDROID_SYSROOT"
|
|
||||||
export ANDROID_NDK_SYSROOT="$ANDROID_SYSROOT"
|
|
||||||
export ANDROID_API="$_ANDROID_API"
|
|
||||||
|
|
||||||
# CROSS_COMPILE and ANDROID_DEV are DFW (Don't Fiddle With). Its used by OpenSSL build system.
|
|
||||||
# export CROSS_COMPILE="arm-linux-androideabi-"
|
|
||||||
export ANDROID_DEV="$ANDROID_NDK_ROOT/platforms/$_ANDROID_API/$_ANDROID_ARCH/usr"
|
|
||||||
export HOSTCC=gcc
|
|
||||||
export CC=clang
|
|
||||||
export RANLIB="$ANDROID_GCC_TOOLCHAIN/ranlib"
|
|
||||||
export AR="$ANDROID_GCC_TOOLCHAIN/ar"
|
|
||||||
export LD="$ANDROID_GCC_TOOLCHAIN/ld"
|
|
||||||
|
|
||||||
# See https://github.com/cocochpie/android-openssl/blob/master/build-all-arch.sh
|
|
||||||
#+xCFLAGS="-DSHARED_EXTENSION=.so -fPIC -DOPENSSL_PIC -DDSO_DLFCN -DHAVE_DLFCN_H -B$ANDROID_DEV/lib -O3 -fomit-frame-pointer -Wall -D__ANDROID_API__=18 --target=armv7a-none-linux-androideabi --gcc-toolchain=$ANDROID_NDK_ROOT/toolchains/$_ANDROID_TARGET-4.9/prebuilt/$host --sysroot=$ANDROID_SYSROOT -I$ANDROID_DEV/include -I$ANDROID_DEV/include/$_ANDROID_TARGET -L$ANDROID_NDK_ROOT/platforms/$_ANDROID_API/$_ANDROID_ARCH/usr/lib -B$ANDROID_NDK_ROOT/platforms/$_ANDROID_API/$_ANDROID_ARCH/usr/lib"
|
|
||||||
|
|
||||||
xCFLAGS="-DSHARED_EXTENSION=.so -DOPENSSL_PIC -DDSO_DLFCN -DHAVE_DLFCN_H \
|
|
||||||
-fPIC -fomit-frame-pointer \
|
|
||||||
-Wall -Wno-error=macro-redefined \
|
|
||||||
-O3 \
|
|
||||||
-I$ANDROID_SYSROOT/usr/include/$_ANDROID_TARGET \
|
|
||||||
-I$ANDROID_DEV/include \
|
|
||||||
-B$ANDROID_DEV/lib -B$ANDROID_NDK_ROOT/platforms/$_ANDROID_API/$_ANDROID_ARCH/usr/lib \
|
|
||||||
-L$ANDROID_NDK_ROOT/platforms/$_ANDROID_API/$_ANDROID_ARCH/usr/lib -L$ANDROID_NDK_ROOT/toolchains/$_ANDROID_GCC-4.9/prebuilt/$host/lib/gcc/$_ANDROID_TARGET/4.9.x/ \
|
|
||||||
--gcc-toolchain=$ANDROID_GCC_TOOLCHAIN \
|
|
||||||
--sysroot=$ANDROID_SYSROOT \
|
|
||||||
--target=$RUST_TARGET"
|
|
||||||
|
|
||||||
VERBOSE=1
|
|
||||||
if [ ! -z "$VERBOSE" ] && [ "$VERBOSE" != "0" ]; then
|
|
||||||
echo "ANDROID_NDK_ROOT: $ANDROID_NDK_ROOT"
|
|
||||||
echo "ANDROID_ARCH: $_ANDROID_ARCH"
|
|
||||||
echo "ANDROID_EABI: $_ANDROID_EABI"
|
|
||||||
echo "ANDROID_API: $ANDROID_API"
|
|
||||||
echo "ANDROID_SYSROOT: $ANDROID_SYSROOT"
|
|
||||||
echo "ANDROID_TOOLCHAIN: $ANDROID_TOOLCHAIN"
|
|
||||||
echo "FIPS_SIG: $FIPS_SIG"
|
|
||||||
echo "CROSS_COMPILE: $CROSS_COMPILE"
|
|
||||||
echo "ANDROID_DEV: $ANDROID_DEV"
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd openssl-$2
|
|
||||||
perl -pi -e 's/install: all install_docs install_sw/install: install_docs install_sw/g' Makefile.org
|
|
||||||
|
|
||||||
# The code being built isn't maintained by us, so we redirect stderr to stdout
|
|
||||||
# so that the warnings don't clutter up buildbot
|
|
||||||
./Configure shared -no-ssl2 -no-ssl3 -no-comp -no-hw -no-engine --openssldir=/usr/local/ssl/$ANDROID_API $_OPENSSL_CONFIG $xCFLAGS 2>&1
|
|
||||||
make depend 2>&1
|
|
||||||
make all 2>&1
|
|
|
@ -464480,7 +464480,7 @@
|
||||||
[]
|
[]
|
||||||
],
|
],
|
||||||
"executorservo.py": [
|
"executorservo.py": [
|
||||||
"89aaf00352f4142a311bb34c1d8dd57b8ff22b0c",
|
"a8ec38699616c5baf7a3b43b8149b89746308f35",
|
||||||
[]
|
[]
|
||||||
],
|
],
|
||||||
"executorservodriver.py": [
|
"executorservodriver.py": [
|
||||||
|
|
|
@ -38,6 +38,9 @@ def build_servo_command(test, test_url_func, browser, binary, pause_after_test,
|
||||||
extra_args=None, debug_opts="replace-surrogates"):
|
extra_args=None, debug_opts="replace-surrogates"):
|
||||||
args = [
|
args = [
|
||||||
"--hard-fail", "-u", "Servo/wptrunner",
|
"--hard-fail", "-u", "Servo/wptrunner",
|
||||||
|
# See https://github.com/servo/servo/issues/30080.
|
||||||
|
# For some reason rustls does not like the certificate generated by the WPT tooling.
|
||||||
|
"--ignore-certificate-errors",
|
||||||
"-z", test_url_func(test),
|
"-z", test_url_func(test),
|
||||||
]
|
]
|
||||||
if debug_opts:
|
if debug_opts:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue