first shot at "addrequest" support

This commit is contained in:
leitner
2007-06-28 22:17:33 +00:00
parent fefbe77ba0
commit 35f2b3b745
68 changed files with 897 additions and 339 deletions

View File

@@ -65,7 +65,7 @@ t1 parse: ldif.a storage.a
t2: ldap.a asn1.a
t3 t4 t5 addindex: storage.a
t6: storage.a
tinyldap tinyldap_standalone tinyldap_debug: ldif.a auth.a
tinyldap tinyldap_standalone tinyldap_debug: ldif.a storage.a auth.a
bindrequest tinyldap tinyldap_standalone tinyldap_debug ldapclient ldapclient_str: ldap.a asn1.a
idx2ldif: ldap.a
dumpacls: ldap.a asn1.a

16
TODO
View File

@@ -1,4 +1,20 @@
1. let tinyldap check for and incorporate updates from the journal in
the hash table
2. support modify and delete requests (should be easy)
9. test whether the acls for add actually work
10. think about how to incorporate the journal into the database while
still allowing new writes. Second journal? Switch to one-process
model?
11. think about compressed database (maybe add first n chars of each
string to index to avoid decompressing too much)
[old and obsolete]
- add auth method (openldap md5: base64, 4 bytes salt, direct hash)
- add write support with an external journal
We can also implement clustering through this journal.

View File

@@ -58,7 +58,7 @@ uint32 hashmapped(uint32 ofs,int ignorecase) {
unsigned char* c=(unsigned char*)map+ofs;
uint32 len;
if (*c) return ignorecase?hash_tolower(c,strlen((char*)c)):hash(c,strlen((char*)c));
uint32_unpack(c+1,&len);
uint32_unpack((char*)c+1,&len);
return ignorecase?hash_tolower(c+5,len):hash(c+5,len);
}

53
asn1.h
View File

@@ -1,6 +1,8 @@
/* parser and formatter for ASN.1 DER encoding.
* The parser can read BER encoding, too. */
#include <stddef.h>
enum asn1_tagclass {
UNIVERSAL=(0<<6),
APPLICATION=(1<<6),
@@ -24,29 +26,32 @@ enum asn1_tag {
/* write int in least amount of bytes, return number of bytes */
/* as used in ASN.1 tag */
unsigned int fmt_asn1tag(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,unsigned long tag);
size_t 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 */
unsigned int fmt_asn1length(char* dest,unsigned long l);
size_t fmt_asn1length(char* dest,size_t 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! */
unsigned int fmt_asn1intpayload(char* dest,unsigned long l);
size_t fmt_asn1intpayload(char* dest,unsigned long val);
/* 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! */
unsigned int fmt_asn1sintpayload(char* dest,signed long l);
size_t fmt_asn1sintpayload(char* dest,signed long val);
/* write int in least amount of bytes, return number of bytes */
/* as used in ASN.1 INTEGER or ENUMERATED. */
unsigned int fmt_asn1int(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,enum asn1_tag tag,unsigned long l);
size_t fmt_asn1int(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,
enum asn1_tag tag,unsigned long val);
/* write int in least amount of bytes, return number of bytes */
/* as used in ASN.1 INTEGER or ENUMERATED. */
unsigned int fmt_asn1sint(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,enum asn1_tag tag,signed long l);
size_t fmt_asn1sint(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,
enum asn1_tag tag,signed long val);
/* write any data type that does not require transformation in the least
* amount of bytes, return number of bytes */
@@ -54,11 +59,13 @@ unsigned int fmt_asn1sint(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,
/* 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 */
unsigned int fmt_asn1transparent(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,enum asn1_tag tag,unsigned long l);
size_t fmt_asn1transparent(char* dest,enum asn1_tagclass tc,
enum asn1_tagtype tt,enum asn1_tag tag,size_t len);
/* write string in least amount of bytes, return number of bytes */
/* as used in ASN.1 OCTET STRING. */
unsigned int fmt_asn1string(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,enum asn1_tag tag,const char* c,unsigned long l);
size_t fmt_asn1string(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,
enum asn1_tag tag,const char* c,size_t l);
/* write ASN.1 OCTET STRING */
#define fmt_asn1OCTETSTRING(dest,c,l) fmt_asn1string(dest,UNIVERSAL,PRIMITIVE,OCTET_STRING,c,l)
@@ -85,32 +92,32 @@ unsigned int fmt_asn1string(char* dest,enum asn1_tagclass tc,enum asn1_tagtype t
* the return value is the number of bytes parsed or 0 for parse error */
/* parse ASN.1 tag into a tag class, tag type and tag number */
unsigned int scan_asn1tag(const char* src,const char* max,
enum asn1_tagclass* tc,enum asn1_tagtype* tt, unsigned long* tag);
size_t scan_asn1tag(const char* src,const char* max,
enum asn1_tagclass* tc,enum asn1_tagtype* tt, unsigned long* tag);
/* parse ASN.1 length */
unsigned int scan_asn1length(const char* src,const char* max,unsigned long* length);
size_t scan_asn1length(const char* src,const char* max,size_t* length);
/* parse ASN.1 integer with tag and length */
unsigned int scan_asn1int(const char* src,const char* max,
enum asn1_tagclass* tc,enum asn1_tagtype* tt, unsigned long* tag,
long* l);
size_t scan_asn1int(const char* src,const char* max,
enum asn1_tagclass* tc,enum asn1_tagtype* tt, unsigned long* tag,
long* val);
/* parse raw integer (payload after tag and length); internal helper */
unsigned int scan_asn1rawint(const char* src,const char* max,unsigned int len,long* i);
size_t scan_asn1rawint(const char* src,const char* max,size_t len,long* val);
/* parse string with tag and length.
* Points s to the first byte in the string, and writes the length of
* the string to l. */
unsigned int scan_asn1string(const char* src,const char* max,
size_t 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);
const char** s,size_t* l);
/* the following expect a specific universal type and return a parse
* error if the tag does not match that type */
unsigned int scan_asn1BOOLEAN(const char* src,const char* max,unsigned long* l);
unsigned int scan_asn1INTEGER(const char* src,const char* max,signed long* l);
unsigned int scan_asn1ENUMERATED(const char* src,const char* max,unsigned long* l);
unsigned int scan_asn1STRING(const char* src,const char* max,const char** s,unsigned long* l);
unsigned int scan_asn1SEQUENCE(const char* src,const char* max,unsigned long* len);
unsigned int scan_asn1SET(const char* src,const char* max,unsigned long* len);
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_asn1SEQUENCE(const char* src,const char* max,size_t* len);
size_t scan_asn1SET(const char* src,const char* max,size_t* len);

7
bstr.h
View File

@@ -1,11 +1,12 @@
#include <stddef.h>
int bstr_diff(const char* a,const char* b);
#define bstr_equal(s,t) (!bstr_diff((s),(t)))
int bstr_diff2(const char* a,const char* b,unsigned int blen);
int bstr_diff2(const char* a,const char* b,size_t blen);
#define bstr_equal2(s,t,l) (!bstr_diff2((s),(t),(l)))
int bstrlen(const char* a);
int bstrstart(const char* a); /* offset of first byte of bstring */
size_t bstrlen(const char* a);
size_t bstrstart(const char* a); /* offset of first byte of bstring */
const char* bstrfirst(const char* a); /* pointer to first byte of bstring */

View File

@@ -3,7 +3,7 @@
#include "uint32.h"
#include "bstr.h"
int bstr_diff2(const char* a,const char* b,unsigned int blen) {
int bstr_diff2(const char* a,const char* b,size_t blen) {
const char* A,* B;
int j;
/* like str_diff, just for bstrs */
@@ -23,7 +23,7 @@ int bstr_diff2(const char* a,const char* b,unsigned int blen) {
} else
if (b==B)
return 1;
if ((j=(*a-*b))) break;
if ((j=((unsigned char)*a-(unsigned char)*b))) break;
++a; ++b;
}
return j;

View File

@@ -3,6 +3,6 @@
#include "uint32.h"
#include "str.h"
int bstrlen(const char* a) {
size_t bstrlen(const char* a) {
if (*a) return str_len(a); else return uint32_read(a+1);
}

View File

@@ -1,6 +1,6 @@
#include "bstr.h"
#include "uint32.h"
int bstrstart(const char* a) {
size_t bstrstart(const char* a) {
if (*a) return 0; else return 5;
}

View File

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

View File

@@ -1,16 +1,14 @@
#include <asn1.h>
unsigned int fmt_asn1intpayload(char* dest,unsigned long l) {
unsigned int needed=sizeof l;
unsigned int i;
unsigned int fixup;
size_t fmt_asn1intpayload(char* dest,unsigned long l) {
size_t needed=sizeof l,i,fixup;
for (i=1; i<needed; ++i) {
if (!(l>>(i*8)))
break;
}
fixup=(l>>((i-1)*8))&0x80 ? 1 : 0;
if (dest) {
unsigned int j=i;
size_t j=i;
if (fixup) *dest++=0;
while (j) {
--j;

View File

@@ -2,10 +2,9 @@
/* write int in least amount of bytes, return number of bytes */
/* as used in ASN.1 length */
unsigned int fmt_asn1length(char* dest,unsigned long l) {
size_t fmt_asn1length(char* dest,size_t l) {
/* encoding is either l%128 or (0x80+number of bytes,bytes) */
int needed=(sizeof l);
int i;
size_t needed=(sizeof l),i;
if (l<128) {
if (dest) *dest=l&0x7f;
return 1;

View File

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

View File

@@ -1,8 +1,7 @@
#include <asn1.h>
unsigned int fmt_asn1sintpayload(char* dest,signed long l) {
unsigned int needed=sizeof l;
unsigned int i;
size_t fmt_asn1sintpayload(char* dest,signed long l) {
size_t needed=sizeof l,i;
signed long tmp=0x7f;
if (l>=0) return fmt_asn1intpayload(dest,l);
for (i=1; i<needed; ++i) {
@@ -12,7 +11,7 @@ unsigned int fmt_asn1sintpayload(char* dest,signed long l) {
tmp=(tmp<<8)|0xff;
}
if (dest) {
int j=i;
size_t j=i;
while (j) {
--j;
*dest=(l>>(j*8))&0xff;

View File

@@ -1,8 +1,9 @@
#include "asn1.h"
#include "byte.h"
unsigned 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;
size_t fmt_asn1string(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,enum asn1_tag tag,const char* c,size_t l) {
size_t len;
if (l>(size_t)-100) return (size_t)-1;
len=fmt_asn1transparent(dest,tc,tt,tag,l);
if (dest) byte_copy(dest+len,l,c);
return len+l;

View File

@@ -2,10 +2,9 @@
/* write int in least amount of bytes, return number of bytes */
/* as used in ASN.1 tags */
unsigned int fmt_asn1tag(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,unsigned long l) {
size_t fmt_asn1tag(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,unsigned long l) {
/* encoding is either l%128 or (0x1f,...) */
int needed=(sizeof l)*7/8;
int i;
size_t needed=(sizeof l)*7/8,i;
if (l<0x1f) {
if (dest) *dest=(int)tc+(int)tt+(l&0x1f);
return 1;
@@ -14,7 +13,7 @@ unsigned int fmt_asn1tag(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,u
if (!(l>>(i*7)))
break;
if (dest) {
int j=i;
size_t j=i;
*dest=(int)tc+(int)tt+0x1f; ++dest;
while (j) {
--j;

View File

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

View File

@@ -1,10 +1,9 @@
#include "asn1.h"
#include "ldap.h"
static int doit(char* dest,struct AttributeDescriptionList* adl,int seq) {
static size_t doit(char* dest,struct AttributeDescriptionList* adl,int seq) {
struct AttributeDescriptionList* x=adl;
long sum=0;
int tmp;
size_t sum=0,tmp;
while (x) {
sum+=fmt_asn1OCTETSTRING(0,0,x->a.l);
x=x->next;
@@ -25,10 +24,10 @@ static int doit(char* dest,struct AttributeDescriptionList* adl,int seq) {
return sum;
}
unsigned int fmt_ldapadl(char* dest,struct AttributeDescriptionList* adl) {
size_t fmt_ldapadl(char* dest,struct AttributeDescriptionList* adl) {
return doit(dest,adl,1);
}
unsigned int fmt_ldapavl(char* dest,struct AttributeDescriptionList* adl) {
size_t fmt_ldapavl(char* dest,struct AttributeDescriptionList* adl) {
return doit(dest,adl,0);
}

View File

@@ -1,8 +1,8 @@
#include "asn1.h"
#include "ldap.h"
unsigned int fmt_ldapava(char* dest,struct AttributeValueAssertion* a) {
long sum,l;
size_t fmt_ldapava(char* dest,struct AttributeValueAssertion* a) {
size_t sum,l;
sum=fmt_ldapstring(dest,&a->desc);
if (dest) dest+=sum;
l=fmt_ldapstring(dest,&a->value);

View File

@@ -2,16 +2,18 @@
#include "asn1.h"
#include "ldap.h"
#include "str.h"
#include "rangecheck.h"
unsigned int fmt_ldapbindrequest(char* dest,long version,char* name,char* simple) {
unsigned int l,sum;
unsigned int nlen=str_len(name);
size_t fmt_ldapbindrequest(char* dest,long version,char* name,char* simple) {
size_t l,sum;
size_t nlen=str_len(name);
sum=l=fmt_asn1INTEGER(dest,version);
if (dest) dest+=l;
l=fmt_asn1OCTETSTRING(dest,name,nlen);
sum+=l; if (dest) dest+=l;
if (add_of(sum,sum,l)) return (size_t)-1; if (dest) dest+=l;
// sum+=l; if (dest) dest+=l;
nlen=str_len(simple);
l=fmt_asn1string(dest,PRIVATE,PRIMITIVE,0,simple,nlen);
if (dest) dest+=l;
return sum+l;
if (add_of(sum,sum,l)) return (size_t)-1; if (dest) dest+=l;
return sum;
}

View File

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

View File

@@ -1,9 +1,9 @@
#include "asn1.h"
#include "ldap.h"
unsigned int fmt_ldappal(char* dest,struct PartialAttributeList* pal) {
size_t fmt_ldappal(char* dest,struct PartialAttributeList* pal) {
// int l,l2,sum;
long sum,l,l2;
size_t sum,l,l2;
if (!pal) return 0;
sum=fmt_ldapstring(0,&pal->type);
/* look how much space the adl needs */

View File

@@ -2,9 +2,8 @@
#include "ldap.h"
#include "str.h"
unsigned int fmt_ldapresult(char* dest,long result,char* matcheddn,char* errormessage,char* referral) {
unsigned int l,sum=0;
unsigned int nlen;
size_t fmt_ldapresult(char* dest,long result,char* matcheddn,char* errormessage,char* referral) {
size_t l,sum=0,nlen;
sum=l=fmt_asn1ENUMERATED(dest,result);
if (dest) dest+=l;
nlen=str_len(matcheddn);

View File

@@ -17,8 +17,8 @@
extensibleMatch [9] MatchingRuleAssertion }
*/
int fmt_ldapsubstring(char* dest,struct Substring* s) {
long sum=0,tmp=0;
size_t fmt_ldapsubstring(char* dest,struct Substring* s) {
size_t sum=0,tmp=0;
while (s) {
tmp=fmt_asn1string(dest,PRIVATE,PRIMITIVE,s->substrtype,s->s.s,s->s.l);
if (dest) dest+=tmp; sum+=tmp;
@@ -27,9 +27,8 @@ int fmt_ldapsubstring(char* dest,struct Substring* s) {
return sum;
}
unsigned int fmt_ldapsearchfilter(char* dest,struct Filter* f) {
long sum=0,tmp;
long savesum;
size_t fmt_ldapsearchfilter(char* dest,struct Filter* f) {
size_t sum=0,tmp,savesum;
if (!f)
return 0;
switch (f->type) {
@@ -40,7 +39,7 @@ unsigned int fmt_ldapsearchfilter(char* dest,struct Filter* f) {
case SUBSTRING:
{
char* nd=dest;
long l=0,tmp=0;
size_t l,tmp;
tmp=fmt_ldapsubstring(0,f->substrings);
l=fmt_ldapstring(nd,&f->ava.desc);

View File

@@ -3,8 +3,8 @@
#include "str.h"
#include "ldap.h"
unsigned int fmt_ldapsearchfilterstring(char* dest,struct Filter* f) {
unsigned int len;
size_t fmt_ldapsearchfilterstring(char* dest,struct Filter* f) {
size_t len;
len = fmt_str(dest,"(");
switch (f->type) {
case AND: case OR: case NOT:

View File

@@ -1,8 +1,8 @@
#include "asn1.h"
#include "ldap.h"
unsigned int fmt_ldapsearchrequest(char* dest,struct SearchRequest* sr) {
int l,sum=0;
size_t fmt_ldapsearchrequest(char* dest,struct SearchRequest* sr) {
size_t l,sum=0;
sum=fmt_ldapstring(dest,&sr->baseObject);
if (dest) dest+=sum;
l=fmt_asn1ENUMERATED(dest,sr->scope);

View File

@@ -1,8 +1,8 @@
#include "asn1.h"
#include "ldap.h"
unsigned int fmt_ldapsearchresultentry(char* dest,struct SearchResultEntry* sre) {
unsigned int l,sum=0;
size_t fmt_ldapsearchresultentry(char* dest,struct SearchResultEntry* sre) {
size_t l,sum=0;
sum=fmt_ldapstring(dest,&sre->objectName);
if (dest) dest+=sum;
l=fmt_asn1SEQUENCE(dest,fmt_ldappal(0,sre->attributes));

View File

@@ -1,6 +1,6 @@
#include "asn1.h"
#include "ldap.h"
unsigned int fmt_ldapstring(char* dest,struct string* s) {
size_t fmt_ldapstring(char* dest,struct string* s) {
return fmt_asn1OCTETSTRING(dest,s->s,s->l);
}

View File

@@ -6,27 +6,32 @@
#include "uint32.h"
#include "bstr.h"
#include "textcode.h"
#include <assert.h>
static void dumpbstr(const char* c) {
int printable=1;
int i,l;
size_t i,l,up;
const char* d;
l=bstrlen(c);
d=bstrfirst(c);
for (i=0; i<l; ++i)
if (!isprint(d[i])) { printable=0; break; }
if (printable) {
up=fmt_ldapescape(0,d,l);
assert(up>=l);
if (up==l) {
buffer_puts(buffer_1," ");
if (*c)
buffer_puts(buffer_1,c);
else
buffer_put(buffer_1,bstrfirst(c),bstrlen(c));
} else {
} else if (up > (l+2)/3*4) {
char* e;
i=fmt_base64(0,d,l);
e=alloca(i+1);
buffer_puts(buffer_1,": ");
buffer_put(buffer_1,e,fmt_base64(e,d,l));
} else {
char* e;
e=alloca(up);
buffer_puts(buffer_1,": ");
buffer_put(buffer_1,e,fmt_ldapescape(e,d,l));
}
}

79
ldap.h
View File

@@ -1,10 +1,11 @@
#ifndef _LDAP_H
#define _LDAP_H
#include "uint32.h"
#include <stddef.h>
#include <inttypes.h>
struct string {
unsigned long l;
size_t l;
const char* s;
};
@@ -19,7 +20,7 @@ struct AttributeValueAssertion {
struct AttributeDescriptionList {
struct string a;
uint32 attrofs;
uint32_t attrofs;
struct AttributeDescriptionList *next;
};
@@ -42,8 +43,8 @@ enum FilterType {
struct Filter {
enum FilterType type;
struct AttributeValueAssertion ava;
uint32 attrofs; /* offset of attribute name in index */
uint32 attrflag; /* "case sensitivity" flag from index */
uint32_t attrofs; /* offset of attribute name in index */
uint32_t attrflag; /* "case sensitivity" flag from index */
struct Substring* substrings;
struct AttributeDescriptionList *a;
struct Filter* x,*next;
@@ -152,40 +153,40 @@ void freefilter(struct Filter* f);
void freeava(struct AttributeDescriptionList* a);
void freepal(struct PartialAttributeList* a);
unsigned int scan_ldapstring(const char* src,const char* max,struct string* s);
unsigned int scan_ldapmessage(const char* src,const char* max,
unsigned long* messageid,unsigned long* op,
unsigned long* len);
unsigned int scan_ldapbindrequest(const char* src,const char* max,
unsigned long* version,struct string* name,
unsigned long* method);
unsigned int scan_ldapbindresponse(const char* src,const char* max,
unsigned long* result,struct string* matcheddn,
struct string* errormessage,struct string* referral);
unsigned int scan_ldapava(const char* src,const char* max,struct AttributeValueAssertion* a);
unsigned int scan_ldapsearchfilter(const char* src,const char* max,struct Filter** f);
unsigned int scan_ldapsearchrequest(const char* src,const char* max,struct SearchRequest* s);
unsigned int scan_ldapsearchresultentry(const char* src,const char* max,struct SearchResultEntry* sre);
unsigned int scan_ldapresult(const char* src,const char* max,unsigned long* result,
struct string* matcheddn,struct string* errormessage,
struct string* referral);
unsigned int scan_ldapmodifyrequest(const char* src,const char* max,struct ModifyRequest* m);
unsigned int scan_ldapaddrequest(const char * src, const char * max, struct AddRequest * a);
unsigned int scan_ldapsearchfilterstring(const char* src,struct Filter** f);
size_t scan_ldapstring(const char* src,const char* max,struct string* s);
size_t scan_ldapmessage(const char* src,const char* max,
unsigned long* messageid,unsigned long* op,
size_t* len);
size_t scan_ldapbindrequest(const char* src,const char* max,
unsigned long* version,struct string* name,
unsigned long* method);
size_t scan_ldapbindresponse(const char* src,const char* max,
unsigned long* result,struct string* matcheddn,
struct string* errormessage,struct string* referral);
size_t scan_ldapava(const char* src,const char* max,struct AttributeValueAssertion* a);
size_t scan_ldapsearchfilter(const char* src,const char* max,struct Filter** f);
size_t scan_ldapsearchrequest(const char* src,const char* max,struct SearchRequest* s);
size_t scan_ldapsearchresultentry(const char* src,const char* max,struct SearchResultEntry* sre);
size_t scan_ldapresult(const char* src,const char* max,unsigned long* result,
struct string* matcheddn,struct string* errormessage,
struct string* referral);
size_t scan_ldapmodifyrequest(const char* src,const char* max,struct ModifyRequest* m);
size_t scan_ldapaddrequest(const char* src, const char * max, struct AddRequest * a);
size_t scan_ldapsearchfilterstring(const char* src,struct Filter** f);
unsigned int fmt_ldapstring(char* dest,struct string* s);
unsigned int fmt_ldapmessage(char* dest,long messageid,long op,long len);
unsigned int fmt_ldapbindrequest(char* dest,long version,char* name,char* simple);
unsigned int fmt_ldapsearchfilter(char* dest,struct Filter* f);
unsigned int fmt_ldapsearchrequest(char* dest,struct SearchRequest* s);
unsigned int fmt_ldapsearchresultentry(char* dest,struct SearchResultEntry* sre);
unsigned int fmt_ldapresult(char* dest,long result,char* matcheddn,char* errormessage,char* referral);
unsigned int fmt_ldappal(char* dest,struct PartialAttributeList* pal);
unsigned int fmt_ldapava(char* dest,struct AttributeValueAssertion* a);
unsigned int fmt_ldapadl(char* dest,struct AttributeDescriptionList* adl);
unsigned int fmt_ldapavl(char* dest,struct AttributeDescriptionList* adl);
unsigned int fmt_ldapmodifyrequest(char* dest,struct ModifyRequest* m);
unsigned int fmt_ldapsearchfilterstring(char* dest,struct Filter* f);
size_t fmt_ldapstring(char* dest,struct string* s);
size_t fmt_ldapmessage(char* dest,long messageid,long op,size_t len);
size_t fmt_ldapbindrequest(char* dest,long version,char* name,char* simple);
size_t fmt_ldapsearchfilter(char* dest,struct Filter* f);
size_t fmt_ldapsearchrequest(char* dest,struct SearchRequest* s);
size_t fmt_ldapsearchresultentry(char* dest,struct SearchResultEntry* sre);
size_t fmt_ldapresult(char* dest,long result,char* matcheddn,char* errormessage,char* referral);
size_t fmt_ldappal(char* dest,struct PartialAttributeList* pal);
size_t fmt_ldapava(char* dest,struct AttributeValueAssertion* a);
size_t fmt_ldapadl(char* dest,struct AttributeDescriptionList* adl);
size_t fmt_ldapavl(char* dest,struct AttributeDescriptionList* adl);
size_t fmt_ldapmodifyrequest(char* dest,struct ModifyRequest* m);
size_t fmt_ldapsearchfilterstring(char* dest,struct Filter* f);
#define fmt_ldapbindresponse(a,b,c,d,e) fmt_ldapresult(a,b,c,d,e)
#define fmt_ldapsearchresultdone(a,b,c,d,e) fmt_ldapresult(a,b,c,d,e)
@@ -204,5 +205,7 @@ void free_ldapsearchresultentry(struct SearchResultEntry* e);
int ldap_matchfilter_sre(struct SearchResultEntry* sre,struct Filter* f);
int matchint(struct Filter* f,const char* t);
int substringmatch(struct Substring* x,const char* attr,int ignorecase);
#endif

View File

@@ -14,7 +14,7 @@ extern long filelen;
extern uint32 magic,attribute_count,record_count,indices_offset,size_of_string_table;
extern uint32 dn_ofs,objectClass_ofs;
static int substringmatch(struct Substring* x,const char* attr,int ignorecase) {
int substringmatch(struct Substring* x,const char* attr,int ignorecase) {
int (*diff)(const void* a, unsigned long len, const void* b);
if (ignorecase)
diff=case_diffb;
@@ -66,7 +66,7 @@ uint32 ldap_find_attr_value(uint32 ofs,uint32 attrofs) {
return 0;
}
static inline int matchint(struct Filter* f,const char* t) {
int matchint(struct Filter* f,const char* t) {
int r;
if (f->attrflag&1)

View File

@@ -72,7 +72,7 @@ found:
return 1;
}
extern uint32 dn_ofs;
extern uint32_t dn_ofs;
int ldap_matchfilter_sre(struct SearchResultEntry* sre,struct Filter* f) {
struct PartialAttributeList* p;

View File

@@ -9,12 +9,20 @@
#include "socket.h"
#include "ip4.h"
#include "str.h"
#include "textcode.h"
#include <fcntl.h>
#include <sys/socket.h>
#define BUFSIZE 8192
static void buffer_putescaped(buffer* b,const char* x,size_t l) {
size_t needed=fmt_ldapescape(0,x,l);
char* buf=alloca(needed);
fmt_ldapescape(buf,x,l);
buffer_put(b,buf,needed);
}
static unsigned long messageid=1;
static int ldapbind(int sock) {
@@ -118,7 +126,7 @@ usage:
}
shutdown(sock,SHUT_WR);
{
char buf[8192]; /* arbitrary limit, bad! */
char buf[32*1024]; /* arbitrary limit, bad! */
int len=0,tmp,tmp2;
char* max;
struct SearchResultEntry sre;
@@ -158,16 +166,16 @@ nextmessage:
if (durchlauf==0) {
buffer_puts(buffer_1,"dn: ");
buffer_put(buffer_1,sre.objectName.s,sre.objectName.l);
buffer_putescaped(buffer_1,sre.objectName.s,sre.objectName.l);
buffer_puts(buffer_1,"\n");
while (pal) {
struct AttributeDescriptionList* adl=pal->values;
do {
buffer_puts(buffer_1," ");
buffer_put(buffer_1,pal->type.s,pal->type.l);
// buffer_puts(buffer_1," ");
buffer_putescaped(buffer_1,pal->type.s,pal->type.l);
buffer_puts(buffer_1,": ");
if (adl) {
buffer_put(buffer_1,adl->a.s,adl->a.l);
buffer_putescaped(buffer_1,adl->a.s,adl->a.l);
buffer_puts(buffer_1,"\n");
adl=adl->next;
if (!adl) break;

18
ldif.h
View File

@@ -1,21 +1,21 @@
#include "uint32.h"
#include <inttypes.h>
#include <ldap.h>
/* how many attributes do we allow per record? */
#define ATTRIBS 100
struct attribute {
uint32 name, value;
uint32_t name, value;
};
struct ldaprec {
uint32 dn;
int n; /* number of attributes */
uint32_t dn;
unsigned int n; /* number of attributes */
struct attribute a[ATTRIBS];
struct ldaprec* next;
};
extern uint32 dn, mail, sn, cn, objectClass;
extern uint32_t dn, mail, sn, cn, objectClass;
extern struct ldaprec *first;
extern unsigned long ldifrecords;
@@ -23,7 +23,7 @@ int ldif_parse(const char* filename);
/* return non-zero if the record matches the search request */
int ldap_match(struct ldaprec* r,struct SearchRequest* sr);
int ldap_match_mapped(uint32 ofs,struct SearchRequest* sr);
int ldap_match_present(uint32 ofs,uint32 attrofs);
uint32 ldap_find_attr_value(uint32 ofs,uint32 attrofs);
int ldap_matchfilter_mapped(uint32 ofs,struct Filter* f);
int ldap_match_mapped(uint32_t ofs,struct SearchRequest* sr);
int ldap_match_present(uint32_t ofs,uint32_t attrofs);
uint32_t ldap_find_attr_value(uint32_t ofs,uint32_t attrofs);
int ldap_matchfilter_mapped(uint32_t ofs,struct Filter* f);

View File

@@ -12,10 +12,11 @@
#include "byte.h"
#include "textcode.h"
#include "stralloc.h"
#include "uint32.h"
mduptab_t attributes,classes;
mstorage_t stringtable;
uint32 dn, objectClass;
uint32_t dn, objectClass;
unsigned long lines;
/* this is called after each record.
@@ -27,11 +28,11 @@ unsigned long lines;
* If the callback is NULL, a callback that always returns 1 is assumed.
* */
int (*ldif_parse_callback)(struct ldaprec* l);
uint32 (*ldif_addstring_callback)(const char* s,unsigned long len);
uint32_t (*ldif_addstring_callback)(const char* s,unsigned long len);
unsigned long ldifrecords;
static void addattribute(struct ldaprec** l,uint32 name,uint32 val) {
static void addattribute(struct ldaprec** l,uint32_t name,uint32_t val) {
if (name==dn) (*l)->dn=val; else
if ((*l)->n<ATTRIBS) {
(*l)->a[(*l)->n].name=name;
@@ -80,28 +81,28 @@ static int unbase64(char* buf) {
return destlen;
}
uint32 (*ldif_addstring_callback)(const char* s,unsigned long len);
uint32_t (*ldif_addstring_callback)(const char* s,unsigned long len);
static uint32 addstring(const char* s,unsigned long len) {
static uint32_t addstring(const char* s,unsigned long len) {
return mstorage_add(&stringtable,s,len);
}
static long commit_string_bin(const char* s,unsigned long n) {
unsigned int i;
static char zero;
uint32 x;
uint32_t x;
char intbuf[4];
if (n==0 || (n==1 && s[0]==0)) goto encodebinary;
for (i=0; i<n-1; ++i)
if (!s[i]) {
encodebinary:
uint32_pack(intbuf,n);
if ((x=ldif_addstring_callback(&zero,1))==(uint32)-1 || ldif_addstring_callback(intbuf,4)==(uint32)-1 || ldif_addstring_callback(s,n)==(uint32)-1) return -1;
if ((x=ldif_addstring_callback(&zero,1))==(uint32_t)-1 || ldif_addstring_callback(intbuf,4)==(uint32_t)-1 || ldif_addstring_callback(s,n)==(uint32_t)-1) return -1;
return x;
}
x=ldif_addstring_callback(s,n);
if (s[n-1])
if (ldif_addstring_callback(&zero,1)==(uint32)-1) return -1;
if (ldif_addstring_callback(&zero,1)==(uint32_t)-1) return -1;
return x;
}
@@ -117,7 +118,7 @@ static int parserec(buffer* b, struct ldaprec** l) {
char buf[8192];
int n,i,eof=0,ofs=0;
unsigned int i2;
int len,base64,binary;
size_t len,base64,binary;
stralloc payload={0,0,0};
if (!(*l=malloc(sizeof(struct ldaprec)))) {
@@ -129,7 +130,7 @@ nomem:
(*l)->next=0; (*l)->n=0;
ldifrecords=0;
do {
uint32 tmp, val;
uint32_t tmp, val;
base64=binary=0;
n=ofs+buffer_get_token(b,buf+ofs,8192-ofs,":",1);
if (n==0) break;
@@ -139,7 +140,7 @@ nomem:
buf[i2]=0;
if (str_equal("binary",buf+i2+1)) binary=1;
}
if ((tmp=mduptab_adds(&attributes,buf+i))==(uint32)-1) goto nomem;
if ((tmp=mduptab_adds(&attributes,buf+i))==(uint32_t)-1) goto nomem;
if (!stralloc_copys(&payload,"")) goto nomem;
{
char dummy;
@@ -178,8 +179,12 @@ lookagain:
if (base64) {
len=unbase64(payload.s);
if (!binary) { payload.s[len]=0; ++len; }
} else
len=n+1;
} else {
len=n;
scan_ldapescape(payload.s,payload.s,&len);
payload.s[len]=0;
++len;
}
} else
len=0;
@@ -192,11 +197,11 @@ lookagain:
#endif
if (tmp==objectClass) {
if ((val=mduptab_add(&classes,payload.s,len-1))==(uint32)-1) goto nomem;
if ((val=mduptab_add(&classes,payload.s,len-1))==(uint32_t)-1) goto nomem;
} else if (tmp==dn) {
if ((val=add_normalized(payload.s,len))==(uint32)-1) goto nomem;
if ((val=add_normalized(payload.s,len))==(uint32_t)-1) goto nomem;
} else
if ((val=commit_string_bin(payload.s,len))==(uint32)-1) goto nomem;
if ((val=commit_string_bin(payload.s,len))==(uint32_t)-1) goto nomem;
addattribute(l,tmp,val);
m=0;
@@ -236,8 +241,12 @@ lookagain:
if (base64) {
len=unbase64(payload.s);
if (!binary) { payload.s[len]=0; ++len; }
} else
len=n+1;
} else {
len=n;
scan_ldapescape(payload.s,payload.s,&len);
payload.s[len]=0;
++len;
}
} else
len=0;
@@ -250,16 +259,16 @@ lookagain:
#endif
if (tmp==objectClass) {
if ((val=mduptab_add(&classes,payload.s,len-1))==(uint32)-1) goto nomem;
if ((val=mduptab_add(&classes,payload.s,len-1))==(uint32_t)-1) goto nomem;
} else if (tmp==dn) {
if ((val=add_normalized(payload.s,payload.len))==(uint32)-1) goto nomem;
if ((val=add_normalized(payload.s,payload.len))==(uint32_t)-1) goto nomem;
} else
if ((val=commit_string_bin(payload.s,len))==(uint32)-1) goto nomem;
if ((val=commit_string_bin(payload.s,len))==(uint32_t)-1) goto nomem;
addattribute(l,tmp,val);
#endif
} while (!eof);
if (ldif_parse_callback && ldif_parse_callback(*l)==-1) return -1;
if ((*l)->dn==(uint32)-1 && ((*l)->next)) {
if ((*l)->dn==(uint32_t)-1 && ((*l)->next)) {
struct ldaprec* m=(*l)->next;
free((*l));
(*l)=m;

View File

@@ -14,5 +14,5 @@ typedef struct mduptable {
void mduptab_init(mduptab_t* t);
void mduptab_init_reuse(mduptab_t* t,mstorage_t* s);
long mduptab_add(mduptab_t* t,const char* s,unsigned int len);
long mduptab_add(mduptab_t* t,const char* s,size_t len);
long mduptab_adds(mduptab_t* t,const char* s);

View File

@@ -6,7 +6,7 @@
#include "mduptab.h"
#include "uint32.h"
long mduptab_add(mduptab_t* t,const char* s,unsigned int len) {
long mduptab_add(mduptab_t* t,const char* s,size_t len) {
unsigned int i;
unsigned long* l=(unsigned long*)t->table.root;
long x,bak;

View File

@@ -1,11 +1,13 @@
#ifndef _MSTORAGE_H
#define _MSTORAGE_H
#include <stddef.h>
/* (optionally persistent) mmapped storage. */
typedef struct mstorage {
char* root;
unsigned long mapped,used;
size_t mapped,used;
int fd;
} mstorage_t;
@@ -16,7 +18,7 @@ int mstorage_init_persistent(mstorage_t* p,int fd);
/* Works like strstorage_add, but will return an
* offset to mstorage_root, which is mmapped and may thus change. */
/* offset -1 ==> error */
long mstorage_add(mstorage_t* p,const char* s,unsigned long n);
long mstorage_add(mstorage_t* p,const char* s,size_t n);
/* undo mapping */
void mstorage_unmap(mstorage_t* p);
@@ -26,6 +28,6 @@ void mstorage_unmap(mstorage_t* p);
* char 0;
* uint32 len;
* char data[len] */
long mstorage_add_bin(mstorage_t* p,const char* s,unsigned long n);
long mstorage_add_bin(mstorage_t* p,const char* s,size_t n);
#endif

View File

@@ -85,7 +85,7 @@ uint32 my_addstring(const char* s,unsigned long len) {
int ldif_callback(struct ldaprec* l) {
char x[8]; /* temp buf for endianness conversion */
int i;
unsigned int i;
// uint32 ofs;
uint32 oc=(uint32)-1; /* value of the first objectClass */
@@ -99,7 +99,7 @@ int ldif_callback(struct ldaprec* l) {
}
if (oc==(uint32)-1) {
extern long lines;
buffer_puts(buffer_1,"ignoring record without objectClass... (line");
buffer_puts(buffer_1,"ignoring record without objectClass... (line ");
buffer_putulong(buffer_1,lines);
buffer_putsflush(buffer_1,")\n");
return 0;

View File

@@ -1,15 +1,15 @@
#include "asn1.h"
unsigned int scan_asn1BOOLEAN(const char* src,const char* max,unsigned long* l) {
unsigned int tmp;
size_t scan_asn1BOOLEAN(const char* src,const char* max,unsigned long* val) {
size_t tmp;
unsigned long tag;
enum asn1_tagclass tc;
enum asn1_tagtype tt;
long ltmp;
if ((tmp=scan_asn1int(src,max,&tc,&tt,&tag,&ltmp)))
if (tc==UNIVERSAL && tt==PRIMITIVE && tag==BOOLEAN) {
if (ltmp<0 || src+tmp+ltmp>max) return 0;
*l=(unsigned long)ltmp;
if (ltmp!=0 && ltmp!=1) return 0;
*val=(unsigned long)ltmp;
return tmp;
}
return 0;

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
#include "asn1.h"
unsigned int scan_asn1SEQUENCE(const char* src,const char* max,unsigned long* len) {
unsigned int res,tmp;
size_t scan_asn1SEQUENCE(const char* src,const char* max,size_t* len) {
size_t res,tmp;
unsigned long tag;
enum asn1_tagclass tc;
enum asn1_tagtype tt;

View File

@@ -1,7 +1,7 @@
#include "asn1.h"
unsigned int scan_asn1SET(const char* src,const char* max,unsigned long* len) {
unsigned int res,tmp;
size_t scan_asn1SET(const char* src,const char* max,size_t* len) {
size_t res,tmp;
unsigned long tag;
enum asn1_tagclass tc;
enum asn1_tagtype tt;

View File

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

View File

@@ -1,8 +1,7 @@
#include "asn1.h"
unsigned int scan_asn1int(const char* src,const char* max,enum asn1_tagclass* tc,enum asn1_tagtype* tt,unsigned long* tag,signed long* l) {
unsigned int len,tmp;
unsigned long tlen;
size_t scan_asn1int(const char* src,const char* max,enum asn1_tagclass* tc,enum asn1_tagtype* tt,unsigned long* tag,signed long* l) {
size_t len,tmp,tlen;
if (!(len=scan_asn1tag(src,max,tc,tt,tag))) return 0;
if (!(tmp=scan_asn1length(src+len,max,&tlen))) return 0;
len+=tmp;

View File

@@ -1,14 +1,14 @@
#include <inttypes.h>
#include "asn1.h"
unsigned int scan_asn1length(const char* src,const char* max,unsigned long* length) {
size_t scan_asn1length(const char* src,const char* max,size_t* length) {
const char* orig=src;
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) {
int chars=*src&0x7f;
unsigned long l=0;
size_t l=0;
while (chars>0) {
if (++src>=max) return 0;
if (l>(((unsigned long)-1)>>8)) return 0; /* catch integer overflow */
@@ -20,6 +20,6 @@ unsigned int scan_asn1length(const char* src,const char* max,unsigned long* leng
*length=*src&0x7f;
src++;
if (src+*length>max) return 0; /* catch integer overflow */
if ((uintptr_t)src+*length<(uintptr_t)src) return 0; /* gcc 4 removes this check without the cast to uintptr_t */
if ((uintptr_t)src+*length<(uintptr_t)src) return 0; /* gcc 4.1 removes this check without the cast to uintptr_t */
return src-orig;
}

View File

@@ -1,15 +1,15 @@
#include "asn1.h"
unsigned int scan_asn1oid(const char* src,const char* max) {
unsigned int res,tmp;
unsigned long tag,tlen;
size_t scan_asn1oid(const char* src,const char* max) {
size_t res,tmp,tlen;
unsigned long tag;
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;
res+=tmp;
{
unsigned int i,x,y;
size_t i,x,y;
tmp=0;
for(i=0;src[res+i]&128;++i)
tmp=(tmp<<7)+((unsigned char)src[res+i]&(~128));

View File

@@ -1,7 +1,7 @@
#include "asn1.h"
unsigned int scan_asn1rawint(const char* src,const char* max,unsigned int len,long* l) {
unsigned int i,j;
size_t scan_asn1rawint(const char* src,const char* max,size_t len,long* l) {
size_t i,j;
long m;
if (*src<0) m=-1; else m=0;
for (i=j=0; i<len; ++i,++j) {

View File

@@ -1,9 +1,9 @@
#include "asn1.h"
unsigned 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) {
unsigned int len,tmp;
size_t scan_asn1string(const char* src,const char* max,
enum asn1_tagclass* tc,enum asn1_tagtype* tt,unsigned long* tag,
const char** s,size_t* l) {
size_t 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;

View File

@@ -1,6 +1,6 @@
#include "asn1.h"
unsigned int scan_asn1tag(const char* src,const char* max,enum asn1_tagclass* tc,enum asn1_tagtype* tt,unsigned long* tag) {
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;
*tc=(*src&0xC0);
*tt=(*src&0x20);

View File

@@ -16,9 +16,8 @@
vals SET OF AttributeValue }
#endif
unsigned int scan_ldapaddrequest(const char* src,const char* max,struct AddRequest* a) {
unsigned int res,tmp;
unsigned long oslen; /* outer sequence length */
size_t scan_ldapaddrequest(const char* src,const char* max,struct AddRequest* a) {
size_t res,tmp,oslen;
struct Addition* last=0;
byte_zero(a,sizeof(*a));
if (!(res=scan_ldapstring(src,max,&a->entry))) goto error;
@@ -28,7 +27,7 @@ unsigned int scan_ldapaddrequest(const char* src,const char* max,struct AddReque
max=src+res+oslen;
if (src+res>=max) goto error; /* need at least one record */
do {
unsigned long islen;
size_t islen;
if (last) {
struct Addition* cur;
if (!(cur=malloc(sizeof(struct Addition))))
@@ -49,7 +48,7 @@ unsigned int scan_ldapaddrequest(const char* src,const char* max,struct AddReque
/* scan set of AttributeValue: */
{
unsigned long set_len;
size_t set_len;
const char* set_max;
struct AttributeDescriptionList* ilast=0;
if (!(tmp=scan_asn1SET(src+res,max,&set_len))) {

View File

@@ -1,8 +1,8 @@
#include "asn1.h"
#include "ldap.h"
unsigned int scan_ldapava(const char* src,const char* max,struct AttributeValueAssertion* ava) {
unsigned int res,tmp;
size_t scan_ldapava(const char* src,const char* max,struct AttributeValueAssertion* ava) {
size_t res,tmp;
if (!(res=scan_ldapstring(src,max,&ava->desc))) goto error;
if (!(tmp=scan_ldapstring(src+res,max,&ava->value))) goto error;
return res+tmp;

View File

@@ -1,10 +1,10 @@
#include "asn1.h"
#include "ldap.h"
unsigned int scan_ldapbindrequest(const char* src,const char* max,
unsigned long* version,struct string* name,
unsigned long* method) {
unsigned int res,tmp;
size_t scan_ldapbindrequest(const char* src,const char* max,
unsigned long* version,struct string* name,
unsigned long* method) {
size_t res,tmp;
if (!(res=scan_asn1INTEGER(src,max,(signed long*)version))) return 0;
if (!(tmp=scan_ldapstring(src+res,max,name))) return 0;
res+=tmp;

View File

@@ -1,10 +1,10 @@
#include "asn1.h"
#include "ldap.h"
unsigned int scan_ldapbindresponse(const char* src,const char* max,
unsigned long* result,struct string* matcheddn,
struct string* errormessage,struct string* referral) {
unsigned int res,tmp;
size_t scan_ldapbindresponse(const char* src,const char* max,
unsigned long* result,struct string* matcheddn,
struct string* errormessage,struct string* referral) {
size_t res,tmp;
if (!(res=scan_asn1ENUMERATED(src,max,result))) return 0;
if (!(tmp=scan_ldapstring(src+res,max,matcheddn))) return 0;
res+=tmp;

View File

@@ -1,9 +1,9 @@
#include "asn1.h"
#include "ldap.h"
unsigned int scan_ldapmessage(const char* src,const char* max,
unsigned long* messageid,unsigned long* op,unsigned long* len) {
unsigned int res,tmp;
size_t scan_ldapmessage(const char* src,const char* max,
unsigned long* messageid,unsigned long* op,size_t* len) {
size_t res,tmp;
if (!(res=scan_asn1SEQUENCE(src,max,len))) goto error;
if (!(tmp=scan_asn1INTEGER(src+res,max,(long*)messageid))) goto error;
res+=tmp;

View File

@@ -17,9 +17,8 @@
vals SET OF AttributeValue }
#endif
unsigned int scan_ldapmodifyrequest(const char* src,const char* max,struct ModifyRequest* m) {
unsigned int res,tmp;
unsigned long oslen; /* outer sequence length */
size_t scan_ldapmodifyrequest(const char* src,const char* max,struct ModifyRequest* m) {
size_t res,tmp,oslen; /* outer sequence length */
struct Modification* last=0;
m->m.next=0;
if (!(res=scan_ldapstring(src,max,&m->object))) goto error;
@@ -29,7 +28,7 @@ unsigned int scan_ldapmodifyrequest(const char* src,const char* max,struct Modif
max=src+res+oslen;
if (src+res>=max) goto error; /* need at least one record */
do {
unsigned long islen, etmp;
size_t islen, etmp;
if (last) {
struct Modification* cur;
if (!(cur=malloc(sizeof(struct Modification)))) goto error;
@@ -42,7 +41,7 @@ unsigned int scan_ldapmodifyrequest(const char* src,const char* max,struct Modif
if (!(tmp=scan_asn1ENUMERATED(src+res,max,&etmp))) goto error;
if (etmp>2) goto error; last->operation=etmp; res+=tmp;
{
unsigned long iislen; /* urgh, _three_ levels of indirection */
size_t iislen; /* urgh, _three_ levels of indirection */
const char* imax;
if (!(tmp=scan_asn1SEQUENCE(src+res,max,&iislen))) goto error;
res+=tmp;
@@ -51,7 +50,7 @@ unsigned int scan_ldapmodifyrequest(const char* src,const char* max,struct Modif
if (!(tmp=scan_ldapstring(src+res,imax,&last->AttributeDescription))) goto error;
res+=tmp;
{
unsigned long iiislen; /* waah, _four_ levels of indirection! It doesn't get more inefficient than this */
size_t iiislen; /* waah, _four_ levels of indirection! It doesn't get more inefficient than this */
const char* iimax;
struct AttributeDescriptionList* ilast=0;
if (!(tmp=scan_asn1SET(src+res,max,&iiislen))) goto error;

View File

@@ -1,10 +1,10 @@
#include "asn1.h"
#include "ldap.h"
unsigned int scan_ldapresult(const char* src,const char* max,unsigned long* result,
struct string* matcheddn,struct string* errormessage,
struct string* referral) {
unsigned int res,tmp;
size_t scan_ldapresult(const char* src,const char* max,unsigned long* result,
struct string* matcheddn,struct string* errormessage,
struct string* referral) {
size_t res,tmp;
if (!(res=scan_asn1ENUMERATED(src,max,result))) return 0;
if (!(tmp=scan_ldapstring(src+res,max,matcheddn))) return 0;
res+=tmp;

View File

@@ -30,12 +30,10 @@
dnAttributes [4] BOOLEAN DEFAULT FALSE }
*/
unsigned int scan_ldapsearchfilter(const char* src,const char* max,struct Filter** f) {
size_t scan_ldapsearchfilter(const char* src,const char* max,struct Filter** f) {
enum asn1_tagclass tc;
enum asn1_tagtype tt;
unsigned long tag,len;
unsigned int res;
unsigned int tmp;
size_t tag,len,res,tmp;
const char* nmax;
*f=0;
if (!(res=scan_asn1tag(src,max,&tc,&tt,&tag))) goto error;
@@ -80,7 +78,7 @@ unsigned int scan_ldapsearchfilter(const char* src,const char* max,struct Filter
break;
case 4: /* substrings [4] SubstringFilter, */
{
unsigned long len2;
size_t len2;
if (!(tmp=scan_ldapstring(src+res,nmax,&(*f)->ava.desc))) goto error;
res+=tmp;
if (!(tmp=scan_asn1SEQUENCE(src+res,nmax,&len2))) goto error;

View File

@@ -2,11 +2,11 @@
#include "ldap.h"
#include "str.h"
unsigned int scan_ldapsearchfilterstring(const char* src,struct Filter** f) {
size_t scan_ldapsearchfilterstring(const char* src,struct Filter** f) {
char* s=(char*)src;
if (!(*f=calloc(sizeof(struct Filter),1))) goto error;
if (s[0]=='*' && (s[1]==0 || s[1]=='(')) {
int i=scan_ldapsearchfilterstring("(objectClass=*)",f);
size_t i=scan_ldapsearchfilterstring("(objectClass=*)",f);
if (i) return 1;
}
if (*s!='(') goto error;
@@ -18,7 +18,7 @@ scan_filterlist:
s+=scan_ldapsearchfilterstring(s,&(*f)->x);
n=&(*f)->x->next;
while (*s!=')') {
unsigned long l=scan_ldapsearchfilterstring(s,n);
size_t l=scan_ldapsearchfilterstring(s,n);
if (!l) return 0;
s+=l;
n=&(*n)->next;
@@ -51,7 +51,7 @@ scan_filterlist:
(*f)->type=SUBSTRING;
substring:
while (*s!=')') {
int i,j;
size_t i,j;
struct Substring* substring=malloc(sizeof(struct Substring));
if (!substring) goto error;
substring->s.s=s;
@@ -70,7 +70,7 @@ substring:
if (*s==0) goto error;
}
} else {
int i,j;
size_t i,j;
i=str_chr(s,')');
j=str_chr(s,'*');
if (i>j) {

View File

@@ -2,9 +2,9 @@
#include "asn1.h"
#include "ldap.h"
unsigned int scan_ldapsearchrequest(const char* src,const char* max,
struct SearchRequest* s) {
unsigned int res,tmp;
size_t scan_ldapsearchrequest(const char* src,const char* max,
struct SearchRequest* s) {
size_t res,tmp;
unsigned long etmp;
signed long ltmp;
s->attributes=0;

View File

@@ -2,9 +2,8 @@
#include "asn1.h"
#include "ldap.h"
unsigned int scan_ldapsearchresultentry(const char* src,const char* max,struct SearchResultEntry* sre) {
unsigned int res,tmp;
unsigned long oslen; /* outer sequence length */
size_t scan_ldapsearchresultentry(const char* src,const char* max,struct SearchResultEntry* sre) {
size_t res,tmp,oslen; /* outer sequence length */
struct PartialAttributeList** a=&sre->attributes;
*a=0;
if (!(res=scan_ldapstring(src,max,&sre->objectName))) goto error;
@@ -15,7 +14,7 @@ unsigned int scan_ldapsearchresultentry(const char* src,const char* max,struct S
while (src+res<max) {
struct string s;
struct AttributeDescriptionList* x;
unsigned long islen;
size_t islen;
const char* nmax;
if (!(tmp=scan_asn1SEQUENCE(src+res,max,&islen))) goto error;
res+=tmp; nmax=src+res+islen; if (nmax>max) goto error;

View File

@@ -1,6 +1,6 @@
#include <asn1.h>
#include <ldap.h>
unsigned int scan_ldapstring(const char* src,const char* max,struct string* s) {
size_t scan_ldapstring(const char* src,const char* max,struct string* s) {
return scan_asn1STRING(src,max,&s->s,&s->l);
}

View File

@@ -7,7 +7,7 @@
#define PAGESIZE 4096
const char* strduptab_add(struct stringduptable* t,const char* s) {
int i;
size_t i;
for (i=0; i<t->n; ++i)
if (str_equal(t->s[i],s))
return t->s[i];

View File

@@ -6,7 +6,7 @@
* the new string. */
struct stringduptable {
int n,a;
size_t n,a;
const char** s;
};

View File

@@ -4,9 +4,9 @@
#define PAGESIZE 4096
const char* strstorage_add(const char* s,int n) {
const char* strstorage_add(const char* s,size_t n) {
static char* page=0;
static int leftonpage=0;
static size_t leftonpage=0;
if (leftonpage>=n) {
copyit:
byte_copy(page,n,s);

View File

@@ -2,5 +2,5 @@
* later. On the plus side, the allocation overhead is close to zero.
* Will return a pointer to the stored copy of the string. */
const char* strstorage_add(const char* s,int n);
const char* strstorage_add(const char* s,size_t n);

4
t2.c
View File

@@ -120,7 +120,7 @@ int main(int argc,char* argv[]) {
{
unsigned long result;
struct string matcheddn,errormessage,referral;
printf("scan_ldapbindresponse: %d\n",
printf("scan_ldapbindresponse: %zd\n",
scan_ldapbindresponse(ldapsequence+done+res,ldapsequence+done+res+len,
&result,&matcheddn,&errormessage,&referral));
printf("result %lu, matcheddn \"%.*s\", errormessage \"%.*s\", referral \"%.*s\"\n",
@@ -184,7 +184,7 @@ int main(int argc,char* argv[]) {
{
unsigned long result;
struct string matcheddn,errormessage,referral;
printf("scan_ldapresult: %d\n",
printf("scan_ldapresult: %zd\n",
scan_ldapresult(ldapsequence+done+res,ldapsequence+done+res+len,
&result,&matcheddn,&errormessage,&referral));
printf("result %lu, matcheddn \"%.*s\", errormessage \"%.*s\", referral \"%.*s\"\n",

View File

@@ -1,10 +1,12 @@
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "str.h"
#include "case.h"
#include "byte.h"
#include "buffer.h"
#include "ldap.h"
#include "mduptab.h"
#include "ldif.h"
#include "open.h"
#include "mmap.h"
@@ -28,6 +30,9 @@
#include <ctype.h>
#include <assert.h>
#include <fcntl.h>
#include "errmsg.h"
#include "textcode.h"
#include "fmt.h"
#ifdef DEBUG
#include <sys/poll.h>
@@ -38,9 +43,11 @@
#define debug 0
#endif
#define HUGE_SIZE_FOR_SANITY_CHECKS 1024*1024
/* basic operation: the whole data file is mmapped read-only at the beginning and stays there. */
char* map; /* where the file is mapped */
unsigned long filelen; /* how many bytes are mapped (the whole file) */
size_t filelen; /* how many bytes are mapped (the whole file) */
uint32 magic,attribute_count,record_count,indices_offset,size_of_string_table;
/* these are the first values from the file, see the file "FORMAT"
* basic counts and offsets needed to calculate the positions of
@@ -58,6 +65,23 @@ uint32 dn_ofs,objectClass_ofs,userPassword_ofs,any_ofs;
/* journal hash structures */
struct attribute2 {
unsigned char* a,* v;
};
struct hashnode {
struct hashnode* next;
unsigned long hashval;
unsigned char* dn;
size_t n;
struct attribute2 a[1];
};
/* to avoid string compares, we don't work with char* but with uint32 (offsets within
* the mmapped file) whenever it's about values that will be mentioned in the file, such
* as attribute names. So, for each filter we get sent, we look up the attributes in the
@@ -82,7 +106,7 @@ static void fixup(struct Filter* f) {
case APPROX:
{
char* x=map+5*4+size_of_string_table;
unsigned int i;
size_t i;
f->attrofs=f->attrflag=0;
for (i=0; i<attribute_count; ++i) {
uint32 j=uint32_read(x);
@@ -112,7 +136,7 @@ static void fixup(struct Filter* f) {
static void fixupadl(struct AttributeDescriptionList* a) {
while (a) {
char* x=map+5*4+size_of_string_table;
unsigned int i;
size_t i;
a->attrofs=0;
for (i=0; i<attribute_count; ++i) {
uint32 j=uint32_read(x);
@@ -138,14 +162,14 @@ static void fixupadl(struct AttributeDescriptionList* a) {
#if 0
/*
_ _
__ _ ___| | ___ _ _ _ __ _ __ ___ _ __| |_
/ _` |/ __| | / __| | | | '_ \| '_ \ / _ \| '__| __|
| (_| | (__| | \__ \ |_| | |_) | |_) | (_) | | | |_
\__,_|\___|_| |___/\__,_| .__/| .__/ \___/|_| \__|
|_| |_|
#endif
*/
uint32 filters,acls; /* number of filters and acls in the ACL section of the data file */
uint32 filtertab,acltab; /* offsets of the filter and acl table in the data file */
@@ -204,7 +228,7 @@ kaputt:
else if (scan_ldapsearchfilter(map+ofs,map+filelen,&f)!=0) {
fixup(f);
if (debug) {
unsigned long l=fmt_ldapsearchfilterstring(0,f);
size_t l=fmt_ldapsearchfilterstring(0,f);
char* buf=malloc(l+23);
if (!buf) goto kaputt;
buf[fmt_ldapsearchfilterstring(buf,f)]=0;
@@ -258,14 +282,14 @@ kaputt:
#if 0
/*
_ _ _
__| | ___| |__ _ _ __ _ ___ ___ __| | ___
/ _` |/ _ \ '_ \| | | |/ _` | / __/ _ \ / _` |/ _ \
| (_| | __/ |_) | |_| | (_| | | (_| (_) | (_| | __/
\__,_|\___|_.__/ \__,_|\__, | \___\___/ \__,_|\___|
|___/
#endif
*/
#define BUFSIZE 8192
@@ -354,13 +378,13 @@ mergesub:
#if 0
/*
_ _ _
(_)_ __ __| | _____ __ ___ ___ __| | ___
| | '_ \ / _` |/ _ \ \/ / / __/ _ \ / _` |/ _ \
| | | | | (_| | __/> < | (_| (_) | (_| | __/
|_|_| |_|\__,_|\___/_/\_\ \___\___/ \__,_|\___|
#endif
*/
/* find out whether this filter can be accelerated with the indices */
static int indexable(struct Filter* f) {
@@ -463,14 +487,14 @@ static long findrec(uint32 dat) {
struct bitfield {
unsigned long* bits;
#ifdef RANGECHECK
unsigned long n;
size_t n;
#endif
unsigned long first,last;
size_t first,last;
};
/* basic bit-set support: set all bits to 0 */
static inline void emptyset(struct bitfield* b) {
unsigned long i;
size_t i;
#ifdef RANGECHECK
b->n=
#endif
@@ -481,7 +505,7 @@ static inline void emptyset(struct bitfield* b) {
/* basic bit-set support: set all bits to 1 */
static inline void fillset(struct bitfield* b) {
unsigned long i;
size_t i;
b->first=0;
#ifdef RANGECHECK
b->n=
@@ -491,7 +515,7 @@ static inline void fillset(struct bitfield* b) {
}
/* basic bit-set support: set one bit to 1 */
static inline void setbit(struct bitfield* b,unsigned long bit) {
static inline void setbit(struct bitfield* b,size_t bit) {
#ifdef RANGECHECK
if (bit<=b->n) {
#endif
@@ -504,7 +528,7 @@ static inline void setbit(struct bitfield* b,unsigned long bit) {
}
/* basic bit-set support: see if given bit is set */
static inline int isset(struct bitfield* b,unsigned long bit) {
static inline int isset(struct bitfield* b,size_t bit) {
#ifdef RANGECHECK
if (bit>b->n) return 0;
#endif
@@ -514,7 +538,7 @@ static inline int isset(struct bitfield* b,unsigned long bit) {
/* use index (sorted table of offsets to records) to do a binary search
* for all records that match the value in s. Set the corresponding
* bits to 1 in bitfield. */
static void tagmatches(uint32* index,unsigned int elements,struct string* s,
static void tagmatches(uint32* index,size_t elements,struct string* s,
struct bitfield* b,int (*match)(struct string* s,const char* c),
uint32 index_type,enum FilterType ft) {
uint32 bottom=0;
@@ -623,9 +647,8 @@ static void tagmatches(uint32* index,unsigned int elements,struct string* s,
}
}
uint32 hash(const unsigned char* c,unsigned long keylen) {
unsigned long h=0;
unsigned long i;
uint32 hash(const unsigned char* c,size_t keylen) {
size_t h=0,i;
for (i=0; i<keylen; ++i) {
/* from djb's cdb */
h += (h<<5);
@@ -634,9 +657,8 @@ uint32 hash(const unsigned char* c,unsigned long keylen) {
return (uint32)h;
}
uint32 hash_tolower(const unsigned char* c,unsigned long keylen) {
unsigned long h=0;
unsigned long i;
uint32 hash_tolower(const unsigned char* c,size_t keylen) {
size_t h=0,i;
for (i=0; i<keylen; ++i) {
/* from djb's cdb */
h += (h<<5);
@@ -701,7 +723,7 @@ static int useindex(struct Filter* f,struct bitfield* b) {
fillset(b);
while (y) {
if (useindex(y,&tmp)) {
unsigned int i;
size_t i;
for (i=0; i<record_set_length; ++i)
b->bits[i] &= tmp.bits[i];
if (tmp.first>b->first) b->first=tmp.first;
@@ -724,7 +746,7 @@ static int useindex(struct Filter* f,struct bitfield* b) {
emptyset(b);
while (y) {
if (useindex(y,&tmp)) {
unsigned int i;
size_t i;
for (i=0; i<record_set_length; ++i)
b->bits[i] |= tmp.bits[i];
if (tmp.first<b->first) b->first=tmp.first;
@@ -765,7 +787,7 @@ static int useindex(struct Filter* f,struct bitfield* b) {
* through the record table, but since each check is very cheap,
* we pretend it's indexed */
char* x=map+5*4+size_of_string_table+attribute_count*8;
unsigned long i;
size_t i;
emptyset(b);
for (i=0; i<record_count; ++i) {
if (ldap_match_present(x-map,f->attrofs))
@@ -801,17 +823,17 @@ static int useindex(struct Filter* f,struct bitfield* b) {
#if 0
/*
_
__ _ _ _ ___ _ __ _ _ __ _ _ __ _____ _____ _ __(_)_ __ __ _
/ _` | | | |/ _ \ '__| | | | / _` | '_ \/ __\ \ /\ / / _ \ '__| | '_ \ / _` |
| (_| | |_| | __/ | | |_| | | (_| | | | \__ \\ V V / __/ | | | | | | (_| |
\__, |\__,_|\___|_| \__, | \__,_|_| |_|___/ \_/\_/ \___|_| |_|_| |_|\__, |
|_| |___/ |___/
#endif
*/
static int checkacl(uint32 ofs,uint32 attrofs,unsigned long operation,struct SearchResultEntry* sre) {
uint32_t j;
static int checkacl(uint32 recofs,uint32 attrofs,unsigned long operation,struct SearchResultEntry* sre) {
uint32 j;
for (j=0; j<acls; ++j) {
/* does the ACL subject apply? */
if (!acl_ec_subjects[Acls[j]->subject]) continue;
@@ -824,9 +846,9 @@ static int checkacl(uint32 ofs,uint32 attrofs,unsigned long operation,struct Sea
if (Filters[Acls[j]->object]==(struct Filter*)Any)
match=1;
else if (Filters[Acls[j]->object]==(struct Filter*)Self)
match=(ofs==authenticated_as);
else if (ofs)
match=ldap_matchfilter_mapped(ofs,Filters[Acls[j]->object]);
match=(recofs==authenticated_as);
else if (recofs)
match=ldap_matchfilter_mapped(recofs,Filters[Acls[j]->object]);
else if (sre)
match=ldap_matchfilter_sre(sre,Filters[Acls[j]->object]);
else
@@ -853,12 +875,62 @@ static int checkacl(uint32 ofs,uint32 attrofs,unsigned long operation,struct Sea
return 0;
}
static int ldap_matchfilter_hn(struct hashnode* hn,struct Filter* f);
static int checkacl_hn(struct hashnode* hn,const unsigned char* attr,unsigned long operation) {
uint32 j;
for (j=0; j<acls; ++j) {
/* does the ACL subject apply? */
if (!acl_ec_subjects[Acls[j]->subject]) continue;
/* does the ACL even apply to the wanted operation? */
if ((Acls[j]->may | Acls[j]->maynot) & operation) {
uint32 k;
if (acl_ec_subjects[filters+Acls[j]->object]==-1) continue;
if (acl_ec_subjects[filters+Acls[j]->object]==0) {
int match=0;
if (Filters[Acls[j]->object]==(struct Filter*)Any)
match=1;
else if (Filters[Acls[j]->object]==(struct Filter*)Self)
match=dn && !strcmp((char*)hn->dn,map+authenticated_as);
else if (dn)
match=ldap_matchfilter_hn(hn,Filters[Acls[j]->object]);
else
match=-1;
if (match)
acl_ec_subjects[filters+Acls[j]->object]=1;
else {
acl_ec_subjects[filters+Acls[j]->object]=-1;
continue;
}
}
for (k=0; k<Acls[j]->attrs; ++k) {
/* if (Acls[j]->Attrs[k]==any_ofs || !matchstring(&adl->a,map+Acls[j]->Attrs[k])) { */
if (Acls[j]->Attrs[k]==any_ofs || bstr_equal((char*)attr,map+Acls[j]->Attrs[k])) {
if (Acls[j]->may&operation)
return 1;
else
return -1;
break;
}
}
}
}
return 0;
}
static struct hashnode** dn_in_journal(unsigned char* dn);
/* this routine is called for each record matched the query. It basically puts together
* an answer LDAP message from the record and the list of attributes the other side said
* it wanted to have. */
static void answerwith(uint32 ofs,struct SearchRequest* sr,long messageid,int out) {
struct SearchResultEntry sre;
struct PartialAttributeList** pal=&sre.attributes;
struct hashnode** hn;
if ((hn=dn_in_journal((unsigned char*)map+uint32_read(map+ofs+8))) && *hn)
return;
#if (debug != 0)
if (debug) {
@@ -897,20 +969,21 @@ static void answerwith(uint32 ofs,struct SearchRequest* sr,long messageid,int ou
/* now go through list of requested attributes */
{
struct AttributeDescriptionList* adl=sr->attributes;
if (!adl) {
if (!adl && attribute_count>2) {
/* did not ask for any attributes. send 'em all. */
/* to do that, construct a list of all attributes */
/* FIXME! This adl appears to create a segfault later on */
uint32 i;
char* x=map+5*4+size_of_string_table+4;
if (attribute_count>HUGE_SIZE_FOR_SANITY_CHECKS/sizeof(struct AttributeDescriptionList))
return;
adl=alloca((attribute_count)*sizeof(struct AttributeDescriptionList));
for (i=0; i<attribute_count-1; ++i) {
uint32 j;
uint32_unpack(x,&j);
x+=4;
adl[i].a.s=map+j;
adl[i].a.l=strlen(map+j);
adl[i].a.l=str_len(map+j);
adl[i].attrofs=j;
adl[i].next=adl+i+1;
}
@@ -974,29 +1047,32 @@ add_attribute:
}
{
long l=fmt_ldapsearchresultentry(0,&sre);
char *buf=alloca(l+300); /* you never know ;) */
char *buf;
long tmp;
if (verbose) {
buffer_puts(buffer_2,"sre len ");
buffer_putulong(buffer_2,l);
buffer_putsflush(buffer_2,".\n");
if (l<=HUGE_SIZE_FOR_SANITY_CHECKS) {
buf=alloca(l+300); /* you never know ;) */
if (verbose) {
buffer_puts(buffer_2,"sre len ");
buffer_putulong(buffer_2,l);
buffer_putsflush(buffer_2,".\n");
}
tmp=fmt_ldapmessage(buf,messageid,SearchResultEntry,l);
fmt_ldapsearchresultentry(buf+tmp,&sre);
write(out,buf,l+tmp);
}
tmp=fmt_ldapmessage(buf,messageid,SearchResultEntry,l);
fmt_ldapsearchresultentry(buf+tmp,&sre);
write(out,buf,l+tmp);
}
free_ldappal(sre.attributes);
}
#if 0
/*
_ _ _ _ _ _ _
| |__ (_) __ _| |__ | | _____ _____| | | | __| | __ _ _ __
| '_ \| |/ _` | '_ \ | |/ _ \ \ / / _ \ | | |/ _` |/ _` | '_ \
| | | | | (_| | | | | | | __/\ V / __/ | | | (_| | (_| | |_) |
|_| |_|_|\__, |_| |_| |_|\___| \_/ \___|_| |_|\__,_|\__,_| .__/
|___/ |_|
#endif
*/
int copystring(struct string* dest,struct string* src) {
dest->s=malloc(src->l+1);
@@ -1037,6 +1113,7 @@ static int copypal(struct PartialAttributeList** dest,struct PartialAttributeLis
}
#endif
/* small helper for addreq2sre */
static int ar2sreh1(struct PartialAttributeList** dest,struct Addition* src) {
*dest=0;
while (src) {
@@ -1050,25 +1127,112 @@ static int ar2sreh1(struct PartialAttributeList** dest,struct Addition* src) {
return 0;
}
int addreq2sre(struct SearchResultEntry* sre,struct AddRequest* ar) {
/* convert an AddRequest to a SearchResultEntry */
static int addreq2sre(struct SearchResultEntry* sre,struct AddRequest* ar) {
byte_zero(sre,sizeof(*sre));
if (copystring(&sre->objectName,&ar->entry)) goto allocfailed;
if (!(sre->attributes=malloc(sizeof(*sre->attributes)))) goto allocfailed;
if (ar2sreh1(&sre->attributes,&ar->a)) goto allocfailed;
if (copystring(&sre->objectName,&ar->entry) ||
!(sre->attributes=malloc(sizeof(*sre->attributes))) ||
ar2sreh1(&sre->attributes,&ar->a)) {
free_ldapsearchresultentry(sre);
return -1;
}
return 0;
allocfailed:
free_ldapsearchresultentry(sre);
return -1;
}
/* write a search result entry to a file */
static int writesretofd(int fd,struct SearchResultEntry* sre) {
/* we have no locking, but we open using O_APPEND, so the OS synchronizes for us as long
* as we write atomically. Therefore we have to buffer here. */
size_t i,l,nl;
char* c;
struct PartialAttributeList* pal=sre->attributes;
l=5+fmt_ldapescape(0,sre->objectName.s,sre->objectName.l); /* "\ndn: ...\n" */
if (l<=5) return -1;
while (pal) {
struct AttributeDescriptionList* adl=pal->values;
while (adl) {
nl=fmt_ldapescape(0,pal->type.s,pal->type.l);
if (nl>HUGE_SIZE_FOR_SANITY_CHECKS) return -1;
l+=nl;
nl=fmt_ldapescape(0,adl->a.s,adl->a.l);
if (nl>HUGE_SIZE_FOR_SANITY_CHECKS) return -1;
l+=nl;
if (l+3>HUGE_SIZE_FOR_SANITY_CHECKS) return -1;
l+=3;
adl=adl->next;
}
pal=pal->next;
}
c=alloca(l+1);
if (!c) return -1;
i=fmt_str(c,"dn: ");
i+=fmt_ldapescape(c+i,sre->objectName.s,sre->objectName.l);
i+=fmt_str(c+i,"\n");
pal=sre->attributes;
while (pal) {
struct AttributeDescriptionList* adl=pal->values;
while (adl) {
i+=fmt_ldapescape(c+i,pal->type.s,pal->type.l);
i+=fmt_str(c+i,": ");
i+=fmt_ldapescape(c+i,adl->a.s,adl->a.l);
i+=fmt_str(c+i,"\n");
adl=adl->next;
}
pal=pal->next;
}
i+=fmt_str(c+i,"\n");
return (write(fd,c,i)==(ssize_t)i)?0:-1;
}
/* This is the high level LDAP handling code. It reads queries from the socket at in, and
* then writes the answers to out. Normally in == out, but they are separate here so this
* can also be called with in=stdin and out=stdout. */
int writesretofd(int fd,struct SearchResultEntry* sre) {
unsigned long l=fmt_ldapsearchresultentry(0,sre);
char* c=alloca(l+10); /* you never know */
return (write(fd,c,l)==(ssize_t)l)?0:-1;
static void answerwithjournal(struct SearchRequest* sr,long messageid,int out);
static struct hashnode** dn_in_journal2(const char* dn,size_t dnlen);
static int lookupdn(struct string* dn,size_t* index, struct hashnode** hn) {
struct Filter f;
struct hashnode** tmphn;
if ((tmphn=dn_in_journal2(dn->s,dn->l)) && *tmphn) {
*hn=*tmphn;
*index=-1;
return (*hn)->n > 0;
}
*hn=0;
f.type=EQUAL;
f.ava.desc.l=2; f.ava.desc.s="dn";
f.ava.value=*dn;
f.next=0;
fixup(&f);
if (!indexable(&f)) {
buffer_putsflush(buffer_2,"no index for dn, lookup failed!\n");
return -1;
} else {
struct bitfield result;
size_t i,done;
result.bits=alloca(record_set_length*sizeof(unsigned long));
useindex(&f,&result);
done=0;
if (result.first>result.last)
return 0;
done=0;
assert(result.last<=record_count);
for (i=result.first; i<=result.last; ) {
if (!result.bits[i/(8*sizeof(long))]) {
i+=8*sizeof(long);
continue;
}
for (; i<=result.last; ++i) {
if (isset(&result,i)) {
*index=i;
return 1;
}
}
}
}
return 0;
}
/* a standard LDAP session looks like this:
@@ -1083,12 +1247,12 @@ int writesretofd(int fd,struct SearchResultEntry* sre) {
* tinyldap does not complain if you don't unbind before hanging up.
*/
int handle(int in,int out) {
unsigned int len;
size_t len;
char buf[BUFSIZE];
for (len=0;;) {
int tmp=read(in,buf+len,BUFSIZE-len);
int res;
unsigned long messageid,op,Len;
size_t messageid,op,Len;
if (tmp==0) {
close(in);
if (in!=out) close(out);
@@ -1140,16 +1304,16 @@ int handle(int in,int out) {
authfailure:
{
char outbuf[1024];
int s=100;
int len=fmt_ldapbindresponse(outbuf+s,inappropriateAuthentication,"","authentication failure","");
int hlen=fmt_ldapmessage(0,messageid,BindResponse,len);
size_t s=100;
size_t len=fmt_ldapbindresponse(outbuf+s,inappropriateAuthentication,"","authentication failure","");
size_t hlen=fmt_ldapmessage(0,messageid,BindResponse,len);
fmt_ldapmessage(outbuf+s-hlen,messageid,BindResponse,len);
write(out,outbuf+s-hlen,len+hlen);
continue;
}
} else {
struct bitfield result;
unsigned long i,done;
size_t i,done;
result.bits=alloca(record_set_length*sizeof(unsigned long));
useindex(&f,&result);
done=0;
@@ -1220,7 +1384,7 @@ found:
}
#endif
if ((tmp=scan_ldapsearchrequest(buf+res,buf+res+len,&sr))) {
unsigned long returned=0;
size_t returned=0;
#if (debug != 0)
if (debug) {
@@ -1247,7 +1411,7 @@ found:
fixupadl(sr.attributes);
if (indexable(sr.filter)) {
struct bitfield result;
unsigned long i;
size_t i;
#if (debug != 0)
if (debug) buffer_putsflush(buffer_2,"query can be answered with index!\n");
#endif
@@ -1258,7 +1422,7 @@ found:
useindex(sr.filter,&result);
assert(result.last<=record_count);
for (i=result.first; i<=result.last; ) {
unsigned long ni=i+8*sizeof(long);
size_t ni=i+8*sizeof(long);
if (!result.bits[i/(8*sizeof(long))]) {
i=ni;
continue;
@@ -1278,7 +1442,7 @@ found:
}
} else {
char* x=map+5*4+size_of_string_table+attribute_count*8;
unsigned long i;
size_t i;
#if (debug != 0)
if (debug) buffer_putsflush(buffer_2,"query can NOT be answered with index!\n");
#endif
@@ -1293,6 +1457,9 @@ found:
x+=j*8;
}
}
/* now answer with the results from the journal */
answerwithjournal(&sr,messageid,out);
free_ldapsearchrequest(&sr);
} else {
buffer_putsflush(buffer_2,"couldn't parse search request!\n");
@@ -1353,15 +1520,23 @@ found:
// buffer_putsflush(buffer_2,"AddRequest!\n");
if ((tmp=scan_ldapaddrequest(buf+res,buf+res+len,&ar))) {
struct SearchResultEntry sre;
addreq2sre(&sre,&ar);
/* convert addrequest to searchresultentry */
addreq2sre(&sre,&ar);
/* TODO: do something with the add request ;-) */
/* 1. check ACLs */
if (!acls || checkacl(0,0,acl_add,&sre)==1) {
/* 2. check is there already is a record with this dn */
/* 2. check if there already is a record with this dn */
struct hashnode* hn;
size_t idx;
switch (lookupdn(&sre.objectName,&idx,&hn)) {
case -1: err=operationsError; break;
case 1: err=entryAlreadyExists; break;
case 0: break;
default: err=operationsError;
}
if (err==success) {
/* 3. write record to "data.upd" */
{
int fd=open("data.upd",O_WRONLY|O_APPEND|O_CREAT,0600);
int fd=open("journal",O_WRONLY|O_APPEND|O_CREAT,0600);
if (fd==-1)
err=operationsError;
else {
@@ -1426,19 +1601,360 @@ found:
}
}
#if 0
/* journal reading code */
extern int (*ldif_parse_callback)(struct ldaprec* l);
extern mstorage_t stringtable;
extern mduptab_t attributes,classes;
unsigned long hash2(const unsigned char* c) {
unsigned long h=0;
if (*c==0) {
uint32 len=uint32_read((char*)c+1);
return hash(c+5,len);
}
while (*c) {
/* from djb's cdb */
h += (h<<5);
h ^= *c;
++c;
}
return h;
}
#define HASHTABSIZE 8191
unsigned char* bstrdup(unsigned char* c) {
size_t len;
unsigned char* x;
if (*c)
len=str_len((char*)c);
else {
len=5+uint32_read((char*)c+1);
if (len<5) return 0;
}
x=malloc(len);
if (x) byte_copy(x,len,c);
return x;
}
unsigned char* bstrdup_attrib(unsigned char* c) {
char* x=map+5*4+size_of_string_table;
size_t i,l;
if (*c)
l=str_len((char*)c)+1;
else {
l=uint32_read((char*)c+1);
c+=5;
}
for (i=0; i<attribute_count; ++i) {
uint32 j=uint32_read(x);
if (case_equalb(c,l,map+j))
return (unsigned char*)map+j;
x+=4;
}
return bstrdup(c);
}
struct hashnode* hashtab[HASHTABSIZE];
static struct hashnode** dn_in_journal(unsigned char* dn) {
unsigned long hashval;
struct hashnode** hn;
hashval=hash2(dn);
hn=hashtab+(hashval%HASHTABSIZE);
while (*hn) {
if ((*hn)->hashval==hashval) {
if (!bstr_diff((char*)(*hn)->dn,(char*)dn))
break;
}
hn=&((*hn)->next);
}
return hn;
}
static struct hashnode** dn_in_journal2(const char* dn,size_t dnlen) {
unsigned long hashval;
struct hashnode** hn;
hashval=hash2((const unsigned char*)dn);
hn=hashtab+(hashval%HASHTABSIZE);
while (*hn) {
if ((*hn)->hashval==hashval) {
if (!bstr_diff2((char*)(*hn)->dn,dn,dnlen))
break;
}
hn=&((*hn)->next);
}
return hn;
}
int parse_callback(struct ldaprec* l) {
size_t i;
unsigned long hashval;
struct hashnode** hn;
if (l->dn==(uint32)-1) return -1;
hashval=hash2((unsigned char*)stringtable.root+l->dn);
hn=hashtab+(hashval%HASHTABSIZE);
while (*hn) {
if ((*hn)->hashval==hashval) {
if (!bstr_diff((char*)(*hn)->dn,stringtable.root+l->dn))
break;
}
hn=&((*hn)->next);
}
if (*hn) {
/* a record with this dn exists */
/* adjust it to the new reality */
for (i=0; i<(*hn)->n; ++i) {
free((*hn)->a[i].a);
free((*hn)->a[i].v);
}
*hn = realloc(*hn,sizeof(**hn)-sizeof(struct attribute2)+l->n*sizeof(struct attribute2));
if (!*hn) nomem: die(1,"out of memory!");
} else {
*hn = malloc(sizeof(**hn)-sizeof(struct attribute2)+l->n*sizeof(struct attribute2));
if (!*hn) goto nomem;
if (!((*hn)->dn=bstrdup((unsigned char*)stringtable.root+l->dn))) goto nomem;
(*hn)->hashval=hashval;
(*hn)->next=0;
}
(*hn)->n=l->n;
for (i=0; i<l->n; ++i) {
if (!((*hn)->a[i].a=bstrdup_attrib((unsigned char*)attributes.strings.root+l->a[i].name)) ||
!((*hn)->a[i].v=bstrdup((unsigned char*)((*hn)->a[i].a==(unsigned char*)map+objectClass_ofs?classes.strings.root:stringtable.root)+l->a[i].value))) goto nomem;
}
stringtable.used=0;
return 0;
}
int readjournal() {
ldif_parse_callback=parse_callback;
mduptab_init(&attributes);
mduptab_init(&classes);
return ldif_parse("journal");
}
static int ldap_matchfilter_hn(struct hashnode* hn,struct Filter* f) {
struct Filter* y=f->x;
size_t i;
if (!hn->n) return 0;
if (!f) return 1;
switch (f->type) {
case AND:
while (y) {
if (!ldap_matchfilter_hn(hn,y)) return 0;
y=y->next;
}
return 1;
case OR:
while (y) {
if (ldap_matchfilter_hn(hn,y)) return 1;
y=y->next;
}
return 0;
case NOT:
return !ldap_matchfilter_hn(hn,y);
case PRESENT:
if (f->attrofs==dn_ofs)
return 1;
for (i=0; i<hn->n; ++i)
if (!matchstring(&f->ava.desc,(char*)hn->a[i].a))
return 1;
return 0;
case EQUAL:
case LESSEQUAL:
case GREATEQUAL:
if (f->attrofs==dn_ofs)
return matchint(f,(char*)hn->dn);
for (i=0; i<hn->n; ++i)
if (!matchstring(&f->ava.desc,(char*)hn->a[i].a) &&
matchint(f,(char*)hn->a[i].v)) return 1;
return 0;
case SUBSTRING:
if (f->attrofs==dn_ofs)
return substringmatch(f->substrings,(char*)hn->dn,f->attrflag&1);
for (i=0; i<hn->n; ++i)
if (!matchstring(&f->ava.desc,(char*)hn->a[i].a) &&
substringmatch(f->substrings,(char*)hn->a[i].v,f->attrflag&1)) return 1;
return 0;
default:
write(2,"unsupported query type\n",23);
return 0;
}
return 1;
}
/* return 0 if they didn't match, otherwise return length in b */
static int match(const char* a,int len,const char* b) {
const char* A=a+len;
const char* B=b+str_len(b);
while (len>0 && A>a && B>b) {
--A; --B; --len;
while (*A==' ' && A>a) { --A; --len; }
while (*B==' ' && B>b) --B;
if (tolower(*A) != tolower(*B))
return 0;
}
return str_len(B);
}
static int matchhashnode(struct hashnode* hn,struct SearchRequest* sr) {
size_t i,len=bstrlen((char*)hn->dn);
unsigned char* c;
if (sr->baseObject.l>len)
/* baseObject is longer than dn */
return 0;
if (sr->baseObject.l && !match(sr->baseObject.s,sr->baseObject.l,(char*)hn->dn))
/* baseObject is not a suffix of dn */
return 0;
switch (sr->scope) {
case wholeSubtree: break;
case baseObject: if (len==sr->baseObject.l) break; return 0;
default:
c=hn->dn+bstrstart((char*)hn->dn);
for (i=0; i<len; ++i)
if (c[i]==',')
break;
if (i+2>=len-sr->baseObject.l) break;
return 0;
}
return ldap_matchfilter_hn(hn,sr->filter);
}
static void answerwith_hn(struct hashnode* hn,struct SearchRequest* sr,long messageid,int out) {
struct SearchResultEntry sre;
struct PartialAttributeList** pal=&sre.attributes;
if (acls)
byte_zero(acl_ec_subjects+filters,filters);
if (acls && checkacl_hn(hn,(unsigned char*)map+dn_ofs,acl_read)!=1) return;
sre.objectName.l=bstrlen(sre.objectName.s=(char*)hn->dn);
sre.attributes=0;
/* now go through list of requested attributes */
{
struct AttributeDescriptionList* adl=sr->attributes;
if (!adl && hn->n && hn->n<HUGE_SIZE_FOR_SANITY_CHECKS/sizeof(*adl)) {
/* did not ask for any attributes. send 'em all. */
/* to do that, construct a list of all attributes */
uint32 i,j,k;
adl=alloca(hn->n*sizeof(*adl));
for (i=k=0; i<hn->n; ++i) {
adl[k].a.s=(char*)hn->a[i].a;
adl[k].a.l=str_len((char*)hn->a[i].a);
adl[k].attrofs=0;
adl[k].next=adl+k+1;
for (j=0; j<i; ++j) {
if (!strcmp((char*)hn->a[i].a,(char*)hn->a[j].a)) {
--k;
break;
}
}
++k;
}
if (k) adl[k-1].next=0;
}
while (adl) {
const unsigned char* val=0;
uint32 i=0;
if (!acls || checkacl_hn(hn,(unsigned char*)adl->a.s,acl_read)==1) {
if (!matchstring(&adl->a,"dn"))
val=hn->dn;
else {
for (; i<hn->n; ++i)
if (!matchstring(&adl->a,(char*)hn->a[i].a)) {
val=hn->a[i].v;
++i;
break;
}
}
if (val) {
*pal=malloc(sizeof(struct PartialAttributeList));
if (!*pal) {
nomem:
buffer_putsflush(buffer_2,"out of virtual memory!\n");
exit(1);
}
(*pal)->type=adl->a;
{
struct AttributeDescriptionList** a;
a=&(*pal)->values;
add_attribute:
*a=malloc(sizeof(struct AttributeDescriptionList));
if (!*a) goto nomem;
(*a)->a.s=bstrfirst((char*)val);
(*a)->a.l=bstrlen((char*)val);
for (;i<hn->n; ++i)
if (!matchstring(&adl->a,(char*)hn->a[i].a)) {
val=hn->a[i].v;
++i;
a=&(*a)->next;
goto add_attribute;
}
(*a)->next=0;
}
(*pal)->next=0;
pal=&(*pal)->next;
}
}
adl=adl->next;
}
}
{
long l=fmt_ldapsearchresultentry(0,&sre);
char *buf;
long tmp;
if (l<HUGE_SIZE_FOR_SANITY_CHECKS) {
buf=alloca(l+300); /* you never know ;) */
if (verbose) {
buffer_puts(buffer_2,"sre len ");
buffer_putulong(buffer_2,l);
buffer_putsflush(buffer_2,".\n");
}
tmp=fmt_ldapmessage(buf,messageid,SearchResultEntry,l);
fmt_ldapsearchresultentry(buf+tmp,&sre);
write(out,buf,l+tmp);
}
}
free_ldappal(sre.attributes);
}
static void answerwithjournal(struct SearchRequest* sr,long messageid,int out) {
int i;
for (i=0; i<HASHTABSIZE; ++i) { /* for all entries in hash table... */
struct hashnode* hn=hashtab[i];
while (hn) {
if (matchhashnode(hn,sr)) {
answerwith_hn(hn,sr,messageid,out);
}
hn=hn->next;
}
}
}
/*
_
_ __ ___ __ _(_)_ __
| '_ ` _ \ / _` | | '_ \
| | | | | | (_| | | | | |
|_| |_| |_|\__,_|_|_| |_|
#endif
*/
int main(int argc,char* argv[]) {
#ifdef STANDALONE
int sock;
#endif
errmsg_iam("tinyldap");
signal(SIGPIPE,SIG_IGN);
map=mmap_read(argc>1?argv[1]:"data",&filelen);
@@ -1456,7 +1972,7 @@ int main(int argc,char* argv[]) {
/* look up "dn" and "objectClass" */
{
char* x=map+5*4+size_of_string_table;
unsigned int i;
size_t i;
dn_ofs=objectClass_ofs=userPassword_ofs=any_ofs=0;
for (i=0; i<attribute_count; ++i) {
uint32 j;
@@ -1477,6 +1993,8 @@ int main(int argc,char* argv[]) {
load_acls();
readjournal();
#if 0
ldif_parse("exp.ldif");
if (!first) {