ACL parsing appears to work, and a new test program called dumpacl can

dump them back out.  Now we just need to check them when executing ldap
requests.  *cough*
This commit is contained in:
leitner
2005-07-15 23:04:23 +00:00
parent 9c31097db5
commit 783126698f
6 changed files with 307 additions and 42 deletions

6
FORMAT
View File

@@ -37,11 +37,17 @@ All integers are stored LITTLE ENDIAN.
faster but twice as large; this is actually saved
as two arrays, one for the pointers and one for
the numbers, for cache performance reasons.
2 == ACL data
rest reserved */
uint32_t next; /* offset of next index */
/* for index_type==0: */
uint32_t indexed_attribute; /* offset of attribute name */
uint32_t record_offsets[record_count];
/* for index_type==1: */
uint32_t indexed_attribute;
uint32_t record_offsets[record_count];
uint32_t record_number[record_count];
/* for index_type==2 see file "ACL" */
}
The indices are at the end to make it possible to add more indices.

View File

@@ -2,7 +2,7 @@ DEBUG=1
all: t1 t2 parse dumpidx idx2ldif addindex bindrequest tinyldap \
tinyldap_standalone tinyldap_debug ldapclient ldapclient_str \
md5password mysql2ldif acl # t6 # t
md5password mysql2ldif acl dumpacls # 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 \
@@ -21,7 +21,8 @@ fmt_ldapsearchfilter.o fmt_ldapsearchrequest.o matchstring.o \
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
scan_ldapsearchfilterstring.o free_ldapsearchresultentry.o \
fmt_ldapsearchfilterstring.o
ldif.a: ldif_parse.o ldap_match_mapped.o
@@ -61,6 +62,7 @@ t6: storage.a
tinyldap tinyldap_standalone tinyldap_debug: ldif.a auth.a
bindrequest tinyldap tinyldap_standalone tinyldap_debug ldapclient ldapclient_str: ldap.a asn1.a
idx2ldif: ldap.a
dumpacls: ldap.a asn1.a
tinyldap_standalone: tinyldap.c
$(DIET) $(CC) $(CFLAGS) -DSTANDALONE -o $@ $^ $(LDFLAGS) -lowfat $(LIBS)

201
acl.c
View File

@@ -1,3 +1,4 @@
#define _FILE_OFFSET_BITS 64
#define MAIN
#include <buffer.h>
@@ -11,11 +12,15 @@
#include <mmap.h>
#include <case.h>
#include <ldap.h>
#include <uint16.h>
#include <uint32.h>
#include <open.h>
#include <unistd.h>
const char Any[]="*";
const char Self[]="self";
const char Dn[]="dn";
uint32 any_ofs;
enum {
acl_read = 1,
@@ -28,6 +33,7 @@ enum {
struct assertion {
const char* filterstring;
struct Filter* f;
uint32 idx;
struct assertion* sameas;
};
@@ -128,7 +134,7 @@ int parseaclattrib(buffer* in,struct acl* a) {
{
char c=*buffer_peek(in);
if (c=='+' || c=='-') {
a->attrib=Any;
a->attrib=(char*)Any;
a->anum=1;
return 1;
}
@@ -139,7 +145,7 @@ int parseaclattrib(buffer* in,struct acl* a) {
stralloc_chop(&x);
if (!stralloc_0(&x)) return -1;
if (str_equal(x.s,"*")) {
a->attrib=Any;
a->attrib=(char*)Any;
a->anum=1;
return 1;
}
@@ -195,6 +201,7 @@ static int parseacl(buffer* in,struct acl* a) {
}
static void fold(struct assertion* a,struct assertion* b) {
if (a==b) return;
if (a->sameas || b->sameas) return;
if (!strcmp(a->filterstring,b->filterstring))
b->sameas=a;
@@ -221,7 +228,7 @@ int readacls(const char* filename) {
int r;
root=0; next=&root;
if (buffer_mmapread(&b,filename)==-1) return -1;
while ((r=parseacl(&b,&a))!=-1) {
while ((r=parseacl(&b,&a))==1) {
*next=malloc(sizeof(struct acl));
if (!*next) diesys(1,"malloc");
**next=a;
@@ -251,21 +258,39 @@ int marshalfilter(stralloc* x,struct assertion* a) {
}
}
int marshal(char* map,unsigned long filelen) {
int marshal(char* map,unsigned long filelen,const char* filename) {
unsigned long filters,acls,i,j,k;
unsigned long filter_offset,acl_offset;
struct acl* a;
uint32* F,* A;
uint32 attribute_count;
uint32 attrtab;
static stralloc x;
static stralloc x,y;
int fd=open_append(filename);
if (fd==-1)
diesys(1,"could not open file `",filename,"' for writing");
stralloc_copys(&x,"");
stralloc_copys(&y,"");
filters=acls=0;
for (a=root; a; a=a->next) {
++acls;
if (!a->subject.sameas) ++filters;
if (!a->object.sameas) ++filters;
if (!a->subject.sameas) {
a->subject.idx=filters;
++filters;
}
if (!a->object.sameas) {
a->object.idx=filters;
++filters;
}
}
buffer_putulong(buffer_1,acls);
buffer_puts(buffer_1," ACLs with ");
buffer_putulong(buffer_1,filters);
buffer_putsflush(buffer_1," filters.\n");
F=malloc(sizeof(*F)*(filters+1));
filter_offset=filelen+(filters+4)*sizeof(*F); /* 2 uints for index header, 1 uint filters_count, then filter_count+1 uint32 in F */
@@ -297,38 +322,49 @@ nomem:
* the ACLs. To make it possible to skip over it, the offset table of
* the filters has one more element, which points to the start of the
* ACLs. */
for (a=root; a; a=a->next) {
unsigned int l=0;
if (!(a->attrs=malloc(a->anum*sizeof(*a->attrs))))
goto nomem;
a->attrs[l]=a->attrib; ++l;
for (k=0; a->attrib[k]; ++k)
if (a->attrib[k]==',') {
a->attrib[k]=0;
a->attrs[l]=a->attrib+k+1;
}
if (a->attrib!=Self && a->attrib!=Any)
for (k=0; k<a->anum; ++k) {
int found=0;
for (j=0; j<attribute_count; ++j) {
if (!strcmp(map+uint32_read(map+attrtab+j*4),a->attrs[k])) {
a->attrs[k]=map+uint32_read(map+attrtab+j*4);
found=1;
break;
{
int anyused=0;
for (a=root; a; a=a->next) {
unsigned int l=0;
if (!(a->attrs=malloc(a->anum*sizeof(*a->attrs))))
goto nomem;
a->attrs[l]=a->attrib; ++l;
if (a->attrib!=Any) {
for (k=0; a->attrib[k]; ++k)
if (a->attrib[k]==',') {
a->attrib[k]=0;
a->attrs[l]=a->attrib+k+1;
}
for (k=0; k<a->anum; ++k) {
int found=0;
for (j=0; j<attribute_count; ++j) {
if (!strcmp(map+uint32_read(map+attrtab+j*4),a->attrs[k])) {
a->attrs[k]=map+uint32_read(map+attrtab+j*4);
found=1;
break;
}
}
if (!found) {
/* warning: evil kludge ahead! We assume that the sum of the
* lengths of the new attributes plus the ACLs is smaller than
* the address where mmap mapped the file. */
char* tmp=a->attrs[k];
// buffer_putmflush(buffer_1,"adding attribute ",a->attrs[k],"\n");
a->attrs[k]=map+filelen+
2*4+ /* index_type and next */
(filters+2)*4+ /* filters_count plus (filter_count+1)*uint32 */
x.len;
if (!stralloc_catb(&x,tmp,strlen(tmp)+1)) goto nomem;
}
}
if (!found) {
/* warning: evil kludge ahead! We assume that the sum of the
* lengths of the new attributes plus the ACLs is smaller than
* the address where mmap mapped the file. */
char* tmp=a->attrs[k];
a->attrs[k]=map+filelen+
2*4+ /* index_type and next */
(filters+2)*4+ /* filters_count plus (filter_count+1)+uint32 */
x.len;
if (!stralloc_cats(&x,tmp)) goto nomem;
}
}
} else anyused=1;
}
if (anyused) {
any_ofs=filelen+2*4+(filters+2)*4+x.len;
// printf("filelen is %d, filters is %d, x.len is %d -> anyofs is %d\n",filelen,filters,x.len,any_ofs);
if (!stralloc_catb(&x,Any,2)) goto nomem;
}
}
/* 32-bit align */
@@ -344,13 +380,98 @@ nomem:
if (!A) goto nomem;
acl_offset=F[i]+(acls+1)*sizeof(*A);
/* FIXME, TODO */
i=0;
for (a=root; a; a=a->next) {
char tmp[4];
unsigned int j;
A[i]=y.len; ++i;
if (!stralloc_readyplus(&y,12)) goto nomem;
if (a->subject.sameas)
uint32_pack(tmp,a->subject.sameas->idx);
else
uint32_pack(tmp,a->subject.idx);
stralloc_catb(&y,tmp,4);
if (a->object.sameas)
uint32_pack(tmp,a->object.sameas->idx);
else
uint32_pack(tmp,a->object.idx);
stralloc_catb(&y,tmp,4);
uint16_pack(tmp,a->may);
stralloc_catb(&y,tmp,2);
uint16_pack(tmp,a->maynot);
stralloc_catb(&y,tmp,2);
if (a->attrib==Any) {
uint32_pack(tmp,any_ofs);
if (!stralloc_catb(&y,tmp,4)) goto nomem;
} else {
for (j=0; j<a->anum; ++j) {
if (a->attrs[j]==Any)
buffer_putmflush(buffer_1,a->attrs[j],"\n");
uint32_pack(tmp,a->attrs[j]-map);
if (!stralloc_catb(&y,tmp,4)) goto nomem;
}
}
uint32_pack(tmp,0);
if (!stralloc_catb(&y,tmp,4)) goto nomem;
}
/* 32-bit align */
{
unsigned int align=(-(y.len&3))&3;
if (!stralloc_catb(&y,"\0\0\0",align)) goto nomem;
}
{
char tmp[8];
unsigned long i;
uint32 fixup;
/* write index header:
* uint32 index_type (2 in this case);
* uint32 offset_of_next_header; */
uint32_pack(tmp,2);
uint32_pack(tmp+4,filelen+
8+ /* index header */
4+ /* uint32 filters_count; */
4*(filters+1)+ /* uint32 offsets_to_filters_in_scan_ldapsearchfilter_format[filter_count+1]; */
x.len+ /* marshalled filters */
4+ /* uint32 acl_count */
4*acls+ /* uint32 offsets_to_acls[acl_count]; */
y.len); /* marshalled acls */
if (write(fd,tmp,8)!=8) {
shortwrite:
ftruncate(fd,filelen);
close(fd);
diesys(1,"short write");
}
/* uint32 filter_count */
uint32_pack(tmp,filters);
if (write(fd,tmp,4)!=4) goto shortwrite;
/* uint32 offsets_to_filters_in_scan_ldapsearchfilter_format[filter_count+1]; */
for (i=0; i<filters+1; ++i)
uint32_pack(F+i,F[i]);
if (write(fd,F,(filters+1)*4) != (ssize_t)((filters+1)*4)) goto shortwrite;
/* write marshalled filter data */
if (write(fd,x.s,x.len) != (ssize_t)x.len) goto shortwrite;
/* uint32 acl_count */
uint32_pack(tmp,acls);
if (write(fd,tmp,4)!=4) goto shortwrite;
/* uint32 offsets_to_acls[acl_count] */
fixup=lseek(fd,0,SEEK_CUR)+acls*4;
for (i=0; i<acls; ++i)
uint32_pack(A+i,A[i]+fixup);
if (write(fd,A,acls*4) != (ssize_t)(acls*4)) goto shortwrite;
/* write marshalled acl data */
if (write(fd,y.s,y.len) != (ssize_t)y.len) goto shortwrite;
}
close(fd);
return 0;
}
#ifdef MAIN
int main(int argc,char* argv[]) {
unsigned long filelen;
char* map=mmap_read(argc>1?argv[1]:"data",&filelen);
char* filename=argc>1?argv[1]:"data";
char* map=mmap_read(filename,&filelen);
if (filelen<5*4 || uint32_read(map)!=0xfefe1da9) {
buffer_putmflush(buffer_2,"not a valid tinyldap data file!\n");
@@ -360,7 +481,7 @@ int main(int argc,char* argv[]) {
if (readacls("acls")==-1) die(1,"readacls failed");
// acl_offsets(map,filelen);
marshal(map,filelen);
marshal(map,filelen,filename);
return 0;
}
#endif

132
dumpacls.c Normal file
View File

@@ -0,0 +1,132 @@
#include <stdlib.h>
#include <assert.h>
#include "buffer.h"
#include "mmap.h"
#include "uint16.h"
#include "uint32.h"
#include "ldap.h"
#include "byte.h"
int main(int argc,char* argv[]) {
int verbose=0;
unsigned long filelen;
char* fn=argc<2?"data":argv[1];
char* map=mmap_read(fn,&filelen);
uint32 magic,attribute_count,record_count,indices_offset,size_of_string_table,acl_ofs;
if (!map) {
buffer_puts(buffer_2,"could not open `");
buffer_puts(buffer_2,fn);
buffer_puts(buffer_2,"´: ");
buffer_puterror(buffer_2);
buffer_putnlflush(buffer_2);
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);
{
uint32 ofs,next;
acl_ofs=0;
for (ofs=indices_offset+record_count*4; ofs<(unsigned long)filelen;) {
uint32 index_type,next,indexed_attribute;
uint32_unpack(map+ofs,&index_type);
uint32_unpack(map+ofs+4,&next);
if (index_type==2) { acl_ofs=ofs; break; }
if (next<ofs || next>filelen) {
kaputt:
buffer_putsflush(buffer_1,"broken file!\n");
return 1;
}
ofs=next;
}
if (acl_ofs) {
uint32 i,filters,acls,filtertab,acltab;
ofs=acl_ofs+8;
buffer_putulong(buffer_1,filters=uint32_read(map+ofs));
buffer_puts(buffer_1," Filters:\n\n");
filtertab=ofs+4;
ofs=filtertab+filters*4;
if (ofs<filtertab) goto kaputt;
for (i=0; i<filters; ++i) {
struct Filter* f;
ofs=uint32_read(map+filtertab+i*4);
if (ofs<filtertab || ofs>filelen) goto kaputt;
buffer_putulong(buffer_1,i);
buffer_puts(buffer_1,": ");
if (byte_equal(map+ofs,4,"self"))
buffer_puts(buffer_1,"self");
else if (byte_equal(map+ofs,3,"any"))
buffer_puts(buffer_1,"any");
else if (scan_ldapsearchfilter(map+ofs,map+filelen,&f)!=0) {
unsigned long l=fmt_ldapsearchfilterstring(0,f);
unsigned long l2;
char* buf=malloc(l+23);
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);
}
buffer_putsflush(buffer_1,"\n");
}
ofs=uint32_read(map+filtertab+filters*4);
if (ofs<filtertab || ofs>filelen-4) goto kaputt;
acls=uint32_read(map+ofs);
buffer_puts(buffer_1,"\n\n");
buffer_putulong(buffer_1,acls);
buffer_putsflush(buffer_1," ACLs:\n\n");
acltab=ofs+4;
for (i=0; i<acls; ++i) {
uint16 may,maynot;
ofs=uint32_read(map+acltab+i*4);
if (ofs>filelen-16) goto kaputt;
buffer_putlong(buffer_1,i);
buffer_puts(buffer_1,": acl [");
buffer_putulong(buffer_1,uint32_read(map+ofs));
buffer_puts(buffer_1,"] [");
buffer_putulong(buffer_1,uint32_read(map+ofs+4));
buffer_puts(buffer_1,"] ");
may=uint16_read(map+ofs+8);
maynot=uint16_read(map+ofs+10);
for (ofs+=12; ofs<filelen; ofs+=4) {
uint32 j=uint32_read(map+ofs);
if (j>ofs) goto kaputt;
if (!j) break;
buffer_puts(buffer_1,map+j);
buffer_puts(buffer_1,uint32_read(map+ofs+4)?",":" ");
}
if (may) {
buffer_puts(buffer_1,"+");
if (may&1) buffer_puts(buffer_1,"r");
if (may&2) buffer_puts(buffer_1,"w");
if (may&4) buffer_puts(buffer_1,"a");
if (may&8) buffer_puts(buffer_1,"d");
if (may&16) buffer_puts(buffer_1,"R");
}
if (maynot) {
buffer_puts(buffer_1,"-");
if (maynot&1) buffer_puts(buffer_1,"r");
if (maynot&2) buffer_puts(buffer_1,"w");
if (maynot&4) buffer_puts(buffer_1,"a");
if (maynot&8) buffer_puts(buffer_1,"d");
if (maynot&16) buffer_puts(buffer_1,"R");
}
buffer_putsflush(buffer_1,"\n");
}
}
}
buffer_flush(buffer_1);
return 0;
}

View File

@@ -98,6 +98,9 @@ int main(int argc,char* argv[]) {
case 1:
buffer_puts(buffer_1,"sorted table with record pointer");
break;
case 2:
buffer_puts(buffer_1,"acl data");
break;
default:
buffer_puts(buffer_1,"unknown (");
buffer_putulong(buffer_1,index_type);

1
ldap.h
View File

@@ -143,6 +143,7 @@ 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);
#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)