Handle LDAP Compare and Delete requests

This commit is contained in:
Alex 2020-01-19 21:48:14 +01:00
parent 3decb94271
commit f9cb0552be
1 changed files with 130 additions and 0 deletions

130
main.go
View File

@ -154,6 +154,8 @@ func main() {
routes.Bind(gobottin.handleBind)
routes.Search(gobottin.handleSearch)
routes.Add(gobottin.handleAdd)
routes.Compare(gobottin.handleCompare)
routes.Delete(gobottin.handleDelete)
ldapserver.Handle(routes)
// listen on 10389
@ -556,3 +558,131 @@ func (server *Server) handleAddInternal(state *State, r *message.AddRequest) (in
return ldap.LDAPResultSuccess, nil
}
func (server *Server) handleCompare(s ldap.UserState, w ldap.ResponseWriter, m *ldap.Message) {
state := s.(*State)
r := m.GetCompareRequest()
code, err := server.handleCompareInternal(state, &r)
res := ldap.NewResponse(code)
if err != nil {
res.SetDiagnosticMessage(err.Error())
}
w.Write(message.CompareResponse(res))
}
func (server *Server) handleCompareInternal(state *State, r *message.CompareRequest) (int, error) {
dn := string(r.Entry())
attr := string(r.Ava().AttributeDesc())
expected := string(r.Ava().AssertionValue())
_, err := server.checkSuffix(dn, false)
if err != nil {
return ldap.LDAPResultInvalidDNSyntax, err
}
// TODO check user for permissions to read dn
exists, err := server.objectExists(dn)
if err != nil {
return ldap.LDAPResultOperationsError, err
}
if !exists {
return ldap.LDAPResultNoSuchObject, fmt.Errorf("Not found: %s", dn)
}
values, err := server.getAttribute(dn, attr)
if err != nil {
return ldap.LDAPResultOperationsError, err
}
for _, v := range values {
if v == expected {
return ldap.LDAPResultCompareTrue, nil
}
}
return ldap.LDAPResultCompareFalse, nil
}
func (server *Server) handleDelete(s ldap.UserState, w ldap.ResponseWriter, m *ldap.Message) {
state := s.(*State)
r := m.GetDeleteRequest()
code, err := server.handleDeleteInternal(state, &r)
res := ldap.NewResponse(code)
if err != nil {
res.SetDiagnosticMessage(err.Error())
}
w.Write(message.DelResponse(res))
}
func (server *Server) handleDeleteInternal(state *State, r *message.DelRequest) (int, error) {
dn := string(*r)
_, err := server.checkSuffix(dn, false)
if err != nil {
return ldap.LDAPResultInvalidDNSyntax, err
}
// TODO check user for permissions to write dn
// Check that this LDAP entry exists and has no children
path := dnToConsul(dn) + "/"
items, _, err := server.kv.List(path, nil)
if err != nil {
return ldap.LDAPResultOperationsError, err
}
if len(items) == 0 {
return ldap.LDAPResultNoSuchObject, fmt.Errorf("Not found: %s", dn)
}
for _, item := range items {
itemDN, _, _ := consulToDN(item)
if itemDN != dn {
return ldap.LDAPResultNotAllowedOnNonLeaf, fmt.Errorf(
"Cannot delete %d as it has children", dn)
}
}
// Retrieve group membership before we delete everything
memberOf, err := server.getAttribute(dn, "memberOf")
if err != nil {
return ldap.LDAPResultOperationsError, err
}
// Delete the LDAP entry
_, err = server.kv.DeleteTree(path, nil)
if err != nil {
return ldap.LDAPResultOperationsError, err
}
// Delete it from the member list of all the groups it was a member of
if memberOf != nil {
for _, group := range memberOf {
groupMembers , err := server.getAttribute(dn, "member")
if err != nil {
return ldap.LDAPResultOperationsError, err
}
newMembers := []string{}
for _, memb := range groupMembers {
if memb != dn {
newMembers = append(newMembers, memb)
}
}
err = server.addElements(group, Entry{
"member": newMembers,
})
if err != nil {
return ldap.LDAPResultOperationsError, err
}
}
}
return ldap.LDAPResultSuccess, nil
}