package ldap
import (
"4a.si/asn1-ber"
"log"
"net"
)
func HandleBindRequest(req *ber.Packet, fns map[string]Binder, conn net.Conn) (resultCode LDAPResultCode) {
defer func() {
if r := recover(); r != nil {
resultCode = LDAPResultOperationsError
}
}()
// we only support ldapv3
ldapVersion, ok := req.Children[0].Value.(uint64)
if !ok {
return LDAPResultProtocolError
}
if ldapVersion != 3 {
log.Printf("Unsupported LDAP version: %d", ldapVersion)
return LDAPResultInappropriateAuthentication
}
// auth types
bindDN, ok := req.Children[1].Value.(string)
if !ok {
return LDAPResultProtocolError
}
bindAuth := req.Children[2]
switch bindAuth.Tag {
default:
log.Print("Unknown LDAP authentication method")
return LDAPResultInappropriateAuthentication
case LDAPBindAuthSimple:
if len(req.Children) == 3 {
fnNames := []string{}
for k := range fns {
fnNames = append(fnNames, k)
}
fn := routeFunc(bindDN, fnNames)
resultCode, err := fns[fn].Bind(bindDN, bindAuth.Data.String(), conn)
if err != nil {
log.Printf("BindFn Error %s", err.Error())
return LDAPResultOperationsError
}
return resultCode
} else {
log.Print("Simple bind request has wrong # children. len(req.Children) != 3")
return LDAPResultInappropriateAuthentication
}
case LDAPBindAuthSASL:
log.Print("SASL authentication is not supported")
return LDAPResultInappropriateAuthentication
}
return LDAPResultOperationsError
}
func encodeBindResponse(messageID uint64, ldapResultCode LDAPResultCode) *ber.Packet {
responsePacket := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Response")
responsePacket.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "Message ID"))
bindReponse := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationBindResponse, nil, "Bind Response")
bindReponse.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(ldapResultCode), "resultCode: "))
bindReponse.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, "", "matchedDN: "))
bindReponse.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, "", "errorMessage: "))
responsePacket.AppendChild(bindReponse)
// ber.PrintPacket(responsePacket)
return responsePacket
}