diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..a7bce3105 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.toml text eol=lf diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 77c85a4d2..ea6a151e9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,6 +28,8 @@ jobs: clippy: name: clippy runs-on: ubuntu-latest + env: + CARGO_HOME: ${{ github.workspace }}/.cache/cargo steps: - uses: actions/checkout@v4 with: @@ -36,15 +38,17 @@ jobs: run: rustup toolchain add stable --no-self-update --component clippy && rustup default stable - name: Get rust version id: rust-version + shell: bash run: | echo "version=$(rustc --version)" >> $GITHUB_OUTPUT - name: Cache cargo index uses: actions/cache@v4 with: path: | - ~/.cargo/registry/index - ~/.cargo/registry/cache + .cache/cargo/registry/index + .cache/cargo/registry/cache key: index-${{ steps.rust-version.outputs.version }}-${{ hashFiles('Cargo.toml') }} + enableCrossOsArchive: true - name: Fetch dependencies run: cargo fetch - name: Cache target directory @@ -188,15 +192,28 @@ jobs: os: windows-latest # CI's Windows doesn't have required root certs extra_test_args: --workspace --exclude tokio-boring --exclude hyper-boring - + env: + CARGO_HOME: ${{ github.workspace }}/.cache/cargo steps: - uses: actions/checkout@v4 with: submodules: 'recursive' - name: Install Rust (rustup) - run: rustup update ${{ matrix.rust }} --no-self-update && rustup default ${{ matrix.rust }} + run: rustup update ${{ matrix.rust }} --no-self-update && rustup default ${{ matrix.rust }} && rustup target add ${{ matrix.target }} + shell: bash + - name: Get rust version + id: rust-version shell: bash - - run: rustup target add ${{ matrix.target }} + run: | + echo "version=$(rustc --version)" >> $GITHUB_OUTPUT + - name: Prepopulate cargo index + uses: actions/cache/restore@v4 + with: + path: | + .cache/cargo/registry/index + .cache/cargo/registry/cache + key: index-${{ steps.rust-version.outputs.version }}-${{ hashFiles('Cargo.toml') }} + enableCrossOsArchive: true - name: Install golang uses: actions/setup-go@v5 with: @@ -221,17 +238,6 @@ jobs: - name: Set Android Linker path if: endsWith(matrix.thing, '-android') run: echo "CARGO_TARGET_$(echo ${{ matrix.target }} | tr \\-a-z _A-Z)_LINKER=$ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/$(echo ${{ matrix.target }} | sed s/armv7/armv7a/)21-clang++" >> "$GITHUB_ENV" - - name: Get rust version - id: rust-version - run: | - echo "version=$(rustc --version)" >> $GITHUB_OUTPUT - - name: Prepopulate cargo index - uses: actions/cache/restore@v4 - with: - path: | - ~/.cargo/registry/index - ~/.cargo/registry/cache - key: index-${{ steps.rust-version.outputs.version }}-${{ hashFiles('Cargo.toml') }} - name: Build tests # We `build` because we want the linker to verify we are cross-compiling correctly for check-only targets. run: cargo build --target ${{ matrix.target }} --tests ${{ matrix.extra_test_args }} diff --git a/boring-sys/build/main.rs b/boring-sys/build/main.rs index 798d5984b..d4e3b90dd 100644 --- a/boring-sys/build/main.rs +++ b/boring-sys/build/main.rs @@ -654,15 +654,15 @@ fn generate_bindings(config: &Config) { .clang_arg("--sysroot") .clang_arg(sysroot.display().to_string()); - let c_target = format!( - "{}-{}-{}", - &config.target_arch, &config.target_os, &config.target_env - ); - // we need to add special platform header file with env for support cross building - let header = format!("{}/usr/include/{}", sysroot.display(), c_target); - if PathBuf::from(&header).is_dir() { - builder = builder.clang_arg("-I").clang_arg(&header); + let target_include_dir = sysroot.join(format!( + "usr/include/{}-{}-{}", + config.target_arch, config.target_os, config.target_env + )); + if target_include_dir.is_dir() { + builder = builder + .clang_arg("-I") + .clang_arg(target_include_dir.display().to_string()); } } @@ -717,7 +717,7 @@ fn ensure_err_lib_enum_is_named(source_code: &mut Vec) { let src = String::from_utf8_lossy(source_code); let enum_type = src .split_once("ERR_LIB_SSL:") - .and_then(|(_, def)| Some(def.split_once("=")?.0)) + .and_then(|(_, def)| Some(def.split_once('=')?.0)) .unwrap_or("_bindgen_ty_1"); source_code.extend_from_slice( diff --git a/boring/src/dsa.rs b/boring/src/dsa.rs index be13da9fa..ca7efaf32 100644 --- a/boring/src/dsa.rs +++ b/boring/src/dsa.rs @@ -300,7 +300,7 @@ mod test { let mut ctx = BigNumContext::new().unwrap(); let mut calc = BigNum::new().unwrap(); calc.mod_exp(g, priv_key, p, &mut ctx).unwrap(); - assert_eq!(&calc, pub_key) + assert_eq!(&calc, pub_key); } #[test] diff --git a/boring/src/ssl/error.rs b/boring/src/ssl/error.rs index 5acad8200..ba5a333b9 100644 --- a/boring/src/ssl/error.rs +++ b/boring/src/ssl/error.rs @@ -79,6 +79,7 @@ impl ErrorCode { } #[corresponds(SSL_error_description)] + #[must_use] pub fn description(self) -> Option<&'static str> { unsafe { let msg = ffi::SSL_error_description(self.0); diff --git a/boring/src/ssl/mod.rs b/boring/src/ssl/mod.rs index 1f2026504..8e7d03c30 100644 --- a/boring/src/ssl/mod.rs +++ b/boring/src/ssl/mod.rs @@ -1686,7 +1686,7 @@ impl SslContextBuilder { C: CertificateCompressor, { const { - assert!(C::CAN_COMPRESS || C::CAN_DECOMPRESS, "Either compression or decompression must be supported for algorithm to be registered") + assert!(C::CAN_COMPRESS || C::CAN_DECOMPRESS, "Either compression or decompression must be supported for algorithm to be registered"); }; let success = unsafe { ffi::SSL_CTX_add_cert_compression_alg( @@ -1733,7 +1733,7 @@ impl SslContextBuilder { decrypt: Some(callbacks::raw_decrypt::), complete: Some(callbacks::raw_complete::), }, - ) + ); } } diff --git a/boring/src/ssl/test/ech.rs b/boring/src/ssl/test/ech.rs index d2797d427..db4d43149 100644 --- a/boring/src/ssl/test/ech.rs +++ b/boring/src/ssl/test/ech.rs @@ -40,7 +40,7 @@ fn ech() { let (_server, client) = bootstrap_ech(ECH_CONFIG, ECH_KEY, ECH_CONFIG_LIST); let ssl_stream = client.connect(); - assert!(ssl_stream.ssl().ech_accepted()) + assert!(ssl_stream.ssl().ech_accepted()); } #[test] @@ -57,7 +57,7 @@ fn ech_rejection() { Some(b"ech.com".to_vec().as_ref()) ); assert!(failed_ssl_stream.ssl().get_ech_retry_configs().is_some()); - assert!(!failed_ssl_stream.ssl().ech_accepted()) + assert!(!failed_ssl_stream.ssl().ech_accepted()); } #[test] @@ -69,5 +69,5 @@ fn ech_grease() { client.ssl().set_enable_ech_grease(true); let ssl_stream = client.connect(); - assert!(!ssl_stream.ssl().ech_accepted()) + assert!(!ssl_stream.ssl().ech_accepted()); } diff --git a/boring/src/ssl/test/mod.rs b/boring/src/ssl/test/mod.rs index e6c61cf85..324163897 100644 --- a/boring/src/ssl/test/mod.rs +++ b/boring/src/ssl/test/mod.rs @@ -1010,7 +1010,7 @@ fn test_set_compliance() { assert_eq!(ciphers.len(), FIPS_CIPHERS.len()); for cipher in ciphers.into_iter().zip(FIPS_CIPHERS) { - assert_eq!(cipher.0.name(), cipher.1) + assert_eq!(cipher.0.name(), cipher.1); } let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); @@ -1029,7 +1029,7 @@ fn test_set_compliance() { assert_eq!(ciphers.len(), WPA3_192_CIPHERS.len()); for cipher in ciphers.into_iter().zip(WPA3_192_CIPHERS) { - assert_eq!(cipher.0.name(), cipher.1) + assert_eq!(cipher.0.name(), cipher.1); } ctx.set_compliance_policy(CompliancePolicy::NONE) @@ -1092,7 +1092,7 @@ fn test_ssl_set_compliance() { assert_eq!(ciphers.len(), FIPS_CIPHERS.len()); for cipher in ciphers.into_iter().zip(FIPS_CIPHERS) { - assert_eq!(cipher.0.name(), cipher.1) + assert_eq!(cipher.0.name(), cipher.1); } let ctx = SslContext::builder(SslMethod::tls()).unwrap().build(); @@ -1112,7 +1112,7 @@ fn test_ssl_set_compliance() { assert_eq!(ciphers.len(), WPA3_192_CIPHERS.len()); for cipher in ciphers.into_iter().zip(WPA3_192_CIPHERS) { - assert_eq!(cipher.0.name(), cipher.1) + assert_eq!(cipher.0.name(), cipher.1); } ssl.set_compliance_policy(CompliancePolicy::NONE) diff --git a/boring/src/ssl/test/session.rs b/boring/src/ssl/test/session.rs index 23c0f4d5d..97ed8c1c3 100644 --- a/boring/src/ssl/test/session.rs +++ b/boring/src/ssl/test/session.rs @@ -49,7 +49,7 @@ fn new_get_session_callback() { .ctx() .set_session_cache_mode(SslSessionCacheMode::SERVER | SslSessionCacheMode::NO_INTERNAL); server.ctx().set_new_session_callback(|_, session| { - SERVER_SESSION_DER.set(session.to_der().unwrap()).unwrap() + SERVER_SESSION_DER.set(session.to_der().unwrap()).unwrap(); }); unsafe { server.ctx().set_get_session_callback(|_, id| { @@ -76,7 +76,7 @@ fn new_get_session_callback() { .ctx() .set_session_cache_mode(SslSessionCacheMode::CLIENT); client.ctx().set_new_session_callback(|_, session| { - CLIENT_SESSION_DER.set(session.to_der().unwrap()).unwrap() + CLIENT_SESSION_DER.set(session.to_der().unwrap()).unwrap(); }); let client = client.build(); diff --git a/boring/src/ssl/test/session_resumption.rs b/boring/src/ssl/test/session_resumption.rs index 808abe304..5c65c53ce 100644 --- a/boring/src/ssl/test/session_resumption.rs +++ b/boring/src/ssl/test/session_resumption.rs @@ -61,7 +61,7 @@ fn custom_callback_success() { unsafe { server .ctx() - .set_ticket_key_callback(test_success_tickey_key_callback) + .set_ticket_key_callback(test_success_tickey_key_callback); }; let server = server.build(); @@ -106,7 +106,7 @@ fn custom_callback_unrecognized_decryption_ticket() { unsafe { server .ctx() - .set_ticket_key_callback(test_noop_tickey_key_callback) + .set_ticket_key_callback(test_noop_tickey_key_callback); }; let server = server.build(); diff --git a/boring/src/x509/tests/mod.rs b/boring/src/x509/tests/mod.rs index 371cd9b63..2a1b3fd56 100644 --- a/boring/src/x509/tests/mod.rs +++ b/boring/src/x509/tests/mod.rs @@ -73,7 +73,7 @@ fn test_subject_read_cn() { let cert = X509::from_pem(cert).unwrap(); let subject = cert.subject_name(); let cn = subject.entries_by_nid(Nid::COMMONNAME).next().unwrap(); - assert_eq!(cn.data().as_slice(), b"foobar.com") + assert_eq!(cn.data().as_slice(), b"foobar.com"); } #[test] diff --git a/boring/src/x509/tests/trusted_first.rs b/boring/src/x509/tests/trusted_first.rs index 187a49b0b..ad660a3b1 100644 --- a/boring/src/x509/tests/trusted_first.rs +++ b/boring/src/x509/tests/trusted_first.rs @@ -60,7 +60,7 @@ fn test_verify_cert() { assert_eq!( Ok(()), verify(&leaf, &[&root1], &[&intermediate, &root1_cross], |param| { - param.clear_flags(X509VerifyFlags::TRUSTED_FIRST) + param.clear_flags(X509VerifyFlags::TRUSTED_FIRST); }) ); } diff --git a/hyper-boring/src/cache.rs b/hyper-boring/src/cache.rs index 185c3dc41..ad0bddbb5 100644 --- a/hyper-boring/src/cache.rs +++ b/hyper-boring/src/cache.rs @@ -86,9 +86,8 @@ impl SessionCache { } pub fn remove(&mut self, session: &SslSessionRef) { - let key = match self.reverse.remove(session.id()) { - Some(key) => key, - None => return, + let Some(key) = self.reverse.remove(session.id()) else { + return; }; if let Entry::Occupied(mut sessions) = self.sessions.entry(key) { diff --git a/hyper-boring/src/v1.rs b/hyper-boring/src/v1.rs index f4cb0168d..38b454229 100644 --- a/hyper-boring/src/v1.rs +++ b/hyper-boring/src/v1.rs @@ -113,7 +113,7 @@ impl HttpsLayer { /// /// The session cache configuration of `ssl` will be overwritten. pub fn with_connector(ssl: SslConnectorBuilder) -> Result { - Self::with_connector_and_settings(ssl, Default::default()) + Self::with_connector_and_settings(ssl, HttpsLayerSettings::default()) } /// Creates a new `HttpsLayer` with settings @@ -243,9 +243,8 @@ where let f = async { let conn = connect.await.map_err(Into::into)?.into_inner(); - let (inner, uri) = match tls_setup { - Some((inner, uri)) => (inner, uri), - None => return Ok(MaybeHttpsStream::Http(conn)), + let Some((inner, uri)) = tls_setup else { + return Ok(MaybeHttpsStream::Http(conn)); }; let mut host = uri.host().ok_or("URI missing host")?; @@ -253,15 +252,12 @@ where // If `host` is an IPv6 address, we must strip away the square brackets that surround // it (otherwise, boring will fail to parse the host as an IP address, eventually // causing the handshake to fail due a hostname verification error). - if !host.is_empty() { - let last = host.len() - 1; - let mut chars = host.chars(); - - if let (Some('['), Some(']')) = (chars.next(), chars.last()) { - if host[1..last].parse::().is_ok() { - host = &host[1..last]; - } - } + if let Some(ipv6) = host + .strip_prefix('[') + .and_then(|h| h.strip_suffix(']')) + .filter(|h| h.parse::().is_ok()) + { + host = ipv6; } let ssl = inner.setup_ssl(&uri, host)?; diff --git a/hyper-boring/tests/v1.rs b/hyper-boring/tests/v1.rs index 4082d2cef..1965959f3 100644 --- a/hyper-boring/tests/v1.rs +++ b/hyper-boring/tests/v1.rs @@ -78,7 +78,7 @@ async fn localhost() { let file = File::create("../target/keyfile.log").unwrap(); ssl.set_keylog_callback(move |_, line| { - let _ = writeln!(&file, "{}", line); + let _ = writeln!(&file, "{line}"); }); let ssl = HttpsConnector::with_connector(connector, ssl).unwrap(); @@ -86,7 +86,7 @@ async fn localhost() { for _ in 0..3 { let resp = client - .get(format!("https://foobar.com:{}", port).parse().unwrap()) + .get(format!("https://foobar.com:{port}").parse().unwrap()) .await .unwrap(); assert!(resp.status().is_success(), "{}", resp.status()); @@ -149,7 +149,7 @@ async fn alpn_h2() { let client = Client::builder(TokioExecutor::new()).build::<_, Empty>(ssl); let resp = client - .get(format!("https://foobar.com:{}", port).parse().unwrap()) + .get(format!("https://foobar.com:{port}").parse().unwrap()) .await .unwrap(); assert!(resp.status().is_success(), "{}", resp.status()); diff --git a/tokio-boring/tests/async_get_session.rs b/tokio-boring/tests/async_get_session.rs index 0ab9b396e..177d84940 100644 --- a/tokio-boring/tests/async_get_session.rs +++ b/tokio-boring/tests/async_get_session.rs @@ -26,7 +26,7 @@ async fn test() { builder .set_session_cache_mode(SslSessionCacheMode::SERVER | SslSessionCacheMode::NO_INTERNAL); builder.set_new_session_callback(|_, session| { - SERVER_SESSION_DER.set(session.to_der().unwrap()).unwrap() + SERVER_SESSION_DER.set(session.to_der().unwrap()).unwrap(); }); unsafe { @@ -49,7 +49,7 @@ async fn test() { let connector = create_connector(|builder| { builder.set_session_cache_mode(SslSessionCacheMode::CLIENT); builder.set_new_session_callback(|_, session| { - CLIENT_SESSION_DER.set(session.to_der().unwrap()).unwrap() + CLIENT_SESSION_DER.set(session.to_der().unwrap()).unwrap(); }); builder.set_ca_file("tests/cert.pem")