diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4a47b9b..7178fc8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,10 +3,10 @@ name: CI on: pull_request: branches: - - master + - '**' push: branches: - - master + - '**' env: RUSTFLAGS: -Dwarnings @@ -18,8 +18,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - uses: sfackler/actions/rustup@master - - uses: sfackler/actions/rustfmt@master + - uses: dtolnay/rust-toolchain@stable windows: strategy: @@ -32,27 +31,56 @@ jobs: name: test-${{ matrix.os }} runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v2 - - uses: sfackler/actions/rustup@master - with: - version: 1.80.0 + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable - run: echo "::set-output name=version::$(rustc --version)" id: rust-version - - uses: actions/cache@v1 - with: - path: ~/.cargo/registry/index - key: index-${{ runner.os }}-${{ github.run_number }} - restore-keys: | - index-${{ runner.os }}- - run: cargo generate-lockfile - - uses: actions/cache@v1 - with: - path: ~/.cargo/registry/cache - key: registry-${{ runner.os }}-${{ steps.rust-version.outputs.version }}-${{ hashFiles('Cargo.lock') }} - run: cargo fetch - - uses: actions/cache@v1 - with: - path: target - key: target-${{ runner.os }}-${{ steps.rust-version.outputs.version }}-${{ hashFiles('Cargo.lock') }} - - run: cargo test --features vendored + - run: cargo fmt --check + - run: cargo clippy --all-targets -- -D warnings - run: cargo test --features vendored + + build_n_test_ios: + strategy: + fail-fast: false + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + - name: Install cargo lipo and rust compiler for ios target + if: ${{ !cancelled() }} + run: | + cargo install --locked cargo-lipo + rustup target add x86_64-apple-ios aarch64-apple-ios + - name: clippy + if: ${{ !cancelled() }} + run: cargo clippy --target x86_64-apple-ios --all-features -- -D warnings + - name: Build + if: ${{ !cancelled() }} + run: | + cargo lipo --verbose --all-features + - name: Abort on error + if: ${{ failure() }} + run: echo "iOS build job failed" && false + + build_n_test_android: + strategy: + fail-fast: false + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install cargo ndk and rust compiler for android target + if: ${{ !cancelled() }} + run: | + cargo install --locked cargo-ndk + rustup target add x86_64-linux-android + - name: clippy + if: ${{ !cancelled() }} + run: cargo ndk -t x86_64 clippy --features vendored -- -D warnings + - name: Build + if: ${{ !cancelled() }} + run: | + cargo ndk -t x86_64 rustc --verbose --features vendored --lib --crate-type=cdylib + - name: Abort on error + if: ${{ failure() }} + run: echo "Android build job failed" && false diff --git a/.gitignore b/.gitignore index 2deeb18..5b04ad2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.VSCodeCounter/ target Cargo.lock .idea diff --git a/Cargo.toml b/Cargo.toml index e6a49eb..a790c0b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,12 +12,16 @@ rust-version = "1.80.0" features = ["alpn"] rustdoc-args = ["--cfg", "docsrs"] +[lib] +crate-type = ["staticlib", "rlib"] + [features] vendored = ["openssl/vendored"] alpn = ["security-framework/alpn"] +have_min_max_version = [] [target.'cfg(target_vendor = "apple")'.dependencies] -security-framework = "2.0.0" +security-framework = "3" security-framework-sys = "2.0.0" libc = "0.2" diff --git a/src/imp/openssl.rs b/src/imp/openssl.rs index 4e096c1..bc3ab74 100644 --- a/src/imp/openssl.rs +++ b/src/imp/openssl.rs @@ -17,11 +17,11 @@ use std::fmt; use std::io; use std::sync::LazyLock; -use {Protocol, TlsAcceptorBuilder, TlsConnectorBuilder}; +use crate::{Protocol, TlsAcceptorBuilder, TlsConnectorBuilder}; static PROBE_RESULT: LazyLock = LazyLock::new(openssl_probe::probe); -#[cfg(have_min_max_version)] +#[cfg(feature = "have_min_max_version")] fn supported_protocols( min: Option, max: Option, @@ -44,7 +44,7 @@ fn supported_protocols( Ok(()) } -#[cfg(not(have_min_max_version))] +#[cfg(not(feature = "have_min_max_version"))] fn supported_protocols( min: Option, max: Option, @@ -465,9 +465,7 @@ impl TlsStream { match self.0.shutdown() { Ok(_) => Ok(()), Err(ref e) if e.code() == ssl::ErrorCode::ZERO_RETURN => Ok(()), - Err(e) => Err(e - .into_io_error() - .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e))), + Err(e) => Err(e.into_io_error().unwrap_or_else(io::Error::other)), } } } diff --git a/src/imp/schannel.rs b/src/imp/schannel.rs index 62e5042..5ba23db 100644 --- a/src/imp/schannel.rs +++ b/src/imp/schannel.rs @@ -10,18 +10,21 @@ use std::fmt; use std::io; use std::str; -use {TlsAcceptorBuilder, TlsConnectorBuilder}; +use crate::{TlsAcceptorBuilder, TlsConnectorBuilder}; const SEC_E_NO_CREDENTIALS: u32 = 0x8009030E; -static PROTOCOLS: &'static [Protocol] = &[ +static PROTOCOLS: &[Protocol] = &[ Protocol::Ssl3, Protocol::Tls10, Protocol::Tls11, Protocol::Tls12, ]; -fn convert_protocols(min: Option<::Protocol>, max: Option<::Protocol>) -> &'static [Protocol] { +fn convert_protocols( + min: Option, + max: Option, +) -> &'static [Protocol] { let mut protocols = PROTOCOLS; if let Some(p) = max.and_then(|max| protocols.get(..=max as usize)) { protocols = p; @@ -101,7 +104,7 @@ impl Identity { } let mut store = Memory::new()?.into_store(); - let mut cert_iter = pem::PemBlock::new(pem).into_iter(); + let mut cert_iter = pem::PemBlock::new(pem); let leaf = cert_iter.next().ok_or_else(|| { io::Error::new( io::ErrorKind::InvalidInput, @@ -124,7 +127,7 @@ impl Identity { Ok(container) => container, Err(_) => options.new_keyset(true).acquire(type_)?, }; - container.import().import_pkcs8_pem(&key)?; + container.import().import_pkcs8_pem(key)?; cert.set_key_prov_info() .container(&name) @@ -202,6 +205,7 @@ impl MidHandshakeTlsStream where S: io::Read + io::Write, { + #[allow(clippy::result_large_err)] pub fn handshake(self) -> Result, HandshakeError> { match self.0.handshake() { Ok(s) => Ok(TlsStream(s)), @@ -210,6 +214,7 @@ where } } +#[allow(clippy::large_enum_variant)] pub enum HandshakeError { Failure(Error), WouldBlock(MidHandshakeTlsStream), @@ -236,8 +241,8 @@ impl From for HandshakeError { pub struct TlsConnector { cert: Option, roots: CertStore, - min_protocol: Option<::Protocol>, - max_protocol: Option<::Protocol>, + min_protocol: Option, + max_protocol: Option, use_sni: bool, accept_invalid_hostnames: bool, accept_invalid_certs: bool, @@ -268,6 +273,7 @@ impl TlsConnector { }) } + #[allow(clippy::result_large_err)] pub fn connect(&self, domain: &str, stream: S) -> Result, HandshakeError> where S: io::Read + io::Write, @@ -289,10 +295,8 @@ impl TlsConnector { } else if self.disable_built_in_roots { let roots_copy = self.roots.clone(); builder.verify_callback(move |res| { - if let Err(err) = res.result() { - // Propagate previous error encountered during normal cert validation. - return Err(err); - } + // Propagate previous error encountered during normal cert validation. + res.result()?; if let Some(chain) = res.chain() { if chain @@ -303,8 +307,7 @@ impl TlsConnector { } } - Err(io::Error::new( - io::ErrorKind::Other, + Err(io::Error::other( "unable to find any user-specified roots in the final cert chain", )) }); @@ -327,8 +330,8 @@ impl TlsConnector { #[derive(Clone)] pub struct TlsAcceptor { cert: CertContext, - min_protocol: Option<::Protocol>, - max_protocol: Option<::Protocol>, + min_protocol: Option, + max_protocol: Option, } impl TlsAcceptor { @@ -340,6 +343,7 @@ impl TlsAcceptor { }) } + #[allow(clippy::result_large_err)] pub fn accept(&self, stream: S) -> Result, HandshakeError> where S: io::Read + io::Write, @@ -469,7 +473,7 @@ mod pem { Some(end) => end + begin + 1, None => last, }; - return Some(&self.pem_block[begin..self.cur_end].as_bytes()); + Some(&self.pem_block.as_bytes()[begin..self.cur_end]) } } diff --git a/src/imp/security_framework.rs b/src/imp/security_framework.rs index 302791a..acbd355 100644 --- a/src/imp/security_framework.rs +++ b/src/imp/security_framework.rs @@ -15,7 +15,6 @@ use std::error; use std::fmt; use std::io; use std::str; -use std::sync::Mutex; use std::sync::Once; #[cfg(not(any( @@ -56,8 +55,9 @@ use self::security_framework::os::macos::import_export::{ )))] use self::security_framework::os::macos::keychain::{self, KeychainSettings, SecKeychain}; -use {Protocol, TlsAcceptorBuilder, TlsConnectorBuilder}; +use crate::{Protocol, TlsAcceptorBuilder, TlsConnectorBuilder}; +#[allow(dead_code)] static SET_AT_EXIT: Once = Once::new(); #[cfg(not(any( @@ -66,7 +66,8 @@ static SET_AT_EXIT: Once = Once::new(); target_os = "tvos", target_os = "visionos" )))] -static TEMP_KEYCHAIN: Mutex> = Mutex::new(None); +static TEMP_KEYCHAIN: std::sync::Mutex> = + std::sync::Mutex::new(None); fn convert_protocol(protocol: Protocol) -> SslProtocol { match protocol { @@ -152,7 +153,7 @@ impl Identity { let cert = items .certificates - .get(0) + .first() .ok_or_else(|| Error(base::Error::from(errSecParam)))?; let ident = SecIdentity::with_certificate(&[keychain], cert)?; Ok(Identity { @@ -233,6 +234,7 @@ impl Identity { } } +#[allow(dead_code)] fn random_password() -> Result { use std::fmt::Write; let mut bytes = [0_u8; 10]; @@ -479,6 +481,7 @@ impl TlsAcceptor { pub struct TlsStream { stream: secure_transport::SslStream, + #[allow(dead_code)] cert: Option, } @@ -641,6 +644,7 @@ impl io::Write for TlsStream { } } +#[allow(dead_code)] enum Digest { Sha224, Sha256, @@ -649,9 +653,10 @@ enum Digest { } impl Digest { + #[allow(dead_code)] fn hash(&self, data: &[u8]) -> Vec { unsafe { - assert!(data.len() <= CC_LONG::max_value() as usize); + assert!(data.len() <= CC_LONG::MAX as usize); match *self { Digest::Sha224 => { let mut buf = [0; CC_SHA224_DIGEST_LENGTH]; @@ -679,16 +684,24 @@ impl Digest { } // FIXME ideally we'd pull these in from elsewhere +#[allow(dead_code)] const CC_SHA224_DIGEST_LENGTH: usize = 28; +#[allow(dead_code)] const CC_SHA256_DIGEST_LENGTH: usize = 32; +#[allow(dead_code)] const CC_SHA384_DIGEST_LENGTH: usize = 48; +#[allow(dead_code)] const CC_SHA512_DIGEST_LENGTH: usize = 64; -#[allow(non_camel_case_types)] +#[allow(non_camel_case_types, dead_code)] type CC_LONG = u32; extern "C" { + #[allow(dead_code)] fn CC_SHA224(data: *const u8, len: CC_LONG, md: *mut u8) -> *mut u8; + #[allow(dead_code)] fn CC_SHA256(data: *const u8, len: CC_LONG, md: *mut u8) -> *mut u8; + #[allow(dead_code)] fn CC_SHA384(data: *const u8, len: CC_LONG, md: *mut u8) -> *mut u8; + #[allow(dead_code)] fn CC_SHA512(data: *const u8, len: CC_LONG, md: *mut u8) -> *mut u8; } diff --git a/src/lib.rs b/src/lib.rs index 30c53ff..32d7afc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -35,8 +35,8 @@ //! # Cargo Features //! //! * `vendored` - If enabled, the crate will compile and statically link to a -//! vendored copy of OpenSSL. This feature has no effect on Windows and -//! macOS, where OpenSSL is not used. +//! vendored copy of OpenSSL. This feature has no effect on Windows and +//! macOS, where OpenSSL is not used. //! //! # Examples //! @@ -246,6 +246,7 @@ where /// Note that the error may not be fatal. For example if the underlying /// stream is an asynchronous one then `HandshakeError::WouldBlock` may /// just mean to wait for more I/O to happen later. + #[allow(clippy::result_large_err)] pub fn handshake(self) -> result::Result, HandshakeError> { match self.0.handshake() { Ok(s) => Ok(TlsStream(s)), @@ -256,6 +257,7 @@ where /// An error returned from `ClientBuilder::handshake`. #[derive(Debug)] +#[allow(clippy::large_enum_variant)] pub enum HandshakeError { /// A fatal error. Failure(Error), @@ -500,6 +502,7 @@ impl TlsConnector { /// /// The domain is ignored if both SNI and hostname verification are /// disabled. + #[allow(clippy::result_large_err)] pub fn connect( &self, domain: &str, @@ -616,6 +619,7 @@ impl TlsAcceptor { /// the handshake, a `HandshakeError::WouldBlock` error will be returned /// which can be used to restart the handshake when the socket is ready /// again. + #[allow(clippy::result_large_err)] pub fn accept(&self, stream: S) -> result::Result, HandshakeError> where S: io::Read + io::Write,