]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
rust: safe string handling in logging
authorJason Ish <ish@unx.ca>
Tue, 20 Jun 2017 18:47:34 +0000 (12:47 -0600)
committerVictor Julien <victor@inliniac.net>
Mon, 26 Jun 2017 07:59:54 +0000 (09:59 +0200)
In logging (SCLog*), safely convert strings to cstrings instead
of blindly unwrapping them.

Also implement a simple rust logger if the Suricata C context
is not available.

rust/src/core.rs
rust/src/log.rs

index e3647673c686386841afe634a0fb041340fd19c6..98d37afcdcfd43fae3cba9ee017121cb07f8dc4c 100644 (file)
@@ -105,7 +105,7 @@ pub type SCFileSetTx = extern "C" fn (
 #[allow(non_snake_case)]
 #[repr(C)]
 pub struct SuricataContext {
-    SCLogMessage: SCLogMessageFunc,
+    pub SCLogMessage: SCLogMessageFunc,
     DetectEngineStateFree: DetectEngineStateFreeFunc,
     AppLayerDecoderEventsSetEventRaw: AppLayerDecoderEventsSetEventRawFunc,
     AppLayerDecoderEventsFreeEvents: AppLayerDecoderEventsFreeEventsFunc,
@@ -135,23 +135,6 @@ pub extern "C" fn rs_init(context: &'static mut SuricataContext)
     }
 }
 
-/// SCLogMessage wrapper.
-pub fn sc_log_message(level: libc::c_int,
-                      filename: *const libc::c_char,
-                      line: libc::c_uint,
-                      function: *const libc::c_char,
-                      code: libc::c_int,
-                      message: *const libc::c_char) -> libc::c_int
-{
-    unsafe {
-        if let Some(c) = SC {
-            return (c.SCLogMessage)(level, filename, line, function,
-                                  code, message);
-        }
-    }
-    return 0;
-}
-
 /// DetectEngineStateFree wrapper.
 pub fn sc_detect_engine_state_free(state: *mut DetectEngineState)
 {
index 19b78cf6c3952c08e6e978c20c6116d18d722df5..ec09f812a2e8023524c754de5eb506fc79014d62 100644 (file)
 
 extern crate libc;
 
-use std::ffi::{CString};
+use std::ffi::CString;
 use std::path::Path;
 
 use core::*;
 
+#[derive(Debug)]
 pub enum Level {
     NotSet = -1,
     None = 0,
@@ -59,12 +60,12 @@ pub fn sclog(level: Level, file: &str, line: u32, function: &str,
          code: i32, message: &str)
 {
     let filename = basename(file);
-    sc_log_message(level as i32,
-                   CString::new(filename).unwrap().as_ptr(),
+    sc_log_message(level,
+                   filename,
                    line,
-                   CString::new(function).unwrap().as_ptr(),
+                   function,
                    code,
-                   CString::new(message).unwrap().as_ptr());
+                   message);
 }
 
 /// Return the function name, but for now just return <rust> as Rust
@@ -126,3 +127,52 @@ pub extern "C" fn rs_log_set_level(level: i32) {
         LEVEL = level;
     }
 }
+
+pub fn log_set_level(level: Level) {
+    rs_log_set_level(level as i32);
+}
+
+/// SCLogMessage wrapper. If the Suricata C context is not registered
+/// a more basic log format will be used (for example, when running
+/// Rust unit tests).
+pub fn sc_log_message(level: Level,
+                      filename: &str,
+                      line: libc::c_uint,
+                      function: &str,
+                      code: libc::c_int,
+                      message: &str) -> libc::c_int
+{
+    unsafe {
+        if let Some(c) = SC {
+            let filename = match CString::new(filename) {
+                Ok(filename) => filename,
+                Err(_) => CString::new("<filename not available>").unwrap()
+            };
+            let function = match CString::new(function) {
+                Ok(function) => function,
+                Err(_) => CString::new("<function not available>").unwrap()
+            };
+            let message = match CString::new(message) {
+                Ok(val) => val,
+                Err(_) => CString::new("<message not available>").unwrap()
+            };
+            return (c.SCLogMessage)(
+                level as i32,
+                filename.as_ptr(),
+                line,
+                function.as_ptr(),
+                code,
+                message.as_ptr());
+        }
+    }
+
+    // Fall back if the Suricata C context is not registered which is
+    // the case when Rust unit tests are running.
+    //
+    // We don't log the time right now as I don't think it can be done
+    // with Rust 1.7.0 without using an external crate. With Rust
+    // 1.8.0 and newer we can unix UNIX_EPOCH.elapsed() to get the
+    // unix time.
+    println!("{}:{} <{:?}> -- {}", filename, line, level, message);
+    return 0;
+}