summaryrefslogtreecommitdiffstats
path: root/scan_ldapsearchfilter.c
blob: a07888b408eaf38acbce87c4c7406a6448e7f928 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include "ldap.h"
#include <stdlib.h>

/*
        Filter ::= CHOICE {
                and             [0] SET OF Filter,
                or              [1] SET OF Filter,
                not             [2] Filter,
                equalityMatch   [3] AttributeValueAssertion,
                substrings      [4] SubstringFilter,
                greaterOrEqual  [5] AttributeValueAssertion,
                lessOrEqual     [6] AttributeValueAssertion,
                present         [7] AttributeDescription,
                approxMatch     [8] AttributeValueAssertion,
                extensibleMatch [9] MatchingRuleAssertion }

        SubstringFilter ::= SEQUENCE {
                type            AttributeDescription,
                -- at least one must be present
                substrings      SEQUENCE OF CHOICE {
                        initial [0] LDAPString,
                        any     [1] LDAPString,
                        final   [2] LDAPString } }

        MatchingRuleAssertion ::= SEQUENCE {
                matchingRule    [1] MatchingRuleId OPTIONAL,
                type            [2] AttributeDescription OPTIONAL,
                matchValue      [3] AssertionValue,
                dnAttributes    [4] BOOLEAN DEFAULT FALSE }
*/

size_t scan_ldapsearchfilter(const char* src,const char* max,struct Filter** f) {
  enum asn1_tagclass tc;
  enum asn1_tagtype tt;
  size_t len,res,tmp;
  unsigned long tag;
  const char* nmax;
  *f=0;
  if (!(res=scan_asn1tag(src,max,&tc,&tt,&tag))) goto error;
  if (tc!=CONTEXT_SPECIFIC || (tt!=CONSTRUCTED && tag!=7) || tag>9) goto error;
  if (!(tmp=scan_asn1length(src+res,max,&len))) goto error;
  res+=tmp;
  nmax=src+res+len;
  if (nmax>max) goto error;
  if (!(*f=calloc(1,sizeof(struct Filter)))) goto error;
  switch ((*f)->type=tag) {
  case 0:    /*  and             [0] SET OF Filter, */
  case 1:    /*  or              [1] SET OF Filter, */
    (*f)->x=0;
    while (src+res<nmax) {
      struct Filter* F=(*f)->x;
      if (!(tmp=scan_ldapsearchfilter(src+res,nmax,&(*f)->x))) {
	if (F) {	/* OK, end of sequence */
	  (*f)->x=F;
	  break;
	}
	(*f)->x=F;
	goto error;
      }
      (*f)->x->next=F;
      res+=tmp;
    }
    break;
  case 2:    /*  not             [2] Filter, */
    if (!(tmp=scan_ldapsearchfilter(src+res,nmax,&(*f)->x))) goto error;
    if (tmp!=len) goto error;
    res+=tmp;
    break;
  case 3:    /*  equalityMatch   [3] AttributeValueAssertion, */
  case 5:    /*  greaterOrEqual  [5] AttributeValueAssertion, */
  case 6:    /*  lessOrEqual     [6] AttributeValueAssertion, */
  case 8:    /*  approxMatch     [8] AttributeValueAssertion, */
    if (!(tmp=scan_ldapava(src+res,nmax,&(*f)->ava))) goto error;
    res+=tmp;
    break;
  case 4:    /*  substrings      [4] SubstringFilter, */
    {
      size_t len2;
      if (!(tmp=scan_ldapstring(src+res,nmax,&(*f)->ava.desc))) goto error;
      res+=tmp;
      if (!(tmp=scan_asn1SEQUENCE(src+res,nmax,&len2))) goto error;
      res+=tmp;
      if (src+res+len2!=nmax) goto error;
      while (src+res<nmax) {
	struct Substring* s=calloc(1,sizeof(struct Substring));
	unsigned long x;
	enum asn1_tagtype tt;
	enum asn1_tagclass tc;
	if (!s) goto error;
	if (!(tmp=scan_asn1string(src+res,nmax,&tc,&tt,&x,&s->s.s,&s->s.l)) || x>2) { free(s); goto error; }
	s->substrtype=x;
	res+=tmp;
	s->next=(*f)->substrings;
	(*f)->substrings=s;
      }
      break;
    }
  case 7:    /*  present         [7] AttributeDescription, */
    (*f)->ava.desc.s=src+res;
    (*f)->ava.desc.l=len;
    res+=len;
    break;
  case 9:    /*  extensibleMatch [9] MatchingRuleAssertion } */
    goto error;
  }
  return res;
error:
  free_ldapsearchfilter(*f);
  *f=0;
  return 0;
}