ssl/tls: use the rust decoder to decode X.509 certificates

pull/4721/head
Pierre Chifflier 5 years ago
parent 10d9deec9f
commit d92321d8b1

@ -69,3 +69,4 @@ pub mod sip;
pub mod rfb;
pub mod applayertemplate;
pub mod rdp;
pub mod x509;

@ -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));
}

@ -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:

Loading…
Cancel
Save