diff --git a/Makefile b/Makefile index be81401..3721671 100644 --- a/Makefile +++ b/Makefile @@ -23,7 +23,7 @@ matchprefix.o matchcasestring.o matchcaseprefix.o \ scan_ldapmodifyrequest.o scan_ldapaddrequest.o bstrlen.o bstrfirst.o \ bstrstart.o free_ldapadl.o free_ldappal.o free_ldapsearchfilter.o \ scan_ldapsearchfilterstring.o free_ldapsearchresultentry.o \ -fmt_ldapsearchfilterstring.o +fmt_ldapsearchfilterstring.o ldap_match_sre.o ldif.a: ldif_parse.o ldap_match_mapped.o @@ -146,3 +146,5 @@ scan_ldapsearchfilterstring.o: scan_ldapsearchfilterstring.c ldap.h scan_ldapsearchrequest.o: scan_ldapsearchrequest.c asn1.h ldap.h scan_ldapsearchresultentry.o: scan_ldapsearchresultentry.c asn1.h ldap.h scan_ldapstring.o: scan_ldapstring.c asn1.h ldap.h + +ldap_match_sre.o: ldap_match_sre.c ldap.h diff --git a/acl.c b/acl.c index 7e8452a..b7edae1 100644 --- a/acl.c +++ b/acl.c @@ -167,7 +167,7 @@ int parseaclpermissions(buffer* in,struct acl* a) { case '-': s=&a->maynot; break; case 'r': *s|=acl_read; break; case 'w': *s|=acl_write; break; - case 'a': *s|=acl_auth; break; + case 'a': *s|=acl_add; break; case 'd': *s|=acl_delete; break; case 'R': *s|=acl_rendn; break; case ' ': case '\t': case '\n': break; diff --git a/acl.h b/acl.h index 57f8689..951a3a6 100644 --- a/acl.h +++ b/acl.h @@ -2,7 +2,7 @@ enum { acl_read = 1, acl_write = 2, - acl_auth = 4, + acl_add = 4, acl_delete = 8, acl_rendn = 16, }; diff --git a/ldap.h b/ldap.h index 2ca2b39..f3da7aa 100644 --- a/ldap.h +++ b/ldap.h @@ -107,6 +107,47 @@ enum ldapops { ExtendedResponse=24 }; +enum ldaperrors { + success=0, + operationsError=1, + protocolError=2, + timeLimitExceeded=3, + sizeLimitExceeded=4, + compareFalse=5, + compareTrue=6, + authMethodNotSupported=7, + strongAuthRequired=8, + referral=10, + adminLimitExceeded=11, + unavailableCriticalExtension=12, + confidentialityRequired=13, + saslBindInProgress=14, + noSuchAttribute=16, + undefinedAttributeType=17, + inappropriateMatching=18, + constraintViolation=19, + attributeOrValueExists=20, + invalidAttributeSyntax=21, + noSuchObject=32, + aliasProblem=33, + invalidDNSyntax=34, + aliasDereferencingProblem=36, + inappropriateAuthentication=48, + invalidCredentials=49, + insufficientAccessRights=50, + busy=51, + unavailable=52, + unwillingToPerform=53, + loopDetect=54, + namingViolation=64, + objectClassViolation=65, + notAllowedOnNonLeaf=66, + notAllowedOnRDN=67, + entryAlreadyExists=68, + objectClassModsProhibited=69, + affectsMultipleDSAs=71, +}; + void freefilter(struct Filter* f); void freeava(struct AttributeDescriptionList* a); void freepal(struct PartialAttributeList* a); @@ -161,5 +202,7 @@ void free_ldapaddrequest(struct AddRequest * a); /* does not free e itself */ void free_ldapsearchresultentry(struct SearchResultEntry* e); +int ldap_matchfilter_sre(struct SearchResultEntry* sre,struct Filter* f); + #endif diff --git a/ldap_match_mapped.c b/ldap_match_mapped.c index 537cd90..d9b76dc 100644 --- a/ldap_match_mapped.c +++ b/ldap_match_mapped.c @@ -152,7 +152,7 @@ int ldap_matchfilter_mapped(uint32 ofs,struct Filter* f) { } break; default: - write(2,"unsupported query type\n",4); + write(2,"unsupported query type\n",23); return 0; } return 1; diff --git a/ldap_match_sre.c b/ldap_match_sre.c new file mode 100644 index 0000000..c7b5750 --- /dev/null +++ b/ldap_match_sre.c @@ -0,0 +1,166 @@ +#include +#include "ldap.h" +#include "byte.h" +#include "case.h" +#include + +static int matchcasestr(struct string* a,struct string* b) { + unsigned long l=a->l; + unsigned long r; + if (b->ll; + 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->ll; + 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->ls.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 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; iobjectName.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); +} diff --git a/scan_ldapaddrequest.c b/scan_ldapaddrequest.c index 58dc169..dff64f3 100644 --- a/scan_ldapaddrequest.c +++ b/scan_ldapaddrequest.c @@ -2,6 +2,7 @@ #include "asn1.h" #include "ldap.h" #include "buffer.h" +#include "byte.h" #if 0 AddRequest ::= [APPLICATION 8] SEQUENCE { @@ -19,7 +20,7 @@ unsigned int scan_ldapaddrequest(const char* src,const char* max,struct AddReque unsigned int res,tmp; unsigned long oslen; /* outer sequence length */ struct Addition* last=0; - a->a.next=0; + byte_zero(a,sizeof(*a)); if (!(res=scan_ldapstring(src,max,&a->entry))) goto error; if (!(tmp=scan_asn1SEQUENCE(src+res,max,&oslen))) goto error; res+=tmp; @@ -30,19 +31,19 @@ unsigned int scan_ldapaddrequest(const char* src,const char* max,struct AddReque unsigned long islen; if (last) { struct Addition* cur; - if (!(cur=malloc(sizeof(struct Addition)))) + if (!(cur=malloc(sizeof(struct Addition)))) goto error; - last->next=cur; + last->next=cur; last=cur; } else { last=&a->a; } last->next=0; - if (!(tmp=scan_asn1SEQUENCE(src+res,max,&islen))) + if (!(tmp=scan_asn1SEQUENCE(src+res,max,&islen))) goto error; res+=tmp; /* scan AttributeDescription: */ - if (!(tmp=scan_ldapstring(src+res,max,&last->AttributeDescription))) + if (!(tmp=scan_ldapstring(src+res,max,&last->AttributeDescription))) goto error; res+=tmp; @@ -69,7 +70,7 @@ unsigned int scan_ldapaddrequest(const char* src,const char* max,struct AddReque ilast=&last->vals; } ilast->next=0; - if (!(tmp=scan_ldapstring(src+res,max,&ilast->a))) + if (!(tmp=scan_ldapstring(src+res,max,&ilast->a))) goto error; res+=tmp; } diff --git a/tinyldap.c b/tinyldap.c index 53b9e54..697fafa 100644 --- a/tinyldap.c +++ b/tinyldap.c @@ -26,6 +26,8 @@ #include "uint16.h" #include "acl.h" #include +#include +#include #ifdef DEBUG #include @@ -456,40 +458,71 @@ static long findrec(uint32 dat) { return -1; } +#define RANGECHECK 1 + +struct bitfield { + unsigned long* bits; +#ifdef RANGECHECK + unsigned long n; +#endif + unsigned long first,last; +}; + /* basic bit-set support: set all bits to 0 */ -static inline void emptyset(unsigned long* r) { +static inline void emptyset(struct bitfield* b) { unsigned long i; - for (i=0; in= +#endif + b->first=record_count; + b->last=0; + for (i=0; ibits[i]=0; } /* basic bit-set support: set all bits to 1 */ -static inline void fillset(unsigned long* r) { +static inline void fillset(struct bitfield* b) { unsigned long i; - for (i=0; ifirst=0; +#ifdef RANGECHECK + b->n= +#endif + b->last=record_count; + for (i=0; ibits[i]=(unsigned long)-1; } /* basic bit-set support: set one bit to 1 */ -static inline void setbit(unsigned long* r,unsigned long bit) { - r[bit/(8*sizeof(long))] |= (1<<(bit&(8*sizeof(long)-1))); +static inline void setbit(struct bitfield* b,unsigned long bit) { +#ifdef RANGECHECK + if (bit<=b->n) { +#endif + if (bitfirst) b->first=bit; + if (bit>b->last) b->last=bit; + b->bits[bit/(8*sizeof(long))] |= (1<<(bit&(8*sizeof(long)-1))); +#ifdef RANGECHECK + } +#endif } /* basic bit-set support: see if given bit is set */ -static inline int isset(unsigned long* r,unsigned long bit) { - return r[bit/(8*sizeof(long))] & (1<<(bit&(8*sizeof(long)-1))); +static inline int isset(struct bitfield* b,unsigned long bit) { +#ifdef RANGECHECK + if (bit>b->n) return 0; +#endif + return b->bits[bit/(8*sizeof(long))] & (1<<(bit&(8*sizeof(long)-1))); } /* use index (sorted table of offsets to records) to do a binary search * for all records that match the value in s. Set the corresponding * bits to 1 in bitfield. */ static void tagmatches(uint32* index,unsigned int elements,struct string* s, - unsigned long* bitfield,int (*match)(struct string* s,const char* c), + struct bitfield* b,int (*match)(struct string* s,const char* c), uint32 index_type,enum FilterType ft) { uint32 bottom=0; uint32 top=elements; uint32 mid,k,m; long rec; rec=0; - emptyset(bitfield); + emptyset(b); while ((top>=bottom)) { int l; @@ -523,7 +556,7 @@ static void tagmatches(uint32* index,unsigned int elements,struct string* s, return; } if (rec>=0) - setbit(bitfield,rec); + setbit(b,rec); /* there may be multiple matches. * Look before and after mid, too */ for (k=mid-1; k>0; --k) { @@ -534,7 +567,7 @@ static void tagmatches(uint32* index,unsigned int elements,struct string* s, else if (index_type==1) rec=uint32_read((char*)(&index[k+elements])); if (rec>=0) - setbit(bitfield,rec); + setbit(b,rec); } else break; } for (k=mid+1; k=0) - setbit(bitfield,rec); + setbit(b,rec); } else break; } return; @@ -575,7 +608,7 @@ static void tagmatches(uint32* index,unsigned int elements,struct string* s, else if (index_type==1) rec=uint32_read((char*)(&index[k+elements])); if (rec>=0) - setbit(bitfield,rec); + setbit(b,rec); } } else if (ft==LESSEQUAL) { for (k=0; k<=mid; ++k) { @@ -585,7 +618,7 @@ static void tagmatches(uint32* index,unsigned int elements,struct string* s, else if (index_type==1) rec=uint32_read((char*)(&index[k+elements])); if (rec>=0) - setbit(bitfield,rec); + setbit(b,rec); } } } @@ -619,7 +652,7 @@ uint32 hash_tolower(const unsigned char* c,unsigned long keylen) { * be used if it only helps eliminate some of the possible matches (for * example an AND query where only one of the involved attributes has an * index). */ -static int useindex(struct Filter* f,unsigned long* bitfield) { +static int useindex(struct Filter* f,struct bitfield* b) { struct Filter* y=f->x; if (!f) return 1; @@ -639,12 +672,12 @@ static int useindex(struct Filter* f,unsigned long* bitfield) { if (hashofs==0) return 1; if (hashofstype) { case AND: { - unsigned long* tmp=alloca(record_set_length*sizeof(unsigned long)); + struct bitfield tmp; int ok=0; - fillset(bitfield); + tmp.bits=alloca(record_set_length*sizeof(unsigned long)); + if (y) { + useindex(y,b); + y=y->next; + } else + fillset(b); while (y) { - if (useindex(y,tmp)) { + if (useindex(y,&tmp)) { unsigned int i; for (i=0; ibits[i] &= tmp.bits[i]; + if (tmp.first>b->first) b->first=tmp.first; + if (tmp.lastlast) b->last=tmp.last; ok=1; } y=y->next; @@ -674,14 +714,21 @@ static int useindex(struct Filter* f,unsigned long* bitfield) { } case OR: { - unsigned long* tmp=alloca(record_set_length*sizeof(unsigned long)); + struct bitfield tmp; int ok=1; - emptyset(bitfield); + tmp.bits=alloca(record_set_length*sizeof(unsigned long)); + if (y) { + useindex(y,b); + y=y->next; + } else + emptyset(b); while (y) { - if (useindex(y,tmp)) { + if (useindex(y,&tmp)) { unsigned int i; for (i=0; ibits[i] |= tmp.bits[i]; + if (tmp.firstfirst) b->first=tmp.first; + if (tmp.last>b->last) b->last=tmp.last; } else ok=0; y=y->next; @@ -704,7 +751,7 @@ static int useindex(struct Filter* f,unsigned long* bitfield) { indexed_attribute=uint32_read(map+ofs+8); if (index_type<=1) if (!matchstring(&f->ava.desc,map+indexed_attribute)) { - tagmatches((uint32*)(map+ofs+12),(next-ofs-12)/(4<substrings->s,bitfield, + tagmatches((uint32*)(map+ofs+12),(next-ofs-12)/(4<substrings->s,b, f->attrflag&1?matchcaseprefix:matchprefix,index_type,f->type); return 1; } @@ -719,10 +766,10 @@ static int useindex(struct Filter* f,unsigned long* bitfield) { * we pretend it's indexed */ char* x=map+5*4+size_of_string_table+attribute_count*8; unsigned long i; - emptyset(bitfield); + emptyset(b); for (i=0; iattrofs)) - setbit(bitfield,i); + setbit(b,i); x+=uint32_read(x)*8; } return 1; @@ -739,7 +786,7 @@ static int useindex(struct Filter* f,unsigned long* bitfield) { indexed_attribute=uint32_read(map+ofs+8); if (index_type<=1) if (!matchstring(&f->ava.desc,map+indexed_attribute)) { - tagmatches((uint32*)(map+ofs+12),(next-ofs-12)/(4<ava.value,bitfield, + tagmatches((uint32*)(map+ofs+12),(next-ofs-12)/(4<ava.value,b, f->attrflag&1?matchcasestring:matchstring,index_type,f->type); return 1; } @@ -763,6 +810,49 @@ static int useindex(struct Filter* f,unsigned long* bitfield) { |_| |___/ |___/ #endif +static int checkacl(uint32 ofs,uint32 attrofs,unsigned long operation,struct SearchResultEntry* sre) { + uint32_t j; + for (j=0; jsubject]) continue; + /* does the ACL even apply to the wanted operation? */ + if ((Acls[j]->may | Acls[j]->maynot) & operation) { + uint32 k; + if (acl_ec_subjects[filters+Acls[j]->object]==-1) continue; + if (acl_ec_subjects[filters+Acls[j]->object]==0) { + int match=0; + if (Filters[Acls[j]->object]==(struct Filter*)Any) + match=1; + else if (Filters[Acls[j]->object]==(struct Filter*)Self) + match=(ofs==authenticated_as); + else if (ofs) + match=ldap_matchfilter_mapped(ofs,Filters[Acls[j]->object]); + else if (sre) + match=ldap_matchfilter_sre(sre,Filters[Acls[j]->object]); + else + match=-1; + if (match) + acl_ec_subjects[filters+Acls[j]->object]=1; + else { + acl_ec_subjects[filters+Acls[j]->object]=-1; + continue; + } + } + for (k=0; kattrs; ++k) { +/* if (Acls[j]->Attrs[k]==any_ofs || !matchstring(&adl->a,map+Acls[j]->Attrs[k])) { */ + if (Acls[j]->Attrs[k]==any_ofs || attrofs==Acls[j]->Attrs[k]) { + if (Acls[j]->may&operation) + return 1; + else + return -1; + break; + } + } + } + } + return 0; +} + /* this routine is called for each record matched the query. It basically puts together * an answer LDAP message from the record and the list of attributes the other side said * it wanted to have. */ @@ -799,8 +889,11 @@ static void answerwith(uint32 ofs,struct SearchRequest* sr,long messageid,int ou if (acls) byte_zero(acl_ec_subjects+filters,filters); + if (acls && checkacl(ofs,dn_ofs,acl_read,0)!=1) return; + sre.objectName.l=bstrlen(sre.objectName.s=map+uint32_read(map+ofs+8)); sre.attributes=0; + /* now go through list of requested attributes */ { struct AttributeDescriptionList* adl=sr->attributes; @@ -826,52 +919,8 @@ static void answerwith(uint32 ofs,struct SearchRequest* sr,long messageid,int ou while (adl) { const char* val=0; uint32 i=2,j; - int ok=acls?0:1; - for (j=0; jsubject]) continue; - /* does the ACL even apply to read operations? */ - if ((Acls[j]->may | Acls[j]->maynot) & acl_read) { - uint32 k; - if (acl_ec_subjects[filters+Acls[j]->object]==-1) continue; - if (acl_ec_subjects[filters+Acls[j]->object]==0) { - int match=0; - if (Filters[Acls[j]->object]==(struct Filter*)Any) - match=1; - else if (Filters[Acls[j]->object]==(struct Filter*)Self) - match=(ofs==authenticated_as); - else - match=(ldap_matchfilter_mapped(ofs,Filters[Acls[j]->object])); - if (match) - acl_ec_subjects[filters+Acls[j]->object]=1; - else { - acl_ec_subjects[filters+Acls[j]->object]=-1; - continue; - } - } - for (k=0; kattrs; ++k) { -/* if (Acls[j]->Attrs[k]==any_ofs || !matchstring(&adl->a,map+Acls[j]->Attrs[k])) { */ - if (Acls[j]->Attrs[k]==any_ofs || adl->attrofs==Acls[j]->Attrs[k]) { - if (Acls[j]->may&acl_read) { -#if 0 - printf("acl %u allowed serving attribute \"%.*s\"\n",j,(int)adl->a.l,adl->a.s); -#endif - ok=1; - } else { -#if 0 - printf("acl %u disallowed serving attribute \"%.*s\"\n",j,(int)adl->a.l,adl->a.s); -#endif - ok=-1; - } - break; - } - } - } - if (ok) break; - } - - if (ok==1) { + if (!acls || checkacl(ofs,adl->attrofs,acl_read,0)==1) { uint32_unpack(map+ofs,&j); #if 0 buffer_puts(buffer_2,"looking for attribute \""); @@ -949,10 +998,79 @@ add_attribute: |___/ |_| #endif +int copystring(struct string* dest,struct string* src) { + dest->s=malloc(src->l+1); + if (!dest->s) return -1; + byte_copy((char*)dest->s,src->l,src->s); + dest->l=src->l; + return 0; +} + +/* deep copy an attribute description list */ +static int copyadl(struct AttributeDescriptionList** dest,struct AttributeDescriptionList* src) { + *dest=0; + while (src) { + if (!(*dest=malloc(sizeof(*src)))) return -1; + byte_zero(*dest,sizeof(*src)); + if (copystring(&(*dest)->a,&src->a)) return -1; + (*dest)->attrofs=src->attrofs; + dest=&(*dest)->next; + src=src->next; + } + return 0; +} + + +#if 0 +/* deep copy a partial attribute list */ +static int copypal(struct PartialAttributeList** dest,struct PartialAttributeList* src) { + *dest=0; + while (src) { + if (!(*dest=malloc(sizeof(**dest)))) return -1; + byte_zero(*dest,sizeof(**dest)); + if (copystring(&(*dest)->type,&src->type) || + copyadl(&(*dest)->values,src->values)) return -1; + dest=&(*dest)->next; + src=src->next; + } + return 0; +} +#endif + +static int ar2sreh1(struct PartialAttributeList** dest,struct Addition* src) { + *dest=0; + while (src) { + if (!(*dest=malloc(sizeof(**dest)))) return -1; + byte_zero(*dest,sizeof(**dest)); + if (copystring(&(*dest)->type,&src->AttributeDescription) || + copyadl(&(*dest)->values,&src->vals)) return -1; + dest=&(*dest)->next; + src=src->next; + } + return 0; +} + +int addreq2sre(struct SearchResultEntry* sre,struct AddRequest* ar) { + byte_zero(sre,sizeof(*sre)); + if (copystring(&sre->objectName,&ar->entry)) goto allocfailed; + if (!(sre->attributes=malloc(sizeof(*sre->attributes)))) goto allocfailed; + if (ar2sreh1(&sre->attributes,&ar->a)) goto allocfailed; + return 0; +allocfailed: + free_ldapsearchresultentry(sre); + return -1; +} + /* This is the high level LDAP handling code. It reads queries from the socket at in, and * then writes the answers to out. Normally in == out, but they are separate here so this * can also be called with in=stdin and out=stdout. */ +int writesretofd(int fd,struct SearchResultEntry* sre) { + unsigned long l=fmt_ldapsearchresultentry(0,sre); + char* c=alloca(l+10); /* you never know */ + return write(fd,c,l)==l?0:-1; +} + /* a standard LDAP session looks like this: * 1. connect to server * 2. send a BindRequest @@ -1023,33 +1141,31 @@ authfailure: { char outbuf[1024]; int s=100; - int len=fmt_ldapbindresponse(outbuf+s,48,"","authentication failure",""); + int len=fmt_ldapbindresponse(outbuf+s,inappropriateAuthentication,"","authentication failure",""); int hlen=fmt_ldapmessage(0,messageid,BindResponse,len); fmt_ldapmessage(outbuf+s-hlen,messageid,BindResponse,len); write(out,outbuf+s-hlen,len+hlen); continue; } } else { - unsigned long* result; + struct bitfield result; unsigned long i,done; - result=alloca(record_set_length*sizeof(unsigned long)); - useindex(&f,result); + result.bits=alloca(record_set_length*sizeof(unsigned long)); + useindex(&f,&result); done=0; - for (i=0; iresult.last) { buffer_putsflush(buffer_2,"no matching dn found, bind failed!\n"); goto authfailure; } done=0; - for (i=0; irecord_count) ni=record_count; for (; i