diff --git a/Makefile b/Makefile index f58f90f..11645f2 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,10 @@ scan_asn1BOOLEAN.o ldap.a: scan_ldapmessage.o fmt_ldapmessage.o fmt_ldapbindrequest.o \ scan_ldapbindrequest.o fmt_ldapbindresponse.o scan_ldapbindresponse.o \ scan_ldapstring.o scan_ldapsearchfilter.o scan_ldapsearchrequest.o \ -freefilter.o freeava.o scan_ldapava.o +freefilter.o freeava.o scan_ldapava.o fmt_ldapsearchresultentry.o \ +fmt_ldapstring.o + +ldif.a: ldif_parse.o DIET=diet -Os CC=gcc @@ -34,8 +37,7 @@ t1: strduptab.o strstorage.o t2: ldap.a asn1.a bindrequest tinyldap ldapclient: ldap.a asn1.a -strduptab.o: strduptab.c - gcc $(CFLAGS) -c $^ +tinyldap: ldif.a .PHONY: clean tar clean: @@ -50,11 +52,34 @@ fmt_asn1length.o: fmt_asn1length.c asn1.h fmt_asn1string.o: fmt_asn1string.c asn1.h fmt_asn1tag.o: fmt_asn1tag.c asn1.h fmt_asn1transparent.o: fmt_asn1transparent.c asn1.h +fmt_ldapbindrequest.o: fmt_ldapbindrequest.c asn1.h ldap.h +fmt_ldapbindresponse.o: fmt_ldapbindresponse.c asn1.h ldap.h +fmt_ldapmessage.o: fmt_ldapmessage.c asn1.h ldap.h + +scan_asn1BOOLEAN.o: scan_asn1BOOLEAN.c asn1.h +scan_asn1ENUMERATED.o: scan_asn1ENUMERATED.c asn1.h +scan_asn1INTEGER.o: scan_asn1INTEGER.c asn1.h +scan_asn1SEQUENCE.o: scan_asn1SEQUENCE.c asn1.h +scan_asn1STRING.o: scan_asn1STRING.c asn1.h scan_asn1int.o: scan_asn1int.c asn1.h scan_asn1length.o: scan_asn1length.c asn1.h scan_asn1string.o: scan_asn1string.c asn1.h scan_asn1tag.o: scan_asn1tag.c asn1.h -scan_asn1INTEGER.o: scan_asn1INTEGER.c asn1.h -scan_asn1STRING.o: scan_asn1STRING.c asn1.h -scan_asn1SEQUENCE.o: scan_asn1SEQUENCE.c asn1.h +scan_ldapava.o: scan_ldapava.c asn1.h ldap.h +scan_ldapbindrequest.o: scan_ldapbindrequest.c asn1.h ldap.h +scan_ldapbindresponse.o: scan_ldapbindresponse.c asn1.h ldap.h scan_ldapmessage.o: scan_ldapmessage.c asn1.h ldap.h +scan_ldapsearchfilter.o: scan_ldapsearchfilter.c asn1.h ldap.h +scan_ldapsearchrequest.o: scan_ldapsearchrequest.c asn1.h ldap.h +scan_ldapstring.o: scan_ldapstring.c + +ldif_parse.o: ldif_parse.c strduptab.h strstorage.h ldif.h + +tinyldap.o: tinyldap.c ldap.h ldif.h +ldapclient.o: ldapclient.c ldap.h +bindrequest.o: bindrequest.c ldap.h + +strduptab.o: strduptab.c strduptab.h strstorage.h +strstorage.o: strstorage.c strstorage.h +freeava.o: freeava.c ldap.h +freefilter.o: freefilter.c ldap.h diff --git a/fmt_ldapsearchresultentry.c b/fmt_ldapsearchresultentry.c new file mode 100644 index 0000000..0c91cc8 --- /dev/null +++ b/fmt_ldapsearchresultentry.c @@ -0,0 +1,37 @@ +#include "asn1.h" +#include "ldap.h" + +int fmt_ldappal(char* dest,struct PartialAttributeList* pal) { + int l,sum; + if (pal) return 0; + sum=fmt_ldapstring(dest,&pal->type); + if (dest) dest+=sum; + { + long avlen=0; + struct AttributeDescriptionList* x=pal->values; + while (x) { + avlen+=fmt_asn1OCTETSTRING(0,0,x->a.l); + avlen+=x->a.l; + x=x->next; + } + l=fmt_asn1SEQUENCE(dest,avlen); + if (!dest) return sum+l+avlen; + dest+=l; + x=pal->values; + while (x) { + dest+=fmt_asn1OCTETSTRING(dest,x->a.s,x->a.l); + x=x->next; + } + return sum+l+avlen; + } +} + +int fmt_ldapsearchresultentry(char* dest,struct SearchResultEntry* sre) { + int l,sum=0; + sum=fmt_ldapstring(dest,&sre->objectName); + if (dest) dest+=sum; + l=fmt_asn1SEQUENCE(dest,fmt_ldappal(0,sre->attributes)); + sum+=l; if (dest) dest+=l; + l=fmt_ldappal(dest,sre->attributes); + return sum+l; +} diff --git a/fmt_ldapstring.c b/fmt_ldapstring.c new file mode 100644 index 0000000..1058b84 --- /dev/null +++ b/fmt_ldapstring.c @@ -0,0 +1,6 @@ +#include "asn1.h" +#include "ldap.h" + +int fmt_ldapstring(char* dest,struct string* s) { + return fmt_asn1OCTETSTRING(dest,s->s,s->l); +} diff --git a/freeava.c b/freeava.c index 5295fbe..fb6530e 100644 --- a/freeava.c +++ b/freeava.c @@ -1,9 +1,9 @@ #include #include "ldap.h" -void freeava(struct AttributeList* a) { +void freeava(struct AttributeDescriptionList* a) { while (a) { - struct AttributeList* tmp=a->next; + struct AttributeDescriptionList* tmp=a->next; free(a); a=tmp; } diff --git a/freefilter.c b/freefilter.c index 3a661b8..a57e08b 100644 --- a/freefilter.c +++ b/freefilter.c @@ -3,11 +3,7 @@ void freefilter(struct Filter* f) { if (f) { - while (f->a) { - struct AttributeList* a=f->a->next; - free(f->a); - f->a=a; - } + freeava(f->a); if (f->x) freefilter(f->x); if (f->next) freefilter(f->next); free(f); diff --git a/ldap.h b/ldap.h index 3c69780..c7718a6 100644 --- a/ldap.h +++ b/ldap.h @@ -1,3 +1,5 @@ +#ifndef _LDAP_H +#define _LDAP_H struct string { long l; @@ -8,9 +10,15 @@ struct AttributeValueAssertion { struct string desc, value; }; -struct AttributeList { +struct AttributeDescriptionList { struct string a; - struct AttributeList *next; + struct AttributeDescriptionList *next; +}; + +struct PartialAttributeList { + struct string type; + struct AttributeDescriptionList* values; + struct PartialAttributeList* next; }; struct Filter { @@ -18,7 +26,7 @@ struct Filter { AND=0, OR=1, NOT=2, EQUAL=3, SUBSTRING=4, GREATEQUAL=5, LESSEQUAL=6, PRESENT=7, APPROX=8, EXTENSIBLE=9 } type; struct AttributeValueAssertion ava; - struct AttributeList *a; + struct AttributeDescriptionList *a; enum { PREFIX=0, ANY=1, SUFFIX=2 } substrtype; @@ -26,7 +34,7 @@ struct Filter { }; struct SearchRequest { - struct string LDAPDN; + struct string baseObject; enum { baseObject=0, singleLevel=1, wholeSubtree=2 } scope; enum { neverDerefAliases=0, @@ -37,7 +45,12 @@ struct SearchRequest { unsigned long sizeLimit, timeLimit, typesOnly; struct Filter* filter; /* really an AttributeDescriptionList, but the types are equivalent: */ - struct AttributeList* attributes; + struct AttributeDescriptionList* attributes; +}; + +struct SearchResultEntry { + struct string objectName; + struct PartialAttributeList* attributes; }; enum ldapops { @@ -50,11 +63,12 @@ enum ldapops { ModifyDNRequest=12, ModifyDNResponse=13, CompareRequest=14, CompareResponse=15, AbandonRequest=16, - ExtendedRequest=23 /* das ist doch kein Zufall?! */, ExtendedResponse=24 + ExtendedRequest=23 /* coincidence? I think not. */, + ExtendedResponse=24 }; void freefilter(struct Filter* f); -void freeava(struct AttributeList* a); +void freeava(struct AttributeDescriptionList* a); int scan_ldapstring(const char* src,const char* max,struct string* s); int scan_ldapmessage(const char* src,const char* max, @@ -67,9 +81,16 @@ int scan_ldapbindresponse(const char* src,const char* max, int scan_ldapava(const char* src,const char* max,struct AttributeValueAssertion* a); int scan_ldapsearchfilter(const char* src,const char* max,struct Filter** f); int scan_ldapsearchrequest(const char* src,const char* max,struct SearchRequest* s); +int scan_ldapsearchresultentry(const char* src,const char* max,struct SearchResultEntry* sre); +int fmt_ldapstring(char* dest,struct string* s); int fmt_ldapmessage(char* dest,long messageid,long op,long len); int fmt_ldapbindrequest(char* dest,long version,char* name,char* simple); int fmt_ldapbindresponse(char* dest,long result,char* matcheddn, char* errormessage,char* referral); int fmt_ldapsearchfilter(char* dest,struct Filter* f); +int fmt_ldapsearchrequest(char* dest,struct SearchRequest* s); +int fmt_ldapsearchresultentry(char* dest,struct SearchResultEntry* sre); +int fmt_ldapsearchresultdone(char* dest,long result,char* matcheddn,char* errormessage,char* referral); + +#endif diff --git a/ldif.h b/ldif.h new file mode 100644 index 0000000..d38a8a8 --- /dev/null +++ b/ldif.h @@ -0,0 +1,21 @@ +#include + +/* how many attributes do we allow per record? */ +#define ATTRIBS 8 + +struct attribute { + const char* name,* value; +}; + +struct ldaprec { + const char* dn,* mail,* sn,* cn; /* most often encountered records */ + int n; /* number of attributes */ + struct attribute a[ATTRIBS]; + struct ldaprec* next; +}; + +extern const char* dn,* mail,* sn,* cn,* objectClass; +extern struct ldaprec *first; + +int parse_ldif(const char* filename); +void free_ldif(); diff --git a/ldif_parse.c b/ldif_parse.c new file mode 100644 index 0000000..48d2cbc --- /dev/null +++ b/ldif_parse.c @@ -0,0 +1,107 @@ +#include +#include +#include +#include +#include +#include "strduptab.h" +#include "strstorage.h" +#include "str.h" +#include "ldif.h" + +static struct stringduptable tags; +static struct stringduptable classes; + +const char* dn,* mail,* sn,* cn,* objectClass; + +static int parserec(buffer* b, struct ldaprec** l) { + char buf[8192]; + int n,i,eof=0,ofs=0; + if (!(*l=malloc(sizeof(struct ldaprec)))) return 2; + do { + const char* tmp,* val; + n=ofs+buffer_get_token(b,buf+ofs,8192-ofs,":",1); + i=scan_whitenskip(buf,n); + buf[n]=0; + if (!(tmp=strduptab_add(&tags,buf+i))) { +nomem: + buffer_putsflush(buffer_2,"out of memory!\n"); + return 1; + } + n=buffer_get_token(b,buf,8192,"\n",1); + if (n==0) break; + i=scan_whitenskip(buf,n); +lookagain: + { + char c; + switch (buffer_getc(b,&c)) { + case 0: eof=1; break; + case -1: buffer_putsflush(buffer_2,"read error!\n"); return 1; + } + if (c==' ') { /* continuation */ +// puts("continuation!"); + n+=buffer_get_token(b,buf+n,8192-n,"\n",1); + goto lookagain; + } else if (c=='\n') { +#if 1 + struct ldaprec* m=malloc(sizeof(struct ldaprec)); + if (!m) return 2; + (*l)->next=m; + m->n=0; m->dn=m->mail=m->sn=m->cn=0; m->next=0; + ofs=0; + l=&((*l)->next); +#else + struct ldaprec* m=malloc(sizeof(struct ldaprec)); + if (!m) return 2; + m->next=*l; + *l=m; + m->n=0; m->dn=m->mail=m->sn=m->cn=0; + ofs=0; +#endif + } else { + ofs=1; + buf[0]=c; + } + } + buf[n]=0; + if (tmp==objectClass) { + if (!(val=strduptab_add(&classes,buf+i))) goto nomem; + } else + if (!(val=strstorage_add(buf+i,n-i+1))) goto nomem; + if (tmp==dn) (*l)->dn=val; else + if (tmp==mail) (*l)->mail=val; else + if (tmp==sn) (*l)->sn=val; else + if (tmp==cn) (*l)->cn=val; else { + if ((*l)->na[(*l)->n].name=tmp; + (*l)->a[(*l)->n].value=val; + ++(*l)->n; + } + } + } while (!eof); + if (!(*l)->dn) { + struct ldaprec* m=(*l)->next; + free((*l)); + (*l)=m; + } + return 0; +} + +struct ldaprec *first=0; + +int ldif_parse(const char* filename) { + char buf[4096]; + int fd=open_read(filename); + buffer in=BUFFER_INIT(read,fd,buf,sizeof buf); + if (fd<0) return 1; + dn=strduptab_add(&tags,"dn"); + mail=strduptab_add(&tags,"mail"); + sn=strduptab_add(&tags,"sn"); + cn=strduptab_add(&tags,"cn"); + objectClass=strduptab_add(&tags,"objectClass"); + { + int res=parserec(&in,&first); + close(fd); + return res; + } +} + diff --git a/scan_ldapmessage.c b/scan_ldapmessage.c index 12dec56..27a740b 100644 --- a/scan_ldapmessage.c +++ b/scan_ldapmessage.c @@ -11,7 +11,7 @@ int scan_ldapmessage(const char* src,const char* max, enum asn1_tagclass tc; enum asn1_tagtype tt; if (!(tmp=scan_asn1tag(src+res,max,&tc,&tt,op))) goto error; - if (tc!=APPLICATION || tt!=CONSTRUCTED) goto error; + if (tc!=APPLICATION) goto error; res+=tmp; if (!(tmp=scan_asn1length(src+res,max,len))) goto error; res+=tmp; diff --git a/scan_ldapsearchrequest.c b/scan_ldapsearchrequest.c index 0ecef18..c8f7ce8 100644 --- a/scan_ldapsearchrequest.c +++ b/scan_ldapsearchrequest.c @@ -6,7 +6,7 @@ int scan_ldapsearchrequest(const char* src,const char* max, struct SearchRequest* s) { int res,tmp; unsigned long etmp; - if (!(res=scan_ldapstring(src,max,&s->LDAPDN))) goto error; + if (!(res=scan_ldapstring(src,max,&s->baseObject))) goto error; if (!(tmp=scan_asn1ENUMERATED(src+res,max,&etmp))) goto error; if (etmp>2) goto error; s->scope=etmp; res+=tmp; if (!(tmp=scan_asn1ENUMERATED(src+res,max,&etmp))) goto error; @@ -27,12 +27,12 @@ int scan_ldapsearchrequest(const char* src,const char* max, { const char* nmax=src+res+etmp; //#define nmax max - struct AttributeList** a=&s->attributes; + struct AttributeDescriptionList** a=&s->attributes; if (nmax>max) goto error; for (;;) { if (src+res>nmax) goto error; if (src+res==nmax) break; - if (!*a) *a=malloc(sizeof(struct AttributeList)); + if (!*a) *a=malloc(sizeof(struct AttributeDescriptionList)); if (!*a) goto error; (*a)->next=0; if (!(tmp=scan_ldapstring(src+res,nmax,&(*a)->a))) goto error; diff --git a/t2.c b/t2.c index de996d6..780c8e9 100644 --- a/t2.c +++ b/t2.c @@ -8,7 +8,7 @@ void printava(struct AttributeValueAssertion* a,const char* rel) { printf("[%.*s %s %.*s]",(int)a->desc.l,a->desc.s,rel,(int)a->value.l,a->value.s); } -void printal(struct AttributeList* a) { +void printal(struct AttributeDescriptionList* a) { while (a) { printf("%.*s",(int)a->a.l,a->a.s); a=a->next; @@ -73,6 +73,7 @@ int main(int argc,char* argv[]) { printf("message id %lu, op %lu, len %lu\n",messageid,op,len); switch (op) { case BindRequest: + puts(" >> BindRequest <<"); { long version,method; struct string name; @@ -89,16 +90,23 @@ int main(int argc,char* argv[]) { break; } case SearchRequest: + puts(" >> SearchRequest <<"); { struct SearchRequest br; - printf("scan_ldapsearchrequest %d\n",res=scan_ldapsearchrequest(ldapsequence+done+res,ldapsequence+size,&br)); - if (res) { - printf("LDAPDN: \"%.*s\"\n",(int)br.LDAPDN.l,br.LDAPDN.s); + int tmp; + printf("scan_ldapsearchrequest %d\n",tmp=scan_ldapsearchrequest(ldapsequence+done+res,ldapsequence+size,&br)); + if (tmp) { + printf("baseObject: \"%.*s\"\n",(int)br.baseObject.l,br.baseObject.s); printfilter(br.filter); printf("\n"); } printal(br.attributes); break; } + case UnbindRequest: + puts(" >> UnbindRequest <<"); + break; + default: + puts(" >> unklar << ;)"); } done+=len+res; } diff --git a/tinyldap.c b/tinyldap.c index b501d84..f94fd20 100644 --- a/tinyldap.c +++ b/tinyldap.c @@ -2,6 +2,7 @@ #include "byte.h" #include "buffer.h" #include "ldap.h" +#include "ldif.h" #define BUFSIZE 8192