Ensure objects have an objectclass property

This commit is contained in:
Alex 2020-02-14 21:23:01 +01:00
parent 81328aa321
commit fd6a555216
3 changed files with 15 additions and 3 deletions

View file

@ -112,7 +112,7 @@ A rule is a string composed of five fields separated by `:`. The fields are the
1. The name of the user that must be bound (logged in) for the rule to apply. May contain wildcards such as `*` (see the format used by Go's `path.Match`). The special name `ANONYMOUS` applies to clients before they bind to an LDAP entity. 1. The name of the user that must be bound (logged in) for the rule to apply. May contain wildcards such as `*` (see the format used by Go's `path.Match`). The special name `ANONYMOUS` applies to clients before they bind to an LDAP entity.
2. The groups that the user must be a part of, separated by spaces. Wildcards may also be used. If several groups (or wildcard group patterns) are specified, for each pattern the user must be part of a group that matches it. 2. The groups that the user must be a part of, separated by spaces. Wildcards may also be used. If several groups (or wildcard group patterns) are specified, for each pattern the user must be part of a group that matches it.
3. The action, a subset of `bind`, `read`, `add`, `delete`, `modify` separated by spaces. 3. The action, a subset of `bind`, `read`, `add`, `delete`, `modify`, `modifyAdd` separated by spaces. `modifyAdd` is a special value that only authorizes modifications that add new values to a given attribute. This can be used to allow users to add other users to a group but not remove users from the group.
4. The target entity of the action as a pattern that may contain wildcards. The special word `SELF` is replaced by the entity name of the bound user before trying to match. 4. The target entity of the action as a pattern that may contain wildcards. The special word `SELF` is replaced by the entity name of the bound user before trying to match.
5. The allowed attributes for a read, add or modify operation. This is specified as a list of patterns to include and exclude attributes, separated by spaces. A pattern that starts by `!` is an exclude pattern, otherwise it is an include pattern. To read/write an attribute, it has to match at least one include pattern and not match any exclude pattern. Delete operations do not check for any attribute, thus as soon as `delete` is included in the allowed actions, the right to delete entities is granted. 5. The allowed attributes for a read, add or modify operation. This is specified as a list of patterns to include and exclude attributes, separated by spaces. A pattern that starts by `!` is an exclude pattern, otherwise it is an include pattern. To read/write an attribute, it has to match at least one include pattern and not match any exclude pattern. Delete operations do not check for any attribute, thus as soon as `delete` is included in the allowed actions, the right to delete entities is granted.

View file

@ -27,6 +27,7 @@ const ATTR_CREATORSNAME = "creatorsname"
const ATTR_CREATETIMESTAMP = "createtimestamp" const ATTR_CREATETIMESTAMP = "createtimestamp"
const ATTR_MODIFIERSNAME = "modifiersname" const ATTR_MODIFIERSNAME = "modifiersname"
const ATTR_MODIFYTIMESTAMP = "modifytimestamp" const ATTR_MODIFYTIMESTAMP = "modifytimestamp"
const ATTR_OBJECTCLASS = "objectclass"
type ConfigFile struct { type ConfigFile struct {
Suffix string `json:"suffix"` Suffix string `json:"suffix"`

View file

@ -103,6 +103,9 @@ func (server *Server) handleAddInternal(state *State, r *message.AddRequest) (in
} }
} }
if _, ok := entry[ATTR_OBJECTCLASS]; !ok {
entry[ATTR_OBJECTCLASS] = []string{"top"}
}
entry[ATTR_CREATORSNAME] = []string{state.login.user} entry[ATTR_CREATORSNAME] = []string{state.login.user}
entry[ATTR_CREATETIMESTAMP] = []string{genTimestamp()} entry[ATTR_CREATETIMESTAMP] = []string{genTimestamp()}
entry[ATTR_ENTRYUUID] = []string{genUuid()} entry[ATTR_ENTRYUUID] = []string{genUuid()}
@ -263,7 +266,8 @@ func (server *Server) handleModifyInternal(state *State, r *message.ModifyReques
} }
// First permission check with no particular attributes // First permission check with no particular attributes
if !server.config.Acl.Check(&state.login, "modify", dn, []string{}) { if !server.config.Acl.Check(&state.login, "modify", dn, []string{}) &&
!server.config.Acl.Check(&state.login, "modifyAdd", dn, []string{}) {
return ldap.LDAPResultInsufficientAccessRights, nil return ldap.LDAPResultInsufficientAccessRights, nil
} }
@ -316,7 +320,9 @@ func (server *Server) handleModifyInternal(state *State, r *message.ModifyReques
} }
// Check for permission to modify this attribute // Check for permission to modify this attribute
if !server.config.Acl.Check(&state.login, "modify", dn, []string{attr}) { if !(server.config.Acl.Check(&state.login, "modify", dn, []string{attr}) ||
(change.Operation() == ldap.ModifyRequestChangeOperationAdd &&
server.config.Acl.Check(&state.login, "modifyAdd", dn, []string{attr}))) {
return ldap.LDAPResultInsufficientAccessRights, nil return ldap.LDAPResultInsufficientAccessRights, nil
} }
@ -415,6 +421,11 @@ func (server *Server) handleModifyInternal(state *State, r *message.ModifyReques
addMembers[i] = addMem addMembers[i] = addMem
} }
if v, ok := newEntry[ATTR_OBJECTCLASS]; ok && len(v) == 0 {
return ldap.LDAPResultInsufficientAccessRights, fmt.Errorf(
"Cannot remove all objectclass values")
}
// Now, the modification has been processed and accepted and we want to commit it // Now, the modification has been processed and accepted and we want to commit it
newEntry[ATTR_MODIFIERSNAME] = []string{state.login.user} newEntry[ATTR_MODIFIERSNAME] = []string{state.login.user}
newEntry[ATTR_MODIFYTIMESTAMP] = []string{genTimestamp()} newEntry[ATTR_MODIFYTIMESTAMP] = []string{genTimestamp()}