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