aboutsummaryrefslogtreecommitdiffstats
path: root/ldap
diff options
context:
space:
mode:
Diffstat (limited to 'ldap')
-rw-r--r--ldap/acl.ldif90
-rw-r--r--ldap/authz.ldif10
-rw-r--r--ldap/base.ldif19
-rw-r--r--ldap/constraint.ldif3
-rw-r--r--ldap/fripost.ldif44
-rw-r--r--ldap/index.ldif8
-rw-r--r--ldap/populate.ldif43
-rwxr-xr-xldap/test-user-acl.sh212
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}"