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.