]> git.ipfire.org Git - people/ms/suricata.git/blame - rust/src/krb/krb5.rs
app-layer: include decoder events in app-layer tx data
[people/ms/suricata.git] / rust / src / krb / krb5.rs
CommitLineData
2f5834cd 1/* Copyright (C) 2017-2020 Open Information Security Foundation
77f0c11c
PC
2 *
3 * You can copy, redistribute or modify this Program under the terms of
4 * the GNU General Public License version 2 as published by the Free
5 * Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * version 2 along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18// written by Pierre Chifflier <chifflier@wzdftpd.net>
19
77f0c11c 20use std;
e92cb36b 21use std::ffi::CString;
13b73997 22use nom;
f3ddd712 23use nom::IResult;
44250067 24use nom::number::streaming::be_u32;
5b809f77 25use der_parser::der::der_read_element_header;
6b8517dc 26use der_parser::ber::BerClass;
77f0c11c 27use kerberos_parser::krb5_parser;
3a017f61 28use kerberos_parser::krb5::{EncryptionType,ErrorCode,MessageType,PrincipalName,Realm};
2f5834cd 29use crate::applayer::{self, *};
9c67c634
JI
30use crate::core;
31use crate::core::{AppProto,Flow,ALPROTO_FAILED,ALPROTO_UNKNOWN,Direction};
77f0c11c 32
e92cb36b 33#[derive(AppLayerEvent)]
77f0c11c 34pub enum KRB5Event {
e92cb36b 35 MalformedData,
50370511 36 WeakEncryption,
77f0c11c
PC
37}
38
39pub struct KRB5State {
40 pub req_id: u8,
41
e9ae62ed
PC
42 pub record_ts: usize,
43 pub defrag_buf_ts: Vec<u8>,
44 pub record_tc: usize,
45 pub defrag_buf_tc: Vec<u8>,
46
77f0c11c
PC
47 /// List of transactions for this session
48 transactions: Vec<KRB5Transaction>,
49
50 /// tx counter for assigning incrementing id's to tx's
51 tx_id: u64,
52}
53
238ec953
JI
54impl State<KRB5Transaction> for KRB5State {
55 fn get_transactions(&self) -> &[KRB5Transaction] {
56 &self.transactions
57 }
58}
59
77f0c11c
PC
60pub struct KRB5Transaction {
61 /// The message type: AS-REQ, AS-REP, etc.
62 pub msg_type: MessageType,
63
64 /// The client PrincipalName, if present
65 pub cname: Option<PrincipalName>,
66 /// The server Realm, if present
67 pub realm: Option<Realm>,
68 /// The server PrincipalName, if present
69 pub sname: Option<PrincipalName>,
70
71 /// Encryption used (only in AS-REP and TGS-REP)
72 pub etype: Option<EncryptionType>,
73
52f5c791 74 /// Error code, if request has failed
3a017f61 75 pub error_code: Option<ErrorCode>,
52f5c791 76
77f0c11c
PC
77 /// The internal transaction id
78 id: u64,
79
9f29366c 80 tx_data: applayer::AppLayerTxData,
77f0c11c
PC
81}
82
238ec953
JI
83impl Transaction for KRB5Transaction {
84 fn id(&self) -> u64 {
85 self.id
86 }
87}
88
77f0c11c
PC
89pub fn to_hex_string(bytes: &[u8]) -> String {
90 let mut s = String::new();
91 for &b in bytes {
92 s.push_str(&format!("{:02X}", b));
93 }
94 s
95}
96
97impl KRB5State {
98 pub fn new() -> KRB5State {
99 KRB5State{
100 req_id: 0,
e9ae62ed
PC
101 record_ts: 0,
102 defrag_buf_ts: Vec::new(),
103 record_tc: 0,
104 defrag_buf_tc: Vec::new(),
77f0c11c
PC
105 transactions: Vec::new(),
106 tx_id: 0,
107 }
108 }
109
110 /// Parse a Kerberos request message
111 ///
44d3f264 112 /// Returns 0 in case of success, or -1 on error
209e2f17 113 fn parse(&mut self, i: &[u8], _direction: Direction) -> i32 {
77f0c11c 114 match der_read_element_header(i) {
13b73997 115 Ok((_rem,hdr)) => {
77f0c11c 116 // Kerberos messages start with an APPLICATION header
6b8517dc 117 if hdr.class != BerClass::Application { return 0; }
5b809f77 118 match hdr.tag.0 {
77f0c11c 119 10 => {
5b809f77 120 self.req_id = 10;
77f0c11c
PC
121 },
122 11 => {
123 let res = krb5_parser::parse_as_rep(i);
13b73997 124 if let Ok((_,kdc_rep)) = res {
77f0c11c
PC
125 let mut tx = self.new_tx();
126 tx.msg_type = MessageType::KRB_AS_REP;
127 tx.cname = Some(kdc_rep.cname);
128 tx.realm = Some(kdc_rep.crealm);
129 tx.sname = Some(kdc_rep.ticket.sname);
130 tx.etype = Some(kdc_rep.enc_part.etype);
131 self.transactions.push(tx);
50370511
PC
132 if test_weak_encryption(kdc_rep.enc_part.etype) {
133 self.set_event(KRB5Event::WeakEncryption);
134 }
13b73997 135 };
77f0c11c
PC
136 self.req_id = 0;
137 },
138 12 => {
5b809f77 139 self.req_id = 12;
77f0c11c
PC
140 },
141 13 => {
142 let res = krb5_parser::parse_tgs_rep(i);
13b73997 143 if let Ok((_,kdc_rep)) = res {
77f0c11c
PC
144 let mut tx = self.new_tx();
145 tx.msg_type = MessageType::KRB_TGS_REP;
146 tx.cname = Some(kdc_rep.cname);
147 tx.realm = Some(kdc_rep.crealm);
148 tx.sname = Some(kdc_rep.ticket.sname);
149 tx.etype = Some(kdc_rep.enc_part.etype);
150 self.transactions.push(tx);
50370511
PC
151 if test_weak_encryption(kdc_rep.enc_part.etype) {
152 self.set_event(KRB5Event::WeakEncryption);
153 }
13b73997 154 };
77f0c11c
PC
155 self.req_id = 0;
156 },
157 14 => {
5b809f77 158 self.req_id = 14;
77f0c11c
PC
159 },
160 15 => {
161 self.req_id = 0;
162 },
163 30 => {
52f5c791 164 let res = krb5_parser::parse_krb_error(i);
13b73997 165 if let Ok((_,error)) = res {
52f5c791
PC
166 let mut tx = self.new_tx();
167 tx.msg_type = MessageType(self.req_id as u32);
168 tx.cname = error.cname;
169 tx.realm = error.crealm;
170 tx.sname = Some(error.sname);
171 tx.error_code = Some(error.error_code);
172 self.transactions.push(tx);
13b73997 173 };
77f0c11c
PC
174 self.req_id = 0;
175 },
176 _ => { SCLogDebug!("unknown/unsupported tag {}", hdr.tag); },
177 }
178 0
179 },
13b73997 180 Err(nom::Err::Incomplete(_)) => {
77f0c11c
PC
181 SCLogDebug!("Insufficient data while parsing KRB5 data");
182 self.set_event(KRB5Event::MalformedData);
183 -1
184 },
13b73997 185 Err(_) => {
77f0c11c
PC
186 SCLogDebug!("Error while parsing KRB5 data");
187 self.set_event(KRB5Event::MalformedData);
188 -1
189 },
190 }
191 }
192
77f0c11c
PC
193 pub fn free(&mut self) {
194 // All transactions are freed when the `transactions` object is freed.
195 // But let's be explicit
196 self.transactions.clear();
197 }
198
199 fn new_tx(&mut self) -> KRB5Transaction {
200 self.tx_id += 1;
201 KRB5Transaction::new(self.tx_id)
202 }
203
204 fn get_tx_by_id(&mut self, tx_id: u64) -> Option<&KRB5Transaction> {
205 self.transactions.iter().find(|&tx| tx.id == tx_id + 1)
206 }
207
208 fn free_tx(&mut self, tx_id: u64) {
69cf5c9e 209 let tx = self.transactions.iter().position(|tx| tx.id == tx_id + 1);
77f0c11c
PC
210 debug_assert!(tx != None);
211 if let Some(idx) = tx {
212 let _ = self.transactions.remove(idx);
213 }
214 }
215
216 /// Set an event. The event is set on the most recent transaction.
217 fn set_event(&mut self, event: KRB5Event) {
218 if let Some(tx) = self.transactions.last_mut() {
7732efbe 219 tx.tx_data.set_event(event as u8);
77f0c11c
PC
220 }
221 }
222}
223
224impl KRB5Transaction {
225 pub fn new(id: u64) -> KRB5Transaction {
226 KRB5Transaction{
227 msg_type: MessageType(0),
228 cname: None,
229 realm: None,
230 sname: None,
231 etype: None,
52f5c791 232 error_code: None,
77f0c11c 233 id: id,
9f29366c 234 tx_data: applayer::AppLayerTxData::new(),
77f0c11c
PC
235 }
236 }
237}
238
50370511
PC
239/// Return true if Kerberos `EncryptionType` is weak
240pub fn test_weak_encryption(alg:EncryptionType) -> bool {
241 match alg {
242 EncryptionType::AES128_CTS_HMAC_SHA1_96 |
243 EncryptionType::AES256_CTS_HMAC_SHA1_96 |
244 EncryptionType::AES128_CTS_HMAC_SHA256_128 |
245 EncryptionType::AES256_CTS_HMAC_SHA384_192 |
246 EncryptionType::CAMELLIA128_CTS_CMAC |
247 EncryptionType::CAMELLIA256_CTS_CMAC => false,
248 _ => true, // all other ciphers are weak or deprecated
249 }
250}
251
252
77f0c11c
PC
253
254
255
256/// Returns *mut KRB5State
257#[no_mangle]
547d6c2d 258pub extern "C" fn rs_krb5_state_new(_orig_state: *mut std::os::raw::c_void, _orig_proto: AppProto) -> *mut std::os::raw::c_void {
77f0c11c
PC
259 let state = KRB5State::new();
260 let boxed = Box::new(state);
53413f2d 261 return Box::into_raw(boxed) as *mut _;
77f0c11c
PC
262}
263
264/// Params:
265/// - state: *mut KRB5State as void pointer
266#[no_mangle]
3f6624bf 267pub extern "C" fn rs_krb5_state_free(state: *mut std::os::raw::c_void) {
53413f2d 268 let mut state: Box<KRB5State> = unsafe{Box::from_raw(state as _)};
77f0c11c
PC
269 state.free();
270}
271
272#[no_mangle]
363b5f99 273pub unsafe extern "C" fn rs_krb5_state_get_tx(state: *mut std::os::raw::c_void,
bf1bd407 274 tx_id: u64)
3f6624bf 275 -> *mut std::os::raw::c_void
77f0c11c
PC
276{
277 let state = cast_pointer!(state,KRB5State);
278 match state.get_tx_by_id(tx_id) {
53413f2d 279 Some(tx) => tx as *const _ as *mut _,
77f0c11c
PC
280 None => std::ptr::null_mut(),
281 }
282}
283
284#[no_mangle]
363b5f99 285pub unsafe extern "C" fn rs_krb5_state_get_tx_count(state: *mut std::os::raw::c_void)
bf1bd407 286 -> u64
77f0c11c
PC
287{
288 let state = cast_pointer!(state,KRB5State);
289 state.tx_id
290}
291
292#[no_mangle]
363b5f99 293pub unsafe extern "C" fn rs_krb5_state_tx_free(state: *mut std::os::raw::c_void,
bf1bd407 294 tx_id: u64)
77f0c11c
PC
295{
296 let state = cast_pointer!(state,KRB5State);
297 state.free_tx(tx_id);
298}
299
77f0c11c 300#[no_mangle]
3f6624bf 301pub extern "C" fn rs_krb5_tx_get_alstate_progress(_tx: *mut std::os::raw::c_void,
bf1bd407 302 _direction: u8)
3f6624bf 303 -> std::os::raw::c_int
77f0c11c
PC
304{
305 1
306}
307
77f0c11c
PC
308static mut ALPROTO_KRB5 : AppProto = ALPROTO_UNKNOWN;
309
310#[no_mangle]
363b5f99 311pub unsafe extern "C" fn rs_krb5_probing_parser(_flow: *const Flow,
422e4892 312 _direction: u8,
bf1bd407 313 input:*const u8, input_len: u32,
422e4892
VJ
314 _rdir: *mut u8) -> AppProto
315{
77f0c11c 316 let slice = build_slice!(input,input_len as usize);
363b5f99
JI
317 let alproto = ALPROTO_KRB5;
318 if slice.len() <= 10 { return ALPROTO_FAILED; }
77f0c11c 319 match der_read_element_header(slice) {
13b73997 320 Ok((rem, ref hdr)) => {
77f0c11c 321 // Kerberos messages start with an APPLICATION header
363b5f99 322 if hdr.class != BerClass::Application { return ALPROTO_FAILED; }
77f0c11c 323 // Tag number should be <= 30
363b5f99 324 if hdr.tag.0 > 30 { return ALPROTO_FAILED; }
77f0c11c 325 // Kerberos messages contain sequences
363b5f99 326 if rem.is_empty() || rem[0] != 0x30 { return ALPROTO_FAILED; }
645ba175 327 // Check kerberos version
13b73997 328 if let Ok((rem,_hdr)) = der_read_element_header(rem) {
645ba175
PC
329 if rem.len() > 5 {
330 match (rem[2],rem[3],rem[4]) {
331 // Encoding of DER integer 5 (version)
332 (2,1,5) => { return alproto; },
333 _ => (),
334 }
335 }
336 }
363b5f99 337 return ALPROTO_FAILED;
77f0c11c 338 },
13b73997 339 Err(nom::Err::Incomplete(_)) => {
77f0c11c
PC
340 return ALPROTO_UNKNOWN;
341 },
13b73997 342 Err(_) => {
363b5f99 343 return ALPROTO_FAILED;
77f0c11c
PC
344 },
345 }
346}
347
1e5f5d40 348#[no_mangle]
363b5f99 349pub unsafe extern "C" fn rs_krb5_probing_parser_tcp(_flow: *const Flow,
422e4892 350 direction: u8,
bf1bd407 351 input:*const u8, input_len: u32,
422e4892
VJ
352 rdir: *mut u8) -> AppProto
353{
1e5f5d40 354 let slice = build_slice!(input,input_len as usize);
363b5f99 355 if slice.len() <= 14 { return ALPROTO_FAILED; }
f3ddd712 356 match be_u32(slice) as IResult<&[u8],u32> {
13b73997 357 Ok((rem, record_mark)) => {
3eade88b 358 // protocol implementations forbid very large requests
363b5f99 359 if record_mark > 16384 { return ALPROTO_FAILED; }
422e4892
VJ
360 return rs_krb5_probing_parser(_flow, direction,
361 rem.as_ptr(), rem.len() as u32, rdir);
1e5f5d40 362 },
13b73997 363 Err(nom::Err::Incomplete(_)) => {
1e5f5d40
PC
364 return ALPROTO_UNKNOWN;
365 },
13b73997 366 Err(_) => {
363b5f99 367 return ALPROTO_FAILED;
1e5f5d40
PC
368 },
369 }
370}
371
77f0c11c 372#[no_mangle]
363b5f99 373pub unsafe extern "C" fn rs_krb5_parse_request(_flow: *const core::Flow,
3f6624bf
VJ
374 state: *mut std::os::raw::c_void,
375 _pstate: *mut std::os::raw::c_void,
bf1bd407 376 input: *const u8,
77f0c11c 377 input_len: u32,
3f6624bf 378 _data: *const std::os::raw::c_void,
44d3f264 379 _flags: u8) -> AppLayerResult {
77f0c11c
PC
380 let buf = build_slice!(input,input_len as usize);
381 let state = cast_pointer!(state,KRB5State);
209e2f17 382 if state.parse(buf, Direction::ToServer) < 0 {
44d3f264
VJ
383 return AppLayerResult::err();
384 }
385 AppLayerResult::ok()
77f0c11c
PC
386}
387
388#[no_mangle]
363b5f99 389pub unsafe extern "C" fn rs_krb5_parse_response(_flow: *const core::Flow,
3f6624bf
VJ
390 state: *mut std::os::raw::c_void,
391 _pstate: *mut std::os::raw::c_void,
bf1bd407 392 input: *const u8,
77f0c11c 393 input_len: u32,
3f6624bf 394 _data: *const std::os::raw::c_void,
44d3f264 395 _flags: u8) -> AppLayerResult {
77f0c11c
PC
396 let buf = build_slice!(input,input_len as usize);
397 let state = cast_pointer!(state,KRB5State);
209e2f17 398 if state.parse(buf, Direction::ToClient) < 0 {
44d3f264
VJ
399 return AppLayerResult::err();
400 }
401 AppLayerResult::ok()
77f0c11c
PC
402}
403
1e5f5d40 404#[no_mangle]
363b5f99 405pub unsafe extern "C" fn rs_krb5_parse_request_tcp(_flow: *const core::Flow,
3f6624bf
VJ
406 state: *mut std::os::raw::c_void,
407 _pstate: *mut std::os::raw::c_void,
bf1bd407 408 input: *const u8,
1e5f5d40 409 input_len: u32,
3f6624bf 410 _data: *const std::os::raw::c_void,
44d3f264 411 _flags: u8) -> AppLayerResult {
1e5f5d40
PC
412 let buf = build_slice!(input,input_len as usize);
413 let state = cast_pointer!(state,KRB5State);
e9ae62ed
PC
414
415 let mut v : Vec<u8>;
e9ae62ed
PC
416 let tcp_buffer = match state.record_ts {
417 0 => buf,
418 _ => {
419 // sanity check to avoid memory exhaustion
420 if state.defrag_buf_ts.len() + buf.len() > 100000 {
12c2d18c 421 SCLogDebug!("rs_krb5_parse_request_tcp: TCP buffer exploded {} {}",
e9ae62ed 422 state.defrag_buf_ts.len(), buf.len());
44d3f264 423 return AppLayerResult::err();
e9ae62ed
PC
424 }
425 v = state.defrag_buf_ts.split_off(0);
426 v.extend_from_slice(buf);
427 v.as_slice()
428 }
429 };
430 let mut cur_i = tcp_buffer;
431 while cur_i.len() > 0 {
432 if state.record_ts == 0 {
f3ddd712 433 match be_u32(cur_i) as IResult<&[u8],u32> {
13b73997 434 Ok((rem,record)) => {
e9ae62ed
PC
435 state.record_ts = record as usize;
436 cur_i = rem;
437 },
23f796a0
PA
438 Err(nom::Err::Incomplete(_)) => {
439 state.defrag_buf_ts.extend_from_slice(cur_i);
44d3f264 440 return AppLayerResult::ok();
23f796a0 441 }
e9ae62ed 442 _ => {
7bc3c3ac 443 SCLogDebug!("rs_krb5_parse_request_tcp: reading record mark failed!");
44d3f264 444 return AppLayerResult::err();
e9ae62ed
PC
445 }
446 }
447 }
448 if cur_i.len() >= state.record_ts {
209e2f17 449 if state.parse(cur_i, Direction::ToServer) < 0 {
44d3f264 450 return AppLayerResult::err();
e9ae62ed
PC
451 }
452 state.record_ts = 0;
453 cur_i = &cur_i[state.record_ts..];
454 } else {
455 // more fragments required
456 state.defrag_buf_ts.extend_from_slice(cur_i);
44d3f264 457 return AppLayerResult::ok();
e9ae62ed
PC
458 }
459 }
44d3f264 460 AppLayerResult::ok()
1e5f5d40
PC
461}
462
463#[no_mangle]
363b5f99 464pub unsafe extern "C" fn rs_krb5_parse_response_tcp(_flow: *const core::Flow,
3f6624bf
VJ
465 state: *mut std::os::raw::c_void,
466 _pstate: *mut std::os::raw::c_void,
bf1bd407 467 input: *const u8,
1e5f5d40 468 input_len: u32,
3f6624bf 469 _data: *const std::os::raw::c_void,
44d3f264 470 _flags: u8) -> AppLayerResult {
1e5f5d40
PC
471 let buf = build_slice!(input,input_len as usize);
472 let state = cast_pointer!(state,KRB5State);
e9ae62ed
PC
473
474 let mut v : Vec<u8>;
e9ae62ed
PC
475 let tcp_buffer = match state.record_tc {
476 0 => buf,
477 _ => {
478 // sanity check to avoid memory exhaustion
479 if state.defrag_buf_tc.len() + buf.len() > 100000 {
480 SCLogDebug!("rs_krb5_parse_response_tcp: TCP buffer exploded {} {}",
481 state.defrag_buf_tc.len(), buf.len());
44d3f264 482 return AppLayerResult::err();
e9ae62ed
PC
483 }
484 v = state.defrag_buf_tc.split_off(0);
485 v.extend_from_slice(buf);
486 v.as_slice()
487 }
488 };
489 let mut cur_i = tcp_buffer;
490 while cur_i.len() > 0 {
491 if state.record_tc == 0 {
f3ddd712 492 match be_u32(cur_i) as IResult<&[u8],_> {
13b73997 493 Ok((rem,record)) => {
e9ae62ed
PC
494 state.record_tc = record as usize;
495 cur_i = rem;
496 },
23f796a0
PA
497 Err(nom::Err::Incomplete(_)) => {
498 state.defrag_buf_tc.extend_from_slice(cur_i);
44d3f264 499 return AppLayerResult::ok();
23f796a0 500 }
e9ae62ed 501 _ => {
76dd9515 502 SCLogDebug!("reading record mark failed!");
44d3f264 503 return AppLayerResult::ok();
e9ae62ed
PC
504 }
505 }
506 }
507 if cur_i.len() >= state.record_tc {
209e2f17 508 if state.parse(cur_i, Direction::ToClient) < 0 {
44d3f264 509 return AppLayerResult::err();
e9ae62ed
PC
510 }
511 state.record_tc = 0;
512 cur_i = &cur_i[state.record_tc..];
513 } else {
514 // more fragments required
515 state.defrag_buf_tc.extend_from_slice(cur_i);
44d3f264 516 return AppLayerResult::ok();
e9ae62ed
PC
517 }
518 }
44d3f264 519 AppLayerResult::ok()
1e5f5d40
PC
520}
521
9f29366c 522export_tx_data_get!(rs_krb5_get_tx_data, KRB5Transaction);
77f0c11c
PC
523
524const PARSER_NAME : &'static [u8] = b"krb5\0";
525
526#[no_mangle]
527pub unsafe extern "C" fn rs_register_krb5_parser() {
528 let default_port = CString::new("88").unwrap();
1e5f5d40 529 let mut parser = RustParser {
12c2d18c
JL
530 name : PARSER_NAME.as_ptr() as *const std::os::raw::c_char,
531 default_port : default_port.as_ptr(),
532 ipproto : core::IPPROTO_UDP,
66632465
PA
533 probe_ts : Some(rs_krb5_probing_parser),
534 probe_tc : Some(rs_krb5_probing_parser),
12c2d18c
JL
535 min_depth : 0,
536 max_depth : 16,
537 state_new : rs_krb5_state_new,
538 state_free : rs_krb5_state_free,
539 tx_free : rs_krb5_state_tx_free,
540 parse_ts : rs_krb5_parse_request,
541 parse_tc : rs_krb5_parse_response,
542 get_tx_count : rs_krb5_state_get_tx_count,
543 get_tx : rs_krb5_state_get_tx,
efc9a7a3
VJ
544 tx_comp_st_ts : 1,
545 tx_comp_st_tc : 1,
12c2d18c 546 tx_get_progress : rs_krb5_tx_get_alstate_progress,
e92cb36b
JI
547 get_eventinfo : Some(KRB5Event::get_event_info),
548 get_eventinfo_byid : Some(KRB5Event::get_event_info_by_id),
12c2d18c
JL
549 localstorage_new : None,
550 localstorage_free : None,
12c2d18c 551 get_files : None,
238ec953 552 get_tx_iterator : Some(applayer::state_get_tx_iterator::<KRB5State, KRB5Transaction>),
c94a5e63 553 get_tx_data : rs_krb5_get_tx_data,
5665fc83 554 apply_tx_config : None,
f7dee602 555 flags : APP_LAYER_PARSER_OPT_UNIDIR_TXS,
4da0d9bd 556 truncate : None,
77f0c11c 557 };
1e5f5d40 558 // register UDP parser
77f0c11c
PC
559 let ip_proto_str = CString::new("udp").unwrap();
560 if AppLayerProtoDetectConfProtoDetectionEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
561 let alproto = AppLayerRegisterProtocolDetection(&parser, 1);
562 // store the allocated ID for the probe function
563 ALPROTO_KRB5 = alproto;
564 if AppLayerParserConfParserEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
565 let _ = AppLayerRegisterParser(&parser, alproto);
566 }
567 } else {
12c2d18c 568 SCLogDebug!("Protocol detector and parser disabled for KRB5/UDP.");
1e5f5d40
PC
569 }
570 // register TCP parser
0301ceab 571 parser.ipproto = core::IPPROTO_TCP;
66632465
PA
572 parser.probe_ts = Some(rs_krb5_probing_parser_tcp);
573 parser.probe_tc = Some(rs_krb5_probing_parser_tcp);
1e5f5d40
PC
574 parser.parse_ts = rs_krb5_parse_request_tcp;
575 parser.parse_tc = rs_krb5_parse_response_tcp;
576 let ip_proto_str = CString::new("tcp").unwrap();
577 if AppLayerProtoDetectConfProtoDetectionEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
578 let alproto = AppLayerRegisterProtocolDetection(&parser, 1);
579 // store the allocated ID for the probe function
580 ALPROTO_KRB5 = alproto;
581 if AppLayerParserConfParserEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
582 let _ = AppLayerRegisterParser(&parser, alproto);
583 }
584 } else {
12c2d18c 585 SCLogDebug!("Protocol detector and parser disabled for KRB5/TCP.");
77f0c11c
PC
586 }
587}