1 #include "ldif.h"
2 #include "byte.h"
3 #include "str.h"
4 #include "uint32.h"
5 #include "case.h"
6 #include <ctype.h>
7 #include <unistd.h>
8 #include <stdio.h>
9 #include <string.h>
10 
11 extern char* map;
12 extern long filelen;
13 extern uint32 magic,attribute_count,record_count,indices_offset,size_of_string_table;
14 extern uint32 dn_ofs,objectClass_ofs;
15 
substringmatch(struct Substring * x,const char * attr,int ignorecase)16 int substringmatch(struct Substring* x,const char* attr,int ignorecase) {
17   int (*diff)(const void* a, unsigned long len, const void* b);
18   if (ignorecase)
19     diff=case_diffb;
20   else
21     diff=byte_diff;
22   while (x) {
23     unsigned long i;
24     if (x->s.l>str_len(attr)) return 0;
25     switch (x->substrtype) {
26     case prefix:
27       if (diff(x->s.s,x->s.l,attr)) return 0;
28 found:
29       break;
30     case any:
31       {
32 	unsigned long len=str_len(attr);
33 	if (len<x->s.l) return 0;
34 	for (i=0; i<=len-x->s.l; ++i)
35 	  if (!diff(x->s.s,x->s.l,attr+i))
36 	    goto found;
37       }
38       return 0;
39     case suffix:
40       if (diff(x->s.s,x->s.l,attr+str_len(attr)-x->s.l)) return 0;
41     }
42     x=x->next;
43   }
44   return 1;
45 }
46 
ldap_match_present(uint32 ofs,uint32 attrofs)47 int ldap_match_present(uint32 ofs,uint32 attrofs) {
48   uint32 j,k;
49   if (attrofs==dn_ofs || attrofs==objectClass_ofs) return 1;
50   uint32_unpack(map+ofs,&j);
51   for (k=2; k<j; ++k)
52     if (uint32_read(map+ofs+k*8)==attrofs)
53       return 1;
54   return 0;
55 }
56 
ldap_find_attr_value(uint32 ofs,uint32 attrofs)57 uint32 ldap_find_attr_value(uint32 ofs,uint32 attrofs) {
58   uint32 j,k;
59   if (attrofs==dn_ofs) return uint32_read(map+ofs+8);
60   if (attrofs==objectClass_ofs) return uint32_read(map+ofs+12);
61   uint32_unpack(map+ofs,&j);
62   for (k=2; k<j; ++k)
63     if (uint32_read(map+ofs+k*8)==attrofs)
64       return uint32_read(map+ofs+k*8+4);
65   return 0;
66 }
67 
matchint(struct Filter * f,const char * t)68 int matchint(struct Filter* f,const char* t) {
69   int r;
70 
71   if (f->attrflag&1)
72     r=matchcasestring(&f->ava.value,t);
73   else
74     r=matchstring(&f->ava.value,t);
75   if (f->type==EQUAL) return (r==0);
76   if (f->type==LESSEQUAL) return (r>0);
77   return (r<0);
78 }
79 
80 /* return non-zero if the record matches the search filter */
ldap_matchfilter_mapped(uint32 ofs,struct Filter * f)81 int ldap_matchfilter_mapped(uint32 ofs,struct Filter* f) {
82   struct Filter* y=f->x;
83   if (!f) return 1;
84   switch (f->type) {
85   case AND:
86     while (y) {
87       if (!ldap_matchfilter_mapped(ofs,y)) return 0;
88       y=y->next;
89     }
90     return 1;
91   case OR:
92     while (y) {
93       if (ldap_matchfilter_mapped(ofs,y)) return 1;
94       y=y->next;
95     }
96     return 0;
97   case NOT:
98     return !ldap_matchfilter_mapped(ofs,y);
99   case PRESENT:
100     return ldap_match_present(ofs,f->attrofs);
101   case EQUAL:
102   case LESSEQUAL:
103   case GREATEQUAL:
104     {
105       uint32 i,j,k;
106       uint32_unpack(map+ofs,&j);
107 //      if (!matchstring(&f->ava.desc,"dn")) {
108       if (f->attrofs==dn_ofs) {
109 	uint32_unpack(map+ofs+8,&k);
110 	return matchint(f,map+k);
111 //      } else if (!matchstring(&f->ava.desc,"objectName")) {
112       } else if (f->attrofs==objectClass_ofs) {
113 	uint32_unpack(map+ofs+12,&k);
114 	if (matchint(f,map+k)) return 1;
115       }
116       for (i=2; i<j; ++i) {
117 	uint32_unpack(map+ofs+i*8,&k);
118 //	if (!matchstring(&f->ava.desc,map+k)) {
119 	if (f->attrofs==k) {
120 	  uint32_unpack(map+ofs+i*8+4,&k);
121 	  if (matchint(f,map+k)) return 1;
122 	}
123       }
124       return 0;
125     }
126     break;
127   case SUBSTRING:
128     {
129       uint32 i,j,k;
130       uint32_unpack(map+ofs,&j);
131 //      if (matchstring(&f->ava.desc,"dn")) {
132       if (f->attrofs==dn_ofs) {
133 	uint32_unpack(map+ofs+8,&k);
134 	if (substringmatch(f->substrings,map+k,f->attrflag&1)) return 1;
135 	return 0;
136 //      } else if (matchstring(&f->ava.desc,"objectName")) {
137       } else if (f->attrofs==objectClass_ofs) {
138 	uint32_unpack(map+ofs+12,&k);
139 	if (substringmatch(f->substrings,map+k,f->attrflag&1)) return 1;
140       }
141       for (i=2; i<j; ++i) {
142 	uint32_unpack(map+ofs+i*8,&k);
143 //	if (!matchstring(&f->ava.desc,map+k)) {
144 	if (f->attrofs==k) {
145 	  uint32_unpack(map+ofs+i*8+4,&k);
146 	  if (substringmatch(f->substrings,map+k,f->attrflag&1))
147 	    return 1;
148 	}
149       }
150       return 0;
151     }
152     break;
153   default:
154     write(2,"unsupported query type\n",23);
155     return 0;
156   }
157   return 1;
158 }
159 
160 /* return 0 if they didn't match, otherwise return length in b */
match(const char * a,int len,const char * b)161 static int match(const char* a,int len,const char* b) {
162   const char* A=a+len;
163   const char* B=b+str_len(b);
164   while (len>0 && A>a && B>b) {
165     --A; --B; --len;
166     while (*A==' ' && A>a) { --A; --len; }
167     while (*B==' ' && B>b) --B;
168     if (tolower(*A) != tolower(*B))
169       return 0;
170   }
171   return str_len(B);
172 }
173 
174 /* return non-zero if the record matches the search request */
ldap_match_mapped(uint32 ofs,struct SearchRequest * sr)175 int ldap_match_mapped(uint32 ofs,struct SearchRequest* sr) {
176   unsigned int l,i;
177   uint32 k;
178   uint32_unpack(map+ofs+8,&k);
179   l=str_len(map+k);
180   /* first see if baseObject is a suffix of dn */
181   if (sr->baseObject.l>l) {
182 //    puts("fail: baseObject longer than dn");
183     return 0;
184   }
185   /* we want "o=foo, o=bar" and "o=FOO,o=baR" to be equal */
186   if (sr->baseObject.l && !match(sr->baseObject.s,sr->baseObject.l,map+k)) {
187 //    puts("fail: not suffix");
188     return 0;
189   }
190   /* it is.  If scope==wholeSubtree, the scope check is also done */
191   switch (sr->scope) {
192   case wholeSubtree: break;
193   case baseObject: if (l==sr->baseObject.l) break; return 0;
194   default:
195     i=str_chr(map+k,',');
196     if (i+2>=l-sr->baseObject.l) break;
197     return 0;
198   }
199   return ldap_matchfilter_mapped(ofs,sr->filter);
200 }
201