summaryrefslogtreecommitdiff
path: root/src/secure.rs
blob: 1fc3a111b21be4c9da5314cfb54a16f603e337b2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
use std::{os::{unix::prelude::PermissionsExt, linux::fs::MetadataExt}, fs, io::ErrorKind};
use nix::unistd;

pub fn write_file(dir: &str, file: &str, data: &str) -> Result<(), Box<dyn std::error::Error>> {
  std::fs::create_dir_all(dir)?;
  make_file_root(dir)?;
  let path = path(dir, file);
  std::fs::write(&path, "")?;
  make_file_root(&path)?;
  std::fs::write(&path, data)?;
  Ok(())
}

pub fn read_file(dir: &str, file: &str) -> Option<String> {
  let path = path(dir,file);
  if !is_file_root(&path) {
      return None;
  }
  match std::fs::read_to_string(&path) {
      Ok(data) => return Some(data),
      Err(_) => return None
  };
}

fn make_file_root(path: &str) -> Result<(), Box<dyn std::error::Error>> {
  unistd::chown(std::path::Path::new(path), Some(unistd::Uid::from(0)), Some(unistd::Gid::from(0)))?;
  let metadata = std::fs::metadata(path)?;
  let mut perms = metadata.permissions();
  perms.set_mode(0o100600);
  fs::set_permissions(path, perms)?;
  Ok(())
}

fn is_file_root(path: &str) -> bool {
  return check_file_permissions(0, 0, 0o100600, path);
}

fn check_file_permissions(uid: u32, gid: u32, mode: u32, path: &str) -> bool {
  let metadata = match std::fs::metadata(path) {
    Ok(data) => data,
    Err(e) => {
        return e.kind() == ErrorKind::NotFound
    }
  };
  let perms = metadata.permissions();
  return perms.mode() == mode && metadata.st_uid() == uid && metadata.st_gid() == gid;
}

fn path(dir: &str, file: &str) -> String {
  return format!("{}/{}", dir, file);
}