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