From 7376f0342cd6de664ac8ef40e22079a2a42f0c0e Mon Sep 17 00:00:00 2001 From: leitner Date: Thu, 13 Oct 2005 16:51:44 +0000 Subject: [PATCH] add hash table index type --- README.security | 8 ++ addindex.c | 211 ++++++++++++++++++++++++++++++++++++++++++++++-- dumpidx.c | 5 +- tinyldap.c | 55 ++++++++++++- 4 files changed, 269 insertions(+), 10 deletions(-) create mode 100644 README.security diff --git a/README.security b/README.security new file mode 100644 index 0000000..0568a9e --- /dev/null +++ b/README.security @@ -0,0 +1,8 @@ +tinyldap trusts the binary data file on disk. +There are numerous ways to make tinyldap crash or loop endlessly if an +attacker can hex edit the data file. + +Other than that, tinyldap does not trust anyone :-) + +tinyldap can (and should) be run as non-root, via tcpserver, in a chroot +jail. diff --git a/addindex.c b/addindex.c index 5f891fa..53aa370 100644 --- a/addindex.c +++ b/addindex.c @@ -10,6 +10,8 @@ #include "uint32.h" #include "mstorage.h" #include +#include +#include mstorage_t idx; char* map; @@ -30,9 +32,39 @@ int compari(const void* a,const void* b) { return *(uint32*)b-*(uint32*)a; } +uint32 hash(const unsigned char* c,unsigned long keylen) { + unsigned long h=0; + unsigned long i; + for (i=0; i2; --j) { uint32_unpack(x,&k); @@ -169,6 +201,169 @@ int main(int argc,char* argv[]) { } } } else if (mode==HASHTABLE) { + uint32 i,j,counted,cur; + char* x; + struct node { + uint32 recnum,hashcode; + }* y; + struct htentry { + uint32 count; + uint32* x; + }* tab; + uint32 maxtabsize; + uint32 maxcoll,mincoll,cmaxcoll,nmaxcoll,nmincoll,cmincoll; + uint32 indexsize; + cmaxcoll=cmincoll=0; /* shut gcc up */ + if (wanted==dn) + counted=record_count; + else { + x=map+5*4+size_of_string_table+attribute_count*8; + counted=0; + for (i=0; i2; --j) { + uint32_unpack(x,&k); + if (k==wanted) + ++counted; + x+=8; + } + } + } + if (!counted) die(111,"attribute does not occur?!"); + y=malloc(counted*sizeof(struct node)); + if (!y) die(111,"out of memory"); + x=map+5*4+size_of_string_table+attribute_count*8; + for (cur=i=0; i2; --j) { + uint32_unpack(x,&k); + if (k==wanted) { + y[cur].recnum=i; + y[cur].hashcode=hashmapped(k,ignorecase); + ++cur; + } + x+=8; + } + } + } + buffer_putulong(buffer_1,counted); + buffer_putsflush(buffer_1," entries hashed; looking for hash table size with least collisions..."); + i=counted; + if (!(i&1)) ++i; + maxtabsize=counted+counted/8; + tab=malloc(maxtabsize*sizeof(struct htentry)); + if (!tab) die(111,"out of memory"); + maxcoll=nmaxcoll=nmincoll=0; mincoll=-1; + for (; i1) ++k; + if (tab[l].count==2) ++chains; + } + if (k>maxcoll) { + nmaxcoll=i; + maxcoll=k; + cmaxcoll=chains; + } + if (k1) + indexsize+=(tab[j].count+1)*4; + + free(y); + munmap(map,filelen); + + { + int fd=open(filename,O_RDWR); + char* dest,* x,* z; + if (fd<0) + diesys(111,"Could not re-open database file read-write"); + ftruncate(fd,filelen+indexsize); + map=mmap(0,filelen+indexsize,PROT_WRITE,MAP_SHARED,fd,0); + if (map==(char*)-1) + diesys(111,"Could not mmap database file read-write"); + uint32_pack(map+casesensitive,ignorecase); + dest=map+filelen; + uint32_pack(dest,3); /* index type 3 == hash table */ + uint32_pack(dest+4,filelen+indexsize); /* offset of next index */ + uint32_pack(dest+2*4,wanted); /* indexed attribute */ + uint32_pack(dest+3*4,maxtabsize); /* hash table size in uint32s */ + x=dest+4*4; + z=x+maxtabsize*4; + for (j=0; j1) { + uint32 k; + uint32_pack(x,filelen+(z-dest)); + x+=4; + uint32_pack(z,tab[j].count); + z+=4; + for (k=0; ktype==EQUAL)) if (!matchstring(&f->ava.desc,map+indexed_attribute)) return 1; ofs=next; @@ -567,6 +567,28 @@ 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; + for (i=0; ix; if (!f) return 1; + if (f->type==EQUAL) { /* prefer a hash index if there is one */ + uint32 ofs; + for (ofs=indices_offset+record_count*4; ofs<(unsigned long)filelen;) { + uint32 index_type,next,indexed_attribute; + index_type=uint32_read(map+ofs); + next=uint32_read(map+ofs+4); + indexed_attribute=uint32_read(map+ofs+8); + if (index_type==3) + if (!matchstring(&f->ava.desc,map+indexed_attribute)) { + uint32 hashtabsize=uint32_read(map+ofs+12); + uint32 hashtab=ofs+16; + uint32 hashval=hash(f->ava.value.s,f->ava.value.l); + uint32 hashofs=uint32_read(map+hashtab+(hashval%hashtabsize)*4); + if (hashofs==0) return 1; + if (hashofstype) { case AND: {