Files
mars-tinyldap/scan_ldapsearchfilter.c
leitner fc2b16c556 remove #if 0'd code from scan_ldapsearchfilter
add unit tests to scan_ldapaddrequest
2023-09-17 12:17:55 +00:00

235 lines
8.2 KiB
C

#include "ldap.h"
#include <stdlib.h>
#ifdef UNITTEST
void* mycalloc(size_t a,size_t b);
#define calloc mycalloc
#endif
/*
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))) // fail01
goto error;
if (tc!=PRIVATE || (tt!=CONSTRUCTED && tag!=7) || tag>9) // fail02
goto error;
if (!(tmp=scan_asn1length(src+res,max,&len))) // fail03
goto error;
res+=tmp;
nmax=src+res+len;
if (!(*f=calloc(1,sizeof(struct Filter)))) // fail04
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))) { // fail05
(*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))) // fail06
goto error;
if (tmp!=len) // fail07
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))) // fail08
goto error;
res+=tmp;
break;
case 4: /* substrings [4] SubstringFilter, */
{
size_t len2;
if (!(tmp=scan_ldapstring(src+res,nmax,&(*f)->ava.desc))) // fail09
goto error;
res+=tmp;
if (!(tmp=scan_asn1SEQUENCE(src+res,nmax,&len2))) // fail10
goto error;
res+=tmp;
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) // fail11
goto error;
if (!(tmp=scan_asn1string(src+res,nmax,&tc,&tt,&x,&s->s.s,&s->s.l)) || x>2) { // fail12
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 */
default:
goto error; // fail14
}
return res;
error:
free_ldapsearchfilter(*f);
*f=0;
return 0;
}
#ifdef UNITTEST
#undef UNITTEST
#include <string.h>
#include <assert.h>
#include "free_ldapsearchfilter.c"
#include "scan_asn1tag.c"
#include "scan_asn1length.c"
#include "scan_ldapava.c"
#include "scan_ldapstring.c"
#include "scan_asn1STRING.c"
#include "scan_asn1tagint.c"
#include "scan_asn1string.c"
#include "scan_asn1SEQUENCE.c"
#include <stdio.h>
#undef calloc
size_t callocfail=(size_t)-1;
void* mycalloc(size_t a,size_t b) {
if (--callocfail==0) return 0;
return calloc(a,b);
}
int main() {
struct Filter *f = 0;
char buf[100];
strcpy(buf,"\x87\x03""foo");
// type 7, PRESENT
assert(scan_ldapsearchfilter(buf, buf+100, &f) == 5); // "(foo=*)" (PRESENT)
assert(f && f->type==PRESENT && f->ava.desc.l==3 && !memcmp(f->ava.desc.s,"foo",3));
free_ldapsearchfilter(f); f=0;
callocfail=1; assert(scan_ldapsearchfilter(buf, buf+100, &f) == 0); // fail04
callocfail=(size_t)-1;
buf[1]=0x7e; assert(scan_ldapsearchfilter(buf, buf+100, &f)==0); // fail03
buf[0]=0x27; assert(scan_ldapsearchfilter(buf, buf+100, &f)==0); // middle fail02
buf[0]=0x8a; assert(scan_ldapsearchfilter(buf, buf+100, &f)==0); // right fail02
buf[0]=0x00; assert(scan_ldapsearchfilter(buf, buf+100, &f)==0); // left fail02
buf[0]=0x1f; assert(scan_ldapsearchfilter(buf, buf+1, &f)==0); // fail01
// type 2, NOT
strcpy(buf,"\xa2\x05\x87\x03""foo");
assert(scan_ldapsearchfilter(buf, buf+100, &f) == 7); // "(!(foo=*))" (NOT + PRESENT)
assert(f && f->type==NOT && f->x->type==PRESENT);
free_ldapsearchfilter(f); f=0;
buf[1]=6; assert(scan_ldapsearchfilter(buf, buf+100, &f) == 0); // fail07
buf[1]=5;
buf[2]=0x00; assert(scan_ldapsearchfilter(buf, buf+100, &f) == 0); // fail06
buf[0]=0xa9; assert(scan_ldapsearchfilter(buf, buf+100, &f) == 0); // type 9 (extensibleMatch) not implemented, should be rejected, fail14
// type 1, OR
strcpy(buf,"\xa1\x0d\x87\5danke\x87\4text");
assert(scan_ldapsearchfilter(buf, buf+100, &f) == 15);
assert(f && f->type==OR && f->x->type==PRESENT && f->x->next->type==PRESENT);
free_ldapsearchfilter(f); f=0;
buf[1]=0xc; assert(scan_ldapsearchfilter(buf, buf+100, &f) == 0); // fail05
buf[1]=0xd; buf[0]=0xa0; assert(scan_ldapsearchfilter(buf, buf+100, &f) == 15); // type 0, AND
assert(f && f->type==AND && f->x->type==PRESENT && f->x->next->type==PRESENT);
free_ldapsearchfilter(f); f=0;
// type 3, equalityMatch
strcpy(buf,"\xa3\x06\x04\x01x\x04\x01y");
assert(scan_ldapsearchfilter(buf, buf+100, &f) == 8);
assert(f && f->type==EQUAL && f->ava.desc.l==1 && f->ava.desc.s[0]=='x' &&
f->ava.value.l==1 && f->ava.value.s[0]=='y');
free_ldapsearchfilter(f); f=0;
// this also achieves 100% coverge of scan_ldapava:
buf[1]=5; assert(scan_ldapsearchfilter(buf, buf+100, &f) == 0); // fail08, fail 2 in scan_ldapava
buf[1]=2; assert(scan_ldapsearchfilter(buf, buf+100, &f) == 0); // fail08, fail 1 in scan_ldapava
// type 5, greaterOrEqual
strcpy(buf,"\xa5\x06\x04\x01x\x04\x01y");
assert(scan_ldapsearchfilter(buf, buf+100, &f) == 8);
assert(f && f->type==GREATEQUAL && f->ava.desc.l==1 && f->ava.desc.s[0]=='x' &&
f->ava.value.l==1 && f->ava.value.s[0]=='y');
free_ldapsearchfilter(f); f=0;
// type 6, lessOrEqual
strcpy(buf,"\xa6\x06\x04\x01x\x04\x01y");
assert(scan_ldapsearchfilter(buf, buf+100, &f) == 8);
assert(f && f->type==LESSEQUAL && f->ava.desc.l==1 && f->ava.desc.s[0]=='x' &&
f->ava.value.l==1 && f->ava.value.s[0]=='y');
free_ldapsearchfilter(f); f=0;
// type 8, approxMatch
strcpy(buf,"\xa8\x06\x04\x01x\x04\x01y");
assert(scan_ldapsearchfilter(buf, buf+100, &f) == 8);
assert(f && f->type==APPROX && f->ava.desc.l==1 && f->ava.desc.s[0]=='x' &&
f->ava.value.l==1 && f->ava.value.s[0]=='y');
free_ldapsearchfilter(f); f=0;
// type 4, substrings
strcpy(buf,"\xa4\x0e\x04\5danke\x30\x05\x82\3red"); // "(danke=*red)"
assert(scan_ldapsearchfilter(buf, buf+100, &f) == 16);
assert(f && f->type==SUBSTRING && f->ava.desc.l==5 && !memcmp(f->ava.desc.s,"danke",5) &&
f->substrings->substrtype==suffix && f->substrings->s.l==3 && !memcmp(f->substrings->s.s,"red",3) &&
f->substrings->next==0);
free_ldapsearchfilter(f); f=0;
callocfail=2;
assert(scan_ldapsearchfilter(buf, buf+100, &f) == 0); // fail11
callocfail=(size_t)-1;
buf[12]=4; assert(scan_ldapsearchfilter(buf, buf+100, &f) == 0); // fail12
buf[10]++; assert(scan_ldapsearchfilter(buf, buf+100, &f) == 0); // fail10
buf[3]=100; assert(scan_ldapsearchfilter(buf, buf+100, &f) == 0); // fail09
return 0;
}
#endif