server_bind.go 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. package ldap
  2. import (
  3. "github.com/nmcclain/asn1-ber"
  4. "log"
  5. "net"
  6. )
  7. func HandleBindRequest(req *ber.Packet, fns map[string]Binder, conn net.Conn) (resultCode LDAPResultCode) {
  8. defer func() {
  9. if r := recover(); r != nil {
  10. resultCode = LDAPResultOperationsError
  11. }
  12. }()
  13. // we only support ldapv3
  14. ldapVersion, ok := req.Children[0].Value.(uint64)
  15. if !ok {
  16. return LDAPResultProtocolError
  17. }
  18. if ldapVersion != 3 {
  19. log.Printf("Unsupported LDAP version: %d", ldapVersion)
  20. return LDAPResultInappropriateAuthentication
  21. }
  22. // auth types
  23. bindDN, ok := req.Children[1].Value.(string)
  24. if !ok {
  25. return LDAPResultProtocolError
  26. }
  27. bindAuth := req.Children[2]
  28. switch bindAuth.Tag {
  29. default:
  30. log.Print("Unknown LDAP authentication method")
  31. return LDAPResultInappropriateAuthentication
  32. case LDAPBindAuthSimple:
  33. if len(req.Children) == 3 {
  34. fnNames := []string{}
  35. for k := range fns {
  36. fnNames = append(fnNames, k)
  37. }
  38. fn := routeFunc(bindDN, fnNames)
  39. resultCode, err := fns[fn].Bind(bindDN, bindAuth.Data.String(), conn)
  40. if err != nil {
  41. log.Printf("BindFn Error %s", err.Error())
  42. return LDAPResultOperationsError
  43. }
  44. return resultCode
  45. } else {
  46. log.Print("Simple bind request has wrong # children. len(req.Children) != 3")
  47. return LDAPResultInappropriateAuthentication
  48. }
  49. case LDAPBindAuthSASL:
  50. log.Print("SASL authentication is not supported")
  51. return LDAPResultInappropriateAuthentication
  52. }
  53. return LDAPResultOperationsError
  54. }
  55. func encodeBindResponse(messageID uint64, ldapResultCode LDAPResultCode) *ber.Packet {
  56. responsePacket := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Response")
  57. responsePacket.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "Message ID"))
  58. bindReponse := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationBindResponse, nil, "Bind Response")
  59. bindReponse.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(ldapResultCode), "resultCode: "))
  60. bindReponse.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, "", "matchedDN: "))
  61. bindReponse.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, "", "errorMessage: "))
  62. responsePacket.AppendChild(bindReponse)
  63. // ber.PrintPacket(responsePacket)
  64. return responsePacket
  65. }