1// File contains Compare functionality
2//
3// https://tools.ietf.org/html/rfc4511
4//
5// CompareRequest ::= [APPLICATION 14] SEQUENCE {
6//              entry           LDAPDN,
7//              ava             AttributeValueAssertion }
8//
9// AttributeValueAssertion ::= SEQUENCE {
10//              attributeDesc   AttributeDescription,
11//              assertionValue  AssertionValue }
12//
13// AttributeDescription ::= LDAPString
14//                         -- Constrained to <attributedescription>
15//                         -- [RFC4512]
16//
17// AttributeValue ::= OCTET STRING
18//
19
20package ldap
21
22import (
23	"fmt"
24
25	ber "gopkg.in/asn1-ber.v1"
26)
27
28// CompareRequest represents an LDAP CompareRequest operation.
29type CompareRequest struct {
30	DN        string
31	Attribute string
32	Value     string
33}
34
35func (req *CompareRequest) appendTo(envelope *ber.Packet) error {
36	pkt := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationCompareRequest, nil, "Compare Request")
37	pkt.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, req.DN, "DN"))
38
39	ava := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "AttributeValueAssertion")
40	ava.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, req.Attribute, "AttributeDesc"))
41	ava.AppendChild(ber.Encode(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, req.Value, "AssertionValue"))
42
43	pkt.AppendChild(ava)
44
45	envelope.AppendChild(pkt)
46
47	return nil
48}
49
50// Compare checks to see if the attribute of the dn matches value. Returns true if it does otherwise
51// false with any error that occurs if any.
52func (l *Conn) Compare(dn, attribute, value string) (bool, error) {
53	msgCtx, err := l.doRequest(&CompareRequest{
54		DN:        dn,
55		Attribute: attribute,
56		Value:     value})
57	if err != nil {
58		return false, err
59	}
60	defer l.finishMessage(msgCtx)
61
62	packet, err := l.readPacket(msgCtx)
63	if err != nil {
64		return false, err
65	}
66
67	if packet.Children[1].Tag == ApplicationCompareResponse {
68		err := GetLDAPError(packet)
69
70		switch {
71		case IsErrorWithCode(err, LDAPResultCompareTrue):
72			return true, nil
73		case IsErrorWithCode(err, LDAPResultCompareFalse):
74			return false, nil
75		default:
76			return false, err
77		}
78	}
79	return false, fmt.Errorf("unexpected Response: %d", packet.Children[1].Tag)
80}
81