diff options
author | Guilhem Moulin <guilhem.moulin@fripost.org> | 2012-09-26 02:36:45 +0200 |
---|---|---|
committer | Guilhem Moulin <guilhem.moulin@fripost.org> | 2012-09-26 02:36:45 +0200 |
commit | 6689ea9829fd2957ff1c1589b0731eedb5fc8817 (patch) | |
tree | a882337de4b2024f72c94b45c3c561b08fc30bb4 /ldap | |
parent | 4239920246a5123644fd7a778b467aa371f990e6 (diff) |
Updated the LDAP schema to suit the list creation script, and the acl to suit the SASL authentication.
Diffstat (limited to 'ldap')
-rw-r--r-- | ldap/acl.ldif | 90 | ||||
-rw-r--r-- | ldap/authz.ldif | 10 | ||||
-rw-r--r-- | ldap/base.ldif | 19 | ||||
-rw-r--r-- | ldap/constraint.ldif | 3 | ||||
-rw-r--r-- | ldap/fripost.ldif | 44 | ||||
-rw-r--r-- | ldap/index.ldif | 8 | ||||
-rw-r--r-- | ldap/populate.ldif | 43 | ||||
-rwxr-xr-x | ldap/test-user-acl.sh | 212 |
8 files changed, 324 insertions, 105 deletions
diff --git a/ldap/acl.ldif b/ldap/acl.ldif index e52e4d5..ac2e19d 100644 --- a/ldap/acl.ldif +++ b/ldap/acl.ldif @@ -29,9 +29,10 @@ replace: olcAccess # TODO: for postfix, it'd be more efficient and more secure to SASL-bind # on a UNIX socket (EXTERNAL mechanism); wait for Postfix 2.8. # TODO: IMAP & SASLauth +# TODO: if possible, make use GSSAPI for the services. olcAccess: to dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=dev" - attrs=entry,objectClass,fvd,fripostIsStatusActive,fripostOptionalMaildrop,fvu,fripostOptionalMaildrop,fva,fripostMaildrop,fvl,fripostListCommand - filter=(|(objectClass=FripostVirtualDomain)(objectClass=FripostVirtualMailbox)(objectClass=FripostVirtualAlias)(objectClass=FripostVirtualList)) + attrs=entry,objectClass,fvd,fripostIsStatusActive,fripostIsStatusPending,fripostOptionalMaildrop,fvu,fva,fripostMaildrop,fvl,fvlc,fripostLocalAlias + filter=(|(objectClass=FripostVirtualDomain)(objectClass=FripostVirtualMailbox)(objectClass=FripostVirtualAlias)(objectClass=FripostVirtualList)(objectClass=FripostVirtualListCommand)) by dn.exact="cn=SMTP,ou=services,o=mailHosting,dc=fripost,dc=dev" =rsd by users none break # @@ -45,23 +46,28 @@ olcAccess: to dn.one="ou=services,o=mailHosting,dc=fripost,dc=dev" attrs=entry,objectClass,authzTo by * =x # -# 1. Services have no access other than the one above. -# 2. Managers have read/write access to the "virtual" subtree. +# 1. Managers have read/write access to the "virtual" subtree. +# 2. The list creator needs further access. +# 3. Other services have no access other than the one above. +# 4,5. Other users need further access. olcAccess: to dn.subtree="ou=virtual,o=mailHosting,dc=fripost,dc=dev" + by dn.onelevel="ou=managers,o=mailHosting,dc=fripost,dc=dev" write + by dn.exact="cn=ListCreator,ou=services,o=mailHosting,dc=fripost,dc=dev" none break by dn.onelevel="ou=services,o=mailHosting,dc=fripost,dc=dev" none - by dn.onelevel="ou=managers,o=mailHosting,dc=fripost,dc=org" write - by * none break + by dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=dev" none break + by anonymous none break # # 1. Users can change their password (but not read it). -# 2. Anonymous users/services/managers can bind. +# 2. Anonymous users can bind. # 3. Else, we inspect the 2 following ACLs. olcAccess: to dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=dev" attrs=userPassword by self =w by anonymous auth - by users none break + by dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=dev" none break # -# The postmaster of a domain can change (replace) his/her users' password. +# The postmaster of a domain can change (replace) his/her users' +# password (but not see it). olcAccess: to dn.regex="^fvu=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=dev)$" filter=(objectClass=FripostVirtualMailbox) attrs=userPassword @@ -73,22 +79,25 @@ olcAccess: to dn.subtree="o=mailHosting,dc=fripost,dc=dev" attrs=userPassword by * none # -# Users can search (e.g., to list the entries they have created). +# 1. Users can search (e.g., to list the entries they have created). +# 2. So can the list creator. olcAccess: to dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=dev" attrs=objectClass - by users =s + by dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=dev" =s + by dn.exact="cn=ListCreator,ou=services,o=mailHosting,dc=fripost,dc=dev" =s # # Users can search (e.g., to list the entries they have created). # Additional permissions may be added later on. olcAccess: to dn.subtree="ou=virtual,o=mailHosting,dc=fripost,dc=dev" attrs=entry,creatorsName,fripostOwner,fripostPostmaster,fripostCanCreateAlias,fripostCanCreateList - by users =s break + by dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=dev" =s break + by dn.onelevel="ou=services,o=mailHosting,dc=fripost,dc=dev" none break # # Everyone can delete domains. (Provided s/he has +d access to the "entry" # attribute of the domains s/he wants to delete.) olcAccess: to dn.base="ou=virtual,o=mailHosting,dc=fripost,dc=dev" attrs=children - by users =z + by dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=dev" =z # # Reserved local parts are reserved. olcAccess: to dn.regex="^(fvu|fva|fvl)=(postmaster|abuse),fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=dev$" @@ -122,7 +131,7 @@ olcAccess: to dn.regex="^(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=dev)$ by dnattr=fripostPostmaster read by set.exact="(this/fripostCanCreateAlias | this/fripostCanCreateList)& (user | user/-1)" read by dn.onelevel,expand="$1" +d - by users +0 + by dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=dev" +0 # # Every one can add or delete children, but we will be carefull with the # kid's "entry" attribute, which require +a and +z to add and delete @@ -130,7 +139,7 @@ olcAccess: to dn.regex="^(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=dev)$ olcAccess: to dn.regex="^fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=dev$" filter=(objectClass=FripostVirtualDomain) attrs=children - by users +w + by dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=dev" +w # # 1. Domain owners can edit their entry's attributes. # 2. So can domain postmasters. @@ -151,7 +160,7 @@ olcAccess: to dn.regex="^fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=dev$" attrs=@fripostVirtualDomain by dnattr=fripostOwner write by dnattr=fripostPostmaster write - by users +0 + by dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=dev" +0 # # 1. Domain owners can delete the domain (and read the entry). # 2. So can domain postmasters. @@ -164,7 +173,7 @@ olcAccess: to dn.regex="^(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=dev)$ by dnattr=fripostPostmaster +zrd by dn.onelevel,expand="$1" +rd by set.exact="(this/fripostCanCreateAlias | this/fripostCanCreateList) & (user | user/-1)" +rd - by users +0 + by dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=dev" +0 # # Noone (but the managers) can change quotas. olcAccess: to dn.regex="^fvu=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=dev)$" @@ -199,7 +208,7 @@ olcAccess: to dn.regex="^fva=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripos by dnattr=fripostOwner read continue by group/fripostVirtualDomain/fripostOwner.expand="$1" write by group/fripostVirtualDomain/fripostPostmaster.expand="$1" write - by users +0 + by dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=dev" +0 # # 1. The alias owners can edit the rest of their entry's attributes. # 2. So can the domain owners. @@ -223,7 +232,7 @@ olcAccess: to dn.regex="^fva=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripos by group/fripostVirtualDomain/fripostOwner.expand="$1" +wrd by group/fripostVirtualDomain/fripostPostmaster.expand="$1" +wrd by set.exact="this/-1/fripostCanCreateAlias & (user | user/-1)" +a - by users +0 + by dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=dev" +0 # # 1. The list owner can list the ownership of the entry. # 2. The domain owner can add/delete/change the ownership of the entry. @@ -234,18 +243,27 @@ olcAccess: to dn.regex="^fvl=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripos by dnattr=fripostOwner read continue by group/fripostVirtualDomain/fripostOwner.expand="$1" write by group/fripostVirtualDomain/fripostPostmaster.expand="$1" write - by users +0 + by dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=dev" +0 # # 1. The list owner read (but not edit) the transport-related attributes. # 2. So can the domain ower. # 3. So can the domain postmaster. olcAccess: to dn.regex="^fvl=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=dev)$" filter=(objectClass=FripostVirtualList) - attrs=fripostListManager,fripostListCommand + attrs=fripostListManager by dnattr=fripostOwner read by group/fripostVirtualDomain/fripostOwner.expand="$1" read by group/fripostVirtualDomain/fripostPostmaster.expand="$1" read # +# Only the list creator can remove the "pending" flag +olcAccess: to dn.regex="^fvl=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=dev)$" + filter=(objectClass=FripostVirtualList) + attrs=fripostIsStatusPending + by dnattr=fripostOwner read + by group/fripostVirtualDomain/fripostOwner.expand="$1" read + by group/fripostVirtualDomain/fripostPostmaster.expand="$1" read + by dn.exact="cn=ListCreator,ou=services,o=mailHosting,dc=fripost,dc=dev" =zrd +# # 1. The list owners can edit their entry's attributes. # 2. So can the domain owners. # 3. So can the domain postmasters. @@ -256,24 +274,34 @@ olcAccess: to dn.regex="^fvl=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripos by group/fripostVirtualDomain/fripostOwner.expand="$1" write by group/fripostVirtualDomain/fripostPostmaster.expand="$1" write # -# 1. The list owners can read and delete the entry. +# 1. The list owners can read the entry. # 2. So can the domain's Owner. # 3. So can the domain's Postmaster. # 4. Users with "canCreateList" capability (either explicitely, or as a wildcard) for the domain can create lists for that domain. # (But *not* delete them, unless also owner.) +# 6. The list creator can read the entry. olcAccess: to dn.regex="^fvl=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=dev)$" filter=(objectClass=FripostVirtualList) attrs=entry - by dnattr=fripostOwner +rzd continue - by group/fripostVirtualDomain/fripostOwner.expand="$1" +rwd - by group/fripostVirtualDomain/fripostPostmaster.expand="$1" +rwd + by dnattr=fripostOwner +rd continue + by group/fripostVirtualDomain/fripostOwner.expand="$1" +rad + by group/fripostVirtualDomain/fripostPostmaster.expand="$1" +rad by set.exact="this/-1/fripostCanCreateList & (user | user/-1)" +a - by users +0 -#TODO -#olcAccess: to dn.regex="^fvl=([^,]+)-request,fvl=[^,]+,fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=dev$" -# filter=(objectClass=FripostVirtualListCommand) -# by users read + by dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=dev" +0 + by dn.exact="cn=ListCreator,ou=services,o=mailHosting,dc=fripost,dc=dev" =rsd +# +# The List Creator can add list commands. +olcAccess: to dn.regex="^fvl=[^,]+,fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=dev" + filter=(objectClass=FripostVirtualList) + attrs=children + by dn.exact="cn=ListCreator,ou=services,o=mailHosting,dc=fripost,dc=dev" =a +# +# The List Creator can add list commands. +olcAccess: to dn.regex="^fvlc=[^,]+,fvl=[^,]+,fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=dev" + filter=(objectClass=FripostVirtualListCommand) + attrs=entry + by dn.exact="cn=ListCreator,ou=services,o=mailHosting,dc=fripost,dc=dev" =a # # Catch the "break" control above. olcAccess: to dn.subtree="ou=virtual,o=mailHosting,dc=fripost,dc=dev" - by users +0 + by dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=dev" +0 diff --git a/ldap/authz.ldif b/ldap/authz.ldif index 657d718..34a02df 100644 --- a/ldap/authz.ldif +++ b/ldap/authz.ldif @@ -7,8 +7,11 @@ # # SASL authentication can be checked with: # -# ldapwhoami -W -Y PLAIN -U AdminWebPanel@fripost.org -H ldapi:// -# ldapwhoami -W -Y PLAIN -U AdminWebPanel@fripost.org -H ldapi:// -X "dn:fvu=user1,fvd=fripost.org,ou=virtual,o=mailHosting,dc=fripost,dc=dev" +# ldapwhoami -U 'AdminWebPanel' +# ldapwhoami -U 'AdminWebPanel' -X "dn:fvu=user1,fvd=fripost.org,ou=virtual,o=mailHosting,dc=fripost,dc=dev" +# +# Note: The user making the LDAP query needs to have a valid kerberos +# ticket for the principal AdminWebPanel/fripost.org. # # WARNING: Beware that will also delete existing AuthzRegexp and # AuthzPolicy. @@ -22,8 +25,7 @@ dn: cn=config changetype: modify replace: olcAuthzRegexp -# TODO: force the mechanism here (GSSAPI) -olcAuthzRegexp: uid=(AdminWebPanel)@fripost\.org,cn=[^,]+,cn=auth cn=$1,ou=services,o=mailHosting,dc=fripost,dc=dev +olcAuthzRegexp: uid=(AdminWebPanel),cn=GSSAPI,cn=auth cn=$1,ou=services,o=mailHosting,dc=fripost,dc=dev - replace: olcAuthzPolicy olcAuthzPolicy: to diff --git a/ldap/base.ldif b/ldap/base.ldif index 8acbe10..0f414f1 100644 --- a/ldap/base.ldif +++ b/ldap/base.ldif @@ -22,16 +22,19 @@ description: Virtual mail hosting dn: ou=services,o=mailHosting,dc=fripost,dc=dev objectClass: organizationalUnit -dn: cn=AdminWebPanel,ou=services,o=mailHosting,dc=fripost,dc=dev +dn: cn=SMTP,ou=services,o=mailHosting,dc=fripost,dc=dev objectClass: simpleSecurityObject objectClass: organizationalRole -description: The adminstrator Web Panel -userPassword: panel -authzTo: dn.regex:^fvu=[^,]+,fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=dev$ +userPassword: smtp +description: Where Postfix bind to for LDAP lookups. -dn: cn=SMTP,ou=services,o=mailHosting,dc=fripost,dc=dev +dn: cn=ListCreator,ou=services,o=mailHosting,dc=fripost,dc=dev objectClass: simpleSecurityObject objectClass: organizationalRole -userPassword: smtp -description: The entry the replicates bind to when fetching the LDAP - directory. Right now it is also used by Postfix for LDAP lookups. +description: The entity that is authorized to add list commands +userPassword: listcreator + +dn: cn=AdminWebPanel,ou=services,o=mailHosting,dc=fripost,dc=dev +objectClass: organizationalRole +description: The adminstrator Web Panel +authzTo: dn.regex:^fvu=[^,]+,fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=dev$ diff --git a/ldap/constraint.ldif b/ldap/constraint.ldif index 555be85..f909c6b 100644 --- a/ldap/constraint.ldif +++ b/ldap/constraint.ldif @@ -21,8 +21,9 @@ olcConstraintAttribute: fvd regex ^.+\..+$ olcConstraintAttribute: fvu regex ^.+$ olcConstraintAttribute: fva regex ^.+$ olcConstraintAttribute: fvl regex ^.+$ +olcConstraintAttribute: fvlc regex ^.+-.+$ olcConstraintAttribute: fripostMaildrop regex ^.*@.+\..+$ olcConstraintAttribute: fripostOptionalMaildrop regex ^.*@.+\..+$ -olcConstraintAttribute: fripostListCommand regex ^.+-.+$ +olcConstraintAttribute: fripostLocalAlias regex ^.+$ olcConstraintAttribute: fripostListManager regex ^(mailman|schleuder)$ olcConstraintAttribute: userPassword count 1 diff --git a/ldap/fripost.ldif b/ldap/fripost.ldif index b110ee7..e0c226d 100644 --- a/ldap/fripost.ldif +++ b/ldap/fripost.ldif @@ -64,13 +64,19 @@ olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.4 NAME 'fvl' SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{64} SINGLE-VALUE ) # -olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.5 NAME 'fripostListCommand' - DESC 'The local part of a command associated with a list' +olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.5 NAME 'fvlc' + DESC 'The local part of a virtual list command' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch - SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{64} ) + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{64} SINGLE-VALUE ) +# +olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.6 NAME 'fripostLocalAlias' + DESC 'A local alias, typically localpart#domainpart.tld' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{64} SINGLE-VALUE ) # -olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.6 NAME 'fripostMaildrop' +olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.7 NAME 'fripostMaildrop' DESC 'An email address the virtual alias should be mapped to' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch @@ -79,39 +85,44 @@ olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.6 NAME 'fripostMaildrop' # We are creating a new attribute, optional in virtual domains and # mailboxes, because the presence index should *not* apply to the # mandatory attribute above. -olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.7 NAME 'fripostOptionalMaildrop' +olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.8 NAME 'fripostOptionalMaildrop' DESC 'An optional email address for catch-all aliases on domains and mailboxes' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} ) # -olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.8 NAME 'fripostIsStatusActive' +olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.9 NAME 'fripostIsStatusActive' DESC 'Is the entry active?' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) # -olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.9 NAME 'fripostMailboxQuota' +olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.10 NAME 'fripostIsStatusPending' + DESC 'Is the entry pending?' + EQUALITY booleanMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) +# +olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.11 NAME 'fripostMailboxQuota' DESC 'The quota on a mailbox e.g., "50MB"' EQUALITY caseExactMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32} SINGLE-VALUE ) # -olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.10 NAME 'fripostCanCreateAlias' +olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.12 NAME 'fripostCanCreateAlias' DESC 'A user/domain that can create aliases for the parent domain' SUP distinguishedName ) # -olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.11 NAME 'fripostCanCreateList' +olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.13 NAME 'fripostCanCreateList' DESC 'A user/domain that can create lists for the parent domain' SUP distinguishedName ) # -olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.12 NAME 'fripostOwner' +olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.14 NAME 'fripostOwner' DESC 'A user that owns the parent domain' SUP distinguishedName ) # -olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.13 NAME 'fripostPostmaster' +olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.15 NAME 'fripostPostmaster' DESC 'A user that is a postmaster of the parent domain' SUP distinguishedName ) # -olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.14 NAME 'fripostListManager' +olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.16 NAME 'fripostListManager' DESC 'The list manager' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch @@ -144,6 +155,11 @@ olcObjectclasses: ( 1.3.6.1.4.1.40011.1.2.3 NAME 'FripostVirtualAlias' olcObjectclasses: ( 1.3.6.1.4.1.40011.1.2.4 NAME 'FripostVirtualList' SUP top STRUCTURAL DESC 'Virtual list' - MUST ( fvl $ fripostListManager $ fripostIsStatusActive ) - MAY ( fripostListCommand $ fripostOwner $ description ) ) + MUST ( fvl $ fripostListManager $ fripostIsStatusActive $ fripostLocalAlias ) + MAY ( fripostOwner $ description $ fripostIsStatusPending ) ) +# +olcObjectclasses: ( 1.3.6.1.4.1.40011.1.2.5 NAME 'FripostVirtualListCommand' + SUP top STRUCTURAL + DESC 'Virtual list command' + MUST ( fvlc $ fripostLocalAlias ) ) diff --git a/ldap/index.ldif b/ldap/index.ldif index f044ebe..6d720bd 100644 --- a/ldap/index.ldif +++ b/ldap/index.ldif @@ -26,11 +26,13 @@ changetype: modify replace: olcDbIndex olcDbIndex: objectClass eq - -# Let us make Postfix's job easier. +# Let us make Postfix's life easier. add: olcDbIndex -olcDbIndex: fripostIsStatusActive,fvd,fvu,fva,fvl,fripostListCommand,fripostListManager eq +olcDbIndex: fripostIsStatusActive,fvd,fvu,fva,fvl,fvlc eq +- +add: olcDbIndex +olcDbIndex: fripostIsStatusPending pres,eq - -# Let us make Postfix's job easier. add: olcDbIndex olcDbIndex: fripostOptionalMaildrop pres - diff --git a/ldap/populate.ldif b/ldap/populate.ldif index e8098fd..d0f6c0b 100644 --- a/ldap/populate.ldif +++ b/ldap/populate.ldif @@ -53,8 +53,7 @@ dn: fvl=list1,fvd=fripost.org,ou=virtual,o=mailHosting,dc=fripost,dc=dev objectClass: FripostVirtualList fripostListManager: mailman fripostIsStatusActive: TRUE -fripostListCommand: list1-request -fripostListCommand: list1-bounces +fripostLocalAlias: list1#fripost.org fripostOwner: fvu=user1,fvd=fripost.org,ou=virtual,o=mailHosting,dc=fripost,dc=dev # An independent list (for user1) @@ -65,6 +64,15 @@ fripostIsStatusActive: TRUE fripostOwner: fvu=user2,fvd=fripost.org,ou=virtual,o=mailHosting,dc=fripost,dc=dev # Buggy owner fripostOwner: fvd=fripost.org,ou=virtual,o=mailHosting,dc=fripost,dc=dev +fripostLocalAlias: list2#fripost.org + +dn: fvl=test-mailman,fvd=fripost.org,ou=virtual,o=mailHosting,dc=fripost,dc=dev +objectClass: FripostVirtualList +fripostListManager: mailman +fripostIsStatusActive: TRUE +fripostIsStatusPending: TRUE +fripostLocalAlias: test-mailman#fripost.org +fripostOwner: fvu=user1,fvd=fripost.org,ou=virtual,o=mailHosting,dc=fripost,dc=dev # An independent domain, with canCreateAlias options @@ -100,6 +108,7 @@ objectClass: FripostVirtualList fripostIsStatusActive: TRUE fripostListManager: schleuder fripostOwner: fvu=user2,fvd=fripost.org,ou=virtual,o=mailHosting,dc=fripost,dc=dev +fripostLocalAlias: list1#example2.org # An independent domain, with both can createAlias and canCreateList options @@ -115,6 +124,7 @@ objectClass: FripostVirtualList fripostIsStatusActive: TRUE fripostListManager: mailman fripostOwner: fvu=user1,fvd=fripost.org,ou=virtual,o=mailHosting,dc=fripost,dc=dev +fripostLocalAlias: list#example3.org # A owned domain @@ -137,8 +147,7 @@ dn: fvl=list,fvd=owned.org,ou=virtual,o=mailHosting,dc=fripost,dc=dev objectClass: FripostVirtualList fripostListManager: mailman fripostIsStatusActive: TRUE -fripostListCommand: list-request -fripostListCommand: list-bounces +fripostLocalAlias: list#owned.org dn: fvu=user,fvd=owned.org,ou=virtual,o=mailHosting,dc=fripost,dc=dev objectClass: FripostVirtualMailbox @@ -170,13 +179,11 @@ dn: fvl=list,fvd=postmastered.org,ou=virtual,o=mailHosting,dc=fripost,dc=dev objectClass: FripostVirtualList fripostListManager: mailman fripostIsStatusActive: TRUE -fripostListCommand: list-request -fripostListCommand: list-bounces -#FripostLocalAlias: postmastered.org#list-request +FripostLocalAlias: list#postmastered.org -#dn: fvlc=list-request,fvl=list,fvd=postmastered.org,ou=virtual,o=mailHosting,dc=fripost,dc=dev -#objectClass: FripostVirtualListCommand -#FripostLocalAlias: postmastered.org#list-request +dn: fvlc=list-request,fvl=list,fvd=postmastered.org,ou=virtual,o=mailHosting,dc=fripost,dc=dev +objectClass: FripostVirtualListCommand +FripostLocalAlias: list-request#postmastered.org dn: fvu=user,fvd=postmastered.org,ou=virtual,o=mailHosting,dc=fripost,dc=dev objectClass: FripostVirtualMailbox @@ -189,25 +196,11 @@ objectClass: FripostVirtualMailbox userPassword: bigbrother fripostIsStatusActive: TRUE -dn: fvd=xn--v4h.xn--fiqs8s,ou=virtual,o=mailHosting,dc=fripost,dc=dev -objectClass: FripostVirtualDomain -fripostIsStatusActive: TRUE -description: Test domain internalization (☮.中国) -fripostPostmaster: fvu=user1,fvd=fripost.org,ou=virtual,o=mailHosting,dc=fripost,dc=dev -fripostPostmaster: fvu=user,fvd=xn--v4h.xn--fiqs8s,ou=virtual,o=mailHosting,dc=fripost,dc=dev - -dn: fvu=user,fvd=xn--v4h.xn--fiqs8s,ou=virtual,o=mailHosting,dc=fripost,dc=dev -objectClass: FripostVirtualMailbox -fripostIsStatusActive: TRUE -userPassword: user -description: Test domain internalization (user@☮.中国). -description: Unicode is not allowed in the local part. Net::TLD doesn't - work with international TLDs. - dn: fvd=xn--v4h.net,ou=virtual,o=mailHosting,dc=fripost,dc=dev objectClass: FripostVirtualDomain fripostIsStatusActive: TRUE description: Test domain internalization (☮.net) +description: Net::TLD doesn't work with international TLDs. fripostPostmaster: fvu=user1,fvd=fripost.org,ou=virtual,o=mailHosting,dc=fripost,dc=dev fripostPostmaster: fvu=user,fvd=xn--v4h.net,ou=virtual,o=mailHosting,dc=fripost,dc=dev diff --git a/ldap/test-user-acl.sh b/ldap/test-user-acl.sh index b3fd930..12f3d14 100755 --- a/ldap/test-user-acl.sh +++ b/ldap/test-user-acl.sh @@ -11,7 +11,9 @@ SLAPACL=/usr/sbin/slapacl -SUFFIX="ou=virtual,o=mailHosting,dc=fripost,dc=dev" +SUFFIXV="ou=virtual,o=mailHosting,dc=fripost,dc=dev" +SUFFIXS="ou=services,o=mailHosting,dc=fripost,dc=dev" +SUFFIX="${SUFFIXV}" RES=$(tempfile) || exit 1 @@ -19,7 +21,7 @@ checkACL () { CMD=${SLAPACL} BIND="${1},${SUFFIX}" if [ -n "${1}" ]; then CMD="${CMD} -D ${BIND}"; fi - if [ -n "${2}" ]; then BASE="${2},${SUFFIX}"; else BASE="${SUFFIX}"; fi + if [ -n "${2}" ]; then BASE="${2},${SUFFIXV}"; else BASE="${SUFFIXV}"; fi shift; shift ${CMD} -b "${BASE}" "$@" 2>&1 | grep -vixF -e "authcDN: \"${BIND}\"" @@ -74,6 +76,10 @@ ALIASES=$(search -u -b "${SUFFIX}" "objectClass=FripostVirtualAlias" dn | \ grep -i '^ufn: ' | sed -re 's/^ufn: ([^,]+), *([^,]+),.*/fva=\1,fvd=\2/') LISTS=$(search -u -b "${SUFFIX}" "objectClass=FripostVirtualList" dn | \ grep -i '^ufn: ' | sed -re 's/^ufn: ([^,]+), *([^,]+),.*/fvl=\1,fvd=\2/') +LISTSC=$(search -u -b "${SUFFIX}" "objectClass=FripostVirtualListCommand" dn | \ + grep -i '^ufn: ' | sed -re 's/^ufn: ([^,]+), *([^,]+), *([^,]+),.*/fvlc=\1,fvl=\2,fvd=\3/') + +OPERATTRS="structuralObjectClass entryUUID createTimestamp entryCSN modifiersName modifyTimestamp" ######################################################################## @@ -150,7 +156,7 @@ usersB children | isOK '=z$' children msg "Have =0 access to the operational attributes" -usersB structuralObjectClass entryUUID createTimestamp entryCSN modifiersName modifyTimestamp | isOK '=0$' entryUUID +usersB ${OPERATTRS} | isOK '=0$' entryUUID [ $? -eq 0 ] || exit $? @@ -224,7 +230,7 @@ usersD entry/search fripostOwner/search fripostPostmaster/search | isOK 'ALLOWED [ $? -eq 0 ] || exit $? msg "Have =0 access to the operational attributes" -usersD structuralObjectClass entryUUID createTimestamp entryCSN modifiersName modifyTimestamp | isOK '=0$' entryUUID +usersD ${OPERATTRS} | isOK '=0$' entryUUID [ $? -eq 0 ] || exit $? @@ -478,7 +484,7 @@ usersU entry/read entry/search entry/disclose fvu/read \ [ $? -eq 0 ] || exit $? msg "Have =0 access to their \"children\" and operational attributes" -usersU children structuralObjectClass entryUUID createTimestamp entryCSN modifiersName modifyTimestamp | isOK '=0$' children +usersU children ${OPERATTRS} | isOK '=0$' children [ $? -eq 0 ] || exit $? msg "Have =s access to \"objectClass\"" @@ -532,7 +538,7 @@ usersP entry | isOK '=arsd$' entry [ $? -eq 0 ] || exit $? msg "Have =0 access to their users' \"children\" and operational attributes (if Postmaster)" -usersP children structuralObjectClass entryUUID createTimestamp entryCSN modifiersName modifyTimestamp | isOK '=0$' children +usersP children ${OPERATTRS} | isOK '=0$' children [ $? -eq 0 ] || exit $? @@ -578,7 +584,7 @@ usersA fripostOwner/search entry/search | isOK 'ALLOWED$' entry msg "Have =0 access to the \"children\" and operational attributes" -usersA children structuralObjectClass entryUUID createTimestamp entryCSN modifiersName modifyTimestamp | isOK '=0$' children +usersA children ${OPERATTRS} | isOK '=0$' children [ $? -eq 0 ] || exit $? msg "Have =s access to \"objectClass\"" @@ -701,7 +707,7 @@ echo "Authenticated users, access to list entries" # * entry: # =s for all # +a if canCreateList, domain owner or domain postmaster -# +zrd if list owner, domain owner or domain postmaster +# +rd if list owner, domain owner or domain postmaster # * children: # =0 for all # * fvl: @@ -710,7 +716,7 @@ echo "Authenticated users, access to list entries" # =rscd if list owner, domain owner or domain postmaster # * fripostIsStatusActive: # =wrscd if list owner, domain owner or domain postmaster -# * fripostListCommand: +# * fripostIsStatusPending: # =rscd if list owner, domain owner or domain postmaster # * fripostOwner: # =d for all @@ -734,40 +740,48 @@ usersL fripostOwner/search entry/search | isOK 'ALLOWED$' entry msg "Have =0 access the \"children\" and operational attributes" -usersL children structuralObjectClass entryUUID createTimestamp entryCSN modifiersName modifyTimestamp | isOK '=0$' children +usersL children ${OPERATTRS} | isOK '=0$' children [ $? -eq 0 ] || exit $? -msg "Cannot change transport-related attributes" +msg "Cannot change transport" for U in ${USERS}; do for L in ${LISTS}; do - checkACL "${U}" "${L}" fripostListCommand/add fripostListCommand/delete \ - fripostListManager/write + checkACL "${U}" "${L}" fripostListManager/write done done | isOK 'DENIED$' fripostListManager [ $? -eq 0 ] || exit $? -ATTRS="entry/read entry/disclose entry/delete +msg "Cannot edit pending status; Cannot delete entry" +for U in ${USERS}; do + for L in ${LISTS}; do + checkACL "${U}" "${L}" fripostIsStatusPending/write entry/delete + done +done | isOK 'DENIED$' fripostIsStatusPending +[ $? -eq 0 ] || exit $? + + +ATTRS="entry/read entry/disclose fvl/write fvl/read fvl/search fvl/compare fvl/disclose fripostListManager/read fripostListManager/search fripostListManager/compare fripostListManager/disclose fripostIsStatusActive/write fripostIsStatusActive/read fripostIsStatusActive/search fripostIsStatusActive/compare fripostIsStatusActive/disclose - fripostListCommand/read fripostListCommand/search fripostListCommand/compare fripostListCommand/disclose + fripostIsStatusPending/read fripostIsStatusPending/search fripostIsStatusPending/compare fripostIsStatusPending/disclose fripostOwner/read fripostOwner/compare fripostOwner/disclose description/add description/delete description/read description/compare description/disclose" ATTRS2="fripostOwner/add fripostOwner/delete" -msg "Can edit/delete list (if list Owner)" +msg "Can edit list (if list Owner)" for U in ${USERS}; do for L in ${LISTS}; do search -s base -b "${L},${SUFFIX}" "fripostOwner=${U},${SUFFIX}" | grep -q '^dn: ' && \ checkACL "${U}" "${L}" ${ATTRS} done -done | isOK 'ALLOWED$' entry delete +done | isOK 'ALLOWED$' entry read [ $? -eq 0 ] || exit $? -msg "Can edit/create/delete list (if domain Owner)" +msg "Can edit/create list (if domain Owner)" [ $? -eq 0 ] || exit $? for U in ${USERS}; do for L in ${LISTS}; do @@ -779,7 +793,7 @@ done | isOK 'ALLOWED$' entry add [ $? -eq 0 ] || exit $? -msg "Can edit/create/delete list (if domain Postmaster)" +msg "Can edit/create list (if domain Postmaster)" [ $? -eq 0 ] || exit $? for U in ${USERS}; do for L in ${LISTS}; do @@ -855,9 +869,169 @@ for U in ${USERS}; do done | isOK 'DENIED$' entry delete [ $? -eq 0 ] || exit $? +msg "Have =0 access to the list command entries" +for U in ${USERS}; do + for LC in ${LISTSC}; do + checkACL "${U}" "${LC}" + done +done | grep -Ev '^(objectClass|creatorsName)=' | isOK '=0$' entry +[ $? -eq 0 ] || exit $? ########################################################################### +SUFFIX="${SUFFIXS}" + +echo +echo "Service SMTP" + +msg "Can read and search the domain attributes it needs" +for D in ${DOMAINS}; do + checkACL "cn=SMTP" "${D}" entry objectClass fvd fripostIsStatusActive fripostOptionalMaildrop +done | isOK '=rsd$' entry + +msg "Have =0 access on other domain attributes" +for D in ${DOMAINS}; do + checkACL "cn=SMTP" "${D}" children ${OPERATTRS} fripostCanCreateAlias fripostCanCreateList fripostOwner fripostPostmaster description +done | isOK 'none(=0)$' children + +msg "Can read and search the mailbox attributes it needs" +for U in ${USERS}; do + checkACL "cn=SMTP" "${U}" entry objectClass fvu fripostIsStatusActive fripostOptionalMaildrop +done | isOK '=rsd$' entry + +msg "Have =0 access on other mailbox attributes" +for U in ${USERS}; do + checkACL "cn=SMTP" "${U}" children ${OPERATTRS} userPassword fripostMailboxQuota description +done | isOK 'none(=0)$' children + +msg "Can read and search the alias attributes it needs" +for A in ${ALIASES}; do + checkACL "cn=SMTP" "${A}" entry objectClass fva fripostMaildrop fripostIsStatusActive +done | isOK '=rsd$' entry + +msg "Have =0 access on other alias attributes" +for A in ${ALIASES}; do + checkACL "cn=SMTP" "${A}" children ${OPERATTRS} fripostOwner description +done | isOK 'none(=0)$' children + +msg "Can read and search the list attributes it needs" +for L in ${LISTS}; do + checkACL "cn=SMTP" "${L}" entry objectClass fvl fripostIsStatusActive fripostLocalAlias fripostIsStatusPending +done | isOK '=rsd$' entry + +msg "Have =0 access on other list attributes" +for L in ${LISTS}; do + checkACL "cn=SMTP" "${L}" children ${OPERATTRS} fripostListManager fripostOwner description +done | isOK 'none(=0)$' children + +msg "Can read and search the list command attributes it needs" +for LC in ${LISTSC}; do + checkACL "cn=SMTP" "${LC}" entry objectClass fvlc fripostIsStatusActive fripostLocalAlias +done | isOK '=rsd$' entry + +msg "Have =0 access on other list command attributes" +for LC in ${LISTSC}; do + checkACL "cn=SMTP" "${LC}" children ${OPERATTRS} +done | isOK 'none(=0)$' children + + +########################################################################### + +echo +echo "Service ListCreator" + +msg "Have =0 access on domain attributes" +for D in ${DOMAINS}; do + checkACL "cn=ListCreator" "${D}" entry children ${OPERATTRS} fvd fripostIsStatusActive fripostOptionalMaildrop fripostCanCreateAlias fripostCanCreateList fripostOwner fripostPostmaster description +done | isOK '=0$' entry + +msg "Have =0 access on mailbox attributes" +for U in ${USERS}; do + checkACL "cn=ListCreator" "${U}" entry children ${OPERATTRS} fvu userPassword fripostIsStatusActive fripostMailboxQuota fripostOptionalMaildrop description +done | isOK '=0$' entry + +msg "Have =0 access on alias attributes" +for A in ${ALIASES}; do + checkACL "cn=ListCreator" "${A}" entry children ${OPERATTRS} fva fripostMaildrop fripostIsStatusActive fripostOwner description +done | isOK '=0$' entry + +msg "Have =zrd access on lists' pending status" +for L in ${LISTS}; do + checkACL "cn=ListCreator" "${L}" fripostIsStatusPending +done | isOK '=zrd$' + +msg "Have =rsd access on lists' entry attribute" +for L in ${LISTS}; do + checkACL "cn=ListCreator" "${L}" entry +done | isOK '=rsd$' + +msg "Have =a access on lists' children attribute" +for L in ${LISTS}; do + checkACL "cn=ListCreator" "${L}" children +done | isOK '=a$' + +msg "Have =0 access on other list attributes" +for L in ${LISTS}; do + checkACL "cn=ListCreator" "${L}" ${OPERATTRS} fvl fripostListManager fripostIsStatusActive fripostLocalAlias fripostOwner description +done | isOK '=0$' fvl + +msg "Have =a access on list commands' entry attribute" +for LC in ${LISTSC}; do + checkACL "cn=ListCreator" "${LC}" entry +done | isOK '=a$' + +msg "Have =0 access on other list command attributes" +for LC in ${LISTSC}; do + checkACL "cn=ListCreator" "${LC}" children ${OPERATTRS} fvlc fripostLocalAlias +done | isOK '=0$' children + + +########################################################################### + +echo +echo "Service AdminWebPanel" + +msg "Have =0 access on domain attributes" +for D in ${DOMAINS}; do + checkACL "cn=AdminWebPanel" "${D}" entry children ${OPERATTRS} fvd fripostIsStatusActive fripostOptionalMaildrop fripostCanCreateAlias fripostCanCreateList fripostOwner fripostPostmaster description +done | isOK 'none(=0)$' entry + +msg "Have =0 access on mailbox attributes" +for U in ${USERS}; do + checkACL "cn=AdminWebPanel" "${U}" entry children ${OPERATTRS} fvu userPassword fripostIsStatusActive fripostMailboxQuota fripostOptionalMaildrop description +done | isOK 'none(=0)$' entry + +msg "Have =0 access on alias attributes" +for A in ${ALIASES}; do + checkACL "cn=AdminWebPanel" "${A}" entry children ${OPERATTRS} fva fripostMaildrop fripostIsStatusActive fripostOwner description +done | isOK 'none(=0)$' entry + +msg "Have =0 access on list attributes" +for L in ${LISTS}; do + checkACL "cn=AdminWebPanel" "${L}" entry children ${OPERATTRS} fvl fripostListManager fripostIsStatusActive fripostLocalAlias fripostOwner description fripostIsStatusPending +done | isOK 'none(=0)$' entry + +msg "Have =0 access on other list command attributes" +for LC in ${LISTSC}; do + checkACL "cn=AdminWebPanel" "${LC}" entry children ${OPERATTRS} fvlc fripostLocalAlias +done | isOK 'none(=0)$' entry + +if sudo -u fpanel klist >/dev/null; then + msg "Can SASL authenticate (GSSAPI)" + DN=$(echo "dn:cn=AdminWebPanel,${SUFFIXS}" | tr [A-Z] [a-z]) + DN2=$(sudo -u fpanel ldapwhoami -Q | tr [A-Z] [a-z]) + if [ "${DN}" = "${DN2}" ]; then echo ok; else echo fail; fi | isOK '^ok$' + + msg "Can proxy authorize" + for U in ${USERS}; do + DN=$(echo "dn:${U},${SUFFIXV}" | tr [A-Z] [a-z]) + DN2=$(sudo -u fpanel ldapwhoami -Q -X "${DN}" | tr [A-Z] [a-z]) + if [ "${DN}" = "${DN2}" ]; then echo ok; else echo fail; fi + done | isOK '^ok$' +else + echo "WARN: No valid ticket found. Didn't check SSAL authentication" +fi + rm "${RES}" |