Move client certificate setup into epp_connect()

This commit is contained in:
Dirkjan Ochtman 2021-12-01 14:15:08 +01:00 committed by masalachai
parent 7ff8547840
commit d1cf43af46
2 changed files with 42 additions and 44 deletions

View File

@ -38,15 +38,9 @@
//! ``` //! ```
use std::collections::HashMap; use std::collections::HashMap;
use std::fs::File;
use std::io::{BufReader, Seek, SeekFrom};
use rustls::{Certificate, PrivateKey};
use rustls_pemfile;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::error::Error;
/// Paths to the client certificate and client key PEM files /// Paths to the client certificate and client key PEM files
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
pub struct EppClientTlsFiles { pub struct EppClientTlsFiles {
@ -91,36 +85,4 @@ impl EppClientConnection {
pub fn ext_uris(&self) -> Option<&Vec<String>> { pub fn ext_uris(&self) -> Option<&Vec<String>> {
self.ext_uris.as_ref() self.ext_uris.as_ref()
} }
/// Returns the parsed client certificate and private key for client TLS auth
pub fn tls_files(&self) -> Result<Option<(Vec<Certificate>, PrivateKey)>, Error> {
let (certs_file, key_file) = match &self.tls_files {
Some(files) => (&files.cert_chain, &files.key),
None => return Ok(None),
};
let certs = rustls_pemfile::certs(&mut BufReader::new(File::open(certs_file)?))?
.into_iter()
.map(Certificate)
.collect::<Vec<_>>();
let mut r = BufReader::new(File::open(key_file).unwrap());
let mut rsa_keys = rustls_pemfile::rsa_private_keys(&mut r).unwrap();
if rsa_keys.len() > 1 {
warn!("Multiple RSA keys found in PEM file {}", key_file);
} else if let Some(key) = rsa_keys.pop() {
return Ok(Some((certs, rustls::PrivateKey(key))));
}
r.seek(SeekFrom::Start(0))?;
let mut pkcs8_keys = rustls_pemfile::pkcs8_private_keys(&mut r).unwrap();
if pkcs8_keys.len() > 1 {
warn!("Multiple PKCS8 keys found in PEM file {}", key_file);
} else if let Some(key) = pkcs8_keys.pop() {
return Ok(Some((certs, rustls::PrivateKey(key))));
}
Err(Error::Other("No private key found in PEM file".to_owned()))
}
} }

View File

@ -1,10 +1,15 @@
//! Manages registry connections and reading/writing to them //! Manages registry connections and reading/writing to them
use rustls::{OwnedTrustAnchor, RootCertStore};
use std::convert::TryInto; use std::convert::TryInto;
use std::fs::File;
use std::io::{BufReader, Seek, SeekFrom};
use std::sync::Arc; use std::sync::Arc;
use std::{error::Error, io as stdio, net::ToSocketAddrs}; use std::{error::Error, io as stdio, net::ToSocketAddrs};
use std::{io, str, u32}; use std::{io, str, u32};
use rustls::{Certificate, PrivateKey};
use rustls::{OwnedTrustAnchor, RootCertStore};
use rustls_pemfile;
use tokio::{io::AsyncReadExt, io::AsyncWriteExt, net::TcpStream}; use tokio::{io::AsyncReadExt, io::AsyncWriteExt, net::TcpStream};
use tokio_rustls::{client::TlsStream, rustls::ClientConfig, TlsConnector}; use tokio_rustls::{client::TlsStream, rustls::ClientConfig, TlsConnector};
@ -137,11 +142,42 @@ pub async fn epp_connect(
.with_safe_defaults() .with_safe_defaults()
.with_root_certificates(roots); .with_root_certificates(roots);
let config = match registry_creds.tls_files()? { let config = match &registry_creds.tls_files {
Some((cert_chain, key)) => match builder.with_single_cert(cert_chain, key) { Some(files) => {
Ok(config) => config, let (certs_file, key_file) = (&files.cert_chain, &files.key);
Err(e) => return Err(format!("Failed to set client TLS credentials: {}", e).into()), let certs = rustls_pemfile::certs(&mut BufReader::new(File::open(certs_file)?))?
}, .into_iter()
.map(Certificate)
.collect::<Vec<_>>();
let mut key;
let mut r = BufReader::new(File::open(key_file).unwrap());
let mut rsa_keys = rustls_pemfile::rsa_private_keys(&mut r).unwrap();
if rsa_keys.len() > 1 {
warn!("Multiple RSA keys found in PEM file {}", key_file);
}
key = rsa_keys.pop();
if key.is_none() {
r.seek(SeekFrom::Start(0))?;
let mut pkcs8_keys = rustls_pemfile::pkcs8_private_keys(&mut r).unwrap();
if pkcs8_keys.len() > 1 {
warn!("Multiple PKCS8 keys found in PEM file {}", key_file);
}
key = pkcs8_keys.pop();
}
match key {
Some(key) => builder
.with_single_cert(certs, PrivateKey(key))
.map_err(|e| error::Error::Other(e.to_string()))?,
None => {
return Err(error::Error::Other(
"No private key found in PEM file".to_owned(),
))
}
}
}
None => builder.with_no_client_auth(), None => builder.with_no_client_auth(),
}; };