summaryrefslogtreecommitdiffstats
path: root/rust/src/smb/smb1_session.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--rust/src/smb/smb1_session.rs202
1 files changed, 202 insertions, 0 deletions
diff --git a/rust/src/smb/smb1_session.rs b/rust/src/smb/smb1_session.rs
new file mode 100644
index 0000000..c39c7ce
--- /dev/null
+++ b/rust/src/smb/smb1_session.rs
@@ -0,0 +1,202 @@
+/* Copyright (C) 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.
+ */
+
+use crate::smb::smb_records::*;
+use crate::smb::smb1_records::*;
+use crate::smb::smb::*;
+use crate::smb::events::*;
+use crate::smb::auth::*;
+
+#[derive(Debug)]
+pub struct SessionSetupRequest {
+ pub native_os: Vec<u8>,
+ pub native_lm: Vec<u8>,
+ pub primary_domain: Vec<u8>,
+}
+
+#[derive(Debug)]
+pub struct SessionSetupResponse {
+ pub native_os: Vec<u8>,
+ pub native_lm: Vec<u8>,
+}
+
+pub fn smb1_session_setup_request_host_info(r: &SmbRecord, blob: &[u8]) -> SessionSetupRequest
+{
+ if blob.len() > 1 && r.has_unicode_support() {
+ let offset = r.data.len() - blob.len();
+ let blob = if offset % 2 == 1 { &blob[1..] } else { blob };
+ let (native_os, native_lm, primary_domain) = match smb_get_unicode_string(blob) {
+ Ok((rem, n1)) => {
+ match smb_get_unicode_string(rem) {
+ Ok((rem, n2)) => {
+ match smb_get_unicode_string(rem) {
+ Ok((_, n3)) => { (n1, n2, n3) },
+ _ => { (n1, n2, Vec::new()) },
+ }
+ },
+ _ => { (n1, Vec::new(), Vec::new()) },
+ }
+ },
+ _ => { (Vec::new(), Vec::new(), Vec::new()) },
+ };
+
+ SCLogDebug!("name1 {:?} name2 {:?} name3 {:?}", native_os,native_lm,primary_domain);
+ SessionSetupRequest {
+ native_os,
+ native_lm,
+ primary_domain,
+ }
+ } else {
+ let (native_os, native_lm, primary_domain) = match smb_get_ascii_string(blob) {
+ Ok((rem, n1)) => {
+ match smb_get_ascii_string(rem) {
+ Ok((rem, n2)) => {
+ match smb_get_ascii_string(rem) {
+ Ok((_, n3)) => { (n1, n2, n3) },
+ _ => { (n1, n2, Vec::new()) },
+ }
+ },
+ _ => { (n1, Vec::new(), Vec::new()) },
+ }
+ },
+ _ => { (Vec::new(), Vec::new(), Vec::new()) },
+ };
+
+ SCLogDebug!("session_setup_request_host_info: not unicode");
+ SessionSetupRequest {
+ native_os,
+ native_lm,
+ primary_domain,
+ }
+ }
+}
+
+pub fn smb1_session_setup_response_host_info(r: &SmbRecord, blob: &[u8]) -> SessionSetupResponse
+{
+ if blob.len() > 1 && r.has_unicode_support() {
+ let offset = r.data.len() - blob.len();
+ let blob = if offset % 2 == 1 { &blob[1..] } else { blob };
+ let (native_os, native_lm) = match smb_get_unicode_string(blob) {
+ Ok((rem, n1)) => {
+ match smb_get_unicode_string(rem) {
+ Ok((_, n2)) => (n1, n2),
+ _ => { (n1, Vec::new()) },
+ }
+ },
+ _ => { (Vec::new(), Vec::new()) },
+ };
+
+ SCLogDebug!("name1 {:?} name2 {:?}", native_os,native_lm);
+ SessionSetupResponse {
+ native_os,
+ native_lm,
+ }
+ } else {
+ SCLogDebug!("session_setup_response_host_info: not unicode");
+ let (native_os, native_lm) = match smb_get_ascii_string(blob) {
+ Ok((rem, n1)) => {
+ match smb_get_ascii_string(rem) {
+ Ok((_, n2)) => (n1, n2),
+ _ => { (n1, Vec::new()) },
+ }
+ },
+ _ => { (Vec::new(), Vec::new()) },
+ };
+ SessionSetupResponse {
+ native_os,
+ native_lm,
+ }
+ }
+}
+
+pub fn smb1_session_setup_request(state: &mut SMBState, r: &SmbRecord, andx_offset: usize)
+{
+ SCLogDebug!("SMB1_COMMAND_SESSION_SETUP_ANDX user_id {}", r.user_id);
+ #[allow(clippy::single_match)]
+ match parse_smb_setup_andx_record(&r.data[andx_offset-SMB1_HEADER_SIZE..]) {
+ Ok((rem, setup)) => {
+ let hdr = SMBCommonHdr::new(SMBHDR_TYPE_HEADER,
+ r.ssn_id as u64, 0, r.multiplex_id as u64);
+ let tx = state.new_sessionsetup_tx(hdr);
+ tx.vercmd.set_smb1_cmd(r.command);
+
+ if let Some(SMBTransactionTypeData::SESSIONSETUP(ref mut td)) = tx.type_data {
+ td.request_host = Some(smb1_session_setup_request_host_info(r, rem));
+ if let Some(s) = parse_secblob(setup.sec_blob) {
+ td.ntlmssp = s.ntlmssp;
+ td.krb_ticket = s.krb;
+ if let Some(ntlm) = &td.ntlmssp {
+ if ntlm.warning {
+ tx.set_event(SMBEvent::UnusualNtlmsspOrder);
+ }
+ }
+ }
+ }
+ },
+ _ => {
+ // events.push(SMBEvent::MalformedData);
+ },
+ }
+}
+
+fn smb1_session_setup_update_tx(tx: &mut SMBTransaction, r: &SmbRecord, andx_offset: usize)
+{
+ match parse_smb_response_setup_andx_record(&r.data[andx_offset-SMB1_HEADER_SIZE..]) {
+ Ok((rem, _setup)) => {
+ if let Some(SMBTransactionTypeData::SESSIONSETUP(ref mut td)) = tx.type_data {
+ td.response_host = Some(smb1_session_setup_response_host_info(r, rem));
+ }
+ },
+ _ => {
+ tx.set_event(SMBEvent::MalformedData);
+ },
+ }
+ // update tx even if we can't parse the response
+ tx.hdr = SMBCommonHdr::from1(r, SMBHDR_TYPE_HEADER); // to overwrite ssn_id 0
+ tx.set_status(r.nt_status, r.is_dos_error);
+ tx.response_done = true;
+}
+
+pub fn smb1_session_setup_response(state: &mut SMBState, r: &SmbRecord, andx_offset: usize)
+{
+ // try exact match with session id already set (e.g. NTLMSSP AUTH phase)
+ let found = r.ssn_id != 0 && match state.get_sessionsetup_tx(
+ SMBCommonHdr::new(SMBHDR_TYPE_HEADER,
+ r.ssn_id as u64, 0, r.multiplex_id as u64))
+ {
+ Some(tx) => {
+ smb1_session_setup_update_tx(tx, r, andx_offset);
+ SCLogDebug!("smb1_session_setup_response: tx {:?}", tx);
+ true
+ },
+ None => { false },
+ };
+ // otherwise try match with ssn id 0 (e.g. NTLMSSP_NEGOTIATE)
+ if !found {
+ match state.get_sessionsetup_tx(
+ SMBCommonHdr::new(SMBHDR_TYPE_HEADER, 0, 0, r.multiplex_id as u64))
+ {
+ Some(tx) => {
+ smb1_session_setup_update_tx(tx, r, andx_offset);
+ SCLogDebug!("smb1_session_setup_response: tx {:?}", tx);
+ },
+ None => {
+ SCLogDebug!("smb1_session_setup_response: tx not found for {:?}", r);
+ },
+ }
+ }
+}