Skip to content
Snippets Groups Projects
access-control.sdf 52.8 KiB
Newer Older
  • Learn to ignore specific revisions
  • Quanah Gibson-Mount's avatar
    Quanah Gibson-Mount committed
    # Copyright 1999-2021 The OpenLDAP Foundation, All Rights Reserved.
    
    # COPYING RESTRICTIONS APPLY, see COPYRIGHT.
    
    H1: Access Control
    
    
    Howard Chu's avatar
    Howard Chu committed
    As the directory gets populated with more and more data of varying sensitivity,
    
    controlling the kinds of access granted to the directory becomes more and more
    
    Howard Chu's avatar
    Howard Chu committed
    critical. For instance, the directory may contain data of a confidential nature
    that you may need to protect by contract or by law. Or, if using the directory
    to control access to other services, inappropriate access to the directory may
    create avenues of attack to your sites security that result in devastating
    
    Access to your directory can be configured via two methods, the first using
    
    Howard Chu's avatar
    Howard Chu committed
    {{SECT:The slapd Configuration File}} and the second using the {{slapd-config}}(5)
    
    Howard Chu's avatar
    Howard Chu committed
    The default access control policy is allow read by all clients. Regardless of
    what access control policy is defined, the {{rootdn}} is always allowed full
    
    rights (i.e. auth, search, compare, read and write) on everything and anything.
    
    
    Howard Chu's avatar
    Howard Chu committed
    As a consequence, it's useless (and results in a performance penalty) to explicitly
    
    list the {{rootdn}} among the {{<by>}} clauses.
    
    
    Howard Chu's avatar
    Howard Chu committed
    The following sections will describe Access Control Lists in greater depth and
    
    follow with some examples and recommendations. See {{slapd.access}}(5) for
    complete details.
    
    H2: Access Control via Static Configuration
    
    
    Access to entries and attributes is controlled by the
    access configuration file directive. The general form of an
    access line is:
    
    
    >    <access directive> ::= access to <what>
    >        [by <who> [<access>] [<control>] ]+
    >    <what> ::= * |
    >        [dn[.<basic-style>]=<regex> | dn.<scope-style>=<DN>]
    >        [filter=<ldapfilter>] [attrs=<attrlist>]
    >    <basic-style> ::= regex | exact
    >    <scope-style> ::= base | one | subtree | children
    >    <attrlist> ::= <attr> [val[.<basic-style>]=<regex>] | <attr> , <attrlist>
    >    <attr> ::= <attrname> | entry | children
    >    <who> ::= * | [anonymous | users | self
    
    Howard Chu's avatar
    Howard Chu committed
    >            | dn[.<basic-style>]=<regex> | dn.<scope-style>=<DN>]
    
    >        [dnattr=<attrname>]
    >        [group[/<objectclass>[/<attrname>][.<basic-style>]]=<regex>]
    >        [peername[.<basic-style>]=<regex>]
    >        [sockname[.<basic-style>]=<regex>]
    >        [domain[.<basic-style>]=<regex>]
    >        [sockurl[.<basic-style>]=<regex>]
    >        [set=<setspec>]
    >        [aci=<attrname>]
    >    <access> ::= [self]{<level>|<priv>}
    >    <level> ::= none | disclose | auth | compare | search | read | write | manage
    >    <priv> ::= {=|+|-}{m|w|r|s|c|x|d|0}+
    >    <control> ::= [stop | continue | break]
    
    
    where the <what> part selects the entries and/or attributes to which
    the access applies, the {{EX:<who>}} part specifies which entities
    are granted access, and the {{EX:<access>}} part specifies the
    access granted. Multiple {{EX:<who> <access> <control>}} triplets
    are supported, allowing many entities to be granted different access
    to the same set of entries and attributes. Not all of these access
    control options are described here; for more details see the
    {{slapd.access}}(5) man page.
    
    
    H3: What to control access to
    
    The <what> part of an access specification determines the entries
    and attributes to which the access control applies.  Entries are
    commonly selected in two ways: by DN and by filter.  The following
    qualifiers select entries by DN:
    
    
    >    to *
    >    to dn[.<basic-style>]=<regex>
    >    to dn.<scope-style>=<DN>
    
    
    The first form is used to select all entries.  The second form may
    be used to select entries by matching a regular expression against
    the target entry's {{normalized DN}}.   (The second form is not
    discussed further in this document.)  The third form is used to
    select entries which are within the requested scope of DN.  The
    <DN> is a string representation of the Distinguished Name, as
    described in {{REF:RFC4514}}.
    
    The scope can be either {{EX:base}}, {{EX:one}}, {{EX:subtree}},
    or {{EX:children}}.  Where {{EX:base}} matches only the entry with
    provided DN, {{EX:one}} matches the entries whose parent is the
    provided DN, {{EX:subtree}} matches all entries in the subtree whose
    root is the provided DN, and {{EX:children}} matches all entries
    under the DN (but not the entry named by the DN).
    
    For example, if the directory contained entries named:
    
    
    >    0: o=suffix
    >    1: cn=Manager,o=suffix
    >    2: ou=people,o=suffix
    >    3: uid=kdz,ou=people,o=suffix
    >    4: cn=addresses,uid=kdz,ou=people,o=suffix
    >    5: uid=hyc,ou=people,o=suffix
    
    
    \Then:
    . {{EX:dn.base="ou=people,o=suffix"}} match 2;
    . {{EX:dn.one="ou=people,o=suffix"}} match 3, and 5;
    . {{EX:dn.subtree="ou=people,o=suffix"}} match 2, 3, 4, and 5; and
    . {{EX:dn.children="ou=people,o=suffix"}} match 3, 4, and 5.
    
    
    Entries may also be selected using a filter:
    
    
    
    where <ldap filter> is a string representation of an LDAP
    search filter, as described in {{REF:RFC4515}}.  For example:
    
    
    
    Note that entries may be selected by both DN and filter by
    including both qualifiers in the <what> clause.
    
    
    >    to dn.one="ou=people,o=suffix" filter=(objectClass=person)
    
    
    Attributes within an entry are selected by including a comma-separated
    list of attribute names in the <what> selector:
    
    
    
    A specific value of an attribute is selected by using a single
    attribute name and also using a value selector:
    
    
    >    attrs=<attribute> val[.<style>]=<regex>
    
    
    There are two special {{pseudo}} attributes {{EX:entry}} and
    {{EX:children}}.  To read (and hence return) a target entry, the
    subject must have {{EX:read}} access to the target's {{entry}}
    
    attribute.  To perform a search, the subject must have
    {{EX:search}} access to the search base's {{entry}} attribute.
    To add or delete an entry, the subject must have
    
    {{EX:write}} access to the entry's {{EX:entry}} attribute AND must
    have {{EX:write}} access to the entry's parent's {{EX:children}}
    attribute.  To rename an entry, the subject must have {{EX:write}}
    access to entry's {{EX:entry}} attribute AND have {{EX:write}}
    access to both the old parent's and new parent's {{EX:children}}
    attributes.  The complete examples at the end of this section should
    help clear things up.
    
    Lastly, there is a special entry selector {{EX:"*"}} that is used to
    select any entry.  It is used when no other {{EX:<what>}}
    selector has been provided.  It's equivalent to "{{EX:dn=.*}}"
    
    
    H3: Who to grant access to
    
    The <who> part identifies the entity or entities being granted
    access. Note that access is granted to "entities" not "entries."
    The following table summarizes entity specifiers:
    
    !block table; align=Center; coltags="EX,N"; \
    
        title="Table 6.3: Access Entity Specifiers"
    
    Specifier|Entities
    *|All, including anonymous and authenticated users
    anonymous|Anonymous (non-authenticated) users
    users|Authenticated users
    self|User associated with target entry
    dn[.<basic-style>]=<regex>|Users matching a regular expression
    dn.<scope-style>=<DN>|Users within scope of a DN
    !endblock
    
    The DN specifier behaves much like <what> clause DN specifiers.
    
    Other control factors are also supported.  For example, a {{EX:<who>}}
    can be restricted by an entry listed in a DN-valued attribute in
    the entry to which the access applies:
    
    
    
    The dnattr specification is used to give access to an entry
    whose DN is listed in an attribute of the entry (e.g., give
    access to a group entry to whoever is listed as the owner of
    the group entry).
    
    Some factors may not be appropriate in all environments (or any).
    For example, the domain factor relies on IP to domain name lookups.
    As these can easily be spoofed, the domain factor should be avoided.
    
    
    H3: The access to grant
    
    The kind of <access> granted can be one of the following:
    
    !block table; colaligns="LRL"; coltags="EX,EX,N"; align=Center; \
    
        title="Table 6.4: Access Levels"
    Level        Privileges    Description
    none        =0             no access
    disclose    =d             needed for information disclosure on error
    auth        =dx            needed to authenticate (bind)
    compare     =cdx           needed to compare
    search      =scdx          needed to apply search filters
    read        =rscdx         needed to read search results
    write       =wrscdx        needed to modify/rename
    manage      =mwrscdx       needed to manage
    
    !endblock
    
    Each level implies all lower levels of access. So, for example,
    granting someone {{EX:write}} access to an entry also grants them
    {{EX:read}}, {{EX:search}}, {{EX:compare}}, {{EX:auth}} and
    {{EX:disclose}} access.  However, one may use the privileges specifier
    to grant specific permissions.
    
    
    H3: Access Control Evaluation
    
    When evaluating whether some requester should be given access to
    an entry and/or attribute, slapd compares the entry and/or attribute
    to the {{EX:<what>}} selectors given in the configuration file.
    For each entry, access controls provided in the database which holds
    
    the entry (or the global access directives if not held in any database) apply
    
    Howard Chu's avatar
    Howard Chu committed
    first, followed by the global access directives. However, when dealing with
    an access list, because the global access list is effectively appended
    to each per-database list, if the resulting list is non-empty then the
    access list will end with an implicit {{EX:access to * by * none}} directive.
    If there are no access directives applicable to a backend, then a default
    
    priority, access directives are examined in the order in which they
    appear in the config file.  Slapd stops with the first {{EX:<what>}}
    selector that matches the entry and/or attribute. The corresponding
    access directive is the one slapd will use to evaluate access.
    
    Next, slapd compares the entity requesting access to the {{EX:<who>}}
    selectors within the access directive selected above in the order
    in which they appear. It stops with the first {{EX:<who>}} selector
    that matches the requester. This determines the access the entity
    requesting access has to the entry and/or attribute.
    
    Finally, slapd compares the access granted in the selected
    {{EX:<access>}} clause to the access requested by the client. If
    it allows greater or equal access, access is granted. Otherwise,
    access is denied.
    
    The order of evaluation of access directives makes their placement
    in the configuration file important. If one access directive is
    more specific than another in terms of the entries it selects, it
    should appear first in the config file. Similarly, if one {{EX:<who>}}
    selector is more specific than another it should come first in the
    access directive. The access control examples given below should
    help make this clear.
    
    
    
    H3: Access Control Examples
    
    The access control facility described above is quite powerful.  This
    section shows some examples of its use for descriptive purposes.
    
    A simple example:
    
    
    
    This access directive grants read access to everyone.
    
    
    >    access to *
    >        by self write
    >        by anonymous auth
    >        by * read
    
    
    This directive allows the user to modify their entry, allows anonymous
    
    to authenticate against these entries, and allows all others to
    
    read these entries.  Note that only the first {{EX:by <who>}} clause
    which matches applies.  Hence, the anonymous users are granted
    {{EX:auth}}, not {{EX:read}}.  The last clause could just as well
    have been "{{EX:by users read}}".
    
    It is often desirable to restrict operations based upon the level
    of protection in place.  The following shows how security strength
    factors (SSF) can be used.
    
    
    >    access to *
    >        by ssf=128 self write
    >        by ssf=64 anonymous auth
    >        by ssf=64 users read
    
    
    This directive allows users to modify their own entries if security
    
    protections of strength 128 or better have been established, allows
    authentication access to anonymous users, and read access when 64
    or better security protections have been established.  If a client
    has not established sufficient security protections, the implicit
    {{EX:by * none}} clause would be applied.
    
    
    The following example shows the use of a style specifiers to select
    the entries by DN in two access directives where ordering is
    significant.
    
    
    >    access to dn.children="dc=example,dc=com"
    >         by * search
    >    access to dn.children="dc=com"
    >         by * read
    
    
    Read access is granted to entries under the {{EX:dc=com}} subtree,
    except for those entries under the {{EX:dc=example,dc=com}} subtree,
    to which search access is granted.  No access is granted to
    {{EX:dc=com}} as neither access directive matches this DN.  If the
    order of these access directives was reversed, the trailing directive
    would never be reached, since all entries under {{EX:dc=example,dc=com}}
    are also under {{EX:dc=com}} entries.
    
    Also note that if no {{EX:access to}} directive matches or no {{EX:by
    <who>}} clause, {{B:access is denied}}.  That is, every {{EX:access
    
    to}} directive ends with an implicit {{EX:by * none}} clause. When dealing
    
    Howard Chu's avatar
    Howard Chu committed
    with an access list, because the global access list is effectively appended
    to each per-database list, if the resulting list is non-empty then the access
    
    list will end with an implicit {{EX:access to * by * none}} directive. If
    there are no access directives applicable to a backend, then a default read is
    used.
    
    
    The next example again shows the importance of ordering, both of
    the access directives and the {{EX:by <who>}} clauses.  It also
    shows the use of an attribute selector to grant access to a specific
    attribute and various {{EX:<who>}} selectors.
    
    
    >    access to dn.subtree="dc=example,dc=com" attrs=homePhone
    >        by self write
    >        by dn.children="dc=example,dc=com" search
    
    >    access to dn.subtree="dc=example,dc=com"
    >        by self write
    >        by dn.children="dc=example,dc=com" search
    >        by anonymous auth
    
    
    This example applies to entries in the "{{EX:dc=example,dc=com}}"
    subtree. To all attributes except {{EX:homePhone}}, an entry can
    write to itself, entries under {{EX:example.com}} entries can search
    by them, anybody else has no access (implicit {{EX:by * none}})
    excepting for authentication/authorization (which is always done
    anonymously).  The {{EX:homePhone}} attribute is writable by the
    entry, searchable by entries under {{EX:example.com}}, readable by
    clients connecting from network 10, and otherwise not readable
    (implicit {{EX:by * none}}).  All other access is denied by the
    implicit {{EX:access to * by * none}}.
    
    Sometimes it is useful to permit a particular DN to add or
    remove itself from an attribute. For example, if you would like to
    create a group and allow people to add and remove only
    their own DN from the member attribute, you could accomplish
    it with an access directive like this:
    
    
    >    access to attrs=member,entry
    >         by dnattr=member selfwrite
    
    
    The dnattr {{EX:<who>}} selector says that the access applies to
    entries listed in the {{EX:member}} attribute. The {{EX:selfwrite}} access
    selector says that such members can only add or delete their
    own DN from the attribute, not other values. The addition of
    the entry attribute is required because access to the entry is
    required to access any of the entry's attributes.
    
    !if 0
    For more details on how to use the {{EX:access}} directive,
    consult the {{Advanced Access Control}} chapter.
    !endif
    
    
    
    H2: Access Control via Dynamic Configuration
    
    
    Access to slapd entries and attributes is controlled by the
    olcAccess attribute, whose values are a sequence of access directives.
    The general form of the olcAccess configuration is:
    
    
    >    olcAccess: <access directive>
    >    <access directive> ::= to <what>
    >        [by <who> [<access>] [<control>] ]+
    >    <what> ::= * |
    >        [dn[.<basic-style>]=<regex> | dn.<scope-style>=<DN>]
    >        [filter=<ldapfilter>] [attrs=<attrlist>]
    >    <basic-style> ::= regex | exact
    >    <scope-style> ::= base | one | subtree | children
    >    <attrlist> ::= <attr> [val[.<basic-style>]=<regex>] | <attr> , <attrlist>
    >    <attr> ::= <attrname> | entry | children
    >    <who> ::= * | [anonymous | users | self
    
    Howard Chu's avatar
    Howard Chu committed
    >            | dn[.<basic-style>]=<regex> | dn.<scope-style>=<DN>]
    
    >        [dnattr=<attrname>]
    >        [group[/<objectclass>[/<attrname>][.<basic-style>]]=<regex>]
    >        [peername[.<basic-style>]=<regex>]
    >        [sockname[.<basic-style>]=<regex>]
    >        [domain[.<basic-style>]=<regex>]
    >        [sockurl[.<basic-style>]=<regex>]
    >        [set=<setspec>]
    >        [aci=<attrname>]
    >    <access> ::= [self]{<level>|<priv>}
    >    <level> ::= none | disclose | auth | compare | search | read | write | manage
    >    <priv> ::= {=|+|-}{m|w|r|s|c|x|d|0}+
    >    <control> ::= [stop | continue | break]
    
    
    where the <what> part selects the entries and/or attributes to which
    the access applies, the {{EX:<who>}} part specifies which entities
    are granted access, and the {{EX:<access>}} part specifies the
    access granted. Multiple {{EX:<who> <access> <control>}} triplets
    are supported, allowing many entities to be granted different access
    to the same set of entries and attributes. Not all of these access
    control options are described here; for more details see the
    {{slapd.access}}(5) man page.
    
    
    H3: What to control access to
    
    The <what> part of an access specification determines the entries
    and attributes to which the access control applies.  Entries are
    commonly selected in two ways: by DN and by filter.  The following
    qualifiers select entries by DN:
    
    
    >    to *
    >    to dn[.<basic-style>]=<regex>
    >    to dn.<scope-style>=<DN>
    
    
    The first form is used to select all entries.  The second form may
    be used to select entries by matching a regular expression against
    the target entry's {{normalized DN}}.   (The second form is not
    discussed further in this document.)  The third form is used to
    select entries which are within the requested scope of DN.  The
    <DN> is a string representation of the Distinguished Name, as
    described in {{REF:RFC4514}}.
    
    The scope can be either {{EX:base}}, {{EX:one}}, {{EX:subtree}},
    or {{EX:children}}.  Where {{EX:base}} matches only the entry with
    provided DN, {{EX:one}} matches the entries whose parent is the
    provided DN, {{EX:subtree}} matches all entries in the subtree whose
    root is the provided DN, and {{EX:children}} matches all entries
    under the DN (but not the entry named by the DN).
    
    For example, if the directory contained entries named:
    
    
    >    0: o=suffix
    >    1: cn=Manager,o=suffix
    >    2: ou=people,o=suffix
    >    3: uid=kdz,ou=people,o=suffix
    >    4: cn=addresses,uid=kdz,ou=people,o=suffix
    >    5: uid=hyc,ou=people,o=suffix
    
    
    \Then:
    . {{EX:dn.base="ou=people,o=suffix"}} match 2;
    . {{EX:dn.one="ou=people,o=suffix"}} match 3, and 5;
    . {{EX:dn.subtree="ou=people,o=suffix"}} match 2, 3, 4, and 5; and
    . {{EX:dn.children="ou=people,o=suffix"}} match 3, 4, and 5.
    
    
    Entries may also be selected using a filter:
    
    
    
    where <ldap filter> is a string representation of an LDAP
    search filter, as described in {{REF:RFC4515}}.  For example:
    
    
    
    Note that entries may be selected by both DN and filter by
    including both qualifiers in the <what> clause.
    
    
    >    to dn.one="ou=people,o=suffix" filter=(objectClass=person)
    
    
    Attributes within an entry are selected by including a comma-separated
    list of attribute names in the <what> selector:
    
    
    
    A specific value of an attribute is selected by using a single
    attribute name and also using a value selector:
    
    
    >    attrs=<attribute> val[.<style>]=<regex>
    
    
    There are two special {{pseudo}} attributes {{EX:entry}} and
    {{EX:children}}.  To read (and hence return) a target entry, the
    subject must have {{EX:read}} access to the target's {{entry}}
    
    attribute.  To perform a search, the subject must have
    {{EX:search}} access to the search base's {{entry}} attribute.
    To add or delete an entry, the subject must have
    
    {{EX:write}} access to the entry's {{EX:entry}} attribute AND must
    have {{EX:write}} access to the entry's parent's {{EX:children}}
    attribute.  To rename an entry, the subject must have {{EX:write}}
    access to entry's {{EX:entry}} attribute AND have {{EX:write}}
    access to both the old parent's and new parent's {{EX:children}}
    attributes.  The complete examples at the end of this section should
    help clear things up.
    
    Lastly, there is a special entry selector {{EX:"*"}} that is used to
    select any entry.  It is used when no other {{EX:<what>}}
    selector has been provided.  It's equivalent to "{{EX:dn=.*}}"
    
    
    H3: Who to grant access to
    
    The <who> part identifies the entity or entities being granted
    access. Note that access is granted to "entities" not "entries."
    The following table summarizes entity specifiers:
    
    !block table; align=Center; coltags="EX,N"; \
    
        title="Table 5.3: Access Entity Specifiers"
    
    Specifier|Entities
    *|All, including anonymous and authenticated users
    anonymous|Anonymous (non-authenticated) users
    users|Authenticated users
    self|User associated with target entry
    dn[.<basic-style>]=<regex>|Users matching a regular expression
    dn.<scope-style>=<DN>|Users within scope of a DN
    !endblock
    
    The DN specifier behaves much like <what> clause DN specifiers.
    
    Other control factors are also supported.  For example, a {{EX:<who>}}
    can be restricted by an entry listed in a DN-valued attribute in
    the entry to which the access applies:
    
    
    
    The dnattr specification is used to give access to an entry
    whose DN is listed in an attribute of the entry (e.g., give
    access to a group entry to whoever is listed as the owner of
    the group entry).
    
    Some factors may not be appropriate in all environments (or any).
    For example, the domain factor relies on IP to domain name lookups.
    As these can easily be spoofed, the domain factor should be avoided.
    
    
    H3: The access to grant
    
    The kind of <access> granted can be one of the following:
    
    !block table; colaligns="LRL"; coltags="EX,EX,N"; align=Center; \
    
        title="Table 5.4: Access Levels"
    Level        Privileges    Description
    none         =0            no access
    disclose     =d            needed for information disclosure on error
    auth         =dx           needed to authenticate (bind)
    compare      =cdx          needed to compare
    search       =scdx         needed to apply search filters
    read         =rscdx        needed to read search results
    write        =wrscdx       needed to modify/rename
    manage       =mwrscdx      needed to manage
    
    !endblock
    
    Each level implies all lower levels of access. So, for example,
    granting someone {{EX:write}} access to an entry also grants them
    {{EX:read}}, {{EX:search}}, {{EX:compare}}, {{EX:auth}} and
    {{EX:disclose}} access.  However, one may use the privileges specifier
    to grant specific permissions.
    
    
    H3: Access Control Evaluation
    
    When evaluating whether some requester should be given access to
    an entry and/or attribute, slapd compares the entry and/or attribute
    to the {{EX:<what>}} selectors given in the configuration.  For
    each entry, access controls provided in the database which holds
    
    the entry (or the global access directives if not held in any database) apply
    
    first, followed by the global access directives (which are held in
    
    Howard Chu's avatar
    Howard Chu committed
    the {{EX:frontend}} database definition). However, when dealing with
    an access list, because the global access list is effectively appended
    to each per-database list, if the resulting list is non-empty then the
    access list will end with an implicit {{EX:access to * by * none}} directive.
    If there are no access directives applicable to a backend, then a default
    
    read is used.
    
    Within this priority,
    
    access directives are examined in the order in which they appear
    in the configuration attribute.  Slapd stops with the first
    {{EX:<what>}} selector that matches the entry and/or attribute. The
    corresponding access directive is the one slapd will use to evaluate
    access.
    
    Next, slapd compares the entity requesting access to the {{EX:<who>}}
    selectors within the access directive selected above in the order
    in which they appear. It stops with the first {{EX:<who>}} selector
    that matches the requester. This determines the access the entity
    requesting access has to the entry and/or attribute.
    
    Finally, slapd compares the access granted in the selected
    {{EX:<access>}} clause to the access requested by the client. If
    it allows greater or equal access, access is granted. Otherwise,
    access is denied.
    
    The order of evaluation of access directives makes their placement
    in the configuration file important. If one access directive is
    more specific than another in terms of the entries it selects, it
    should appear first in the configuration. Similarly, if one {{EX:<who>}}
    selector is more specific than another it should come first in the
    access directive. The access control examples given below should
    help make this clear.
    
    
    
    H3: Access Control Examples
    
    The access control facility described above is quite powerful.  This
    section shows some examples of its use for descriptive purposes.
    
    A simple example:
    
    
    
    This access directive grants read access to everyone.
    
    
    >    olcAccess: to *
    >        by self write
    >        by anonymous auth
    >        by * read
    
    
    This directive allows the user to modify their entry, allows anonymous
    to authenticate against these entries, and allows all others to
    read these entries.  Note that only the first {{EX:by <who>}} clause
    which matches applies.  Hence, the anonymous users are granted
    {{EX:auth}}, not {{EX:read}}.  The last clause could just as well
    have been "{{EX:by users read}}".
    
    It is often desirable to restrict operations based upon the level
    of protection in place.  The following shows how security strength
    factors (SSF) can be used.
    
    
    >    olcAccess: to *
    >        by ssf=128 self write
    >        by ssf=64 anonymous auth
    >        by ssf=64 users read
    
    
    This directive allows users to modify their own entries if security
    protections of strength 128 or better have been established,
    allows authentication access to anonymous users, and read access
    when strength 64 or better security protections have been established.  If
    the client has not establish sufficient security protections, the
    implicit {{EX:by * none}} clause would be applied.
    
    The following example shows the use of style specifiers to select
    the entries by DN in two access directives where ordering is
    significant.
    
    
    >    olcAccess: to dn.children="dc=example,dc=com"
    >         by * search
    >    olcAccess: to dn.children="dc=com"
    >         by * read
    
    
    Read access is granted to entries under the {{EX:dc=com}} subtree,
    except for those entries under the {{EX:dc=example,dc=com}} subtree,
    to which search access is granted.  No access is granted to
    {{EX:dc=com}} as neither access directive matches this DN.  If the
    order of these access directives was reversed, the trailing directive
    would never be reached, since all entries under {{EX:dc=example,dc=com}}
    are also under {{EX:dc=com}} entries.
    
    Also note that if no {{EX:olcAccess: to}} directive matches or no {{EX:by
    
    Howard Chu's avatar
    Howard Chu committed
    <who>}} clause, {{B:access is denied}}.  When dealing with an access list,
    because the global access list is effectively appended to each per-database
    list, if the resulting list is non-empty then the access list will end with
    an implicit {{EX:access to * by * none}} directive. If there are no access
    
    directives applicable to a backend, then a default read is used.
    
    
    The next example again shows the importance of ordering, both of
    the access directives and the {{EX:by <who>}} clauses.  It also
    shows the use of an attribute selector to grant access to a specific
    attribute and various {{EX:<who>}} selectors.
    
    
    >    olcAccess: to dn.subtree="dc=example,dc=com" attrs=homePhone
    >        by self write
    >        by dn.children=dc=example,dc=com" search
    
    >    olcAccess: to dn.subtree="dc=example,dc=com"
    >        by self write
    >        by dn.children="dc=example,dc=com" search
    >        by anonymous auth
    
    
    This example applies to entries in the "{{EX:dc=example,dc=com}}"
    subtree. To all attributes except {{EX:homePhone}}, an entry can
    write to itself, entries under {{EX:example.com}} entries can search
    by them, anybody else has no access (implicit {{EX:by * none}})
    excepting for authentication/authorization (which is always done
    anonymously).  The {{EX:homePhone}} attribute is writable by the
    entry, searchable by entries under {{EX:example.com}}, readable by
    clients connecting from network 10, and otherwise not readable
    (implicit {{EX:by * none}}).  All other access is denied by the
    implicit {{EX:access to * by * none}}.
    
    Sometimes it is useful to permit a particular DN to add or
    remove itself from an attribute. For example, if you would like to
    create a group and allow people to add and remove only
    their own DN from the member attribute, you could accomplish
    it with an access directive like this:
    
    
    >    olcAccess: to attrs=member,entry
    >         by dnattr=member selfwrite
    
    
    The dnattr {{EX:<who>}} selector says that the access applies to
    entries listed in the {{EX:member}} attribute. The {{EX:selfwrite}} access
    selector says that such members can only add or delete their
    own DN from the attribute, not other values. The addition of
    the entry attribute is required because access to the entry is
    required to access any of the entry's attributes.
    
    
    
    H3: Access Control Ordering
    
    Since the ordering of {{EX:olcAccess}} directives is essential to their
    proper evaluation, but LDAP attributes normally do not preserve the
    ordering of their values, OpenLDAP uses a custom schema extension to
    maintain a fixed ordering of these values. This ordering is maintained
    by prepending a {{EX:"{X}"}} numeric index to each value, similarly to
    the approach used for ordering the configuration entries. These index
    tags are maintained automatically by slapd and do not need to be specified
    when originally defining the values. For example, when you create the
    settings
    
    
    >    olcAccess: to attrs=member,entry
    >         by dnattr=member selfwrite
    >    olcAccess: to dn.children="dc=example,dc=com"
    >         by * search
    >    olcAccess: to dn.children="dc=com"
    >         by * read
    
    
    when you read them back using slapcat or ldapsearch they will contain
    
    
    >    olcAccess: {0}to attrs=member,entry
    >         by dnattr=member selfwrite
    >    olcAccess: {1}to dn.children="dc=example,dc=com"
    >         by * search
    >    olcAccess: {2}to dn.children="dc=com"
    >         by * read
    
    
    The numeric index may be used to specify a particular value to change
    when using ldapmodify to edit the access rules. This index can be used
    
    Howard Chu's avatar
    Howard Chu committed
    instead of (or in addition to) the actual access value. Using this
    
    numeric index is very helpful when multiple access rules are being managed.
    
    For example, if we needed to change the second rule above to grant
    write access instead of search, we could try this LDIF:
    
    
    >    changetype: modify
    >    delete: olcAccess
    >    olcAccess: to dn.children="dc=example,dc=com" by * search
    >    -
    >    add: olcAccess
    >    olcAccess: to dn.children="dc=example,dc=com" by * write
    >    -
    
    
    But this example {{B:will not}} guarantee that the existing values remain in
    their original order, so it will most likely yield a broken security
    configuration. Instead, the numeric index should be used:
    
    
    >    changetype: modify
    >    delete: olcAccess
    >    olcAccess: {1}
    >    -
    >    add: olcAccess
    >    olcAccess: {1}to dn.children="dc=example,dc=com" by * write
    >    -
    
    
    This example deletes whatever rule is in value #1 of the {{EX:olcAccess}}
    attribute (regardless of its value) and adds a new value that is
    explicitly inserted as value #1. The result will be
    
    
    >    olcAccess: {0}to attrs=member,entry
    >         by dnattr=member selfwrite
    >    olcAccess: {1}to dn.children="dc=example,dc=com"
    >         by * write
    >    olcAccess: {2}to dn.children="dc=com"
    >         by * read
    
    
    which is exactly what was intended.
    
    !if 0
    For more details on how to use the {{EX:access}} directive,
    consult the {{Advanced Access Control}} chapter.
    !endif
    
    
    
    H2: Access Control Common Examples
    
    H3: Basic ACLs
    
    Generally one should start with some basic ACLs such as:
    
    
    >        by self =xw
    >        by anonymous auth
    >        by * none
    >
    >
    >      access to *
    >        by self write
    >        by users read
    >        by * none
    
    
    Howard Chu's avatar
    Howard Chu committed
    The first ACL allows users to update (but not read) their passwords, anonymous
    users to authenticate against this attribute, and (implicitly) denying all
    
    Howard Chu's avatar
    Howard Chu committed
    The second ACL allows users full access to their entry, authenticated users read
    access to anything, and (implicitly) denying all access to others (in this case,
    anonymous users).
    
    
    
    H3: Matching Anonymous and Authenticated users
    
    An anonymous user has a empty DN. While the {{dn.exact=""}} or {{dn.regex="^$"}}
    
    Howard Chu's avatar
    Howard Chu committed
     could be used, {{slapd}}(8)) offers an anonymous shorthand which should be
    
    Howard Chu's avatar
    Howard Chu committed
    denies all access to anonymous users while granting others read.
    
    Howard Chu's avatar
    Howard Chu committed
    Authenticated users have a subject DN. While {{dn.regex=".+"}} will match any
    authenticated user, OpenLDAP provides the users short hand which should be used
    
    Howard Chu's avatar
    Howard Chu committed
    This ACL grants read permissions to authenticated users while denying others
    
    Howard Chu's avatar
    Howard Chu committed
    You could specify the {{rootdn}} in {{slapd.conf}}(5) or {{slapd.d}} without
    specifying a {{rootpw}}. Then you have to add an actual directory entry with
    
    the same dn, e.g.:
    
    >    dn: cn=Manager,o=MyOrganization
    >    cn: Manager
    >    sn: Manager
    >    objectClass: person
    >    objectClass: top
    >    userPassword: {SSHA}someSSHAdata
    
    
    Howard Chu's avatar
    Howard Chu committed
    Then binding as the {{rootdn}} will require a regular bind to that DN, which
    in turn requires auth access to that entry's DN and {{userPassword}}, and this
    
    can be restricted via ACLs. E.g.:
    
    >    access to dn.base="cn=Manager,o=MyOrganization"
    >      by peername.regex=127\.0\.0\.1 auth
    >      by peername.regex=192\.168\.0\..* auth
    >      by users none
    >      by * none
    
    
    Howard Chu's avatar
    Howard Chu committed
    The ACLs above will only allow binding using rootdn from localhost and
    
    H3: Controlling the LDAP Proxied Authorization Control
    
    The Proxied Authorization Control allows a client to request that an
    operation be processed under a provided authorization identity instead of
    under the current authentication identity associated with the connection.
    
    This facility is controlled by the {{EX:authz-policy}} configuration
    option and by the {{EX:authzTo}} and {{EX:authzFrom}} attributes.
    It can be further controlled by applying access control to those attributes.
    
    A client application might bind as cn=Client,o=MyOrganization whose entry
    looks like this:
    
    >    dn: cn=Client,o=MyOrganization
    >    cn: Client
    >    objectClass: organizationalRole
    >    objectClass: simpleSecurityObject
    >    objectClass: top
    >    userPassword: {SSHA}someSSHAdata
    >    authzTo: dn.regex:^cn=[^,]+,ou=People,o=MyOrganization$
    
    To make use of the proxy facility, the client needs at least {{EX:auth}}
    privilege on the {{EX:authzTo}} attribute:
    
    >    access to dn.exact=cn=Client,o=MyOrganization attr=authzTo
    >      by self auth
    >      by * break
    
    This access would be automatically granted if cn=Client,o=MyOrganization
    has {{EX:read}} privilege on its own entry.
    
    Now if you want to lock down the use of this powerful account, you might
    write an ACL like this:
    
    >    access to dn.exact=cn=Client,o=MyOrganization attr=authzTo
    >      by self peername.regex=192\.168\.0\..*  ssf=256 auth
    >      by * none
    
    Now, cn=Client,o=MyOrganization can only make use of the proxy authorization
    control if it has connected from an appropriate IP address using
    a sufficient level of cryptographic protection. No other IDs can even
    see the authzTo attribute.
    
    
    
    Howard Chu's avatar
    Howard Chu committed
    There are a few ways to do this. One approach is illustrated here. Consider the
    
    following DIT layout:
    
    >    +-dc=example,dc=com
    >    +---cn=administrators,dc=example,dc=com
    
    Howard Chu's avatar
    Howard Chu committed
    >    +---cn=fred blogs,dc=example,dc=com
    
    
    and the following group object (in LDIF format):
    
    >    dn: cn=administrators,dc=example,dc=com
    >    cn: administrators of this region
    >    objectclass: groupOfNames  (important for the group acl feature)
    
    Howard Chu's avatar
    Howard Chu committed
    >    member: cn=fred blogs,dc=example,dc=com
    
    >    member: cn=somebody else,dc=example,dc=com
    
    
    Howard Chu's avatar
    Howard Chu committed
    One can then grant access to the members of this this group by adding appropriate
    
    {{by group}} clause to an access directive in {{slapd.conf}}(5). For instance,
    
    
    Howard Chu's avatar
    Howard Chu committed
    >    access to dn.children="dc=example,dc=com"
    >        by self write
    >        by group.exact="cn=Administrators,dc=example,dc=com" write
    
    Howard Chu's avatar
    Howard Chu committed
    Like by {{dn}} clauses, one can also use {{expand}} to expand the group name
    based upon the regular expression matching of the target, that is, the to {{dn.regex}}).
    
    For instance,
    
    >    access to dn.regex="(.+,)?ou=People,(dc=[^,]+,dc=[^,]+)$"
    >             attrs=children,entry,uid
    >        by group.expand="cn=Managers,$2" write
    >        by users read
    >        by * auth
    
    
    
    Howard Chu's avatar
    Howard Chu committed
    The above illustration assumed that the group members are to be found in the
    {{member}} attribute type of the {{groupOfNames}} object class. If you need to
    use a different group object and/or a different attribute type then use the
    
    following {{slapd.conf}}(5) (abbreviated) syntax:
    
    >    access to <what>
    >            by group/<objectclass>/<attributename>=<DN> <access>
    
    For example:
    
    >    access to *
    >      by group/organizationalRole/roleOccupant="cn=Administrator,dc=example,dc=com" write
    
    
    Howard Chu's avatar
    Howard Chu committed
    In this case, we have an ObjectClass {{organizationalRole}} which contains the
    
    administrator DN's in the {{roleOccupant}} attribute. For instance:
    
    >    dn: cn=Administrator,dc=example,dc=com
    >    cn: Administrator
    >    objectclass: organizationalRole
    
    Howard Chu's avatar
    Howard Chu committed
    >    roleOccupant: cn=Jane Doe,dc=example,dc=com
    
    Howard Chu's avatar
    Howard Chu committed
    Note: the specified member attribute type MUST be of DN or {{NameAndOptionalUID}} syntax,
    
    and the specified object class SHOULD allow the attribute type.
    
    Dynamic Groups are also supported in Access Control. Please see {{slapo-dynlist}}(5)
    and the {{SECT:Dynamic Lists}} overlay section.
    
    
    H3:  Granting access to a subset of attributes
    
    
    Howard Chu's avatar
    Howard Chu committed
    You can grant access to a set of attributes by specifying a list of attribute names
    in the ACL {{to}} clause. To be useful, you also need to grant access to the
    {{entry}} itself. Also note how {{children}} controls the ability to add, delete,
    
    and rename entries.
    
    >    # mail: self may write, authenticated users may read
    >    access to attrs=mail
    >      by self write
    >      by users read
    >      by * none
    
    Howard Chu's avatar
    Howard Chu committed
    >
    
    >    # cn, sn: self my write, all may read
    >    access to attrs=cn,sn
    >      by self write
    >      by * read
    
    Howard Chu's avatar
    Howard Chu committed
    >
    
    >    # immediate children: only self can add/delete entries under this entry
    >    access to attrs=children
    >      by self write
    
    Howard Chu's avatar
    Howard Chu committed
    >
    
    >    # entry itself: self may write, all may read
    >    access to attrs=entry
    >      by self write
    >      by * read
    
    Howard Chu's avatar
    Howard Chu committed
    >
    
    >    # other attributes: self may write, others have no access
    >    access to *
    >      by self write
    >      by * none
    
    
    Howard Chu's avatar
    Howard Chu committed
    ObjectClass names may also be specified in this list, which will affect
    all the attributes that are required and/or allowed by that {{objectClass}}.
    Actually, names in {{attrlist}} that are prefixed by {{@}} are directly treated
    as objectClass names. A name prefixed by {{!}} is also treated as an objectClass,
    but in this case the access rule affects the attributes that are not required
    nor allowed by that {{objectClass}}.