red_smb 0.0.3

Library to play with SMB
Documentation
use crate::smb2::Smb2NegResp;
use crate::smb2::Smb2NegReq;
use crate::smb2::Smb2SessionSetupResp;
use crate::smb2::Smb2SessionSetupReq;
use crate::SmbNegResp;
use crate::Error;
use crate::smb1::Smb1NegReq;
use crate::SmbMsg;
use crate::smb2::Smb2Msg;
use crate::Result;
use std::io;
use std::io::{Read, Write};
use std::net::TcpStream;

pub const SMB_TCP_PORT: u16 = 445;

/// Sends a raw SMB request over TCP and receives the response.
pub fn send_recv(
    stream: &mut TcpStream,
    raw_req: &[u8],
) -> io::Result<Vec<u8>> {
    let req_len = (raw_req.len() as u32) & 0x00ffffff;

    let mut bytes = req_len.to_be_bytes().to_vec();
    bytes.extend(raw_req);
    stream.write(&bytes)?;

    let mut resp_len_bytes = [0 as u8; 4];
    stream.read_exact(&mut resp_len_bytes)?;
    let resp_len = u32::from_be_bytes(resp_len_bytes) & 0x00ffffff;

    let mut raw_resp: Vec<u8> = vec![0; resp_len as usize];
    stream.read_exact(&mut raw_resp)?;

    return Ok(raw_resp);
}

/// Sends a SMB packet and receives the response packet.
pub fn send_recv_msg(
    stream: &mut TcpStream,
    req_packet: &SmbMsg,
) -> Result<SmbMsg> {
    let raw_resp = send_recv(stream, &req_packet.build())?;
    return SmbMsg::parse(&raw_resp);
}

pub fn send_recv_negotiate_msg(
    stream: &mut TcpStream,
    req_neg: &Smb1NegReq,
) -> Result<SmbNegResp> {
    let raw_resp = send_recv(stream, &req_neg.build())?;

    let resp_msg = SmbMsg::parse(&raw_resp)?;

    match resp_msg {
        SmbMsg::V1(_) => {
            todo!("SMB1 Negotiation response")
        },
        SmbMsg::V2(msg2) => {
            match msg2 {
                Smb2Msg::NegResp(msg) => Ok(SmbNegResp::V2(msg)),
                _ => Err(Error::Smb2UnexpectedResponse(msg2)),
            }
        }
    }
}


/// Sends a SMB2 request and receives the response.
pub fn send_recv_msg2(
    stream: &mut TcpStream,
    req_packet: &Smb2Msg,
) -> Result<Smb2Msg> {
    let raw_resp = send_recv(stream, &req_packet.build())?;
    return Smb2Msg::parse(&raw_resp);
}

pub fn send_recv_negotiate2(
    stream: &mut TcpStream,
    req: &Smb2NegReq,
) -> Result<Smb2NegResp> {
    let raw_resp = send_recv(stream, &req.build())?;

    let resp_msg =  Smb2Msg::parse(&raw_resp)?;
    match resp_msg {
        Smb2Msg::NegResp(msg) => Ok(msg),
        _ => Err(Error::Smb2UnexpectedResponse(resp_msg))
    }
}


pub fn send_recv_session_setup2(
    stream: &mut TcpStream,
    req: &Smb2SessionSetupReq,
) -> Result<Smb2SessionSetupResp> {
    let raw_resp = send_recv(stream, &req.build())?;

    let resp_msg =  Smb2Msg::parse(&raw_resp)?;
    match resp_msg {
        Smb2Msg::SessionSetupResp(msg) => Ok(msg),
        _ => Err(Error::Smb2UnexpectedResponse(resp_msg))
    }
}