]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
ssl/tls: use the rust decoder to decode X.509 certificates
authorPierre Chifflier <chifflier@wzdftpd.net>
Mon, 9 Mar 2020 12:38:13 +0000 (13:38 +0100)
committerPierre Chifflier <chifflier@wzdftpd.net>
Mon, 23 Mar 2020 15:54:19 +0000 (16:54 +0100)
rust/src/lib.rs
rust/src/x509/mod.rs [new file with mode: 0644]
src/app-layer-ssl.c

index dddb9ec1431496b3bede6a1434b593cdbda880e2..30624ba7b1025993675ea8ab638ccae1a2cfd9fe 100644 (file)
@@ -69,3 +69,4 @@ pub mod sip;
 pub mod rfb;
 pub mod applayertemplate;
 pub mod rdp;
+pub mod x509;
diff --git a/rust/src/x509/mod.rs b/rust/src/x509/mod.rs
new file mode 100644 (file)
index 0000000..780dc62
--- /dev/null
@@ -0,0 +1,105 @@
+/* Copyright (C) 2019-2020 Open Information Security Foundation
+ *
+ * You can copy, redistribute or modify this Program under the terms of
+ * the GNU General Public License version 2 as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+// written by Pierre Chifflier  <chifflier@wzdftpd.net>
+
+use crate::common::rust_string_to_c;
+use std;
+use std::os::raw::c_char;
+use x509_parser::{parse_x509_der, X509Certificate};
+
+pub struct X509(X509Certificate<'static>);
+
+/// Attempt to parse a X.509 from input, and return a pointer to the parsed object if successful.
+///
+/// # Safety
+///
+/// input must be a valid buffer of at least input_len bytes
+#[no_mangle]
+pub unsafe extern "C" fn rs_x509_decode(input: *const u8, input_len: u32) -> *mut X509 {
+    let slice = std::slice::from_raw_parts(input, input_len as usize);
+    let res = parse_x509_der(slice);
+    match res {
+        Ok((_rem, cert)) => Box::into_raw(Box::new(X509(cert))),
+        Err(_) => std::ptr::null_mut(),
+    }
+}
+
+#[no_mangle]
+pub extern "C" fn rs_x509_get_subject(ptr: *const X509) -> *mut c_char {
+    if ptr.is_null() {
+        return std::ptr::null_mut();
+    }
+    let x509 = cast_pointer! {ptr, X509};
+    let subject = x509.0.tbs_certificate.subject.to_string();
+    rust_string_to_c(subject)
+}
+
+#[no_mangle]
+pub extern "C" fn rs_x509_get_issuer(ptr: *const X509) -> *mut c_char {
+    if ptr.is_null() {
+        return std::ptr::null_mut();
+    }
+    let x509 = cast_pointer! {ptr, X509};
+    let issuer = x509.0.tbs_certificate.issuer.to_string();
+    rust_string_to_c(issuer)
+}
+
+#[no_mangle]
+pub extern "C" fn rs_x509_get_serial(ptr: *const X509) -> *mut c_char {
+    if ptr.is_null() {
+        return std::ptr::null_mut();
+    }
+    let x509 = cast_pointer! {ptr, X509};
+    let serial = x509.0.tbs_certificate.serial.to_string();
+    rust_string_to_c(serial)
+}
+
+/// Extract validity from input X.509 object
+///
+/// # Safety
+///
+/// ptr must be a valid object obtained using `rs_x509_decode`
+#[no_mangle]
+pub unsafe extern "C" fn rs_x509_get_validity(
+    ptr: *const X509,
+    not_before: *mut i64,
+    not_after: *mut i64,
+) -> i32 {
+    if ptr.is_null() {
+        return -1;
+    }
+    let x509 = &*ptr;
+    let n_b = x509.0.tbs_certificate.validity.not_before.to_timespec().sec;
+    let n_a = x509.0.tbs_certificate.validity.not_after.to_timespec().sec;
+    *not_before = n_b;
+    *not_after = n_a;
+    0
+}
+
+/// Free a X.509 object allocated by Rust
+///
+/// # Safety
+///
+/// ptr must be a valid object obtained using `rs_x509_decode`
+#[no_mangle]
+pub unsafe extern "C" fn rs_x509_free(ptr: *mut X509) {
+    if ptr.is_null() {
+        return;
+    }
+    drop(Box::from_raw(ptr));
+}
index f38346adc289854f5ab011bbf578415fbbf4cb03..8b3e43b2cad629172e0f9c21f8ea137cbb522c96 100644 (file)
@@ -385,91 +385,6 @@ static void TlsDecodeHSCertificateErrSetEvent(SSLState *ssl_state, uint32_t err)
     }
 }
 
-static inline int TlsDecodeHSCertificateSubject(SSLState *ssl_state,
-                                                Asn1Generic *cert)
-{
-    if (unlikely(ssl_state->server_connp.cert0_subject != NULL))
-        return 0;
-
-    uint32_t err = 0;
-    char buffer[512];
-
-    int rc = Asn1DerGetSubjectDN(cert, buffer, sizeof(buffer), &err);
-    if (rc != 0) {
-        TlsDecodeHSCertificateErrSetEvent(ssl_state, err);
-        return 0;
-    }
-
-    ssl_state->server_connp.cert0_subject = SCStrdup(buffer);
-    if (ssl_state->server_connp.cert0_subject == NULL)
-        return -1;
-
-    return 0;
-}
-
-static inline int TlsDecodeHSCertificateIssuer(SSLState *ssl_state,
-                                               Asn1Generic *cert)
-{
-    if (unlikely(ssl_state->server_connp.cert0_issuerdn != NULL))
-        return 0;
-
-    uint32_t err = 0;
-    char buffer[512];
-
-    int rc = Asn1DerGetIssuerDN(cert, buffer, sizeof(buffer), &err);
-    if (rc != 0) {
-        TlsDecodeHSCertificateErrSetEvent(ssl_state, err);
-        return 0;
-    }
-
-    ssl_state->server_connp.cert0_issuerdn = SCStrdup(buffer);
-    if (ssl_state->server_connp.cert0_issuerdn == NULL)
-        return -1;
-
-    return 0;
-}
-
-static inline int TlsDecodeHSCertificateSerial(SSLState *ssl_state,
-                                               Asn1Generic *cert)
-{
-    if (unlikely(ssl_state->server_connp.cert0_serial != NULL))
-        return 0;
-
-    uint32_t err = 0;
-    char buffer[512];
-
-    int rc = Asn1DerGetSerial(cert, buffer, sizeof(buffer), &err);
-    if (rc != 0) {
-        TlsDecodeHSCertificateErrSetEvent(ssl_state, err);
-        return 0;
-    }
-
-    ssl_state->server_connp.cert0_serial = SCStrdup(buffer);
-    if (ssl_state->server_connp.cert0_serial == NULL)
-        return -1;
-
-    return 0;
-}
-
-static inline int TlsDecodeHSCertificateValidity(SSLState *ssl_state,
-                                                 Asn1Generic *cert)
-{
-    uint32_t err = 0;
-    time_t not_before;
-    time_t not_after;
-
-    int rc = Asn1DerGetValidity(cert, &not_before, &not_after, &err);
-    if (rc != 0) {
-        TlsDecodeHSCertificateErrSetEvent(ssl_state, err);
-        return 0;
-    }
-
-    ssl_state->server_connp.cert0_not_before = not_before;
-    ssl_state->server_connp.cert0_not_after = not_after;
-
-    return 0;
-}
-
 static inline int TlsDecodeHSCertificateFingerprint(SSLState *ssl_state,
                                                     const uint8_t *input,
                                                     uint32_t cert_len)
@@ -515,7 +430,7 @@ static int TlsDecodeHSCertificate(SSLState *ssl_state,
 {
     const uint8_t *input = (uint8_t *)initial_input;
 
-    Asn1Generic *cert = NULL;
+    X509 *x509 = NULL;
 
     if (!(HAS_SPACE(3)))
         return 1;
@@ -539,40 +454,47 @@ static int TlsDecodeHSCertificate(SSLState *ssl_state,
         if (!(HAS_SPACE(cert_len)))
             goto invalid_cert;
 
-        uint32_t err = 0;
+        // uint32_t err = 0;
         int rc = 0;
 
         /* only store fields from the first certificate in the chain */
         if (processed_len == 0) {
-            /* coverity[tainted_data] */
-            cert = DecodeDer(input, cert_len, &err);
-            if (cert == NULL) {
-                TlsDecodeHSCertificateErrSetEvent(ssl_state, err);
+            char * str;
+            int64_t not_before, not_after;
+
+            x509 = rs_x509_decode(input, cert_len);
+            if (x509 == NULL) {
+                TlsDecodeHSCertificateErrSetEvent(ssl_state, ERR_DER_GENERIC);
                 goto next;
             }
 
-            rc = TlsDecodeHSCertificateSubject(ssl_state, cert);
-            if (rc != 0)
+            str = rs_x509_get_subject(x509);
+            if (str == NULL)
                 goto error;
+            ssl_state->server_connp.cert0_subject = str;
 
-            rc = TlsDecodeHSCertificateIssuer(ssl_state, cert);
-            if (rc != 0)
+            str = rs_x509_get_issuer(x509);
+            if (str == NULL)
                 goto error;
+            ssl_state->server_connp.cert0_issuerdn = str;
 
-            rc = TlsDecodeHSCertificateSerial(ssl_state, cert);
-            if (rc != 0)
+            str = rs_x509_get_serial(x509);
+            if (str == NULL)
                 goto error;
+            ssl_state->server_connp.cert0_serial = str;
 
-            rc = TlsDecodeHSCertificateValidity(ssl_state, cert);
+            rc = rs_x509_get_validity(x509, &not_before, &not_after);
             if (rc != 0)
                 goto error;
+            ssl_state->server_connp.cert0_not_before = (time_t)not_before;
+            ssl_state->server_connp.cert0_not_after = (time_t)not_after;
+
+            rs_x509_free(x509);
+            x509 = NULL;
 
             rc = TlsDecodeHSCertificateFingerprint(ssl_state, input, cert_len);
             if (rc != 0)
                 goto error;
-
-            DerFree(cert);
-            cert = NULL;
         }
 
         rc = TlsDecodeHSCertificateAddCertToChain(ssl_state, input, cert_len);
@@ -587,8 +509,8 @@ next:
     return (input - initial_input);
 
 error:
-    if (cert != NULL)
-        DerFree(cert);
+    if (x509 != NULL)
+        rs_x509_free(x509);
     return -1;
 
 invalid_cert: