summaryrefslogtreecommitdiffstats
path: root/ldap_match_mapped.c
diff options
context:
space:
mode:
Diffstat (limited to 'ldap_match_mapped.c')
-rw-r--r--ldap_match_mapped.c200
1 files changed, 200 insertions, 0 deletions
diff --git a/ldap_match_mapped.c b/ldap_match_mapped.c
new file mode 100644
index 0000000..d457a1a
--- /dev/null
+++ b/ldap_match_mapped.c
@@ -0,0 +1,200 @@
+#include "ldif.h"
+#include "byte.h"
+#include <str.h>
+#include "uint32.h"
+#include "case.h"
+#include <ctype.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+
+extern char* map;
+extern long filelen;
+extern uint32 magic,attribute_count,record_count,indices_offset,size_of_string_table;
+extern uint32 dn_ofs,objectClass_ofs;
+
+int substringmatch(struct Substring* x,const char* attr,int ignorecase) {
+ int (*diff)(const void* a, unsigned long len, const void* b);
+ if (ignorecase)
+ diff=case_diffb;
+ else
+ diff=byte_diff;
+ while (x) {
+ unsigned long i;
+ if (x->s.l>str_len(attr)) return 0;
+ switch (x->substrtype) {
+ case prefix:
+ if (diff(x->s.s,x->s.l,attr)) return 0;
+found:
+ break;
+ case any:
+ {
+ unsigned long len=str_len(attr);
+ if (len<x->s.l) return 0;
+ for (i=0; i<=len-x->s.l; ++i)
+ if (!diff(x->s.s,x->s.l,attr+i))
+ goto found;
+ }
+ return 0;
+ case suffix:
+ if (diff(x->s.s,x->s.l,attr+str_len(attr)-x->s.l)) return 0;
+ }
+ x=x->next;
+ }
+ return 1;
+}
+
+int ldap_match_present(uint32 ofs,uint32 attrofs) {
+ uint32 j,k;
+ if (attrofs==dn_ofs || attrofs==objectClass_ofs) return 1;
+ uint32_unpack(map+ofs,&j);
+ for (k=2; k<j; ++k)
+ if (uint32_read(map+ofs+k*8)==attrofs)
+ return 1;
+ return 0;
+}
+
+uint32 ldap_find_attr_value(uint32 ofs,uint32 attrofs) {
+ uint32 j,k;
+ if (attrofs==dn_ofs) return uint32_read(map+ofs+8);
+ if (attrofs==objectClass_ofs) return uint32_read(map+ofs+12);
+ uint32_unpack(map+ofs,&j);
+ for (k=2; k<j; ++k)
+ if (uint32_read(map+ofs+k*8)==attrofs)
+ return uint32_read(map+ofs+k*8+4);
+ return 0;
+}
+
+int matchint(struct Filter* f,const char* t) {
+ int r;
+
+ if (f->attrflag&1)
+ r=matchcasestring(&f->ava.value,t);
+ else
+ r=matchstring(&f->ava.value,t);
+ if (f->type==EQUAL) return (r==0);
+ if (f->type==LESSEQUAL) return (r>0);
+ return (r<0);
+}
+
+/* return non-zero if the record matches the search filter */
+int ldap_matchfilter_mapped(uint32 ofs,struct Filter* f) {
+ struct Filter* y=f->x;
+ if (!f) return 1;
+ switch (f->type) {
+ case AND:
+ while (y) {
+ if (!ldap_matchfilter_mapped(ofs,y)) return 0;
+ y=y->next;
+ }
+ return 1;
+ case OR:
+ while (y) {
+ if (ldap_matchfilter_mapped(ofs,y)) return 1;
+ y=y->next;
+ }
+ return 0;
+ case NOT:
+ return !ldap_matchfilter_mapped(ofs,y);
+ case PRESENT:
+ return ldap_match_present(ofs,f->attrofs);
+ case EQUAL:
+ case LESSEQUAL:
+ case GREATEQUAL:
+ {
+ uint32 i,j,k;
+ uint32_unpack(map+ofs,&j);
+// if (!matchstring(&f->ava.desc,"dn")) {
+ if (f->attrofs==dn_ofs) {
+ uint32_unpack(map+ofs+8,&k);
+ return matchint(f,map+k);
+// } else if (!matchstring(&f->ava.desc,"objectName")) {
+ } else if (f->attrofs==objectClass_ofs) {
+ uint32_unpack(map+ofs+12,&k);
+ if (matchint(f,map+k)) return 1;
+ }
+ for (i=2; i<j; ++i) {
+ uint32_unpack(map+ofs+i*8,&k);
+// if (!matchstring(&f->ava.desc,map+k)) {
+ if (f->attrofs==k) {
+ uint32_unpack(map+ofs+i*8+4,&k);
+ if (matchint(f,map+k)) return 1;
+ }
+ }
+ return 0;
+ }
+ break;
+ case SUBSTRING:
+ {
+ uint32 i,j,k;
+ uint32_unpack(map+ofs,&j);
+// if (matchstring(&f->ava.desc,"dn")) {
+ if (f->attrofs==dn_ofs) {
+ uint32_unpack(map+ofs+8,&k);
+ if (substringmatch(f->substrings,map+k,f->attrflag&1)) return 1;
+ return 0;
+// } else if (matchstring(&f->ava.desc,"objectName")) {
+ } else if (f->attrofs==objectClass_ofs) {
+ uint32_unpack(map+ofs+12,&k);
+ if (substringmatch(f->substrings,map+k,f->attrflag&1)) return 1;
+ }
+ for (i=2; i<j; ++i) {
+ uint32_unpack(map+ofs+i*8,&k);
+// if (!matchstring(&f->ava.desc,map+k)) {
+ if (f->attrofs==k) {
+ uint32_unpack(map+ofs+i*8+4,&k);
+ if (substringmatch(f->substrings,map+k,f->attrflag&1))
+ return 1;
+ }
+ }
+ return 0;
+ }
+ break;
+ default:
+ write(2,"unsupported query type\n",23);
+ return 0;
+ }
+ return 1;
+}
+
+/* return 0 if they didn't match, otherwise return length in b */
+static int match(const char* a,int len,const char* b) {
+ const char* A=a+len;
+ const char* B=b+str_len(b);
+ while (len>0 && A>a && B>b) {
+ --A; --B; --len;
+ while (*A==' ' && A>a) { --A; --len; }
+ while (*B==' ' && B>b) --B;
+ if (tolower(*A) != tolower(*B))
+ return 0;
+ }
+ return str_len(B);
+}
+
+/* return non-zero if the record matches the search request */
+int ldap_match_mapped(uint32 ofs,struct SearchRequest* sr) {
+ unsigned int l,i;
+ uint32 k;
+ uint32_unpack(map+ofs+8,&k);
+ l=str_len(map+k);
+ /* first see if baseObject is a suffix of dn */
+ if (sr->baseObject.l>l) {
+// puts("fail: baseObject longer than dn");
+ return 0;
+ }
+ /* we want "o=foo, o=bar" and "o=FOO,o=baR" to be equal */
+ if (sr->baseObject.l && !match(sr->baseObject.s,sr->baseObject.l,map+k)) {
+// puts("fail: not suffix");
+ return 0;
+ }
+ /* it is. If scope==wholeSubtree, the scope check is also done */
+ switch (sr->scope) {
+ case wholeSubtree: break;
+ case baseObject: if (l==sr->baseObject.l) break; return 0;
+ default:
+ i=str_chr(map+k,',');
+ if (i+2>=l-sr->baseObject.l) break;
+ return 0;
+ }
+ return ldap_matchfilter_mapped(ofs,sr->filter);
+}