Added create_folder
method to MailStore
trait; Add code to set
restrictive permissions on mail account folders;
This commit is contained in:
parent
dcb182e4d0
commit
3a25914ec5
3 changed files with 56 additions and 1 deletions
|
@ -5,6 +5,7 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
digest = "0.10"
|
digest = "0.10"
|
||||||
|
libc = "0.2.146"
|
||||||
rustls-pemfile = "1.0"
|
rustls-pemfile = "1.0"
|
||||||
sha2 = "0.10"
|
sha2 = "0.10"
|
||||||
time = "0.3"
|
time = "0.3"
|
||||||
|
@ -12,6 +13,11 @@ x509-parser = "0.15"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies.pw]
|
||||||
|
git = "https://codeberg.org/jeang3nie/pw_rs.git"
|
||||||
|
default-features = false
|
||||||
|
features = [ "libc" ]
|
||||||
|
|
||||||
[dependencies.rustls]
|
[dependencies.rustls]
|
||||||
version = "0.21"
|
version = "0.21"
|
||||||
features = [ "dangerous_configuration" ]
|
features = [ "dangerous_configuration" ]
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
use std::io::BufReader;
|
use std::{
|
||||||
|
ffi::CString,
|
||||||
|
io::BufReader,
|
||||||
|
os::{fd::AsRawFd, unix::prelude::OpenOptionsExt},
|
||||||
|
};
|
||||||
|
|
||||||
use crate::prelude::Certificate;
|
use crate::prelude::Certificate;
|
||||||
|
|
||||||
|
@ -149,6 +153,21 @@ impl MailStore for Filesystem {
|
||||||
Some(folder)
|
Some(folder)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_folder(&self, user: &str, folder: &str) -> Result<(), io::Error> {
|
||||||
|
if self.has_mailuser(user) {
|
||||||
|
let user: Mailbox = user.parse().map_err(|e: ParseMailboxError| {
|
||||||
|
io::Error::new(io::ErrorKind::Other, e.to_string())
|
||||||
|
})?;
|
||||||
|
let user: Mailuser = user.into();
|
||||||
|
let mut path = self.path.clone();
|
||||||
|
path.push(&user.host.to_string());
|
||||||
|
path.push(&user.username);
|
||||||
|
path.push(folder);
|
||||||
|
fs::create_dir_all(&path)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn get_message(&self, user: &str, folder: &str, id: &str) -> Option<Message> {
|
fn get_message(&self, user: &str, folder: &str, id: &str) -> Option<Message> {
|
||||||
self.get_folder(user, folder)
|
self.get_folder(user, folder)
|
||||||
.and_then(|f| f.messages.get(id).cloned())
|
.and_then(|f| f.messages.get(id).cloned())
|
||||||
|
@ -230,7 +249,22 @@ impl MailStore for Filesystem {
|
||||||
.create(true)
|
.create(true)
|
||||||
.write(true)
|
.write(true)
|
||||||
.truncate(true)
|
.truncate(true)
|
||||||
|
.mode(0o2770)
|
||||||
.open(path)?;
|
.open(path)?;
|
||||||
|
if let Some(pw) = pw::Passwd::getpw()
|
||||||
|
.map_err(|e: pw::Error| io::Error::new(io::ErrorKind::Other, e.to_string()))?
|
||||||
|
{
|
||||||
|
let groups = pw
|
||||||
|
.groups()
|
||||||
|
.map_err(|e: pw::Error| io::Error::new(io::ErrorKind::Other, e.to_string()))?;
|
||||||
|
if let Some(gr) = groups.iter().find(|g| g.name == mb.username) {
|
||||||
|
unsafe {
|
||||||
|
if libc::fchown(fd.as_raw_fd(), pw.uid, gr.gid) != 0 {
|
||||||
|
return Err(io::Error::last_os_error());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
let mut writer = BufWriter::new(fd);
|
let mut writer = BufWriter::new(fd);
|
||||||
writer.write_all(blurb.as_bytes())?;
|
writer.write_all(blurb.as_bytes())?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@ pub trait MailStore {
|
||||||
fn has_mailuser(&self, mailuser: &str) -> bool;
|
fn has_mailuser(&self, mailuser: &str) -> bool;
|
||||||
/// Retreives all of the messages for this user
|
/// Retreives all of the messages for this user
|
||||||
fn get_folder(&self, user: &str, folder: &str) -> Option<Folder>;
|
fn get_folder(&self, user: &str, folder: &str) -> Option<Folder>;
|
||||||
|
/// Creates a folder for the specified user, if it doesn't already exist
|
||||||
|
fn create_folder(&self, user: &str, folder: &str) -> Result<(), Self::Error>;
|
||||||
/// Checks whether this server has a message with the given title for this user and if so
|
/// Checks whether this server has a message with the given title for this user and if so
|
||||||
/// returns the message
|
/// returns the message
|
||||||
fn get_message(&self, user: &str, folder: &str, id: &str) -> Option<Message>;
|
fn get_message(&self, user: &str, folder: &str, id: &str) -> Option<Message>;
|
||||||
|
@ -97,6 +99,19 @@ impl MailStore for Domain {
|
||||||
.and_then(|u| u.folders.get(folder).cloned())
|
.and_then(|u| u.folders.get(folder).cloned())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_folder(&self, user: &str, folder: &str) -> Result<(), io::Error> {
|
||||||
|
self.users.get(user).cloned().and_then(|mut u| {
|
||||||
|
u.folders.insert(
|
||||||
|
folder.to_string(),
|
||||||
|
Folder {
|
||||||
|
name: folder.to_string(),
|
||||||
|
messages: HashMap::new(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
});
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn get_message(&self, user: &str, folder: &str, title: &str) -> Option<Message> {
|
fn get_message(&self, user: &str, folder: &str, title: &str) -> Option<Message> {
|
||||||
self.users
|
self.users
|
||||||
.get(user)
|
.get(user)
|
||||||
|
|
Loading…
Add table
Reference in a new issue