#[derive(Clone, Debug, PartialEq)]
pub(crate) enum AuthFlavor {
Null = 0,
Unix = 1,
}
#[derive(Clone, Debug, PartialEq)]
pub(crate) struct Auth {
pub(crate) flavor: AuthFlavor,
pub(crate) uid: u32,
pub(crate) gid: u32,
pub(crate) body: Vec<u8>,
}
impl Auth {
pub(crate) fn new_null() -> Self {
Self {
flavor: AuthFlavor::Null,
uid: 0,
gid: 0,
body: vec![],
}
}
pub(crate) fn new_unix(machinename: &str, uid: u32, gid: u32) -> Self {
let stamp = super::get_current_time();
let unix = AuthUnix {
stamp,
machinename: machinename.to_string(),
uid,
gid,
gids: Vec::new(),
};
let mut body = Vec::<u8>::new();
unix.encode(&mut body);
Self {
flavor: AuthFlavor::Unix,
uid,
gid,
body,
}
}
pub(crate) fn encode(&self, buf: &mut Vec<u8>) {
buf.extend_from_slice(&(self.flavor.clone() as u32).to_be_bytes());
buf.extend_from_slice(&(self.body.len() as u32).to_be_bytes());
buf.extend_from_slice(&self.body);
let pad = (4 - self.body.len() % 4) % 4;
for _ in 0..pad {
buf.push(0);
}
}
}
struct AuthUnix {
stamp: u32,
machinename: String,
uid: u32,
gid: u32,
gids: Vec<u32>,
}
impl AuthUnix {
fn encode(&self, buf: &mut Vec<u8>) {
buf.extend_from_slice(&self.stamp.to_be_bytes());
let name = self.machinename.as_bytes();
buf.extend_from_slice(&(name.len() as u32).to_be_bytes());
buf.extend_from_slice(name);
let pad = (4 - name.len() % 4) % 4;
for _ in 0..pad {
buf.push(0);
}
buf.extend_from_slice(&self.uid.to_be_bytes());
buf.extend_from_slice(&self.gid.to_be_bytes());
buf.extend_from_slice(&(self.gids.len() as u32).to_be_bytes());
for &gid in &self.gids {
buf.extend_from_slice(&gid.to_be_bytes());
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn auth_new_null() {
assert_eq!(
Auth::new_null(),
Auth {
flavor: AuthFlavor::Null,
uid: 0,
gid: 0,
body: vec![]
}
);
}
#[test]
fn auth_null_pack() {
let auth = Auth::new_null();
let mut buf = Vec::<u8>::new();
auth.encode(&mut buf);
let expected: Vec<u8> = vec![
0, 0, 0, 0, 0, 0, 0, 0, ];
assert_eq!(buf, expected);
}
#[test]
fn auth_new_unix_with_padding_of_0() {
let actual = Auth::new_unix("machined", 1, 2);
let mut expected = Auth {
flavor: AuthFlavor::Unix,
uid: 1,
gid: 2,
body: vec![
0, 0, 0, 0, 0, 0, 0, 8, 109, 97, 99, 104, 105, 110, 101, 100, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, ],
};
assert_ne!(actual, expected);
expected.body.splice(0..4, actual.body[0..4].to_vec());
assert_eq!(actual, expected);
}
#[test]
fn auth_new_unix_with_padding_of_1() {
let actual = Auth::new_unix("machine", 350, 400);
let mut expected = Auth {
flavor: AuthFlavor::Unix,
uid: 350,
gid: 400,
body: vec![
0, 0, 0, 0, 0, 0, 0, 7, 109, 97, 99, 104, 105, 110, 101, 0, 0, 0, 1, 94, 0, 0, 1, 144, 0, 0, 0, 0, ],
};
assert_ne!(actual, expected);
expected.body.splice(0..4, actual.body[0..4].to_vec());
assert_eq!(actual, expected);
}
#[test]
fn auth_new_unix_with_padding_of_2() {
let actual = Auth::new_unix("machin", 666, 616);
let mut expected = Auth {
flavor: AuthFlavor::Unix,
uid: 666,
gid: 616,
body: vec![
0, 0, 0, 0, 0, 0, 0, 6, 109, 97, 99, 104, 105, 110, 0, 0, 0, 0, 2, 154, 0, 0, 2, 104, 0, 0, 0, 0, ],
};
assert_ne!(actual, expected);
expected.body.splice(0..4, actual.body[0..4].to_vec());
assert_eq!(actual, expected);
}
#[test]
fn auth_new_unix_with_padding_of_3() {
let actual = Auth::new_unix("machi", 1024, 2048);
let mut expected = Auth {
flavor: AuthFlavor::Unix,
uid: 1024,
gid: 2048,
body: vec![
0, 0, 0, 0, 0, 0, 0, 5, 109, 97, 99, 104, 105, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 0, 0, ],
};
assert_ne!(actual, expected);
expected.body.splice(0..4, actual.body[0..4].to_vec());
assert_eq!(actual, expected);
}
#[test]
fn auth_unix_pack() {
let auth = Auth::new_unix("machine", 350, 400);
let mut buf = Vec::<u8>::new();
auth.encode(&mut buf);
let mut expected: Vec<u8> = vec![
0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 7, 109, 97, 99, 104, 105, 110, 101, 0, 0, 0, 1, 94, 0, 0, 1, 144, 0, 0, 0, 0, ];
assert_ne!(buf, expected);
expected.splice(8..12, auth.body[0..4].to_vec());
assert_eq!(buf, expected);
}
}