bytebeamio / rumqtt

The MQTT ecosystem in rust
Apache License 2.0
1.58k stars 245 forks source link

Error with tls example 1 #498

Open EnricoMucelli opened 1 year ago

EnricoMucelli commented 1 year ago

HI, i'm trying to connect to mosquitto using the mosquitto.org.crt certificate, i've added it to the root certificates but when i start the app i get an infinite loop like this:

            `2022-11-10 08:56:21 - TRACE: registering event source with poller: token=Token(0), interests=READABLE
            2022-11-10 08:56:21 - TRACE: registering event source with poller: token=Token(1), interests=READABLE | WRITABLE
            2022-11-10 08:56:21 - DEBUG: No cached session for DnsName(DnsName(DnsName("test.mosquitto.org")))
            2022-11-10 08:56:21 - DEBUG: Not resuming any session
            2022-11-10 08:56:21 - TRACE: Sending ClientHello Message {
                version: TLSv1_0,
                payload: Handshake {
                    parsed: HandshakeMessagePayload {
                        typ: ClientHello,
                        payload: ClientHello(
                            ClientHelloPayload {
                                client_version: TLSv1_2,
                                random: fbca48af6ff5c799755a1eafe56b6939402cd088b1e6ca8b7a03b4bad9713ce7,
                                session_id: a24ff1e049985c94734a9309e826b1edad75941ec60db8d3dc347a2369ffb621,
                                cipher_suites: [
                                    TLS13_AES_256_GCM_SHA384,
                                    TLS13_AES_128_GCM_SHA256,
                                    TLS13_CHACHA20_POLY1305_SHA256,
                                    TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
                                    TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
                                    TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
                                    TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
                                    TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
                                    TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
                                    TLS_EMPTY_RENEGOTIATION_INFO_SCSV,
                                ],
                                compression_methods: [
                                    Null,
                                ],
                                extensions: [
                                    SupportedVersions(
                                        [
                                            TLSv1_3,
                                            TLSv1_2,
                                        ],
                                    ),
                                    ECPointFormats(
                                        [
                                            Uncompressed,
                                        ],
                                    ),
                                    NamedGroups(
                                        [
                                            X25519,
                                            secp256r1,
                                            secp384r1,
                                        ],
                                    ),
                                    SignatureAlgorithms(
                                        [
                                            ECDSA_NISTP384_SHA384,
                                            ECDSA_NISTP256_SHA256,
                                            ED25519,
                                            RSA_PSS_SHA512,
                                            RSA_PSS_SHA384,
                                            RSA_PSS_SHA256,
                                            RSA_PKCS1_SHA512,
                                            RSA_PKCS1_SHA384,
                                            RSA_PKCS1_SHA256,
                                        ],
                                    ),
                                    ExtendedMasterSecretRequest,
                                    CertificateStatusRequest(
                                        OCSP(
                                            OCSPCertificateStatusRequest {
                                                responder_ids: [],
                                                extensions: ,
                                            },
                                        ),
                                    ),
                                    ServerName(
                                        [
                                            ServerName {
                                                typ: HostName,
                                                payload: HostName(
                                                    (
                                                        746573742e6d6f7371756974746f2e6f7267,
                                                        DnsName(
                                                            "test.mosquitto.org",
                                                        ),
                                                    ),
                                                ),
                                            },
                                        ],
                                    ),
                                    SignedCertificateTimestampRequest,
                                    KeyShare(
                                        [
                                            KeyShareEntry {
                                                group: X25519,
                                                payload: a5894b22972c4d542530de9a476fbaacea74cf5d008c846f1e99922df0ad3a72,
                                            },
                                        ],
                                    ),
                                    PresharedKeyModes(
                                        [
                                            PSK_DHE_KE,
                                        ],
                                    ),
                                    SessionTicket(
                                        Request,
                                    ),
                                ],
                            },
                        ),
                    },
                    encoded:                               
    010000f00303fbca48af6ff5c799755a1eafe56b6939402cd088b1e6ca8b7a03b4bad9713ce720a24ff1e049985c94734a9309e826b1edad75941ec60db8d3dc347a2369ffb6210014130213011303c02cc02bcca9c030c02fcca800ff01000093002b00050403040303000b00020100000a00080006001d00170018000d0014001205030403080708060805080406010501040100170000000500050100000000000000170015000012746573742e6d6f7371756974746f2e6f726700120000003300260024001d0020a5894b22972c4d542530de9a476fbaacea74cf5d008c846f1e99922df0ad3a72002d0002010100230000,
                },
            }
            2022-11-10 08:56:21 - TRACE: We got ServerHello ServerHelloPayload {
                legacy_version: TLSv1_2,
                random: e8c1038f54e3b34492404422de36c3a2d67beb9c4ada233e1b163b844fc0994e,
                session_id: a24ff1e049985c94734a9309e826b1edad75941ec60db8d3dc347a2369ffb621,
                cipher_suite: TLS13_AES_256_GCM_SHA384,
                compression_method: Null,
                extensions: [
                    SupportedVersions(
                        TLSv1_3,
                    ),
                    KeyShare(
                        KeyShareEntry {
                            group: X25519,
                            payload: bb987824f63c74b55c1004d295c1855d5e01f759bfe2795ead69bdc94c51da6d,
                        },
                    ),
                ],
            }
            2022-11-10 08:56:21 - DEBUG: Using ciphersuite TLS13_AES_256_GCM_SHA384
            2022-11-10 08:56:21 - DEBUG: Not resuming
            2022-11-10 08:56:21 - TRACE: EarlyData rejected
            2022-11-10 08:56:21 - TRACE: Dropping CCS
            2022-11-10 08:56:21 - DEBUG: TLS1.3 encrypted extensions: [ServerNameAck]
            2022-11-10 08:56:21 - DEBUG: ALPN protocol is None
            2022-11-10 08:56:21 - TRACE: Server cert is [Certificate(b"0\x82\x03\x970\x82\x02\x7f\x02\x14}\xd3\x9bO\xdc[\xf7-\x0f\x0c\x04~\xb8\xf3#\x9e\xc1\x9b\xb7\xb70\r\x06\t*\x86H\x86\xf7\r\x01\x01\x0b\x05\00\x81\x901\x0b0\t\x06\x03U\x04\x06\x13\x02GB1\x170\x15\x06\x03U\x04\x08\x0c\x0eUnited Kingdom1\x0e0\x0c\x06\x03U\x04\x07\x0c\x05Derby1\x120\x10\x06\x03U\x04\n\x0c\tMosquitto1\x0b0\t\x06\x03U\x04\x0b\x0c\x02CA1\x160\x14\x06\x03U\x04\x03\x0c\rmosquitto.org1\x1f0\x1d\x06\t*\x86H\x86\xf7\r\x01\t\x01\x16\x10roger@atchoo.org0\x1e\x17\r200609112156Z\x17\r300606112156Z0\x7f1\x0b0\t\x06\x03U\x04\x06\x13\x02GB1\x170\x15\x06\x03U\x04\x08\x0c\x0eUnited Kingdom1\x0e0\x0c\x06\x03U\x04\x07\x0c\x05Derby1\x120\x10\x06\x03U\x04\n\x0c\tMosquitto1\x160\x14\x06\x03U\x04\x0b\x0c\rPublic server1\x1b0\x19\x06\x03U\x04\x03\x0c\x12test.mosquitto.org0\x82\x01\"0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x01\x05\0\x03\x82\x01\x0f\00\x82\x01\n\x02\x82\x01\x01\0\xe5\x84\xb2-\x99mh|\x06\x9c\xa7\xf2\x15\xc9\xcb7\xc7\x85#\xae\x18\xd6$\xf1\x7f\xdd:\x80\xd8\xa9\x1c\xb3\xb4J\t\xa9]:mH\x8f]y\xe1\x8d\x1a#\x1a\xc3%\x8f\xfc.\x0fD\xba\x90\xda\x11\xe4\xb8gh\xc1\xca,\x9b\xa8\x99\xe9e>,~\x8d\x8e\xb2\\HS\xb2`\xe2t\xf8\xad\xbd\xc1\xf8\xd8\x82f0\xb1\xdd\xee\xe4\x97\"w\xcf\xb2\xba\xb2\x1ek\xa4\xb6?\x870\xb7\xe0\x9b\xc4q\x18\x01>\xf4\xfd\"\xee\xbc78\x9eU\x938\xe1k\xde\xdd\x99+\xf8e\xa8(\xfc\xe9F2\x1e~\x07y\xa9\xe5.P\x08\xa1\xa6Y1\xea\x9b\xb9:Fo\xed\xa6\x80\x8d\\\xc9C\xebC$T\x18\xfc\x02_S\xbdx\xea\x85\xf9\\\xe7\x9c:\x12\x15\x0ci\xd37\x0b\xce\x1d\xdbg\xb7\x8a\xc6w\x17_\x97\xa6;\xdf}\xb3\xd3tDK\x91gyoVzkx\x1c\x1c\xca|\x1e[\xb2\x88\n\x0c\x80\xec\xaeN\xd7\x81\xc6`\xaa{\xc7@Z\xf78w\x17\xb6\x7f\xc0iJ!\x02\x03\x01\0\x010\r\x06\t*\x86H\x86\xf7\r\x01\x01\x0b\x05\0\x03\x82\x01\x01\0\xbao\x99\xce\xe1)!k\xba\xe0\\K\xe2\x96\xfd,\x1f7'\x8f\xdf\x97j\xf7xM5\x04\xf0\xff\xec}U\xe7\xb1\xec\xdf^!\xf7\x1f\xe4\xd8#\xa9\x16z\xc1\xdb\xbc\xb4k\xb8\nW\x8f\xc0\x0bj\xbf4\x82\x9dX\x9dc\xf5\xe6\xc2\"\xf5C\x8b\xae`\xd6\xed\x11\x84\xa5\x92\xb4\x95\xb9`\x96\xfd\xc5:!\x89\xde~w\xe2p$\xea\0\xbf\x90\x18d\\\xa7\x95bB\xa4\x94G\xd4\x0c\x9b\xe8\x18\xfa\x85\xa9\xdd\x9a\x14\xb9\xed\xbd\xd7\xf9\xb1M\xa9\xd6\n\xcf\xee\x1d\x80\xd0*\xef\xf1\xae\xf9{O\xd6k\x96\xa2\x05\xd4{\xa1\x95\x92\x88d=\xd6kfJ\xf7\xfba\xb1\xa4'\x07\xbdx`\x1e\xa5\x8a\x93\xe3Vy\x05\xd6;I_\xe0\xe3\xf5\xd7\x15!\x130nD\n\x99pq\xb1~\x18\xe48\xf4\x85\x89\x1f\x8e\x86\x93 u\x93\xd7?\xff\x07\xb9BufJ\x8f\xb8\xf15|h|\xd7\0\x91\xbf\xf3\x9b\x83\x80X\n\xe9\xad3\xf2\x06<\x8e\xde\x8b\xfd\xe8\x8d\xea\x96\tg}\xa7")]
            2022-11-10 08:56:21 - WARN: Sending fatal alert BadCertificate
            2022-11-10 08:56:21 - TRACE: deregistering event source from poller
            Error = Tls(Io(Custom { kind: InvalidData, error: InvalidCertificateData("invalid peer certificate: UnsupportedCertVersion") }))`

the function is this one :

    `use std::error::Error;

    #[cfg(feature = "use-rustls")]
    #[tokio::main]
    pub async fn test_mqtt() -> Result<(), Box<dyn Error>> {
        use rumqttc::{self, AsyncClient, Event, Incoming, MqttOptions, Transport};
        use rustls::ClientConfig;

        let mut mqttoptions = MqttOptions::new("noz", "test.mosquitto.org", 8883);
        mqttoptions.set_keep_alive(std::time::Duration::from_secs(5));
        //mqttoptions.set_credentials("rw", "readwrite");

        // Use rustls-native-certs to load root certificates from the operating system.
        let mut root_cert_store = rustls::RootCertStore::empty();
        for cert in rustls_native_certs::load_native_certs().expect("could not load platform certs") {
            root_cert_store.add(&rustls::Certificate(cert.0))?;
        }

        let client_config = ClientConfig::builder()
            .with_safe_defaults()
            .with_root_certificates(root_cert_store)
            .with_no_client_auth();

        mqttoptions.set_transport(Transport::tls_with_config(client_config.into()));

        let (_client, mut eventloop) = AsyncClient::new(mqttoptions, 10);

        loop {
            match eventloop.poll().await {
                Ok(Event::Incoming(Incoming::Publish(p))) => {
                    println!("Topic: {}, Payload: {:?}", p.topic, p.payload);
                }
                Ok(Event::Incoming(i)) => {
                    println!("Incoming = {:?}", i);
                }
                Ok(Event::Outgoing(o)) => println!("Outgoing = {:?}", o),
                Err(e) => {
                    println!("Error = {:?}", e);
                }
            }
        }
    }

    #[cfg(not(feature = "use-rustls"))]
    fn main() -> Result<(), Box<dyn Error>> {
        panic!("Enable feature 'use-rustls'");
    }`
shimunn commented 1 year ago

Same issue with both my own CA/certs as well as with test.mosquitto.org

Bravo555 commented 1 year ago

UnsupportedCertVersion error originates from the webpki crate, and means that the certificate is not X509v3. You can check if a local certificate is v3 using this command:

$ openssl x509 -in server.crt -noout -text | grep Version
        Version: 3 (0x2)

To print remote certificate (eg. test.mosquitto.org) we use another command:

$ echo | openssl s_client -showcerts -servername test.mosquitto.org \
-connect test.mosquitto.org:8883 2>/dev/null | openssl x509 -inform pem -noout -text | grep Version
        Version: 1 (0x0)

We see that certificate for test.mosquitto.org is not v3, so it won't be verified. This seems to me that perhaps verification is too strict, if we can't even connect to test.mosquitto.org where other clients connect to it just fine.

I've also found that certificate needs to use X509v3 Subject Alternative Name extension, and it needs to contain DNS:[$CN], where $CN is the value of the CN field in the certificate. I think for some reason webpki while verifying whether a certificate is valid for the host we try to connect to, it only looks at the collection of subject alternative names and doesn't look at CN??? Honestly I have no clue, but I've somehow got it to work.

I'm not an expert in TLS, so I don't know if this is intended behaviour or not? From a user's perspective, it seems that rumqttc just refuses to connect to brokers other clients can connect to just fine.

FinitelyFailed commented 5 months ago

Hi,

I'm trying out rumqttc and stumble on the same issue.

I'm trying to connect to mosquitto test brokers (https://test.mosquitto.org/), and when I try to connect to one listed as: "8883 : MQTT, encrypted, unauthenticated". Which states that I shall use the ca-cert file provided by mosquitto (mosquitto.org.crt). But when do try I get: "I/O: invalid peer certificate: Other(OtherError(UnsupportedCertVersion))".