(&self, args: LoadCertChainArgs, vm: &VirtualMachine)
| 1831 | |
| 1832 | #[pymethod] |
| 1833 | fn load_cert_chain(&self, args: LoadCertChainArgs, vm: &VirtualMachine) -> PyResult<()> { |
| 1834 | use openssl::pkey::PKey; |
| 1835 | use std::cell::RefCell; |
| 1836 | |
| 1837 | let LoadCertChainArgs { |
| 1838 | certfile, |
| 1839 | keyfile, |
| 1840 | password, |
| 1841 | } = args; |
| 1842 | |
| 1843 | let mut ctx = self.builder(); |
| 1844 | let key_path = keyfile.map(|path| path.to_path_buf(vm)).transpose()?; |
| 1845 | let cert_path = certfile.to_path_buf(vm)?; |
| 1846 | |
| 1847 | // Check file existence before calling OpenSSL to get proper errno |
| 1848 | if !cert_path.exists() { |
| 1849 | return Err(vm |
| 1850 | .new_os_subtype_error( |
| 1851 | vm.ctx.exceptions.file_not_found_error.to_owned(), |
| 1852 | Some(libc::ENOENT), |
| 1853 | format!("No such file or directory: '{}'", cert_path.display()), |
| 1854 | ) |
| 1855 | .upcast()); |
| 1856 | } |
| 1857 | if let Some(ref kp) = key_path |
| 1858 | && !kp.exists() |
| 1859 | { |
| 1860 | return Err(vm |
| 1861 | .new_os_subtype_error( |
| 1862 | vm.ctx.exceptions.file_not_found_error.to_owned(), |
| 1863 | Some(libc::ENOENT), |
| 1864 | format!("No such file or directory: '{}'", kp.display()), |
| 1865 | ) |
| 1866 | .upcast()); |
| 1867 | } |
| 1868 | |
| 1869 | // Load certificate chain |
| 1870 | ctx.set_certificate_chain_file(&cert_path) |
| 1871 | .map_err(|e| convert_openssl_error(vm, e))?; |
| 1872 | |
| 1873 | // Load private key - handle password if provided |
| 1874 | let key_file_path = key_path.as_ref().unwrap_or(&cert_path); |
| 1875 | |
| 1876 | // PEM_BUFSIZE = 1024 (maximum password length in OpenSSL) |
| 1877 | const PEM_BUFSIZE: usize = 1024; |
| 1878 | |
| 1879 | // Read key file data |
| 1880 | let key_data = std::fs::read(key_file_path) |
| 1881 | .map_err(|e| crate::vm::convert::ToPyException::to_pyexception(&e, vm))?; |
| 1882 | |
| 1883 | let pkey = if let Some(ref pw_obj) = password { |
| 1884 | if pw_obj.is_callable() { |
| 1885 | // Callable password - use callback that calls Python function |
| 1886 | // Store any Python error that occurs in the callback |
| 1887 | let py_error: RefCell<Option<PyBaseExceptionRef>> = RefCell::new(None); |
| 1888 | |
| 1889 | let result = PKey::private_key_from_pem_callback(&key_data, |buf| { |
| 1890 | // Call the Python password callback |
nothing calls this directly
no test coverage detected