check in work in progress.
Please see README.
This commit is contained in:
57
Makefile
Normal file
57
Makefile
Normal 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
28
README
Normal 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
74
asn1.h
Normal 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
12
bindrequest.c
Normal 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
11
fmt_asn1int.c
Normal 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
19
fmt_asn1intpayload.c
Normal 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
26
fmt_asn1length.c
Normal 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
9
fmt_asn1string.c
Normal 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
26
fmt_asn1tag.c
Normal 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
10
fmt_asn1transparent.c
Normal 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
15
fmt_ldapbindrequest.c
Normal 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
20
fmt_ldapbindresponse.c
Normal 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
13
fmt_ldapmessage.c
Normal 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
56
ldap.h
Normal 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
74
ldapclient.c
Normal 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
12
scan_asn1ENUMERATED.c
Normal 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
12
scan_asn1INTEGER.c
Normal 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
17
scan_asn1SEQUENCE.c
Normal 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
12
scan_asn1STRING.c
Normal 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
21
scan_asn1int.c
Normal 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
18
scan_asn1length.c
Normal 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
13
scan_asn1string.c
Normal 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
19
scan_asn1tag.c
Normal 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
19
scan_ldapbindrequest.c
Normal 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
24
scan_ldapbindresponse.c
Normal 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
22
scan_ldapmessage.c
Normal 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
29
strduptab.c
Normal 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
13
strduptab.h
Normal 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
29
strstorage.c
Normal 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
5
strstorage.h
Normal 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
557
t.c
Normal 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
143
t1.c
Normal 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
49
t2.c
Normal 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
58
tinyldap.c
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user