check in work in progress.

Please see README.
This commit is contained in:
leitner
2002-01-14 16:14:31 +00:00
commit 2d32361380
34 changed files with 1522 additions and 0 deletions

57
Makefile Normal file
View File

@@ -0,0 +1,57 @@
#DEBUG=1
all: t t1 t2 bindrequest tinyldap ldapclient
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
ldap.a: scan_ldapmessage.o fmt_ldapmessage.o fmt_ldapbindrequest.o \
scan_ldapbindrequest.o fmt_ldapbindresponse.o scan_ldapbindresponse.o
DIET=diet -Os
CC=gcc
CFLAGS=-pipe -I. -Wall
ifneq ($(DEBUG),)
DIET=diet
CFLAGS=-pipe -I. -Wall -g
endif
%.o: %.c
$(DIET) $(CC) $(CFLAGS) -c $<
%.a:
ar cru $@ $^
%: %.c
$(DIET) $(CC) $(CFLAGS) -o $@ $^ -lowfat
t1: strduptab.o strstorage.o
t2: ldap.a asn1.a
bindrequest tinyldap ldapclient: ldap.a asn1.a
strduptab.o: strduptab.c
gcc $(CFLAGS) -c $^
.PHONY: clean tar
clean:
rm -f t t1 t2 *.[ao] bindrequest tinyldap
tar: clean
cd ..; tar cvvf ldap.tar.bz2 ldap --use=bzip2 --exclude CVS --exclude exp.ldif --exclude polyp* --exclude rfc*
fmt_asn1int.o: fmt_asn1int.c
fmt_asn1intpayload.o: fmt_asn1intpayload.c
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
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_ldapmessage.o: scan_ldapmessage.c asn1.h ldap.h

28
README Normal file
View File

@@ -0,0 +1,28 @@
polyp-00 ist der ASN.1-Code, der mir gemailt wurde.
Leider half er mir nicht sonderlich beim Verständnis von LDAP, daher hab
ich das nochmal selber angefangen.
Nachdem mir der Parser beim Verständnis geholfen hat, weiß ich jetzt,
wie der Parser wirklich aussehen muß, und habe ihn in Form von scan_*
Routinen neugehackt. Er ist dadurch viel übersichtlicher geworden.
Die Routinen auf dem höchsten Level sind scan_ldapmessage und
scan_ldapbindrequest, und damit erschöpft sich der Parser im Moment auch
schon. Ich habe auch gleich angefangen, einen LDAP Formatter zu
schreiben, der in Form der fmt_* Routinen vorliegt, und er ist genau so
weit wie der Parser, nämlich kann er eine BindResponse mit der gleichen
Message-ID wie der BindRequest formatieren, in eine LDAPMessage
einpacken und das auf file handle 1 ausgeben. Das Ergebnis entspricht
den Paketen von openldap, d.h. scheint zu funktionieren.
bindrequest ist die Client-Testanwendung. Er stellt einen BindRequest
und gibt ihn auf stdout aus.
-rwxr-xr-x 1 leitner users 1676 Jan 14 02:58 bindrequest
tinyldap ist die Server-Testanwendung. Er list eine LDAPMessage von
stdin, schaut ob es ein BindRequest ist, und wenn ja, dann generiert er
eine passende BindResponse.
-rwxr-xr-x 1 leitner users 4084 Jan 14 03:13 tinyldap
diet libc und libowfat rulen! ;)

74
asn1.h Normal file
View File

@@ -0,0 +1,74 @@
enum asn1_tagclass {
UNIVERSAL=(0<<6),
APPLICATION=(1<<6),
PRIVATE=(2<<6),
CONTEXT_SPECIFIC=(3<<6)
};
enum asn1_tagtype {
PRIMITIVE=(0<<5),
CONSTRUCTED=(1<<5)
};
enum asn1_tag {
INTEGER=2,
OCTET_STRING=4,
ENUMERATED=10,
SEQUENCE_OF=16,
};
/* write int in least amount of bytes, return number of bytes */
/* as used in ASN.1 tag */
int fmt_asn1tag(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,unsigned long tag);
/* write int in least amount of bytes, return number of bytes */
/* as used in ASN.1 length */
int fmt_asn1length(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_asn1intpayload(char* dest,unsigned 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 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. */
/* does not wrote the payload itself, just the header! First construct
* the sequence/octet string so you know the length, then use
* fmt_asn1transparent to write the header before it */
int fmt_asn1transparent(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,enum asn1_tag tag,unsigned long l);
/* write string in least amount of bytes, return number of bytes */
/* as used in ASN.1 OCTET STRING. */
int fmt_asn1string(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,enum asn1_tag tag,const char* c,unsigned long l);
/* write ASN.1 OCTET STRING */
#define fmt_asn1OCTETSTRING(dest,c,l) fmt_asn1string(dest,UNIVERSAL,PRIMITIVE,OCTET_STRING,c,l);
/* write ASN.1 INTEGER */
#define fmt_asn1INTEGER(dest,l) fmt_asn1int(dest,UNIVERSAL,PRIMITIVE,INTEGER,l);
/* write ASN.1 ENUMERATED */
#define fmt_asn1ENUMERATED(dest,l) fmt_asn1int(dest,UNIVERSAL,PRIMITIVE,ENUMERATED,l);
/* write ASN.1 SEQUENCE */
#define fmt_asn1SEQUENCE(dest,l) fmt_asn1transparent(dest,UNIVERSAL,CONSTRUCTED,SEQUENCE_OF,l);
int scan_asn1tag(const char* src,const char* max,
enum asn1_tagclass* tc,enum asn1_tagtype* tt, unsigned long* tag);
int scan_asn1length(const char* src,const char* max,unsigned long* length);
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_asn1string(const char* src,const char* max,
enum asn1_tagclass* tc,enum asn1_tagtype* tt,unsigned long* tag,
const char** s,unsigned long* l);
int scan_asn1SEQUENCE(const char* src,const char* max,unsigned long* len);
int scan_asn1INTEGER(const char* src,const char* max,unsigned 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);

12
bindrequest.c Normal file
View File

@@ -0,0 +1,12 @@
#include <unistd.h>
#include "ldap.h"
int main() {
char buf[1024];
int s=100;
int len=fmt_ldapbindrequest(buf+s,3,"","");
int hlen=fmt_ldapmessage(0,1,0,len);
fmt_ldapmessage(buf+s-hlen,1,0,len);
write(1,buf+s-hlen,len+hlen);
return 0;
}

11
fmt_asn1int.c Normal file
View File

@@ -0,0 +1,11 @@
#include <asn1.h>
int fmt_asn1int(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,enum asn1_tag tag,unsigned long l) {
int len,tmp;
/* first the tag */
if (!dest) return 2+fmt_asn1intpayload(0,l);
len=fmt_asn1tag(dest,tc,tt,tag);
tmp=fmt_asn1intpayload(dest+len+1,l);
if (fmt_asn1length(dest+len,tmp)!=1) return 0;
return len+tmp+1;
}

19
fmt_asn1intpayload.c Normal file
View File

@@ -0,0 +1,19 @@
#include <asn1.h>
int fmt_asn1intpayload(char* dest,unsigned long l) {
int needed=sizeof l;
int i;
for (i=1; i<needed; ++i) {
if (!(l>>(i*8)))
break;
}
if (dest) {
int j=i;
while (j) {
--j;
*dest=(l>>(j*8))&0xff;
++dest;
}
}
return i;
}

26
fmt_asn1length.c Normal file
View File

@@ -0,0 +1,26 @@
#include "asn1.h"
/* write int in least amount of bytes, return number of bytes */
/* as used in ASN.1 length */
int fmt_asn1length(char* dest,unsigned long l) {
/* encoding is either l%128 or (0x80+number of bytes,bytes) */
int needed=(sizeof l);
int i;
if (l<128) {
if (dest) *dest=l&0x7f;
return 1;
}
for (i=1; i<needed; ++i)
if (!(l>>(i*8)))
break;
if (dest) {
int j=i;
*dest=0x80+i; ++dest;
while (j) {
--j;
*dest=((l>>(j*8))&0xff);
++dest;
}
}
return i+1;
}

9
fmt_asn1string.c Normal file
View File

@@ -0,0 +1,9 @@
#include "asn1.h"
#include "byte.h"
int fmt_asn1string(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,enum asn1_tag tag,const char* c,unsigned long l) {
int len;
len=fmt_asn1transparent(dest,tc,tt,tag,l);
if (dest) byte_copy(dest+len,l,c);
return len+l;
}

26
fmt_asn1tag.c Normal file
View File

@@ -0,0 +1,26 @@
#include "asn1.h"
/* write int in least amount of bytes, return number of bytes */
/* as used in ASN.1 tags */
int fmt_asn1tag(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,unsigned long l) {
/* encoding is either l%128 or (0x80+number of bytes,bytes) */
int needed=(sizeof l)+1;
int 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) {
int j=i;
*dest=(int)tc+(int)tt+0x1f; ++dest;
while (j) {
--j;
*dest=((l>>(j*7))&0x7f);
++dest;
}
}
return i+1;
}

10
fmt_asn1transparent.c Normal file
View File

@@ -0,0 +1,10 @@
#include "asn1.h"
#include "byte.h"
int fmt_asn1transparent(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,enum asn1_tag tag,unsigned long l) {
int len,tmp;
/* first the tag */
len=fmt_asn1tag(dest,tc,tt,tag);
tmp=fmt_asn1length(dest?dest+len:dest,l);
return tmp+len;
}

15
fmt_ldapbindrequest.c Normal file
View File

@@ -0,0 +1,15 @@
#include "asn1.h"
#include "ldap.h"
int fmt_ldapbindrequest(char* dest,long version,char* name,char* simple) {
int l,sum=0;
int nlen=strlen(name);
sum=l=fmt_asn1INTEGER(dest,version);
if (dest) dest+=l;
l=fmt_asn1OCTETSTRING(dest,name,nlen);
sum+=l+nlen; if (dest) dest+=l+nlen;
nlen=strlen(simple);
l=fmt_asn1string(dest,PRIVATE,PRIMITIVE,0,simple,nlen);
if (dest) dest+=l+nlen;
return sum+l+nlen;
}

20
fmt_ldapbindresponse.c Normal file
View File

@@ -0,0 +1,20 @@
#include "asn1.h"
#include "ldap.h"
int fmt_ldapbindresponse(char* dest,long result,char* matcheddn,char* errormessage,char* referral) {
int l,sum=0;
int nlen;
sum=l=fmt_asn1ENUMERATED(dest,result);
if (dest) dest+=l;
nlen=strlen(matcheddn);
l=fmt_asn1OCTETSTRING(dest,matcheddn,nlen);
sum+=l+nlen; if (dest) dest+=l+nlen;
nlen=strlen(errormessage);
l=fmt_asn1OCTETSTRING(dest,errormessage,nlen);
sum+=l+nlen; if (dest) dest+=l+nlen;
nlen=strlen(referral);
l=fmt_asn1OCTETSTRING(dest,referral,nlen);
if (dest) dest+=l+nlen;
return sum+l+nlen;
}

13
fmt_ldapmessage.c Normal file
View File

@@ -0,0 +1,13 @@
#include "asn1.h"
#include "ldap.h"
int fmt_ldapmessage(char* dest,long messageid,long op,long len) {
int l,l2,l3;
l2=fmt_asn1INTEGER(0,messageid);
l3=fmt_asn1transparent(0,APPLICATION,CONSTRUCTED,op,len);
l=fmt_asn1SEQUENCE(dest,len+l2+l3);
if (!dest) return l+l2+l3;
l+=fmt_asn1INTEGER(dest+l,messageid);
l+=fmt_asn1transparent(dest+l,APPLICATION,CONSTRUCTED,op,len);
return l;
}

56
ldap.h Normal file
View File

@@ -0,0 +1,56 @@
struct attributevalueassertion {
unsigned char* desc,* value;
long dlen, vlen;
};
struct attributelist {
unsigned char* a;
long alen;
struct attributelist* next;
};
struct filter {
enum {
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;
enum {
PREFIX=0, ANY=1, SUFFIX=2
} substrtype;
struct filter* x,*next;
};
struct string {
long l;
const char* s;
};
enum ldapops {
BindRequest=0, BindResponse=1,
UnbindRequest=2,
SearchRequest=3, SearchResultEntry=4, SearchResultDone=5,
ModifyRequest=6, ModifyResponse=7,
AddRequest=8, AddResponse=9,
DelRequest=10, DelResponse=11,
ModifyDNRequest=12, ModifyDNResponse=13,
CompareRequest=14, CompareResponse=15,
AbandonRequest=16,
ExtendedRequest=23 /* das ist doch kein Zufall?! */, ExtendedResponse=24
};
void freefilter(struct filter* f);
int scan_ldapmessage(const char* src,const char* max,
long* messageid,long* op,long* len);
int scan_ldapbindrequest(const char* src,const char* max,
long* version,struct string* name,long* method);
int scan_ldapbindresponse(const char* src,const char* max,
long* result,struct string* matcheddn,
struct string* errormessage,struct string* referral);
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);

74
ldapclient.c Normal file
View File

@@ -0,0 +1,74 @@
#include <unistd.h>
#include "byte.h"
#include "buffer.h"
#include "ldap.h"
#include "socket.h"
#include "ip4.h"
#define BUFSIZE 8192
int main() {
int sock;
char buf[BUFSIZE];
int len=0;
long messageid=1;
sock=socket_tcp4();
{
char ip[4];
scan_ip4(ip,"127.0.0.1");
if (socket_connect4(sock,ip,389)) {
buffer_putsflush(buffer_2,"could not connect to ldap server!\n");
return 1;
}
}
{
char outbuf[1024];
int s=100;
int len=fmt_ldapbindrequest(outbuf+s,3,"","");
int hlen=fmt_ldapmessage(0,messageid,BindRequest,len);
fmt_ldapmessage(outbuf+s-hlen,messageid,BindRequest,len);
write(sock,outbuf+s-hlen,len+hlen);
}
for (;;) {
int tmp=read(sock,buf+len,BUFSIZE-len);
int res;
long messageid,op,Len;
if (tmp==0) { write(2,"eof!\n",5); return 0; }
if (tmp<1) { write(2,"error!\n",7); return 1; }
len+=tmp;
res=scan_ldapmessage(buf,buf+len,&messageid,&op,&Len);
if (res>0) {
buffer_puts(buffer_2,"got message of length ");
buffer_putulong(buffer_2,Len);
buffer_puts(buffer_2," with id ");
buffer_putulong(buffer_2,messageid);
buffer_puts(buffer_2,": op ");
buffer_putulong(buffer_2,op);
buffer_putsflush(buffer_2,".\n");
switch (op) {
case BindResponse:
{
long result;
struct string matcheddn,errormessage,referral;
res=scan_ldapbindresponse(buf+res,buf+res+len,&result,&matcheddn,&errormessage,&referral);
if (res>=0) {
buffer_puts(buffer_2,"bind response: result ");
buffer_putulong(buffer_2,result);
buffer_puts(buffer_2,", matched dn \"");
buffer_put(buffer_2,matcheddn.s,matcheddn.l);
buffer_puts(buffer_2,"\", error message \"");
buffer_put(buffer_2,errormessage.s,errormessage.l);
buffer_puts(buffer_2,"\", referral \"");
buffer_put(buffer_2,referral.s,referral.l);
buffer_putsflush(buffer_2,"\".\n");
}
}
}
if (Len<len) {
byte_copyr(buf,len-Len,buf+len);
len-=Len;
}
}
}
}

12
scan_asn1ENUMERATED.c Normal file
View File

@@ -0,0 +1,12 @@
#include "asn1.h"
int scan_asn1ENUMERATED(const char* src,const char* max,unsigned long* l) {
int tmp;
long tag;
enum asn1_tagclass tc;
enum asn1_tagtype tt;
if ((tmp=scan_asn1int(src,max,&tc,&tt,&tag,l)))
if (tc==UNIVERSAL || tt==PRIMITIVE || tag==ENUMERATED)
return tmp;
return 0;
}

12
scan_asn1INTEGER.c Normal file
View File

@@ -0,0 +1,12 @@
#include "asn1.h"
int scan_asn1INTEGER(const char* src,const char* max,unsigned long* l) {
int tmp;
long tag;
enum asn1_tagclass tc;
enum asn1_tagtype tt;
if ((tmp=scan_asn1int(src,max,&tc,&tt,&tag,l)))
if (tc==UNIVERSAL || tt==PRIMITIVE || tag==INTEGER)
return tmp;
return 0;
}

17
scan_asn1SEQUENCE.c Normal file
View File

@@ -0,0 +1,17 @@
#include "asn1.h"
int scan_asn1SEQUENCE(const char* src,const char* max,unsigned long* len) {
int res,tmp;
long tlen;
long tag;
enum asn1_tagclass tc;
enum asn1_tagtype tt;
if (!(res=scan_asn1tag(src,max,&tc,&tt,&tag))) return 0;
if (!(tmp=scan_asn1length(src+res,max,&tlen))) return 0;
res+=tmp;
if (src+res+tlen>max) return 0;
*len=res+tlen;
if (tc==UNIVERSAL || tt==CONSTRUCTED || tag==SEQUENCE_OF)
return res;
return 0;
}

12
scan_asn1STRING.c Normal file
View File

@@ -0,0 +1,12 @@
#include "asn1.h"
int scan_asn1STRING(const char* src,const char* max,const char** s,unsigned long* l) {
int tmp;
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==OCTET_STRING)
return tmp;
return 0;
}

21
scan_asn1int.c Normal file
View File

@@ -0,0 +1,21 @@
#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 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;
if (src+len+tlen>max) return 0;
*l=handleint(src+len,tlen);
return len+tlen;
}

18
scan_asn1length.c Normal file
View File

@@ -0,0 +1,18 @@
#include "asn1.h"
int scan_asn1length(const char* src,const char* max,unsigned long* length) {
const char* orig=src;
if (src>max) return 0;
if (*src&0x80) {
int chars=*src&0x7f;
long l=0;
while (chars>0) {
if (++src>=max) return 0;
l=l*256+*src;
--chars;
}
*length=l;
} else
*length=*src&0x7f;
return src-orig+1;
}

13
scan_asn1string.c Normal file
View File

@@ -0,0 +1,13 @@
#include "asn1.h"
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) {
int len,tmp;
if (!(len=scan_asn1tag(src,max,tc,tt,tag))) return 0;
if (!(tmp=scan_asn1length(src+len,max,l))) return 0;
len+=tmp;
if (src+len+*l>max) return 0;
*s=src+len;
return len+*l;
}

19
scan_asn1tag.c Normal file
View File

@@ -0,0 +1,19 @@
#include "asn1.h"
int scan_asn1tag(const char* src,const char* max,enum asn1_tagclass* tc,enum asn1_tagtype* tt,unsigned long* tag) {
const char* orig=src;
*tc=(*src&0xC0);
*tt=(*src&0x20);
if (max<src) return 0;
if ((*src & 0x1f) == 0x1f) {
for (;;) {
if (src>max) return 0;
*tag=*tag*128+(*src&0x7F);
if (!(*src&0x80)) break;
}
return (src-orig+1);
} else {
*tag=*src&0x1f;
return 1;
}
}

19
scan_ldapbindrequest.c Normal file
View File

@@ -0,0 +1,19 @@
#include "asn1.h"
#include "ldap.h"
int scan_ldapbindrequest(const char* src,const char* max,
long* version,struct string* name,long* method) {
int res,tmp;
if (!(res=scan_asn1INTEGER(src,max,version))) return 0;
if (!(tmp=scan_asn1STRING(src+res,max,&name->s,&name->l))) return 0;
res+=tmp;
{
enum asn1_tagclass tc;
enum asn1_tagtype tt;
long method;
if (!(tmp=scan_asn1tag(src+res,max,&tc,&tt,&method))) return 0;
if (tc!=PRIVATE || tt!=PRIMITIVE) return 0;
res+=tmp;
}
return res;
}

24
scan_ldapbindresponse.c Normal file
View File

@@ -0,0 +1,24 @@
#include "asn1.h"
#include "ldap.h"
int scan_ldapbindresponse(const char* src,const char* max,
long* result,struct string* matcheddn,
struct string* errormessage,struct string* referral) {
int res,tmp;
if (!(res=scan_asn1ENUMERATED(src,max,result))) return 0;
if (!(tmp=scan_asn1STRING(src+res,max,&matcheddn->s,&matcheddn->l))) return 0;
res+=tmp;
if (src+res<max) {
if (!(tmp=scan_asn1STRING(src+res,max,&errormessage->s,&errormessage->l))) return 0;
res+=tmp;
} else {
errormessage->s=0; errormessage->l=0;
}
if (src+res<max) {
if (!(tmp=scan_asn1STRING(src+res,max,&referral->s,&referral->l))) return 0;
res+=tmp;
} else {
referral->s=0; referral->l=0;
}
return res;
}

22
scan_ldapmessage.c Normal file
View File

@@ -0,0 +1,22 @@
#include "asn1.h"
#include "ldap.h"
int scan_ldapmessage(const char* src,const char* max,
long* messageid,long* op,long* len) {
int res,tmp;
if (!(res=scan_asn1SEQUENCE(src,max,len))) goto error;
if (!(tmp=scan_asn1INTEGER(src+res,max,messageid))) goto error;
res+=tmp;
{
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;
res+=tmp;
if (!(tmp=scan_asn1length(src+res,max,len))) goto error;
res+=tmp;
}
return res;
error:
return 0;
}

29
strduptab.c Normal file
View File

@@ -0,0 +1,29 @@
#include <stdlib.h>
#include "str.h"
#include "strduptab.h"
#include "strstorage.h"
#define PAGESIZE 4096
const char* strduptab_add(struct stringduptable* t,const char* s) {
int i;
for (i=0; i<t->n; ++i)
if (str_equal(t->s[i],s))
return t->s[i];
if (t->n>=t->a) {
const char** x;
int a=t->a*2;
if (!a) a=1024;
if (!(x=realloc((char**)t->s,a*sizeof(char*))))
return 0;
t->a=a;
t->s=x;
}
{
const char* x=strstorage_add(s,strlen(s)+1);
if (!x) return 0;
s=x;
}
t->s[t->n]=s; ++t->n;
return s;
}

13
strduptab.h Normal file
View File

@@ -0,0 +1,13 @@
/* save memory for constant strings by keeping a list of the ones that
* we already saw and not allocating memory for each new one. The only
* API is "add string and return pointer". Will try to insert the
* string in the table. If the same string was already there, it will
* return a pointer to that string, otherwise it will insert a copy of
* the new string. */
struct stringduptable {
int n,a;
const char** s;
};
const char* strduptab_add(struct stringduptable* t,const char* s);

29
strstorage.c Normal file
View File

@@ -0,0 +1,29 @@
#include <stdlib.h>
#include "byte.h"
#include "strstorage.h"
#define PAGESIZE 4096
const char* strstorage_add(const char* s,int n) {
static char* page=0;
static int leftonpage=0;
if (leftonpage>=n) {
copyit:
byte_copy(page,n,s);
s=page;
page+=n;
leftonpage-=n;
} else {
if (n>=PAGESIZE/2) {
char* tmp=malloc(n);
if (!tmp) return 0;
byte_copy(tmp,n,s);
s=tmp;
} else {
if (!(page=malloc(PAGESIZE))) return 0;
leftonpage=PAGESIZE;
goto copyit;
}
}
return s;
}

5
strstorage.h Normal file
View File

@@ -0,0 +1,5 @@
/* provide a string allocator. It is add-only, you can't free a string
* later. On the plus side, the allocation overhead is close to zero.
* Will a stored copy of the string. */
const char* strstorage_add(const char* s,int n);

557
t.c Normal file
View File

@@ -0,0 +1,557 @@
#include "open.h"
#include "buffer.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stralloc.h>
#if 0
LDAPMessage ::= SEQUENCE {
messageID MessageID,
protocolOp CHOICE {
bindRequest BindRequest,
bindResponse BindResponse,
unbindRequest UnbindRequest,
searchRequest SearchRequest,
searchResEntry SearchResultEntry,
searchResDone SearchResultDone,
searchResRef SearchResultReference,
modifyRequest ModifyRequest,
modifyResponse ModifyResponse,
addRequest AddRequest,
addResponse AddResponse,
delRequest DelRequest,
delResponse DelResponse,
modDNRequest ModifyDNRequest,
modDNResponse ModifyDNResponse,
compareRequest CompareRequest,
compareResponse CompareResponse,
abandonRequest AbandonRequest,
extendedReq ExtendedRequest,
extendedResp ExtendedResponse },
controls [0] Controls OPTIONAL }
MessageID ::= INTEGER (0 .. maxInt)
maxInt INTEGER ::= 2147483647 -- (2^^31 - 1) --
LDAPString ::= OCTET STRING
LDAPOID ::= OCTET STRING
LDAPDN ::= LDAPString
RelativeLDAPDN ::= LDAPString
#endif
static long int handleint(unsigned char* c,int len) {
long l=0;
while (len) {
l=l*256+*c;
--len; ++c;
}
return l;
}
static int gethibitlen(unsigned char* c,unsigned char* max,unsigned long* len) {
unsigned char* orig=c;
if (*c&0x80) {
int chars=*c&0x7f;
*len=0;
while (chars>0) {
if (++c>=max) return 0;
*len=*len*256+*c;
--chars;
}
} else
*len=*c&0x7f;
return c-orig+1;
}
static int parsetag(unsigned char* c,unsigned char* max,unsigned long* tag,unsigned long* len) {
unsigned char* orig=c;
if (max<c+2) return 0;
*tag=*len=0;
/* find tag and length */
if ((*c&0x1f)==0x1f)
for (;;) {
if (++c>=max) return 0;
*tag=*tag*128+(*c&0x7F);
if (!(*c&0x80)) break;
}
else
*tag=*c&0x1f;
++c;
c+=gethibitlen(c,max,len);
return c-orig;
}
static void interpret(unsigned char* c,int dlen) {
// unsigned char *max=c+dlen;
// enum { PRIMITIVE, CONSTRUCTED } type;
unsigned long tag=0;
unsigned long len=0;
switch (*c>>6) {
case 0: puts("universal"); break;
case 1: puts("application"); break;
case 2: puts("context-specific"); break;
case 3: puts("private"); break;
}
if (!(*c & 0x20)) { /* primitive encoding */
puts("primitive, definite-length");
} else {
puts("constructed, definite-length");
}
if ((*c&0x1f) == 0x1f) { /* high-tag-number form */
for (;;) {
++c;
tag=tag*128+(*c&0x7F);
if (!(*c&0x80)) break;
}
} else
tag=*c&0x1f;
++c;
if (*c&0x80) {
int chars=*c&0x7f;
while (chars>0) {
++c;
len=len*256+*c;
--chars;
}
} else
len=*c&0x7f;
++c;
switch (tag) {
case 2:
printf(" -> INTEGER: %ld\n",handleint(c,len));
break;
case 4:
printf(" -> OCTET STRING: "); fwrite(c,len,1,stdout); printf("\n");
break;
case 10:
printf(" -> ENUMERATED: %ld\n",handleint(c,len));
break;
case 16:
puts("SEQUENCE OF");
break;
default:
printf("unknown tag %lu (%lx)\n",tag,tag);
}
if (tag!=16) c+=len;
// if (c<max) interpret(c,max-c);
}
/* parse ASN.1 INTEGER, return length or 0 on parse error */
static unsigned int parseintlike(unsigned char* buf,unsigned char* max,int Tag,long int* l) {
int res;
unsigned long tag,len;
unsigned char* orig=buf;
if ((res=parsetag(buf,max,&tag,&len))) {
if (tag!=Tag) return 0;
buf+=res;
*l=0;
while (len>sizeof(long)) {
if (*buf) return 0; /* number larger than native int size */
++buf; --len;
}
while (len) {
*l=*l*256+*buf;
++buf; --len;
}
return buf-orig;
}
return 0;
}
static unsigned int parseint(unsigned char* buf,unsigned char* max,long int* l) {
return parseintlike(buf,max,2,l);
}
static unsigned int parseenum(unsigned char* buf,unsigned char* max,long int* l) {
return parseintlike(buf,max,10,l);
}
static unsigned int parsebool(unsigned char* buf,unsigned char* max,long int* l) {
return parseintlike(buf,max,1,l);
}
/* parse ASN.1 OCTET STRING, return length or 0 on parse error */
static unsigned int parseoctetstring(unsigned char* buf,unsigned char* max,unsigned char** s,unsigned long* slen) {
int res;
unsigned long tag;
unsigned char* orig=buf;
if ((res=parsetag(buf,max,&tag,slen))) {
if (tag!=4) return 0;
buf+=res;
*s=buf;
buf+=*slen;
return buf-orig;
}
return 0;
}
static int handlebind(unsigned char* buf,unsigned char* max,long messageid,int answerfd) {
int res;
long bindversion;
unsigned char* s;
unsigned long slen;
/* int version */
if (!(res=parseint(buf,max,&bindversion))) return -1;
buf+=res;
printf("bind version %ld\n",bindversion);
#if 0
if (bindversion>3) {
char buf[100];
int b=8,e=8;
}
#endif
/* ldapdn name */
if (!(res=parseoctetstring(buf,max,&s,&slen))) return -1;
buf+=res;
printf("name \""); fwrite(s,slen,1,stdout); printf("\"\n");
/* authentication authenticationchoice */
/* since we are such a trivial LDAP server, we discard bind requests */
return 0;
}
struct attributevalueassertion {
unsigned char* desc,* value;
long dlen, vlen;
};
struct attributelist {
unsigned char* a;
long alen;
struct attributelist* next;
};
static int parseava(unsigned char* buf,unsigned char* max, struct attributevalueassertion* ava) {
/* SEQUENCE { desc: OCTET STRING, value: OCTET STRING } */
int res;
unsigned char* orig=buf;
if (!(res=parseoctetstring(buf,max,&ava->desc,&ava->dlen))) return 0;
buf+=res;
if (!(res=parseoctetstring(buf,max,&ava->value,&ava->vlen))) return 0;
buf+=res;
printf("attribute value assertion: \"");
fwrite(ava->desc,ava->dlen,1,stdout);
printf("\" \"");
fwrite(ava->value,ava->vlen,1,stdout);
printf("\"\n");
return buf-orig;
}
struct filter {
enum {
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;
enum {
PREFIX=0, ANY=1, SUFFIX=2
} substrtype;
struct filter* x,*next;
};
static int parsefilter(unsigned char* buf,unsigned char* max,struct filter** f) {
/*
Filter ::= CHOICE {
and [0] SET OF Filter,
or [1] SET OF Filter,
not [2] Filter,
equalityMatch [3] AttributeValueAssertion,
substrings [4] SubstringFilter,
greaterOrEqual [5] AttributeValueAssertion,
lessOrEqual [6] AttributeValueAssertion,
present [7] AttributeDescription,
approxMatch [8] AttributeValueAssertion,
extensibleMatch [9] MatchingRuleAssertion }
SubstringFilter ::= SEQUENCE {
type AttributeDescription,
-- at least one must be present
substrings SEQUENCE OF CHOICE {
initial [0] LDAPString,
any [1] LDAPString,
final [2] LDAPString } }
MatchingRuleAssertion ::= SEQUENCE {
matchingRule [1] MatchingRuleId OPTIONAL,
type [2] AttributeDescription OPTIONAL,
matchValue [3] AssertionValue,
dnAttributes [4] BOOLEAN DEFAULT FALSE }
*/
unsigned char* orig=buf;
unsigned long slen,tag;
int res;
*f=0;
if ((buf[0]>>6)!=2) goto error; /* context-specific */
if (!(res=parsetag(buf,max,&tag,&slen))) goto error;
if (tag<0 || tag>9) goto error;
*f=malloc(sizeof(struct filter));
(*f)->x=(*f)->next=0;
(*f)->type=tag;
buf+=res;
switch (tag) {
case 3: case 5: case 6: case 8:
if (!(res=parseava(buf,buf+slen,&(*f)->ava))) goto error;
buf+=res;
break;
case 0: puts("AND"); return 0;
case 1:
puts("OR");
(*f)->x=0;
while (buf<max) {
struct filter* F=(*f)->x;
int res;
if (!(res=parsefilter(buf,max,&(*f)->x))) {
if (F) { /* OK, end of sequence */
(*f)->x=F;
return buf-orig;
}
// interpret(buf,max-buf);
(*f)->x=F;
goto error;
}
(*f)->x->next=F;
buf+=res;
}
// interpret(buf,max-buf);
return 0;
case 2: puts("NOT"); return 0;
case 4:
{
unsigned char* nmax=buf+slen;
long l,tlen;
if (!(res=parseoctetstring(buf,nmax,&(*f)->ava.desc,&(*f)->ava.dlen))) goto error;
buf+=res;
printf("substr in attribute \""); fwrite((*f)->ava.desc,(*f)->ava.dlen,1,stdout); printf("\"\n");
if (!(res=parsetag(buf,nmax,&l,&tlen))) goto error;
buf+=res;
if (l != 16) goto error; /* sequence of */
if (buf+tlen != nmax) goto error; /* no more tags after the sequence */
while (buf<nmax) {
if (!(res=parsetag(buf,nmax,&l,&tlen))) goto error;
buf+=res;
(*f)->ava.value=buf; (*f)->ava.vlen=tlen;
buf+=tlen;
if (l<0 || l>2) goto error;
(*f)->substrtype=l;
switch (l) {
case 0: printf("prefix \""); break;
case 1: printf("substr \""); break;
case 2: printf("suffix \""); break;
}
fwrite((*f)->ava.value,(*f)->ava.vlen,1,stdout); printf("\"\n");
}
break;
}
case 7: puts("PRESENT"); return 0;
case 9: puts("EXTENSIBLE"); return 0;
default: goto error;
}
return buf-orig;
error:
if (*f) { free(*f); *f=0; }
return 0;
}
static void freefilter(struct filter* f) {
if (f) {
while (f->a) {
struct attributelist* a=f->a->next;
free(f->a);
f->a=a;
}
if (f->x) freefilter(f->x);
if (f->next) freefilter(f->next);
free(f);
}
}
static int handlesearch(unsigned char* buf,unsigned char* max) {
int res;
unsigned char* s;
unsigned long slen,scope,deref,sizelimit,timelimit,typesonly;
struct filter* f;
f=0;
/* int version */
if (!(res=parseoctetstring(buf,max,&s,&slen))) goto error;
buf+=res;
printf("baseObject \""); fwrite(s,slen,1,stdout); printf("\"\n");
/* scope enumerated; 0=baseObject, 1=singleLevel, 2=wholeSubtree */
if (!(res=parseenum(buf,max,&scope))) goto error;
buf+=res;
printf("scope: ");
switch (scope) {
case 0: puts("baseObject"); break;
case 1: puts("singleLevel"); break;
case 2: puts("wholeSubtree"); break;
default: goto error;
}
/* derefaliases enumerated; 0=never, 1=in searching, 2=baseobject, * 3=always */
if (!(res=parseenum(buf,max,&deref))) goto error;
buf+=res;
printf("derefaliases: ");
switch (scope) {
case 0: puts("never"); break;
case 1: puts("in searching"); break;
case 2: puts("baseobject"); break;
case 3: puts("always"); break;
default: goto error;
}
/* int sizelimit */
if (!(res=parseint(buf,max,&sizelimit))) goto error;
buf+=res;
printf("size limit %lu\n",sizelimit);
/* int timelimit */
if (!(res=parseint(buf,max,&timelimit))) goto error;
buf+=res;
printf("time limit %lu\n",timelimit);
/* bool typesonly */
if (!(res=parsebool(buf,max,&typesonly))) goto error;
buf+=res;
printf("typesonly %lu\n",typesonly);
/* filter */
if (!(res=parsefilter(buf,max,&f))) goto error;
buf+=res;
/* attributes */
{
unsigned char* nmax;
long seqlen;
struct attributelist** a=&f->a;
if (buf[0]!='0') goto error;
++buf;
buf+=gethibitlen(buf,max,&seqlen);
nmax=buf+seqlen;
if (nmax>max) goto error;
for (;;) {
if (buf>max) goto error;
if (buf==max) break;
if (!*a) *a=malloc(sizeof(struct attributelist));
(*a)->next=0;
if (!(res=parseoctetstring(buf,max,&(*a)->a,&(*a)->alen))) goto error;
buf+=res;
printf("attribute \""); fwrite((*a)->a,(*a)->alen,1,stdout); printf("\"\n");
a=&(*a)->next;
}
}
puts("ok");
return 0;
error:
freefilter(f);
return -1;
}
#define TEST
/* return length of query that was parsed OK or 0 on parse error */
static unsigned int parseldapquery(unsigned char* buf,unsigned char* max,int answerfd) {
long seqlen;
int res;
long messageid;
unsigned long tag,len;
unsigned char* orig=buf;
// interpret(buf,max-buf);
/* SEQUENCE OF */
if (buf[0]!='0') goto error;
++buf;
buf+=gethibitlen(buf,max,&seqlen);
/* INTEGER message id */
if (!(res=parseint(buf,max,&messageid))) goto error;
buf+=res;
printf("message id %ld\n",messageid);
/* CHOICE */
if ((buf[0]>>6)!=1) return 0; /* application */
if (!(res=parsetag(buf,max,&tag,&len))) goto error;
buf+=res;
switch (tag) {
case 0:
puts("bind");
if (handlebind(buf,max,messageid,answerfd)) goto error;
break;
case 2:
puts("unbind");
break;
case 3:
puts("search");
if (handlesearch(buf,buf+len)) goto error;
break;
case 16:
printf("abandon %lu\n",handleint(buf,len));
break;
#ifdef TEST
case 1:
puts("bindreply");
/*
BindResponse ::= [APPLICATION 1] SEQUENCE {
COMPONENTS OF LDAPResult,
serverSaslCreds [7] OCTET STRING OPTIONAL }
*/
{
long code,alen;
int res;
unsigned char* a;
len+=(buf-orig);
if (!(res=parseenum(buf,orig+len,&code))) goto error;
printf("code %ld\n",code);
buf+=res;
if (!(res=parseoctetstring(buf,max,&a,&alen))) goto error;
buf+=res;
printf("matchedDN \""); fwrite(a,alen,1,stdout); printf("\"\n");
if (!(res=parseoctetstring(buf,max,&a,&alen))) goto error;
buf+=res;
printf("errorMessage \""); fwrite(a,alen,1,stdout); printf("\"\n");
return len;
}
break;
case 4:
puts("searchResult");
{
int res;
long tag,alen;
unsigned char* a;
if (!(res=parseoctetstring(buf,max,&a,&alen))) goto error;
buf+=res;
printf("objectName \""); fwrite(a,alen,1,stdout); printf("\"\n");
if (!(res=parsetag(buf,max,&tag,&alen))) goto error;
if (tag != 16) goto error;
printf("sequence length %ld\n",alen);
buf+=res;
}
return 0;
#endif
default:
printf("unknown op %ld\n",tag);
return 0;
}
printf("skipping len %ld\n",len);
buf+=len;
return buf-orig;
error:
return 0;
}
int main() {
char buf[8192];
char* max;
int l,fd,res;
// fd=open_read("/tmp/ldap/127.000.000.001.32875-127.000.000.001.00389");
// fd=open_read("/tmp/ldap/127.000.000.001.32779-127.000.000.001.00389");
// fd=open_read("/tmp/ldap/127.000.000.001.38433-127.000.000.001.00389");
// fd=open_read("/tmp/ldap/127.000.000.001.00389-127.000.000.001.32779");
fd=open_read("answer");
l=read(fd,buf,8192);
max=buf+l;
close(fd);
l=0;
for (;;) {
res=parseldapquery(buf+l,max,1);
printf("res= %d\n",res);
if (res==0) break;
l+=res;
}
// interpret(buf,l);
return 0;
}

143
t1.c Normal file
View File

@@ -0,0 +1,143 @@
#include <buffer.h>
#include <scan.h>
#include <open.h>
#include <unistd.h>
#include <stdlib.h>
#include "strduptab.h"
#include "strstorage.h"
#include "str.h"
/* 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;
};
static struct stringduptable tags;
static struct stringduptable classes;
const char* dn,* mail,* sn,* cn,* objectClass;
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;
}
#if 0
buffer_puts(buffer_1,"found tag ");
buffer_put(buffer_1,buf+i,n-i);
buffer_putsflush(buffer_1,".\n");
#endif
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)->n<ATTRIBS) {
(*l)->a[(*l)->n].name=tmp;
(*l)->a[(*l)->n].value=val;
++(*l)->n;
}
}
#if 0
buffer_puts(buffer_1,"found value \"");
buffer_put(buffer_1,buf+i,n-i);
buffer_putsflush(buffer_1,"\".\n");
#endif
// write(2,".",1);
} while (!eof);
if (!(*l)->dn) {
struct ldaprec* m=(*l)->next;
free((*l));
(*l)=m;
}
return 0;
}
struct ldaprec *first=0;
int parse_ldif(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");
parserec(&in,&first);
close(fd);
return 0;
}
#ifndef INCLUDE
int main() {
parse_ldif("exp.ldif");
// read(0,buf,1);
#if 0
/* dump structure */
while (first) {
printf("dn= %s\n",first->dn);
first=first->next;
}
#endif
return 0;
}
#endif

49
t2.c Normal file
View File

@@ -0,0 +1,49 @@
#include <unistd.h>
#include <stdio.h>
#include "mmap.h"
#include "asn1.h"
#include "ldap.h"
int main(int argc,char* argv[]) {
#if 0
unsigned long size;
// char* ldapsequence=mmap_read("req",&size);
char* ldapsequence=mmap_read(argc>1?argv[1]:"capture/127.000.000.001.32779-127.000.000.001.00389",&size);
long messageid, op, len;
int res;
printf("%d\n",res=scan_ldapmessage(ldapsequence,ldapsequence+size,&messageid,&op,&len));
printf("message id %lu, op %lu, len %lu\n",messageid,op,len);
if (op==0) {
long version,namelen,method;
const char* name;
printf("%d\n",res=scan_ldapbindrequest(ldapsequence+res,ldapsequence+size,&version,&name,&namelen,&method));
printf("version %lu, name \"%*s\", method %lu\n",version,namelen,name,method);
if (method==0) {
printf("%d\n",scan_asn1STRING(ldapsequence+res,ldapsequence+size,&name,&namelen));
printf("simple \"%*s\"\n",namelen,name);
}
}
#else
char buf[1024];
int s=100;
int len=fmt_ldapbindrequest(buf+s,3,"","");
int hlen=fmt_ldapmessage(0,1,0,len);
fmt_ldapmessage(buf+s-hlen,1,0,len);
write(1,buf+s-hlen,len+hlen);
#endif
#if 0
char buf[1024];
enum asn1_tagtype tt;
enum asn1_tagclass tc;
long tag,len;
int res;
const char* c;
printf("%d\n",res=fmt_asn1int(buf,UNIVERSAL,PRIMITIVE,INTEGER,0x01020304));
printf("%d\n",scan_asn1int(buf,buf+res,&tc,&tt,&tag,&len));
printf("got %lx\n",len);
printf("%d\n",res=fmt_asn1string(buf,UNIVERSAL,PRIMITIVE,OCTET_STRING,"fnord",5));
printf("%d\n",scan_asn1string(buf,buf+res,&tc,&tt,&tag,&c,&len));
printf("got %*s\n",(int)len,c);
#endif
return 0;
}

58
tinyldap.c Normal file
View File

@@ -0,0 +1,58 @@
#include <unistd.h>
#include "byte.h"
#include "buffer.h"
#include "ldap.h"
#define BUFSIZE 8192
int main() {
char buf[BUFSIZE];
int len=0;
for (;;) {
int tmp=read(0,buf+len,BUFSIZE-len);
int res;
long messageid,op,Len;
if (tmp==0) { write(2,"eof!\n",5); return 0; }
if (tmp<1) { write(2,"error!\n",7); return 1; }
len+=tmp;
res=scan_ldapmessage(buf,buf+len,&messageid,&op,&Len);
if (res>0) {
buffer_puts(buffer_2,"got message of length ");
buffer_putulong(buffer_2,Len);
buffer_puts(buffer_2," with id ");
buffer_putulong(buffer_2,messageid);
buffer_puts(buffer_2,": op ");
buffer_putulong(buffer_2,op);
buffer_putsflush(buffer_2,".\n");
switch (op) {
case 0:
{
long version,method;
struct string name;
res=scan_ldapbindrequest(buf+res,buf+res+len,&version,&name,&method);
if (res>=0) {
buffer_puts(buffer_2,"bind request: version ");
buffer_putulong(buffer_2,version);
buffer_puts(buffer_2," for name \"");
buffer_put(buffer_2,name.s,name.l);
buffer_puts(buffer_2,"\" with method ");
buffer_putulong(buffer_2,method);
buffer_putsflush(buffer_2,".\n");
{
char outbuf[1024];
int s=100;
int len=fmt_ldapbindresponse(outbuf+s,0,"","go ahead","");
int hlen=fmt_ldapmessage(0,messageid,BindResponse,len);
fmt_ldapmessage(outbuf+s-hlen,messageid,BindResponse,len);
write(1,outbuf+s-hlen,len+hlen);
}
}
}
}
if (Len<len) {
byte_copyr(buf,len-Len,buf+len);
len-=Len;
}
}
}
}