]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
Add Kerberos 5 application layer
authorPierre Chifflier <chifflier@wzdftpd.net>
Mon, 16 Apr 2018 06:15:02 +0000 (08:15 +0200)
committerPierre Chifflier <chifflier@wzdftpd.net>
Wed, 13 Jun 2018 08:25:40 +0000 (10:25 +0200)
13 files changed:
rust/Cargo.toml.in
rust/gen-c-headers.py
rust/src/krb/krb5.rs [new file with mode: 0644]
rust/src/krb/mod.rs [new file with mode: 0644]
rust/src/lib.rs
src/Makefile.am
src/app-layer-detect-proto.c
src/app-layer-krb5.c [new file with mode: 0644]
src/app-layer-krb5.h [new file with mode: 0644]
src/app-layer-parser.c
src/app-layer-protos.c
src/app-layer-protos.h
suricata.yaml.in

index bddfebf4b0a406ace34b20b71ee0415b8f7427fd..5e3a411ce682b0300f77fb917300fe37b43ae9fe 100644 (file)
@@ -19,7 +19,7 @@ nom = "~3.2.1"
 libc = "^0.2.36"
 crc = "~1.7.0"
 der-parser = "0.5.2"
-kerberos-parser = "0.1.0"
+kerberos-parser = "0.1.2"
 
 ntp-parser = "0.2.0"
 ipsec-parser = "~0.3.0"
index d5b61bd2f8aa0106acca6e41dcce23e09416c05e..aa7d59d1c292ff5a469aa1428092aefc304a2311 100755 (executable)
@@ -86,6 +86,8 @@ type_map = {
     "SMBTransaction": "SMBTransaction",
     "IKEV2State": "IKEV2State",
     "IKEV2Transaction": "IKEV2Transaction",
+    "KRB5State": "KRB5State",
+    "KRB5Transaction": "KRB5Transaction",
     "JsonT": "json_t",
     "DetectEngineState": "DetectEngineState",
     "core::DetectEngineState": "DetectEngineState",
diff --git a/rust/src/krb/krb5.rs b/rust/src/krb/krb5.rs
new file mode 100644 (file)
index 0000000..1b2fa4f
--- /dev/null
@@ -0,0 +1,475 @@
+/* Copyright (C) 2017-2018 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 libc;
+use std;
+use std::ffi::{CStr,CString};
+use nom::IResult;
+use der_parser::der_read_element_header;
+use kerberos_parser::krb5_parser;
+use kerberos_parser::krb5::{EncryptionType,MessageType,PrincipalName,Realm};
+use applayer;
+use core;
+use core::{AppProto,Flow,ALPROTO_FAILED,ALPROTO_UNKNOWN,STREAM_TOCLIENT,STREAM_TOSERVER,sc_detect_engine_state_free};
+use parser::*;
+
+use log::*;
+
+#[repr(u32)]
+pub enum KRB5Event {
+    MalformedData = 0,
+    WeakCrypto,
+}
+
+pub struct KRB5State {
+    pub req_id: u8,
+
+    /// List of transactions for this session
+    transactions: Vec<KRB5Transaction>,
+
+    /// tx counter for assigning incrementing id's to tx's
+    tx_id: u64,
+}
+
+pub struct KRB5Transaction {
+    /// The message type: AS-REQ, AS-REP, etc.
+    pub msg_type: MessageType,
+
+    /// The client PrincipalName, if present
+    pub cname: Option<PrincipalName>,
+    /// The server Realm, if present
+    pub realm: Option<Realm>,
+    /// The server PrincipalName, if present
+    pub sname: Option<PrincipalName>,
+
+    /// Encryption used (only in AS-REP and TGS-REP)
+    pub etype: Option<EncryptionType>,
+
+    /// The internal transaction id
+    id: u64,
+
+    /// The detection engine state, if present
+    de_state: Option<*mut core::DetectEngineState>,
+
+    /// The events associated with this transaction
+    events: *mut core::AppLayerDecoderEvents,
+
+    logged: applayer::LoggerFlags,
+}
+
+pub fn to_hex_string(bytes: &[u8]) -> String {
+    let mut s = String::new();
+    for &b in bytes {
+        s.push_str(&format!("{:02X}", b));
+    }
+    s
+}
+
+impl KRB5State {
+    pub fn new() -> KRB5State {
+        KRB5State{
+            req_id: 0,
+            transactions: Vec::new(),
+            tx_id: 0,
+        }
+    }
+
+    /// Parse a Kerberos request message
+    ///
+    /// Returns The number of messages parsed, or -1 on error
+    fn parse(&mut self, i: &[u8], _direction: u8) -> i8 {
+        match der_read_element_header(i) {
+            IResult::Done(_rem,hdr) => {
+                // Kerberos messages start with an APPLICATION header
+                if hdr.class != 0b01 { return 1; }
+                match hdr.tag {
+                    10 => {
+                        self.req_id = hdr.tag;
+                    },
+                    11 => {
+                        let res = krb5_parser::parse_as_rep(i);
+                        res.map(|kdc_rep| {
+                            let mut tx = self.new_tx();
+                            tx.msg_type = MessageType::KRB_AS_REP;
+                            tx.cname = Some(kdc_rep.cname);
+                            tx.realm = Some(kdc_rep.crealm);
+                            tx.sname = Some(kdc_rep.ticket.sname);
+                            tx.etype = Some(kdc_rep.enc_part.etype);
+                            self.transactions.push(tx);
+                            self.check_crypto(kdc_rep.enc_part.etype);
+                        });
+                        self.req_id = 0;
+                    },
+                    12 => {
+                        self.req_id = hdr.tag;
+                    },
+                    13 => {
+                        let res = krb5_parser::parse_tgs_rep(i);
+                        res.map(|kdc_rep| {
+                            let mut tx = self.new_tx();
+                            tx.msg_type = MessageType::KRB_TGS_REP;
+                            tx.cname = Some(kdc_rep.cname);
+                            tx.realm = Some(kdc_rep.crealm);
+                            tx.sname = Some(kdc_rep.ticket.sname);
+                            tx.etype = Some(kdc_rep.enc_part.etype);
+                            self.transactions.push(tx);
+                            self.check_crypto(kdc_rep.enc_part.etype);
+                        });
+                        self.req_id = 0;
+                    },
+                    14 => {
+                        self.req_id = hdr.tag;
+                    },
+                    15 => {
+                        self.req_id = 0;
+                    },
+                    30 => {
+                        self.req_id = 0;
+                    },
+                    _ => { SCLogDebug!("unknown/unsupported tag {}", hdr.tag); },
+                }
+                0
+            },
+            IResult::Incomplete(_) => {
+                SCLogDebug!("Insufficient data while parsing KRB5 data");
+                self.set_event(KRB5Event::MalformedData);
+                -1
+            },
+            IResult::Error(_) => {
+                SCLogDebug!("Error while parsing KRB5 data");
+                self.set_event(KRB5Event::MalformedData);
+                -1
+            },
+        }
+    }
+
+    fn check_crypto(&mut self, alg:EncryptionType) {
+        match alg {
+            EncryptionType::AES128_CTS_HMAC_SHA1_96 |
+            EncryptionType::AES256_CTS_HMAC_SHA1_96 |
+            EncryptionType::AES128_CTS_HMAC_SHA256_128 |
+            EncryptionType::AES256_CTS_HMAC_SHA384_192 |
+            EncryptionType::CAMELLIA128_CTS_CMAC |
+            EncryptionType::CAMELLIA256_CTS_CMAC => (),
+            _ => { // all other ciphers are weak or deprecated
+                SCLogDebug!("Kerberos5: weak encryption {:?}", alg);
+                self.set_event(KRB5Event::WeakCrypto);
+            }
+        }
+    }
+
+    pub fn free(&mut self) {
+        // All transactions are freed when the `transactions` object is freed.
+        // But let's be explicit
+        self.transactions.clear();
+    }
+
+    fn new_tx(&mut self) -> KRB5Transaction {
+        self.tx_id += 1;
+        KRB5Transaction::new(self.tx_id)
+    }
+
+    fn get_tx_by_id(&mut self, tx_id: u64) -> Option<&KRB5Transaction> {
+        self.transactions.iter().find(|&tx| tx.id == tx_id + 1)
+    }
+
+    fn free_tx(&mut self, tx_id: u64) {
+        let tx = self.transactions.iter().position(|ref tx| tx.id == tx_id + 1);
+        debug_assert!(tx != None);
+        if let Some(idx) = tx {
+            let _ = self.transactions.remove(idx);
+        }
+    }
+
+    /// Set an event. The event is set on the most recent transaction.
+    fn set_event(&mut self, event: KRB5Event) {
+        if let Some(tx) = self.transactions.last_mut() {
+            let ev = event as u8;
+            core::sc_app_layer_decoder_events_set_event_raw(&mut tx.events, ev);
+        }
+    }
+}
+
+impl KRB5Transaction {
+    pub fn new(id: u64) -> KRB5Transaction {
+        KRB5Transaction{
+            msg_type: MessageType(0),
+            cname: None,
+            realm: None,
+            sname: None,
+            etype: None,
+            id: id,
+            de_state: None,
+            events: std::ptr::null_mut(),
+            logged: applayer::LoggerFlags::new(),
+        }
+    }
+}
+
+impl Drop for KRB5Transaction {
+    fn drop(&mut self) {
+        if self.events != std::ptr::null_mut() {
+            core::sc_app_layer_decoder_events_free_events(&mut self.events);
+        }
+        if let Some(state) = self.de_state {
+            sc_detect_engine_state_free(state);
+        }
+    }
+}
+
+
+
+
+/// Returns *mut KRB5State
+#[no_mangle]
+pub extern "C" fn rs_krb5_state_new() -> *mut libc::c_void {
+    let state = KRB5State::new();
+    let boxed = Box::new(state);
+    return unsafe{std::mem::transmute(boxed)};
+}
+
+/// Params:
+/// - state: *mut KRB5State as void pointer
+#[no_mangle]
+pub extern "C" fn rs_krb5_state_free(state: *mut libc::c_void) {
+    // Just unbox...
+    let mut state: Box<KRB5State> = unsafe{std::mem::transmute(state)};
+    state.free();
+}
+
+#[no_mangle]
+pub extern "C" fn rs_krb5_state_get_tx(state: *mut libc::c_void,
+                                      tx_id: libc::uint64_t)
+                                      -> *mut libc::c_void
+{
+    let state = cast_pointer!(state,KRB5State);
+    match state.get_tx_by_id(tx_id) {
+        Some(tx) => unsafe{std::mem::transmute(tx)},
+        None     => std::ptr::null_mut(),
+    }
+}
+
+#[no_mangle]
+pub extern "C" fn rs_krb5_state_get_tx_count(state: *mut libc::c_void)
+                                            -> libc::uint64_t
+{
+    let state = cast_pointer!(state,KRB5State);
+    state.tx_id
+}
+
+#[no_mangle]
+pub extern "C" fn rs_krb5_state_tx_free(state: *mut libc::c_void,
+                                       tx_id: libc::uint64_t)
+{
+    let state = cast_pointer!(state,KRB5State);
+    state.free_tx(tx_id);
+}
+
+#[no_mangle]
+pub extern "C" fn rs_krb5_state_progress_completion_status(
+    _direction: libc::uint8_t)
+    -> libc::c_int
+{
+    return 1;
+}
+
+#[no_mangle]
+pub extern "C" fn rs_krb5_tx_get_alstate_progress(_tx: *mut libc::c_void,
+                                                 _direction: libc::uint8_t)
+                                                 -> libc::c_int
+{
+    1
+}
+
+#[no_mangle]
+pub extern "C" fn rs_krb5_tx_set_logged(_state: *mut libc::c_void,
+                                       tx: *mut libc::c_void,
+                                       logged: libc::uint32_t)
+{
+    let tx = cast_pointer!(tx,KRB5Transaction);
+    tx.logged.set(logged);
+}
+
+#[no_mangle]
+pub extern "C" fn rs_krb5_tx_get_logged(_state: *mut libc::c_void,
+                                       tx: *mut libc::c_void)
+                                       -> u32
+{
+    let tx = cast_pointer!(tx,KRB5Transaction);
+    return tx.logged.get();
+}
+
+
+#[no_mangle]
+pub extern "C" fn rs_krb5_state_set_tx_detect_state(
+    tx: *mut libc::c_void,
+    de_state: &mut core::DetectEngineState) -> libc::c_int
+{
+    let tx = cast_pointer!(tx,KRB5Transaction);
+    tx.de_state = Some(de_state);
+    0
+}
+
+#[no_mangle]
+pub extern "C" fn rs_krb5_state_get_tx_detect_state(
+    tx: *mut libc::c_void)
+    -> *mut core::DetectEngineState
+{
+    let tx = cast_pointer!(tx,KRB5Transaction);
+    match tx.de_state {
+        Some(ds) => ds,
+        None => std::ptr::null_mut(),
+    }
+}
+
+
+#[no_mangle]
+pub extern "C" fn rs_krb5_state_get_events(state: *mut libc::c_void,
+                                          tx_id: libc::uint64_t)
+                                          -> *mut core::AppLayerDecoderEvents
+{
+    let state = cast_pointer!(state,KRB5State);
+    match state.get_tx_by_id(tx_id) {
+        Some(tx) => tx.events,
+        _        => std::ptr::null_mut(),
+    }
+}
+
+#[no_mangle]
+pub extern "C" fn rs_krb5_state_get_event_info(event_name: *const libc::c_char,
+                                              event_id: *mut libc::c_int,
+                                              event_type: *mut core::AppLayerEventType)
+                                              -> libc::c_int
+{
+    if event_name == std::ptr::null() { return -1; }
+    let c_event_name: &CStr = unsafe { CStr::from_ptr(event_name) };
+    let event = match c_event_name.to_str() {
+        Ok(s) => {
+            match s {
+                "malformed_data"     => KRB5Event::MalformedData as i32,
+                _                    => -1, // unknown event
+            }
+        },
+        Err(_) => -1, // UTF-8 conversion failed
+    };
+    unsafe{
+        *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION;
+        *event_id = event as libc::c_int;
+    };
+    0
+}
+static mut ALPROTO_KRB5 : AppProto = ALPROTO_UNKNOWN;
+
+#[no_mangle]
+pub extern "C" fn rs_krb5_probing_parser(_flow: *const Flow, input:*const libc::uint8_t, input_len: u32, _offset: *const u32) -> AppProto {
+    let slice = build_slice!(input,input_len as usize);
+    let alproto = unsafe{ ALPROTO_KRB5 };
+    if slice.len() <= 10 { return unsafe{ALPROTO_FAILED}; }
+    match der_read_element_header(slice) {
+        IResult::Done(rem, ref hdr) => {
+            // Kerberos messages start with an APPLICATION header
+            if hdr.class != 0b01 { return unsafe{ALPROTO_FAILED}; }
+            // Tag number should be <= 30
+            if hdr.tag >= 30 { return unsafe{ALPROTO_FAILED}; }
+            // Kerberos messages contain sequences
+            if rem.is_empty() || rem[0] != 0x30 { return unsafe{ALPROTO_FAILED}; }
+            // XXX check kerberos version ?
+            // SCLogInfo!("probe hdr: {:?}", hdr);
+            return alproto;
+        },
+        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,
+                                       _pstate: *mut libc::c_void,
+                                       input: *const libc::uint8_t,
+                                       input_len: u32,
+                                       _data: *const libc::c_void) -> i8 {
+    let buf = build_slice!(input,input_len as usize);
+    let state = cast_pointer!(state,KRB5State);
+    state.parse(buf, STREAM_TOSERVER)
+}
+
+#[no_mangle]
+pub extern "C" fn rs_krb5_parse_response(_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 {
+    let buf = build_slice!(input,input_len as usize);
+    let state = cast_pointer!(state,KRB5State);
+    state.parse(buf, 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 {
+        name              : PARSER_NAME.as_ptr() as *const libc::c_char,
+        default_port      : default_port.as_ptr(),
+        ipproto           : libc::IPPROTO_UDP,
+        probe_ts          : rs_krb5_probing_parser,
+        probe_tc          : rs_krb5_probing_parser,
+        min_depth         : 0,
+        max_depth         : 16,
+        state_new         : rs_krb5_state_new,
+        state_free        : rs_krb5_state_free,
+        tx_free           : rs_krb5_state_tx_free,
+        parse_ts          : rs_krb5_parse_request,
+        parse_tc          : rs_krb5_parse_response,
+        get_tx_count      : rs_krb5_state_get_tx_count,
+        get_tx            : rs_krb5_state_get_tx,
+        tx_get_comp_st    : rs_krb5_state_progress_completion_status,
+        tx_get_progress   : rs_krb5_tx_get_alstate_progress,
+        get_tx_logged     : Some(rs_krb5_tx_get_logged),
+        set_tx_logged     : Some(rs_krb5_tx_set_logged),
+        get_de_state      : rs_krb5_state_get_tx_detect_state,
+        set_de_state      : rs_krb5_state_set_tx_detect_state,
+        get_events        : Some(rs_krb5_state_get_events),
+        get_eventinfo     : Some(rs_krb5_state_get_event_info),
+        localstorage_new  : None,
+        localstorage_free : None,
+        get_tx_mpm_id     : None,
+        set_tx_mpm_id     : None,
+        get_files         : None,
+    };
+    let ip_proto_str = CString::new("udp").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.");
+    }
+}
diff --git a/rust/src/krb/mod.rs b/rust/src/krb/mod.rs
new file mode 100644 (file)
index 0000000..735c71c
--- /dev/null
@@ -0,0 +1,20 @@
+/* Copyright (C) 2017-2018 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>
+
+pub mod krb5;
index 5e4689e9439f25207045490041dec8147fd3f12a..0a6e0652cca933fc367d72b7e0f0dd100dc9055f 100644 (file)
@@ -49,6 +49,7 @@ pub mod dns;
 pub mod nfs;
 pub mod ftp;
 pub mod smb;
+pub mod krb;
 
 pub mod ikev2;
 
index 6c40e7742a4525acd5ec8bbe3ea92c2c7ba8290d..5cb872a0344f08547b5dc9db9ced9e6236c5aaac 100644 (file)
@@ -47,6 +47,7 @@ app-layer-ntp.c app-layer-ntp.h \
 app-layer-register.c app-layer-register.h \
 app-layer-tftp.c app-layer-tftp.h \
 app-layer-ikev2.c app-layer-ikev2.h \
+app-layer-krb5.c app-layer-krb5.h \
 app-layer-template.c app-layer-template.h \
 app-layer-ssh.c app-layer-ssh.h \
 app-layer-ssl.c app-layer-ssl.h \
index 2cfeaaa92adda110c58d9917cc0dd116185f254a..6ef06d3083ac32e679933307cd1ac94d31ccc8af 100644 (file)
@@ -727,6 +727,8 @@ static void AppLayerProtoDetectPrintProbingParsers(AppLayerProtoDetectProbingPar
                         printf("            alproto: ALPROTO_TFTP\n");
                     else if (pp_pe->alproto == ALPROTO_IKEV2)
                         printf("            alproto: ALPROTO_IKEV2\n");
+                    else if (pp_pe->alproto == ALPROTO_KRB5)
+                        printf("            alproto: ALPROTO_KRB5\n");
                     else if (pp_pe->alproto == ALPROTO_TEMPLATE)
                         printf("            alproto: ALPROTO_TEMPLATE\n");
                     else if (pp_pe->alproto == ALPROTO_DNP3)
@@ -794,6 +796,8 @@ static void AppLayerProtoDetectPrintProbingParsers(AppLayerProtoDetectProbingPar
                     printf("            alproto: ALPROTO_TFTP\n");
                 else if (pp_pe->alproto == ALPROTO_IKEV2)
                     printf("            alproto: ALPROTO_IKEV2\n");
+                else if (pp_pe->alproto == ALPROTO_KRB5)
+                    printf("            alproto: ALPROTO_KRB5\n");
                 else if (pp_pe->alproto == ALPROTO_TEMPLATE)
                     printf("            alproto: ALPROTO_TEMPLATE\n");
                 else if (pp_pe->alproto == ALPROTO_DNP3)
diff --git a/src/app-layer-krb5.c b/src/app-layer-krb5.c
new file mode 100644 (file)
index 0000000..66777f6
--- /dev/null
@@ -0,0 +1,66 @@
+/* Copyright (C) 2015 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.
+ */
+
+/**
+ * \file
+ *
+ * \author Pierre Chifflier <chifflier@wzdftpd.net>
+ *
+ * Parser for Kerberos v5 application layer running on UDP port 88.
+ */
+
+#include "suricata-common.h"
+#include "stream.h"
+#include "conf.h"
+
+#include "util-unittest.h"
+
+#include "app-layer-detect-proto.h"
+#include "app-layer-parser.h"
+
+#include "app-layer-krb5.h"
+
+#ifdef HAVE_RUST
+
+#include "rust-krb-krb5-gen.h"
+
+void RegisterKRB5Parsers(void)
+{
+    rs_register_krb5_parser();
+
+#ifdef UNITTESTS
+    AppLayerParserRegisterProtocolUnittests(IPPROTO_TCP, ALPROTO_KRB5,
+        KRB5ParserRegisterTests);
+#endif
+}
+
+#ifdef UNITTESTS
+#endif
+
+void KRB5ParserRegisterTests(void)
+{
+#ifdef UNITTESTS
+#endif
+}
+
+#else /* HAVE_RUST */
+
+void RegisterKRB5Parsers(void)
+{
+}
+
+#endif /* HAVE_RUST */
diff --git a/src/app-layer-krb5.h b/src/app-layer-krb5.h
new file mode 100644 (file)
index 0000000..19968fc
--- /dev/null
@@ -0,0 +1,34 @@
+/* Copyright (C) 2015 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.
+ */
+
+/**
+ * \file
+ *
+ * \author Pierre Chifflier <chifflier@wzdftpd.net>
+ */
+
+#ifndef __APP_LAYER_KRB5_H__
+#define __APP_LAYER_KRB5_H__
+
+void RegisterKRB5Parsers(void);
+void KRB5ParserRegisterTests(void);
+
+/** Opaque Rust types. */
+typedef struct KRB5State_ KRB5State;
+typedef struct KRB5Transaction_ KRB5Transaction;
+
+#endif /* __APP_LAYER_KRB5_H__ */
index 8707ac270faecf037a5ff8bdd528d7569c7a7b6f..0587a12a930a8b1259f3ec56e1d034015cf723fd 100644 (file)
@@ -65,6 +65,7 @@
 #include "app-layer-ntp.h"
 #include "app-layer-tftp.h"
 #include "app-layer-ikev2.h"
+#include "app-layer-krb5.h"
 #include "app-layer-template.h"
 
 #include "conf.h"
@@ -1452,6 +1453,7 @@ void AppLayerParserRegisterProtocolParsers(void)
     RegisterNTPParsers();
     RegisterTFTPParsers();
     RegisterIKEV2Parsers();
+    RegisterKRB5Parsers();
     RegisterTemplateParsers();
 
     /** IMAP */
index 14dc1f704ae86f129364664f78840145f76122ef..e8c199a8463cc4bb42f874d7a78d53da535261d6 100644 (file)
@@ -96,6 +96,9 @@ const char *AppProtoToString(AppProto alproto)
         case ALPROTO_IKEV2:
             proto_name = "ikev2";
             break;
+        case ALPROTO_KRB5:
+            proto_name = "krb5";
+            break;
         case ALPROTO_TEMPLATE:
             proto_name = "template";
             break;
@@ -136,6 +139,7 @@ AppProto StringToAppProto(const char *proto_name)
     if (strcmp(proto_name,"nfs")==0) return ALPROTO_NFS;
     if (strcmp(proto_name,"ntp")==0) return ALPROTO_NTP;
     if (strcmp(proto_name,"ikev2")==0) return ALPROTO_IKEV2;
+    if (strcmp(proto_name,"krb5")==0) return ALPROTO_KRB5;
     if (strcmp(proto_name,"template")==0) return ALPROTO_TEMPLATE;
     if (strcmp(proto_name,"failed")==0) return ALPROTO_FAILED;
 
index 3293e71d25e0d54caee361bffc6708a55a81b143..466f6ed96e3a662dfaf48d25a805fa8d07388f2e 100644 (file)
@@ -49,6 +49,7 @@ enum AppProtoEnum {
     ALPROTO_FTPDATA,
     ALPROTO_TFTP,
     ALPROTO_IKEV2,
+    ALPROTO_KRB5,
     ALPROTO_TEMPLATE,
 
     /* used by the probing parser when alproto detection fails
index 47922e96872affc779bb10b4b6a9e8f336eef808..ec951f290f4b5e48d2fcfa13891fd4a565424441 100644 (file)
@@ -808,6 +808,8 @@ pcap-file:
 # "detection-only" enables protocol detection only (parser disabled).
 app-layer:
   protocols:
+    krb5:
+      enabled: @rust_config_enabled@
     ikev2:
       enabled: yes
     tls: