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:
6
FORMAT
6
FORMAT
@@ -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.
|
||||
|
||||
6
Makefile
6
Makefile
@@ -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
201
acl.c
@@ -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
132
dumpacls.c
Normal 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;
|
||||
}
|
||||
@@ -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
1
ldap.h
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user