add journal rereading

add DelRequest support
add little delete test tool ldapdelete
This commit is contained in:
leitner
2008-04-20 06:59:11 +00:00
parent fcf6ed51f2
commit 05d388f122
16 changed files with 448 additions and 137 deletions

View File

@@ -3,7 +3,7 @@
all: t1 t2 parse dumpidx idx2ldif addindex bindrequest tinyldap \
tinyldap_standalone tinyldap_debug ldapclient ldapclient_str \
md5password mysql2ldif acl dumpacls # t6 # t
md5password mysql2ldif acl dumpacls ldapdelete # t6 # t
asn1.a: fmt_asn1intpayload.o fmt_asn1length.o fmt_asn1tag.o \
fmt_asn1int.o fmt_asn1string.o fmt_asn1transparent.o scan_asn1tag.o \
@@ -23,20 +23,21 @@ matchprefix.o matchcasestring.o matchcaseprefix.o \
scan_ldapmodifyrequest.o scan_ldapaddrequest.o bstrlen.o bstrfirst.o \
bstrstart.o free_ldapadl.o free_ldappal.o free_ldapsearchfilter.o \
scan_ldapsearchfilterstring.o free_ldapsearchresultentry.o \
fmt_ldapsearchfilterstring.o ldap_match_sre.o
fmt_ldapsearchfilterstring.o ldap_match_sre.o \
fmt_ldapdeleterequest.o scan_ldapdeleterequest.o normalize_dn.o
ldif.a: ldif_parse.o ldap_match_mapped.o
storage.a: strstorage.o strduptab.o mstorage_add.o mduptab_add.o \
bstr_diff.o mduptab_adds.o bstr_diff2.o mstorage_add_bin.o \
mstorage_init.o mstorage_init_persistent.o mstorage_unmap.o \
mduptab_init.o mduptab_init_reuse.o
mduptab_init.o mduptab_init_reuse.o mduptab_reset.o
auth.a: auth.o
DIET=/opt/diet/bin/diet -Os
CC=gcc
CFLAGS=-pipe -I. -Wall -W
CFLAGS=-pipe -I. -Wall -W -Wextra
ifneq ($(DEBUG),)
DIET=/opt/diet/bin/diet
CFLAGS=-pipe -I. -Wall -W -g -fstack-protector
@@ -66,9 +67,10 @@ t2: ldap.a asn1.a
t3 t4 t5 addindex: storage.a
t6: storage.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
bindrequest tinyldap tinyldap_standalone tinyldap_debug ldapclient ldapclient_str ldapdelete: ldap.a asn1.a
idx2ldif: ldap.a
dumpacls: ldap.a asn1.a
parse: normalize_dn.o
tinyldap_standalone: tinyldap.c
$(DIET) $(CC) $(CFLAGS) -DSTANDALONE -o $@ $^ $(LDFLAGS) -lowfat $(LIBS)

View File

@@ -66,15 +66,6 @@ kaputt:
if (!buf) goto kaputt;
buf[l2=fmt_ldapsearchfilterstring(buf,f)]=0;
buffer_puts(buffer_1,buf);
if (l!=l2) {
buffer_puts(buffer_1,"\n\n\n");
buffer_putulong(buffer_1,l);
buffer_puts(buffer_1," != ");
buffer_putulong(buffer_1,l2);
buffer_puts(buffer_1,"\n");
buffer_flush(buffer_1);
assert(l==l2);
}
free_ldapsearchfilter(f);
free(f);
}

8
fmt_ldapdeleterequest.c Normal file
View File

@@ -0,0 +1,8 @@
#include <string.h>
#include "ldap.h"
#include "byte.h"
size_t fmt_ldapdeleterequest(char* dest,struct string* s) {
if (dest) byte_copy(dest,s->l,s->s);
return s->l;
}

View File

@@ -14,7 +14,7 @@ static void dumpbstr(const char* c) {
l=bstrlen(c);
d=bstrfirst(c);
up=fmt_ldapescape(0,d,l);
assert(up>=l);
// assert(up>=l);
if (up==l) {
buffer_puts(buffer_1," ");
if (*c)

14
ldap.h
View File

@@ -14,6 +14,10 @@ int matchcasestring(struct string* s,const char* c);
int matchprefix(struct string* s,const char* c);
int matchcaseprefix(struct string* s,const char* c);
/* "ou=fnord; O=fefe; c=de" -> "ou=fnord,o=fefe,c=de" */
/* returns the length of the new string */
size_t normalize_dn(char* dest,const char* src,int len);
struct AttributeValueAssertion {
struct string desc, value;
};
@@ -94,6 +98,12 @@ struct AddRequest {
struct Addition a;
};
struct ModifyDNRequest {
struct string entry, newrdn;
int deleteoldrdn;
struct string newsuperior;
};
enum ldapops {
BindRequest=0, BindResponse=1,
UnbindRequest=2,
@@ -173,6 +183,8 @@ size_t scan_ldapresult(const char* src,const char* max,unsigned long* result,
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);
size_t scan_ldapdeleterequest(const char* src,const char* max,struct string* s);
size_t scan_ldapmodifydnrequest(const char* src,const char* max,struct ModifyDNRequest* mdr);
size_t fmt_ldapstring(char* dest,struct string* s);
size_t fmt_ldapmessage(char* dest,long messageid,long op,size_t len);
@@ -187,6 +199,8 @@ 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);
size_t fmt_ldapdeleterequest(char* dest,struct string* s);
size_t fmt_ldapmodifydnrequest(char* dest,struct ModifyDNRequest* mdr);
#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)

View File

@@ -195,6 +195,21 @@ nextmessage:
goto copypartialandcontinue;
}
} else if (op==SearchResultDone) {
unsigned long result;
struct string matcheddn,errormessage,referral;
if (scan_ldapresult(buf+cur+tmp2,max,&result,&matcheddn,&errormessage,&referral)>0) {
if (result!=0) {
buffer_puts(buffer_2,"fail, code ");
buffer_putulong(buffer_2,result);
if (errormessage.l) {
buffer_puts(buffer_2,", error message \"");
buffer_put(buffer_2,errormessage.s,errormessage.l);
buffer_puts(buffer_2,"\n");
}
buffer_putsflush(buffer_2,".\n");
}
} else
buffer_putsflush(buffer_2,"scan_ldapresult failed!\n");
if (!matches)
buffer_putsflush(buffer_2,"no matches.\n");
if (bench && durchlauf!=0)

127
ldapdelete.c Normal file
View File

@@ -0,0 +1,127 @@
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "byte.h"
#include "buffer.h"
#include "asn1.h"
#include "ldap.h"
#include "socket.h"
#include "ip4.h"
#include "str.h"
#include "textcode.h"
#include <fcntl.h>
#include <sys/socket.h>
#define BUFSIZE 8192
static unsigned long messageid=1;
static int ldapbind(int sock) {
char outbuf[1024];
int s=100;
size_t len=fmt_ldapbindrequest(outbuf+s,3,"","");
size_t hlen=fmt_ldapmessage(0,messageid,BindRequest,len);
size_t res,Len;
unsigned long op,result;
struct string matcheddn,errormessage,referral;
fmt_ldapmessage(outbuf+s-hlen,messageid,BindRequest,len);
if ((size_t)write(sock,outbuf+s-hlen,len+hlen)!=len+hlen) return 0;;
len=read(sock,outbuf,1024);
res=scan_ldapmessage(outbuf,outbuf+len,&messageid,&op,&Len);
if (!res) return 0;
if (op!=BindResponse) return 0;
res=scan_ldapbindresponse(outbuf+res,outbuf+res+Len,&result,&matcheddn,&errormessage,&referral);
if (!res) return 0;
if (result) return 0;
return 1;
}
int main(int argc,char* argv[]) {
int sock;
char buf[BUFSIZE];
int len=0;
char* me;
if ((me=strrchr(argv[0],'/')))
++me;
else
me=argv[0];
if (argc<2) {
usage:
buffer_putsflush(buffer_2,"usage: ldapdelete ip dn\n");
return 0;
}
sock=socket_tcp4b();
{
char ip[4];
if (argv[1][scan_ip4(argv[1],ip)]) goto usage;
if (socket_connect4(sock,ip,389)) {
buffer_putsflush(buffer_2,"could not connect to ldap server!\n");
return 1;
}
}
if (ldapbind(sock)) {
struct string s;
s.l=strlen(argv[2]);
s.s=argv[2];
len=fmt_ldapdeleterequest(buf+100,&s);
{
int tmp=fmt_ldapmessage(0,++messageid,DelRequest,len);
fmt_ldapmessage(buf+100-tmp,messageid,DelRequest,len);
write(sock,buf+100-tmp,len+tmp);
}
shutdown(sock,SHUT_WR);
{
char buf[32*1024]; /* arbitrary limit, bad! */
int len=0,tmp,tmp2;
char* max;
unsigned long mid,op;
size_t slen;
int cur=0;
tmp=read(sock,buf+len,sizeof(buf)-len);
if (tmp<=0) {
buffer_putsflush(buffer_2,"read error.\n");
return 2;
}
len+=tmp;
if ((tmp2=scan_ldapmessage(buf+cur,buf+len,&mid,&op,&slen))) {
max=buf+cur+slen+tmp2;
if (op==DelResponse) {
unsigned long result;
struct string matcheddn, errormessage, referral;
if (scan_ldapresult(buf+cur+tmp2,max,&result,&matcheddn,&errormessage,&referral)>0) {
if (result==success) {
buffer_putsflush(buffer_2,"ok\n");
} else {
buffer_puts(buffer_2,"fail, code ");
buffer_putulong(buffer_2,result);
if (errormessage.l) {
buffer_puts(buffer_2,", error message \"");
buffer_put(buffer_2,errormessage.s,errormessage.l);
buffer_puts(buffer_2,"\n");
}
buffer_putsflush(buffer_2,".\n");
}
} else
buffer_putsflush(buffer_2,"failed to parse result message.\n");
} else
buffer_putsflush(buffer_2,"unexpected response.\n");
} else
buffer_putsflush(buffer_2,"failed to parse ldap message.\n");
}
} else {
buffer_putsflush(buffer_2,"ldapbind failed\n");
return 2;
}
close(sock);
return 0;
}

4
ldif.h
View File

@@ -1,3 +1,5 @@
#define _FILE_OFFSET_BITS 64
#include <sys/stat.h>
#include <inttypes.h>
#include <ldap.h>
@@ -19,7 +21,7 @@ extern uint32_t dn, mail, sn, cn, objectClass;
extern struct ldaprec *first;
extern unsigned long ldifrecords;
int ldif_parse(const char* filename);
int ldif_parse(const char* filename,off_t fromofs,struct stat* ss);
/* return non-zero if the record matches the search request */
int ldap_match(struct ldaprec* r,struct SearchRequest* sr);

View File

@@ -1,3 +1,4 @@
#define _FILE_OFFSET_BITS 64
#include <alloca.h>
#include <buffer.h>
#include <scan.h>
@@ -48,34 +49,10 @@ static void addattribute(struct ldaprec** l,uint32_t name,uint32_t val) {
}
}
/* "ou=fnord; O=fefe; c=de" -> "ou=fnord,o=fefe,c=de" */
/* returns the length of the new string */
static int normalize_dn(char* dest,const char* src,int len) {
int makelower=1;
char* orig=dest;
while (len) {
if (*src==';' || *src==',') {
*dest=',';
while (len>1 && src[1]==' ') { ++src; --len; }
makelower=1;
} else {
if (makelower)
*dest=tolower(*src);
else
*dest=*src;
if (*dest=='=') makelower=0;
}
++dest;
++src;
--len;
}
return dest-orig;
}
static int unbase64(char* buf) {
unsigned long destlen;
static size_t unbase64(char* buf) {
size_t destlen;
char temp[8192];
long l=scan_base64(buf,temp,&destlen);
size_t l=scan_base64(buf,temp,&destlen);
if (buf[l] && buf[l]!='\n') return 0;
byte_copy(buf,destlen,temp);
return destlen;
@@ -302,6 +279,7 @@ lookagain:
addattribute(l,tmp,val);
#endif
} while (!eof);
if ((*l)->dn==(uint32_t)-1) return 0;
if (ldif_parse_callback && ldif_parse_callback(*l)==-1) return -1;
if ((*l)->dn==(uint32_t)-1 && ((*l)->next)) {
struct ldaprec* m=(*l)->next;
@@ -313,7 +291,7 @@ lookagain:
struct ldaprec *first=0;
int ldif_parse(const char* filename) {
int ldif_parse(const char* filename,off_t fromofs,struct stat* ss) {
char buf[4096];
int fd;
buffer in;
@@ -325,7 +303,8 @@ int ldif_parse(const char* filename) {
fd=-1;
} else {
fd=open_read(filename);
if (fd<0) return 1;
if (fd<0) return 0; // no journal file is permissible
if (fromofs) lseek(fd,fromofs,SEEK_SET);
buffer_init(&in,(void*)read,fd,buf,sizeof buf);
tmp=&in;
}
@@ -334,6 +313,13 @@ int ldif_parse(const char* filename) {
lines=0;
{
int res=parserec(tmp,&first);
if (ss) {
fstat(fd,ss);
/* the file size may have changed between parserec hitting EOF and
* us calling lstat, we we write the current file pointer position
* to st_size */
ss->st_size=lseek(fd,0,SEEK_CUR);
}
if (fd!=-1) close(fd);
return res;
}

View File

@@ -16,3 +16,4 @@ 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,size_t len);
long mduptab_adds(mduptab_t* t,const char* s);
void mduptab_reset(mduptab_t* t);

View File

@@ -2,7 +2,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/fcntl.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <stdio.h>
#include "byte.h"

View File

@@ -1,12 +1,22 @@
#include "mstorage.h"
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <sys/shm.h>
void mstorage_unmap(mstorage_t* p) {
#ifdef MREMAP_MAYMOVE
munmap(p->root,p->mapped);
#else
free(p->root);
#endif
if (p->fd!=-1) {
ftruncate(p->fd,p->used);
close(p->fd);
}
p->mapped=p->used=0;
p->root=0;
}

View File

@@ -193,7 +193,7 @@ writeerror:
// if ((mduptab_adds(&attributes,"*"))<0)
// die(1,"out of memory");
ldif_parse(argc<2?"exp.ldif":argv[1]);
ldif_parse(argc<2?"exp.ldif":argv[1],0,0);
if (!first)
die(1,"usage: parse [src-ldif-filename] [dest-bin-filename]\n");

View File

@@ -8,7 +8,6 @@ size_t scan_asn1ENUMERATED(const char* src,const char* max,unsigned long* val) {
long ltmp;
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;
*val=(unsigned long)ltmp;
return tmp;
}

10
scan_ldapdeleterequest.c Normal file
View File

@@ -0,0 +1,10 @@
#include "asn1.h"
#include "ldap.h"
size_t scan_ldapdeleterequest(const char* src,const char* max,
struct string* s) {
if (src>=max) return 0;
s->l=max-src;
s->s=src;
return s->l;
}

View File

@@ -1,3 +1,4 @@
#define _FILE_OFFSET_BITS 64
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
@@ -196,6 +197,8 @@ struct acl {
struct acl** Acls;
static void load_acls() {
struct acl** oldAcls=Acls;
size_t oldacls=acls;
uint32 ofs;
uint32 acl_ofs;
acl_ofs=0;
@@ -281,11 +284,56 @@ kaputt:
for (i=0; i<filters; ++i)
acl_ec_subjects[i]=(Filters[i]==(struct Filter*)Any);
}
if (oldAcls) {
size_t i;
for (i=0; i<oldacls; ++i)
free(oldAcls[i]);
free(oldAcls);
}
}
/* End of ACL code */
static const char* datafilename;
static struct stat ss_data;
static struct stat ss_journal;
void map_datafile(const char* filename) {
map=mmap_read(datafilename=filename,&filelen);
stat(datafilename,&ss_data);
if (!map) {
buffer_putsflush(buffer_2,"could not open data!\n");
exit(1);
}
uint32_unpack(map,&magic);
uint32_unpack(map+4,&attribute_count);
uint32_unpack(map+2*4,&record_count);
uint32_unpack(map+3*4,&indices_offset);
uint32_unpack(map+4*4,&size_of_string_table);
record_set_length=(record_count+sizeof(unsigned long)*8-1) / (sizeof(long)*8);
/* look up "dn" and "objectClass" */
{
char* x=map+5*4+size_of_string_table;
size_t i;
dn_ofs=objectClass_ofs=userPassword_ofs=any_ofs=0;
for (i=0; i<attribute_count; ++i) {
uint32 j;
j=uint32_read(x);
if (case_equals("dn",map+j))
dn_ofs=j;
else if (case_equals("objectClass",map+j))
objectClass_ofs=j;
else if (case_equals("userPassword",map+j))
userPassword_ofs=j;
x+=4;
}
if (!dn_ofs || !objectClass_ofs) {
buffer_putsflush(buffer_2,"can't happen error: dn or objectClass not there?!\n");
exit(0);
}
}
}
/*
_ _ _
@@ -652,7 +700,7 @@ static void tagmatches(uint32* index,size_t elements,struct string* s,
}
}
uint32 hash(const unsigned char* c,size_t keylen) {
static uint32 hash(const unsigned char* c,size_t keylen) {
size_t h=0,i;
for (i=0; i<keylen; ++i) {
/* from djb's cdb */
@@ -662,7 +710,7 @@ uint32 hash(const unsigned char* c,size_t keylen) {
return (uint32)h;
}
uint32 hash_tolower(const unsigned char* c,size_t keylen) {
static 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 */
@@ -869,7 +917,6 @@ static int checkacl(uint32 recofs,uint32 attrofs,unsigned long operation,struct
}
}
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 || attrofs==Acls[j]->Attrs[k]) {
if (Acls[j]->may&operation)
return 1;
@@ -1087,7 +1134,7 @@ add_attribute:
|___/ |_|
*/
int copystring(struct string* dest,struct string* src) {
static int copystring(struct string* dest,struct string* src) {
dest->s=malloc(src->l+1);
if (!dest->s) return -1;
byte_copy((char*)dest->s,src->l,src->s);
@@ -1340,7 +1387,7 @@ static int lookupdn(struct string* dn,size_t* index, struct hashnode** hn) {
useindex(&f,&result);
if (result.first>result.last)
return 0;
assert(result.last<=record_count);
// assert(result.last<=record_count);
for (i=result.first; i<=result.last; ) {
if (!result.bits[i/(8*sizeof(long))]) {
i+=8*sizeof(long);
@@ -1357,6 +1404,17 @@ static int lookupdn(struct string* dn,size_t* index, struct hashnode** hn) {
return 0;
}
static void normalize_string_dn(struct string* s) {
/* OK this is a kludge. s->s is supposed to be read-only because it points into the
* buffer where we read it into from the network.
* Since normalize_dn ends up using less or equal space, and we are not interested in
* the non-normalized dn, we do the read-write cast and normalize in-place.
* Kids, don't do this at home. */
s->l=normalize_dn((char*)s->s,s->s,s->l);
}
static void update();
/* a standard LDAP session looks like this:
* 1. connect to server
* 2. send a BindRequest
@@ -1368,7 +1426,7 @@ static int lookupdn(struct string* dn,size_t* index, struct hashnode** hn) {
* 5. close
* tinyldap does not complain if you don't unbind before hanging up.
*/
int handle(int in,int out) {
static int handle(int in,int out) {
size_t len;
char buf[BUFSIZE];
for (len=0;;) {
@@ -1395,14 +1453,15 @@ int handle(int in,int out) {
buffer_putulong(buffer_2,op);
buffer_putsflush(buffer_2,".\n");
}
update();
switch (op) {
case BindRequest:
{
unsigned long version,method;
struct string name;
int tmp;
tmp=scan_ldapbindrequest(buf+res,buf+res+len,&version,&name,&method);
if (tmp>=0) {
size_t tmp;
tmp=scan_ldapbindrequest(buf+res,buf+len,&version,&name,&method);
if (tmp>0) {
if (verbose) {
buffer_puts(buffer_2,"bind request: version ");
buffer_putulong(buffer_2,version);
@@ -1418,8 +1477,9 @@ int handle(int in,int out) {
struct hashnode* hn;
int err=success;
scan_ldapstring(buf+res+tmp,buf+res+len,&password);
scan_ldapstring(buf+res+tmp,buf+len,&password);
normalize_string_dn(&name);
switch (lookupdn(&name,&idx,&hn)) {
case -1: err=operationsError; break;
case 1: break;
@@ -1430,7 +1490,7 @@ int handle(int in,int out) {
goto authfailure;
else {
char* c=0;
uint32 authdn;
uint32 authdn=0;
char* authdn_str=0;
if (idx==(size_t)-1) { // found in journal
size_t i;
@@ -1485,9 +1545,9 @@ authfailure:
}
{
char outbuf[1024];
int s=100;
int len=fmt_ldapbindresponse(outbuf+s,0,"","go ahead","");
int hlen=fmt_ldapmessage(0,messageid,BindResponse,len);
size_t s=100;
size_t len=fmt_ldapbindresponse(outbuf+s,0,"","go ahead","");
size_t hlen=fmt_ldapmessage(0,messageid,BindResponse,len);
fmt_ldapmessage(outbuf+s-hlen,messageid,BindResponse,len);
write(out,outbuf+s-hlen,len+hlen);
}
@@ -1497,7 +1557,7 @@ authfailure:
case SearchRequest:
{
struct SearchRequest sr;
int tmp;
size_t tmp;
#if 0
{
int fd=open_write("request");
@@ -1505,7 +1565,7 @@ authfailure:
close(fd);
}
#endif
if ((tmp=scan_ldapsearchrequest(buf+res,buf+res+len,&sr))) {
if ((tmp=scan_ldapsearchrequest(buf+res,buf+len,&sr))) {
size_t returned=0;
#if (debug != 0)
@@ -1542,7 +1602,7 @@ authfailure:
* of the matches in a table. Use findrec to locate
* the records that point to the data. */
useindex(sr.filter,&result);
assert(result.last<=record_count);
// assert(result.last<=record_count);
for (i=result.first; i<=result.last; ) {
size_t ni=i+8*sizeof(long);
if (!result.bits[i/(8*sizeof(long))]) {
@@ -1589,8 +1649,8 @@ authfailure:
}
{
char buf[1000];
long l=fmt_ldapsearchresultdone(buf+100,0,"","","");
int hlen=fmt_ldapmessage(0,messageid,SearchResultDone,l);
size_t l=fmt_ldapsearchresultdone(buf+100,0,"","","");
size_t hlen=fmt_ldapmessage(0,messageid,SearchResultDone,l);
fmt_ldapmessage(buf+100-hlen,messageid,SearchResultDone,l);
write(out,buf+100-hlen,l+hlen);
}
@@ -1602,30 +1662,34 @@ authfailure:
case ModifyRequest:
{
struct ModifyRequest mr;
int tmp,err=success;
size_t tmp,err=success;
buffer_putsflush(buffer_2,"modifyrequest!\n");
if ((tmp=scan_ldapmodifyrequest(buf+res,buf+res+len,&mr))) {
if ((tmp=scan_ldapmodifyrequest(buf+res,buf+len,&mr))) {
struct SearchResultEntry sre;
buffer_puts(buffer_1,"modify request: dn \"");
buffer_put(buffer_1,mr.object.s,mr.object.l);
buffer_putsflush(buffer_1,"\"\n");
switch (mr.m.operation) {
case 0: buffer_puts(buffer_1,"Add\n"); break;
case 1: buffer_puts(buffer_1,"Delete\n"); break;
case 2: buffer_puts(buffer_1,"Replace\n"); break;
if (verbose) {
buffer_puts(buffer_1,"modify request: dn \"");
buffer_put(buffer_1,mr.object.s,mr.object.l);
buffer_putsflush(buffer_1,"\"\n");
switch (mr.m.operation) {
case 0: buffer_puts(buffer_1,"Add\n"); break;
case 1: buffer_puts(buffer_1,"Delete\n"); break;
case 2: buffer_puts(buffer_1,"Replace\n"); break;
}
buffer_put(buffer_1,mr.m.AttributeDescription.s,mr.m.AttributeDescription.l);
buffer_puts(buffer_1,"\n");
{
struct AttributeDescriptionList* x=mr.m.vals;
do {
buffer_puts(buffer_1," -> \"");
buffer_put(buffer_1,x->a.s,x->a.l);
buffer_putsflush(buffer_1,"\"\n");
x=x->next;
} while (x);
}
}
buffer_put(buffer_1,mr.m.AttributeDescription.s,mr.m.AttributeDescription.l);
buffer_puts(buffer_1,"\n");
{
struct AttributeDescriptionList* x=mr.m.vals;
do {
buffer_puts(buffer_1," -> \"");
buffer_put(buffer_1,x->a.s,x->a.l);
buffer_putsflush(buffer_1,"\"\n");
x=x->next;
} while (x);
}
/* TODO: do something with the modify request ;-) */
normalize_string_dn(&mr.object);
if (acls) {
/* convert modifyrequest to searchresultentry */
modreq2sre(&sre,&mr);
@@ -1648,7 +1712,7 @@ authfailure:
#if 1
/* 3. apply modifications to record to get new record */
if (!applymodreq(hn,&mr,&sre)) {
/* 4. write record to "data.upd" */
/* 4. write record to journal */
int fd=open("journal",O_WRONLY|O_APPEND|O_CREAT,0600);
if (fd==-1)
err=operationsError;
@@ -1665,8 +1729,10 @@ authfailure:
#endif
}
}
} else
} else {
buffer_putsflush(buffer_2,"could not parse modifyRequest!\n");
err=protocolError;
}
{
char outbuf[1024];
@@ -1681,7 +1747,7 @@ authfailure:
}
break;
case AbandonRequest:
buffer_putsflush(buffer_2,"AbandonRequest!\n");
if (verbose) buffer_putsflush(buffer_2,"AbandonRequest!\n");
/* do nothing */
break;
case AddRequest:
@@ -1689,11 +1755,12 @@ authfailure:
int err=success;
struct AddRequest ar;
// buffer_putsflush(buffer_2,"AddRequest!\n");
if ((tmp=scan_ldapaddrequest(buf+res,buf+res+len,&ar))) {
if ((tmp=scan_ldapaddrequest(buf+res,buf+len,&ar))) {
struct SearchResultEntry sre;
normalize_string_dn(&ar.entry);
/* 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 if there already is a record with this dn */
@@ -1706,7 +1773,7 @@ authfailure:
default: err=operationsError;
}
if (err==success) {
/* 3. write record to "data.upd" */
/* 3. write record to journal */
int fd=open("journal",O_WRONLY|O_APPEND|O_CREAT,0600);
if (fd==-1)
err=operationsError;
@@ -1740,14 +1807,70 @@ authfailure:
{
char outbuf[1024];
int s=100;
int len=fmt_ldapresult(outbuf+s,err,"","","");
int hlen=fmt_ldapmessage(0,messageid,AddResponse,len);
size_t s=100;
size_t len=fmt_ldapresult(outbuf+s,err,"","","");
size_t hlen=fmt_ldapmessage(0,messageid,AddResponse,len);
fmt_ldapmessage(outbuf+s-hlen,messageid,AddResponse,len);
write(out,outbuf+s-hlen,len+hlen);
}
}
break;
case DelRequest:
{
struct string s;
size_t l=scan_ldapdeleterequest(buf+res,buf+len,&s);
if (l>0) {
struct SearchResultEntry sre;
int err=success;
if (verbose) {
buffer_puts(buffer_2,"Delete Request for DN \"");
buffer_put(buffer_2,s.s,s.l);
buffer_putsflush(buffer_2,"\".\n");
}
normalize_string_dn(&s);
/* convert modifyrequest to searchresultentry */
sre.objectName=s;
sre.attributes=0;
if (acls) {
/* 1. check ACLs */
if (checkacl(0,0,acl_delete,&sre)!=1)
err=insufficientAccessRights;
}
if (err==success) {
/* 2. check if there already is a record with this dn */
struct hashnode* hn;
size_t idx;
switch (lookupdn(&s,&idx,&hn)) {
case -1: err=operationsError; break;
case 1: break;
case 0: err=noSuchObject; break;
default: err=operationsError;
}
if (err==success) {
/* 3. write record to journal */
int fd=open("journal",O_WRONLY|O_APPEND|O_CREAT,0600);
if (fd==-1)
err=operationsError;
else {
if (writesretofd(fd,&sre)==-1)
err=operationsError;
close(fd);
}
}
}
{
char outbuf[1024];
size_t s=100;
size_t len=fmt_ldapresult(outbuf+s,err,"","","");
size_t hlen=fmt_ldapmessage(0,messageid,DelResponse,len);
fmt_ldapmessage(outbuf+s-hlen,messageid,DelResponse,len);
write(out,outbuf+s-hlen,len+hlen);
}
}
}
break;
case ModifyDNRequest:
/* TODO */
default:
buffer_puts(buffer_2,"unknown request type ");
buffer_putulong(buffer_2,op);
@@ -1781,7 +1904,7 @@ extern int (*ldif_parse_callback)(struct ldaprec* l);
extern mstorage_t stringtable;
extern mduptab_t attributes,classes;
unsigned long hash2(const unsigned char* c) {
static unsigned long hash2(const unsigned char* c) {
unsigned long h=0;
if (*c==0) {
uint32 len=uint32_read((char*)c+1);
@@ -1798,7 +1921,7 @@ unsigned long hash2(const unsigned char* c) {
#define HASHTABSIZE 8191
unsigned char* bstrdup(unsigned char* c) {
static unsigned char* bstrdup(unsigned char* c) {
size_t len;
unsigned char* x;
if (*c)
@@ -1812,7 +1935,7 @@ unsigned char* bstrdup(unsigned char* c) {
return x;
}
unsigned char* bstrdup_attrib(unsigned char* c) {
static unsigned char* bstrdup_attrib(unsigned char* c) {
char* x=map+5*4+size_of_string_table;
size_t i,l;
if (*c)
@@ -1865,12 +1988,13 @@ static struct hashnode** dn_in_journal2(const char* dn,size_t dnlen) {
struct hashnode* root;
int parse_callback(struct ldaprec* l) {
static int parse_callback(struct ldaprec* l) {
static struct hashnode** nextinlinearlist=&root;
size_t i;
unsigned long hashval;
struct hashnode** hn;
if (l->dn==(uint32)-1) return -1;
if (l->dn==(uint32)-1)
return -1;
hashval=hash2((unsigned char*)stringtable.root+l->dn);
// printf("journal: \"%s\" -> %lu\n",stringtable.root+l->dn,hashval);
hn=hashtab+(hashval%HASHTABSIZE);
@@ -1912,11 +2036,64 @@ int parse_callback(struct ldaprec* l) {
return 0;
}
int readjournal() {
static void readjournal() {
ldif_parse_callback=parse_callback;
mduptab_init(&attributes);
mduptab_init(&classes);
return ldif_parse("journal");
if (ldif_parse("journal",0,&ss_journal)) {
buffer_putsflush(buffer_2,"Failed to parse journal!\n");
exit(1);
}
}
static void update() {
struct stat new_data,new_journal;
if (stat(datafilename,&new_data)==-1) {
/* no data file?! There is no way to salvage the situation. */
buffer_putsflush(buffer_2,"ABEND: data file suddenly gone.\n");
exit(1);
}
/* now see if the data file changed. If it did, map it anew. */
if (new_data.st_size!=ss_data.st_size ||
new_data.st_mtime!=ss_data.st_mtime ||
new_data.st_ino!=ss_data.st_ino) {
buffer_putsflush(buffer_2,"Data file changed, reloading.\n");
mmap_unmap(map,filelen);
/* If the new data file is corrupt, map_datafile calls exit.
* I don't believe in limping on. If something is broken on such a fundamental level,
* it's better to bail so that the problem does not go unnoticed and things get even
* worse. */
map_datafile(datafilename);
/* OK, now that we have the datafile reloaded, we need to clean our idea of a journal
* and reload the journal from scratch. */
mduptab_reset(&attributes);
mduptab_reset(&classes);
readjournal();
ss_data=new_data;
return;
}
/* the data file did not change. Maybe the journal did. */
if (stat("journal",&new_journal)==-1) {
/* no journal; that means:
* a) there never was one, totaly read-only data
* b) there was one, but it has now been incorporated into the main database
* in this case: delete journal data
*/
mduptab_reset(&attributes);
mduptab_reset(&classes);
return;
}
if (new_journal.st_size!=ss_journal.st_size ||
new_journal.st_mtime!=ss_journal.st_mtime ||
new_journal.st_ino!=ss_journal.st_ino) {
/* Journal changed. Since all we ever do is append, we just read the part from how
* far we got last time, which happens to be ss_journal.st_size. */
if (ldif_parse("journal",ss_journal.st_size,&ss_journal)) {
buffer_putsflush(buffer_2,"Failed to parse journal!\n");
exit(1);
}
ss_data=new_data;
}
}
static int ldap_matchfilter_hn(struct hashnode* hn,struct Filter* f) {
@@ -2010,6 +2187,7 @@ static void answerwith_hn(struct hashnode* hn,struct SearchRequest* sr,long mess
struct SearchResultEntry sre;
struct PartialAttributeList** pal=&sre.attributes;
if (!hn->n) return;
if (acls)
byte_zero(acl_ec_subjects+filters,filters);
@@ -2134,39 +2312,7 @@ int main(int argc,char* argv[]) {
signal(SIGPIPE,SIG_IGN);
map=mmap_read(argc>1?argv[1]:"data",&filelen);
if (!map) {
buffer_putsflush(buffer_2,"could not open data!\n");
return 1;
}
uint32_unpack(map,&magic);
uint32_unpack(map+4,&attribute_count);
uint32_unpack(map+2*4,&record_count);
uint32_unpack(map+3*4,&indices_offset);
uint32_unpack(map+4*4,&size_of_string_table);
record_set_length=(record_count+sizeof(unsigned long)*8-1) / (sizeof(long)*8);
/* look up "dn" and "objectClass" */
{
char* x=map+5*4+size_of_string_table;
size_t i;
dn_ofs=objectClass_ofs=userPassword_ofs=any_ofs=0;
for (i=0; i<attribute_count; ++i) {
uint32 j;
j=uint32_read(x);
if (case_equals("dn",map+j))
dn_ofs=j;
else if (case_equals("objectClass",map+j))
objectClass_ofs=j;
else if (case_equals("userPassword",map+j))
userPassword_ofs=j;
x+=4;
}
if (!dn_ofs || !objectClass_ofs) {
buffer_putsflush(buffer_2,"can't happen error: dn or objectClass not there?!\n");
return 0;
}
}
map_datafile(argc>1?argv[1]:"data");
load_acls();