summaryrefslogtreecommitdiffstats
path: root/ldap_match_sre.c
diff options
context:
space:
mode:
authorSimon Rettberg2014-03-15 01:49:50 +0100
committerSimon Rettberg2014-03-15 01:49:50 +0100
commitbedd2e7ccb1595c23e159eaa952ae1b0b5a3d2ad (patch)
treec7d1995a09f6ed0c4e6873252e957d72f5d07d07 /ldap_match_sre.c
downloadldadp-bedd2e7ccb1595c23e159eaa952ae1b0b5a3d2ad.tar.gz
ldadp-bedd2e7ccb1595c23e159eaa952ae1b0b5a3d2ad.tar.xz
ldadp-bedd2e7ccb1595c23e159eaa952ae1b0b5a3d2ad.zip
Lean and mean initial commit
Not much functionality yet
Diffstat (limited to 'ldap_match_sre.c')
-rw-r--r--ldap_match_sre.c166
1 files changed, 166 insertions, 0 deletions
diff --git a/ldap_match_sre.c b/ldap_match_sre.c
new file mode 100644
index 0000000..b0e69c1
--- /dev/null
+++ b/ldap_match_sre.c
@@ -0,0 +1,166 @@
+#include <unistd.h>
+#include "ldap.h"
+#include "byte.h"
+#include "case.h"
+#include <ctype.h>
+
+static int matchcasestr(struct string* a,struct string* b) {
+ unsigned long l=a->l;
+ unsigned long r;
+ if (b->l<l) l=b->l;
+ if ((r=case_diffb(a->s,l,b->s))) return r;
+ if (a->l>l) return 1;
+ if (b->l>l) return -1;
+ return 0;
+}
+
+static int matchstr(struct string* a,struct string* b) {
+ unsigned long l=a->l;
+ unsigned long r;
+ if (b->l<l) l=b->l;
+ if ((r=byte_diff(a->s,l,b->s))) return r;
+ if (a->l>l) return 1;
+ if (b->l>l) return -1;
+ return 0;
+}
+
+static int matchstr_sre(struct Filter* f,struct string* s) {
+ int r;
+ if (f->attrflag&1)
+ r=matchcasestr(&f->ava.value,s);
+ else
+ r=matchstr(&f->ava.value,s);
+ if (f->type==EQUAL) return (r==0);
+ if (f->type==LESSEQUAL) return (r>0);
+ return (r<0);
+}
+
+static int ldap_match_present_sre(struct SearchResultEntry* sre,struct string* s) {
+ struct PartialAttributeList* p;
+ for (p=sre->attributes; p; p=p->next) {
+ int r;
+ if ((r=matchstr(&p->type,s))) return r;
+ }
+ return 0;
+}
+
+static int substrmatch(struct Substring* x,struct string* s,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>s->l) return 0;
+ switch (x->substrtype) {
+ case prefix:
+ if (diff(x->s.s,x->s.l,s->s)) return 0;
+found:
+ break;
+ case any:
+ if (s->l<x->s.l) return 0;
+ for (i=0; i<=s->l-x->s.l; ++i)
+ if (!diff(x->s.s,x->s.l,s->s+i))
+ goto found;
+ return 0;
+ case suffix:
+ if (diff(x->s.s,x->s.l,s->s+s->l-x->s.l)) return 0;
+ }
+ x=x->next;
+ }
+ return 1;
+}
+
+extern uint32_t dn_ofs;
+
+int ldap_matchfilter_sre(struct SearchResultEntry* sre,struct Filter* f) {
+ struct PartialAttributeList* p;
+ struct Filter* y=f->x;
+ if (!f) return 1;
+ switch (f->type) {
+ case AND:
+ while (y) {
+ if (!ldap_matchfilter_sre(sre,y)) return 0;
+ y=y->next;
+ }
+ return 1;
+ case OR:
+ while (y) {
+ if (ldap_matchfilter_sre(sre,y)) return 1;
+ y=y->next;
+ }
+ return 0;
+ case NOT:
+ return !ldap_matchfilter_sre(sre,y);
+ case PRESENT:
+ return ldap_match_present_sre(sre,&f->ava.desc);
+ case EQUAL:
+ case LESSEQUAL:
+ case GREATEQUAL:
+ if (f->attrofs==dn_ofs)
+ return matchstr_sre(f,&sre->objectName);
+ for (p=sre->attributes; p; p=p->next) {
+ int r;
+ struct AttributeDescriptionList* a;
+ if (matchstr(&f->ava.desc,&p->type)) {
+ for (a=p->values; a; a=a->next)
+ if ((r=matchstr_sre(f,&a->a))) return r;
+ return 0;
+ }
+ }
+ return 0;
+ case SUBSTRING:
+ if (f->attrofs==dn_ofs)
+ return substrmatch(f->substrings,&sre->objectName,f->attrflag&1);
+ for (p=sre->attributes; p; p=p->next) {
+ if (matchstr(&f->ava.desc,&p->type)) {
+ struct AttributeDescriptionList* a;
+ int r;
+ for (a=p->values; a; a=a->next)
+ if ((r=substrmatch(f->substrings,&a->a,f->attrflag&1))) return r;
+ return 0;
+ }
+ }
+ return 0;
+ 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,int blen) {
+ const char* A=a+len;
+ const char* B=b+blen;
+ 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 b+blen-B;
+}
+
+int ldap_match_sre(struct SearchResultEntry* sre,struct SearchRequest* sr) {
+ unsigned long i;
+ if (sr->baseObject.l>sre->objectName.l)
+ /* baseObject is longer than dn */
+ return 0;
+ if (sr->baseObject.l && !match(sr->baseObject.s,sr->baseObject.l,sre->objectName.s,sre->objectName.l))
+ /* baseObject is not a suffix of dn */
+ return 0;
+ switch (sr->scope) {
+ case wholeSubtree: break;
+ case baseObject: if (sre->objectName.l==sr->baseObject.l) break; return 0;
+ default:
+ for (i=0; i<sre->objectName.l; ++i)
+ if (sre->objectName.s[i]==',')
+ break;
+ if (i+2>=sre->objectName.l-sr->baseObject.l) break;
+ return 0;
+ }
+ return ldap_matchfilter_sre(sre,sr->filter);
+}