20200216 fix gidnumber validation (#186)

* Fix an issue with gid number validation
This commit is contained in:
Firstyear 2020-02-17 08:09:11 +10:30 committed by GitHub
parent d82b942ddc
commit f8adfc3840
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -13,7 +13,13 @@ use crate::value::{PartialValue, Value};
use kanidm_proto::v1::OperationError; use kanidm_proto::v1::OperationError;
static GIDNUMBER_MIN: u32 = 2000; /// Systemd dynamic units allocate between 6118465519, most distros allocate
/// system uids from 0 - 1000, and many others give user ids between 1000 to
/// 2000. This whole numberspace is cursed, lets assume it's not ours. :(
static GID_SYSTEM_NUMBER_MIN: u32 = 65536;
/// This is the normal system range, we MUST NOT allow it to be allocated.
static GID_SAFETY_NUMBER_MIN: u32 = 1000;
lazy_static! { lazy_static! {
static ref CLASS_POSIXGROUP: PartialValue = PartialValue::new_iutf8s("posixgroup"); static ref CLASS_POSIXGROUP: PartialValue = PartialValue::new_iutf8s("posixgroup");
@ -32,11 +38,11 @@ fn apply_gidnumber<T: Copy>(
{ {
let u_ref = try_audit!(au, e.get_uuid().ok_or(OperationError::InvalidEntryState)); let u_ref = try_audit!(au, e.get_uuid().ok_or(OperationError::InvalidEntryState));
let gid = uuid_to_gid_u32(u_ref); let gid = uuid_to_gid_u32(u_ref);
// assert the value is greater than 2000 // assert the value is greater than the system range.
if gid < GIDNUMBER_MIN { if gid < GID_SYSTEM_NUMBER_MIN {
return Err(OperationError::InvalidAttribute(format!( return Err(OperationError::InvalidAttribute(format!(
"gidnumber {} may overlap with system range {}", "gidnumber {} may overlap with system range {}",
gid, GIDNUMBER_MIN gid, GID_SYSTEM_NUMBER_MIN
))); )));
} }
@ -44,6 +50,16 @@ fn apply_gidnumber<T: Copy>(
audit_log!(au, "Generated {} for {:?}", gid, u_ref); audit_log!(au, "Generated {} for {:?}", gid, u_ref);
e.set_avas("gidnumber", vec![gid_v]); e.set_avas("gidnumber", vec![gid_v]);
Ok(()) Ok(())
} else if let Some(gid) = e.get_ava_single_uint32("gidnumber") {
// If they provided us with a gid number, ensure it's in a safe range.
if gid <= GID_SAFETY_NUMBER_MIN {
Err(OperationError::InvalidAttribute(format!(
"gidnumber {} overlaps into system secure range {}",
gid, GID_SAFETY_NUMBER_MIN
)))
} else {
Ok(())
}
} else { } else {
Ok(()) Ok(())
} }
@ -87,6 +103,7 @@ mod tests {
use crate::entry::{Entry, EntryInvalid, EntryNew}; use crate::entry::{Entry, EntryInvalid, EntryNew};
use crate::server::{QueryServerTransaction, QueryServerWriteTransaction}; use crate::server::{QueryServerTransaction, QueryServerWriteTransaction};
use crate::value::{PartialValue, Value}; use crate::value::{PartialValue, Value};
use kanidm_proto::v1::OperationError;
use uuid::Uuid; use uuid::Uuid;
fn check_gid( fn check_gid(
@ -146,7 +163,7 @@ mod tests {
"class": ["account", "posixaccount"], "class": ["account", "posixaccount"],
"name": ["testperson"], "name": ["testperson"],
"uuid": ["83a0927f-3de1-45ec-bea0-2f7b997ef244"], "uuid": ["83a0927f-3de1-45ec-bea0-2f7b997ef244"],
"gidnumber": ["1000"], "gidnumber": ["10001"],
"description": ["testperson"], "description": ["testperson"],
"displayname": ["testperson"] "displayname": ["testperson"]
} }
@ -165,7 +182,7 @@ mod tests {
au, au,
qs_write, qs_write,
"83a0927f-3de1-45ec-bea0-2f7b997ef244", "83a0927f-3de1-45ec-bea0-2f7b997ef244",
1000 10001
) )
); );
} }
@ -237,9 +254,9 @@ mod tests {
); );
} }
// Test NOT altered if given on mod // Test NOT regenerated if given on mod
#[test] #[test]
fn test_gidnumber_modify_noaction() { fn test_gidnumber_modify_noregen() {
let e: Entry<EntryInvalid, EntryNew> = Entry::unsafe_from_entry_str( let e: Entry<EntryInvalid, EntryNew> = Entry::unsafe_from_entry_str(
r#"{ r#"{
"valid": null, "valid": null,
@ -274,4 +291,88 @@ mod tests {
) )
); );
} }
#[test]
fn test_gidnumber_create_system_reject() {
let e: Entry<EntryInvalid, EntryNew> = Entry::unsafe_from_entry_str(
r#"{
"attrs": {
"class": ["account", "posixaccount"],
"name": ["testperson"],
"uuid": ["83a0927f-3de1-45ec-bea0-2f7b00000244"],
"description": ["testperson"],
"displayname": ["testperson"]
}
}"#,
);
let create = vec![e.clone()];
let preload = Vec::new();
run_create_test!(
Err(OperationError::InvalidAttribute(
"gidnumber 580 may overlap with system range 65536".to_string()
)),
preload,
create,
None,
|_, _| {}
);
}
#[test]
fn test_gidnumber_create_secure_reject() {
let e: Entry<EntryInvalid, EntryNew> = Entry::unsafe_from_entry_str(
r#"{
"attrs": {
"class": ["account", "posixaccount"],
"name": ["testperson"],
"gidnumber": ["500"],
"description": ["testperson"],
"displayname": ["testperson"]
}
}"#,
);
let create = vec![e.clone()];
let preload = Vec::new();
run_create_test!(
Err(OperationError::InvalidAttribute(
"gidnumber 500 overlaps into system secure range 1000".to_string()
)),
preload,
create,
None,
|_, _| {}
);
}
#[test]
fn test_gidnumber_create_secure_root_reject() {
let e: Entry<EntryInvalid, EntryNew> = Entry::unsafe_from_entry_str(
r#"{
"attrs": {
"class": ["account", "posixaccount"],
"name": ["testperson"],
"gidnumber": ["0"],
"description": ["testperson"],
"displayname": ["testperson"]
}
}"#,
);
let create = vec![e.clone()];
let preload = Vec::new();
run_create_test!(
Err(OperationError::InvalidAttribute(
"gidnumber 0 overlaps into system secure range 1000".to_string()
)),
preload,
create,
None,
|_, _| {}
);
}
} }