package ldap import ( "math/rand" "time" csm "git.loafle.net/commons/service_matcher-go" ber "gopkg.in/asn1-ber.v1" ) const ( ApplicationBindRequest = 0 ApplicationBindResponse = 1 ) type LDAPMatcher struct { csm.Matchers reqID int64 } func (l *LDAPMatcher) Key() string { return "LDAP" } func (l *LDAPMatcher) Name() string { return "LDAP" } func (l *LDAPMatcher) Meta() csm.Metadata { return nil } func (l *LDAPMatcher) IsPrePacket() bool { return false } func (l *LDAPMatcher) IsError(info csm.MatchInfo, index int, packet *csm.Packet) bool { return false } func (l *LDAPMatcher) Match(info csm.MatchInfo, index int, packet *csm.Packet) error { if packet == nil || packet.Buffer == nil || packet.Len == 0 { return csm.NoPacketReceivedError() } p := ber.DecodePacket(packet.Buffer) respID, ok := p.Children[0].Value.(int64) if !ok { return csm.NotMatchedError() } if respID != l.reqID { return csm.NotMatchedError() } if p.Children[1].Tag != ApplicationBindResponse { return csm.NotMatchedError() } return nil } func NewMatcher() csm.Matcher { m := &LDAPMatcher{} rand.Seed(time.Now().UnixNano()) m.reqID = rand.Int63n(1000) p := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request") p.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, m.reqID, "MessageID")) bindRequest := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationBindRequest, nil, "Bind Request") bindRequest.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, 2, "Version")) bindRequest.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, "LOAFLEOVERFLOW", "User Name")) bindRequest.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, "LOAFLEOVERFLOW", "Password")) p.AppendChild(bindRequest) m.AddPacket(csm.NewPacket(p.Bytes(), len(p.Bytes()))) return m }