Initial QSfera import
This commit is contained in:
+127
@@ -0,0 +1,127 @@
|
||||
package ldapserver
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
ber "github.com/go-asn1-ber/asn1-ber"
|
||||
"github.com/go-ldap/ldap/v3"
|
||||
)
|
||||
|
||||
func HandleAddRequest(req *ber.Packet, boundDN string, server *Server, conn net.Conn) error {
|
||||
if boundDN == "" {
|
||||
return ldap.NewError(ldap.LDAPResultInsufficientAccessRights, errors.New("anonymous Write denied"))
|
||||
}
|
||||
addReq, err := parseAddRequest(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fnNames := []string{}
|
||||
for k := range server.AddFns {
|
||||
fnNames = append(fnNames, k)
|
||||
}
|
||||
fn := routeFunc(addReq.DN, fnNames)
|
||||
var adder Adder
|
||||
if adder = server.AddFns[fn]; adder == nil {
|
||||
if fn == "" {
|
||||
err = fmt.Errorf("no suitable handler found for dn: '%s'", addReq.DN)
|
||||
} else {
|
||||
err = fmt.Errorf("handler '%s' does not support add", fn)
|
||||
}
|
||||
return ldap.NewError(ldap.LDAPResultUnwillingToPerform, err)
|
||||
}
|
||||
code, err := adder.Add(boundDN, addReq, conn)
|
||||
return ldap.NewError(uint16(code), err)
|
||||
}
|
||||
|
||||
func parseAddRequest(req *ber.Packet) (*ldap.AddRequest, error) {
|
||||
addReq := ldap.AddRequest{}
|
||||
// LDAP Add request have 2 Elements (DN and AttributeList)
|
||||
if len(req.Children) != 2 {
|
||||
return nil, ldap.NewError(ldap.LDAPResultProtocolError, errors.New("invalid add request"))
|
||||
}
|
||||
|
||||
dn, ok := req.Children[0].Value.(string)
|
||||
if !ok {
|
||||
return nil, ldap.NewError(ldap.LDAPResultProtocolError, errors.New("error decoding entry DN"))
|
||||
}
|
||||
|
||||
_, err := ldap.ParseDN(dn)
|
||||
if err != nil {
|
||||
return nil, ldap.NewError(ldap.LDAPResultProtocolError, err)
|
||||
}
|
||||
addReq.DN = dn
|
||||
|
||||
al, err := parseAttributeList(req.Children[1])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
addReq.Attributes = al
|
||||
|
||||
return &addReq, nil
|
||||
}
|
||||
|
||||
func parseAttributeList(req *ber.Packet) ([]ldap.Attribute, error) {
|
||||
ldapAttrs := []ldap.Attribute{}
|
||||
|
||||
if req.ClassType != ber.ClassUniversal || req.TagType != ber.TypeConstructed || req.Tag != ber.TagSequence {
|
||||
return nil, ldap.NewError(ldap.LDAPResultProtocolError, errors.New("error decoding Attribute List"))
|
||||
}
|
||||
|
||||
for _, a := range req.Children {
|
||||
attr, err := parseAttribute(a, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ldapAttrs = append(ldapAttrs, *attr)
|
||||
|
||||
}
|
||||
return ldapAttrs, nil
|
||||
}
|
||||
|
||||
func parseAttribute(attr *ber.Packet, partial bool) (*ldap.Attribute, error) {
|
||||
var la ldap.Attribute
|
||||
var ok bool
|
||||
var err error
|
||||
|
||||
// Partial attributes, might just contain a type and allow the Value to be absent
|
||||
if partial && (len(attr.Children) < 1 || len(attr.Children) > 2) {
|
||||
return nil, ldap.NewError(ldap.LDAPResultProtocolError, errors.New("error decoding partial Attribute"))
|
||||
} else if !partial && len(attr.Children) != 2 {
|
||||
return nil, ldap.NewError(ldap.LDAPResultProtocolError, errors.New("error decoding Attribute"))
|
||||
}
|
||||
|
||||
ad := attr.Children[0]
|
||||
if ad.ClassType != ber.ClassUniversal || ad.TagType != ber.TypePrimitive || ad.Tag != ber.TagOctetString {
|
||||
return nil, ldap.NewError(ldap.LDAPResultProtocolError, errors.New("error decoding Attribute Description"))
|
||||
}
|
||||
la.Type, ok = ad.Value.(string)
|
||||
if !ok {
|
||||
return nil, ldap.NewError(ldap.LDAPResultProtocolError, errors.New("error decoding Attribute Description"))
|
||||
}
|
||||
|
||||
// We can return here if this is a Partial Attribute without values
|
||||
if partial && len(attr.Children) == 1 {
|
||||
return &la, nil
|
||||
}
|
||||
if la.Vals, err = parseAttributeValues(attr.Children[1]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &la, nil
|
||||
}
|
||||
|
||||
func parseAttributeValues(values *ber.Packet) ([]string, error) {
|
||||
var strVals []string
|
||||
if values.ClassType != ber.ClassUniversal || values.TagType != ber.TypeConstructed || values.Tag != ber.TagSet {
|
||||
return nil, ldap.NewError(ldap.LDAPResultProtocolError, errors.New("error decoding Attribute Values"))
|
||||
}
|
||||
for _, value := range values.Children {
|
||||
strVal, ok := value.Value.(string)
|
||||
if !ok {
|
||||
return nil, ldap.NewError(ldap.LDAPResultProtocolError, errors.New("error decoding Attribute Value"))
|
||||
}
|
||||
strVals = append(strVals, strVal)
|
||||
}
|
||||
return strVals, nil
|
||||
}
|
||||
Reference in New Issue
Block a user