mirror of
https://github.com/lldap/lldap.git
synced 2026-07-25 17:58:44 +00:00
server: prevent attributes with conflicting types across users/groups (#1426)
Before creating a user attribute, check if a group attribute with the same name exists with a different type (and vice versa). Return an error if the types conflict, as LDAP requires each attribute name to have a single associated type (RFC 4512). Partial fix for #1202 Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
This commit is contained in:
@@ -29,28 +29,80 @@ impl ReadSchemaBackendHandler for SqlBackendHandler {
|
|||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl SchemaBackendHandler for SqlBackendHandler {
|
impl SchemaBackendHandler for SqlBackendHandler {
|
||||||
async fn add_user_attribute(&self, request: CreateAttributeRequest) -> Result<()> {
|
async fn add_user_attribute(&self, request: CreateAttributeRequest) -> Result<()> {
|
||||||
let new_attribute = model::user_attribute_schema::ActiveModel {
|
self.sql_pool
|
||||||
attribute_name: Set(request.name),
|
.transaction::<_, (), DomainError>(|transaction| {
|
||||||
attribute_type: Set(request.attribute_type),
|
Box::pin(async move {
|
||||||
is_list: Set(request.is_list),
|
// Check for conflicting group attribute with the same name but different type.
|
||||||
is_user_visible: Set(request.is_visible),
|
// Done inside the transaction to prevent TOCTOU races.
|
||||||
is_user_editable: Set(request.is_editable),
|
let schema =
|
||||||
is_hardcoded: Set(false),
|
Self::get_schema_with_transaction(transaction).await?;
|
||||||
};
|
if let Some(group_attr) = schema
|
||||||
new_attribute.insert(&self.sql_pool).await?;
|
.group_attributes
|
||||||
|
.attributes
|
||||||
|
.iter()
|
||||||
|
.find(|a| a.name == request.name)
|
||||||
|
{
|
||||||
|
if group_attr.attribute_type != request.attribute_type {
|
||||||
|
return Err(DomainError::InternalError(format!(
|
||||||
|
"A group attribute '{}' already exists with type {:?}, \
|
||||||
|
cannot create a user attribute with type {:?}. \
|
||||||
|
LDAP requires each attribute name to have a single type.",
|
||||||
|
request.name, group_attr.attribute_type, request.attribute_type
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let new_attribute = model::user_attribute_schema::ActiveModel {
|
||||||
|
attribute_name: Set(request.name),
|
||||||
|
attribute_type: Set(request.attribute_type),
|
||||||
|
is_list: Set(request.is_list),
|
||||||
|
is_user_visible: Set(request.is_visible),
|
||||||
|
is_user_editable: Set(request.is_editable),
|
||||||
|
is_hardcoded: Set(false),
|
||||||
|
};
|
||||||
|
new_attribute.insert(transaction).await?;
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn add_group_attribute(&self, request: CreateAttributeRequest) -> Result<()> {
|
async fn add_group_attribute(&self, request: CreateAttributeRequest) -> Result<()> {
|
||||||
let new_attribute = model::group_attribute_schema::ActiveModel {
|
self.sql_pool
|
||||||
attribute_name: Set(request.name),
|
.transaction::<_, (), DomainError>(|transaction| {
|
||||||
attribute_type: Set(request.attribute_type),
|
Box::pin(async move {
|
||||||
is_list: Set(request.is_list),
|
// Check for conflicting user attribute with the same name but different type.
|
||||||
is_group_visible: Set(request.is_visible),
|
// Done inside the transaction to prevent TOCTOU races.
|
||||||
is_group_editable: Set(request.is_editable),
|
let schema =
|
||||||
is_hardcoded: Set(false),
|
Self::get_schema_with_transaction(transaction).await?;
|
||||||
};
|
if let Some(user_attr) = schema
|
||||||
new_attribute.insert(&self.sql_pool).await?;
|
.user_attributes
|
||||||
|
.attributes
|
||||||
|
.iter()
|
||||||
|
.find(|a| a.name == request.name)
|
||||||
|
{
|
||||||
|
if user_attr.attribute_type != request.attribute_type {
|
||||||
|
return Err(DomainError::InternalError(format!(
|
||||||
|
"A user attribute '{}' already exists with type {:?}, \
|
||||||
|
cannot create a group attribute with type {:?}. \
|
||||||
|
LDAP requires each attribute name to have a single type.",
|
||||||
|
request.name, user_attr.attribute_type, request.attribute_type
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let new_attribute = model::group_attribute_schema::ActiveModel {
|
||||||
|
attribute_name: Set(request.name),
|
||||||
|
attribute_type: Set(request.attribute_type),
|
||||||
|
is_list: Set(request.is_list),
|
||||||
|
is_group_visible: Set(request.is_visible),
|
||||||
|
is_group_editable: Set(request.is_editable),
|
||||||
|
is_hardcoded: Set(false),
|
||||||
|
};
|
||||||
|
new_attribute.insert(transaction).await?;
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user