1. What ACLs look like ACLs are: acl subject object attributes access; subject and object are LDAP search filter expressions. attributes is a comma separates list of attributes. access says what accesses are allowed or disallowed in a chmod-like syntax. As an abbreviation, you can use '*' to mean '(objectClass=*)' for subject or object, and you can use '*' to mean 'all attributes' in attributes. Example: acl (dn=cn=root,o=fefe,c=de) (objectClass=*) * +rwdR r read w write a add d delete R rename DN The default is: Anonymous user can read all, write none. The first useful ACL is therefore: acl * * userPassword -r; Authenticating against a DN is always allowed. The above ACL prohibits getting the (hopefully encrypted) userPassword field content via LDAP. 2. How they are evaluated ACLs are matched in the order they are given. The first matching ACL wins. 3. How to apply them Put the ACLs in a text file, for example "acls". Use parse to convert your ldif into a "data" file, then use addindex to add indices as usual, then run acl on the new data file. For example, here is a Makefile example: data: ldif $(TINYLDAP)/parse ldif data.new $(TINYLDAP)/addindex data.new dn hu $(TINYLDAP)/addindex data.new danke if $(TINYLDAP)/addindex data.new ts f $(TINYLDAP)/acl data.new chmod a+r data.new mv -f data.new data Note how the new data file is only moved over the old one after all other operations went through without errors. 4. Where is the code? The code to read ACLs in text format, parse them, and put them into the binary form understood by tinyldap is in acl.c. The code that applies the ACLs in tinyldap is in the function called "checkacls" in tinyldap.c. 5. Implementation notes ACL filters share the syntax of search filters. However, because the ACL syntax is limited we expect filters to be used more than ones. That's why acl.c will deduplicate filters and tinyldap will make sure to only match a filter once, even if it is referenced in multiple ACLs. The on disk format looks like this: first the filters: uint32 filters_count; uint32 offsets_to_filters_in_scan_ldapsearchfilter_format[filter_count+1]; // the last pointer points after the marshalled filters then each filter marshalled as readable by scan_ldapsearchfilter (or "self"): [...] then the ACLs: uint32 acl_count; uint32 offsets_to_acls[acl_count]; then for each acl: uint32 subject_filter, object_filter; // index in above filters array uint16 may,maynot; // bit fields for +rw-d uint32 attributes[]; // 0 terminated