minor updates (acls don't work yet)
This commit is contained in:
176
acl.c
176
acl.c
@@ -23,6 +23,8 @@
|
||||
#include <errmsg.h>
|
||||
#include <fmt.h>
|
||||
#include <byte.h>
|
||||
#include <mmap.h>
|
||||
#include <case.h>
|
||||
|
||||
const char Any[]="*";
|
||||
const char Self[]="self";
|
||||
@@ -46,7 +48,8 @@ struct assertion {
|
||||
struct acl {
|
||||
struct assertion login,target;
|
||||
const char* attrib;
|
||||
short may,maynot;
|
||||
uint32 anum;
|
||||
unsigned short may,maynot;
|
||||
struct acl* next;
|
||||
};
|
||||
|
||||
@@ -72,7 +75,7 @@ int skipws(buffer* in) {
|
||||
for (;;) {
|
||||
int r=buffer_getc(in,&c);
|
||||
if (r!=1) return r;
|
||||
if (c=='\n') break;
|
||||
if (c=='\n') { ++lines; break; }
|
||||
}
|
||||
} else return 1;
|
||||
}
|
||||
@@ -90,7 +93,11 @@ int parseacldn(buffer* in,struct assertion* a) {
|
||||
do {
|
||||
r=buffer_get_token_sa(in,&x," \t",2);
|
||||
if (r!=1) return r;
|
||||
} while (!x.len || x.s[x.len-1]!='\\');
|
||||
if (x.len>0 && x.s[x.len-1]=='\\') {
|
||||
x.s[--x.len]=' ';
|
||||
continue;
|
||||
}
|
||||
} while (x.len==0);
|
||||
stralloc_chop(&x);
|
||||
if (!stralloc_0(&x)) return -1;
|
||||
r=byte_chr(x.s,x.len,':');
|
||||
@@ -129,6 +136,16 @@ int parseaclattrib(buffer* in,struct acl* a) {
|
||||
int r;
|
||||
a->attrib=0;
|
||||
if ((r=skipws(in))!=1) return r;
|
||||
|
||||
if (in->p < in->n && buffer_feed(in)<1) return 0;
|
||||
{
|
||||
char c=*buffer_peek(in);
|
||||
if (c=='+' || c=='-') {
|
||||
a->attrib=Any;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
r=buffer_get_new_token_sa(in,&x," \t",2);
|
||||
if (r!=1) return r;
|
||||
stralloc_chop(&x);
|
||||
@@ -143,7 +160,7 @@ int parseaclattrib(buffer* in,struct acl* a) {
|
||||
int parseaclpermissions(buffer* in,struct acl* a) {
|
||||
char c;
|
||||
int r;
|
||||
short* s;
|
||||
unsigned short* s;
|
||||
a->may=a->maynot=0; s=&a->may;
|
||||
for (;;) {
|
||||
r=buffer_getc(in,&c);
|
||||
@@ -168,7 +185,10 @@ static int parseacl(buffer* in,struct acl* a) {
|
||||
char c;
|
||||
if ((r=skipws(in))!=1) return r;
|
||||
for (i=0; i<3; ++i)
|
||||
if (buffer_getc(in,&c)!=1 && c!="acl"[i]) parseerror();
|
||||
if ((r=buffer_getc(in,&c))!=1 && c!="acl"[i]) {
|
||||
if (r==0 && i==0) return 0;
|
||||
parseerror();
|
||||
}
|
||||
if ((r=parseacldn(in,&a->login))!=1) return r;
|
||||
if ((r=parseacldn(in,&a->target))!=1) return r;
|
||||
if ((r=parseaclattrib(in,a))!=1) return r;
|
||||
@@ -197,14 +217,14 @@ static void optimize(struct acl* a) {
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
static struct acl* root;
|
||||
|
||||
int readacls(const char* filename) {
|
||||
buffer b;
|
||||
struct acl* root,**next, a;
|
||||
struct acl **next, a;
|
||||
int r;
|
||||
root=0; next=&root;
|
||||
|
||||
if (buffer_mmapread(&b,"acls")==-1) diesys(1,"buffer_mmapread");
|
||||
|
||||
if (buffer_mmapread(&b,filename)==-1) return -1;
|
||||
while ((r=parseacl(&b,&a))!=-1) {
|
||||
*next=malloc(sizeof(struct acl));
|
||||
if (!*next) diesys(1,"malloc");
|
||||
@@ -216,5 +236,141 @@ int main() {
|
||||
|
||||
buffer_close(&b);
|
||||
optimize(root);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* given a DN a (logged in as DN b), we need to quickly find out what
|
||||
* kind of permissions we have for an attribute c. To make this extra
|
||||
* quick, I'm only comparing DNs if the rule
|
||||
* a) grants or denies the permission I'm interested in (bit test)
|
||||
* b) actually says something about the attribute I'm interested in.
|
||||
* To make b) cheap, I'll not actually compare attribute strings, but
|
||||
* I'll compare the offset of the attribute name in the mmapped file.
|
||||
* The * attribute is represented as 0. An attribute that is not found
|
||||
* in the mmapped file is represented as -1. */
|
||||
|
||||
static uint32 acl_map(char* map,char* x,const char* s,unsigned int attribute_count) {
|
||||
unsigned int i;
|
||||
for (i=0; i<attribute_count; ++i) {
|
||||
uint32 j=uint32_read(x+i*4);
|
||||
if (case_equals(s,map+j))
|
||||
return j;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void acl_offsets(char* map,unsigned long maplen) {
|
||||
uint32 attribute_count=uint32_read(map+4);
|
||||
uint32 size_of_string_table=uint32_read(map+4*4);
|
||||
uint32 dn_ofs,oc_ofs;
|
||||
char* x=map+5*4+size_of_string_table;
|
||||
unsigned int i;
|
||||
struct acl* a;
|
||||
|
||||
dn_ofs=oc_ofs=0;
|
||||
for (i=0; i<attribute_count; ++i) {
|
||||
uint32 j=uint32_read(x+i*4);
|
||||
if (j>maplen-2) { carp("invalid offset in attribute table"); return; } /* can't happen */
|
||||
if (case_equals(map+j,"dn"))
|
||||
dn_ofs=j;
|
||||
else if (case_equals(map+j,"objectClass"))
|
||||
oc_ofs=j;
|
||||
}
|
||||
|
||||
for (a=root; a; a=a->next) {
|
||||
a->anum=(uint32)-1;
|
||||
if (a->attrib==Any)
|
||||
a->anum=0;
|
||||
else
|
||||
a->anum=acl_map(map,maplen,x,a->attrib,attribute_count);
|
||||
|
||||
if (a->login.attr==Dn) a->login.where=dn_ofs;
|
||||
else if (case_equals(a->login.attr,"objectClass")) a->login.where=oc_ofs;
|
||||
else a->login.where=acl_map(map,x,a->login.attr,attribute_count);
|
||||
|
||||
if (a->target.attr==Dn) a->target.where=dn_ofs;
|
||||
else if (case_equals(a->target.attr,"objectClass")) a->target.where=oc_ofs;
|
||||
else a->target.where=acl_map(map,x,a->target.attr,attribute_count);
|
||||
|
||||
#if 0
|
||||
if (a->anum==-1)
|
||||
printf("no offset found for %s\n",a->attrib);
|
||||
if (a->login.where==-1)
|
||||
printf("no offset found for %s\n",a->login.attr);
|
||||
if (a->target.where==-1)
|
||||
printf("no offset found for %s\n",a->target.attr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
extern uint32 dn_ofs,objectClass_ofs;
|
||||
|
||||
int acl_allowed(char* map,unsigned long maplen,const char* logindn,const char* targetdn,uint32 attr,unsigned short wanted) {
|
||||
struct acl* a;
|
||||
struct assertion* l;
|
||||
for (a=root; a; a=a->next) {
|
||||
if (((a->may|a->maynot)&wanted) && /* acl applies to action we want to do */
|
||||
(!a->anum || a->anum==attr)) { /* acl applies to this attribute */
|
||||
|
||||
l=&a->login; if (l->sameas) l=l->sameas;
|
||||
|
||||
/* first, see if logindn matches */
|
||||
if (logindn==0) {
|
||||
/* special case: anonymous bind.
|
||||
* Do not match if login assertion is not "Any" */
|
||||
if (l->attr != Any) continue;
|
||||
} else if (logindn>=map && logindn<=map+maplen) {
|
||||
uint32 n=uint32_read(logindn);
|
||||
uint32 v=0;
|
||||
if (l->attr != Any) {
|
||||
v=ldap_find_attr_value(logindn,l->where);
|
||||
if (v==0) continue; /* attribute not there, no match */
|
||||
if (l->what != Any) {
|
||||
if (l->what[0]=='*') {
|
||||
/* suffix match */
|
||||
} else if (l->what[strlen(l->what)-1]=='*') {
|
||||
/* prefix match */
|
||||
} else {
|
||||
/* direct match */
|
||||
/* TODO XXX FIXME */
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
die(1,"unhandled case: logindn outside map");
|
||||
}
|
||||
|
||||
#if 0
|
||||
struct assertion {
|
||||
const char* attr;
|
||||
uint32 where;
|
||||
const char* what;
|
||||
struct assertion* sameas;
|
||||
};
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
void dumpacls() {
|
||||
struct acl* a;
|
||||
for (a=root; a; a=a->next) {
|
||||
printf("\n--=[ record at %p ]=--\n",a);
|
||||
printf("%s=%s %s=%s %s\n",a->login.attr,a->login.what,a->target.attr,a->target.what,a->attrib);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MAIN
|
||||
int main() {
|
||||
unsigned long filelen;
|
||||
char* map=mmap_read("data",&filelen);
|
||||
|
||||
if (readacls("acls")==-1) die(1,"readacls failed");
|
||||
// dumpacls();
|
||||
acl_offsets(map,filelen);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
6
acls
6
acls
@@ -1,8 +1,8 @@
|
||||
# root@fefe.de can do everything
|
||||
acl dn:cn=root,o=fefe,c=de * +rwdR;
|
||||
acl dn:cn=root,o=fefe,c=de * * +rwdR;
|
||||
# noone can read userPassword
|
||||
acl * * userPassword -r;
|
||||
# but everyone can authenticate using it
|
||||
acl * self +a;
|
||||
acl * self * +a;
|
||||
# admins at fefe.de can write in their tree
|
||||
acl dn:*ou=admin,o=fefe,c=de dn:*,o=fefe,c=de +rwdR;
|
||||
acl dn:*ou=admin,o=fefe,c=de dn:*,o=fefe,c=de * +rwdR;
|
||||
|
||||
@@ -66,6 +66,17 @@ uint32 ldap_find_attr_value(uint32 ofs,uint32 attrofs) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int matchint(struct Filter* f,const char* t) {
|
||||
int r;
|
||||
if (f->attrflag&1)
|
||||
r=matchcasestring(&f->ava.value,t);
|
||||
else
|
||||
r=matchstring(&f->ava.value,t);
|
||||
if (f->type==EQUAL) return (r!=0);
|
||||
if (f->type==LESSEQUAL) return (r>0);
|
||||
return (r<0);
|
||||
}
|
||||
|
||||
/* return non-zero if the record matches the search filter */
|
||||
int ldap_matchfilter_mapped(uint32 ofs,struct Filter* f) {
|
||||
struct Filter* y=f->x;
|
||||
@@ -88,36 +99,26 @@ int ldap_matchfilter_mapped(uint32 ofs,struct Filter* f) {
|
||||
case PRESENT:
|
||||
return ldap_match_present(ofs,f->attrofs);
|
||||
case EQUAL:
|
||||
case LESSEQUAL:
|
||||
case GREATEQUAL:
|
||||
{
|
||||
uint32 i,j,k;
|
||||
uint32_unpack(map+ofs,&j);
|
||||
// if (!matchstring(&f->ava.desc,"dn")) {
|
||||
if (f->attrofs==dn_ofs) {
|
||||
uint32_unpack(map+ofs+8,&k);
|
||||
if (f->attrflag&1) {
|
||||
if (!matchcasestring(&f->ava.value,map+k)) return 1;
|
||||
} else {
|
||||
if (!matchstring(&f->ava.value,map+k)) return 1;
|
||||
}
|
||||
return matchint(f,map+k);
|
||||
// } else if (!matchstring(&f->ava.desc,"objectName")) {
|
||||
} else if (f->attrofs==objectClass_ofs) {
|
||||
uint32_unpack(map+ofs+12,&k);
|
||||
if (f->attrflag&1) {
|
||||
if (!matchcasestring(&f->ava.value,map+k)) return 1;
|
||||
} else {
|
||||
if (!matchstring(&f->ava.value,map+k)) return 1;
|
||||
}
|
||||
if (matchint(f,map+k)) return 1;
|
||||
}
|
||||
for (i=2; i<j; ++i) {
|
||||
uint32_unpack(map+ofs+i*8,&k);
|
||||
// if (!matchstring(&f->ava.desc,map+k)) {
|
||||
if (f->attrofs==k) {
|
||||
uint32_unpack(map+ofs+i*8+4,&k);
|
||||
if (f->attrflag&1) {
|
||||
if (!matchcasestring(&f->ava.value,map+k)) return 1;
|
||||
} else {
|
||||
if (!matchstring(&f->ava.value,map+k)) return 1;
|
||||
}
|
||||
if (matchint(f,map+k)) return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@@ -131,6 +132,7 @@ int ldap_matchfilter_mapped(uint32 ofs,struct Filter* f) {
|
||||
if (f->attrofs==dn_ofs) {
|
||||
uint32_unpack(map+ofs+8,&k);
|
||||
if (substringmatch(f->substrings,map+k,f->attrflag&1)) return 1;
|
||||
return 0;
|
||||
// } else if (matchstring(&f->ava.desc,"objectName")) {
|
||||
} else if (f->attrofs==objectClass_ofs) {
|
||||
uint32_unpack(map+ofs+12,&k);
|
||||
|
||||
4
parse.c
4
parse.c
@@ -13,6 +13,7 @@
|
||||
#include "uint32.h"
|
||||
#include "byte.h"
|
||||
#include "fmt.h"
|
||||
#include "errmsg.h"
|
||||
|
||||
/* these are defined in ldif_parse.c.
|
||||
* We extern them here so we can initialize them.
|
||||
@@ -189,6 +190,9 @@ derrout2:
|
||||
mstorage_add(&stringtable,dummy,5*4);
|
||||
}
|
||||
|
||||
// if ((mduptab_adds(&attributes,"*"))<0)
|
||||
// die(1,"out of memory");
|
||||
|
||||
ldif_parse(argc<2?"exp.ldif":argv[1]);
|
||||
if (!first) {
|
||||
buffer_putsflush(buffer_2,"usage: parse [src-ldif-filename] [dest-bin-filename]\n");
|
||||
|
||||
@@ -40,7 +40,7 @@ uint32 magic,attribute_count,record_count,indices_offset,size_of_string_table;
|
||||
uint32 record_set_length;
|
||||
|
||||
/* some pre-looked-up attribute offsets to speed up ldap_match_mapped */
|
||||
uint32 dn_ofs,objectClass_ofs,userPassword_ofs;
|
||||
uint32 dn_ofs,objectClass_ofs,userPassword_ofs,any_ofs;
|
||||
|
||||
#define BUFSIZE 8192
|
||||
|
||||
@@ -879,16 +879,18 @@ int main() {
|
||||
{
|
||||
char* x=map+5*4+size_of_string_table;
|
||||
unsigned int i;
|
||||
dn_ofs=objectClass_ofs=userPassword_ofs=0;
|
||||
dn_ofs=objectClass_ofs=userPassword_ofs=any_ofs=0;
|
||||
for (i=0; i<attribute_count; ++i) {
|
||||
uint32 j;
|
||||
j=uint32_read(x);
|
||||
if (!strcmp("dn",map+j))
|
||||
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;
|
||||
else if (case_equals("*",map+j))
|
||||
any_ofs=j;
|
||||
x+=4;
|
||||
}
|
||||
if (!dn_ofs || !objectClass_ofs) {
|
||||
|
||||
Reference in New Issue
Block a user