red_smb 0.0.2

Library to play with SMB
Documentation
use crate::smb2::Smb2SessionSetupResp;
use crate::smb2::header::commands::{SMB2_NEGOTIATE_PROTOCOL, SMB2_SESSION_SETUP};
use crate::smb2::Smb2Header;
use crate::smb2::Smb2NegReq;
use crate::smb2::Smb2NegResp;
use crate::smb2::Smb2SessionSetupReq;
use crate::Error;
use crate::Result;

#[derive(Clone, Debug, PartialEq)]
pub enum Smb2Msg {
    NegReq(Smb2NegReq),
    NegResp(Smb2NegResp),
    SessionSetupReq(Smb2SessionSetupReq),
    SessionSetupResp(Smb2SessionSetupResp),
}

impl Smb2Msg {

    pub fn build(&self) -> Vec<u8> {
        match self {
            Self::NegReq(b) => b.build(),
            Self::NegResp(_) => todo!(),
            Self::SessionSetupReq(b) => b.build(),
            Self::SessionSetupResp(_) => todo!(),
        }
    }

    pub fn parse(raw: &[u8]) -> Result<Self> {
        let (_, header) = Smb2Header::parse(raw)?;

        return Ok(match header.command {
            SMB2_NEGOTIATE_PROTOCOL => {
                if header.is_response() {
                    Self::NegResp(Smb2NegResp::parse(raw)?)
                } else {
                    Self::NegReq(Smb2NegReq::parse(raw)?)
                }
            }
            SMB2_SESSION_SETUP => {
                if header.is_response() {
                    Self::SessionSetupResp(Smb2SessionSetupResp::parse(raw)?)
                } else {
                    todo!()
                }
            }
            _ => return Err(Error::Smb2UnknownCommand(header.command)),
        });
    }

}

#[derive(Clone, Debug, PartialEq)]
pub struct Smb2Packet {
    pub header: Smb2Header,
    pub body: Smb2Body,
}

impl Smb2Packet {
    pub fn new(header: Smb2Header, body: Smb2Body) -> Self {
        return Self { header, body };
    }

    pub fn new_neg_req(header: Smb2Header, body: Smb2NegReq) -> Self {
        return Self::new(header, Smb2Body::NegReq(body));
    }

    pub fn new_session_setup_req(
        header: Smb2Header,
        body: Smb2SessionSetupReq,
    ) -> Self {
        return Self::new(header, Smb2Body::SessionSetupReq(body));
    }

    pub fn command(&self) -> u16 {
        return self.header.command;
    }

    pub fn build(&self) -> Vec<u8> {
        let mut raw = self.header.build();
        raw.extend(self.body.build());
        return raw;
    }

    pub fn parse(raw: &[u8]) -> Result<Self> {
        let (raw, header) = Smb2Header::parse(raw)?;

        let body = match header.command {
            SMB2_NEGOTIATE_PROTOCOL => {
                if header.is_response() {
                    Smb2Body::NegResp(Smb2NegResp::parse(raw)?)
                } else {
                    Smb2Body::NegReq(Smb2NegReq::parse(raw)?)
                }
            }
            SMB2_SESSION_SETUP => {
                if header.is_response() {
                    Smb2Body::SessionSetupResp(Smb2SessionSetupResp::parse(raw)?)
                } else {
                    todo!()
                }
            }
            _ => return Err(Error::Smb2UnknownCommand(header.command)),
        };

        return Ok(Self { header, body });
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum Smb2Body {
    NegReq(Smb2NegReq),
    NegResp(Smb2NegResp),
    SessionSetupReq(Smb2SessionSetupReq),
    SessionSetupResp(Smb2SessionSetupResp),
}

impl Smb2Body {
    pub fn build(&self) -> Vec<u8> {
        match self {
            Self::NegReq(b) => b.build(),
            Self::NegResp(_) => todo!(),
            Self::SessionSetupReq(b) => b.build(),
            Self::SessionSetupResp(_) => todo!(),
        }
    }
}

impl Default for Smb2Body {
    fn default() -> Self {
        return Self::NegReq(Smb2NegReq::default());
    }
}