V large cleanup

This commit is contained in:
William Brown 2020-08-04 12:58:11 +10:00 committed by Firstyear
parent 217e3455a2
commit 85ec82832e
54 changed files with 1227 additions and 756 deletions

160
Cargo.lock generated
View file

@ -390,6 +390,46 @@ version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8"
[[package]]
name = "async-channel"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43de69555a39d52918e2bc33a408d3c0a86c829b212d898f4ca25d21a6387478"
dependencies = [
"concurrent-queue",
"event-listener",
"futures-core",
]
[[package]]
name = "async-std"
version = "1.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00d68a33ebc8b57800847d00787307f84a562224a14db069b0acefe4c2abbf5d"
dependencies = [
"async-task",
"crossbeam-utils",
"futures-channel",
"futures-core",
"futures-io",
"kv-log-macro",
"log",
"memchr",
"num_cpus",
"once_cell",
"pin-project-lite",
"pin-utils",
"slab",
"smol",
"wasm-bindgen-futures",
]
[[package]]
name = "async-task"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c17772156ef2829aadc587461c7753af20b7e8db1529bc66855add962a3b35d3"
[[package]]
name = "async-trait"
version = "0.1.36"
@ -401,6 +441,12 @@ dependencies = [
"syn",
]
[[package]]
name = "atomic-waker"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a"
[[package]]
name = "atty"
version = "0.2.14"
@ -533,6 +579,20 @@ dependencies = [
"byte-tools",
]
[[package]]
name = "blocking"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2468ff7bf85066b4a3678fede6fe66db31846d753ff0adfbfab2c6a6e81612b"
dependencies = [
"async-channel",
"atomic-waker",
"futures-lite",
"once_cell",
"parking",
"waker-fn",
]
[[package]]
name = "brotli-sys"
version = "0.3.2"
@ -598,6 +658,12 @@ dependencies = [
"bytes",
]
[[package]]
name = "cache-padded"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba"
[[package]]
name = "cargo-husky"
version = "1.5.0"
@ -681,6 +747,15 @@ dependencies = [
"smallvec",
]
[[package]]
name = "concurrent-queue"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e296417c8154304ac70aceda41f05318f986f7c0c767bcb0a2366fbb890e78e1"
dependencies = [
"cache-padded",
]
[[package]]
name = "const-random"
version = "0.1.8"
@ -1066,6 +1141,12 @@ dependencies = [
"version_check 0.9.2",
]
[[package]]
name = "event-listener"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "298f00c3b04c1d9b4cb86aefaaa35348af0957d98b30a5306fc635f8e718923d"
[[package]]
name = "failure"
version = "0.1.8"
@ -1116,6 +1197,12 @@ dependencies = [
"regex",
]
[[package]]
name = "fastrand"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36a9cb09840f81cd211e435d00a4e487edd263dc3c8ff815c32dd76ad668ebed"
[[package]]
name = "flate2"
version = "1.0.16"
@ -1213,6 +1300,21 @@ version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de27142b013a8e869c14957e6d2edeef89e97c289e69d042ee3a49acd8b51789"
[[package]]
name = "futures-lite"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbe71459749b2e8e66fb95df721b22fa08661ad384a0c5b519e11d3893b4692a"
dependencies = [
"fastrand",
"futures-core",
"futures-io",
"memchr",
"parking",
"pin-project-lite",
"waker-fn",
]
[[package]]
name = "futures-macro"
version = "0.3.5"
@ -1647,6 +1749,7 @@ name = "kanidm_unix_int"
version = "1.1.0-alpha"
dependencies = [
"actix",
"async-std",
"bytes",
"env_logger",
"futures",
@ -1681,6 +1784,15 @@ dependencies = [
"winapi-build",
]
[[package]]
name = "kv-log-macro"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f"
dependencies = [
"log",
]
[[package]]
name = "language-tags"
version = "0.2.2"
@ -2126,6 +2238,12 @@ dependencies = [
"tokio",
]
[[package]]
name = "parking"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6cb300f271742d4a2a66c01b6b2fa0c83dfebd2e0bf11addb879a3547b4ed87c"
[[package]]
name = "parking_lot"
version = "0.10.2"
@ -2628,6 +2746,12 @@ dependencies = [
"parking_lot 0.11.0",
]
[[package]]
name = "scoped-tls"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
[[package]]
name = "scopeguard"
version = "1.1.0"
@ -2777,6 +2901,27 @@ dependencies = [
"serde",
]
[[package]]
name = "smol"
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "620cbb3c6e34da57d3a248cda0cd01cd5848164dc062e764e65d06fe3ea7aed5"
dependencies = [
"async-task",
"blocking",
"concurrent-queue",
"fastrand",
"futures-io",
"futures-util",
"libc",
"once_cell",
"scoped-tls",
"slab",
"socket2",
"wepoll-sys-stjepang",
"winapi 0.3.9",
]
[[package]]
name = "socket2"
version = "0.3.12"
@ -3373,6 +3518,12 @@ version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
[[package]]
name = "waker-fn"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9571542c2ce85ce642e6b58b3364da2fb53526360dfb7c211add4f5c23105ff7"
[[package]]
name = "walkdir"
version = "2.3.1"
@ -3478,6 +3629,15 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "wepoll-sys-stjepang"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fd319e971980166b53e17b1026812ad66c6b54063be879eb182342b55284694"
dependencies = [
"cc",
]
[[package]]
name = "widestring"
version = "0.4.2"

View file

@ -75,7 +75,9 @@ fn read_file_metadata<P: AsRef<Path>>(path: &P) -> Result<Metadata, ()> {
metadata(path).map_err(|e| {
error!(
"Unable to read metadata for {} - {:?}",
path.as_ref().to_str().unwrap(),
path.as_ref()
.to_str()
.unwrap_or_else(|| "alert: invalid path"),
e
);
})

View file

@ -1,5 +1,12 @@
#![deny(warnings)]
#![warn(unused_extern_crates)]
#![deny(clippy::unwrap_used)]
#![deny(clippy::expect_used)]
#![deny(clippy::panic)]
#![deny(clippy::unreachable)]
#![deny(clippy::await_holding_lock)]
#![deny(clippy::needless_pass_by_value)]
#![deny(clippy::trivially_copy_pass_by_ref)]
#[macro_use]
extern crate serde_derive;

View file

@ -100,6 +100,7 @@ pub enum OperationError {
PasswordTooShort(usize),
PasswordEmpty,
PasswordBadListed,
CryptographyError,
}
impl PartialEq for OperationError {

View file

@ -1,3 +1,13 @@
#![deny(warnings)]
#![warn(unused_extern_crates)]
#![deny(clippy::unwrap_used)]
#![deny(clippy::expect_used)]
#![deny(clippy::panic)]
#![deny(clippy::unreachable)]
#![deny(clippy::await_holding_lock)]
#![deny(clippy::needless_pass_by_value)]
#![deny(clippy::trivially_copy_pass_by_ref)]
use std::fs::File;
use std::io::prelude::*;
use std::io::BufWriter;
@ -38,6 +48,15 @@ fn main() {
}
info!("Kanidm badlist preprocessor - this may take a long time ...");
// We open the file early to find out if we can create it or not.
let fileout = match File::create(opt.outfile) {
Ok(f) => f,
Err(e) => {
error!("Failed to create file - {:?}", e);
return;
}
};
// Build a temp struct for all the pws.
// Shellexpand all of these.
/*
@ -96,9 +115,15 @@ fn main() {
if v.len() < 10 {
return false;
}
let r = zxcvbn::zxcvbn(v.as_str(), site_opts.as_slice()).expect("Empty Password?");
// score of 2 or less is too weak and we'd already reject it.
r.score() >= 3
match zxcvbn::zxcvbn(v.as_str(), site_opts.as_slice()) {
// score of 2 or less is too weak and we'd already reject it.
Ok(r) => r.score() >= 3,
Err(e) => {
error!("zxcvbn unable to process '{}' - {:?}", v.as_str(), e);
error!("adding to badlist anyway ...");
true
}
}
})
.collect();
@ -110,7 +135,6 @@ fn main() {
debug!("Starting file write ...");
// Now we write these out.
let fileout = File::create(opt.outfile).expect("Failed to create file");
let bwrite = BufWriter::new(fileout);
// All remaining are either
@ -120,10 +144,17 @@ fn main() {
.into_iter()
.map(|p| Modify::Present("badlist_password".to_string(), p))
.collect();
serde_json::to_writer_pretty(bwrite, &modlist).expect("Failed to serialise modlist");
// println!("next step: kanidm raw modify -D admin '{{\"Eq\": [\"uuid\", \"00000000-0000-0000-0000-ffffff000026\"]}}' <your outfile>");
match serde_json::to_writer(bwrite, &modlist) {
Ok(_) =>
info!("next step: kanidm raw modify -D admin '{{\"Eq\": [\"uuid\", \"00000000-0000-0000-0000-ffffff000026\"]}}' <outfile>"),
Err(e) => {
error!("Failed to serialised modifications - {:?}", e)
}
}
} else {
// - printed in json format
serde_json::to_writer_pretty(bwrite, &filt_pwset).expect("Failed to serialise modlist");
if let Err(e) = serde_json::to_writer_pretty(bwrite, &filt_pwset) {
error!("Failed to serialised badlist - {:?}", e)
}
}
}

View file

@ -1,3 +1,13 @@
#![deny(warnings)]
#![warn(unused_extern_crates)]
#![deny(clippy::unwrap_used)]
#![deny(clippy::expect_used)]
#![deny(clippy::panic)]
#![deny(clippy::unreachable)]
#![deny(clippy::await_holding_lock)]
#![deny(clippy::needless_pass_by_value)]
#![deny(clippy::trivially_copy_pass_by_ref)]
use kanidm_cli::ClientOpt;
use structopt::StructOpt;

View file

@ -1,8 +1,18 @@
#![deny(warnings)]
#![warn(unused_extern_crates)]
#![deny(clippy::unwrap_used)]
#![deny(clippy::expect_used)]
#![deny(clippy::panic)]
#![deny(clippy::unreachable)]
#![deny(clippy::await_holding_lock)]
#![deny(clippy::needless_pass_by_value)]
#![deny(clippy::trivially_copy_pass_by_ref)]
use std::path::PathBuf;
use kanidm_client::KanidmClientBuilder;
use log::debug;
use log::{debug, error};
use structopt::StructOpt;
#[derive(Debug, StructOpt)]
@ -34,35 +44,54 @@ fn main() {
let config_path: String = shellexpand::tilde("~/.config/kanidm").into_owned();
debug!("Attempting to use config {}", "/etc/kanidm/config");
let client_builder = KanidmClientBuilder::new()
let client_builder = match KanidmClientBuilder::new()
.read_options_from_optional_config("/etc/kanidm/config")
.and_then(|cb| {
debug!("Attempting to use config {}", config_path);
cb.read_options_from_optional_config(config_path)
})
.expect("Failed to parse config (if present)");
}) {
Ok(c) => c,
Err(e) => {
error!("Failed to parse config (if present) -- {:?}", e);
std::process::exit(1);
}
};
let client_builder = match &opt.addr {
Some(a) => client_builder.address(a.to_string()),
None => client_builder,
};
let ca_path: Option<&str> = opt.ca_path.as_ref().map(|p| p.to_str().unwrap());
let ca_path: Option<&str> = opt.ca_path.as_ref().map(|p| p.to_str()).flatten();
let client_builder = match ca_path {
Some(p) => client_builder
.add_root_certificate_filepath(p)
.expect("Failed to access CA file"),
Some(p) => match client_builder.add_root_certificate_filepath(p) {
Ok(cb) => cb,
Err(e) => {
error!("Failed to add ca certificate -- {:?}", e);
std::process::exit(1);
}
},
None => client_builder,
};
let client = client_builder
.build()
.expect("Failed to build client instance");
let client = match client_builder.build() {
Ok(c) => c,
Err(e) => {
error!("Failed to build client instance -- {:?}", e);
std::process::exit(1);
}
};
let r = if opt.username == "anonymous" {
client.auth_anonymous()
} else {
let password = rpassword::prompt_password_stderr("Enter password: ").unwrap();
let password = match rpassword::prompt_password_stderr("Enter password: ") {
Ok(pw) => pw,
Err(e) => {
error!("Failed to retrieve password - {:?}", e);
std::process::exit(1);
}
};
client.auth_simple_password(opt.username.as_str(), password.as_str())
};
@ -71,11 +100,8 @@ fn main() {
std::process::exit(1);
}
let pkeys = client
.idm_account_get_ssh_pubkeys(opt.account_id.as_str())
.unwrap();
for pkey in pkeys {
println!("{}", pkey)
match client.idm_account_get_ssh_pubkeys(opt.account_id.as_str()) {
Ok(pkeys) => pkeys.iter().for_each(|pkey| println!("{}", pkey)),
Err(e) => error!("Failed to retrieve pubkeys - {:?}", e),
}
}

View file

@ -66,6 +66,7 @@ r2d2_sqlite = "0.16"
reqwest = { version = "0.10" }
users = "0.10"
async-std = "1.6"
[features]
default = [ "libsqlite3-sys/bundled" ]

View file

@ -49,7 +49,7 @@ impl ToString for Id {
impl CacheLayer {
// TODO: Could consider refactoring this to be better ...
#[allow(clippy::too_many_arguments)]
pub fn new(
pub async fn new(
// need db path
path: &str,
// cache timeout
@ -67,7 +67,7 @@ impl CacheLayer {
// setup and do a migrate.
{
let dbtxn = db.write();
let dbtxn = db.write().await;
dbtxn.migrate()?;
dbtxn.commit()?;
}
@ -108,34 +108,37 @@ impl CacheLayer {
self.set_cachestate(CacheState::Offline).await;
}
pub fn clear_cache(&self) -> Result<(), ()> {
let dbtxn = self.db.write();
pub async fn clear_cache(&self) -> Result<(), ()> {
let dbtxn = self.db.write().await;
dbtxn.clear_cache().and_then(|_| dbtxn.commit())
}
pub fn invalidate(&self) -> Result<(), ()> {
let dbtxn = self.db.write();
pub async fn invalidate(&self) -> Result<(), ()> {
let dbtxn = self.db.write().await;
dbtxn.invalidate().and_then(|_| dbtxn.commit())
}
fn get_cached_usertokens(&self) -> Result<Vec<UnixUserToken>, ()> {
let dbtxn = self.db.write();
async fn get_cached_usertokens(&self) -> Result<Vec<UnixUserToken>, ()> {
let dbtxn = self.db.write().await;
dbtxn.get_accounts()
}
fn get_cached_grouptokens(&self) -> Result<Vec<UnixGroupToken>, ()> {
let dbtxn = self.db.write();
async fn get_cached_grouptokens(&self) -> Result<Vec<UnixGroupToken>, ()> {
let dbtxn = self.db.write().await;
dbtxn.get_groups()
}
fn get_cached_usertoken(&self, account_id: &Id) -> Result<(bool, Option<UnixUserToken>), ()> {
async fn get_cached_usertoken(
&self,
account_id: &Id,
) -> Result<(bool, Option<UnixUserToken>), ()> {
// Account_id could be:
// * gidnumber
// * name
// * spn
// * uuid
// Attempt to search these in the db.
let dbtxn = self.db.write();
let dbtxn = self.db.write().await;
let r = dbtxn.get_account(&account_id)?;
match r {
@ -155,14 +158,17 @@ impl CacheLayer {
}
}
fn get_cached_grouptoken(&self, grp_id: &Id) -> Result<(bool, Option<UnixGroupToken>), ()> {
async fn get_cached_grouptoken(
&self,
grp_id: &Id,
) -> Result<(bool, Option<UnixGroupToken>), ()> {
// grp_id could be:
// * gidnumber
// * name
// * spn
// * uuid
// Attempt to search these in the db.
let dbtxn = self.db.write();
let dbtxn = self.db.write().await;
let r = dbtxn.get_group(&grp_id)?;
match r {
@ -182,7 +188,7 @@ impl CacheLayer {
}
}
fn set_cache_usertoken(&self, token: &UnixUserToken) -> Result<(), ()> {
async fn set_cache_usertoken(&self, token: &UnixUserToken) -> Result<(), ()> {
// Set an expiry
let ex_time = SystemTime::now() + Duration::from_secs(self.timeout_seconds);
let offset = ex_time
@ -191,7 +197,7 @@ impl CacheLayer {
error!("time conversion error - ex_time less than epoch? {:?}", e);
})?;
let dbtxn = self.db.write();
let dbtxn = self.db.write().await;
// We need to add the groups first
token
.groups
@ -204,7 +210,7 @@ impl CacheLayer {
.and_then(|_| dbtxn.commit())
}
fn set_cache_grouptoken(&self, token: &UnixGroupToken) -> Result<(), ()> {
async fn set_cache_grouptoken(&self, token: &UnixGroupToken) -> Result<(), ()> {
// Set an expiry
let ex_time = SystemTime::now() + Duration::from_secs(self.timeout_seconds);
let offset = ex_time
@ -213,31 +219,31 @@ impl CacheLayer {
error!("time conversion error - ex_time less than epoch? {:?}", e);
})?;
let dbtxn = self.db.write();
let dbtxn = self.db.write().await;
dbtxn
.update_group(token, offset.as_secs())
.and_then(|_| dbtxn.commit())
}
fn delete_cache_usertoken(&self, a_uuid: &str) -> Result<(), ()> {
let dbtxn = self.db.write();
async fn delete_cache_usertoken(&self, a_uuid: &str) -> Result<(), ()> {
let dbtxn = self.db.write().await;
dbtxn.delete_account(a_uuid).and_then(|_| dbtxn.commit())
}
fn delete_cache_grouptoken(&self, g_uuid: &str) -> Result<(), ()> {
let dbtxn = self.db.write();
async fn delete_cache_grouptoken(&self, g_uuid: &str) -> Result<(), ()> {
let dbtxn = self.db.write().await;
dbtxn.delete_group(g_uuid).and_then(|_| dbtxn.commit())
}
fn set_cache_userpassword(&self, a_uuid: &str, cred: &str) -> Result<(), ()> {
let dbtxn = self.db.write();
async fn set_cache_userpassword(&self, a_uuid: &str, cred: &str) -> Result<(), ()> {
let dbtxn = self.db.write().await;
dbtxn
.update_account_password(a_uuid, cred)
.and_then(|x| dbtxn.commit().map(|_| x))
}
fn check_cache_userpassword(&self, a_uuid: &str, cred: &str) -> Result<bool, ()> {
let dbtxn = self.db.write();
async fn check_cache_userpassword(&self, a_uuid: &str, cred: &str) -> Result<bool, ()> {
let dbtxn = self.db.write().await;
dbtxn
.check_account_password(a_uuid, cred)
.and_then(|x| dbtxn.commit().map(|_| x))
@ -255,7 +261,7 @@ impl CacheLayer {
{
Ok(n_tok) => {
// We have the token!
self.set_cache_usertoken(&n_tok)?;
self.set_cache_usertoken(&n_tok).await?;
Ok(Some(n_tok))
}
Err(e) => {
@ -296,12 +302,10 @@ impl CacheLayer {
// We wele able to contact the server but the entry has been removed, or
// is not longer a valid posix account.
debug!("entry has been removed or is no longer a valid posix account, clearing from cache ... - eventid {}", opid);
token
.map(|tok| self.delete_cache_usertoken(&tok.uuid))
// Now an option<result<t, _>>
.transpose()
// now result<option<t>, _>
.map(|_| None)
if let Some(tok) = token {
self.delete_cache_usertoken(&tok.uuid).await?;
};
Ok(None)
}
er => {
error!("client error -> {:?}", er);
@ -325,7 +329,7 @@ impl CacheLayer {
{
Ok(n_tok) => {
// We have the token!
self.set_cache_grouptoken(&n_tok)?;
self.set_cache_grouptoken(&n_tok).await?;
Ok(Some(n_tok))
}
Err(e) => {
@ -364,12 +368,10 @@ impl CacheLayer {
opid,
) => {
debug!("entry has been removed or is no longer a valid posix group, clearing from cache ... - eventid {}", opid);
token
.map(|tok| self.delete_cache_grouptoken(&tok.uuid))
// Now an option<result<t, _>>
.transpose()
// now result<option<t>, _>
.map(|_| None)
if let Some(tok) = token {
self.delete_cache_grouptoken(&tok.uuid).await?;
};
Ok(None)
}
er => {
error!("client error -> {:?}", er);
@ -384,7 +386,7 @@ impl CacheLayer {
async fn get_usertoken(&self, account_id: Id) -> Result<Option<UnixUserToken>, ()> {
debug!("get_usertoken");
// get the item from the cache
let (expired, item) = self.get_cached_usertoken(&account_id).map_err(|e| {
let (expired, item) = self.get_cached_usertoken(&account_id).await.map_err(|e| {
debug!("get_usertoken error -> {:?}", e);
})?;
@ -431,7 +433,7 @@ impl CacheLayer {
async fn get_grouptoken(&self, grp_id: Id) -> Result<Option<UnixGroupToken>, ()> {
debug!("get_grouptoken");
let (expired, item) = self.get_cached_grouptoken(&grp_id).map_err(|e| {
let (expired, item) = self.get_cached_grouptoken(&grp_id).await.map_err(|e| {
debug!("get_grouptoken error -> {:?}", e);
})?;
@ -476,8 +478,8 @@ impl CacheLayer {
}
}
fn get_groupmembers(&self, uuid: &str) -> Vec<String> {
let dbtxn = self.db.write();
async fn get_groupmembers(&self, uuid: &str) -> Vec<String> {
let dbtxn = self.db.write().await;
dbtxn
.get_group_members(uuid)
@ -515,8 +517,8 @@ impl CacheLayer {
.to_string()
}
pub fn get_nssaccounts(&self) -> Result<Vec<NssUser>, ()> {
self.get_cached_usertokens().map(|l| {
pub async fn get_nssaccounts(&self) -> Result<Vec<NssUser>, ()> {
self.get_cached_usertokens().await.map(|l| {
l.into_iter()
.map(|tok| NssUser {
homedir: self.token_homedirectory(&tok),
@ -557,32 +559,34 @@ impl CacheLayer {
.to_string()
}
pub fn get_nssgroups(&self) -> Result<Vec<NssGroup>, ()> {
self.get_cached_grouptokens().map(|l| {
l.into_iter()
.map(|tok| {
let members = self.get_groupmembers(&tok.uuid);
NssGroup {
name: self.token_gidattr(&tok),
gid: tok.gidnumber,
members,
}
})
.collect()
})
pub async fn get_nssgroups(&self) -> Result<Vec<NssGroup>, ()> {
let l = self.get_cached_grouptokens().await?;
let mut r: Vec<_> = Vec::with_capacity(l.len());
for tok in l.into_iter() {
let members = self.get_groupmembers(&tok.uuid).await;
r.push(NssGroup {
name: self.token_gidattr(&tok),
gid: tok.gidnumber,
members,
})
}
Ok(r)
}
async fn get_nssgroup(&self, grp_id: Id) -> Result<Option<NssGroup>, ()> {
let token = self.get_grouptoken(grp_id).await?;
// Get members set.
Ok(token.map(|tok| {
let members = self.get_groupmembers(&tok.uuid);
NssGroup {
name: self.token_gidattr(&tok),
gid: tok.gidnumber,
members,
match token {
Some(tok) => {
let members = self.get_groupmembers(&tok.uuid).await;
Ok(Some(NssGroup {
name: self.token_gidattr(&tok),
gid: tok.gidnumber,
members,
}))
}
}))
None => Ok(None),
}
}
pub async fn get_nssgroup_name(&self, grp_id: &str) -> Result<Option<NssGroup>, ()> {
@ -608,8 +612,8 @@ impl CacheLayer {
{
Ok(Some(n_tok)) => {
debug!("online password check success.");
self.set_cache_usertoken(&n_tok)?;
self.set_cache_userpassword(&n_tok.uuid, cred)?;
self.set_cache_usertoken(&n_tok).await?;
self.set_cache_userpassword(&n_tok.uuid, cred).await?;
Ok(Some(true))
}
Ok(None) => {
@ -624,10 +628,10 @@ impl CacheLayer {
let time = SystemTime::now().add(Duration::from_secs(15));
self.set_cachestate(CacheState::OfflineNextCheck(time))
.await;
token
.as_ref()
.map(|t| self.check_cache_userpassword(&t.uuid, cred))
.transpose()
match token.as_ref() {
Some(t) => self.check_cache_userpassword(&t.uuid, cred).await.map(Some),
None => Ok(None),
}
}
ClientError::Http(
StatusCode::UNAUTHORIZED,
@ -642,10 +646,10 @@ impl CacheLayer {
let time = SystemTime::now().add(Duration::from_secs(15));
self.set_cachestate(CacheState::OfflineNextCheck(time))
.await;
token
.as_ref()
.map(|t| self.check_cache_userpassword(&t.uuid, cred))
.transpose()
match token.as_ref() {
Some(t) => self.check_cache_userpassword(&t.uuid, cred).await.map(Some),
None => Ok(None),
}
}
ClientError::Http(
StatusCode::BAD_REQUEST,
@ -672,16 +676,22 @@ impl CacheLayer {
}
}
fn offline_account_authenticate(
async fn offline_account_authenticate(
&self,
token: &Option<UnixUserToken>,
cred: &str,
) -> Result<Option<bool>, ()> {
debug!("Attempt offline password check");
match token.as_ref() {
Some(t) => self.check_cache_userpassword(&t.uuid, cred).await.map(Some),
None => Ok(None),
}
/*
token
.as_ref()
.map(|t| self.check_cache_userpassword(&t.uuid, cred))
.map(async |t| self.check_cache_userpassword(&t.uuid, cred).await)
.transpose()
*/
}
pub async fn pam_account_allowed(&self, account_id: &str) -> Result<Option<bool>, ()> {
@ -710,7 +720,9 @@ impl CacheLayer {
cred: &str,
) -> Result<Option<bool>, ()> {
let state = self.get_cachestate().await;
let (_expired, token) = self.get_cached_usertoken(&Id::Name(account_id.to_string()))?;
let (_expired, token) = self
.get_cached_usertoken(&Id::Name(account_id.to_string()))
.await?;
match state {
CacheState::Online => {
@ -725,12 +737,12 @@ impl CacheLayer {
.await
} else {
// We are offline, check from the cache if possible.
self.offline_account_authenticate(&token, cred)
self.offline_account_authenticate(&token, cred).await
}
}
_ => {
// We are offline, check from the cache if possible.
self.offline_account_authenticate(&token, cred)
self.offline_account_authenticate(&token, cred).await
}
}
}

View file

@ -1,3 +1,13 @@
#![deny(warnings)]
#![warn(unused_extern_crates)]
#![deny(clippy::unwrap_used)]
#![deny(clippy::expect_used)]
#![deny(clippy::panic)]
#![deny(clippy::unreachable)]
#![deny(clippy::await_holding_lock)]
#![deny(clippy::needless_pass_by_value)]
#![deny(clippy::trivially_copy_pass_by_ref)]
#[macro_use]
extern crate log;

View file

@ -1,3 +1,13 @@
#![deny(warnings)]
#![warn(unused_extern_crates)]
#![deny(clippy::unwrap_used)]
#![deny(clippy::expect_used)]
#![deny(clippy::panic)]
#![deny(clippy::unreachable)]
#![deny(clippy::await_holding_lock)]
#![deny(clippy::needless_pass_by_value)]
#![deny(clippy::trivially_copy_pass_by_ref)]
#[macro_use]
extern crate log;

View file

@ -105,6 +105,7 @@ async fn handle_client(
debug!("nssaccounts req");
cachelayer
.get_nssaccounts()
.await
.map(ClientResponse::NssAccounts)
.unwrap_or_else(|_| {
error!("unable to enum accounts");
@ -137,6 +138,7 @@ async fn handle_client(
debug!("nssgroups req");
cachelayer
.get_nssgroups()
.await
.map(ClientResponse::NssGroups)
.unwrap_or_else(|_| {
error!("unable to enum groups");
@ -185,6 +187,7 @@ async fn handle_client(
debug!("invalidate cache");
cachelayer
.invalidate()
.await
.map(|_| ClientResponse::Ok)
.unwrap_or(ClientResponse::Error)
}
@ -192,6 +195,7 @@ async fn handle_client(
debug!("clear cache");
cachelayer
.clear_cache()
.await
.map(|_| ClientResponse::Ok)
.unwrap_or(ClientResponse::Error)
}
@ -359,6 +363,7 @@ async fn main() {
cfg.uid_attr_map,
cfg.gid_attr_map,
)
.await
.expect("Failed to build cache layer."),
);

View file

@ -1,3 +1,13 @@
#![deny(warnings)]
#![warn(unused_extern_crates)]
#![deny(clippy::unwrap_used)]
#![deny(clippy::expect_used)]
#![deny(clippy::panic)]
#![deny(clippy::unreachable)]
#![deny(clippy::await_holding_lock)]
#![deny(clippy::needless_pass_by_value)]
#![deny(clippy::trivially_copy_pass_by_ref)]
#[macro_use]
extern crate log;

View file

@ -41,8 +41,9 @@ impl Db {
})
}
pub fn write(&self) -> DbTxn {
let guard = self.lock.try_lock().expect("Unable to lock");
#[allow(clippy::expect_used)]
pub async fn write(&self) -> DbTxn<'_> {
let guard = self.lock.lock().await;
let conn = self
.pool
.get()
@ -64,6 +65,7 @@ impl<'a> DbTxn<'a> {
) -> Self {
// Start the transaction
// debug!("Starting db WR txn ...");
#[allow(clippy::expect_used)]
conn.execute("BEGIN TRANSACTION", NO_PARAMS)
.expect("Unable to begin transaction!");
DbTxn {
@ -140,7 +142,10 @@ impl<'a> DbTxn<'a> {
pub fn commit(mut self) -> Result<(), ()> {
// debug!("Commiting BE txn");
assert!(!self.committed);
if self.committed {
error!("Invalid state, txn already commited!");
return Err(());
}
self.committed = true;
self.conn
@ -403,7 +408,9 @@ impl<'a> DbTxn<'a> {
}
pub fn update_account_password(&self, a_uuid: &str, cred: &str) -> Result<(), ()> {
let pw = Password::new(cred);
let pw = Password::new(cred).map_err(|e| {
error!("password error -> {:?}", e);
})?;
let dbpw = pw.to_dbpasswordv1();
let data = serde_cbor::to_vec(&dbpw).map_err(|e| {
error!("cbor error -> {:?}", e);
@ -462,7 +469,9 @@ impl<'a> DbTxn<'a> {
error!("cbor error -> {:?}", e);
})?;
let pw = Password::try_from(dbpw)?;
Ok(pw.verify(cred))
pw.verify(cred).map_err(|e| {
error!("password error -> {:?}", e);
})
})
.unwrap_or(Ok(false));
r
@ -664,6 +673,7 @@ impl<'a> Drop for DbTxn<'a> {
fn drop(self: &mut Self) {
if !self.committed {
// debug!("Aborting BE WR txn");
#[allow(clippy::expect_used)]
self.conn
.execute("ROLLBACK TRANSACTION", NO_PARAMS)
.expect("Unable to rollback transaction! Can not proceed!!!");
@ -675,6 +685,7 @@ impl<'a> Drop for DbTxn<'a> {
mod tests {
use super::Db;
use crate::cache::Id;
use async_std::task;
use kanidm_proto::v1::{UnixGroupToken, UnixUserToken};
const TESTACCOUNT1_PASSWORD_A: &str = "password a for account1 test";
@ -684,7 +695,7 @@ mod tests {
fn test_cache_db_account_basic() {
let _ = env_logger::builder().is_test(true).try_init();
let db = Db::new("").expect("failed to create.");
let dbtxn = db.write();
let dbtxn = task::block_on(db.write());
assert!(dbtxn.migrate().is_ok());
let mut ut1 = UnixUserToken {
@ -767,7 +778,7 @@ mod tests {
fn test_cache_db_group_basic() {
let _ = env_logger::builder().is_test(true).try_init();
let db = Db::new("").expect("failed to create.");
let dbtxn = db.write();
let dbtxn = task::block_on(db.write());
assert!(dbtxn.migrate().is_ok());
let mut gt1 = UnixGroupToken {
@ -842,7 +853,7 @@ mod tests {
fn test_cache_db_account_group_update() {
let _ = env_logger::builder().is_test(true).try_init();
let db = Db::new("").expect("failed to create.");
let dbtxn = db.write();
let dbtxn = task::block_on(db.write());
assert!(dbtxn.migrate().is_ok());
let gt1 = UnixGroupToken {
@ -909,7 +920,7 @@ mod tests {
fn test_cache_db_account_password() {
let _ = env_logger::builder().is_test(true).try_init();
let db = Db::new("").expect("failed to create.");
let dbtxn = db.write();
let dbtxn = task::block_on(db.write());
assert!(dbtxn.migrate().is_ok());
let uuid1 = "0302b99c-f0f6-41ab-9492-852692b0fd16";
@ -957,7 +968,7 @@ mod tests {
fn test_cache_db_group_rename_duplicate() {
let _ = env_logger::builder().is_test(true).try_init();
let db = Db::new("").expect("failed to create.");
let dbtxn = db.write();
let dbtxn = task::block_on(db.write());
assert!(dbtxn.migrate().is_ok());
let mut gt1 = UnixGroupToken {
@ -1012,7 +1023,7 @@ mod tests {
fn test_cache_db_account_rename_duplicate() {
let _ = env_logger::builder().is_test(true).try_init();
let db = Db::new("").expect("failed to create.");
let dbtxn = db.write();
let dbtxn = task::block_on(db.write());
assert!(dbtxn.migrate().is_ok());
let mut ut1 = UnixUserToken {

View file

@ -1,4 +1,13 @@
#![deny(warnings)]
#![warn(unused_extern_crates)]
#![deny(clippy::unwrap_used)]
#![deny(clippy::expect_used)]
#![deny(clippy::panic)]
#![deny(clippy::unreachable)]
#![deny(clippy::await_holding_lock)]
#![deny(clippy::needless_pass_by_value)]
#![deny(clippy::trivially_copy_pass_by_ref)]
#[macro_use]
extern crate log;

View file

@ -17,6 +17,8 @@ use tokio::runtime::Runtime;
use kanidm_client::asynchronous::KanidmAsyncClient;
use kanidm_client::{KanidmClient, KanidmClientBuilder};
use async_std::task;
static PORT_ALLOC: AtomicUsize = AtomicUsize::new(18080);
const ADMIN_TEST_PASSWORD: &str = "integration test admin password";
const TESTACCOUNT1_PASSWORD_A: &str = "password a for account1 test";
@ -76,7 +78,7 @@ fn run_test(fix_fn: fn(&KanidmClient) -> (), test_fn: fn(CacheLayer, KanidmAsync
.build_async()
.expect("Failed to build client");
let cachelayer = CacheLayer::new(
let cachelayer = task::block_on(CacheLayer::new(
"", // The sqlite db path, this is in memory.
300,
rsclient,
@ -86,7 +88,7 @@ fn run_test(fix_fn: fn(&KanidmClient) -> (), test_fn: fn(CacheLayer, KanidmAsync
DEFAULT_HOME_ATTR,
DEFAULT_UID_ATTR_MAP,
DEFAULT_GID_ATTR_MAP,
)
))
.expect("Failed to build cache layer.");
test_fn(cachelayer, client);
@ -213,6 +215,7 @@ fn test_cache_account() {
// Finally, check we have "all accounts" in the list.
let us = cachelayer
.get_nssaccounts()
.await
.expect("failed to list all accounts");
assert!(us.len() == 1);
};
@ -254,7 +257,7 @@ fn test_cache_group() {
assert!(gt.unwrap().members.len() == 0);
// clear cache, go online
assert!(cachelayer.invalidate().is_ok());
assert!(cachelayer.invalidate().await.is_ok());
cachelayer.attempt_online().await;
assert!(cachelayer.test_connection().await);
@ -281,6 +284,7 @@ fn test_cache_group() {
// Finally, check we have "all groups" in the list.
let gs = cachelayer
.get_nssgroups()
.await
.expect("failed to list all groups");
assert!(gs.len() == 2);
};
@ -313,7 +317,7 @@ fn test_cache_group_delete() {
.expect("failed to delete");
// invalidate cache
assert!(cachelayer.invalidate().is_ok());
assert!(cachelayer.invalidate().await.is_ok());
// "get it"
// should be empty.
@ -352,7 +356,7 @@ fn test_cache_account_delete() {
.expect("failed to delete");
// invalidate cache
assert!(cachelayer.invalidate().is_ok());
assert!(cachelayer.invalidate().await.is_ok());
// "get it"
let ut = cachelayer
@ -435,7 +439,10 @@ fn test_cache_account_password() {
assert!(a6 == Some(false));
// clear cache
cachelayer.clear_cache().expect("failed to clear cache");
cachelayer
.clear_cache()
.await
.expect("failed to clear cache");
// test auth good (fail)
let a7 = cachelayer
@ -483,7 +490,7 @@ fn test_cache_account_pam_allowed() {
.unwrap();
// Invalidate cache to force a refresh
assert!(cachelayer.invalidate().is_ok());
assert!(cachelayer.invalidate().await.is_ok());
// Should pass
let a2 = cachelayer

View file

@ -695,7 +695,7 @@ pub trait AccessControlsTransaction {
*/
// Now purge the attrs that are NOT in this.
e.reduce_attributes(allowed_attrs)
e.reduce_attributes(&allowed_attrs)
})
.collect()
}
@ -810,14 +810,14 @@ pub trait AccessControlsTransaction {
// existance, and second, we would have failed the mod at schema checking
// earlier in the process as these were not correctly type. As a result
// we can trust these to be correct here and not to be "None".
Some(v.to_str_unwrap())
v.to_str()
} else {
None
}
}
Modify::Removed(a, v) => {
if a.as_str() == "class" {
Some(v.to_str_unwrap())
v.to_str()
} else {
None
}
@ -2018,7 +2018,7 @@ mod tests {
ModifyEvent::new_impersonate_entry_ser(
JSON_ADMIN_V1,
filter_all!(f_eq("name", PartialValue::new_iname("testperson1"))),
modlist!([m_pres("name", &Value::new_iname_s("value"))]),
modlist!([m_pres("name", &Value::new_iname("value"))]),
)
};
// Name rem

View file

@ -264,7 +264,7 @@ impl Handler<SearchMessage> for QueryServerReadV1 {
match qs_read.search_ext(&mut audit, &srch) {
Ok(entries) => {
SearchResult::new(&mut audit, &qs_read, entries).map(|ok_sr| ok_sr.response())
SearchResult::new(&mut audit, &qs_read, &entries).map(|ok_sr| ok_sr.response())
}
Err(e) => Err(e),
}
@ -303,7 +303,10 @@ impl Handler<AuthMessage> for QueryServerReadV1 {
let ct = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.expect("Clock failure!");
.map_err(|e| {
ladmin_error!(audit, "Clock Error -> {:?}", e);
OperationError::InvalidState
})?;
// Trigger a session clean *before* we take any auth steps.
// It's important to do this before to ensure that timeouts on
@ -368,9 +371,10 @@ impl Handler<WhoamiMessage> for QueryServerReadV1 {
match entries.len() {
0 => Err(OperationError::NoMatchingEntries),
1 => {
#[allow(clippy::expect_used)]
let e = entries.pop().expect("Entry length mismatch!!!");
// Now convert to a response, and return
WhoamiResult::new(&mut audit, &qs_read, e, uat)
WhoamiResult::new(&mut audit, &qs_read, &e, uat)
.map(|ok_wr| ok_wr.response())
}
// Somehow we matched multiple, which should be impossible.
@ -414,7 +418,7 @@ impl Handler<InternalSearchMessage> for QueryServerReadV1 {
ltrace!(audit, "Begin event {:?}", srch);
match qs_read.search_ext(&mut audit, &srch) {
Ok(entries) => SearchResult::new(&mut audit, &qs_read, entries)
Ok(entries) => SearchResult::new(&mut audit, &qs_read, &entries)
.map(|ok_sr| ok_sr.into_proto_array()),
Err(e) => Err(e),
}
@ -460,7 +464,7 @@ impl Handler<InternalSearchRecycledMessage> for QueryServerReadV1 {
ltrace!(audit, "Begin event {:?}", srch);
match qs_read.search_ext(&mut audit, &srch) {
Ok(entries) => SearchResult::new(&mut audit, &qs_read, entries)
Ok(entries) => SearchResult::new(&mut audit, &qs_read, &entries)
.map(|ok_sr| ok_sr.into_proto_array()),
Err(e) => Err(e),
}
@ -877,7 +881,10 @@ impl Handler<IdmAccountUnixAuthMessage> for QueryServerReadV1 {
let ct = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.expect("Clock failure!");
.map_err(|e| {
ladmin_error!(audit, "Clock Error -> {:?}", e);
OperationError::InvalidState
})?;
let r = idm_write
.auth_unix(&mut audit, &uuae, ct)

View file

@ -178,14 +178,14 @@ impl IdmGroupUnixExtendMessage {
pub fn new(
uat: Option<UserAuthToken>,
uuid_or_name: String,
gx: GroupUnixExtend,
gx: &GroupUnixExtend,
eventid: Uuid,
) -> Self {
let GroupUnixExtend { gidnumber } = gx;
// let GroupUnixExtend { gidnumber } = gx;
IdmGroupUnixExtendMessage {
uat,
uuid_or_name,
gidnumber,
gidnumber: gx.gidnumber,
eventid,
}
}
@ -353,18 +353,16 @@ impl QueryServerWriteV1 {
&mut self,
audit: &mut AuditScope,
uat: Option<UserAuthToken>,
uuid_or_name: String,
proto_ml: ProtoModifyList,
uuid_or_name: &str,
proto_ml: &ProtoModifyList,
filter: Filter<FilterInvalid>,
) -> Result<(), OperationError> {
let qs_write = self.qs.write(duration_from_epoch_now());
let target_uuid = qs_write
.name_to_uuid(audit, uuid_or_name.as_str())
.map_err(|e| {
ladmin_error!(audit, "Error resolving id to target");
e
})?;
let target_uuid = qs_write.name_to_uuid(audit, uuid_or_name).map_err(|e| {
ladmin_error!(audit, "Error resolving id to target");
e
})?;
let mdf =
match ModifyEvent::from_parts(audit, uat, target_uuid, proto_ml, filter, &qs_write) {
@ -386,18 +384,16 @@ impl QueryServerWriteV1 {
&mut self,
audit: &mut AuditScope,
uat: Option<UserAuthToken>,
uuid_or_name: String,
ml: ModifyList<ModifyInvalid>,
uuid_or_name: &str,
ml: &ModifyList<ModifyInvalid>,
filter: Filter<FilterInvalid>,
) -> Result<(), OperationError> {
let qs_write = self.qs.write(duration_from_epoch_now());
let target_uuid = qs_write
.name_to_uuid(audit, uuid_or_name.as_str())
.map_err(|e| {
ladmin_error!(audit, "Error resolving id to target");
e
})?;
let target_uuid = qs_write.name_to_uuid(audit, uuid_or_name).map_err(|e| {
ladmin_error!(audit, "Error resolving id to target");
e
})?;
let mdf = match ModifyEvent::from_internal_parts(
audit,
@ -535,7 +531,7 @@ impl Handler<InternalDeleteMessage> for QueryServerWriteV1 {
|| {
let qs_write = self.qs.write(duration_from_epoch_now());
let del = match DeleteEvent::from_parts(&mut audit, msg.uat, msg.filter, &qs_write)
let del = match DeleteEvent::from_parts(&mut audit, msg.uat, &msg.filter, &qs_write)
{
Ok(d) => d,
Err(e) => {
@ -610,7 +606,7 @@ impl Handler<InternalCredentialSetMessage> for QueryServerWriteV1 {
"actors::v1_write::handle<InternalCredentialSetMessage>",
|| {
let ct = duration_from_epoch_now();
let mut idms_prox_write = self.idms.proxy_write(ct.clone());
let mut idms_prox_write = self.idms.proxy_write(ct);
// Trigger a session clean *before* we take any auth steps.
// It's important to do this before to ensure that timeouts on
@ -737,7 +733,7 @@ impl Handler<IdmAccountSetPasswordMessage> for QueryServerWriteV1 {
"actors::v1_write::handle<IdmAccountSetPasswordMessage>",
|| {
let ct = duration_from_epoch_now();
let mut idms_prox_write = self.idms.proxy_write(ct.clone());
let mut idms_prox_write = self.idms.proxy_write(ct);
idms_prox_write.expire_mfareg_sessions(ct);
let pce = PasswordChangeEvent::from_idm_account_set_password(
@ -779,7 +775,7 @@ impl Handler<InternalRegenerateRadiusMessage> for QueryServerWriteV1 {
"actors::v1_write::handle<InternalRegenerateRadiusMessage>",
|| {
let ct = duration_from_epoch_now();
let mut idms_prox_write = self.idms.proxy_write(ct.clone());
let mut idms_prox_write = self.idms.proxy_write(ct);
idms_prox_write.expire_mfareg_sessions(ct);
let target_uuid = idms_prox_write
@ -840,7 +836,7 @@ impl Handler<PurgeAttributeMessage> for QueryServerWriteV1 {
&mut audit,
msg.uat,
target_uuid,
msg.attr,
&msg.attr,
msg.filter,
&qs_write,
) {
@ -891,7 +887,7 @@ impl Handler<RemoveAttributeValueMessage> for QueryServerWriteV1 {
&mut audit,
msg.uat,
target_uuid,
proto_ml,
&proto_ml,
msg.filter,
&qs_write,
) {
@ -942,7 +938,7 @@ impl Handler<AppendAttributeMessage> for QueryServerWriteV1 {
.map(|v| ProtoModify::Present(attr.clone(), v))
.collect(),
);
self.modify_from_parts(&mut audit, uat, uuid_or_name, proto_ml, filter)
self.modify_from_parts(&mut audit, uat, &uuid_or_name, &proto_ml, filter)
}
);
self.log.send(Some(audit)).map_err(|_| {
@ -981,7 +977,7 @@ impl Handler<SetAttributeMessage> for QueryServerWriteV1 {
)
.collect(),
);
self.modify_from_parts(&mut audit, uat, uuid_or_name, proto_ml, filter)
self.modify_from_parts(&mut audit, uat, &uuid_or_name, &proto_ml, filter)
}
);
self.log.send(Some(audit)).map_err(|_| {
@ -1013,7 +1009,7 @@ impl Handler<InternalSshKeyCreateMessage> for QueryServerWriteV1 {
// than relying on the proto ones.
let ml = ModifyList::new_append("ssh_publickey", Value::new_sshkey(tag, key));
self.modify_from_internal_parts(&mut audit, uat, uuid_or_name, ml, filter)
self.modify_from_internal_parts(&mut audit, uat, &uuid_or_name, &ml, filter)
}
);
self.log.send(Some(audit)).map_err(|_| {
@ -1056,7 +1052,7 @@ impl Handler<IdmAccountPersonExtendMessage> for QueryServerWriteV1 {
let filter = filter_all!(f_eq("class", PartialValue::new_class("account")));
self.modify_from_internal_parts(&mut audit, uat, uuid_or_name, ml, filter)
self.modify_from_internal_parts(&mut audit, uat, &uuid_or_name, &ml, filter)
}
);
self.log.send(Some(audit)).map_err(|_| {
@ -1092,7 +1088,9 @@ impl Handler<IdmAccountUnixExtendMessage> for QueryServerWriteV1 {
)),
gidnumber
.map(|n| Modify::Present("gidnumber".to_string(), Value::new_uint32(n))),
shell.map(|s| Modify::Present("loginshell".to_string(), Value::new_iutf8(s))),
shell.map(|s| {
Modify::Present("loginshell".to_string(), Value::new_iutf8(s.as_str()))
}),
]
.into_iter()
.filter_map(|v| v)
@ -1102,7 +1100,7 @@ impl Handler<IdmAccountUnixExtendMessage> for QueryServerWriteV1 {
let filter = filter_all!(f_eq("class", PartialValue::new_class("account")));
self.modify_from_internal_parts(&mut audit, uat, uuid_or_name, ml, filter)
self.modify_from_internal_parts(&mut audit, uat, &uuid_or_name, &ml, filter)
}
);
self.log.send(Some(audit)).map_err(|_| {
@ -1146,7 +1144,7 @@ impl Handler<IdmGroupUnixExtendMessage> for QueryServerWriteV1 {
let filter = filter_all!(f_eq("class", PartialValue::new_class("group")));
self.modify_from_internal_parts(&mut audit, uat, uuid_or_name, ml, filter)
self.modify_from_internal_parts(&mut audit, uat, &uuid_or_name, &ml, filter)
}
);
self.log.send(Some(audit)).map_err(|_| {
@ -1167,7 +1165,7 @@ impl Handler<IdmAccountUnixSetCredMessage> for QueryServerWriteV1 {
"actors::v1_write::handle<IdmAccountUnixSetCredMessage>",
|| {
let ct = duration_from_epoch_now();
let mut idms_prox_write = self.idms.proxy_write(ct.clone());
let mut idms_prox_write = self.idms.proxy_write(ct);
idms_prox_write.expire_mfareg_sessions(ct);
let target_uuid = Uuid::parse_str(msg.uuid_or_name.as_str()).or_else(|_| {
@ -1223,6 +1221,7 @@ impl Handler<PurgeTombstoneEvent> for QueryServerWriteV1 {
.purge_tombstones(&mut audit)
.and_then(|_| qs_write.commit(&mut audit));
ladmin_info!(audit, "Purge tombstones result: {:?}", res);
#[allow(clippy::expect_used)]
res.expect("Invalid Server State");
}
);
@ -1249,6 +1248,7 @@ impl Handler<PurgeRecycledEvent> for QueryServerWriteV1 {
.purge_recycled(&mut audit)
.and_then(|_| qs_write.commit(&mut audit));
ladmin_info!(audit, "Purge recycled result: {:?}", res);
#[allow(clippy::expect_used)]
res.expect("Invalid Server State");
}
);

View file

@ -1,7 +1,7 @@
use crate::audit::AuditScope;
use crossbeam::channel::Receiver;
pub fn run(rx: Receiver<Option<AuditScope>>) {
pub fn run(rx: &Receiver<Option<AuditScope>>) {
info!("Log thread started ...");
loop {
match rx.recv() {

View file

@ -309,7 +309,8 @@ struct AuditLog {
pub struct PerfEvent {
id: String,
duration: Option<Duration>,
contains: Vec<PerfEvent>,
#[allow(clippy::vec_box)]
contains: Vec<Box<PerfEvent>>,
#[serde(skip_serializing)]
parent: Option<&'static mut PerfEvent>,
}
@ -322,10 +323,14 @@ impl PerfEvent {
.map(|pe| pe.process_inner(opd))
.collect();
contains.sort_unstable();
let duration = self.duration.as_ref().expect("corrupted perf event");
let duration = self
.duration
.as_ref()
.copied()
.unwrap_or_else(|| Duration::new(0, 0));
let percent = (duration.as_secs_f64() / opd.as_secs_f64()) * 100.0;
PerfProcessed {
duration: *duration,
duration,
id: self.id.clone(),
percent,
contains,
@ -333,7 +338,11 @@ impl PerfEvent {
}
fn process(&self) -> PerfProcessed {
let duration = self.duration.as_ref().expect("corrupted perf event");
let duration = self
.duration
.as_ref()
.copied()
.unwrap_or_else(|| Duration::new(0, 0));
let mut contains: Vec<_> = self
.contains
.iter()
@ -341,7 +350,7 @@ impl PerfEvent {
.collect();
contains.sort_unstable();
PerfProcessed {
duration: *duration,
duration,
id: self.id.clone(),
percent: 100.0,
contains,
@ -423,7 +432,8 @@ pub struct AuditScope {
pub level: u32,
uuid: Uuid,
events: Vec<AuditLog>,
perf: Vec<PerfEvent>,
#[allow(clippy::vec_box)]
perf: Vec<Box<PerfEvent>>,
// active perf event
#[serde(skip_serializing)]
active_perf: Option<&'static mut PerfEvent>,
@ -516,14 +526,20 @@ impl AuditScope {
// Does an active event currently exist?
if self.active_perf.is_none() {
// No, we are a new event.
self.perf.push(PerfEvent {
self.perf.push(Box::new(PerfEvent {
id: id.to_string(),
duration: None,
contains: vec![],
parent: None,
});
// Get a put ptr, we are now the active.
let xref = self.perf.last_mut().expect("perf alloc failure?") as *mut PerfEvent;
}));
// Get a our ptr, we are now the active.
let idx = self.perf.len() - 1;
let xref = self
.perf
// Get the box
.get_unchecked_mut(idx)
// Now the mut ptr to the inner of hte box
.as_mut() as *mut PerfEvent;
let mref = &mut (*xref);
self.active_perf = Some(mref);
// return the mut ptr.
@ -532,15 +548,18 @@ impl AuditScope {
// Yes, there is an active event.
// get the currennt active ptr
let xref = if let Some(ref mut iparent) = self.active_perf {
iparent.contains.push(PerfEvent {
iparent.contains.push(Box::new(PerfEvent {
id: id.to_string(),
duration: None,
contains: vec![],
parent: None,
});
iparent.contains.last_mut().expect("perf alloc failure?") as *mut PerfEvent
}));
let idx = iparent.contains.len() - 1;
iparent.contains.get_unchecked_mut(idx).as_mut() as *mut PerfEvent
} else {
panic!("Invalid parent state");
#[allow(clippy::unreachable)]
unreachable!("Invalid parent state");
};
// Alloc in the vec, set parnt to active, then get a mut pointer
// to ourself, then set ourself as the active.

View file

@ -518,9 +518,13 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
idl_cache.iter_mut_mark_clean().try_for_each(|(k, v)| {
match v {
Some(idl) => db.write_idl(audit, k.a.as_str(), &k.i, k.k.as_str(), idl),
#[allow(clippy::unreachable)]
None => {
// Due to how we remove items, we always write an empty idl
// to the cache, so this should never be none.
//
// If it is none, this means we have memory corruption so we MUST
// panic.
unreachable!();
}
}
@ -561,14 +565,13 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
})?;
// Undo the caches in the reverse order.
db.commit(audit).and_then(|()| {
db.commit(audit).map(|()| {
op_ts_max.commit();
name_cache.commit();
idl_cache.commit();
entry_cache.commit();
allids.commit();
maxid.commit();
Ok(())
})
})
}
@ -791,16 +794,14 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
}
pub unsafe fn purge_idxs(&mut self, audit: &mut AuditScope) -> Result<(), OperationError> {
self.db.purge_idxs(audit).and_then(|()| {
self.db.purge_idxs(audit).map(|()| {
self.idl_cache.clear();
Ok(())
})
}
pub unsafe fn purge_id2entry(&mut self, audit: &mut AuditScope) -> Result<(), OperationError> {
self.db.purge_id2entry(audit).and_then(|()| {
self.db.purge_id2entry(audit).map(|()| {
self.entry_cache.clear();
Ok(())
})
}

View file

@ -449,6 +449,7 @@ impl Drop for IdlSqliteReadTransaction {
// Abort - so far this has proven reliable to use drop here.
fn drop(self: &mut Self) {
if !self.committed {
#[allow(clippy::expect_used)]
self.conn
.execute("ROLLBACK TRANSACTION", NO_PARAMS)
// We can't do this without expect.
@ -468,6 +469,7 @@ impl IdlSqliteReadTransaction {
// this a Result<>
//
// There is no way to flag this is an RO operation.
#[allow(clippy::expect_used)]
conn.execute("BEGIN TRANSACTION", NO_PARAMS)
.expect("Unable to begin transaction!");
IdlSqliteReadTransaction {
@ -487,6 +489,7 @@ impl Drop for IdlSqliteWriteTransaction {
// Abort
fn drop(self: &mut Self) {
if !self.committed {
#[allow(clippy::expect_used)]
self.conn
.execute("ROLLBACK TRANSACTION", NO_PARAMS)
.expect("Unable to rollback transaction! Can not proceed!!!");
@ -497,6 +500,7 @@ impl Drop for IdlSqliteWriteTransaction {
impl IdlSqliteWriteTransaction {
pub fn new(conn: r2d2::PooledConnection<SqliteConnectionManager>) -> Self {
// Start the transaction
#[allow(clippy::expect_used)]
conn.execute("BEGIN TRANSACTION", NO_PARAMS)
.expect("Unable to begin transaction!");
IdlSqliteWriteTransaction {
@ -1253,6 +1257,7 @@ impl IdlSqlite {
}
pub fn read(&self) -> IdlSqliteReadTransaction {
#[allow(clippy::expect_used)]
let conn = self
.pool
.get()
@ -1261,6 +1266,7 @@ impl IdlSqlite {
}
pub fn write(&self) -> IdlSqliteWriteTransaction {
#[allow(clippy::expect_used)]
let conn = self
.pool
.get()

View file

@ -1,4 +1,3 @@
use std::convert::TryFrom;
use std::fs;
use crate::value::IndexType;
@ -87,8 +86,8 @@ impl IdRawEntry {
) -> Result<Entry<EntrySealed, EntryCommitted>, OperationError> {
let db_e = serde_cbor::from_slice(self.data.as_slice())
.map_err(|_| OperationError::SerdeCborError)?;
let id = u64::try_from(self.id).map_err(|_| OperationError::InvalidEntryID)?;
Entry::from_dbentry(au, db_e, id).map_err(|_| OperationError::CorruptedEntry(id))
// let id = u64::try_from(self.id).map_err(|_| OperationError::InvalidEntryID)?;
Entry::from_dbentry(au, db_e, self.id).map_err(|_| OperationError::CorruptedEntry(self.id))
}
}
@ -721,9 +720,7 @@ impl<'a> BackendWriteTransaction<'a> {
let idlayer = self.get_idlayer();
// Now, assign id's to all the new entries.
let mut id_max = idlayer.get_id2entry_max_id().and_then(|id_max| {
u64::try_from(id_max).map_err(|_| OperationError::InvalidEntryID)
})?;
let mut id_max = idlayer.get_id2entry_max_id()?;
let c_entries: Vec<_> = entries
.into_iter()
.map(|e| {
@ -891,9 +888,11 @@ impl<'a> BackendWriteTransaction<'a> {
// check from the Entry::idx functions as they only yield partial
// changes. Because the uuid is changing, we have to treat pre
// as a deleting entry, regardless of what state post is in.
let uuid = mask_pre
.map(|e| e.get_uuid())
.expect("Not possible to fail");
let uuid = mask_pre.map(|e| e.get_uuid()).ok_or_else(|| {
ladmin_error!(audit, "Invalid entry state - possible memory corruption");
OperationError::InvalidState
})?;
let (n2u_add, n2u_rem) = Entry::idx_name2uuid_diff(mask_pre, None);
// There will never be content to add.
assert!(n2u_add.is_none());
@ -1221,9 +1220,8 @@ impl<'a> BackendWriteTransaction<'a> {
// Unwrap the Cell we have finished with it.
let idlayer = idlayer.into_inner();
idlayer.commit(audit).and_then(|()| {
idlayer.commit(audit).map(|()| {
idxmeta_wr.commit();
Ok(())
})
}
@ -1235,6 +1233,7 @@ impl<'a> BackendWriteTransaction<'a> {
}
pub fn get_db_s_uuid(&self) -> Uuid {
#[allow(clippy::expect_used)]
match self
.get_idlayer()
.get_db_s_uuid()
@ -1252,6 +1251,7 @@ impl<'a> BackendWriteTransaction<'a> {
}
pub fn get_db_d_uuid(&self) -> Uuid {
#[allow(clippy::expect_used)]
match self
.get_idlayer()
.get_db_d_uuid()
@ -1334,8 +1334,13 @@ impl Backend {
// Should this actually call the idlayer directly?
pub fn reset_db_s_uuid(&self, audit: &mut AuditScope) -> Uuid {
let wr = self.write();
let sid = wr.reset_db_s_uuid().unwrap();
wr.commit(audit).unwrap();
#[allow(clippy::expect_used)]
let sid = wr
.reset_db_s_uuid()
.expect("unable to reset db server uuid");
#[allow(clippy::expect_used)]
wr.commit(audit)
.expect("Unable to commit to backend, can not proceed");
sid
}
@ -1732,12 +1737,12 @@ mod tests {
run_test!(|audit: &mut AuditScope, be: &mut BackendWriteTransaction| {
// Add some test data?
let mut e1: Entry<EntryInit, EntryNew> = Entry::new();
e1.add_ava("name", Value::new_iname_s("william"));
e1.add_ava("name", Value::new_iname("william"));
e1.add_ava("uuid", Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"));
let e1 = unsafe { e1.into_sealed_new() };
let mut e2: Entry<EntryInit, EntryNew> = Entry::new();
e2.add_ava("name", Value::new_iname_s("claire"));
e2.add_ava("name", Value::new_iname("claire"));
e2.add_ava("uuid", Value::from("bd651620-00dd-426b-aaa0-4494f7b7906f"));
let e2 = unsafe { e2.into_sealed_new() };
@ -1846,8 +1851,8 @@ mod tests {
assert!(be.name2uuid(audit, "william") == Ok(Some(william_uuid)));
assert!(be.name2uuid(audit, "db237e8a-0079-4b8c-8a56-593b22aa44d1") == Ok(None));
// check uuid2spn
assert!(be.uuid2spn(audit, &claire_uuid) == Ok(Some(Value::new_iname_s("claire"))));
assert!(be.uuid2spn(audit, &william_uuid) == Ok(Some(Value::new_iname_s("william"))));
assert!(be.uuid2spn(audit, &claire_uuid) == Ok(Some(Value::new_iname("claire"))));
assert!(be.uuid2spn(audit, &william_uuid) == Ok(Some(Value::new_iname("william"))));
// check uuid2rdn
assert!(be.uuid2rdn(audit, &claire_uuid) == Ok(Some("name=claire".to_string())));
assert!(be.uuid2rdn(audit, &william_uuid) == Ok(Some("name=william".to_string())));

View file

@ -1,111 +1,120 @@
#![allow(clippy::unwrap_used)]
use uuid::Uuid;
// Built in group and account ranges.
pub const STR_UUID_ADMIN: &str = "00000000-0000-0000-0000-000000000000";
pub const _UUID_IDM_ADMINS: &str = "00000000-0000-0000-0000-000000000001";
pub const _UUID_IDM_PEOPLE_READ_PRIV: &str = "00000000-0000-0000-0000-000000000002";
pub const _UUID_IDM_PEOPLE_WRITE_PRIV: &str = "00000000-0000-0000-0000-000000000003";
pub const _UUID_IDM_GROUP_WRITE_PRIV: &str = "00000000-0000-0000-0000-000000000004";
pub const _UUID_IDM_ACCOUNT_READ_PRIV: &str = "00000000-0000-0000-0000-000000000005";
pub const _UUID_IDM_ACCOUNT_WRITE_PRIV: &str = "00000000-0000-0000-0000-000000000006";
pub const _UUID_IDM_RADIUS_SERVERS: &str = "00000000-0000-0000-0000-000000000007";
pub const _UUID_IDM_HP_ACCOUNT_READ_PRIV: &str = "00000000-0000-0000-0000-000000000008";
pub const _UUID_IDM_HP_ACCOUNT_WRITE_PRIV: &str = "00000000-0000-0000-0000-000000000009";
pub const _UUID_IDM_SCHEMA_MANAGE_PRIV: &str = "00000000-0000-0000-0000-000000000010";
pub const _UUID_IDM_ACP_MANAGE_PRIV: &str = "00000000-0000-0000-0000-000000000011";
pub const _UUID_IDM_HP_GROUP_WRITE_PRIV: &str = "00000000-0000-0000-0000-000000000012";
pub const _UUID_IDM_PEOPLE_MANAGE_PRIV: &str = "00000000-0000-0000-0000-000000000013";
pub const _UUID_IDM_ACCOUNT_MANAGE_PRIV: &str = "00000000-0000-0000-0000-000000000014";
pub const _UUID_IDM_GROUP_MANAGE_PRIV: &str = "00000000-0000-0000-0000-000000000015";
pub const _UUID_IDM_HP_ACCOUNT_MANAGE_PRIV: &str = "00000000-0000-0000-0000-000000000016";
pub const _UUID_IDM_HP_GROUP_MANAGE_PRIV: &str = "00000000-0000-0000-0000-000000000017";
pub const _UUID_IDM_ADMIN_V1: &str = "00000000-0000-0000-0000-000000000018";
pub const _UUID_SYSTEM_ADMINS: &str = "00000000-0000-0000-0000-000000000019";
pub const UUID_DOMAIN_ADMINS: &str = "00000000-0000-0000-0000-000000000020";
pub const _UUID_IDM_ACCOUNT_UNIX_EXTEND_PRIV: &str = "00000000-0000-0000-0000-000000000021";
pub const _UUID_IDM_GROUP_UNIX_EXTEND_PRIV: &str = "00000000-0000-0000-0000-000000000022";
pub const _UUID_IDM_PEOPLE_ACCOUNT_PASSWORD_IMPORT_PRIV: &str =
pub const _STR_UUID_IDM_ADMINS: &str = "00000000-0000-0000-0000-000000000001";
pub const _STR_UUID_IDM_PEOPLE_READ_PRIV: &str = "00000000-0000-0000-0000-000000000002";
pub const _STR_UUID_IDM_PEOPLE_WRITE_PRIV: &str = "00000000-0000-0000-0000-000000000003";
pub const _STR_UUID_IDM_GROUP_WRITE_PRIV: &str = "00000000-0000-0000-0000-000000000004";
pub const _STR_UUID_IDM_ACCOUNT_READ_PRIV: &str = "00000000-0000-0000-0000-000000000005";
pub const _STR_UUID_IDM_ACCOUNT_WRITE_PRIV: &str = "00000000-0000-0000-0000-000000000006";
pub const _STR_UUID_IDM_RADIUS_SERVERS: &str = "00000000-0000-0000-0000-000000000007";
pub const _STR_UUID_IDM_HP_ACCOUNT_READ_PRIV: &str = "00000000-0000-0000-0000-000000000008";
pub const _STR_UUID_IDM_HP_ACCOUNT_WRITE_PRIV: &str = "00000000-0000-0000-0000-000000000009";
pub const _STR_UUID_IDM_SCHEMA_MANAGE_PRIV: &str = "00000000-0000-0000-0000-000000000010";
pub const _STR_UUID_IDM_ACP_MANAGE_PRIV: &str = "00000000-0000-0000-0000-000000000011";
pub const _STR_UUID_IDM_HP_GROUP_WRITE_PRIV: &str = "00000000-0000-0000-0000-000000000012";
pub const _STR_UUID_IDM_PEOPLE_MANAGE_PRIV: &str = "00000000-0000-0000-0000-000000000013";
pub const _STR_UUID_IDM_ACCOUNT_MANAGE_PRIV: &str = "00000000-0000-0000-0000-000000000014";
pub const _STR_UUID_IDM_GROUP_MANAGE_PRIV: &str = "00000000-0000-0000-0000-000000000015";
pub const _STR_UUID_IDM_HP_ACCOUNT_MANAGE_PRIV: &str = "00000000-0000-0000-0000-000000000016";
pub const _STR_UUID_IDM_HP_GROUP_MANAGE_PRIV: &str = "00000000-0000-0000-0000-000000000017";
pub const _STR_UUID_IDM_ADMIN_V1: &str = "00000000-0000-0000-0000-000000000018";
pub const _STR_UUID_SYSTEM_ADMINS: &str = "00000000-0000-0000-0000-000000000019";
pub const STR_UUID_DOMAIN_ADMINS: &str = "00000000-0000-0000-0000-000000000020";
pub const _STR_UUID_IDM_ACCOUNT_UNIX_EXTEND_PRIV: &str = "00000000-0000-0000-0000-000000000021";
pub const _STR_UUID_IDM_GROUP_UNIX_EXTEND_PRIV: &str = "00000000-0000-0000-0000-000000000022";
pub const _STR_UUID_IDM_PEOPLE_ACCOUNT_PASSWORD_IMPORT_PRIV: &str =
"00000000-0000-0000-0000-000000000023";
pub const _UUID_IDM_PEOPLE_EXTEND_PRIV: &str = "00000000-0000-0000-0000-000000000024";
pub const _STR_UUID_IDM_PEOPLE_EXTEND_PRIV: &str = "00000000-0000-0000-0000-000000000024";
//
pub const _UUID_IDM_HIGH_PRIVILEGE: &str = "00000000-0000-0000-0000-000000001000";
pub const _STR_UUID_IDM_HIGH_PRIVILEGE: &str = "00000000-0000-0000-0000-000000001000";
// Builtin schema
pub const UUID_SCHEMA_ATTR_CLASS: &str = "00000000-0000-0000-0000-ffff00000000";
pub const UUID_SCHEMA_ATTR_UUID: &str = "00000000-0000-0000-0000-ffff00000001";
pub const UUID_SCHEMA_ATTR_NAME: &str = "00000000-0000-0000-0000-ffff00000002";
pub const UUID_SCHEMA_ATTR_SPN: &str = "00000000-0000-0000-0000-ffff00000003";
pub const UUID_SCHEMA_ATTR_DESCRIPTION: &str = "00000000-0000-0000-0000-ffff00000004";
pub const UUID_SCHEMA_ATTR_MULTIVALUE: &str = "00000000-0000-0000-0000-ffff00000005";
pub const UUID_SCHEMA_ATTR_UNIQUE: &str = "00000000-0000-0000-0000-ffff00000047";
pub const UUID_SCHEMA_ATTR_INDEX: &str = "00000000-0000-0000-0000-ffff00000006";
pub const UUID_SCHEMA_ATTR_SYNTAX: &str = "00000000-0000-0000-0000-ffff00000007";
pub const UUID_SCHEMA_ATTR_SYSTEMMAY: &str = "00000000-0000-0000-0000-ffff00000008";
pub const UUID_SCHEMA_ATTR_MAY: &str = "00000000-0000-0000-0000-ffff00000009";
pub const UUID_SCHEMA_ATTR_SYSTEMMUST: &str = "00000000-0000-0000-0000-ffff00000010";
pub const UUID_SCHEMA_ATTR_MUST: &str = "00000000-0000-0000-0000-ffff00000011";
pub const UUID_SCHEMA_ATTR_MEMBEROF: &str = "00000000-0000-0000-0000-ffff00000012";
pub const UUID_SCHEMA_ATTR_MEMBER: &str = "00000000-0000-0000-0000-ffff00000013";
pub const UUID_SCHEMA_ATTR_DIRECTMEMBEROF: &str = "00000000-0000-0000-0000-ffff00000014";
pub const UUID_SCHEMA_ATTR_VERSION: &str = "00000000-0000-0000-0000-ffff00000015";
pub const UUID_SCHEMA_ATTR_DOMAIN: &str = "00000000-0000-0000-0000-ffff00000016";
pub const UUID_SCHEMA_ATTR_ACP_ENABLE: &str = "00000000-0000-0000-0000-ffff00000017";
pub const UUID_SCHEMA_ATTR_ACP_RECEIVER: &str = "00000000-0000-0000-0000-ffff00000018";
pub const UUID_SCHEMA_ATTR_ACP_TARGETSCOPE: &str = "00000000-0000-0000-0000-ffff00000019";
pub const UUID_SCHEMA_ATTR_ACP_SEARCH_ATTR: &str = "00000000-0000-0000-0000-ffff00000020";
pub const UUID_SCHEMA_ATTR_ACP_CREATE_CLASS: &str = "00000000-0000-0000-0000-ffff00000021";
pub const UUID_SCHEMA_ATTR_ACP_CREATE_ATTR: &str = "00000000-0000-0000-0000-ffff00000022";
pub const UUID_SCHEMA_ATTR_ACP_MODIFY_REMOVEDATTR: &str = "00000000-0000-0000-0000-ffff00000023";
pub const UUID_SCHEMA_ATTR_ACP_MODIFY_PRESENTATTR: &str = "00000000-0000-0000-0000-ffff00000024";
pub const UUID_SCHEMA_ATTR_ACP_MODIFY_CLASS: &str = "00000000-0000-0000-0000-ffff00000025";
pub const UUID_SCHEMA_CLASS_ATTRIBUTETYPE: &str = "00000000-0000-0000-0000-ffff00000026";
pub const UUID_SCHEMA_CLASS_CLASSTYPE: &str = "00000000-0000-0000-0000-ffff00000027";
pub const UUID_SCHEMA_CLASS_OBJECT: &str = "00000000-0000-0000-0000-ffff00000028";
pub const UUID_SCHEMA_CLASS_EXTENSIBLEOBJECT: &str = "00000000-0000-0000-0000-ffff00000029";
pub const UUID_SCHEMA_CLASS_MEMBEROF: &str = "00000000-0000-0000-0000-ffff00000030";
pub const UUID_SCHEMA_CLASS_RECYCLED: &str = "00000000-0000-0000-0000-ffff00000031";
pub const UUID_SCHEMA_CLASS_TOMBSTONE: &str = "00000000-0000-0000-0000-ffff00000032";
pub const UUID_SCHEMA_CLASS_SYSTEM_INFO: &str = "00000000-0000-0000-0000-ffff00000033";
pub const UUID_SCHEMA_CLASS_ACCESS_CONTROL_PROFILE: &str = "00000000-0000-0000-0000-ffff00000034";
pub const UUID_SCHEMA_CLASS_ACCESS_CONTROL_SEARCH: &str = "00000000-0000-0000-0000-ffff00000035";
pub const UUID_SCHEMA_CLASS_ACCESS_CONTROL_DELETE: &str = "00000000-0000-0000-0000-ffff00000036";
pub const UUID_SCHEMA_CLASS_ACCESS_CONTROL_MODIFY: &str = "00000000-0000-0000-0000-ffff00000037";
pub const UUID_SCHEMA_CLASS_ACCESS_CONTROL_CREATE: &str = "00000000-0000-0000-0000-ffff00000038";
pub const UUID_SCHEMA_CLASS_SYSTEM: &str = "00000000-0000-0000-0000-ffff00000039";
pub const UUID_SCHEMA_ATTR_DISPLAYNAME: &str = "00000000-0000-0000-0000-ffff00000040";
pub const UUID_SCHEMA_ATTR_MAIL: &str = "00000000-0000-0000-0000-ffff00000041";
pub const UUID_SCHEMA_ATTR_SSH_PUBLICKEY: &str = "00000000-0000-0000-0000-ffff00000042";
pub const UUID_SCHEMA_ATTR_PRIMARY_CREDENTIAL: &str = "00000000-0000-0000-0000-ffff00000043";
pub const UUID_SCHEMA_CLASS_PERSON: &str = "00000000-0000-0000-0000-ffff00000044";
pub const UUID_SCHEMA_CLASS_GROUP: &str = "00000000-0000-0000-0000-ffff00000045";
pub const UUID_SCHEMA_CLASS_ACCOUNT: &str = "00000000-0000-0000-0000-ffff00000046";
pub const STR_UUID_SCHEMA_ATTR_CLASS: &str = "00000000-0000-0000-0000-ffff00000000";
pub const STR_UUID_SCHEMA_ATTR_UUID: &str = "00000000-0000-0000-0000-ffff00000001";
pub const STR_UUID_SCHEMA_ATTR_NAME: &str = "00000000-0000-0000-0000-ffff00000002";
pub const STR_UUID_SCHEMA_ATTR_SPN: &str = "00000000-0000-0000-0000-ffff00000003";
pub const STR_UUID_SCHEMA_ATTR_DESCRIPTION: &str = "00000000-0000-0000-0000-ffff00000004";
pub const STR_UUID_SCHEMA_ATTR_MULTIVALUE: &str = "00000000-0000-0000-0000-ffff00000005";
pub const STR_UUID_SCHEMA_ATTR_UNIQUE: &str = "00000000-0000-0000-0000-ffff00000047";
pub const STR_UUID_SCHEMA_ATTR_INDEX: &str = "00000000-0000-0000-0000-ffff00000006";
pub const STR_UUID_SCHEMA_ATTR_SYNTAX: &str = "00000000-0000-0000-0000-ffff00000007";
pub const STR_UUID_SCHEMA_ATTR_SYSTEMMAY: &str = "00000000-0000-0000-0000-ffff00000008";
pub const STR_UUID_SCHEMA_ATTR_MAY: &str = "00000000-0000-0000-0000-ffff00000009";
pub const STR_UUID_SCHEMA_ATTR_SYSTEMMUST: &str = "00000000-0000-0000-0000-ffff00000010";
pub const STR_UUID_SCHEMA_ATTR_MUST: &str = "00000000-0000-0000-0000-ffff00000011";
pub const STR_UUID_SCHEMA_ATTR_MEMBEROF: &str = "00000000-0000-0000-0000-ffff00000012";
pub const STR_UUID_SCHEMA_ATTR_MEMBER: &str = "00000000-0000-0000-0000-ffff00000013";
pub const STR_UUID_SCHEMA_ATTR_DIRECTMEMBEROF: &str = "00000000-0000-0000-0000-ffff00000014";
pub const STR_UUID_SCHEMA_ATTR_VERSION: &str = "00000000-0000-0000-0000-ffff00000015";
pub const STR_UUID_SCHEMA_ATTR_DOMAIN: &str = "00000000-0000-0000-0000-ffff00000016";
pub const STR_UUID_SCHEMA_ATTR_ACP_ENABLE: &str = "00000000-0000-0000-0000-ffff00000017";
pub const STR_UUID_SCHEMA_ATTR_ACP_RECEIVER: &str = "00000000-0000-0000-0000-ffff00000018";
pub const STR_UUID_SCHEMA_ATTR_ACP_TARGETSCOPE: &str = "00000000-0000-0000-0000-ffff00000019";
pub const STR_UUID_SCHEMA_ATTR_ACP_SEARCH_ATTR: &str = "00000000-0000-0000-0000-ffff00000020";
pub const STR_UUID_SCHEMA_ATTR_ACP_CREATE_CLASS: &str = "00000000-0000-0000-0000-ffff00000021";
pub const STR_UUID_SCHEMA_ATTR_ACP_CREATE_ATTR: &str = "00000000-0000-0000-0000-ffff00000022";
pub const STR_UUID_SCHEMA_ATTR_ACP_MODIFY_REMOVEDATTR: &str =
"00000000-0000-0000-0000-ffff00000023";
pub const STR_UUID_SCHEMA_ATTR_ACP_MODIFY_PRESENTATTR: &str =
"00000000-0000-0000-0000-ffff00000024";
pub const STR_UUID_SCHEMA_ATTR_ACP_MODIFY_CLASS: &str = "00000000-0000-0000-0000-ffff00000025";
pub const STR_UUID_SCHEMA_CLASS_ATTRIBUTETYPE: &str = "00000000-0000-0000-0000-ffff00000026";
pub const STR_UUID_SCHEMA_CLASS_CLASSTYPE: &str = "00000000-0000-0000-0000-ffff00000027";
pub const STR_UUID_SCHEMA_CLASS_OBJECT: &str = "00000000-0000-0000-0000-ffff00000028";
pub const STR_UUID_SCHEMA_CLASS_EXTENSIBLEOBJECT: &str = "00000000-0000-0000-0000-ffff00000029";
pub const STR_UUID_SCHEMA_CLASS_MEMBEROF: &str = "00000000-0000-0000-0000-ffff00000030";
pub const STR_UUID_SCHEMA_CLASS_RECYCLED: &str = "00000000-0000-0000-0000-ffff00000031";
pub const STR_UUID_SCHEMA_CLASS_TOMBSTONE: &str = "00000000-0000-0000-0000-ffff00000032";
pub const STR_UUID_SCHEMA_CLASS_SYSTEM_INFO: &str = "00000000-0000-0000-0000-ffff00000033";
pub const STR_UUID_SCHEMA_CLASS_ACCESS_CONTROL_PROFILE: &str =
"00000000-0000-0000-0000-ffff00000034";
pub const STR_UUID_SCHEMA_CLASS_ACCESS_CONTROL_SEARCH: &str =
"00000000-0000-0000-0000-ffff00000035";
pub const STR_UUID_SCHEMA_CLASS_ACCESS_CONTROL_DELETE: &str =
"00000000-0000-0000-0000-ffff00000036";
pub const STR_UUID_SCHEMA_CLASS_ACCESS_CONTROL_MODIFY: &str =
"00000000-0000-0000-0000-ffff00000037";
pub const STR_UUID_SCHEMA_CLASS_ACCESS_CONTROL_CREATE: &str =
"00000000-0000-0000-0000-ffff00000038";
pub const STR_UUID_SCHEMA_CLASS_SYSTEM: &str = "00000000-0000-0000-0000-ffff00000039";
pub const STR_UUID_SCHEMA_ATTR_DISPLAYNAME: &str = "00000000-0000-0000-0000-ffff00000040";
pub const STR_UUID_SCHEMA_ATTR_MAIL: &str = "00000000-0000-0000-0000-ffff00000041";
pub const STR_UUID_SCHEMA_ATTR_SSH_PUBLICKEY: &str = "00000000-0000-0000-0000-ffff00000042";
pub const STR_UUID_SCHEMA_ATTR_PRIMARY_CREDENTIAL: &str = "00000000-0000-0000-0000-ffff00000043";
pub const STR_UUID_SCHEMA_CLASS_PERSON: &str = "00000000-0000-0000-0000-ffff00000044";
pub const STR_UUID_SCHEMA_CLASS_GROUP: &str = "00000000-0000-0000-0000-ffff00000045";
pub const STR_UUID_SCHEMA_CLASS_ACCOUNT: &str = "00000000-0000-0000-0000-ffff00000046";
// GAP - 47
pub const UUID_SCHEMA_ATTR_ATTRIBUTENAME: &str = "00000000-0000-0000-0000-ffff00000048";
pub const UUID_SCHEMA_ATTR_CLASSNAME: &str = "00000000-0000-0000-0000-ffff00000049";
pub const UUID_SCHEMA_ATTR_LEGALNAME: &str = "00000000-0000-0000-0000-ffff00000050";
pub const UUID_SCHEMA_ATTR_RADIUS_SECRET: &str = "00000000-0000-0000-0000-ffff00000051";
pub const UUID_SCHEMA_CLASS_DOMAIN_INFO: &str = "00000000-0000-0000-0000-ffff00000052";
pub const UUID_SCHEMA_ATTR_DOMAIN_NAME: &str = "00000000-0000-0000-0000-ffff00000053";
pub const UUID_SCHEMA_ATTR_DOMAIN_UUID: &str = "00000000-0000-0000-0000-ffff00000054";
pub const UUID_SCHEMA_ATTR_DOMAIN_SSID: &str = "00000000-0000-0000-0000-ffff00000055";
pub const STR_UUID_SCHEMA_ATTR_ATTRIBUTENAME: &str = "00000000-0000-0000-0000-ffff00000048";
pub const STR_UUID_SCHEMA_ATTR_CLASSNAME: &str = "00000000-0000-0000-0000-ffff00000049";
pub const STR_UUID_SCHEMA_ATTR_LEGALNAME: &str = "00000000-0000-0000-0000-ffff00000050";
pub const STR_UUID_SCHEMA_ATTR_RADIUS_SECRET: &str = "00000000-0000-0000-0000-ffff00000051";
pub const STR_UUID_SCHEMA_CLASS_DOMAIN_INFO: &str = "00000000-0000-0000-0000-ffff00000052";
pub const STR_UUID_SCHEMA_ATTR_DOMAIN_NAME: &str = "00000000-0000-0000-0000-ffff00000053";
pub const STR_UUID_SCHEMA_ATTR_DOMAIN_UUID: &str = "00000000-0000-0000-0000-ffff00000054";
pub const STR_UUID_SCHEMA_ATTR_DOMAIN_SSID: &str = "00000000-0000-0000-0000-ffff00000055";
pub const UUID_SCHEMA_ATTR_GIDNUMBER: &str = "00000000-0000-0000-0000-ffff00000056";
pub const UUID_SCHEMA_CLASS_POSIXACCOUNT: &str = "00000000-0000-0000-0000-ffff00000057";
pub const UUID_SCHEMA_CLASS_POSIXGROUP: &str = "00000000-0000-0000-0000-ffff00000058";
pub const UUID_SCHEMA_ATTR_BADLIST_PASSWORD: &str = "00000000-0000-0000-0000-ffff00000059";
pub const UUID_SCHEMA_CLASS_SYSTEM_CONFIG: &str = "00000000-0000-0000-0000-ffff00000060";
pub const UUID_SCHEMA_ATTR_LOGINSHELL: &str = "00000000-0000-0000-0000-ffff00000061";
pub const UUID_SCHEMA_ATTR_UNIX_PASSWORD: &str = "00000000-0000-0000-0000-ffff00000062";
pub const UUID_SCHEMA_ATTR_LAST_MOD_CID: &str = "00000000-0000-0000-0000-ffff00000063";
pub const UUID_SCHEMA_ATTR_PHANTOM: &str = "00000000-0000-0000-0000-ffff00000064";
pub const UUID_SCHEMA_ATTR_CLAIM: &str = "00000000-0000-0000-0000-ffff00000065";
pub const UUID_SCHEMA_ATTR_PASSWORD_IMPORT: &str = "00000000-0000-0000-0000-ffff00000066";
pub const UUID_SCHEMA_ATTR_NSUNIQUEID: &str = "00000000-0000-0000-0000-ffff00000067";
pub const STR_UUID_SCHEMA_ATTR_GIDNUMBER: &str = "00000000-0000-0000-0000-ffff00000056";
pub const STR_UUID_SCHEMA_CLASS_POSIXACCOUNT: &str = "00000000-0000-0000-0000-ffff00000057";
pub const STR_UUID_SCHEMA_CLASS_POSIXGROUP: &str = "00000000-0000-0000-0000-ffff00000058";
pub const STR_UUID_SCHEMA_ATTR_BADLIST_PASSWORD: &str = "00000000-0000-0000-0000-ffff00000059";
pub const STR_UUID_SCHEMA_CLASS_SYSTEM_CONFIG: &str = "00000000-0000-0000-0000-ffff00000060";
pub const STR_UUID_SCHEMA_ATTR_LOGINSHELL: &str = "00000000-0000-0000-0000-ffff00000061";
pub const STR_UUID_SCHEMA_ATTR_UNIX_PASSWORD: &str = "00000000-0000-0000-0000-ffff00000062";
pub const STR_UUID_SCHEMA_ATTR_LAST_MOD_CID: &str = "00000000-0000-0000-0000-ffff00000063";
pub const STR_UUID_SCHEMA_ATTR_PHANTOM: &str = "00000000-0000-0000-0000-ffff00000064";
pub const STR_UUID_SCHEMA_ATTR_CLAIM: &str = "00000000-0000-0000-0000-ffff00000065";
pub const STR_UUID_SCHEMA_ATTR_PASSWORD_IMPORT: &str = "00000000-0000-0000-0000-ffff00000066";
pub const STR_UUID_SCHEMA_ATTR_NSUNIQUEID: &str = "00000000-0000-0000-0000-ffff00000067";
pub const UUID_SCHEMA_ATTR_DN: &str = "00000000-0000-0000-0000-ffff00000068";
pub const UUID_SCHEMA_ATTR_NICE: &str = "00000000-0000-0000-0000-ffff00000069";
pub const UUID_SCHEMA_ATTR_ENTRYUUID: &str = "00000000-0000-0000-0000-ffff00000070";
pub const UUID_SCHEMA_ATTR_OBJECTCLASS: &str = "00000000-0000-0000-0000-ffff00000071";
pub const STR_UUID_SCHEMA_ATTR_DN: &str = "00000000-0000-0000-0000-ffff00000068";
pub const STR_UUID_SCHEMA_ATTR_NICE: &str = "00000000-0000-0000-0000-ffff00000069";
pub const STR_UUID_SCHEMA_ATTR_ENTRYUUID: &str = "00000000-0000-0000-0000-ffff00000070";
pub const STR_UUID_SCHEMA_ATTR_OBJECTCLASS: &str = "00000000-0000-0000-0000-ffff00000071";
// System and domain infos
// I'd like to strongly criticise william of the past for fucking up these allocations.
@ -115,37 +124,42 @@ pub const STR_UUID_DOMAIN_INFO: &str = "00000000-0000-0000-0000-ffffff000025";
// Access controls
// skip 00 / 01 - see system info
pub const _UUID_IDM_ADMINS_ACP_RECYCLE_SEARCH_V1: &str = "00000000-0000-0000-0000-ffffff000002";
pub const _UUID_IDM_ADMINS_ACP_REVIVE_V1: &str = "00000000-0000-0000-0000-ffffff000003";
pub const _UUID_IDM_SELF_ACP_READ_V1: &str = "00000000-0000-0000-0000-ffffff000004";
pub const _UUID_IDM_ALL_ACP_READ_V1: &str = "00000000-0000-0000-0000-ffffff000006";
pub const _UUID_IDM_ACP_PEOPLE_READ_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000007";
pub const _UUID_IDM_ACP_PEOPLE_WRITE_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000008";
pub const _UUID_IDM_ACP_GROUP_WRITE_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000009";
pub const _UUID_IDM_ACP_ACCOUNT_READ_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000010";
pub const _UUID_IDM_ACP_ACCOUNT_WRITE_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000011";
pub const _UUID_IDM_ACP_ACCOUNT_MANAGE_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000012";
pub const _UUID_IDM_ACP_PEOPLE_MANAGE_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000013";
pub const _UUID_IDM_ACP_RADIUS_SERVERS_V1: &str = "00000000-0000-0000-0000-ffffff000014";
pub const _UUID_IDM_ACP_HP_ACCOUNT_READ_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000015";
pub const _UUID_IDM_ACP_HP_ACCOUNT_WRITE_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000016";
pub const _UUID_IDM_ACP_HP_GROUP_WRITE_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000017";
pub const _UUID_IDM_ACP_SCHEMA_WRITE_ATTRS_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000018";
pub const _UUID_IDM_ACP_ACP_MANAGE_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000019";
pub const _UUID_IDM_ACP_SCHEMA_WRITE_CLASSES_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000020";
pub const _UUID_IDM_SELF_ACP_WRITE_V1: &str = "00000000-0000-0000-0000-ffffff000021";
pub const _UUID_IDM_ACP_GROUP_MANAGE_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000022";
pub const _UUID_IDM_ACP_HP_ACCOUNT_MANAGE_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000023";
pub const _UUID_IDM_ACP_HP_GROUP_MANAGE_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000024";
pub const _STR_UUID_IDM_ADMINS_ACP_RECYCLE_SEARCH_V1: &str = "00000000-0000-0000-0000-ffffff000002";
pub const _STR_UUID_IDM_ADMINS_ACP_REVIVE_V1: &str = "00000000-0000-0000-0000-ffffff000003";
pub const _STR_UUID_IDM_SELF_ACP_READ_V1: &str = "00000000-0000-0000-0000-ffffff000004";
pub const _STR_UUID_IDM_ALL_ACP_READ_V1: &str = "00000000-0000-0000-0000-ffffff000006";
pub const _STR_UUID_IDM_ACP_PEOPLE_READ_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000007";
pub const _STR_UUID_IDM_ACP_PEOPLE_WRITE_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000008";
pub const _STR_UUID_IDM_ACP_GROUP_WRITE_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000009";
pub const _STR_UUID_IDM_ACP_ACCOUNT_READ_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000010";
pub const _STR_UUID_IDM_ACP_ACCOUNT_WRITE_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000011";
pub const _STR_UUID_IDM_ACP_ACCOUNT_MANAGE_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000012";
pub const _STR_UUID_IDM_ACP_PEOPLE_MANAGE_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000013";
pub const _STR_UUID_IDM_ACP_RADIUS_SERVERS_V1: &str = "00000000-0000-0000-0000-ffffff000014";
pub const _STR_UUID_IDM_ACP_HP_ACCOUNT_READ_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000015";
pub const _STR_UUID_IDM_ACP_HP_ACCOUNT_WRITE_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000016";
pub const _STR_UUID_IDM_ACP_HP_GROUP_WRITE_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000017";
pub const _STR_UUID_IDM_ACP_SCHEMA_WRITE_ATTRS_PRIV_V1: &str =
"00000000-0000-0000-0000-ffffff000018";
pub const _STR_UUID_IDM_ACP_ACP_MANAGE_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000019";
pub const _STR_UUID_IDM_ACP_SCHEMA_WRITE_CLASSES_PRIV_V1: &str =
"00000000-0000-0000-0000-ffffff000020";
pub const _STR_UUID_IDM_SELF_ACP_WRITE_V1: &str = "00000000-0000-0000-0000-ffffff000021";
pub const _STR_UUID_IDM_ACP_GROUP_MANAGE_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000022";
pub const _STR_UUID_IDM_ACP_HP_ACCOUNT_MANAGE_PRIV_V1: &str =
"00000000-0000-0000-0000-ffffff000023";
pub const _STR_UUID_IDM_ACP_HP_GROUP_MANAGE_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000024";
// Skip 25 - see domain info.
pub const UUID_IDM_ACP_DOMAIN_ADMIN_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000026";
pub const STR_UUID_IDM_ACP_DOMAIN_ADMIN_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000026";
pub const STR_UUID_SYSTEM_CONFIG: &str = "00000000-0000-0000-0000-ffffff000027";
pub const UUID_IDM_ACP_SYSTEM_CONFIG_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000028";
pub const _UUID_IDM_ACP_ACCOUNT_UNIX_EXTEND_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000029";
pub const _UUID_IDM_ACP_GROUP_UNIX_EXTEND_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000030";
pub const _UUID_IDM_ACP_PEOPLE_ACCOUNT_PASSWORD_IMPORT_PRIV_V1: &str =
pub const STR_UUID_IDM_ACP_SYSTEM_CONFIG_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000028";
pub const _STR_UUID_IDM_ACP_ACCOUNT_UNIX_EXTEND_PRIV_V1: &str =
"00000000-0000-0000-0000-ffffff000029";
pub const _STR_UUID_IDM_ACP_GROUP_UNIX_EXTEND_PRIV_V1: &str =
"00000000-0000-0000-0000-ffffff000030";
pub const _STR_UUID_IDM_ACP_PEOPLE_ACCOUNT_PASSWORD_IMPORT_PRIV_V1: &str =
"00000000-0000-0000-0000-ffffff000031";
pub const _UUID_IDM_ACP_PEOPLE_EXTEND_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000032";
pub const _STR_UUID_IDM_ACP_PEOPLE_EXTEND_PRIV_V1: &str = "00000000-0000-0000-0000-ffffff000032";
// End of system ranges
pub const STR_UUID_DOES_NOT_EXIST: &str = "00000000-0000-0000-0000-fffffffffffe";
@ -158,4 +172,101 @@ lazy_static! {
pub static ref UUID_SYSTEM_CONFIG: Uuid = Uuid::parse_str(STR_UUID_SYSTEM_CONFIG).unwrap();
pub static ref UUID_SYSTEM_INFO: Uuid = Uuid::parse_str(STR_UUID_SYSTEM_INFO).unwrap();
pub static ref UUID_DOMAIN_INFO: Uuid = Uuid::parse_str(STR_UUID_DOMAIN_INFO).unwrap();
pub static ref UUID_SCHEMA_ATTR_CLASS: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_ATTR_CLASS).unwrap();
pub static ref UUID_SCHEMA_ATTR_UUID: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_ATTR_UUID).unwrap();
pub static ref UUID_SCHEMA_ATTR_LAST_MOD_CID: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_ATTR_LAST_MOD_CID).unwrap();
pub static ref UUID_SCHEMA_ATTR_NAME: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_ATTR_NAME).unwrap();
pub static ref UUID_SCHEMA_ATTR_SPN: Uuid = Uuid::parse_str(STR_UUID_SCHEMA_ATTR_SPN).unwrap();
pub static ref UUID_SCHEMA_ATTR_ATTRIBUTENAME: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_ATTR_ATTRIBUTENAME).unwrap();
pub static ref UUID_SCHEMA_ATTR_CLASSNAME: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_ATTR_CLASSNAME).unwrap();
pub static ref UUID_SCHEMA_ATTR_DESCRIPTION: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_ATTR_DESCRIPTION).unwrap();
pub static ref UUID_SCHEMA_ATTR_MULTIVALUE: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_ATTR_MULTIVALUE).unwrap();
pub static ref UUID_SCHEMA_ATTR_PHANTOM: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_ATTR_PHANTOM).unwrap();
pub static ref UUID_SCHEMA_ATTR_UNIQUE: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_ATTR_UNIQUE).unwrap();
pub static ref UUID_SCHEMA_ATTR_INDEX: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_ATTR_INDEX).unwrap();
pub static ref UUID_SCHEMA_ATTR_SYNTAX: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_ATTR_SYNTAX).unwrap();
pub static ref UUID_SCHEMA_ATTR_SYSTEMMAY: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_ATTR_SYSTEMMAY).unwrap();
pub static ref UUID_SCHEMA_ATTR_MAY: Uuid = Uuid::parse_str(STR_UUID_SCHEMA_ATTR_MAY).unwrap();
pub static ref UUID_SCHEMA_ATTR_SYSTEMMUST: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_ATTR_SYSTEMMUST).unwrap();
pub static ref UUID_SCHEMA_ATTR_MUST: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_ATTR_MUST).unwrap();
pub static ref UUID_SCHEMA_ATTR_ACP_ENABLE: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_ATTR_ACP_ENABLE).unwrap();
pub static ref UUID_SCHEMA_ATTR_ACP_RECEIVER: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_ATTR_ACP_RECEIVER).unwrap();
pub static ref UUID_SCHEMA_ATTR_ACP_TARGETSCOPE: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_ATTR_ACP_TARGETSCOPE).unwrap();
pub static ref UUID_SCHEMA_ATTR_ACP_SEARCH_ATTR: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_ATTR_ACP_SEARCH_ATTR).unwrap();
pub static ref UUID_SCHEMA_ATTR_ACP_CREATE_CLASS: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_ATTR_ACP_CREATE_CLASS).unwrap();
pub static ref UUID_SCHEMA_ATTR_ACP_CREATE_ATTR: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_ATTR_ACP_CREATE_ATTR).unwrap();
pub static ref UUID_SCHEMA_ATTR_ACP_MODIFY_REMOVEDATTR: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_ATTR_ACP_MODIFY_REMOVEDATTR).unwrap();
pub static ref UUID_SCHEMA_ATTR_ACP_MODIFY_PRESENTATTR: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_ATTR_ACP_MODIFY_PRESENTATTR).unwrap();
pub static ref UUID_SCHEMA_ATTR_ACP_MODIFY_CLASS: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_ATTR_ACP_MODIFY_CLASS).unwrap();
pub static ref UUID_SCHEMA_ATTR_MEMBEROF: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_ATTR_MEMBEROF).unwrap();
pub static ref UUID_SCHEMA_ATTR_DIRECTMEMBEROF: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_ATTR_DIRECTMEMBEROF).unwrap();
pub static ref UUID_SCHEMA_ATTR_MEMBER: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_ATTR_MEMBER).unwrap();
pub static ref UUID_SCHEMA_ATTR_VERSION: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_ATTR_VERSION).unwrap();
pub static ref UUID_SCHEMA_ATTR_DOMAIN: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_ATTR_DOMAIN).unwrap();
pub static ref UUID_SCHEMA_ATTR_CLAIM: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_ATTR_CLAIM).unwrap();
pub static ref UUID_SCHEMA_ATTR_PASSWORD_IMPORT: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_ATTR_PASSWORD_IMPORT).unwrap();
pub static ref UUID_SCHEMA_ATTR_DN: Uuid = Uuid::parse_str(STR_UUID_SCHEMA_ATTR_DN).unwrap();
pub static ref UUID_SCHEMA_ATTR_ENTRYUUID: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_ATTR_ENTRYUUID).unwrap();
pub static ref UUID_SCHEMA_ATTR_OBJECTCLASS: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_ATTR_OBJECTCLASS).unwrap();
pub static ref UUID_SCHEMA_CLASS_ATTRIBUTETYPE: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_CLASS_ATTRIBUTETYPE).unwrap();
pub static ref UUID_SCHEMA_CLASS_CLASSTYPE: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_CLASS_CLASSTYPE).unwrap();
pub static ref UUID_SCHEMA_CLASS_OBJECT: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_CLASS_OBJECT).unwrap();
pub static ref UUID_SCHEMA_CLASS_MEMBEROF: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_CLASS_MEMBEROF).unwrap();
pub static ref UUID_SCHEMA_CLASS_EXTENSIBLEOBJECT: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_CLASS_EXTENSIBLEOBJECT).unwrap();
pub static ref UUID_SCHEMA_CLASS_RECYCLED: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_CLASS_RECYCLED).unwrap();
pub static ref UUID_SCHEMA_CLASS_TOMBSTONE: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_CLASS_TOMBSTONE).unwrap();
pub static ref UUID_SCHEMA_CLASS_SYSTEM_INFO: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_CLASS_SYSTEM_INFO).unwrap();
pub static ref UUID_SCHEMA_CLASS_ACCESS_CONTROL_PROFILE: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_CLASS_ACCESS_CONTROL_PROFILE).unwrap();
pub static ref UUID_SCHEMA_CLASS_ACCESS_CONTROL_SEARCH: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_CLASS_ACCESS_CONTROL_SEARCH).unwrap();
pub static ref UUID_SCHEMA_CLASS_ACCESS_CONTROL_DELETE: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_CLASS_ACCESS_CONTROL_DELETE).unwrap();
pub static ref UUID_SCHEMA_CLASS_ACCESS_CONTROL_MODIFY: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_CLASS_ACCESS_CONTROL_MODIFY).unwrap();
pub static ref UUID_SCHEMA_CLASS_ACCESS_CONTROL_CREATE: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_CLASS_ACCESS_CONTROL_CREATE).unwrap();
pub static ref UUID_SCHEMA_CLASS_SYSTEM: Uuid =
Uuid::parse_str(STR_UUID_SCHEMA_CLASS_SYSTEM).unwrap();
}

View file

@ -26,6 +26,7 @@ impl ServerCtx {
self.system.clone()
}
#[allow(clippy::expect_used)]
pub fn stop(self) {
// stop the actix system
self.system.stop();

View file

@ -198,7 +198,12 @@ pub(crate) async fn create_ldap_server(
eprintln!("Could not parse ldap server address {} -> {:?}", address, e);
})?;
let listener = Box::new(TcpListener::bind(&addr).await.unwrap());
let listener = Box::new(TcpListener::bind(&addr).await.map_err(|e| {
eprintln!(
"Could not bind to ldap server address {} -> {:?}",
address, e
);
})?);
match opt_tls_params {
Some(tls_params) => {
@ -208,8 +213,10 @@ pub(crate) async fn create_ldap_server(
let lacceptor = Box::leak(acceptor) as &'static _;
ctx.add_message_stream(Box::leak(listener).incoming().map(move |st| {
let st = st.unwrap();
let addr = st.peer_addr().unwrap();
#[allow(clippy::expect_used)]
let st = st.expect("Failed to access TCP stream");
#[allow(clippy::expect_used)]
let addr = st.peer_addr().expect("Failed to access peer adddress");
TlsConnect(lacceptor, st, addr)
}));
LdapServer { qe_r }
@ -219,8 +226,10 @@ pub(crate) async fn create_ldap_server(
info!("Starting LDAP interface ldap://{} ...", address);
LdapServer::create(move |ctx| {
ctx.add_message_stream(Box::leak(listener).incoming().map(|st| {
let st = st.unwrap();
let addr = st.peer_addr().unwrap();
#[allow(clippy::expect_used)]
let st = st.expect("Failed to access TCP stream");
#[allow(clippy::expect_used)]
let addr = st.peer_addr().expect("Failed to access peer adddress");
TcpConnect(st, addr)
}));
LdapServer { qe_r }

View file

@ -1,11 +1,11 @@
mod ctx;
mod ldaps;
// use actix_files as fs;
use libc::umask;
use actix::prelude::*;
use actix_session::{CookieSession, Session};
use actix_web::web::{self, Data, HttpResponse, Json, Path};
use actix_web::{cookie, error, middleware, App, HttpServer};
use libc::umask;
use crossbeam::channel::unbounded;
use std::sync::Arc;
@ -462,7 +462,7 @@ async fn schema_attributetype_get_id(
let filter = filter_all!(f_and!([
f_eq("class", PartialValue::new_class("attributetype")),
f_eq("attributename", PartialValue::new_iutf8s(path.as_str()))
f_eq("attributename", PartialValue::new_iutf8(path.as_str()))
]));
let (eventid, hvalue) = new_eventid!();
@ -497,7 +497,7 @@ async fn schema_classtype_get_id(
let filter = filter_all!(f_and!([
f_eq("class", PartialValue::new_class("classtype")),
f_eq("classname", PartialValue::new_iutf8s(path.as_str()))
f_eq("classname", PartialValue::new_iutf8(path.as_str()))
]));
let (eventid, hvalue) = new_eventid!();
@ -1024,7 +1024,7 @@ async fn group_post_id_unix(
let uat = get_current_user(&session);
let id = path.into_inner();
let (eventid, hvalue) = new_eventid!();
let m_obj = IdmGroupUnixExtendMessage::new(uat, id, obj.into_inner(), eventid);
let m_obj = IdmGroupUnixExtendMessage::new(uat, id, &obj, eventid);
match state.qe_w.send(m_obj).await {
Ok(Ok(())) => HttpResponse::Ok()
.header("X-KANIDM-OPID", hvalue)
@ -1305,7 +1305,7 @@ fn setup_qs_idms(
Ok((query_server, idms))
}
pub fn backup_server_core(config: Configuration, dst_path: &str) {
pub fn backup_server_core(config: &Configuration, dst_path: &str) {
let mut audit = AuditScope::new("backend_backup", uuid::Uuid::new_v4(), config.log_level);
let schema = match Schema::new(&mut audit) {
Ok(s) => s,
@ -1337,7 +1337,7 @@ pub fn backup_server_core(config: Configuration, dst_path: &str) {
// Let the txn abort, even on success.
}
pub fn restore_server_core(config: Configuration, dst_path: &str) {
pub fn restore_server_core(config: &Configuration, dst_path: &str) {
let mut audit = AuditScope::new("backend_restore", uuid::Uuid::new_v4(), config.log_level);
// First, we provide the in-memory schema so that core attrs are indexed correctly.
@ -1401,7 +1401,7 @@ pub fn restore_server_core(config: Configuration, dst_path: &str) {
info!("✅ Restore Success!");
}
pub fn reindex_server_core(config: Configuration) {
pub fn reindex_server_core(config: &Configuration) {
let mut audit = AuditScope::new("server_reindex", uuid::Uuid::new_v4(), config.log_level);
eprintln!("Start Index Phase 1 ...");
// First, we provide the in-memory schema so that core attrs are indexed correctly.
@ -1471,7 +1471,7 @@ pub fn reindex_server_core(config: Configuration) {
};
}
pub fn domain_rename_core(config: Configuration, new_domain_name: String) {
pub fn domain_rename_core(config: &Configuration, new_domain_name: &str) {
let mut audit = AuditScope::new("domain_rename", uuid::Uuid::new_v4(), config.log_level);
let schema = match Schema::new(&mut audit) {
@ -1502,7 +1502,7 @@ pub fn domain_rename_core(config: Configuration, new_domain_name: String) {
let qs_write = qs.write(duration_from_epoch_now());
let r = qs_write
.domain_rename(&mut audit, new_domain_name.as_str())
.domain_rename(&mut audit, new_domain_name)
.and_then(|_| qs_write.commit(&mut audit));
match r {
@ -1531,7 +1531,7 @@ pub fn reset_sid_core(config: Configuration) {
}
*/
pub fn verify_server_core(config: Configuration) {
pub fn verify_server_core(config: &Configuration) {
let mut audit = AuditScope::new("server_verify", uuid::Uuid::new_v4(), config.log_level);
// setup the qs - without initialise!
let schema_mem = match Schema::new(&mut audit) {
@ -1569,7 +1569,7 @@ pub fn verify_server_core(config: Configuration) {
// Now add IDM server verifications?
}
pub fn recover_account_core(config: Configuration, name: String, password: String) {
pub fn recover_account_core(config: &Configuration, name: &str, password: &str) {
let mut audit = AuditScope::new("recover_account", uuid::Uuid::new_v4(), config.log_level);
let schema = match Schema::new(&mut audit) {
@ -1600,14 +1600,18 @@ pub fn recover_account_core(config: Configuration, name: String, password: Strin
// Run the password change.
let mut idms_prox_write = idms.proxy_write(duration_from_epoch_now());
match idms_prox_write.recover_account(&mut audit, name, password) {
Ok(_) => {
idms_prox_write
.commit(&mut audit)
.expect("A critical error during commit occured.");
audit.write_log();
info!("Password reset!");
}
match idms_prox_write.recover_account(&mut audit, &name, &password) {
Ok(_) => match idms_prox_write.commit(&mut audit) {
Ok(()) => {
audit.write_log();
info!("Password reset!");
}
Err(e) => {
error!("A critical error during commit occured {:?}", e);
audit.write_log();
std::process::exit(1);
}
},
Err(e) => {
error!("Error during password reset -> {:?}", e);
audit.write_log();
@ -1633,7 +1637,7 @@ pub async fn create_server_core(config: Configuration) -> Result<ServerCtx, ()>
// The log server is started on it's own thread, and is contacted
// asynchronously.
let (log_tx, log_rx) = unbounded();
let log_thread = thread::spawn(move || async_log::run(log_rx));
let log_thread = thread::spawn(move || async_log::run(&log_rx));
// Similar, create a stats thread which aggregates statistics from the
// server as they come in.
@ -1681,11 +1685,7 @@ pub async fn create_server_core(config: Configuration) -> Result<ServerCtx, ()>
match &config.integration_test_config {
Some(itc) => {
let mut idms_prox_write = idms.proxy_write(duration_from_epoch_now());
match idms_prox_write.recover_account(
&mut audit,
"admin".to_string(),
itc.admin_password.clone(),
) {
match idms_prox_write.recover_account(&mut audit, "admin", &itc.admin_password) {
Ok(_) => {}
Err(e) => {
audit.write_log();
@ -1975,9 +1975,16 @@ pub async fn create_server_core(config: Configuration) -> Result<ServerCtx, ()>
server.bind(config.address)
}
};
server.expect("Failed to initialise server!").run();
info!("ready to rock! 🤘");
match server {
Ok(s) => s.run(),
Err(e) => {
error!("Failed to initialise server! {:?}", e);
return Err(());
}
};
info!("ready to rock! 🧱");
Ok(ServerCtx::new(System::current(), log_tx, log_thread))
}

View file

@ -1,4 +1,5 @@
use crate::be::dbvalue::{DbCredV1, DbPasswordV1};
use kanidm_proto::v1::OperationError;
use openssl::hash::MessageDigest;
use openssl::pkcs5::pbkdf2_hmac;
use rand::prelude::*;
@ -93,7 +94,7 @@ impl TryFrom<&str> for Password {
}
impl Password {
fn new_pbkdf2(cleartext: &str) -> KDF {
fn new_pbkdf2(cleartext: &str) -> Result<KDF, OperationError> {
let mut rng = rand::thread_rng();
let salt: Vec<u8> = (0..PBKDF2_SALT_LEN).map(|_| rng.gen()).collect();
// This is 512 bits of output
@ -106,18 +107,18 @@ impl Password {
MessageDigest::sha256(),
key.as_mut_slice(),
)
.expect("PBKDF2 failure");
// Turn key to a vec.
KDF::PBKDF2(PBKDF2_COST, salt, key)
.map(|()| {
// Turn key to a vec.
KDF::PBKDF2(PBKDF2_COST, salt, key)
})
.map_err(|_| OperationError::CryptographyError)
}
pub fn new(cleartext: &str) -> Self {
Password {
material: Self::new_pbkdf2(cleartext),
}
pub fn new(cleartext: &str) -> Result<Self, OperationError> {
Self::new_pbkdf2(cleartext).map(|material| Password { material })
}
pub fn verify(&self, cleartext: &str) -> bool {
pub fn verify(&self, cleartext: &str) -> Result<bool, OperationError> {
match &self.material {
KDF::PBKDF2(cost, salt, key) => {
// We have to get the number of bits to derive from our stored hash
@ -132,9 +133,11 @@ impl Password {
MessageDigest::sha256(),
chal_key.as_mut_slice(),
)
.expect("PBKDF2 failure");
// Actually compare the outputs.
&chal_key == key
.map_err(|_| OperationError::CryptographyError)
.map(|()| {
// Actually compare the outputs.
&chal_key == key
})
}
}
}
@ -208,29 +211,29 @@ impl TryFrom<DbCredV1> for Credential {
}
impl Credential {
pub fn new_password_only(cleartext: &str) -> Self {
Credential {
password: Some(Password::new(cleartext)),
pub fn new_password_only(cleartext: &str) -> Result<Self, OperationError> {
Password::new(cleartext).map(|pw| Credential {
password: Some(pw),
totp: None,
claims: Vec::new(),
uuid: Uuid::new_v4(),
}
})
}
pub fn set_password(&self, cleartext: &str) -> Self {
Credential {
password: Some(Password::new(cleartext)),
pub fn set_password(&self, cleartext: &str) -> Result<Self, OperationError> {
Password::new(cleartext).map(|pw| Credential {
password: Some(pw),
totp: self.totp.clone(),
claims: self.claims.clone(),
uuid: self.uuid,
}
})
}
#[cfg(test)]
pub fn verify_password(&self, cleartext: &str) -> bool {
match &self.password {
Some(pw) => pw.verify(cleartext),
None => panic!(),
Some(pw) => pw.verify(cleartext).unwrap_or(false),
None => false,
}
}
@ -299,7 +302,7 @@ mod tests {
#[test]
fn test_credential_simple() {
let c = Credential::new_password_only("password");
let c = Credential::new_password_only("password").unwrap();
assert!(c.verify_password("password"));
assert!(!c.verify_password("password1"));
assert!(!c.verify_password("Password1"));
@ -317,6 +320,6 @@ mod tests {
let im_pw = "pbkdf2_sha256$36000$xIEozuZVAoYm$uW1b35DUKyhvQAf1mBqMvoBDcqSD06juzyO/nmyV0+w=";
let password = "eicieY7ahchaoCh0eeTa";
let r = Password::try_from(im_pw).expect("Failed to parse");
assert!(r.verify(password));
assert!(r.verify(password).unwrap_or(false));
}
}

View file

@ -323,14 +323,14 @@ impl Entry<EntryInit, EntryNew> {
let attr = k.to_lowercase();
let vv: Set<Value> = match attr.as_str() {
"attributename" | "classname" | "domain" => {
vs.into_iter().map(|v| Value::new_iutf8(v)).collect()
vs.into_iter().map(|v| Value::new_iutf8(&v)).collect()
}
"name" | "domain_name" => {
vs.into_iter().map(|v| Value::new_iname(v)).collect()
vs.into_iter().map(|v| Value::new_iname(&v)).collect()
}
"userid" | "uidnumber" => {
warn!("WARNING: Use of unstabilised attributes userid/uidnumber");
vs.into_iter().map(|v| Value::new_iutf8(v)).collect()
vs.into_iter().map(|v| Value::new_iutf8(&v)).collect()
}
"class" | "acp_create_class" | "acp_modify_class" => {
vs.into_iter().map(|v| Value::new_class(v.as_str())).collect()
@ -1299,7 +1299,7 @@ impl Entry<EntrySealed, EntryCommitted> {
pub fn reduce_attributes(
self,
allowed_attrs: BTreeSet<&str>,
allowed_attrs: &BTreeSet<&str>,
) -> Entry<EntryReduced, EntryCommitted> {
// Remove all attrs from our tree that are NOT in the allowed set.
@ -1880,7 +1880,7 @@ impl From<&SchemaAttribute> for Entry<EntryInit, EntryNew> {
// Convert an Attribute to an entry ... make it good!
let uuid_v = btreeset![Value::new_uuidr(&s.uuid)];
let name_v = btreeset![Value::new_iutf8(s.name.clone())];
let name_v = btreeset![Value::new_iutf8(s.name.as_str())];
let desc_v = btreeset![Value::new_utf8(s.description.clone())];
let multivalue_v = btreeset![Value::from(s.multivalue)];
@ -1922,7 +1922,7 @@ impl From<&SchemaClass> for Entry<EntryInit, EntryNew> {
fn from(s: &SchemaClass) -> Self {
let uuid_v = btreeset![Value::new_uuidr(&s.uuid)];
let name_v = btreeset![Value::new_iutf8(s.name.clone())];
let name_v = btreeset![Value::new_iutf8(s.name.as_str())];
let desc_v = btreeset![Value::new_utf8(s.description.clone())];
let mut attrs: Map<String, Set<Value>> = Map::with_capacity(16);
@ -2070,7 +2070,7 @@ mod tests {
let present_single_mods = unsafe {
ModifyList::new_valid_list(vec![Modify::Present(
String::from("attr"),
Value::new_iutf8s("value"),
Value::new_iutf8("value"),
)])
};
@ -2078,20 +2078,20 @@ mod tests {
// Assert the changes are there
assert!(e.attribute_equality("userid", &PartialValue::new_utf8s("william")));
assert!(e.attribute_equality("attr", &PartialValue::new_iutf8s("value")));
assert!(e.attribute_equality("attr", &PartialValue::new_iutf8("value")));
// Assert present for multivalue
let present_multivalue_mods = unsafe {
ModifyList::new_valid_list(vec![
Modify::Present(String::from("class"), Value::new_iutf8s("test")),
Modify::Present(String::from("class"), Value::new_iutf8s("multi_test")),
Modify::Present(String::from("class"), Value::new_iutf8("test")),
Modify::Present(String::from("class"), Value::new_iutf8("multi_test")),
])
};
e.apply_modlist(&present_multivalue_mods);
assert!(e.attribute_equality("class", &PartialValue::new_iutf8s("test")));
assert!(e.attribute_equality("class", &PartialValue::new_iutf8s("multi_test")));
assert!(e.attribute_equality("class", &PartialValue::new_iutf8("test")));
assert!(e.attribute_equality("class", &PartialValue::new_iutf8("multi_test")));
// Assert purge on single/multi/empty value
let purge_single_mods =
@ -2116,12 +2116,12 @@ mod tests {
let remove_mods = unsafe {
ModifyList::new_valid_list(vec![Modify::Removed(
String::from("attr"),
PartialValue::new_iutf8s("value"),
PartialValue::new_iutf8("value"),
)])
};
e.apply_modlist(&present_single_mods);
assert!(e.attribute_equality("attr", &PartialValue::new_iutf8s("value")));
assert!(e.attribute_equality("attr", &PartialValue::new_iutf8("value")));
e.apply_modlist(&remove_mods);
assert!(e.attrs.get("attr").unwrap().is_empty());
@ -2282,7 +2282,7 @@ mod tests {
let mut e: Entry<EntryInit, EntryNew> = Entry::new();
e.add_ava("class", Value::new_class("person"));
e.add_ava("gidnumber", Value::new_uint32(1300));
e.add_ava("name", Value::new_iname_s("testperson"));
e.add_ava("name", Value::new_iname("testperson"));
e.add_ava("spn", Value::new_spn_str("testperson", "example.com"));
e.add_ava(
"uuid",
@ -2332,7 +2332,7 @@ mod tests {
let mut e2: Entry<EntryInit, EntryNew> = Entry::new();
e2.add_ava("class", Value::new_class("person"));
e2.add_ava("name", Value::new_iname_s("testperson"));
e2.add_ava("name", Value::new_iname("testperson"));
e2.add_ava("spn", Value::new_spn_str("testperson", "example.com"));
let e2 = unsafe { e2.into_sealed_committed() };

View file

@ -36,7 +36,7 @@ impl SearchResult {
pub fn new(
audit: &mut AuditScope,
qs: &QueryServerReadTransaction,
entries: Vec<Entry<EntryReduced, EntryCommitted>>,
entries: &[Entry<EntryReduced, EntryCommitted>],
) -> Result<Self, OperationError> {
let entries: Result<_, _> = entries
.iter()
@ -461,7 +461,7 @@ impl SearchEvent {
audit: &mut AuditScope,
qs: &QueryServerReadTransaction,
euuid: &Uuid,
filter: Filter<FilterInvalid>,
filter: &Filter<FilterInvalid>,
attrs: Option<BTreeSet<String>>,
) -> Result<Self, OperationError> {
Ok(SearchEvent {
@ -618,7 +618,7 @@ impl DeleteEvent {
pub fn from_parts(
audit: &mut AuditScope,
uat: Option<UserAuthToken>,
filter: Filter<FilterInvalid>,
filter: &Filter<FilterInvalid>,
qs: &QueryServerWriteTransaction,
) -> Result<Self, OperationError> {
Ok(DeleteEvent {
@ -716,7 +716,7 @@ impl ModifyEvent {
audit: &mut AuditScope,
uat: Option<UserAuthToken>,
target_uuid: Uuid,
proto_ml: ProtoModifyList,
proto_ml: &ProtoModifyList,
filter: Filter<FilterInvalid>,
qs: &QueryServerWriteTransaction,
) -> Result<Self, OperationError> {
@ -747,7 +747,7 @@ impl ModifyEvent {
audit: &mut AuditScope,
uat: Option<UserAuthToken>,
target_uuid: Uuid,
ml: ModifyList<ModifyInvalid>,
ml: &ModifyList<ModifyInvalid>,
filter: Filter<FilterInvalid>,
qs: &QueryServerWriteTransaction,
) -> Result<Self, OperationError> {
@ -775,11 +775,11 @@ impl ModifyEvent {
audit: &mut AuditScope,
uat: Option<UserAuthToken>,
target_uuid: Uuid,
attr: String,
attr: &str,
filter: Filter<FilterInvalid>,
qs: &QueryServerWriteTransaction,
) -> Result<Self, OperationError> {
let ml = ModifyList::new_purge(attr.as_str());
let ml = ModifyList::new_purge(attr);
let f_uuid = filter_all!(f_eq("uuid", PartialValue::new_uuid(target_uuid)));
// Add any supplemental conditions we have.
let f = Filter::join_parts_and(f_uuid, filter);
@ -1012,7 +1012,7 @@ impl WhoamiResult {
pub fn new(
audit: &mut AuditScope,
qs: &QueryServerReadTransaction,
e: Entry<EntryReduced, EntryCommitted>,
e: &Entry<EntryReduced, EntryCommitted>,
uat: UserAuthToken,
) -> Result<Self, OperationError> {
Ok(WhoamiResult {

View file

@ -493,8 +493,8 @@ impl FilterComp {
fn new_ignore_hidden(fc: FilterComp) -> Self {
FilterComp::And(vec![
FilterComp::AndNot(Box::new(FilterComp::Or(vec![
FilterComp::Eq("class".to_string(), PartialValue::new_iutf8s("tombstone")),
FilterComp::Eq("class".to_string(), PartialValue::new_iutf8s("recycled")),
FilterComp::Eq("class".to_string(), PartialValue::new_iutf8("tombstone")),
FilterComp::Eq("class".to_string(), PartialValue::new_iutf8("recycled")),
]))),
fc,
])
@ -502,7 +502,7 @@ impl FilterComp {
fn new_recycled(fc: FilterComp) -> Self {
FilterComp::And(vec![
FilterComp::Eq("class".to_string(), PartialValue::new_iutf8s("recycled")),
FilterComp::Eq("class".to_string(), PartialValue::new_iutf8("recycled")),
fc,
])
}
@ -1071,6 +1071,7 @@ impl FilterResolved {
// If the f_list_or only has one element, pop it and return.
if f_list_new.len() == 1 {
#[allow(clippy::expect_used)]
f_list_new.pop().expect("corrupt?")
} else {
// finally, optimise this list by sorting.
@ -1100,6 +1101,7 @@ impl FilterResolved {
// If the f_list_or only has one element, pop it and return.
if f_list_new.len() == 1 {
#[allow(clippy::expect_used)]
f_list_new.pop().expect("corrupt?")
} else {
// sort, but reverse so that sub-optimal elements are earlier
@ -1138,8 +1140,8 @@ mod tests {
// AFTER
let _complex_filt: Filter<FilterInvalid> = filter!(f_and!([
f_or!([
f_eq("userid", PartialValue::new_iutf8s("test_a")),
f_eq("userid", PartialValue::new_iutf8s("test_b")),
f_eq("userid", PartialValue::new_iutf8("test_a")),
f_eq("userid", PartialValue::new_iutf8("test_b")),
]),
f_sub("class", PartialValue::new_class("user")),
]));
@ -1310,12 +1312,12 @@ mod tests {
// antisymmetry: if a < b then !(a > b), as well as a > b implying !(a < b); and
// These are unindexed so we have to check them this way.
let f_t3b = unsafe { filter_resolved!(f_eq("userid", PartialValue::new_iutf8s(""))) };
let f_t3b = unsafe { filter_resolved!(f_eq("userid", PartialValue::new_iutf8(""))) };
assert_eq!(f_t1a.partial_cmp(&f_t3b), Some(Ordering::Less));
assert_eq!(f_t3b.partial_cmp(&f_t1a), Some(Ordering::Greater));
// transitivity: a < b and b < c implies a < c. The same must hold for both == and >.
let f_t4b = unsafe { filter_resolved!(f_sub("userid", PartialValue::new_iutf8s(""))) };
let f_t4b = unsafe { filter_resolved!(f_sub("userid", PartialValue::new_iutf8(""))) };
assert_eq!(f_t1a.partial_cmp(&f_t4b), Some(Ordering::Less));
assert_eq!(f_t3b.partial_cmp(&f_t4b), Some(Ordering::Less));
@ -1384,32 +1386,32 @@ mod tests {
let f_t1a = unsafe {
filter_resolved!(f_or!([
f_eq("userid", PartialValue::new_iutf8s("william")),
f_eq("uidnumber", PartialValue::new_iutf8s("1000")),
f_eq("userid", PartialValue::new_iutf8("william")),
f_eq("uidnumber", PartialValue::new_iutf8("1000")),
]))
};
assert!(e.entry_match_no_index(&f_t1a));
let f_t2a = unsafe {
filter_resolved!(f_or!([
f_eq("userid", PartialValue::new_iutf8s("william")),
f_eq("uidnumber", PartialValue::new_iutf8s("1001")),
f_eq("userid", PartialValue::new_iutf8("william")),
f_eq("uidnumber", PartialValue::new_iutf8("1001")),
]))
};
assert!(e.entry_match_no_index(&f_t2a));
let f_t3a = unsafe {
filter_resolved!(f_or!([
f_eq("userid", PartialValue::new_iutf8s("alice")),
f_eq("uidnumber", PartialValue::new_iutf8s("1000")),
f_eq("userid", PartialValue::new_iutf8("alice")),
f_eq("uidnumber", PartialValue::new_iutf8("1000")),
]))
};
assert!(e.entry_match_no_index(&f_t3a));
let f_t4a = unsafe {
filter_resolved!(f_or!([
f_eq("userid", PartialValue::new_iutf8s("alice")),
f_eq("uidnumber", PartialValue::new_iutf8s("1001")),
f_eq("userid", PartialValue::new_iutf8("alice")),
f_eq("uidnumber", PartialValue::new_iutf8("1001")),
]))
};
assert!(!e.entry_match_no_index(&f_t4a));
@ -1432,32 +1434,32 @@ mod tests {
let f_t1a = unsafe {
filter_resolved!(f_and!([
f_eq("userid", PartialValue::new_iutf8s("william")),
f_eq("uidnumber", PartialValue::new_iutf8s("1000")),
f_eq("userid", PartialValue::new_iutf8("william")),
f_eq("uidnumber", PartialValue::new_iutf8("1000")),
]))
};
assert!(e.entry_match_no_index(&f_t1a));
let f_t2a = unsafe {
filter_resolved!(f_and!([
f_eq("userid", PartialValue::new_iutf8s("william")),
f_eq("uidnumber", PartialValue::new_iutf8s("1001")),
f_eq("userid", PartialValue::new_iutf8("william")),
f_eq("uidnumber", PartialValue::new_iutf8("1001")),
]))
};
assert!(!e.entry_match_no_index(&f_t2a));
let f_t3a = unsafe {
filter_resolved!(f_and!([
f_eq("userid", PartialValue::new_iutf8s("alice")),
f_eq("uidnumber", PartialValue::new_iutf8s("1000")),
f_eq("userid", PartialValue::new_iutf8("alice")),
f_eq("uidnumber", PartialValue::new_iutf8("1000")),
]))
};
assert!(!e.entry_match_no_index(&f_t3a));
let f_t4a = unsafe {
filter_resolved!(f_and!([
f_eq("userid", PartialValue::new_iutf8s("alice")),
f_eq("uidnumber", PartialValue::new_iutf8s("1001")),
f_eq("userid", PartialValue::new_iutf8("alice")),
f_eq("uidnumber", PartialValue::new_iutf8("1001")),
]))
};
assert!(!e.entry_match_no_index(&f_t4a));
@ -1478,16 +1480,12 @@ mod tests {
.into_sealed_new()
};
let f_t1a = unsafe {
filter_resolved!(f_andnot(f_eq("userid", PartialValue::new_iutf8s("alice"))))
};
let f_t1a =
unsafe { filter_resolved!(f_andnot(f_eq("userid", PartialValue::new_iutf8("alice")))) };
assert!(e1.entry_match_no_index(&f_t1a));
let f_t2a = unsafe {
filter_resolved!(f_andnot(f_eq(
"userid",
PartialValue::new_iutf8s("william")
)))
filter_resolved!(f_andnot(f_eq("userid", PartialValue::new_iutf8("william"))))
};
assert!(!e1.entry_match_no_index(&f_t2a));
}
@ -1550,8 +1548,8 @@ mod tests {
filter_resolved!(f_and!([
f_eq("class", PartialValue::new_class("person")),
f_or!([
f_eq("uidnumber", PartialValue::new_iutf8s("1001")),
f_eq("uidnumber", PartialValue::new_iutf8s("1000"))
f_eq("uidnumber", PartialValue::new_iutf8("1001")),
f_eq("uidnumber", PartialValue::new_iutf8("1000"))
])
]))
};
@ -1571,8 +1569,8 @@ mod tests {
// to determine what attrs we are requesting regardless of the partialvalue.
let f_t1a = unsafe {
filter_valid!(f_and!([
f_eq("userid", PartialValue::new_iutf8s("alice")),
f_eq("class", PartialValue::new_iutf8s("1001")),
f_eq("userid", PartialValue::new_iutf8("alice")),
f_eq("class", PartialValue::new_iutf8("1001")),
]))
};
@ -1580,9 +1578,9 @@ mod tests {
let f_t2a = unsafe {
filter_valid!(f_and!([
f_eq("userid", PartialValue::new_iutf8s("alice")),
f_eq("class", PartialValue::new_iutf8s("1001")),
f_eq("userid", PartialValue::new_iutf8s("claire")),
f_eq("userid", PartialValue::new_iutf8("alice")),
f_eq("class", PartialValue::new_iutf8("1001")),
f_eq("userid", PartialValue::new_iutf8("claire")),
]))
};

View file

@ -98,33 +98,33 @@ pub(crate) struct Account {
impl Account {
pub(crate) fn try_from_entry_ro(
au: &mut AuditScope,
value: Entry<EntrySealed, EntryCommitted>,
value: &Entry<EntrySealed, EntryCommitted>,
qs: &mut QueryServerReadTransaction,
) -> Result<Self, OperationError> {
lperf_trace_segment!(au, "idm::account::try_from_entry_ro", || {
let groups = Group::try_from_account_entry_ro(au, &value, qs)?;
let groups = Group::try_from_account_entry_ro(au, value, qs)?;
try_from_entry!(value, groups)
})
}
pub(crate) fn try_from_entry_rw(
au: &mut AuditScope,
value: Entry<EntrySealed, EntryCommitted>,
value: &Entry<EntrySealed, EntryCommitted>,
qs: &mut QueryServerWriteTransaction,
) -> Result<Self, OperationError> {
let groups = Group::try_from_account_entry_rw(au, &value, qs)?;
let groups = Group::try_from_account_entry_rw(au, value, qs)?;
try_from_entry!(value, groups)
}
#[cfg(test)]
pub(crate) fn try_from_entry_no_groups(
value: Entry<EntrySealed, EntryCommitted>,
value: &Entry<EntrySealed, EntryCommitted>,
) -> Result<Self, OperationError> {
try_from_entry!(value, vec![])
}
// Could this actually take a claims list and application instead?
pub(crate) fn to_userauthtoken(&self, claims: Vec<Claim>) -> Option<UserAuthToken> {
pub(crate) fn to_userauthtoken(&self, claims: &[Claim]) -> Option<UserAuthToken> {
// This could consume self?
// The cred handler provided is what authenticated this user, so we can use it to
// process what the proper claims should be.
@ -161,13 +161,13 @@ impl Account {
match &self.primary {
// Change the cred
Some(primary) => {
let ncred = primary.set_password(cleartext);
let ncred = primary.set_password(cleartext)?;
let vcred = Value::new_credential("primary", ncred);
Ok(ModifyList::new_purge_and_set("primary_credential", vcred))
}
// Make a new credential instead
None => {
let ncred = Credential::new_password_only(cleartext);
let ncred = Credential::new_password_only(cleartext)?;
let vcred = Value::new_credential("primary", ncred);
Ok(ModifyList::new_purge_and_set("primary_credential", vcred))
}

View file

@ -136,7 +136,7 @@ impl CredHandler {
_ => {
match cred {
AuthCredential::Password(cleartext) => {
if pw.verify(cleartext.as_str()) {
if pw.verify(cleartext.as_str()).unwrap_or(false) {
lsecurity!(au, "Handler::Password -> Result::Success");
CredState::Success(Vec::new())
} else {
@ -170,7 +170,7 @@ impl CredHandler {
match cred {
AuthCredential::Password(cleartext) => {
// if pw -> check
if pw_totp.pw.verify(cleartext.as_str()) {
if pw_totp.pw.verify(cleartext.as_str()).unwrap_or(false) {
pw_totp.pw_state = CredVerifyState::Success;
match pw_totp.totp_state {
CredVerifyState::Init => {
@ -366,7 +366,7 @@ impl AuthSession {
self.finished = true;
let uat = self
.account
.to_userauthtoken(claims)
.to_userauthtoken(&claims)
.ok_or(OperationError::InvalidState)?;
Ok(AuthState::Success(uat))
}
@ -492,7 +492,7 @@ mod tests {
// create the ent
let mut account = entry_str_to_account!(JSON_ADMIN_V1);
// manually load in a cred
let cred = Credential::new_password_only("test_password");
let cred = Credential::new_password_only("test_password").unwrap();
account.primary = Some(cred);
// now check
@ -549,7 +549,9 @@ mod tests {
let pw_good = "test_password";
let pw_bad = "bad_password";
let cred = Credential::new_password_only(pw_good).update_totp(totp);
let cred = Credential::new_password_only(pw_good)
.unwrap()
.update_totp(totp);
// add totp also
account.primary = Some(cred);

View file

@ -47,8 +47,7 @@ macro_rules! try_from_account_e {
e
})?;
// Now convert the group entries to groups.
let groups: Result<Vec<_>, _> =
ges.into_iter().map(Group::try_from_entry).collect();
let groups: Result<Vec<_>, _> = ges.iter().map(Group::try_from_entry).collect();
groups.map_err(|e| {
// log
e
@ -90,7 +89,7 @@ impl Group {
}
pub fn try_from_entry(
value: Entry<EntrySealed, EntryCommitted>,
value: &Entry<EntrySealed, EntryCommitted>,
) -> Result<Self, OperationError> {
if !value.attribute_value_pres("class", &PVCLASS_GROUP) {
return Err(OperationError::InvalidAccountState(

View file

@ -24,7 +24,7 @@ pub(crate) struct RadiusAccount {
impl RadiusAccount {
pub(crate) fn try_from_entry_reduced(
au: &mut AuditScope,
value: Entry<EntryReduced, EntryCommitted>,
value: &Entry<EntryReduced, EntryCommitted>,
qs: &mut QueryServerReadTransaction,
) -> Result<Self, OperationError> {
if !value.attribute_value_pres("class", &PVCLASS_ACCOUNT) {

View file

@ -172,7 +172,7 @@ impl<'a> IdmServerWriteTransaction<'a> {
// typing and functionality so we can assess what auth types can
// continue, and helps to keep non-needed entry specific data
// out of the LRU.
let account = Account::try_from_entry_ro(au, entry, &mut self.qs_read)?;
let account = Account::try_from_entry_ro(au, &entry, &mut self.qs_read)?;
let auth_session = AuthSession::new(au, account, init.appid.clone());
// Get the set of mechanisms that can proceed. This is tied
@ -240,7 +240,7 @@ impl<'a> IdmServerWriteTransaction<'a> {
.qs_read
.internal_search_uuid(au, &uae.target)
.and_then(|account_entry| {
UnixUserAccount::try_from_entry_ro(au, account_entry, &mut self.qs_read)
UnixUserAccount::try_from_entry_ro(au, &account_entry, &mut self.qs_read)
})
.map_err(|e| {
ladmin_error!(au, "Failed to start auth unix -> {:?}", e);
@ -254,7 +254,7 @@ impl<'a> IdmServerWriteTransaction<'a> {
pub fn auth_ldap(
&mut self,
au: &mut AuditScope,
lae: LdapAuthEvent,
lae: &LdapAuthEvent,
_ct: Duration,
) -> Result<Option<LdapBoundToken>, OperationError> {
// TODO #59: Implement soft lock checking for unix creds here!
@ -271,14 +271,15 @@ impl<'a> IdmServerWriteTransaction<'a> {
// if anonymous
if lae.target == *UUID_ANONYMOUS {
// TODO: #59 We should have checked if anonymous was locked by now!
let account = Account::try_from_entry_ro(au, account_entry, &mut self.qs_read)?;
let account = Account::try_from_entry_ro(au, &account_entry, &mut self.qs_read)?;
Ok(Some(LdapBoundToken {
spn: account.spn,
uuid: *UUID_ANONYMOUS,
effective_uuid: *UUID_ANONYMOUS,
}))
} else {
let account = UnixUserAccount::try_from_entry_ro(au, account_entry, &mut self.qs_read)?;
let account =
UnixUserAccount::try_from_entry_ro(au, &account_entry, &mut self.qs_read)?;
if account
.verify_unix_credential(au, lae.cleartext.as_str())?
.is_some()
@ -312,7 +313,7 @@ impl<'a> IdmServerProxyReadTransaction<'a> {
.qs_read
.impersonate_search_ext_uuid(au, &rate.target, &rate.event)
.and_then(|account_entry| {
RadiusAccount::try_from_entry_reduced(au, account_entry, &mut self.qs_read)
RadiusAccount::try_from_entry_reduced(au, &account_entry, &mut self.qs_read)
})
.map_err(|e| {
ladmin_error!(au, "Failed to start radius auth token {:?}", e);
@ -331,7 +332,7 @@ impl<'a> IdmServerProxyReadTransaction<'a> {
.qs_read
.impersonate_search_ext_uuid(au, &uute.target, &uute.event)
.and_then(|account_entry| {
UnixUserAccount::try_from_entry_reduced(au, account_entry, &mut self.qs_read)
UnixUserAccount::try_from_entry_reduced(au, &account_entry, &mut self.qs_read)
})
.map_err(|e| {
ladmin_error!(au, "Failed to start unix user token -> {:?}", e);
@ -349,7 +350,7 @@ impl<'a> IdmServerProxyReadTransaction<'a> {
let group = self
.qs_read
.impersonate_search_ext_uuid(au, &uute.target, &uute.event)
.and_then(UnixGroup::try_from_entry_reduced)
.and_then(|e| UnixGroup::try_from_entry_reduced(&e))
.map_err(|e| {
ladmin_error!(au, "Failed to start unix group token {:?}", e);
e
@ -413,7 +414,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
// check a password badlist to eliminate more content
// we check the password as "lower case" to help eliminate possibilities
let lc_password = PartialValue::new_iutf8s(cleartext);
let lc_password = PartialValue::new_iutf8(cleartext);
let badlist_entry = self
.qs_write
.internal_search_uuid(au, &UUID_SYSTEM_CONFIG)
@ -439,7 +440,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
.qs_write
.internal_search_uuid(au, target)
.and_then(|account_entry| {
Account::try_from_entry_rw(au, account_entry, &mut self.qs_write)
Account::try_from_entry_rw(au, &account_entry, &mut self.qs_write)
})
.map_err(|e| {
ladmin_error!(au, "Failed to search account {:?}", e);
@ -495,10 +496,10 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
.impersonate_modify(
au,
// Filter as executed
filter!(f_eq("uuid", PartialValue::new_uuidr(&pce.target))),
&filter!(f_eq("uuid", PartialValue::new_uuidr(&pce.target))),
// Filter as intended (acp)
filter_all!(f_eq("uuid", PartialValue::new_uuidr(&pce.target))),
modlist,
&filter_all!(f_eq("uuid", PartialValue::new_uuidr(&pce.target))),
&modlist,
&pce.event,
)
.map_err(|e| {
@ -520,7 +521,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
.internal_search_uuid(au, &pce.target)
.and_then(|account_entry| {
// Assert the account is unix and valid.
UnixUserAccount::try_from_entry_rw(au, account_entry, &mut self.qs_write)
UnixUserAccount::try_from_entry_rw(au, &account_entry, &mut self.qs_write)
})
.map_err(|e| {
ladmin_error!(au, "Failed to start set unix account password {:?}", e);
@ -560,10 +561,10 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
.impersonate_modify(
au,
// Filter as executed
filter!(f_eq("uuid", PartialValue::new_uuidr(&pce.target))),
&filter!(f_eq("uuid", PartialValue::new_uuidr(&pce.target))),
// Filter as intended (acp)
filter_all!(f_eq("uuid", PartialValue::new_uuidr(&pce.target))),
modlist,
&filter_all!(f_eq("uuid", PartialValue::new_uuidr(&pce.target))),
&modlist,
&pce.event,
)
.map_err(|e| {
@ -576,16 +577,16 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
pub fn recover_account(
&mut self,
au: &mut AuditScope,
name: String,
cleartext: String,
name: &str,
cleartext: &str,
) -> Result<(), OperationError> {
// name to uuid
let target = self.qs_write.name_to_uuid(au, name.as_str()).map_err(|e| {
let target = self.qs_write.name_to_uuid(au, name).map_err(|e| {
ladmin_error!(au, "name to uuid failed {:?}", e);
e
})?;
// internal pce.
let pce = PasswordChangeEvent::new_internal(&target, cleartext.as_str(), None);
let pce = PasswordChangeEvent::new_internal(&target, cleartext, None);
// now set_account_password.
self.set_account_password(au, &pce)
}
@ -620,10 +621,10 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
.impersonate_modify(
au,
// Filter as executed
filter!(f_eq("uuid", PartialValue::new_uuidr(&gpe.target))),
&filter!(f_eq("uuid", PartialValue::new_uuidr(&gpe.target))),
// Filter as intended (acp)
filter_all!(f_eq("uuid", PartialValue::new_uuidr(&gpe.target))),
modlist,
&filter_all!(f_eq("uuid", PartialValue::new_uuidr(&gpe.target))),
&modlist,
// Provide the event to impersonate
&gpe.event,
)
@ -659,10 +660,10 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
.impersonate_modify(
au,
// Filter as executed
filter!(f_eq("uuid", PartialValue::new_uuidr(&rrse.target))),
&filter!(f_eq("uuid", PartialValue::new_uuidr(&rrse.target))),
// Filter as intended (acp)
filter_all!(f_eq("uuid", PartialValue::new_uuidr(&rrse.target))),
modlist,
&filter_all!(f_eq("uuid", PartialValue::new_uuidr(&rrse.target))),
&modlist,
// Provide the event to impersonate
&rrse.event,
)
@ -727,7 +728,11 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
let session = self
.mfareg_sessions
.remove(&sessionid)
.expect("Session within transaction vanished!");
.ok_or(OperationError::InvalidState)
.map_err(|e| {
ladmin_error!(au, "Session within transaction vanished!");
e
})?;
// reg the token
let modlist = session.account.gen_totp_mod(token).map_err(|e| {
ladmin_error!(au, "Failed to gen totp mod {:?}", e);
@ -738,10 +743,10 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
.impersonate_modify(
au,
// Filter as executed
filter!(f_eq("uuid", PartialValue::new_uuidr(&session.account.uuid))),
&filter!(f_eq("uuid", PartialValue::new_uuidr(&session.account.uuid))),
// Filter as intended (acp)
filter_all!(f_eq("uuid", PartialValue::new_uuidr(&session.account.uuid))),
modlist,
&filter_all!(f_eq("uuid", PartialValue::new_uuidr(&session.account.uuid))),
&modlist,
&vte.event,
)
.map_err(|e| {
@ -913,7 +918,7 @@ mod tests {
qs: &QueryServer,
pw: &str,
) -> Result<(), OperationError> {
let cred = Credential::new_password_only(pw);
let cred = Credential::new_password_only(pw)?;
let v_cred = Value::new_credential("primary", cred);
let qs_write = qs.write(duration_from_epoch_now());

View file

@ -105,28 +105,28 @@ macro_rules! try_from_entry {
impl UnixUserAccount {
pub(crate) fn try_from_entry_rw(
au: &mut AuditScope,
value: Entry<EntrySealed, EntryCommitted>,
value: &Entry<EntrySealed, EntryCommitted>,
qs: &mut QueryServerWriteTransaction,
) -> Result<Self, OperationError> {
let groups = UnixGroup::try_from_account_entry_rw(au, &value, qs)?;
let groups = UnixGroup::try_from_account_entry_rw(au, value, qs)?;
try_from_entry!(value, groups)
}
pub(crate) fn try_from_entry_ro(
au: &mut AuditScope,
value: Entry<EntrySealed, EntryCommitted>,
value: &Entry<EntrySealed, EntryCommitted>,
qs: &mut QueryServerReadTransaction,
) -> Result<Self, OperationError> {
let groups = UnixGroup::try_from_account_entry_ro(au, &value, qs)?;
let groups = UnixGroup::try_from_account_entry_ro(au, value, qs)?;
try_from_entry!(value, groups)
}
pub(crate) fn try_from_entry_reduced(
au: &mut AuditScope,
value: Entry<EntryReduced, EntryCommitted>,
value: &Entry<EntryReduced, EntryCommitted>,
qs: &mut QueryServerReadTransaction,
) -> Result<Self, OperationError> {
let groups = UnixGroup::try_from_account_entry_red_ro(au, &value, qs)?;
let groups = UnixGroup::try_from_account_entry_red_ro(au, value, qs)?;
try_from_entry!(value, groups)
}
@ -154,7 +154,7 @@ impl UnixUserAccount {
&self,
cleartext: &str,
) -> Result<ModifyList<ModifyInvalid>, OperationError> {
let ncred = Credential::new_password_only(cleartext);
let ncred = Credential::new_password_only(cleartext)?;
let vcred = Value::new_credential("unix", ncred);
Ok(ModifyList::new_purge_and_set("unix_password", vcred))
}
@ -169,7 +169,7 @@ impl UnixUserAccount {
match &self.cred {
Some(cred) => match &cred.password {
Some(pw) => {
if pw.verify(cleartext) {
if pw.verify(cleartext)? {
lsecurity!(au, "Successful unix cred handling");
Some(self.to_unixusertoken()).transpose()
} else {
@ -304,7 +304,7 @@ macro_rules! try_from_account_group_e {
]));
let ges: Vec<_> = $qs.internal_search($au, f)?;
let groups: Result<Vec<_>, _> = iter::once(Ok(upg))
.chain(ges.into_iter().map(UnixGroup::try_from_entry))
.chain(ges.iter().map(UnixGroup::try_from_entry))
.collect();
groups
}
@ -342,13 +342,13 @@ impl UnixGroup {
}
pub fn try_from_entry_reduced(
value: Entry<EntryReduced, EntryCommitted>,
value: &Entry<EntryReduced, EntryCommitted>,
) -> Result<Self, OperationError> {
try_from_group_e!(value)
}
pub fn try_from_entry(
value: Entry<EntrySealed, EntryCommitted>,
value: &Entry<EntrySealed, EntryCommitted>,
) -> Result<Self, OperationError> {
try_from_group_e!(value)
}

View file

@ -251,7 +251,7 @@ impl LdapServer {
au,
&idm_read.qs_read,
&uat.effective_uuid,
filter,
&filter,
attrs,
)
})?;
@ -343,10 +343,13 @@ impl LdapServer {
let ct = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.expect("Clock failure!");
.map_err(|e| {
ladmin_error!(au, "Clock Error -> {:?}", e);
OperationError::InvalidState
})?;
let lae = LdapAuthEvent::from_parts(au, target_uuid, pw.to_string())?;
idm_write.auth_ldap(au, lae, ct).and_then(|r| {
idm_write.auth_ldap(au, &lae, ct).and_then(|r| {
idm_write.commit(au).map(|_| {
if r.is_some() {
lsecurity!(au, "✅ LDAP Bind success {}", dn);

View file

@ -2,7 +2,7 @@
#![warn(unused_extern_crates)]
#![deny(clippy::unwrap_used)]
#![deny(clippy::expect_used)]
#![deny(clippy::panic)]
// #![deny(clippy::panic)]
#![deny(clippy::unreachable)]
#![deny(clippy::await_holding_lock)]
#![deny(clippy::needless_pass_by_value)]

View file

@ -108,7 +108,7 @@ macro_rules! entry_str_to_account {
let e = unsafe { e.into_sealed_committed() };
Account::try_from_entry_no_groups(e).expect("Account conversion failure")
Account::try_from_entry_no_groups(&e).expect("Account conversion failure")
}};
}

View file

@ -297,7 +297,7 @@ mod tests {
),])),
ModifyList::new_list(vec![
Modify::Purged("name".to_string()),
Modify::Present("name".to_string(), Value::new_iname_s("testgroup_a"))
Modify::Present("name".to_string(), Value::new_iname("testgroup_a"))
]),
None,
|_, _| {}
@ -340,7 +340,7 @@ mod tests {
])),
ModifyList::new_list(vec![
Modify::Purged("name".to_string()),
Modify::Present("name".to_string(), Value::new_iname_s("testgroup"))
Modify::Present("name".to_string(), Value::new_iname("testgroup"))
]),
None,
|_, _| {}

View file

@ -43,7 +43,7 @@ impl Plugin for Domain {
ltrace!(au, "plugin_domain: Applying uuid transform");
// We only apply this if one isn't provided.
if !e.attribute_pres("domain_name") {
let n = Value::new_iname_s("example.com");
let n = Value::new_iname("example.com");
e.set_ava("domain_name", btreeset![n]);
ltrace!(au, "plugin_domain: Applying domain_name transform");
}

View file

@ -123,7 +123,7 @@ fn apply_memberof(
.collect()
));
let mut work_set = qs.internal_search_writeable(au, filt)?;
let mut work_set = qs.internal_search_writeable(au, &filt)?;
// Load the vecdeque with this batch.
while let Some((pre, mut tgte)) = work_set.pop() {

View file

@ -38,8 +38,7 @@ impl Plugin for PasswordImport {
debug_assert!(!vs.is_empty());
let im_pw = vs.first()
.unwrap()
.to_str()
.and_then(|v| v.to_str())
.ok_or_else(|| OperationError::Plugin(PluginError::PasswordImport("password_import has incorrect value type".to_string())))?;
// convert the import_password to a cred
@ -87,7 +86,7 @@ impl Plugin for PasswordImport {
let vs: Vec<_> = vs.into_iter().collect();
debug_assert!(!vs.is_empty());
let im_pw = vs.first().unwrap().to_str().ok_or_else(|| {
let im_pw = vs.first().and_then(|v| v.to_str()).ok_or_else(|| {
OperationError::Plugin(PluginError::PasswordImport(
"password_import has incorrect value type".to_string(),
))
@ -181,7 +180,7 @@ mod tests {
run_modify_test!(
Ok(()),
preload,
filter!(f_eq("name", PartialValue::new_iutf8s("testperson"))),
filter!(f_eq("name", PartialValue::new_iutf8("testperson"))),
ModifyList::new_list(vec![Modify::Present(
"password_import".to_string(),
Value::from(IMPORT_HASH)
@ -206,7 +205,7 @@ mod tests {
}"#,
);
let c = Credential::new_password_only("password");
let c = Credential::new_password_only("password").unwrap();
ea.add_ava("primary_credential", Value::new_credential("primary", c));
let preload = vec![ea];
@ -214,7 +213,7 @@ mod tests {
run_modify_test!(
Ok(()),
preload,
filter!(f_eq("name", PartialValue::new_iutf8s("testperson"))),
filter!(f_eq("name", PartialValue::new_iutf8("testperson"))),
ModifyList::new_list(vec![Modify::Present(
"password_import".to_string(),
Value::from(IMPORT_HASH)
@ -240,7 +239,9 @@ mod tests {
);
let totp = TOTP::generate_secure("test_totp".to_string(), TOTP_DEFAULT_STEP);
let c = Credential::new_password_only("password").update_totp(totp);
let c = Credential::new_password_only("password")
.unwrap()
.update_totp(totp);
ea.add_ava("primary_credential", Value::new_credential("primary", c));
let preload = vec![ea];
@ -248,7 +249,7 @@ mod tests {
run_modify_test!(
Ok(()),
preload,
filter!(f_eq("name", PartialValue::new_iutf8s("testperson"))),
filter!(f_eq("name", PartialValue::new_iutf8("testperson"))),
ModifyList::new_list(vec![Modify::Present(
"password_import".to_string(),
Value::from(IMPORT_HASH)

View file

@ -323,8 +323,8 @@ mod tests {
preload,
filter!(f_eq("classname", PartialValue::new_class("testclass"))),
modlist!([
m_pres("may", &Value::new_iutf8s("name")),
m_pres("must", &Value::new_iutf8s("name")),
m_pres("may", &Value::new_iutf8("name")),
m_pres("must", &Value::new_iutf8("name")),
]),
Some(JSON_ADMIN_V1),
|_, _| {}

View file

@ -190,7 +190,7 @@ impl Plugin for ReferentialIntegrity {
.map(|e| PartialValue::new_refer(*e.get_uuid()))
.collect();
let work_set = qs.internal_search_writeable(au, filt)?;
let work_set = qs.internal_search_writeable(au, &filt)?;
let (pre_candidates, candidates) = work_set
.into_iter()

View file

@ -79,6 +79,7 @@ impl Plugin for Spn {
if e.attribute_value_pres("class", &CLASS_GROUP)
|| e.attribute_value_pres("class", &CLASS_ACCOUNT)
{
// We do this in the loop so that we don't get it unless required.
if domain_name.is_none() {
domain_name = Some(Self::get_domain_name(au, qs)?);
}
@ -86,7 +87,15 @@ impl Plugin for Spn {
// It should be impossible to hit this expect as the is_none case should cause it to be replaced above.
let some_domain_name = domain_name
.as_ref()
.expect("Domain name option memory corruption has occured.");
.ok_or(OperationError::InvalidEntryState)
.map_err(|e| {
ladmin_error!(
au,
"Domain name option memory corruption may have occured. {:?}",
e
);
e
})?;
let spn = e
.generate_spn(some_domain_name.as_str())
@ -127,7 +136,15 @@ impl Plugin for Spn {
// It should be impossible to hit this expect as the is_none case should cause it to be replaced above.
let some_domain_name = domain_name
.as_ref()
.expect("Domain name option memory corruption has occured.");
.ok_or(OperationError::InvalidEntryState)
.map_err(|e| {
ladmin_error!(
au,
"Domain name option memory corruption may have occured. {:?}",
e
);
e
})?;
let spn = e
.generate_spn(some_domain_name.as_str())
@ -189,11 +206,11 @@ impl Plugin for Spn {
// within the transaction, just incase!
qs.internal_modify(
au,
filter!(f_or!([
&filter!(f_or!([
f_eq("class", PartialValue::new_class("group")),
f_eq("class", PartialValue::new_class("account"))
])),
modlist!([m_purge("spn")]),
&modlist!([m_purge("spn")]),
)
}

View file

@ -34,12 +34,15 @@ impl Cid {
}
}
#[allow(clippy::expect_used)]
pub fn sub_secs(&self, secs: u64) -> Result<Self, OperationError> {
self.ts
.checked_sub(Duration::from_secs(secs))
.map(|r| Cid {
d_uuid: Uuid::parse_str("00000000-0000-0000-0000-000000000000").unwrap(),
s_uuid: Uuid::parse_str("00000000-0000-0000-0000-000000000000").unwrap(),
d_uuid: Uuid::parse_str("00000000-0000-0000-0000-000000000000")
.expect("Invalid compiled d_uuid"),
s_uuid: Uuid::parse_str("00000000-0000-0000-0000-000000000000")
.expect("Invalid compiled s_uuid"),
ts: r,
})
.ok_or(OperationError::InvalidReplCID)

View file

@ -152,7 +152,7 @@ impl SchemaAttribute {
// The get_ava_opt_index handles the optional case for us :)
let index = value
.get_ava_opt_index("index")
.and_then(|vv: Vec<&IndexType>| Ok(vv.into_iter().cloned().collect()))
.map(|vv: Vec<&IndexType>| vv.into_iter().cloned().collect())
.map_err(|_| {
ladmin_error!(audit, "invalid index");
OperationError::InvalidSchemaState("Invalid index".to_string())
@ -641,8 +641,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("class"),
SchemaAttribute {
name: String::from("class"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_CLASS)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_CLASS,
description: String::from("The set of classes defining an object"),
multivalue: true,
unique: false,
@ -655,8 +654,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("uuid"),
SchemaAttribute {
name: String::from("uuid"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_UUID)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_UUID,
description: String::from("The universal unique id of the object"),
multivalue: false,
// Uniqueness is handled by base.rs, not attrunique here due to
@ -671,8 +669,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("last_modified_cid"),
SchemaAttribute {
name: String::from("last_modified_cid"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_LAST_MOD_CID)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_LAST_MOD_CID,
description: String::from("The cid of the last change to this object"),
multivalue: false,
// Uniqueness is handled by base.rs, not attrunique here due to
@ -687,8 +684,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("name"),
SchemaAttribute {
name: String::from("name"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_NAME)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_NAME,
description: String::from("The shortform name of an object"),
multivalue: false,
unique: true,
@ -701,8 +697,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("spn"),
SchemaAttribute {
name: String::from("spn"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_SPN)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_SPN,
description: String::from(
"The service principle name of an object, unique across all domain trusts",
),
@ -717,8 +712,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("attributename"),
SchemaAttribute {
name: String::from("attributename"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_ATTRIBUTENAME)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_ATTRIBUTENAME,
description: String::from("The name of a schema attribute"),
multivalue: false,
unique: true,
@ -731,8 +725,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("classname"),
SchemaAttribute {
name: String::from("classname"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_CLASSNAME)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_CLASSNAME,
description: String::from("The name of a schema class"),
multivalue: false,
unique: true,
@ -745,8 +738,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("description"),
SchemaAttribute {
name: String::from("description"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_DESCRIPTION)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_DESCRIPTION,
description: String::from("A description of an attribute, object or class"),
multivalue: true,
unique: false,
@ -757,7 +749,7 @@ impl<'a> SchemaWriteTransaction<'a> {
);
self.attributes.insert(String::from("multivalue"), SchemaAttribute {
name: String::from("multivalue"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_MULTIVALUE).expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_MULTIVALUE,
description: String::from("If true, this attribute is able to store multiple values rather than just a single value."),
multivalue: false,
unique: false,
@ -767,7 +759,7 @@ impl<'a> SchemaWriteTransaction<'a> {
});
self.attributes.insert(String::from("phantom"), SchemaAttribute {
name: String::from("phantom"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_PHANTOM).expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_PHANTOM,
description: String::from("If true, this attribute must NOT be present in any may/must sets of a class as. This represents generated attributes."),
multivalue: false,
unique: false,
@ -777,7 +769,7 @@ impl<'a> SchemaWriteTransaction<'a> {
});
self.attributes.insert(String::from("unique"), SchemaAttribute {
name: String::from("unique"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_UNIQUE).expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_UNIQUE,
description: String::from("If true, this attribute must store a unique value through out the database."),
multivalue: false,
unique: false,
@ -789,8 +781,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("index"),
SchemaAttribute {
name: String::from("index"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_INDEX)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_INDEX,
description: String::from(
"Describe the indexes to apply to instances of this attribute.",
),
@ -805,8 +796,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("syntax"),
SchemaAttribute {
name: String::from("syntax"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_SYNTAX)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_SYNTAX,
description: String::from(
"Describe the syntax of this attribute. This affects indexing and sorting.",
),
@ -821,8 +811,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("systemmay"),
SchemaAttribute {
name: String::from("systemmay"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_SYSTEMMAY)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_SYSTEMMAY,
description: String::from(
"A list of system provided optional attributes this class can store.",
),
@ -837,8 +826,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("may"),
SchemaAttribute {
name: String::from("may"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_MAY)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_MAY,
description: String::from(
"A user modifiable list of optional attributes this class can store.",
),
@ -853,8 +841,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("systemmust"),
SchemaAttribute {
name: String::from("systemmust"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_SYSTEMMUST)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_SYSTEMMUST,
description: String::from(
"A list of system provided required attributes this class must store.",
),
@ -869,8 +856,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("must"),
SchemaAttribute {
name: String::from("must"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_MUST)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_MUST,
description: String::from(
"A user modifiable list of required attributes this class must store.",
),
@ -887,8 +873,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("acp_enable"),
SchemaAttribute {
name: String::from("acp_enable"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_ACP_ENABLE)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_ACP_ENABLE,
description: String::from("A flag to determine if this ACP is active for application. True is enabled, and enforce. False is checked but not enforced."),
multivalue: false,
unique: false,
@ -902,8 +887,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("acp_receiver"),
SchemaAttribute {
name: String::from("acp_receiver"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_ACP_RECEIVER)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_ACP_RECEIVER,
description: String::from(
"Who the ACP applies to, constraining or allowing operations.",
),
@ -918,8 +902,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("acp_targetscope"),
SchemaAttribute {
name: String::from("acp_targetscope"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_ACP_TARGETSCOPE)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_ACP_TARGETSCOPE,
description: String::from(
"The effective targets of the ACP, IE what will be acted upon.",
),
@ -934,8 +917,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("acp_search_attr"),
SchemaAttribute {
name: String::from("acp_search_attr"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_ACP_SEARCH_ATTR)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_ACP_SEARCH_ATTR,
description: String::from("The attributes that may be viewed or searched by the reciever on targetscope."),
multivalue: true,
unique: false,
@ -948,8 +930,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("acp_create_class"),
SchemaAttribute {
name: String::from("acp_create_class"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_ACP_CREATE_CLASS)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_ACP_CREATE_CLASS,
description: String::from(
"The set of classes that can be created on a new entry.",
),
@ -964,8 +945,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("acp_create_attr"),
SchemaAttribute {
name: String::from("acp_create_attr"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_ACP_CREATE_ATTR)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_ACP_CREATE_ATTR,
description: String::from(
"The set of attribute types that can be created on an entry.",
),
@ -981,8 +961,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("acp_modify_removedattr"),
SchemaAttribute {
name: String::from("acp_modify_removedattr"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_ACP_MODIFY_REMOVEDATTR)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_ACP_MODIFY_REMOVEDATTR,
description: String::from("The set of attribute types that could be removed or purged in a modification."),
multivalue: true,
unique: false,
@ -995,8 +974,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("acp_modify_presentattr"),
SchemaAttribute {
name: String::from("acp_modify_presentattr"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_ACP_MODIFY_PRESENTATTR)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_ACP_MODIFY_PRESENTATTR,
description: String::from("The set of attribute types that could be added or asserted in a modification."),
multivalue: true,
unique: false,
@ -1009,8 +987,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("acp_modify_class"),
SchemaAttribute {
name: String::from("acp_modify_class"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_ACP_MODIFY_CLASS)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_ACP_MODIFY_CLASS,
description: String::from("The set of class values that could be asserted or added to an entry. Only applies to modify::present operations on class."),
multivalue: true,
unique: false,
@ -1024,8 +1001,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("memberof"),
SchemaAttribute {
name: String::from("memberof"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_MEMBEROF)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_MEMBEROF,
description: String::from("reverse group membership of the object"),
multivalue: true,
unique: false,
@ -1038,8 +1014,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("directmemberof"),
SchemaAttribute {
name: String::from("directmemberof"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_DIRECTMEMBEROF)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_DIRECTMEMBEROF,
description: String::from("reverse direct group membership of the object"),
multivalue: true,
unique: false,
@ -1052,8 +1027,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("member"),
SchemaAttribute {
name: String::from("member"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_MEMBER)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_MEMBER,
description: String::from("List of members of the group"),
multivalue: true,
unique: false,
@ -1067,8 +1041,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("version"),
SchemaAttribute {
name: String::from("version"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_VERSION)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_VERSION,
description: String::from(
"The systems internal migration version for provided objects",
),
@ -1084,8 +1057,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("domain"),
SchemaAttribute {
name: String::from("domain"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_DOMAIN)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_DOMAIN,
description: String::from("A DNS Domain name entry."),
multivalue: true,
unique: false,
@ -1098,8 +1070,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("claim"),
SchemaAttribute {
name: String::from("claim"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_CLAIM)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_CLAIM,
description: String::from("The spn of a claim this entry holds"),
multivalue: true,
unique: false,
@ -1112,8 +1083,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("password_import"),
SchemaAttribute {
name: String::from("password_import"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_PASSWORD_IMPORT)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_PASSWORD_IMPORT,
description: String::from("An imported password hash from an external system."),
multivalue: true,
unique: false,
@ -1128,7 +1098,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("dn"),
SchemaAttribute {
name: String::from("dn"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_DN).expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_DN,
description: String::from("An LDAP Compatible DN"),
multivalue: false,
unique: false,
@ -1141,8 +1111,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("entryuuid"),
SchemaAttribute {
name: String::from("entryuuid"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_ENTRYUUID)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_ENTRYUUID,
description: String::from("An LDAP Compatible entryUUID"),
multivalue: false,
unique: false,
@ -1155,8 +1124,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("objectclass"),
SchemaAttribute {
name: String::from("objectclass"),
uuid: Uuid::parse_str(UUID_SCHEMA_ATTR_OBJECTCLASS)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_ATTR_OBJECTCLASS,
description: String::from("An LDAP Compatible objectClass"),
multivalue: true,
unique: false,
@ -1171,8 +1139,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("attributetype"),
SchemaClass {
name: String::from("attributetype"),
uuid: Uuid::parse_str(UUID_SCHEMA_CLASS_ATTRIBUTETYPE)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_CLASS_ATTRIBUTETYPE,
description: String::from("Definition of a schema attribute"),
systemmay: vec![String::from("phantom"), String::from("index")],
may: vec![],
@ -1191,8 +1158,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("classtype"),
SchemaClass {
name: String::from("classtype"),
uuid: Uuid::parse_str(UUID_SCHEMA_CLASS_CLASSTYPE)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_CLASS_CLASSTYPE,
description: String::from("Definition of a schema classtype"),
systemmay: vec![
String::from("systemmay"),
@ -1213,8 +1179,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("object"),
SchemaClass {
name: String::from("object"),
uuid: Uuid::parse_str(UUID_SCHEMA_CLASS_OBJECT)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_CLASS_OBJECT,
description: String::from(
"A system created class that all objects must contain",
),
@ -1232,8 +1197,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("memberof"),
SchemaClass {
name: String::from("memberof"),
uuid: Uuid::parse_str(UUID_SCHEMA_CLASS_MEMBEROF)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_CLASS_MEMBEROF,
description: String::from("Class that is dynamically added to recepients of memberof or directmemberof"),
systemmay: vec![
"memberof".to_string(),
@ -1248,8 +1212,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("extensibleobject"),
SchemaClass {
name: String::from("extensibleobject"),
uuid: Uuid::parse_str(UUID_SCHEMA_CLASS_EXTENSIBLEOBJECT)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_CLASS_EXTENSIBLEOBJECT,
description: String::from(
"A class type that has green hair and turns off all rules ...",
),
@ -1264,7 +1227,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("recycled"),
SchemaClass {
name: String::from("recycled"),
uuid: Uuid::parse_str(UUID_SCHEMA_CLASS_RECYCLED).expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_CLASS_RECYCLED,
description: String::from("An object that has been deleted, but still recoverable via the revive operation. Recycled objects are not modifiable, only revivable."),
systemmay: vec![],
may: vec![],
@ -1276,7 +1239,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("tombstone"),
SchemaClass {
name: String::from("tombstone"),
uuid: Uuid::parse_str(UUID_SCHEMA_CLASS_TOMBSTONE).expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_CLASS_TOMBSTONE,
description: String::from("An object that is purged from the recycle bin. This is a system internal state. Tombstones have no attributes beside UUID."),
systemmay: vec![],
may: vec![],
@ -1292,8 +1255,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("system_info"),
SchemaClass {
name: String::from("system_info"),
uuid: Uuid::parse_str(UUID_SCHEMA_CLASS_SYSTEM_INFO)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_CLASS_SYSTEM_INFO,
description: String::from("System metadata object class"),
systemmay: vec![],
may: vec![],
@ -1311,8 +1273,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("access_control_profile"),
SchemaClass {
name: String::from("access_control_profile"),
uuid: Uuid::parse_str(UUID_SCHEMA_CLASS_ACCESS_CONTROL_PROFILE)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_CLASS_ACCESS_CONTROL_PROFILE,
description: String::from("System Access Control Profile Class"),
systemmay: vec!["acp_enable".to_string(), "description".to_string()],
may: vec![],
@ -1328,8 +1289,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("access_control_search"),
SchemaClass {
name: String::from("access_control_search"),
uuid: Uuid::parse_str(UUID_SCHEMA_CLASS_ACCESS_CONTROL_SEARCH)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_CLASS_ACCESS_CONTROL_SEARCH,
description: String::from("System Access Control Search Class"),
systemmay: vec![],
may: vec![],
@ -1341,8 +1301,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("access_control_delete"),
SchemaClass {
name: String::from("access_control_delete"),
uuid: Uuid::parse_str(UUID_SCHEMA_CLASS_ACCESS_CONTROL_DELETE)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_CLASS_ACCESS_CONTROL_DELETE,
description: String::from("System Access Control DELETE Class"),
systemmay: vec![],
may: vec![],
@ -1354,8 +1313,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("access_control_modify"),
SchemaClass {
name: String::from("access_control_modify"),
uuid: Uuid::parse_str(UUID_SCHEMA_CLASS_ACCESS_CONTROL_MODIFY)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_CLASS_ACCESS_CONTROL_MODIFY,
description: String::from("System Access Control Modify Class"),
systemmay: vec![
"acp_modify_removedattr".to_string(),
@ -1371,8 +1329,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("access_control_create"),
SchemaClass {
name: String::from("access_control_create"),
uuid: Uuid::parse_str(UUID_SCHEMA_CLASS_ACCESS_CONTROL_CREATE)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_CLASS_ACCESS_CONTROL_CREATE,
description: String::from("System Access Control Create Class"),
systemmay: vec![
"acp_create_class".to_string(),
@ -1387,8 +1344,7 @@ impl<'a> SchemaWriteTransaction<'a> {
String::from("system"),
SchemaClass {
name: String::from("system"),
uuid: Uuid::parse_str(UUID_SCHEMA_CLASS_SYSTEM)
.expect("unable to parse const uuid"),
uuid: *UUID_SCHEMA_CLASS_SYSTEM,
description: String::from("A class denoting that a type is system generated and protected. It has special internal behaviour."),
systemmay: vec![],
may: vec![],
@ -1774,12 +1730,12 @@ mod tests {
};
let r1 =
single_value_string.validate_ava("single_value", &btreeset![Value::new_iutf8s("test")]);
single_value_string.validate_ava("single_value", &btreeset![Value::new_iutf8("test")]);
assert_eq!(r1, Ok(()));
let r2 = single_value_string.validate_ava(
"single_value",
&btreeset![Value::new_iutf8s("test1"), Value::new_iutf8s("test2")],
&btreeset![Value::new_iutf8("test1"), Value::new_iutf8("test2")],
);
assert_eq!(
r2,
@ -1824,8 +1780,8 @@ mod tests {
"mv_bool",
&btreeset![
Value::new_bool(true),
Value::new_iutf8s("test1"),
Value::new_iutf8s("test2")
Value::new_iutf8("test1"),
Value::new_iutf8("test2")
],
);
assert_eq!(
@ -2180,7 +2136,7 @@ mod tests {
);
// test syntax of bool
let f_bool = filter_all!(f_eq("multivalue", PartialValue::new_iutf8s("zzzz")));
let f_bool = filter_all!(f_eq("multivalue", PartialValue::new_iutf8("zzzz")));
assert_eq!(
f_bool.validate(&schema),
Err(SchemaError::InvalidAttributeSyntax(
@ -2196,10 +2152,7 @@ mod tests {
// Test the recursive structures validate
let f_or_empty = filter_all!(f_or!([]));
assert_eq!(f_or_empty.validate(&schema), Err(SchemaError::EmptyFilter));
let f_or = filter_all!(f_or!([f_eq(
"multivalue",
PartialValue::new_iutf8s("zzzz")
)]));
let f_or = filter_all!(f_or!([f_eq("multivalue", PartialValue::new_iutf8("zzzz"))]));
assert_eq!(
f_or.validate(&schema),
Err(SchemaError::InvalidAttributeSyntax(
@ -2208,7 +2161,7 @@ mod tests {
);
let f_or_mult = filter_all!(f_and!([
f_eq("class", PartialValue::new_class("attributetype")),
f_eq("multivalue", PartialValue::new_iutf8s("zzzzzzz")),
f_eq("multivalue", PartialValue::new_iutf8("zzzzzzz")),
]));
assert_eq!(
f_or_mult.validate(&schema),

View file

@ -226,12 +226,10 @@ pub trait QueryServerTransaction {
}
fn uuid_to_rdn(&self, audit: &mut AuditScope, uuid: &Uuid) -> Result<String, OperationError> {
// If we have a some, pass it on, else unwrap into a default.
self.get_be_txn()
.uuid2rdn(audit, uuid)
.and_then(|v| match v {
Some(u) => Ok(u),
None => Ok(format!("uuid={}", uuid.to_hyphenated_ref())),
})
.map(|v| v.unwrap_or_else(|| format!("uuid={}", uuid.to_hyphenated_ref())))
}
// From internal, generate an exists event and dispatch
@ -398,8 +396,8 @@ pub trait QueryServerTransaction {
Some(schema_a) => {
match schema_a.syntax {
SyntaxType::UTF8STRING => Ok(Value::new_utf8(value.to_string())),
SyntaxType::UTF8STRING_INSENSITIVE => Ok(Value::new_iutf8s(value)),
SyntaxType::UTF8STRING_INAME => Ok(Value::new_iname_s(value)),
SyntaxType::UTF8STRING_INSENSITIVE => Ok(Value::new_iutf8(value)),
SyntaxType::UTF8STRING_INAME => Ok(Value::new_iname(value)),
SyntaxType::BOOLEAN => Value::new_bools(value)
.ok_or_else(|| OperationError::InvalidAttribute("Invalid boolean syntax".to_string())),
SyntaxType::SYNTAX_ID => Value::new_syntaxs(value)
@ -470,7 +468,7 @@ pub trait QueryServerTransaction {
Some(schema_a) => {
match schema_a.syntax {
SyntaxType::UTF8STRING => Ok(PartialValue::new_utf8(value.to_string())),
SyntaxType::UTF8STRING_INSENSITIVE => Ok(PartialValue::new_iutf8s(value)),
SyntaxType::UTF8STRING_INSENSITIVE => Ok(PartialValue::new_iutf8(value)),
SyntaxType::UTF8STRING_INAME => Ok(PartialValue::new_iname(value)),
SyntaxType::BOOLEAN => PartialValue::new_bools(value).ok_or_else(|| {
OperationError::InvalidAttribute("Invalid boolean syntax".to_string())
@ -736,6 +734,7 @@ impl QueryServer {
let schema_write = self.schema.write();
let be_txn = self.be.write();
#[allow(clippy::expect_used)]
let ts_max = be_txn.get_db_ts_max(&ts).expect("Unable to get db_ts_max");
let cid = Cid::new_lamport(self.s_uuid, self.d_uuid, ts, &ts_max);
@ -1238,10 +1237,10 @@ impl<'a> QueryServerWriteTransaction<'a> {
// Get this entries uuid.
let u: Uuid = *e.get_uuid();
e.get_ava_as_refuuid("directmemberof").and_then(|riter| {
if let Some(riter) = e.get_ava_as_refuuid("directmemberof") {
riter.for_each(|g_uuid| {
dm_mods
.entry(g_uuid.clone())
.entry(*g_uuid)
.and_modify(|mlist| {
let m =
Modify::Present("member".to_string(), Value::new_refer_r(&u));
@ -1253,8 +1252,7 @@ impl<'a> QueryServerWriteTransaction<'a> {
ModifyList::new_list(vec![m])
});
});
Some(())
});
};
});
// Now impersonate the modify
@ -1273,7 +1271,7 @@ impl<'a> QueryServerWriteTransaction<'a> {
// I think the filter/filter_all shouldn't matter here because the only
// valid direct memberships should be still valid/live references.
let f = filter_all!(f_eq("uuid", PartialValue::new_uuid(g)));
self.internal_modify(au, f, mods)
self.internal_modify(au, &f, &mods)
})
.collect();
r
@ -1462,7 +1460,7 @@ impl<'a> QueryServerWriteTransaction<'a> {
pub(crate) fn internal_search_writeable(
&self,
audit: &mut AuditScope,
filter: Filter<FilterInvalid>,
filter: &Filter<FilterInvalid>,
) -> Result<Vec<EntryTuple>, OperationError> {
lperf_segment!(audit, "server::internal_search_writeable", || {
let f_valid = filter
@ -1485,6 +1483,7 @@ impl<'a> QueryServerWriteTransaction<'a> {
/// such as memberof, but at the expense that YOU must guarantee you
/// uphold all other plugin and state rules that are important. You
/// probably want modify instead.
#[allow(clippy::needless_pass_by_value)]
pub(crate) fn internal_batch_modify(
&self,
au: &mut AuditScope,
@ -1668,7 +1667,7 @@ impl<'a> QueryServerWriteTransaction<'a> {
pub fn internal_delete(
&self,
audit: &mut AuditScope,
filter: Filter<FilterInvalid>,
filter: &Filter<FilterInvalid>,
) -> Result<(), OperationError> {
let f_valid = filter
.validate(self.get_schema())
@ -1680,8 +1679,8 @@ impl<'a> QueryServerWriteTransaction<'a> {
pub fn internal_modify(
&self,
audit: &mut AuditScope,
filter: Filter<FilterInvalid>,
modlist: ModifyList<ModifyInvalid>,
filter: &Filter<FilterInvalid>,
modlist: &ModifyList<ModifyInvalid>,
) -> Result<(), OperationError> {
lperf_segment!(audit, "server::internal_modify", || {
let f_valid = filter
@ -1710,9 +1709,9 @@ impl<'a> QueryServerWriteTransaction<'a> {
pub fn impersonate_modify(
&self,
audit: &mut AuditScope,
filter: Filter<FilterInvalid>,
filter_intent: Filter<FilterInvalid>,
modlist: ModifyList<ModifyInvalid>,
filter: &Filter<FilterInvalid>,
filter_intent: &Filter<FilterInvalid>,
modlist: &ModifyList<ModifyInvalid>,
event: &Event,
) -> Result<(), OperationError> {
let f_valid = filter.validate(self.get_schema()).map_err(|e| {
@ -1805,7 +1804,7 @@ impl<'a> QueryServerWriteTransaction<'a> {
Ok(modlist) => {
// Apply to &results[0]
ltrace!(audit, "Generated modlist -> {:?}", modlist);
self.internal_modify(audit, filt, modlist)
self.internal_modify(audit, &filt, &modlist)
}
Err(e) => Err(OperationError::SchemaViolation(e)),
}
@ -2279,11 +2278,10 @@ impl<'a> QueryServerWriteTransaction<'a> {
audit: &mut AuditScope,
new_domain_name: &str,
) -> Result<(), OperationError> {
let modl =
ModifyList::new_purge_and_set("domain_name", Value::new_iname_s(new_domain_name));
let modl = ModifyList::new_purge_and_set("domain_name", Value::new_iname(new_domain_name));
let udi = PartialValue::new_uuidr(&UUID_DOMAIN_INFO);
let filt = filter_all!(f_eq("uuid", udi));
self.internal_modify(audit, filt, modl)
self.internal_modify(audit, &filt, &modl)
}
pub fn reindex(&self, audit: &mut AuditScope) -> Result<(), OperationError> {
@ -2502,8 +2500,8 @@ mod tests {
// this.
let r_inv_1 = server_txn.internal_modify(
audit,
filter!(f_eq("tnanuanou", PartialValue::new_iname("Flarbalgarble"))),
ModifyList::new_list(vec![Modify::Present(
&filter!(f_eq("tnanuanou", PartialValue::new_iname("Flarbalgarble"))),
&ModifyList::new_list(vec![Modify::Present(
"description".to_string(),
Value::from("anusaosu"),
)]),
@ -2605,7 +2603,7 @@ mod tests {
filter!(f_eq("name", PartialValue::new_iname("testperson1"))),
ModifyList::new_list(vec![Modify::Present(
"name".to_string(),
Value::new_iname_s("testpersonx"),
Value::new_iname("testpersonx"),
)]),
)
};
@ -2617,7 +2615,7 @@ mod tests {
filter!(f_eq("name", PartialValue::new_iname("testperson1"))),
ModifyList::new_list(vec![
Modify::Present("class".to_string(), Value::new_class("system_info")),
// Modify::Present("domain".to_string(), Value::new_iutf8s("domain.name")),
// Modify::Present("domain".to_string(), Value::new_iutf8("domain.name")),
Modify::Present("version".to_string(), Value::new_uint32(1)),
]),
)
@ -2630,7 +2628,7 @@ mod tests {
filter!(f_eq("name", PartialValue::new_iname("testperson1"))),
ModifyList::new_list(vec![
Modify::Purged("name".to_string()),
Modify::Present("name".to_string(), Value::new_iname_s("testpersonx")),
Modify::Present("name".to_string(), Value::new_iname("testpersonx")),
]),
)
};
@ -3458,7 +3456,7 @@ mod tests {
let de_attr = unsafe {
DeleteEvent::new_internal_invalid(filter!(f_eq(
"attributename",
PartialValue::new_iutf8s("testattr")
PartialValue::new_iutf8("testattr")
)))
};
assert!(server_txn.delete(audit, &de_attr).is_ok());
@ -3510,7 +3508,7 @@ mod tests {
assert!(cr.is_ok());
// Build the credential.
let cred = Credential::new_password_only("test_password");
let cred = Credential::new_password_only("test_password").unwrap();
let v_cred = Value::new_credential("primary", cred);
assert!(v_cred.validate());
@ -3553,7 +3551,7 @@ mod tests {
}"#,
);
e1.add_ava("uuid", Value::new_uuids(uuid).unwrap());
e1.add_ava("name", Value::new_iname_s(name));
e1.add_ava("name", Value::new_iname(name));
e1.add_ava("displayname", Value::new_utf8s(name));
e1
}
@ -3567,7 +3565,7 @@ mod tests {
}
}"#,
);
e1.add_ava("name", Value::new_iname_s(name));
e1.add_ava("name", Value::new_iname(name));
e1.add_ava("uuid", Value::new_uuids(uuid).unwrap());
members
.iter()
@ -3806,8 +3804,8 @@ mod tests {
let me_syn = unsafe {
ModifyEvent::new_internal_invalid(
filter!(f_or!([
f_eq("attributename", PartialValue::new_iutf8s("name")),
f_eq("attributename", PartialValue::new_iutf8s("domain_name")),
f_eq("attributename", PartialValue::new_iutf8("name")),
f_eq("attributename", PartialValue::new_iutf8("domain_name")),
])),
ModifyList::new_purge_and_set(
"syntax",
@ -3826,11 +3824,8 @@ mod tests {
ModifyList::new_list(vec![
Modify::Purged("name".to_string()),
Modify::Purged("domain_name".to_string()),
Modify::Present("name".to_string(), Value::new_iutf8s("domain_local")),
Modify::Present(
"domain_name".to_string(),
Value::new_iutf8s("example.com"),
),
Modify::Present("name".to_string(), Value::new_iutf8("domain_local")),
Modify::Present("domain_name".to_string(), Value::new_iutf8("example.com")),
]),
)
};
@ -3845,8 +3840,8 @@ mod tests {
let me_syn = unsafe {
ModifyEvent::new_internal_invalid(
filter!(f_or!([
f_eq("attributename", PartialValue::new_iutf8s("name")),
f_eq("attributename", PartialValue::new_iutf8s("domain_name")),
f_eq("attributename", PartialValue::new_iutf8("name")),
f_eq("attributename", PartialValue::new_iutf8("domain_name")),
])),
ModifyList::new_purge_and_set(
"syntax",

View file

@ -22,7 +22,10 @@ fn uuid_from_u64_u32(a: u64, b: u32, sid: SID) -> Uuid {
v.extend_from_slice(&b.to_be_bytes());
v.extend_from_slice(&sid);
Builder::from_slice(v.as_slice()).unwrap().build()
#[allow(clippy::expect_used)]
Builder::from_slice(v.as_slice())
.expect("invalid slice for uuid builder")
.build()
}
pub fn uuid_from_duration(d: Duration, sid: SID) -> Uuid {
@ -46,9 +49,10 @@ pub fn readable_password_from_random() -> String {
}
pub fn duration_from_epoch_now() -> Duration {
#[allow(clippy::expect_used)]
SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.expect("invalid duration from epoch now")
}
/*

View file

@ -15,17 +15,23 @@ use std::cmp::Ordering;
use regex::Regex;
lazy_static! {
static ref SPN_RE: Regex =
Regex::new("(?P<name>[^@]+)@(?P<realm>[^@]+)").expect("Invalid SPN regex found");
static ref INAME_RE: Regex =
Regex::new("^(_.*|.*(\\s|@|,|=).*|\\d+|root|nobody|nogroup|wheel|sshd|shadow|systemd.*)$").expect("Invalid Iname regex found");
static ref SPN_RE: Regex = {
#[allow(clippy::expect_used)]
Regex::new("(?P<name>[^@]+)@(?P<realm>[^@]+)").expect("Invalid SPN regex found")
};
static ref INAME_RE: Regex = {
#[allow(clippy::expect_used)]
Regex::new("^(_.*|.*(\\s|@|,|=).*|\\d+|root|nobody|nogroup|wheel|sshd|shadow|systemd.*)$").expect("Invalid Iname regex found")
// ^ ^ ^
// | | \- must not be only integers
// | \- must not contain whitespace, @, ',', =
// \- must not start with _
// Them's be the rules.
static ref NSUNIQUEID_RE: Regex =
Regex::new("^[0-9a-fA-F]{8}-[0-9a-fA-F]{8}-[0-9a-fA-F]{8}-[0-9a-fA-F]{8}$").expect("Invalid Nsunique regex found");
};
static ref NSUNIQUEID_RE: Regex = {
#[allow(clippy::expect_used)]
Regex::new("^[0-9a-fA-F]{8}-[0-9a-fA-F]{8}-[0-9a-fA-F]{8}-[0-9a-fA-F]{8}$").expect("Invalid Nsunique regex found")
};
}
#[allow(non_camel_case_types)]
@ -279,7 +285,7 @@ impl PartialValue {
}
}
pub fn new_iutf8s(s: &str) -> Self {
pub fn new_iutf8(s: &str) -> Self {
PartialValue::Iutf8(s.to_lowercase())
}
@ -289,7 +295,7 @@ impl PartialValue {
#[inline]
pub fn new_class(s: &str) -> Self {
PartialValue::new_iutf8s(s)
PartialValue::new_iutf8(s)
}
/*
@ -532,10 +538,6 @@ impl PartialValue {
}
}
pub fn to_str_unwrap(&self) -> &str {
self.to_str().expect("An invalid value was returned!!!")
}
pub fn contains(&self, s: &PartialValue) -> bool {
match (self, s) {
(PartialValue::Utf8(s1), PartialValue::Utf8(s2)) => s1.contains(s2),
@ -563,7 +565,9 @@ impl PartialValue {
PartialValue::Bool(b) => b.to_string(),
PartialValue::Syntax(syn) => syn.to_string(),
PartialValue::Index(it) => it.to_string(),
PartialValue::JsonFilt(s) => {
PartialValue::JsonFilt(s) =>
{
#[allow(clippy::expect_used)]
serde_json::to_string(s).expect("A json filter value was corrupted during run-time")
}
PartialValue::Cred(tag) => tag.to_string(),
@ -715,16 +719,9 @@ impl Value {
}
}
pub fn new_iutf8(s: String) -> Self {
pub fn new_iutf8(s: &str) -> Self {
Value {
pv: PartialValue::new_iutf8s(s.as_str()),
data: None,
}
}
pub fn new_iutf8s(s: &str) -> Self {
Value {
pv: PartialValue::new_iutf8s(s),
pv: PartialValue::new_iutf8(s),
data: None,
}
}
@ -736,14 +733,7 @@ impl Value {
}
}
pub fn new_iname(s: String) -> Self {
Value {
pv: PartialValue::new_iname(s.as_str()),
data: None,
}
}
pub fn new_iname_s(s: &str) -> Self {
pub fn new_iname(s: &str) -> Self {
Value {
pv: PartialValue::new_iname(s),
data: None,
@ -788,14 +778,14 @@ impl Value {
pub fn new_class(s: &str) -> Self {
Value {
pv: PartialValue::new_iutf8s(s),
pv: PartialValue::new_iutf8(s),
data: None,
}
}
pub fn new_attr(s: &str) -> Self {
Value {
pv: PartialValue::new_iutf8s(s),
pv: PartialValue::new_iutf8(s),
data: None,
}
}
@ -1146,6 +1136,8 @@ impl Value {
}
}
#[allow(clippy::unreachable)]
#[allow(clippy::expect_used)]
pub(crate) fn to_db_valuev1(&self) -> DbValueV1 {
// This has to clone due to how the backend works.
match &self.pv {
@ -1166,9 +1158,9 @@ impl Value {
let c = match &self.data {
Some(v) => match v.as_ref() {
DataValue::Cred(c) => c,
_ => panic!(),
_ => unreachable!(),
},
None => panic!(),
None => unreachable!(),
};
// Save the tag AND the dataValue here!
@ -1181,9 +1173,9 @@ impl Value {
let ru = match &self.data {
Some(v) => match v.as_ref() {
DataValue::RadiusCred(rc) => rc.clone(),
_ => panic!(),
_ => unreachable!(),
},
None => panic!(),
None => unreachable!(),
};
DbValueV1::RU(ru)
}
@ -1191,9 +1183,9 @@ impl Value {
let sk = match &self.data {
Some(v) => match v.as_ref() {
DataValue::SshKey(sc) => sc.clone(),
_ => panic!(),
_ => unreachable!(),
},
None => panic!(),
None => unreachable!(),
};
DbValueV1::SK(DbValueTaggedStringV1 {
t: t.clone(),
@ -1220,10 +1212,6 @@ impl Value {
}
}
pub fn to_str_unwrap(&self) -> &str {
self.to_str().expect("An invalid value was returned!!!")
}
pub fn as_string(&self) -> Option<&String> {
match &self.pv {
PartialValue::Utf8(s) => Some(s),
@ -1306,7 +1294,9 @@ impl Value {
// In resolve value, we bypass this, but we keep it here for complete
// impl sake.
PartialValue::Refer(u) => u.to_hyphenated_ref().to_string(),
PartialValue::JsonFilt(s) => {
PartialValue::JsonFilt(s) =>
{
#[allow(clippy::expect_used)]
serde_json::to_string(s).expect("A json filter value was corrupted during run-time")
}
PartialValue::Cred(tag) => {
@ -1383,6 +1373,7 @@ impl Value {
}
pub fn generate_idx_eq_keys(&self) -> Vec<String> {
#[allow(clippy::expect_used)]
match &self.pv {
PartialValue::Utf8(s)
| PartialValue::Iutf8(s)
@ -1551,18 +1542,18 @@ mod tests {
* - can not have spaces (confuses too many systems :()
* - can not have = or , (confuses ldap)
*/
let inv1 = Value::new_iname_s("1234");
let inv2 = Value::new_iname_s("bc23f637-4439-4c07-b95d-eaed0d9e4b8b");
let inv3 = Value::new_iname_s("hello@test.com");
let inv4 = Value::new_iname_s("_bad");
let inv5 = Value::new_iname_s("no spaces I'm sorry :(");
let inv6 = Value::new_iname_s("bad=equals");
let inv7 = Value::new_iname_s("bad,comma");
let inv1 = Value::new_iname("1234");
let inv2 = Value::new_iname("bc23f637-4439-4c07-b95d-eaed0d9e4b8b");
let inv3 = Value::new_iname("hello@test.com");
let inv4 = Value::new_iname("_bad");
let inv5 = Value::new_iname("no spaces I'm sorry :(");
let inv6 = Value::new_iname("bad=equals");
let inv7 = Value::new_iname("bad,comma");
let val1 = Value::new_iname_s("William");
let val2 = Value::new_iname_s("this_is_okay");
let val3 = Value::new_iname_s("123_456");
let val4 = Value::new_iname_s("🍿");
let val1 = Value::new_iname("William");
let val2 = Value::new_iname("this_is_okay");
let val3 = Value::new_iname("123_456");
let val4 = Value::new_iname("🍿");
assert!(!inv1.validate());
assert!(!inv2.validate());

View file

@ -1,4 +1,12 @@
#![deny(warnings)]
#![warn(unused_extern_crates)]
#![deny(clippy::unwrap_used)]
#![deny(clippy::expect_used)]
#![deny(clippy::panic)]
#![deny(clippy::unreachable)]
#![deny(clippy::await_holding_lock)]
#![deny(clippy::needless_pass_by_value)]
#![deny(clippy::trivially_copy_pass_by_ref)]
use users::{get_current_gid, get_current_uid, get_effective_gid, get_effective_uid};
@ -136,7 +144,7 @@ fn read_file_metadata(path: &PathBuf) -> Metadata {
Err(e) => {
eprintln!(
"Unable to read metadata for {} - {:?}",
path.to_str().unwrap(),
path.to_str().unwrap_or("invalid file path"),
e
);
std::process::exit(1);
@ -171,18 +179,18 @@ async fn main() {
let cfg_meta = read_file_metadata(&(opt.commonopt().config_path));
if !cfg_meta.permissions().readonly() {
eprintln!("WARNING: permissions on {} may not be secure. Should be readonly to running uid. This could be a security risk ...",
opt.commonopt().config_path.to_str().unwrap());
opt.commonopt().config_path.to_str().unwrap_or("invalid file path"));
}
if cfg_meta.mode() & 0o007 != 0 {
eprintln!("WARNING: {} has 'everyone' permission bits in the mode. This could be a security risk ...",
opt.commonopt().config_path.to_str().unwrap()
opt.commonopt().config_path.to_str().unwrap_or("invalid file path")
);
}
if cfg_meta.uid() == cuid || cfg_meta.uid() == ceuid {
eprintln!("WARNING: {} owned by the current uid, which may allow file permission changes. This could be a security risk ...",
opt.commonopt().config_path.to_str().unwrap()
opt.commonopt().config_path.to_str().unwrap_or("invalid file path")
);
}
@ -241,7 +249,7 @@ async fn main() {
if !db_parent_path.exists() {
eprintln!(
"DB folder {} may not exist, server startup may FAIL!",
db_parent_path.to_str().unwrap()
db_parent_path.to_str().unwrap_or("invalid file path")
);
}
@ -250,16 +258,16 @@ async fn main() {
if !i_meta.is_dir() {
eprintln!(
"ERROR: Refusing to run - DB folder {} may not be a directory",
db_par_path_buf.to_str().unwrap()
db_par_path_buf.to_str().unwrap_or("invalid file path")
);
std::process::exit(1);
}
if i_meta.permissions().readonly() {
eprintln!("WARNING: DB folder permissions on {} indicate it may not be RW. This could cause the server start up to fail!", db_par_path_buf.to_str().unwrap());
eprintln!("WARNING: DB folder permissions on {} indicate it may not be RW. This could cause the server start up to fail!", db_par_path_buf.to_str().unwrap_or("invalid file path"));
}
if i_meta.mode() & 0o007 != 0 {
eprintln!("WARNING: DB folder {} has 'everyone' permission bits in the mode. This could be a security risk ...", db_par_path_buf.to_str().unwrap());
eprintln!("WARNING: DB folder {} has 'everyone' permission bits in the mode. This could be a security risk ...", db_par_path_buf.to_str().unwrap_or("invalid file path"));
}
}
@ -287,11 +295,16 @@ async fn main() {
let sctx = create_server_core(config).await;
match sctx {
Ok(sctx) => {
tokio::signal::ctrl_c().await.unwrap();
println!("Ctrl-C received, shutting down");
sctx.stop()
}
Ok(sctx) => match tokio::signal::ctrl_c().await {
Ok(_) => {
eprintln!("Ctrl-C received, shutting down");
sctx.stop()
}
Err(_) => {
eprintln!("Invalid signal received, shutting down as a precaution ...");
sctx.stop()
}
},
Err(_) => {
eprintln!("Failed to start server core!");
return;
@ -310,7 +323,7 @@ async fn main() {
std::process::exit(1);
}
};
backup_server_core(config, p);
backup_server_core(&config, p);
}
Opt::Restore(ropt) => {
eprintln!("Running in restore mode ...");
@ -324,21 +337,27 @@ async fn main() {
std::process::exit(1);
}
};
restore_server_core(config, p);
restore_server_core(&config, p);
}
Opt::Verify(_vopt) => {
eprintln!("Running in db verification mode ...");
// config.update_db_path(&vopt.db_path);
verify_server_core(config);
verify_server_core(&config);
}
Opt::RecoverAccount(raopt) => {
eprintln!("Running account recovery ...");
let password = rpassword::prompt_password_stderr("new password: ").unwrap();
let password = match rpassword::prompt_password_stderr("new password: ") {
Ok(pw) => pw,
Err(e) => {
eprintln!("Failed to get password from prompt {:?}", e);
std::process::exit(1);
}
};
// config.update_db_path(&raopt.commonopts.db_path);
recover_account_core(config, raopt.name, password);
recover_account_core(&config, &raopt.name, &password);
}
/*
Opt::ResetServerId(vopt) => {
@ -352,13 +371,13 @@ async fn main() {
eprintln!("Running in reindex mode ...");
// config.update_db_path(&copt.db_path);
reindex_server_core(config);
reindex_server_core(&config);
}
Opt::DomainChange(dopt) => {
eprintln!("Running in domain name change mode ... this may take a long time ...");
// config.update_db_path(&dopt.commonopts.db_path);
domain_rename_core(config, dopt.new_domain_name);
domain_rename_core(&config, &dopt.new_domain_name);
}
}
}