summaryrefslogtreecommitdiff
path: root/src/secure.rs
blob: 018bc4f1608698e2bd7acd86b2cc2c97a5f5c113 (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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
use std::{os::{unix::prelude::PermissionsExt, linux::fs::MetadataExt}, fs, io::{self, ErrorKind}};
use nix::unistd::{self, Uid};


/// Writes a file securly to a specified path with given data
/// #### Arguments
/// * `dir` - The directory of the secure folder
/// * `file` - The file name to write
/// * `data` - The data to write
/// #### Returns
/// A ``io::Result<()>`` if the write succeded or failed
pub fn write_file(dir: &str, file: &str, data: &str) -> Result<(), io::Error> {
    fs::create_dir_all(dir)?;
    set_file_permissions(0, 0, 0o100600, dir)?;
    let path = path(dir, file);
    fs::write(&path, data)?;
    set_file_permissions(0, 0, 0o100600, &path)?;
    Ok(())
}


/// Reads the file secutly to a specified path. If the file has
/// been tampered (permissions have been changed), it ignores the
/// file.
/// #### Arguments
/// * `dir` - The directory of the secure folder
/// * `file` - The file name to write
/// #### Returns
/// * `None` - If the files doesnt exist or isnt trusted
/// * `Some(String) - If the file is trusted, it returns the file's contents
pub fn read_file(dir: &str, file: &str) -> Option<String> {
    let path = path(dir,file);
    if !check_file_permissions(0, 0, 0o100600, &path) {
        return None;
    }
    match fs::read_to_string(&path) {
        Ok(data) => return Some(data),
        Err(_) => return None
    };
}


/// Elecate the privlages of the current process
/// #### Arguments
/// * `uid` - The uid to set the process to
/// #### Returns
/// If the process fails to elevate, it returns false
pub fn elevate_privilages(uid: Uid) -> bool {
    if unistd::setuid(uid).is_err() {
        return false;
    } 
    true
}


/// Sets the permission for a secure file
/// #### Arguments
/// * `uid` - The user to own the file
/// * `gid` - The group to own the file
/// * `mode` - The mode permissions of the file
/// * `path` - The path of the secure file
/// #### Returns
/// A ``io::Result<()>`` if the write succeded or failed
fn set_file_permissions(uid: u32, gid: u32, mode: u32, path: &str) -> Result<(), io::Error> {
    unistd::chown(std::path::Path::new(path), Some(unistd::Uid::from(uid)), Some(unistd::Gid::from(gid)))?;
    let metadata = fs::metadata(path)?;
    let mut perms = metadata.permissions();
    perms.set_mode(mode);
    fs::set_permissions(path, perms)?;
    Ok(())
}


/// Checks if the files permissions equals the given parameters
/// #### Arguments
/// * `uid` - The user to own the file
/// * `gid` - The group to own the file
/// * `mode` - The mode permissions of the file
/// * `path` - The path of the secure file
/// #### Returns
/// True or false if the files permissions match
fn check_file_permissions(uid: u32, gid: u32, mode: u32, path: &str) -> bool {
    let metadata = match 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;
}


/// Get the path of a file given a directory and file name
fn path(dir: &str, file: &str) -> String {
    return format!("{}/{}.persist", dir, file);
}