package ldap import ( "math/rand" "time" osm "git.loafle.net/overflow/service_matcher-go" ber "gopkg.in/asn1-ber.v1" ) const ( ApplicationBindRequest = 0 ApplicationBindResponse = 1 ) type LDAPMatcher struct { osm.Matchers reqID int64 } func (m *LDAPMatcher) Key() string { return "LDAP" } func (m *LDAPMatcher) Name(matchCtx *osm.MatchCtx) string { return "LDAP" } func (m *LDAPMatcher) IsPrePacket() bool { return false } func (m *LDAPMatcher) IsError(matchCtx *osm.MatchCtx, index int, packet *osm.Packet) bool { return false } func (m *LDAPMatcher) Match(matchCtx *osm.MatchCtx, index int, packet *osm.Packet) error { if packet == nil || !packet.Valid() { return osm.NoPacketReceivedError() } p := ber.DecodePacket(packet.Buffer) if nil == p || nil == p.Children || len(p.Children) <= 1 { return osm.NotMatchedError() } respID, ok := p.Children[0].Value.(int64) if !ok { return osm.NotMatchedError() } if respID != m.reqID { return osm.NotMatchedError() } if p.Children[1].Tag != ApplicationBindResponse { return osm.NotMatchedError() } return nil } func NewMatcher() osm.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(osm.NewPacket(p.Bytes(), len(p.Bytes()))) return m }