priv_sep

Privilege separation library.
git clone https://git.philomathiclife.com/repos/priv_sep
Log | Files | Refs | README

README.md (5200B)


      1 # `priv_sep`
      2 
      3 [<img alt="git" src="https://git.philomathiclife.com/badges/priv_sep.svg" height="20">](https://git.philomathiclife.com/priv_sep/log.html)
      4 [<img alt="crates.io" src="https://img.shields.io/crates/v/priv_sep.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/priv_sep)
      5 [<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-priv_sep-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/priv_sep/latest/priv_sep/)
      6 
      7 `priv_sep` is a library that uses the system's libc to perform privilege separation and privilege reduction.
      8 
      9 ## `priv_sep` in action for OpenBSD
     10 
     11 ```rust
     12 use core::convert::Infallible;
     13 use priv_sep::{Permissions, PrivDropErr, Promise, Promises};
     14 use std::{
     15     fs,
     16     io::Error,
     17     net::{Ipv6Addr, SocketAddrV6},
     18 };
     19 use tokio::net::TcpListener;
     20 #[tokio::main(flavor = "current_thread")]
     21 async fn main() -> Result<Infallible, PrivDropErr<Error>> {
     22     /// Config file.
     23     const CONFIG: &str = "config";
     24     // Get the user ID and group ID for nobody from `passwd(5)`.
     25     // `chroot(2)` to `/path/chroot/` and `chdir(2)` to `/`.
     26     // `pledge(2)` `id`, `inet`, `rpath`, `stdio`, and `unveil`.
     27     // Bind to TCP `[::1]:443` as root.
     28     // `setresgid(2)` to the group ID associated with nobody.
     29     // `setresuid(2)` to the user ID associated with nobody.
     30     // Remove `id` from our `pledge(2)`d promises.
     31     let (listener, mut promises) = Promises::new_chroot_then_priv_drop_async(
     32         "nobody",
     33         "/path/chroot/",
     34         [Promise::Inet, Promise::Rpath, Promise::Unveil],
     35         false,
     36         async || TcpListener::bind(SocketAddrV6::new(Ipv6Addr::LOCALHOST, 443, 0, 0)).await,
     37     ).await?;
     38     // At this point, the process is running under nobody.
     39     // Only allow file system access to `config` and only allow read access to it.
     40     Permissions::READ.unveil(CONFIG)?;
     41     // Read `config`.
     42     // This will of course fail if the file does not exist or nobody does not
     43     // have read permissions.
     44     let config = fs::read(CONFIG)?;
     45     // Remove file system access.
     46     Permissions::NONE.unveil(CONFIG)?;
     47     // Remove `rpath` and `unveil` from our `pledge(2)`d promises
     48     // (i.e., only have `inet` and `stdio` abilities when we begin accepting TCP connections).
     49     promises.remove_promises_then_pledge([Promise::Rpath, Promise::Unveil])?;
     50     loop {
     51         // Handle TCP connections.
     52         if let Ok((_, ip)) = listener.accept().await {
     53             assert!(ip.is_ipv6());
     54         }
     55     }
     56 }
     57 ```
     58 
     59 ## `priv_sep` in action for Unix-like OSes
     60 
     61 ```rust
     62 use core::convert::Infallible;
     63 use priv_sep::{UserInfo, PrivDropErr};
     64 use std::{
     65     io::Error,
     66     net::{Ipv6Addr, SocketAddrV6},
     67 };
     68 use tokio::net::TcpListener;
     69 #[tokio::main(flavor = "current_thread")]
     70 async fn main() -> Result<Infallible, PrivDropErr<Error>> {
     71     // Get the user ID and group ID for nobody from `passwd(5)`.
     72     // `chroot(2)` to `/path/chroot/` and `chdir(2)` to `/`.
     73     // Bind to TCP `[::1]:443` as root.
     74     // `setresgid(2)` to the group ID associated with nobody.
     75     // `setresuid(2)` to the user ID associated with nobody.
     76     let listener = UserInfo::chroot_then_priv_drop_async("nobody", "/path/chroot/", false, async || {
     77         TcpListener::bind(SocketAddrV6::new(Ipv6Addr::LOCALHOST, 443, 0, 0)).await
     78     }).await?;
     79     // At this point, the process is running under nobody.
     80     loop {
     81         // Handle TCP connections.
     82         if let Ok((_, ip)) = listener.accept().await {
     83             assert!(ip.is_ipv6());
     84         }
     85     }
     86 }
     87 ```
     88 
     89 ## Minimum Supported Rust Version (MSRV)
     90 
     91 This will frequently be updated to be the same as stable. Specifically, any time stable is updated and that
     92 update has "useful" features or compilation no longer succeeds (e.g., due to new compiler lints), then MSRV
     93 will be updated.
     94 
     95 MSRV changes will correspond to a SemVer minor version bump.
     96 
     97 ## SemVer Policy
     98 
     99 * All on-by-default features of this library are covered by SemVer
    100 * MSRV is considered exempt from SemVer as noted above
    101 
    102 ## License
    103 
    104 Licensed under either of
    105 
    106 * Apache License, Version 2.0 ([LICENSE-APACHE](https://www.apache.org/licenses/LICENSE-2.0))
    107 * MIT license ([LICENSE-MIT](https://opensource.org/licenses/MIT))
    108 
    109 at your option.
    110 
    111 ## Contribution
    112 
    113 Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you,
    114 as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
    115 
    116 Before any PR is sent, `cargo clippy` and `cargo t` should be run. Additionally
    117 `RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --all-features` should be run to ensure documentation can be built.
    118 
    119 ### Status
    120 
    121 This package will be actively maintained to stay in-sync with the latest version of OpenBSD.
    122 The crate is only tested on the `x86_64-unknown-openbsd` and `x86_64-unknown-linux` targets. While OpenBSD supports
    123 both the most recent -release/-stable release as well as the previous version, only the most recent version will
    124 be supported by this library. If using -stable, it may be necessary to build the
    125 [`rust` port](https://github.com/openbsd/ports/tree/master/lang/rust) from -current.