diff --git a/Makefile b/Makefile index 57cda08..1302447 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,9 @@ fmt_asn1int.o fmt_asn1string.o fmt_asn1transparent.o scan_asn1tag.o \ scan_asn1length.o scan_asn1int.o scan_asn1string.o scan_asn1INTEGER.o \ scan_asn1STRING.o scan_asn1SEQUENCE.o scan_asn1ENUMERATED.o \ scan_asn1BOOLEAN.o scan_asn1rawint.o scan_asn1SET.o fmt_asn1sint.o \ -fmt_asn1sintpayload.o scan_asn1oid.o +fmt_asn1sintpayload.o scan_asn1oid.o scan_asn1BITSTRING.o \ +scan_asn1tagint.o fmt_asn1tagint.o fmt_asn1OID.o scan_asn1generic.o \ +fmt_asn1generic.o ldap.a: scan_ldapmessage.o fmt_ldapmessage.o fmt_ldapbindrequest.o \ scan_ldapbindrequest.o scan_ldapbindresponse.o scan_ldapresult.o \ @@ -111,6 +113,7 @@ fmt_asn1sint.o: fmt_asn1sint.c asn1.h fmt_asn1sintpayload.o: fmt_asn1sintpayload.c asn1.h fmt_asn1string.o: fmt_asn1string.c asn1.h fmt_asn1tag.o: fmt_asn1tag.c asn1.h +fmt_asn1tagint.o: fmt_asn1tagint.c asn1.h fmt_asn1transparent.o: fmt_asn1transparent.c asn1.h fmt_ldapadl.o: fmt_ldapadl.c asn1.h ldap.h fmt_ldapava.o: fmt_ldapava.c asn1.h ldap.h @@ -123,6 +126,8 @@ fmt_ldapsearchfilterstring.o: fmt_ldapsearchfilterstring.c ldap.h fmt_ldapsearchrequest.o: fmt_ldapsearchrequest.c asn1.h ldap.h fmt_ldapsearchresultentry.o: fmt_ldapsearchresultentry.c asn1.h ldap.h fmt_ldapstring.o: fmt_ldapstring.c asn1.h ldap.h +fmt_asn1OID.o: fmt_asn1OID.c asn1.h +fmt_asn1generic.o: fmt_asn1generic.c asn1.h scan_asn1BOOLEAN.o: scan_asn1BOOLEAN.c asn1.h scan_asn1ENUMERATED.o: scan_asn1ENUMERATED.c asn1.h @@ -130,12 +135,14 @@ scan_asn1INTEGER.o: scan_asn1INTEGER.c asn1.h scan_asn1SEQUENCE.o: scan_asn1SEQUENCE.c asn1.h scan_asn1SET.o: scan_asn1SET.c asn1.h scan_asn1STRING.o: scan_asn1STRING.c asn1.h +scan_asn1BITSTRING.o: scan_asn1BITSTRING.c asn1.h scan_asn1int.o: scan_asn1int.c asn1.h scan_asn1length.o: scan_asn1length.c asn1.h scan_asn1oid.o: scan_asn1oid.c asn1.h scan_asn1rawint.o: scan_asn1rawint.c asn1.h scan_asn1string.o: scan_asn1string.c asn1.h scan_asn1tag.o: scan_asn1tag.c asn1.h +scan_asn1tagint.o: scan_asn1tagint.c asn1.h scan_ldapaddrequest.o: scan_ldapaddrequest.c asn1.h ldap.h scan_ldapava.o: scan_ldapava.c asn1.h ldap.h scan_ldapbindrequest.o: scan_ldapbindrequest.c asn1.h ldap.h @@ -148,5 +155,6 @@ 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 +scan_asn1generic.o: scan_asn1generic.c asn1.h ldap_match_sre.o: ldap_match_sre.c ldap.h diff --git a/acl.c b/acl.c index d400ced..dc630fa 100644 --- a/acl.c +++ b/acl.c @@ -1,6 +1,7 @@ #define _FILE_OFFSET_BITS 64 #define MAIN +#include "ldap.h" #include #include #include @@ -11,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -275,7 +275,7 @@ int marshalfilter(stralloc* x,struct assertion* a) { int marshal(char* map,size_t filelen,const char* filename) { size_t filters,acls,i,j,k; - size_t filter_offset,acl_offset; + size_t filter_offset; //,acl_offset; struct acl* a; uint32* F,* A; uint32 attribute_count; @@ -396,7 +396,7 @@ nomem: A=malloc(sizeof(*A)*acls); if (!A) goto nomem; - acl_offset=F[i]+(acls+1)*sizeof(*A); +// acl_offset=F[i]+(acls+1)*sizeof(*A); i=0; for (a=root; a; a=a->next) { diff --git a/asn1.h b/asn1.h index ea38fcf..49cc9aa 100644 --- a/asn1.h +++ b/asn1.h @@ -1,3 +1,6 @@ +#ifndef ASN1_H +#define ASN1_H + /* parser and formatter for ASN.1 DER encoding. * The parser can read BER encoding, too. */ @@ -18,12 +21,18 @@ enum asn1_tagtype { enum asn1_tag { BOOLEAN=1, INTEGER=2, + BIT_STRING=3, OCTET_STRING=4, + OBJECT_IDENTIFIER=6, ENUMERATED=10, SEQUENCE_OF=16, SET_OF=17, + UTCTIME=23 }; +/* write variable length integer in the encoding used in tag and oid */ +size_t fmt_asn1tagint(char* dest,unsigned long val); + /* write int in least amount of bytes, return number of bytes */ /* as used in ASN.1 tag */ size_t fmt_asn1tag(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt, @@ -85,12 +94,17 @@ size_t fmt_asn1string(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt, /* write ASN.1 SET */ #define fmt_asn1SET(dest,l) fmt_asn1transparent(dest,UNIVERSAL,CONSTRUCTED,SET_OF,l) +size_t fmt_asn1OID(char* dest,const unsigned long* array,unsigned long len); + /* conventions for the parser routines: * src points to the first byte to parse * max points to the first byte behind the buffer * the return value is the number of bytes parsed or 0 for parse error */ +/* parse ASN.1 variable length integer as used in tag and oid */ +size_t scan_asn1tagint(const char* src,const char* max,unsigned long* val); + /* parse ASN.1 tag into a tag class, tag type and tag number */ size_t scan_asn1tag(const char* src,const char* max, enum asn1_tagclass* tc,enum asn1_tagtype* tt, unsigned long* tag); @@ -119,5 +133,19 @@ size_t scan_asn1BOOLEAN(const char* src,const char* max,unsigned long* l); size_t scan_asn1INTEGER(const char* src,const char* max,signed long* l); size_t scan_asn1ENUMERATED(const char* src,const char* max,unsigned long* l); size_t scan_asn1STRING(const char* src,const char* max,const char** s,size_t* l); +size_t scan_asn1BITSTRING(const char* src,const char* max,const char** s,size_t* l); size_t scan_asn1SEQUENCE(const char* src,const char* max,size_t* len); size_t scan_asn1SET(const char* src,const char* max,size_t* len); + +/* scan an ASN.1 OID and put the numbers into array. + * Return numbers of bytes parsed or 0 on error. + * Put at most arraylen longs into array; if the OID is longer, or if array is NULL, return real number in arraylen and return 0 + * If 0 is returned and arraylen is also 0, there was a parse error */ +size_t scan_asn1oid(const char* src,const char* max,unsigned long* array,unsigned long* arraylen); + +struct string { + size_t l; + const char* s; +}; + +#endif diff --git a/auth.c b/auth.c index dd4ceee..97ea172 100644 --- a/auth.c +++ b/auth.c @@ -1,3 +1,4 @@ +#define _XOPEN_SOURCE #include #ifdef __dietlibc__ #include @@ -7,7 +8,6 @@ #define MD5Update MD5_Update #define MD5Final MD5_Final #endif -#define _XOPEN_SOURCE #include #include #include diff --git a/dumpacls.c b/dumpacls.c index ce44a9e..88c58ed 100644 --- a/dumpacls.c +++ b/dumpacls.c @@ -15,7 +15,7 @@ int main(int argc,char* argv[]) { if (!map) { buffer_puts(buffer_2,"could not open `"); buffer_puts(buffer_2,fn); - buffer_puts(buffer_2,"´: "); + buffer_puts(buffer_2,"': "); buffer_puterror(buffer_2); buffer_putnlflush(buffer_2); exit(1); diff --git a/fmt_asn1OID.c b/fmt_asn1OID.c new file mode 100644 index 0000000..5bd9c00 --- /dev/null +++ b/fmt_asn1OID.c @@ -0,0 +1,16 @@ +#include "asn1.h" + +size_t fmt_asn1OID(char* dest,const unsigned long* array,unsigned long len) { + size_t i,l,l2; + if (len<2) return 0; + for (l=1,i=2; i +#include +#include "asn1.h" + +size_t fmt_asn1generic(char* dest,const char* fmt,...) { + size_t containerstack[100]; + size_t curinstack=0; + va_list args; + va_start(args,fmt); + unsigned long* application=0; + struct string* s; + struct string S; + size_t curlen=0; + size_t cursor=0; + size_t seqlen; + unsigned long appstore; + while (*fmt) { + char* realdest=dest?dest+cursor:NULL; + switch (*fmt) { + case 'a': // make next tag use APPLICATION with this tag + appstore=va_arg(args,unsigned long); + application=&appstore; + break; + case 'i': // send integer + { + unsigned long i=va_arg(args,unsigned long); + if (application) + curlen=fmt_asn1int(realdest,APPLICATION,PRIMITIVE,*application,i); + else + curlen=fmt_asn1int(realdest,UNIVERSAL,PRIMITIVE,INTEGER,i); + application=NULL; + break; + } + case 'S': // send OCTET_STRING, using struct string* as arg + s=va_arg(args,struct string*); +copystring: + if (application) + curlen=fmt_asn1string(realdest,APPLICATION,PRIMITIVE,*application,s->s,s->l); + else + curlen=fmt_asn1string(realdest,UNIVERSAL,PRIMITIVE,OCTET_STRING,s->s,s->l); + application=NULL; + break; + case 's': // send OCTET_STRING, using const char* with strlen() as arg + S.s=va_arg(args,const char*); + S.l=strlen(S.s); + s=&S; + goto copystring; + case '{': // start SEQUENCE + if (application) + curlen=fmt_asn1tag(realdest,APPLICATION,CONSTRUCTED,*application); + else + curlen=fmt_asn1tag(realdest,UNIVERSAL,CONSTRUCTED,SEQUENCE_OF); + containerstack[curinstack++]=cursor+curlen; + application=NULL; + break; + case '}': // end of SEQUENCE + /* we just wrote the tag and the sequence. Now that we wrote the + * sequence, we know the length it took, and we need to move the + * sequence data backwards to make room to write the ASN.1 length */ + { + char* anfang; + if (!curinstack) return 0; + anfang=dest+containerstack[--curinstack]; + seqlen=dest+cursor-anfang; + curlen=fmt_asn1length(NULL,seqlen); + if (!dest) break; + memmove(anfang+curlen,anfang,seqlen); + fmt_asn1length(anfang,seqlen); + break; + } + } + cursor+=curlen; + ++fmt; + } + return cursor; +} diff --git a/fmt_asn1tag.c b/fmt_asn1tag.c index 8fa1605..b2bd1a0 100644 --- a/fmt_asn1tag.c +++ b/fmt_asn1tag.c @@ -4,22 +4,12 @@ /* as used in ASN.1 tags */ size_t fmt_asn1tag(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,unsigned long l) { /* encoding is either l%128 or (0x1f,...) */ - size_t needed=((sizeof l)*7)/8,i; if (l<0x1f) { if (dest) *dest=(int)tc+(int)tt+(l&0x1f); return 1; } - for (i=1; i>(i*7))) - break; if (dest) { - size_t j=i; *dest=(int)tc+(int)tt+0x1f; ++dest; - while (j) { - --j; - *dest=((l>>(j*7))&0x7f) + (j?0x80:0); - ++dest; - } } - return i+1; + return fmt_asn1tagint(dest,l)+1; } diff --git a/fmt_asn1tagint.c b/fmt_asn1tagint.c new file mode 100644 index 0000000..338d7bf --- /dev/null +++ b/fmt_asn1tagint.c @@ -0,0 +1,17 @@ +#include "asn1.h" + +size_t fmt_asn1tagint(char* dest,unsigned long l) { + size_t needed=((sizeof l)*7)/8,i; + for (i=1; i>(i*7))) + break; + if (dest) { + size_t j=i; + while (j) { + --j; + *dest=((l>>(j*7))&0x7f) + (j?0x80:0); + ++dest; + } + } + return i; +} diff --git a/fmt_ldapadl.c b/fmt_ldapadl.c index cc51999..be4e647 100644 --- a/fmt_ldapadl.c +++ b/fmt_ldapadl.c @@ -1,4 +1,3 @@ -#include "asn1.h" #include "ldap.h" static size_t doit(char* dest,struct AttributeDescriptionList* adl,int seq) { diff --git a/fmt_ldapava.c b/fmt_ldapava.c index c1f9fc3..5640472 100644 --- a/fmt_ldapava.c +++ b/fmt_ldapava.c @@ -1,4 +1,3 @@ -#include "asn1.h" #include "ldap.h" size_t fmt_ldapava(char* dest,struct AttributeValueAssertion* a) { diff --git a/fmt_ldapbindrequest.c b/fmt_ldapbindrequest.c index 76a0bc9..6018737 100644 --- a/fmt_ldapbindrequest.c +++ b/fmt_ldapbindrequest.c @@ -1,5 +1,4 @@ #include -#include "asn1.h" #include "ldap.h" #include "str.h" #include "rangecheck.h" diff --git a/fmt_ldapmessage.c b/fmt_ldapmessage.c index b9b9f59..9a25f7d 100644 --- a/fmt_ldapmessage.c +++ b/fmt_ldapmessage.c @@ -1,4 +1,3 @@ -#include "asn1.h" #include "ldap.h" size_t fmt_ldapmessage(char* dest,long messageid,long op,size_t len) { diff --git a/fmt_ldappal.c b/fmt_ldappal.c index d4322ff..fc519ae 100644 --- a/fmt_ldappal.c +++ b/fmt_ldappal.c @@ -1,4 +1,3 @@ -#include "asn1.h" #include "ldap.h" size_t fmt_ldappal(char* dest,struct PartialAttributeList* pal) { diff --git a/fmt_ldapresult.c b/fmt_ldapresult.c index 0ef6df1..b62b15b 100644 --- a/fmt_ldapresult.c +++ b/fmt_ldapresult.c @@ -1,4 +1,3 @@ -#include "asn1.h" #include "ldap.h" #include "str.h" diff --git a/fmt_ldapsearchfilter.c b/fmt_ldapsearchfilter.c index 1ad3cea..6c2f2c1 100644 --- a/fmt_ldapsearchfilter.c +++ b/fmt_ldapsearchfilter.c @@ -1,5 +1,4 @@ #include -#include "asn1.h" #include "ldap.h" #include @@ -51,7 +50,7 @@ size_t fmt_ldapsearchfilter(char* dest,struct Filter* f) { } break; case PRESENT: - return fmt_asn1string(dest,PRIVATE,PRIMITIVE,f->type,f->ava.desc.s,f->ava.desc.l); + return fmt_asn1string(dest,PRIVATE,PRIMITIVE,(enum asn1_tag)f->type,f->ava.desc.s,f->ava.desc.l); break; default: return 0; } diff --git a/fmt_ldapsearchrequest.c b/fmt_ldapsearchrequest.c index e73bb3c..3dbac1e 100644 --- a/fmt_ldapsearchrequest.c +++ b/fmt_ldapsearchrequest.c @@ -1,4 +1,3 @@ -#include "asn1.h" #include "ldap.h" size_t fmt_ldapsearchrequest(char* dest,struct SearchRequest* sr) { diff --git a/fmt_ldapsearchresultentry.c b/fmt_ldapsearchresultentry.c index 50f5690..6fbe2bf 100644 --- a/fmt_ldapsearchresultentry.c +++ b/fmt_ldapsearchresultentry.c @@ -1,4 +1,3 @@ -#include "asn1.h" #include "ldap.h" size_t fmt_ldapsearchresultentry(char* dest,struct SearchResultEntry* sre) { diff --git a/fmt_ldapstring.c b/fmt_ldapstring.c index 3507262..ffc3632 100644 --- a/fmt_ldapstring.c +++ b/fmt_ldapstring.c @@ -1,4 +1,3 @@ -#include "asn1.h" #include "ldap.h" size_t fmt_ldapstring(char* dest,struct string* s) { diff --git a/free_ldapsearchfilter.c b/free_ldapsearchfilter.c index d5b5250..d952f93 100644 --- a/free_ldapsearchfilter.c +++ b/free_ldapsearchfilter.c @@ -1,5 +1,4 @@ #include -#include "asn1.h" #include "ldap.h" void free_ldapsearchfilter(struct Filter* f) { diff --git a/ldap.h b/ldap.h index 0755d23..47d5edc 100644 --- a/ldap.h +++ b/ldap.h @@ -1,14 +1,10 @@ #ifndef _LDAP_H #define _LDAP_H +#include "asn1.h" #include #include -struct string { - size_t l; - const char* s; -}; - int matchstring(struct string* s,const char* c); int matchcasestring(struct string* s,const char* c); int matchprefix(struct string* s,const char* c); diff --git a/ldap_match_mapped.c b/ldap_match_mapped.c index dc80397..b3cf234 100644 --- a/ldap_match_mapped.c +++ b/ldap_match_mapped.c @@ -1,4 +1,3 @@ -#include "ldap.h" #include "ldif.h" #include "byte.h" #include "str.h" diff --git a/ldapclient.c b/ldapclient.c index 86375ad..56c4c0a 100644 --- a/ldapclient.c +++ b/ldapclient.c @@ -4,7 +4,6 @@ #include #include "byte.h" #include "buffer.h" -#include "asn1.h" #include "ldap.h" #include "socket.h" #include "ip4.h" @@ -51,7 +50,7 @@ static int ldapbind(int sock) { } int main(int argc,char* argv[]) { - int sock; + int sock=0; char buf[BUFSIZE]; int len=0; char* me; diff --git a/ldapclient_str.c b/ldapclient_str.c index 8cfd200..2b0bda3 100644 --- a/ldapclient_str.c +++ b/ldapclient_str.c @@ -3,7 +3,6 @@ #include #include "byte.h" #include "buffer.h" -#include "asn1.h" #include "ldap.h" #include "socket.h" #include "ip4.h" diff --git a/ldapdelete.c b/ldapdelete.c index 8b956b4..8ac9f0c 100644 --- a/ldapdelete.c +++ b/ldapdelete.c @@ -4,7 +4,6 @@ #include #include "byte.h" #include "buffer.h" -#include "asn1.h" #include "ldap.h" #include "socket.h" #include "ip4.h" diff --git a/ldif.h b/ldif.h index cb69bd1..fc6496b 100644 --- a/ldif.h +++ b/ldif.h @@ -1,7 +1,8 @@ #define _FILE_OFFSET_BITS 64 #include #include -#include +#include "asn1.h" +#include "ldap.h" /* how many attributes do we allow per record? */ #define ATTRIBS 100 diff --git a/parse.c b/parse.c index cbfaf5b..4a564ac 100644 --- a/parse.c +++ b/parse.c @@ -144,7 +144,7 @@ int main(int argc,char* argv[]) { char* destname=argc<3?"data":argv[2]; char* tempname; unsigned long size_of_string_table,indices_offset; - long offset_stringtable; +// long offset_stringtable; char* map; uint32 attrofs,classofs; @@ -301,7 +301,7 @@ writeerror: uint32_pack(map+4*4,size_of_string_table); /* size_of_string_table */ // size_of_string_table=stringtable.used+classes.strings.used+attributes.strings.used; - offset_stringtable=5*4; +// offset_stringtable=5*4; offset_classes=outofs; munmap(map,5*4); diff --git a/scan_asn1BITSTRING.c b/scan_asn1BITSTRING.c new file mode 100644 index 0000000..4553ee5 --- /dev/null +++ b/scan_asn1BITSTRING.c @@ -0,0 +1,27 @@ +#include "asn1.h" + +size_t scan_asn1BITSTRING(const char* src,const char* max,const char** s,size_t* l) { + size_t tmp; + unsigned long tag; + enum asn1_tagclass tc; + enum asn1_tagtype tt; + if ((tmp=scan_asn1string(src,max,&tc,&tt,&tag,s,l))) + if (tc==UNIVERSAL && tt==PRIMITIVE && tag==BIT_STRING) { + unsigned char lastbyte; + if (*l==0 || /* length must be at least 1 because for bit strings, the first octet contains the number of unused bits in the last octet */ + (unsigned char)(**s)>7) /* the number of unused bits in the last octet must not be negative and can be at most 7 */ + return 0; + /* these are DER checks */ + /* can't have unused bits if the length is 0 */ + if (*l==1 && **s) + return 0; + /* now check if the unused bits are 0 */ + lastbyte=(*s)[*l+1]; + if (lastbyte & (0xff >> (8-**s))) + return 0; + *l=*l*8-(unsigned char)(**s); + ++*s; + return tmp; + } + return 0; +} diff --git a/scan_asn1generic.c b/scan_asn1generic.c new file mode 100644 index 0000000..21ea582 --- /dev/null +++ b/scan_asn1generic.c @@ -0,0 +1,107 @@ +#include +#include "asn1.h" + +size_t scan_asn1generic(const char* src,const char* max,const char* fmt,...) { + size_t curlen,seqlen; + const char* maxstack[100]; + size_t curmax=0; + va_list args; + int optional=0; + unsigned long* application=NULL; + unsigned long tag; + enum asn1_tagclass tc; + enum asn1_tagtype tt; + const char* orig=src; + va_start(args,fmt); + maxstack[0]=max; + while (*fmt) { + switch (*fmt) { + case '?': // ? = rest is optional (until end of sequence) + optional=1; + break; + case 'i': // i = INTEGER + { + long* dest=va_arg(args,long*); + *dest=0; + curlen=scan_asn1int(src,maxstack[curmax],&tc,&tt,&tag,dest); + if (application) { + if (tc!=APPLICATION) return 0; + *application=tag; + } else { + if (tc!=UNIVERSAL || tt!=PRIMITIVE || tag!=INTEGER) + return 0; + } + if (!curlen) { if (optional) break; else return 0; } + src+=curlen; + application=0; + break; + } + case 's': // s = STRING + { + struct string* dest=va_arg(args,struct string*); + dest->l=0; + dest->s=0; + curlen=scan_asn1string(src,maxstack[curmax],&tc,&tt,&tag,&dest->s,&dest->l); + if (!curlen) { if (optional) break; else return 0; } + if (application) { + if (tc!=APPLICATION) return 0; + *application=tag; + } else { + if (tc!=UNIVERSAL || tt!=PRIMITIVE || tag!=OCTET_STRING) + return 0; + } + src+=curlen; + application=0; + break; + } + case 'a': // next tag class is APPLICATION instead of UNIVERSAL; write tag to unsigned long* + { + application=va_arg(args,unsigned long*); + break; + } + case '{': // { = SEQUENCE + { + curlen=scan_asn1tag(src,maxstack[curmax],&tc,&tt,&tag); + if (!curlen) { if (optional) break; else return 0; } + if (application) { + if (tc!=APPLICATION) return 0; + *application=tag; + } else { + if (tc!=UNIVERSAL || tt!=CONSTRUCTED || tag!=SEQUENCE_OF) + return 0; + } + src+=curlen; + curlen=scan_asn1length(src,maxstack[curmax],&seqlen); + if (!curlen) return 0; + if (curmax>99) return 0; + maxstack[++curmax]=src+curlen+seqlen; + src+=curlen; + application=0; + break; + } + case '!': // save current max-src into size_t + // useful for ldap, where you have an application sequence + // and the tag defines which encoding you have inside the + // sequence, so you can't put it in the format string. + // you still need to know the length so you can call this function + // again on the rest of the data. + { + size_t* dest=va_arg(args,size_t*); + *dest=maxstack[curmax]-src; + break; + } + case '}': // } = end of SEQUENCE + { + optional=0; + if (curmax==0) return 0; + --curmax; + break; + } + default: + return 0; + } + ++fmt; + } + va_end(args); + return src-orig; +} diff --git a/scan_asn1length.c b/scan_asn1length.c index 832309e..944bd52 100644 --- a/scan_asn1length.c +++ b/scan_asn1length.c @@ -3,7 +3,7 @@ size_t scan_asn1length(const char* src,const char* max,size_t* length) { const char* orig=src; - if (src>max) return 0; + if (src>=max) return 0; /* If the highest bit of the first byte is clear, the byte is the length. * Otherwise the next n bytes are the length (n being the lower 7 bits) */ if (*src&0x80) { diff --git a/scan_asn1oid.c b/scan_asn1oid.c index a2a4a1d..89f85b9 100644 --- a/scan_asn1oid.c +++ b/scan_asn1oid.c @@ -1,49 +1,49 @@ #include "asn1.h" -size_t scan_asn1oid(const char* src,const char* max) { - size_t res,tmp,tlen; - unsigned long tag; +size_t scan_asn1oid(const char* src,const char* max,unsigned long* array,unsigned long* arraylen) { + const char* orig=src; + size_t res,tlen,cur=0,al; + unsigned long tag,tmp; enum asn1_tagclass tc; enum asn1_tagtype tt; - if (!(res=scan_asn1tag(src,max,&tc,&tt,&tag))) goto error; - if (!(tmp=scan_asn1length(src+res,max,&tlen))) goto error; + if (!arraylen) return 0; + al=*arraylen; *arraylen=0; + if (!(res=scan_asn1tag(src,max,&tc,&tt,&tag))) return 0; + if (tc!=UNIVERSAL || tt!=PRIMITIVE || tag!=OBJECT_IDENTIFIER) return 0; + if (!(tmp=scan_asn1length(src+res,max,&tlen))) return 0; + if (tlen<1) return 0; /* there has to be at least one octet */ res+=tmp; + if (max>src+res+tlen) max=src+res+tlen; /* clamp max down */ + src+=res; + { - size_t i,x,y; - tmp=0; - for(i=0;src[res+i]&128;++i) - tmp=(tmp<<7)+((unsigned char)src[res+i]&(~128)); - tmp=(tmp<<7)+(unsigned char)src[res+i]; ++i; - x=tmp/40; y=tmp-x*40; - /* AFAIK gilt fuer alle bisher zugewiesenen OIDs: x<=2 & y<40 */ -#if 1 - /* Hier wird das Beispiel aus dem Standard korrekt geparst. */ - while (x>2) { --x; y+=40; } -#else - /* Hier nicht. Dennoch arbeiten einige ASN.1 Parser ebenso. */ - while (y>40) { y-=40; ++x; } -#endif -#if 0 - buffer_putulong(buffer_2,x); - buffer_puts(buffer_2,"."); - buffer_putulong(buffer_2,y); -#endif - for(;i2) { + b+=(a-2)*40; + a=2; } -#if 0 - buffer_putsflush(buffer_2,"\n"); -#endif + if (array && cural) /* did not fit */ + return 0; + return src-orig; } diff --git a/scan_asn1rawint.c b/scan_asn1rawint.c index 263c25b..6f6f676 100644 --- a/scan_asn1rawint.c +++ b/scan_asn1rawint.c @@ -3,6 +3,7 @@ size_t scan_asn1rawint(const char* src,const char* max,size_t len,long* l) { size_t i,j; long m; + if (src>=max) return 0; if (*src<0) m=-1; else m=0; for (i=j=0; imax) return 0; - if (l>(((unsigned long)-1)>>7)) return 0; /* catch integer overflow */ - l=l*128+(*src&0x7F); - if (!(*src&0x80)) break; - } - *tag=l; - return (src-orig+1); + size_t res=scan_asn1tagint(src+1,max,tag); + return res+!!res; /* add 1 unless it's 0, then leave 0 */ } else { *tag=*src&0x1f; return 1; diff --git a/scan_asn1tagint.c b/scan_asn1tagint.c new file mode 100644 index 0000000..49a9974 --- /dev/null +++ b/scan_asn1tagint.c @@ -0,0 +1,14 @@ +#include "asn1.h" + +size_t scan_asn1tagint(const char* src,const char* max,unsigned long* val) { + const char* orig=src; + unsigned long l=0; + for (;; ++src) { + if (src>=max) return 0; + if (l>(((unsigned long)-1)>>7)) return 0; /* catch integer overflow */ + l=l*128+(*src&0x7F); + if (!(*src&0x80)) break; + } + *val=l; + return src-orig+1; +} diff --git a/scan_ldapaddrequest.c b/scan_ldapaddrequest.c index c1a1fd4..9fb4b1d 100644 --- a/scan_ldapaddrequest.c +++ b/scan_ldapaddrequest.c @@ -1,5 +1,4 @@ #include -#include "asn1.h" #include "ldap.h" #include "buffer.h" #include "byte.h" diff --git a/scan_ldapava.c b/scan_ldapava.c index d5724ff..b9332c4 100644 --- a/scan_ldapava.c +++ b/scan_ldapava.c @@ -1,4 +1,3 @@ -#include "asn1.h" #include "ldap.h" size_t scan_ldapava(const char* src,const char* max,struct AttributeValueAssertion* ava) { diff --git a/scan_ldapbindrequest.c b/scan_ldapbindrequest.c index 0bd8f42..0ce7e12 100644 --- a/scan_ldapbindrequest.c +++ b/scan_ldapbindrequest.c @@ -1,4 +1,3 @@ -#include "asn1.h" #include "ldap.h" size_t scan_ldapbindrequest(const char* src,const char* max, diff --git a/scan_ldapbindresponse.c b/scan_ldapbindresponse.c index eef04bf..1161ab1 100644 --- a/scan_ldapbindresponse.c +++ b/scan_ldapbindresponse.c @@ -1,4 +1,3 @@ -#include "asn1.h" #include "ldap.h" size_t scan_ldapbindresponse(const char* src,const char* max, diff --git a/scan_ldapdeleterequest.c b/scan_ldapdeleterequest.c index 38d2af4..f2c8021 100644 --- a/scan_ldapdeleterequest.c +++ b/scan_ldapdeleterequest.c @@ -1,4 +1,3 @@ -#include "asn1.h" #include "ldap.h" size_t scan_ldapdeleterequest(const char* src,const char* max, diff --git a/scan_ldapmessage.c b/scan_ldapmessage.c index dd179b5..baa1173 100644 --- a/scan_ldapmessage.c +++ b/scan_ldapmessage.c @@ -1,4 +1,3 @@ -#include "asn1.h" #include "ldap.h" size_t scan_ldapmessage(const char* src,const char* max, diff --git a/scan_ldapmodifyrequest.c b/scan_ldapmodifyrequest.c index 04d79f3..ba42e4f 100644 --- a/scan_ldapmodifyrequest.c +++ b/scan_ldapmodifyrequest.c @@ -1,5 +1,4 @@ #include -#include "asn1.h" #include "ldap.h" #if 0 diff --git a/scan_ldapresult.c b/scan_ldapresult.c index 7743228..930f458 100644 --- a/scan_ldapresult.c +++ b/scan_ldapresult.c @@ -1,4 +1,3 @@ -#include "asn1.h" #include "ldap.h" size_t scan_ldapresult(const char* src,const char* max,unsigned long* result, diff --git a/scan_ldapsearchfilter.c b/scan_ldapsearchfilter.c index 24bafda..895034f 100644 --- a/scan_ldapsearchfilter.c +++ b/scan_ldapsearchfilter.c @@ -1,4 +1,3 @@ -#include "asn1.h" #include "ldap.h" #include @@ -40,7 +39,7 @@ size_t scan_ldapsearchfilter(const char* src,const char* max,struct Filter** f) if (tc!=PRIVATE || (tt!=CONSTRUCTED && tag!=7) || tag>9) goto error; if (!(tmp=scan_asn1length(src+res,max,&len))) goto error; res+=tmp; - if (src+res+len>max) goto error; + if (src+res+len>=max) goto error; if (!(*f=malloc(sizeof(struct Filter)))) goto error; (*f)->next=0; (*f)->x=0; diff --git a/scan_ldapsearchrequest.c b/scan_ldapsearchrequest.c index f58f24c..4843bb0 100644 --- a/scan_ldapsearchrequest.c +++ b/scan_ldapsearchrequest.c @@ -1,5 +1,4 @@ #include -#include "asn1.h" #include "ldap.h" size_t scan_ldapsearchrequest(const char* src,const char* max, diff --git a/scan_ldapsearchresultentry.c b/scan_ldapsearchresultentry.c index 08f82b4..50e8654 100644 --- a/scan_ldapsearchresultentry.c +++ b/scan_ldapsearchresultentry.c @@ -1,5 +1,4 @@ #include -#include "asn1.h" #include "ldap.h" size_t scan_ldapsearchresultentry(const char* src,const char* max,struct SearchResultEntry* sre) { diff --git a/scan_ldapstring.c b/scan_ldapstring.c index 7f3047d..c6054ee 100644 --- a/scan_ldapstring.c +++ b/scan_ldapstring.c @@ -1,5 +1,4 @@ -#include -#include +#include "ldap.h" size_t scan_ldapstring(const char* src,const char* max,struct string* s) { return scan_asn1STRING(src,max,&s->s,&s->l); diff --git a/t10.c b/t10.c new file mode 100644 index 0000000..eb88038 --- /dev/null +++ b/t10.c @@ -0,0 +1,129 @@ +#include +#include +#include "asn1.h" + +void printasn1(const char* buf,const char* max) { + const char* maxstack[100]; + size_t sptr=0; + size_t indent=0; + unsigned long tag; + enum asn1_tagclass tc; + enum asn1_tagtype tt; + size_t cl,len; + maxstack[sptr]=max; + while (buf %ld\n",indent,"",l); + } else if (tag==OCTET_STRING) { + printf("%*s-> \"",indent,""); + for (i=0; i=99) { + printf("too many nested constructed elements!\n"); + return; + } + maxstack[++sptr]=buf+len; + } else + buf+=len; + + while (sptr && maxstack[sptr]<=buf) { + --sptr; + indent-=2; + printf("%*s}\n",indent,""); + } + + } +} + +main() { + char buf[1024]; + int l,i; + byte_zero(buf,1024); + l=fmt_asn1generic(buf,"a{is}",8,23,"fnord"); + printf("formatted into %d bytes\n",l); + { + printf("-> "); + for (i=0; i #include #include "mmap.h" -#include "asn1.h" #include "ldap.h" #endif diff --git a/tinyldap.c b/tinyldap.c index b208e6c..4174982 100644 --- a/tinyldap.c +++ b/tinyldap.c @@ -639,7 +639,7 @@ static void tagmatches(uint32* index,size_t elements,struct string* s, setbit(b,rec); /* there may be multiple matches. * Look before and after mid, too */ - if (mid) /* thx Andreas Stührk */ + if (mid) /* thx Andreas Stührk */ for (k=mid-1; k>0; --k) { m=uint32_read((char*)(&index[k])); if ((ft==LESSEQUAL) || (l=match(s,map+m))==0) {