use nom7::Err;
use std;
use std::os::raw::c_char;
+use std::fmt;
use x509_parser::prelude::*;
+use crate::x509::GeneralName;
mod time;
mod log;
pub struct X509(X509Certificate<'static>);
+pub struct SCGeneralName<'a>(&'a GeneralName<'a>);
+
+impl<'a> fmt::Display for SCGeneralName<'a> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self.0 {
+ GeneralName::DNSName(s) => write!(f, "{}", s),
+ GeneralName::URI(s) => write!(f, "{}", s),
+ GeneralName::IPAddress(s) => write!(f, "{:?}", s),
+ _ => write!(f, "{}", self.0)
+ }
+ }
+}
+
/// Attempt to parse a X.509 from input, and return a pointer to the parsed object if successful.
///
/// # Safety
rust_string_to_c(subject)
}
+#[no_mangle]
+pub unsafe extern "C" fn rs_x509_get_subjectaltname_len(ptr: *const X509) -> u16 {
+ if ptr.is_null() {
+ return 0;
+ }
+ let x509 = cast_pointer! {ptr, X509};
+ let san_list = x509.0.tbs_certificate.subject_alternative_name();
+ if let Ok(Some(sans)) = san_list {
+ // SAN length in a certificate is kept u16 following discussions at
+ // https://community.letsencrypt.org/t/why-sans-are-limited-to-100-domains-only
+ debug_validate_bug_on!(sans.value.general_names.len() == u16::MAX.into());
+ return sans.value.general_names.len() as u16;
+ }
+ return 0;
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rs_x509_get_subjectaltname_at(ptr: *const X509, idx: u16) -> *mut c_char {
+ if ptr.is_null() {
+ return std::ptr::null_mut();
+ }
+ let x509 = cast_pointer! {ptr, X509};
+ let san_list = x509.0.tbs_certificate.subject_alternative_name();
+ if let Ok(Some(sans)) = san_list {
+ let general_name = &sans.value.general_names[idx as usize];
+ let dns_name = SCGeneralName(general_name);
+ return rust_string_to_c(dns_name.to_string());
+ }
+ return std::ptr::null_mut();
+}
+
#[no_mangle]
pub unsafe extern "C" fn rs_x509_get_issuer(ptr: *const X509) -> *mut c_char {
if ptr.is_null() {
} \
} while (0)
+static void SSLStateCertSANFree(SSLStateConnp *connp);
+
static void *SSLGetTx(void *state, uint64_t tx_id)
{
SSLState *ssl_state = (SSLState *)state;
}
connp->cert0_issuerdn = str;
+ connp->cert0_sans_len = rs_x509_get_subjectaltname_len(x509);
+ char **sans = SCCalloc(connp->cert0_sans_len, sizeof(char *));
+ if (sans == NULL) {
+ goto error;
+ }
+ for (uint16_t i = 0; i < connp->cert0_sans_len; i++) {
+ sans[i] = rs_x509_get_subjectaltname_at(x509, i);
+ }
+ connp->cert0_sans = sans;
str = rs_x509_get_serial(x509);
if (str == NULL) {
err_code = ERR_INVALID_SERIAL;
TlsDecodeHSCertificateErrSetEvent(ssl_state, err_code);
if (x509 != NULL)
rs_x509_free(x509);
+
+ SSLStateCertSANFree(connp);
return -1;
invalid_cert:
return (void *)ssl_state;
}
+static void SSLStateCertSANFree(SSLStateConnp *connp)
+{
+ if (connp->cert0_sans) {
+ for (uint16_t i = 0; i < connp->cert0_sans_len; i++) {
+ rs_cstring_free(connp->cert0_sans[i]);
+ }
+ SCFree(connp->cert0_sans);
+ }
+}
+
/**
* \internal
* \brief Function to free the SSL state memory.
if (ssl_state->server_connp.hs_buffer)
SCFree(ssl_state->server_connp.hs_buffer);
+ SSLStateCertSANFree(&ssl_state->server_connp);
+ SSLStateCertSANFree(&ssl_state->client_connp);
+
AppLayerDecoderEventsFreeEvents(&ssl_state->tx_data.events);
if (ssl_state->tx_data.de_state != NULL) {