From 2848136fc9a9665408c5828d6081443d2f4c4d17 Mon Sep 17 00:00:00 2001 From: leitner Date: Thu, 14 Mar 2002 17:26:06 +0000 Subject: [PATCH] provide some infrastructure for signed ints --- Makefile | 11 ++++++----- asn1.h | 35 +++++++++++++++++++++++++++++++++-- fmt_asn1sint.c | 11 +++++++++++ fmt_asn1sintpayload.c | 23 +++++++++++++++++++++++ fmt_ldapsearchfilter.c | 2 +- matchstring.c | 1 + scan_asn1INTEGER.c | 2 +- scan_asn1int.c | 13 ++----------- scan_asn1rawint.c | 12 ++++++++---- scan_ldapbindrequest.c | 3 +-- scan_ldapsearchfilter.c | 3 ++- t2.c | 5 +++-- 12 files changed, 92 insertions(+), 29 deletions(-) create mode 100644 fmt_asn1sint.c create mode 100644 fmt_asn1sintpayload.c diff --git a/Makefile b/Makefile index bf76e50..6b62632 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,13 @@ -DEBUG=1 +#DEBUG=1 -all: t t1 t2 bindrequest tinyldap ldapclient ldapclient_str +all: t1 t2 bindrequest tinyldap ldapclient ldapclient_str # t asn1.a: fmt_asn1intpayload.o fmt_asn1length.o fmt_asn1tag.o \ 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 +scan_asn1BOOLEAN.o scan_asn1rawint.o scan_asn1SET.o fmt_asn1sint.o \ +fmt_asn1sintpayload.o ldap.a: scan_ldapmessage.o fmt_ldapmessage.o fmt_ldapbindrequest.o \ scan_ldapbindrequest.o scan_ldapbindresponse.o scan_ldapresult.o \ @@ -20,10 +21,10 @@ ldif.a: ldif_parse.o ldap_match.o strduptab.o strstorage.o DIET=diet -Os CC=gcc -CFLAGS=-pipe -I. -Wall +CFLAGS=-pipe -I. -Wall -W ifneq ($(DEBUG),) DIET=diet -CFLAGS=-pipe -I. -Wall -g +CFLAGS=-pipe -I. -Wall -W -g endif %.o: %.c diff --git a/asn1.h b/asn1.h index f4e9e50..5229808 100644 --- a/asn1.h +++ b/asn1.h @@ -1,3 +1,6 @@ +/* parser and formatter for ASN.1 DER encoding. + * The parser can read BER encoding, too. */ + enum asn1_tagclass { UNIVERSAL=(0<<6), APPLICATION=(1<<6), @@ -32,10 +35,19 @@ int fmt_asn1length(char* dest,unsigned long l); * and length headers! */ int fmt_asn1intpayload(char* dest,unsigned long l); +/* write int in least amount of bytes, return number of bytes */ +/* as used in ASN.1 INTEGER. This only does the payload, not the tag + * and length headers! */ +int fmt_asn1sintpayload(char* dest,signed long l); + /* write int in least amount of bytes, return number of bytes */ /* as used in ASN.1 INTEGER or ENUMERATED. */ int fmt_asn1int(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,enum asn1_tag tag,unsigned long l); +/* write int in least amount of bytes, return number of bytes */ +/* as used in ASN.1 INTEGER or ENUMERATED. */ +int fmt_asn1sint(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,enum asn1_tag tag,signed long l); + /* write any data type that does not require transformation in the least * amount of bytes, return number of bytes */ /* as used in ASN.1 OCTET STRING, SEQUENCE etc. */ @@ -66,19 +78,38 @@ int fmt_asn1string(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,enum as /* write ASN.1 SET */ #define fmt_asn1SET(dest,l) fmt_asn1transparent(dest,UNIVERSAL,CONSTRUCTED,SET_OF,l); + +/* 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 tag into a tag class, tag type and tag number */ int scan_asn1tag(const char* src,const char* max, enum asn1_tagclass* tc,enum asn1_tagtype* tt, unsigned long* tag); + +/* parse ASN.1 length */ int scan_asn1length(const char* src,const char* max,unsigned long* length); + +/* parse ASN.1 integer with tag and length */ int scan_asn1int(const char* src,const char* max, enum asn1_tagclass* tc,enum asn1_tagtype* tt, unsigned long* tag, - unsigned long* l); + long* l); + +/* parse raw integer (payload after tag and length); internal helper */ int scan_asn1rawint(const char* src,const char* max,unsigned int len,long* i); + +/* parse string with tag and length. + * Points s to the first byte in the string, and writes the length of + * the string to l. */ int scan_asn1string(const char* src,const char* max, enum asn1_tagclass* tc,enum asn1_tagtype* tt,unsigned long* tag, const char** s,unsigned long* l); +/* the following expect a specific universal type and return a parse + * error if the tag does not match that type */ int scan_asn1BOOLEAN(const char* src,const char* max,unsigned long* l); -int scan_asn1INTEGER(const char* src,const char* max,unsigned long* l); +int scan_asn1INTEGER(const char* src,const char* max,signed long* l); int scan_asn1ENUMERATED(const char* src,const char* max,unsigned long* l); int scan_asn1STRING(const char* src,const char* max,const char** s,unsigned long* l); int scan_asn1SEQUENCE(const char* src,const char* max,unsigned long* len); diff --git a/fmt_asn1sint.c b/fmt_asn1sint.c new file mode 100644 index 0000000..7043bae --- /dev/null +++ b/fmt_asn1sint.c @@ -0,0 +1,11 @@ +#include + +int fmt_asn1sint(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,enum asn1_tag tag,signed long l) { + int len,tmp; + /* first the tag */ + if (!dest) return fmt_asn1tag(0,tc,tt,tag)+1+fmt_asn1intpayload(0,l); + len=fmt_asn1tag(dest,tc,tt,tag); + tmp=fmt_asn1sintpayload(dest+len+1,l); + if (fmt_asn1length(dest+len,tmp)!=1) return 0; + return len+tmp+1; +} diff --git a/fmt_asn1sintpayload.c b/fmt_asn1sintpayload.c new file mode 100644 index 0000000..c8815c1 --- /dev/null +++ b/fmt_asn1sintpayload.c @@ -0,0 +1,23 @@ +#include + +int fmt_asn1sintpayload(char* dest,signed long l) { + int needed=sizeof l; + int i; + signed long tmp=0x7f; + if (l>=0) return fmt_asn1intpayload(dest,l); + for (i=1; i>(j*8))&0xff; + ++dest; + } + } + return i; +} diff --git a/fmt_ldapsearchfilter.c b/fmt_ldapsearchfilter.c index 6ba32d1..e74f5a2 100644 --- a/fmt_ldapsearchfilter.c +++ b/fmt_ldapsearchfilter.c @@ -43,7 +43,7 @@ int fmt_ldapsearchfilter(char* dest,struct Filter* f) { l=fmt_ldapstring(nd,&f->ava.desc); l+=fmt_asn1SEQUENCE(nd+l,tmp); l+=fmt_ldapsubstring(nd+l,f->substrings); - sum+=l; + sum=l; } break; case PRESENT: diff --git a/matchstring.c b/matchstring.c index b4fdf3e..7fe99fa 100644 --- a/matchstring.c +++ b/matchstring.c @@ -1,3 +1,4 @@ +#include "byte.h" #include "ldif.h" /* behave like strcmp */ diff --git a/scan_asn1INTEGER.c b/scan_asn1INTEGER.c index e943861..b41356a 100644 --- a/scan_asn1INTEGER.c +++ b/scan_asn1INTEGER.c @@ -1,6 +1,6 @@ #include "asn1.h" -int scan_asn1INTEGER(const char* src,const char* max,unsigned long* l) { +int scan_asn1INTEGER(const char* src,const char* max,signed long* l) { int tmp; long tag; enum asn1_tagclass tc; diff --git a/scan_asn1int.c b/scan_asn1int.c index 08b637e..b4c1d90 100644 --- a/scan_asn1int.c +++ b/scan_asn1int.c @@ -1,20 +1,11 @@ #include "asn1.h" -static long int handleint(const unsigned char* c,int len) { - long l=0; - while (len) { - l=l*256+*c; - --len; ++c; - } - return l; -} - -int scan_asn1int(const char* src,const char* max,enum asn1_tagclass* tc,enum asn1_tagtype* tt,unsigned long* tag,unsigned long* l) { +int scan_asn1int(const char* src,const char* max,enum asn1_tagclass* tc,enum asn1_tagtype* tt,unsigned long* tag,signed long* l) { int len,tmp; long tlen; if (!(len=scan_asn1tag(src,max,tc,tt,tag))) return 0; if (!(tmp=scan_asn1length(src+len,max,&tlen))) return 0; len+=tmp; - *l=handleint(src+len,tlen); + if (!(scan_asn1rawint(src+len,max,tlen,l))) return 0; return len+tlen; } diff --git a/scan_asn1rawint.c b/scan_asn1rawint.c index fb2aa4a..854a5b7 100644 --- a/scan_asn1rawint.c +++ b/scan_asn1rawint.c @@ -1,12 +1,16 @@ #include "asn1.h" int scan_asn1rawint(const char* src,const char* max,unsigned int len,long* l) { - int i; - *l=0; - for (i=0; imax) return 0; } + if (j>sizeof(long)) return 0; + *l=m; return len; } diff --git a/scan_ldapbindrequest.c b/scan_ldapbindrequest.c index c3ae4b4..4a213da 100644 --- a/scan_ldapbindrequest.c +++ b/scan_ldapbindrequest.c @@ -10,8 +10,7 @@ int scan_ldapbindrequest(const char* src,const char* max, { enum asn1_tagclass tc; enum asn1_tagtype tt; - long method; - if (!(tmp=scan_asn1tag(src+res,max,&tc,&tt,&method))) return 0; + if (!(tmp=scan_asn1tag(src+res,max,&tc,&tt,method))) return 0; if (tc!=PRIVATE || tt!=PRIMITIVE) return 0; } return res; diff --git a/scan_ldapsearchfilter.c b/scan_ldapsearchfilter.c index 86c82a8..600b7a6 100644 --- a/scan_ldapsearchfilter.c +++ b/scan_ldapsearchfilter.c @@ -34,7 +34,8 @@ int scan_ldapsearchfilter(const char* src,const char* max,struct Filter** f) { enum asn1_tagclass tc; enum asn1_tagtype tt; unsigned long tag,len; - int res,tmp; + int res; + unsigned int tmp; const char* nmax; *f=0; if (!(res=scan_asn1tag(src,max,&tc,&tt,&tag))) goto error; diff --git a/t2.c b/t2.c index 6fd8e12..fd87dd2 100644 --- a/t2.c +++ b/t2.c @@ -87,7 +87,8 @@ int main(int argc,char* argv[]) { // char* ldapsequence=mmap_read("req",&size); char* ldapsequence=mmap_read(argc>1?argv[1]:"/tmp/ldap/127.000.000.001.00389-127.000.000.001.38433",&size); long messageid, op, len; - int res,done=0; + int res; + unsigned long done=0; while (done