sfackler / rust-native-tls

Apache License 2.0
474 stars 199 forks source link

Inconsistent handling of PEM files on OSX #132

Open chefsalim opened 5 years ago

chefsalim commented 5 years ago

The Certificate::from_pem function for OSX restricts the number of certificates that can be in the passed in PEM file. Therefore higher level libraries (like reqwest) will fail with a "One or more parameters passed to the function are not valid." message when a PEM file with a cert chain is used.

  1. It would be great to know more details on the restrictions and recommendation for work around
  2. It would be great to have the limitations removed and the ability to support cert chains added explicitly
    #[cfg(not(target_os = "ios"))]
    pub fn from_pem(buf: &[u8]) -> Result<Certificate, Error> {
        let mut items = SecItems::default();
        ImportOptions::new().items(&mut items).import(buf)?;
        if items.certificates.len() == 1 && items.identities.is_empty() && items.keys.is_empty() {
            Ok(Certificate(items.certificates.pop().unwrap()))
        } else {
            Err(Error(base::Error::from(errSecParam)))
        }
    }
sfackler commented 5 years ago

It seems like the better thing would be for from_pem to consistently only accept a single certificate rather than silently discarding the extra ones. We could add a separate method to parse multiple certificates from one file.

chefsalim commented 5 years ago

It would be more consistent than the behavior today, however it might be confusing from a naming standpoint (as PEMs don't have that restriction in general). It would also require all upstream users to know about this limitation and fix up their logic. So there are some downsides to that,

sfackler commented 5 years ago

Upstream users need to be aware of the limitation either way, since every single certificate except the first would be silently ignored otherwise!

jamesmcm commented 4 years ago

I hit this issue recently, openssl works okay though:

use openssl::ssl::{SslConnector, SslMethod};

    let mut builder = SslConnector::builder(SslMethod::tls())?;
    builder.set_ca_file(format!(
        "{}/redshift-ssl-ca-cert.pem",
        std::env::var("CARGO_MANIFEST_DIR").unwrap()
    ))?;