SSL_FILETYPE_ASN1 part of _add_ca_certs in CPython
(der: &[u8])
| 3922 | |
| 3923 | // SSL_FILETYPE_ASN1 part of _add_ca_certs in CPython |
| 3924 | fn x509_stack_from_der(der: &[u8]) -> Result<Vec<X509>, ErrorStack> { |
| 3925 | unsafe { |
| 3926 | openssl::init(); |
| 3927 | let bio = bio::MemBioSlice::new(der)?; |
| 3928 | |
| 3929 | let mut certs = vec![]; |
| 3930 | let mut was_bio_eof = false; |
| 3931 | |
| 3932 | loop { |
| 3933 | // Check for EOF before attempting to parse (like CPython's _add_ca_certs) |
| 3934 | // BIO_ctrl with BIO_CTRL_EOF returns 1 if EOF, 0 otherwise |
| 3935 | if sys::BIO_ctrl(bio.as_ptr(), sys::BIO_CTRL_EOF, 0, std::ptr::null_mut()) != 0 { |
| 3936 | was_bio_eof = true; |
| 3937 | break; |
| 3938 | } |
| 3939 | |
| 3940 | let cert = sys::d2i_X509_bio(bio.as_ptr(), std::ptr::null_mut()); |
| 3941 | if cert.is_null() { |
| 3942 | // Parse error (not just EOF) |
| 3943 | break; |
| 3944 | } |
| 3945 | certs.push(X509::from_ptr(cert)); |
| 3946 | } |
| 3947 | |
| 3948 | // If we loaded some certs but didn't reach EOF, there's garbage data |
| 3949 | // (like cacert_der + b"A") - this is an error |
| 3950 | if !certs.is_empty() && !was_bio_eof { |
| 3951 | // Return the error from the last failed parse attempt |
| 3952 | return Err(ErrorStack::get()); |
| 3953 | } |
| 3954 | |
| 3955 | // Clear any errors (including parse errors when no certs loaded) |
| 3956 | // Let the caller decide how to handle empty results |
| 3957 | sys::ERR_clear_error(); |
| 3958 | Ok(certs) |
| 3959 | } |
| 3960 | } |
| 3961 | |
| 3962 | type CipherTuple = (&'static str, &'static str, i32); |
| 3963 |