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