//! This library contains helper to read, parse and write the
//! configuration files.
-use failure::*;
+use anyhow::{bail, format_err, Error};
+use std::path::PathBuf;
+use nix::sys::stat::Mode;
+use openssl::rsa::{Rsa};
+use openssl::x509::{X509Builder};
+use openssl::pkey::PKey;
-pub mod datastore;
+use proxmox::tools::fs::{CreateOptions, replace_file};
+use proxmox::try_block;
-use crate::tools;
use crate::buildcfg;
+pub mod acl;
+pub mod cached_user_info;
+pub mod datastore;
+pub mod jobstate;
+pub mod network;
+pub mod remote;
+pub mod sync;
+pub mod user;
+pub mod verify;
+
/// Check configuration directory permissions
///
/// For security reasons, we want to make sure they are set correctly:
/// * owned by 'backup' user/group
/// * nobody else can read (mode 0700)
-pub fn check_confidir_permissions() -> Result<(), Error> {
-
+pub fn check_configdir_permissions() -> Result<(), Error> {
let cfgdir = buildcfg::CONFIGDIR;
- let (backup_uid, backup_gid) = tools::getpwnam_ugid("backup")?;
+
+ let backup_user = crate::backup::backup_user()?;
+ let backup_uid = backup_user.uid.as_raw();
+ let backup_gid = backup_user.gid.as_raw();
try_block!({
let stat = nix::sys::stat::stat(cfgdir)?;
if stat.st_uid != backup_uid {
- bail!("wrong user ({} != {})", stat.st_uid, backup_uid);
+ bail!("wrong user ({} != {})", stat.st_uid, backup_uid);
}
if stat.st_gid != backup_gid {
- bail!("wrong group ({} != {})", stat.st_gid, backup_gid);
+ bail!("wrong group ({} != {})", stat.st_gid, backup_gid);
}
let perm = stat.st_mode & 0o777;
if perm != 0o700 {
- bail!("wrong permission ({:o} != {:o})", perm, 0o700);
+ bail!("wrong permission ({:o} != {:o})", perm, 0o700);
}
Ok(())
- }).map_err(|err| format_err!("configuration directory '{}' permission problem - {}", cfgdir, err))
+ })
+ .map_err(|err| {
+ format_err!(
+ "configuration directory '{}' permission problem - {}",
+ cfgdir,
+ err
+ )
+ })
}
pub fn create_configdir() -> Result<(), Error> {
-
- use nix::sys::stat::Mode;
-
let cfgdir = buildcfg::CONFIGDIR;
- let (backup_uid, backup_gid) = tools::getpwnam_ugid("backup")?;
match nix::unistd::mkdir(cfgdir, Mode::from_bits_truncate(0o700)) {
- Ok(()) => {},
+ Ok(()) => {}
Err(nix::Error::Sys(nix::errno::Errno::EEXIST)) => {
- check_confidir_permissions()?;
+ check_configdir_permissions()?;
return Ok(());
- },
- Err(err) => bail!("unable to create configuration directory '{}' - {}", cfgdir, err),
+ }
+ Err(err) => bail!(
+ "unable to create configuration directory '{}' - {}",
+ cfgdir,
+ err
+ ),
}
- try_block!({
- let uid = nix::unistd::Uid::from_raw(backup_uid);
- let gid = nix::unistd::Gid::from_raw(backup_gid);
+ let backup_user = crate::backup::backup_user()?;
- nix::unistd::chown(cfgdir, Some(uid), Some(gid))?;
+ nix::unistd::chown(cfgdir, Some(backup_user.uid), Some(backup_user.gid))
+ .map_err(|err| {
+ format_err!(
+ "unable to set configuration directory '{}' permissions - {}",
+ cfgdir,
+ err
+ )
+ })
+}
- Ok(())
- }).map_err(|err: Error| format_err!(
- "unable to set configuration directory '{}' permissions - {}", cfgdir, err))
+/// Update self signed node certificate.
+pub fn update_self_signed_cert(force: bool) -> Result<(), Error> {
+
+ let backup_user = crate::backup::backup_user()?;
+
+ create_configdir()?;
+
+ let key_path = PathBuf::from(configdir!("/proxy.key"));
+ let cert_path = PathBuf::from(configdir!("/proxy.pem"));
+
+ if key_path.exists() && cert_path.exists() && !force { return Ok(()); }
+
+ let rsa = Rsa::generate(4096).unwrap();
+
+ let priv_pem = rsa.private_key_to_pem()?;
+
+ replace_file(
+ &key_path,
+ &priv_pem,
+ CreateOptions::new()
+ .perm(Mode::from_bits_truncate(0o0640))
+ .owner(nix::unistd::ROOT)
+ .group(backup_user.gid),
+ )?;
+
+ let mut x509 = X509Builder::new()?;
+
+ x509.set_version(2)?;
+
+ let today = openssl::asn1::Asn1Time::days_from_now(0)?;
+ x509.set_not_before(&today)?;
+ let expire = openssl::asn1::Asn1Time::days_from_now(365*1000)?;
+ x509.set_not_after(&expire)?;
+
+ let nodename = proxmox::tools::nodename();
+ let mut fqdn = nodename.to_owned();
+
+ let resolv_conf = crate::api2::node::dns::read_etc_resolv_conf()?;
+ if let Some(search) = resolv_conf["search"].as_str() {
+ fqdn.push('.');
+ fqdn.push_str(search);
+ }
+
+ // we try to generate an unique 'subject' to avoid browser problems
+ //(reused serial numbers, ..)
+ let uuid = proxmox::tools::uuid::Uuid::generate();
+
+ let mut subject_name = openssl::x509::X509NameBuilder::new()?;
+ subject_name.append_entry_by_text("O", "Proxmox Backup Server")?;
+ subject_name.append_entry_by_text("OU", &format!("{:X}", uuid))?;
+ subject_name.append_entry_by_text("CN", &fqdn)?;
+ let subject_name = subject_name.build();
+
+ x509.set_subject_name(&subject_name)?;
+ x509.set_issuer_name(&subject_name)?;
+
+ let bc = openssl::x509::extension::BasicConstraints::new(); // CA = false
+ let bc = bc.build()?;
+ x509.append_extension(bc)?;
+
+ let usage = openssl::x509::extension::ExtendedKeyUsage::new()
+ .server_auth()
+ .build()?;
+ x509.append_extension(usage)?;
+
+ let context = x509.x509v3_context(None, None);
+
+ let mut alt_names = openssl::x509::extension::SubjectAlternativeName::new();
+
+ alt_names.ip("127.0.0.1");
+ alt_names.ip("::1");
+
+ alt_names.dns("localhost");
+
+ if nodename != "localhost" { alt_names.dns(nodename); }
+ if nodename != fqdn { alt_names.dns(&fqdn); }
+
+ let alt_names = alt_names.build(&context)?;
+
+ x509.append_extension(alt_names)?;
+
+ let pub_pem = rsa.public_key_to_pem()?;
+ let pubkey = PKey::public_key_from_pem(&pub_pem)?;
+
+ x509.set_pubkey(&pubkey)?;
+
+ let context = x509.x509v3_context(None, None);
+ let ext = openssl::x509::extension::SubjectKeyIdentifier::new().build(&context)?;
+ x509.append_extension(ext)?;
+
+ let context = x509.x509v3_context(None, None);
+ let ext = openssl::x509::extension::AuthorityKeyIdentifier::new()
+ .keyid(true)
+ .build(&context)?;
+ x509.append_extension(ext)?;
+
+ let privkey = PKey::from_rsa(rsa)?;
+
+ x509.sign(&privkey, openssl::hash::MessageDigest::sha256())?;
+
+ let x509 = x509.build();
+ let cert_pem = x509.to_pem()?;
+
+ replace_file(
+ &cert_path,
+ &cert_pem,
+ CreateOptions::new()
+ .perm(Mode::from_bits_truncate(0o0640))
+ .owner(nix::unistd::ROOT)
+ .group(backup_user.gid),
+ )?;
+
+ Ok(())
}