add "generic" format string based encoder and decoder (scan_asn1generic,
fmt_asn1generic, see t10.c for example usage) add "generic" asn.1 dumper (in t10.c) fix some read off-by-one errors, minor cleanups add real OID support add bitstring support
This commit is contained in:
10
Makefile
10
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
|
||||
|
||||
6
acl.c
6
acl.c
@@ -1,6 +1,7 @@
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#define MAIN
|
||||
|
||||
#include "ldap.h"
|
||||
#include <buffer.h>
|
||||
#include <stralloc.h>
|
||||
#include <str.h>
|
||||
@@ -11,7 +12,6 @@
|
||||
#include <byte.h>
|
||||
#include <mmap.h>
|
||||
#include <case.h>
|
||||
#include <ldap.h>
|
||||
#include <uint16.h>
|
||||
#include <uint32.h>
|
||||
#include <open.h>
|
||||
@@ -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) {
|
||||
|
||||
28
asn1.h
28
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
|
||||
|
||||
2
auth.c
2
auth.c
@@ -1,3 +1,4 @@
|
||||
#define _XOPEN_SOURCE
|
||||
#include <sys/types.h>
|
||||
#ifdef __dietlibc__
|
||||
#include <md5.h>
|
||||
@@ -7,7 +8,6 @@
|
||||
#define MD5Update MD5_Update
|
||||
#define MD5Final MD5_Final
|
||||
#endif
|
||||
#define _XOPEN_SOURCE
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <alloca.h>
|
||||
|
||||
@@ -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);
|
||||
|
||||
16
fmt_asn1OID.c
Normal file
16
fmt_asn1OID.c
Normal file
@@ -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<len; ++i) {
|
||||
l+=fmt_asn1tagint(dest,array[i]);
|
||||
}
|
||||
l2=fmt_asn1transparent(dest,UNIVERSAL,PRIMITIVE,OBJECT_IDENTIFIER,l);
|
||||
if (!dest) return l+l2;
|
||||
dest[l2]=array[0]*40+array[1];
|
||||
dest+=l2+1;
|
||||
for (i=2; i<len; ++i)
|
||||
dest+=fmt_asn1tagint(dest,array[i]);
|
||||
return l+l2;
|
||||
}
|
||||
76
fmt_asn1generic.c
Normal file
76
fmt_asn1generic.c
Normal file
@@ -0,0 +1,76 @@
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#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;
|
||||
}
|
||||
@@ -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<needed; ++i)
|
||||
if (!(l>>(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;
|
||||
}
|
||||
|
||||
17
fmt_asn1tagint.c
Normal file
17
fmt_asn1tagint.c
Normal file
@@ -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<needed; ++i)
|
||||
if (!(l>>(i*7)))
|
||||
break;
|
||||
if (dest) {
|
||||
size_t j=i;
|
||||
while (j) {
|
||||
--j;
|
||||
*dest=((l>>(j*7))&0x7f) + (j?0x80:0);
|
||||
++dest;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
#include "asn1.h"
|
||||
#include "ldap.h"
|
||||
|
||||
static size_t doit(char* dest,struct AttributeDescriptionList* adl,int seq) {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#include "asn1.h"
|
||||
#include "ldap.h"
|
||||
|
||||
size_t fmt_ldapava(char* dest,struct AttributeValueAssertion* a) {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include <string.h>
|
||||
#include "asn1.h"
|
||||
#include "ldap.h"
|
||||
#include "str.h"
|
||||
#include "rangecheck.h"
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#include "asn1.h"
|
||||
#include "ldap.h"
|
||||
|
||||
size_t fmt_ldapmessage(char* dest,long messageid,long op,size_t len) {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#include "asn1.h"
|
||||
#include "ldap.h"
|
||||
|
||||
size_t fmt_ldappal(char* dest,struct PartialAttributeList* pal) {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#include "asn1.h"
|
||||
#include "ldap.h"
|
||||
#include "str.h"
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include <byte.h>
|
||||
#include "asn1.h"
|
||||
#include "ldap.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#include "asn1.h"
|
||||
#include "ldap.h"
|
||||
|
||||
size_t fmt_ldapsearchrequest(char* dest,struct SearchRequest* sr) {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#include "asn1.h"
|
||||
#include "ldap.h"
|
||||
|
||||
size_t fmt_ldapsearchresultentry(char* dest,struct SearchResultEntry* sre) {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#include "asn1.h"
|
||||
#include "ldap.h"
|
||||
|
||||
size_t fmt_ldapstring(char* dest,struct string* s) {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include <stdlib.h>
|
||||
#include "asn1.h"
|
||||
#include "ldap.h"
|
||||
|
||||
void free_ldapsearchfilter(struct Filter* f) {
|
||||
|
||||
6
ldap.h
6
ldap.h
@@ -1,14 +1,10 @@
|
||||
#ifndef _LDAP_H
|
||||
#define _LDAP_H
|
||||
|
||||
#include "asn1.h"
|
||||
#include <stddef.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
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);
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#include "ldap.h"
|
||||
#include "ldif.h"
|
||||
#include "byte.h"
|
||||
#include "str.h"
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include <string.h>
|
||||
#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;
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include <string.h>
|
||||
#include "byte.h"
|
||||
#include "buffer.h"
|
||||
#include "asn1.h"
|
||||
#include "ldap.h"
|
||||
#include "socket.h"
|
||||
#include "ip4.h"
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include <string.h>
|
||||
#include "byte.h"
|
||||
#include "buffer.h"
|
||||
#include "asn1.h"
|
||||
#include "ldap.h"
|
||||
#include "socket.h"
|
||||
#include "ip4.h"
|
||||
|
||||
3
ldif.h
3
ldif.h
@@ -1,7 +1,8 @@
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#include <sys/stat.h>
|
||||
#include <inttypes.h>
|
||||
#include <ldap.h>
|
||||
#include "asn1.h"
|
||||
#include "ldap.h"
|
||||
|
||||
/* how many attributes do we allow per record? */
|
||||
#define ATTRIBS 100
|
||||
|
||||
4
parse.c
4
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);
|
||||
|
||||
27
scan_asn1BITSTRING.c
Normal file
27
scan_asn1BITSTRING.c
Normal file
@@ -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;
|
||||
}
|
||||
107
scan_asn1generic.c
Normal file
107
scan_asn1generic.c
Normal file
@@ -0,0 +1,107 @@
|
||||
#include <stdarg.h>
|
||||
#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;
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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(;i<tlen;++i) {
|
||||
tmp=0;
|
||||
for(;src[res+i]&128;++i)
|
||||
tmp=(tmp<<7)+((unsigned char)src[res+i]&(~128));
|
||||
tmp=(tmp<<7)+(unsigned char)src[res+i];
|
||||
#if 0
|
||||
buffer_puts(buffer_2,".");
|
||||
buffer_putulong(buffer_2,tmp);
|
||||
#endif
|
||||
int a,b;
|
||||
a=(unsigned char)*src;
|
||||
b=a%40;
|
||||
a/=40;
|
||||
/* a can be 0, 1 or 2. And b is <=39 if a is 0 or 1.
|
||||
* So, if a is bigger than 2, it is really 2 */
|
||||
if (a>2) {
|
||||
b+=(a-2)*40;
|
||||
a=2;
|
||||
}
|
||||
#if 0
|
||||
buffer_putsflush(buffer_2,"\n");
|
||||
#endif
|
||||
if (array && cur<al) array[cur]=a; ++cur;
|
||||
if (array && cur<al) array[cur]=b; ++cur;
|
||||
}
|
||||
return res+tlen;
|
||||
error:
|
||||
return 0;
|
||||
|
||||
for (++src; src<max; ) {
|
||||
size_t i;
|
||||
unsigned long tmp;
|
||||
if (!(i=scan_asn1tagint(src,max,&tmp)))
|
||||
return 0;
|
||||
src+=i;
|
||||
if (array && cur<al) array[cur]=tmp; ++cur;
|
||||
}
|
||||
|
||||
/* if we got this far, then we have an OID, but it might not have fit */
|
||||
*arraylen=cur;
|
||||
if (cur>al) /* did not fit */
|
||||
return 0;
|
||||
return src-orig;
|
||||
}
|
||||
|
||||
|
||||
@@ -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; i<len; ++i,++j) {
|
||||
if ((m==0 && *src==0) || (m==-1 && *src==-1)) --j;
|
||||
|
||||
@@ -1,24 +1,15 @@
|
||||
#include "asn1.h"
|
||||
|
||||
size_t scan_asn1tag(const char* src,const char* max,enum asn1_tagclass* tc,enum asn1_tagtype* tt,unsigned long* tag) {
|
||||
const char* orig=src;
|
||||
if (max<=src) return 0;
|
||||
*tc=(*src&0xC0);
|
||||
*tt=(*src&0x20);
|
||||
if (max<src) return 0;
|
||||
/* The lower 5 bits are the tag, unless it's 0x1f, in which case the
|
||||
* next bytes are the tag: always take the lower 7 bits; the last byte
|
||||
* in the sequence is marked by a cleared high bit */
|
||||
if ((*src & 0x1f) == 0x1f) {
|
||||
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;
|
||||
}
|
||||
*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;
|
||||
|
||||
14
scan_asn1tagint.c
Normal file
14
scan_asn1tagint.c
Normal file
@@ -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;
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
#include <stdlib.h>
|
||||
#include "asn1.h"
|
||||
#include "ldap.h"
|
||||
#include "buffer.h"
|
||||
#include "byte.h"
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#include "asn1.h"
|
||||
#include "ldap.h"
|
||||
|
||||
size_t scan_ldapava(const char* src,const char* max,struct AttributeValueAssertion* ava) {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#include "asn1.h"
|
||||
#include "ldap.h"
|
||||
|
||||
size_t scan_ldapbindrequest(const char* src,const char* max,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#include "asn1.h"
|
||||
#include "ldap.h"
|
||||
|
||||
size_t scan_ldapbindresponse(const char* src,const char* max,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#include "asn1.h"
|
||||
#include "ldap.h"
|
||||
|
||||
size_t scan_ldapdeleterequest(const char* src,const char* max,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#include "asn1.h"
|
||||
#include "ldap.h"
|
||||
|
||||
size_t scan_ldapmessage(const char* src,const char* max,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include <stdlib.h>
|
||||
#include "asn1.h"
|
||||
#include "ldap.h"
|
||||
|
||||
#if 0
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#include "asn1.h"
|
||||
#include "ldap.h"
|
||||
|
||||
size_t scan_ldapresult(const char* src,const char* max,unsigned long* result,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#include "asn1.h"
|
||||
#include "ldap.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include <stdlib.h>
|
||||
#include "asn1.h"
|
||||
#include "ldap.h"
|
||||
|
||||
size_t scan_ldapsearchrequest(const char* src,const char* max,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include <stdlib.h>
|
||||
#include "asn1.h"
|
||||
#include "ldap.h"
|
||||
|
||||
size_t scan_ldapsearchresultentry(const char* src,const char* max,struct SearchResultEntry* sre) {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include <asn1.h>
|
||||
#include <ldap.h>
|
||||
#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);
|
||||
|
||||
129
t10.c
Normal file
129
t10.c
Normal file
@@ -0,0 +1,129 @@
|
||||
#include <stdio.h>
|
||||
#include <byte.h>
|
||||
#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<max) {
|
||||
size_t i;
|
||||
printf("%*s",indent,"");
|
||||
cl=scan_asn1tag(buf,maxstack[sptr],&tc,&tt,&tag);
|
||||
if (cl==0) {
|
||||
printf("[could not parse tag]\n");
|
||||
return;
|
||||
}
|
||||
printf("tag ");
|
||||
switch (tc) {
|
||||
case UNIVERSAL: printf("UNIVERSAL"); break;
|
||||
case APPLICATION: printf("APPLICATION"); break;
|
||||
case PRIVATE: printf("PRIVATE"); break;
|
||||
case CONTEXT_SPECIFIC: printf("CONTEXT_SPECIFIC"); break;
|
||||
default: printf("[illegal tag class 0x%x]\n",tc); return;
|
||||
}
|
||||
printf(" ");
|
||||
switch (tt) {
|
||||
case PRIMITIVE: printf("PRIMITIVE"); break;
|
||||
case CONSTRUCTED: printf("CONSTRUCTED"); break;
|
||||
default: printf("[illegal tag type 0x%x]\n",tt); return;
|
||||
}
|
||||
printf(" ");
|
||||
if (tc!=UNIVERSAL)
|
||||
printf("%d (0x%x)",tag,tag);
|
||||
else switch (tag) {
|
||||
case BOOLEAN: printf("BOOLEAN"); break;
|
||||
case INTEGER: printf("INTEGER"); break;
|
||||
case BIT_STRING: printf("BIT_STRING"); break;
|
||||
case OCTET_STRING: printf("OCTET_STRING"); break;
|
||||
case ENUMERATED: printf("ENUMERATED"); break;
|
||||
case SEQUENCE_OF: printf("SEQUENCE_OF"); break;
|
||||
case SET_OF: printf("SET_OF"); break;
|
||||
case UTCTIME: printf("UTCTime"); break;
|
||||
default: printf("[unsupported tag 0x%x]",tag); break;
|
||||
}
|
||||
|
||||
buf+=cl;
|
||||
cl=scan_asn1length(buf,maxstack[sptr],&len);
|
||||
if (cl==0) {
|
||||
puts("[could not parse length]");
|
||||
return;
|
||||
}
|
||||
printf(" length %zu\n",len);
|
||||
buf+=cl;
|
||||
|
||||
if (tc==UNIVERSAL && tt==PRIMITIVE) {
|
||||
if (tag==INTEGER) {
|
||||
unsigned long l;
|
||||
size_t mlen;
|
||||
mlen=scan_asn1rawint(buf,maxstack[sptr],cl,&l);
|
||||
if (mlen)
|
||||
printf("%*s-> %ld\n",indent,"",l);
|
||||
} else if (tag==OCTET_STRING) {
|
||||
printf("%*s-> \"",indent,"");
|
||||
for (i=0; i<len; ++i) {
|
||||
if (buf[i]<' ')
|
||||
printf("\\x%02x",buf[i]);
|
||||
else
|
||||
putchar(buf[i]);
|
||||
}
|
||||
printf("\"\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (tt==CONSTRUCTED) {
|
||||
printf("%*s{\n",indent,"");
|
||||
indent+=2;
|
||||
if (sptr>=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<l; ++i)
|
||||
printf("%02x ",(unsigned char)(buf[i]));
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
printasn1(buf,buf+l);
|
||||
|
||||
|
||||
{
|
||||
unsigned long a;
|
||||
unsigned long a2;
|
||||
unsigned long b;
|
||||
struct string c;
|
||||
l=scan_asn1generic(buf,buf+l,"a{!is}",&a,&a2,&b,&c);
|
||||
printf("%lu\n",l);
|
||||
if (l) {
|
||||
printf("got application tag %d (should be 8)\n",a);
|
||||
printf("got sequence length %d\n",a2);
|
||||
printf("got integer %d (should be 23)\n",b);
|
||||
printf("got string \"%.*s\" (should be \"fnord\")\n",c.l,c.s);
|
||||
}
|
||||
}
|
||||
}
|
||||
1
t2.c
1
t2.c
@@ -2,7 +2,6 @@
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include "mmap.h"
|
||||
#include "asn1.h"
|
||||
#include "ldap.h"
|
||||
#endif
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user