]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
Kerberos 5: add support for TCP as well
authorPierre Chifflier <chifflier@wzdftpd.net>
Tue, 17 Apr 2018 07:31:04 +0000 (09:31 +0200)
committerPierre Chifflier <chifflier@wzdftpd.net>
Wed, 13 Jun 2018 08:25:40 +0000 (10:25 +0200)
doc/userguide/rules/intro.rst
rust/src/krb/krb5.rs
src/output-json-krb5.c

index 55ac9b57f9b44a32f91434537a8ad723e0286c18..64604f0970e0d222eaa9eb754b16c95204b8a51d 100644 (file)
@@ -79,6 +79,7 @@ you can pick from. These are:
 * enip (disabled by default)
 * nfs (depends on rust availability)
 * ikev2 (depends on rust availability)
+* krb5 (depends on rust availability)
 * ntp (depends on rust availability)
 
 The availability of these protocols depends on whether the protocol is enabled in the configuration file suricata.yaml.
index b3f70fbb77425e3f7b9444a74b6c6d23333c3440..6e11b840b912a2a303931181e2800a12f7377693 100644 (file)
@@ -20,7 +20,7 @@
 use libc;
 use std;
 use std::ffi::{CStr,CString};
-use nom::IResult;
+use nom::{IResult,be_u32};
 use der_parser::der_read_element_header;
 use kerberos_parser::krb5_parser;
 use kerberos_parser::krb5::{EncryptionType,MessageType,PrincipalName,Realm};
@@ -410,6 +410,24 @@ pub extern "C" fn rs_krb5_probing_parser(_flow: *const Flow, input:*const libc::
     }
 }
 
+#[no_mangle]
+pub extern "C" fn rs_krb5_probing_parser_tcp(_flow: *const Flow, input:*const libc::uint8_t, input_len: u32, _offset: *const u32) -> AppProto {
+    let slice = build_slice!(input,input_len as usize);
+    if slice.len() <= 14 { return unsafe{ALPROTO_FAILED}; }
+    match be_u32(slice) {
+        IResult::Done(rem, record_mark) => {
+            if record_mark != rem.len() as u32 { return unsafe{ALPROTO_FAILED}; }
+            return rs_krb5_probing_parser(_flow, rem.as_ptr(), rem.len() as u32, _offset);
+        },
+        IResult::Incomplete(_) => {
+            return ALPROTO_UNKNOWN;
+        },
+        IResult::Error(_) => {
+            return unsafe{ALPROTO_FAILED};
+        },
+    }
+}
+
 #[no_mangle]
 pub extern "C" fn rs_krb5_parse_request(_flow: *const core::Flow,
                                        state: *mut libc::c_void,
@@ -434,13 +452,41 @@ pub extern "C" fn rs_krb5_parse_response(_flow: *const core::Flow,
     state.parse(buf, STREAM_TOCLIENT)
 }
 
+#[no_mangle]
+pub extern "C" fn rs_krb5_parse_request_tcp(_flow: *const core::Flow,
+                                       state: *mut libc::c_void,
+                                       _pstate: *mut libc::c_void,
+                                       input: *const libc::uint8_t,
+                                       input_len: u32,
+                                       _data: *const libc::c_void) -> i8 {
+    if input_len < 4 { return -1; }
+    let buf = build_slice!(input,input_len as usize);
+    let state = cast_pointer!(state,KRB5State);
+    // skip the record mark
+    state.parse(&buf[4..], STREAM_TOSERVER)
+}
+
+#[no_mangle]
+pub extern "C" fn rs_krb5_parse_response_tcp(_flow: *const core::Flow,
+                                       state: *mut libc::c_void,
+                                       _pstate: *mut libc::c_void,
+                                       input: *const libc::uint8_t,
+                                       input_len: u32,
+                                       _data: *const libc::c_void) -> i8 {
+    if input_len < 4 { return -1; }
+    let buf = build_slice!(input,input_len as usize);
+    let state = cast_pointer!(state,KRB5State);
+    // skip the record mark
+    state.parse(&buf[4..], STREAM_TOCLIENT)
+}
+
 
 const PARSER_NAME : &'static [u8] = b"krb5\0";
 
 #[no_mangle]
 pub unsafe extern "C" fn rs_register_krb5_parser() {
     let default_port = CString::new("88").unwrap();
-    let parser = RustParser {
+    let mut parser = RustParser {
         name              : PARSER_NAME.as_ptr() as *const libc::c_char,
         default_port      : default_port.as_ptr(),
         ipproto           : libc::IPPROTO_UDP,
@@ -469,6 +515,7 @@ pub unsafe extern "C" fn rs_register_krb5_parser() {
         set_tx_mpm_id     : None,
         get_files         : None,
     };
+    // register UDP parser
     let ip_proto_str = CString::new("udp").unwrap();
     if AppLayerProtoDetectConfProtoDetectionEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
         let alproto = AppLayerRegisterProtocolDetection(&parser, 1);
@@ -478,6 +525,23 @@ pub unsafe extern "C" fn rs_register_krb5_parser() {
             let _ = AppLayerRegisterParser(&parser, alproto);
         }
     } else {
-        SCLogDebug!("Protocol detecter and parser disabled for KRB5.");
+        SCLogDebug!("Protocol detecter and parser disabled for KRB5/UDP.");
+    }
+    // register TCP parser
+    parser.ipproto = libc::IPPROTO_TCP;
+    parser.probe_ts = rs_krb5_probing_parser_tcp;
+    parser.probe_tc = rs_krb5_probing_parser_tcp;
+    parser.parse_ts = rs_krb5_parse_request_tcp;
+    parser.parse_tc = rs_krb5_parse_response_tcp;
+    let ip_proto_str = CString::new("tcp").unwrap();
+    if AppLayerProtoDetectConfProtoDetectionEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
+        let alproto = AppLayerRegisterProtocolDetection(&parser, 1);
+        // store the allocated ID for the probe function
+        ALPROTO_KRB5 = alproto;
+        if AppLayerParserConfParserEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
+            let _ = AppLayerRegisterParser(&parser, alproto);
+        }
+    } else {
+        SCLogDebug!("Protocol detecter and parser disabled for KRB5/TCP.");
     }
 }
index 84b592c48e6f09ea1e750460d0d6ece4d19cd3e8..08ddb109bf582476fcf3e7f2235906de2d8695b5 100644 (file)
@@ -128,6 +128,7 @@ static OutputInitResult OutputKRB5LogInitSub(ConfNode *conf,
 
     SCLogDebug("KRB5 log sub-module initialized.");
 
+    AppLayerParserRegisterLogger(IPPROTO_TCP, ALPROTO_KRB5);
     AppLayerParserRegisterLogger(IPPROTO_UDP, ALPROTO_KRB5);
 
     result.ctx = output_ctx;