sfackler / rust-native-tls

Apache License 2.0
468 stars 197 forks source link

PKCS12 Legacy Support #268

Closed 641i130 closed 1 year ago

641i130 commented 1 year ago

I'm trying to write an HTTPS server that uses a legacy format of PFX (pkcs#12 aka .p12) identity files for TLS.

From attempting to with the native_tls example structure (see code below), I find that it doesn't support this.

In a situation where I'm forced to use this format of a certificate for a client that cannot be modified, how would one go about this? I'm doing this for a learning experience, but seeing that this is a totally reasonable situation to find yourself at an odd job, what do you do?

use native_tls::{Identity, TlsAcceptor, TlsStream};
use std::fs::File;
use std::io::Read;
use std::io::{prelude::*, BufReader};
use std::net::{TcpListener, TcpStream};
use std::sync::Arc;
use std::thread;

fn handle_connection(mut stream: TlsStream<TcpStream>) {
    let buf_reader = BufReader::new(&mut stream);
    let http_request: Vec<_> = buf_reader.lines().map(|result| result.unwrap()).take_while(|line| !line.is_empty()).collect();

    println!("Request: {:#?}", http_request);
}

fn main() {
    let mut file = File::open("root.pfx").unwrap();
    let mut identity = vec![];
    file.read_to_end(&mut identity).unwrap();
    let identity = Identity::from_pkcs12(&identity, "").unwrap();

    let listener = TcpListener::bind("0.0.0.0:8443").unwrap();
    let acceptor = TlsAcceptor::new(identity).unwrap();
    let acceptor = Arc::new(acceptor);

    for stream in listener.incoming() {
        match stream {
            Ok(stream) => {
                let acceptor = acceptor.clone();
                thread::spawn(move || {
                    let stream = acceptor.accept(stream).unwrap();
                    handle_connection(stream);
                });
            }
            Err(e) => { /* connection failed */ }
        }
    }
}

Error:

This happens when trying to access the port via a webbrowser.

thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: Failure(Ssl(Error { code: 
ErrorCode(1), cause: Some(Ssl(ErrorStack([Error { code: 336130204, library: "SSL routines", function: 
"ssl3_get_record", reason: "http request", file: "ssl/record/ssl3_record.c", line: 321 }]))) }, 
X509VerifyResult { code: 0, error: "ok" }))', src/main.rs:31:58

(I'm guessing this means it's not supported, but maybe I'm doing something else wrong)

The certificate is generated like this:

# Generate certificate
openssl req -newkey rsa:2048 -nodes -keyout root.key -x509 -days 3650 -out root.crt -subj "CN=Root Cert"
# Put into legacy PFX format for client
openssl pkcs12 -export -certpbe PBE-SHA1-3DES -keypbe PBE-SHA1-3DES -nomac -inkey root.key -in root.crt -out root.pfx

For more detail on why I'm doing this, read my previous post.

641i130 commented 1 year ago

Hang on, I missed a few things...