1,084
edits
Technician (talk | contribs) (Created page with "The member database of the FeministWiki is stored via LDAP. The basic structure looks like this: dc=feministwiki,dc=org ou=members - cn=''username'' objectCl...") |
Technician (talk | contribs) |
||
(7 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
The member database of the FeministWiki is stored via LDAP. The basic structure looks like this: | The member database of the FeministWiki is stored via LDAP. This page explains some details about the setup. | ||
=== Structure === | |||
The basic structure looks like this: | |||
dc=feministwiki,dc=org | dc=feministwiki,dc=org | ||
Line 34: | Line 38: | ||
* The <code>fwRecoveryMail</code> field may hold a mail address that will be used for password reset requests. It's different from the primary mail address because that one may be the member's FeministWiki address, which they can't access if they've lost their password. | * The <code>fwRecoveryMail</code> field may hold a mail address that will be used for password reset requests. It's different from the primary mail address because that one may be the member's FeministWiki address, which they can't access if they've lost their password. | ||
* The <code>manager</code> contains the DN (distinguished name) of the member who added the member. It may be empty for special member accounts like "Administrator" or the "Deleted" pseudo-account. | * The <code>manager</code> contains the DN (distinguished name) of the member who added the member. It may be empty for special member accounts like "Administrator" or the "Deleted" pseudo-account. | ||
=== Read-only user === | |||
For security purposes, it's a good idea to have a "read-only" user for LDAP read operations, instead of using the admin for everything. | |||
# Add read-only user | |||
ldapadd -xy ~/pwd/ldap <<EOF | |||
dn: cn=readonly,dc=feministwiki,dc=org | |||
objectClass: simpleSecurityObject | |||
objectClass: organizationalRole | |||
cn: readonly | |||
description: Read-only user | |||
EOF | |||
No fiddling with access control is needed, since read-only access is the default. | |||
=== Custom objectClass === | === Custom objectClass === | ||
The following | The following command creates the <code>fwMember</code> object class. | ||
ldapadd -Y external -H ldapi:// <<EOF | |||
dn: cn=feministwiki,cn=schema,cn=config | dn: cn=feministwiki,cn=schema,cn=config | ||
objectClass: olcSchemaConfig | objectClass: olcSchemaConfig | ||
Line 54: | Line 73: | ||
STRUCTURAL | STRUCTURAL | ||
MAY ( fwRecoveryMail ) ) | MAY ( fwRecoveryMail ) ) | ||
EOF | |||
=== Attribute permissions === | === Attribute permissions === | ||
We want | We want to make the following changes to the default LDAP permissions: | ||
* Members should be able to change their own display name (<code>sn</code>) and e-mail address (<code>mail</code>). | |||
* The read-only user should be able to find users via the combination of their username and recovery mail address (<code>fwRecoveryMail</code>), but not actually see their recovery mail addresses. (The password reset mechanism uses this.) | |||
* Members should not be able to see who a member was added by (the <code>manager</code> field). | |||
The following command makes the necessary access control changes: | |||
ldapmodify -Y external -H ldapi:// <<EOF | |||
dn: olcDatabase={1}mdb,cn=config | dn: olcDatabase={1}mdb,cn=config | ||
changetype: modify | changetype: modify | ||
Line 65: | Line 91: | ||
olcAccess: {2}to attrs=sn,mail by self write | olcAccess: {2}to attrs=sn,mail by self write | ||
olcAccess: {3}to attrs=fwRecoveryMail by self write by dn.exact="cn=readonly,dc=feministwiki,dc=org" search | olcAccess: {3}to attrs=fwRecoveryMail by self write by dn.exact="cn=readonly,dc=feministwiki,dc=org" search | ||
olcAccess: {4}to attrs=manager by self read | |||
EOF | |||
=== Password | Note that <code>olcAccess</code> entries are evaluated in order, and the first match takes effect. This can affect performance. In the statement above, we start inserting entries from index 2, because indexes 0 and 1 already have some meaningful default entries. | ||
=== Password policy === | |||
To make sure passwords are stored with the <code>{SSHA}</code> scheme rather than plain text, the <code>ppolicy</code> "password policy overlay" is used. ZYTRAX has a very nice book about LDAP which documents how to enable this: http://www.zytrax.com/books/ldap/ch6/ppolicy.html | To make sure passwords are stored with the <code>{SSHA}</code> scheme rather than plain text, the <code>ppolicy</code> "password policy overlay" is used. ZYTRAX has a very nice book about LDAP which documents how to enable this: http://www.zytrax.com/books/ldap/ch6/ppolicy.html | ||
Line 74: | Line 103: | ||
# Add the ppolicy schema | # Add the ppolicy schema | ||
ldapadd -Y external -H ldapi: | ldapadd -Y external -H ldapi:// < /etc/ldap/schema/ppolicy.ldif | ||
# Enable the ppolicy dynamic module | # Enable the ppolicy dynamic module | ||
ldapmodify -Y external -H ldapi: | ldapmodify -Y external -H ldapi:// <<EOF | ||
dn: cn=module{0},cn=config | dn: cn=module{0},cn=config | ||
changetype: modify | changetype: modify | ||
Line 85: | Line 114: | ||
# Add the ppolicy overlay with olcPPolicyHashCleartext set to TRUE | # Add the ppolicy overlay with olcPPolicyHashCleartext set to TRUE | ||
ldapadd -Y external -H ldapi: | ldapadd -Y external -H ldapi:// <<EOF | ||
dn: olcOverlay=ppolicy,olcDatabase={1}mdb,cn=config | dn: olcOverlay=ppolicy,olcDatabase={1}mdb,cn=config | ||
objectClass: olcPPolicyConfig | objectClass: olcPPolicyConfig | ||
olcOverlay: ppolicy | olcOverlay: ppolicy | ||
olcPPolicyHashCleartext: TRUE | olcPPolicyHashCleartext: TRUE | ||
EOF | |||
Further, <code>ppolicy</code> is used to enable brute-force protection. For this, we need to add an entry of the object class <code>pwdPolicy</code> to the directory, add attributes related to brute-force protection, and then set it as the default password policy: | |||
# Add an OU for password policies | |||
ldapadd -xy ~/pwd/ldap <<EOF | |||
dn: ou=pwdPolicies,dc=feministwiki,dc=org | |||
objectClass: organizationalUnit | |||
ou: pwdPolicies | |||
EOF | |||
# Add the pwdPolicy object | |||
ldapadd -xy ~/pwd/ldap <<EOF | |||
dn: cn=default,ou=pwdPolicies,dc=feministwiki,dc=org | |||
objectClass: applicationProcess | |||
objectClass: pwdPolicy | |||
cn: default | |||
pwdAttribute: userPassword | |||
pwdLockout: TRUE | |||
pwdLockoutDuration: 3600 | |||
pwdMaxFailure: 10 | |||
pwdFailureCountInterval: 3600 | |||
EOF | |||
# Set it as the default password policy | |||
ldapmodify -Y external -H ldapi:// <<EOF | |||
dn: olcOverlay={0}ppolicy,olcDatabase={1}mdb,cn=config | |||
changetype: modify | |||
add: olcPPolicyDefault | |||
olcPPolicyDefault: cn=default,ou=pwdPolicies,dc=feministwiki,dc=org | |||
EOF | |||
With these settings, ten consecutive authentication failures with a username will lock the account for an hour. Login failures are also cleared after an hour. This means it's possible to try ten passwords per hour during a brute-force attack, which won't get the attacker very far. | |||
=== Time of last login === | |||
The <code>lastbind</code> module of OpenLDAP keeps track of when a user last logged in. | |||
# Load the module | |||
ldapmodify -Y external -H ldapi:// <<EOF | |||
dn: cn=module{0},cn=config | |||
changetype: modify | |||
add: olcModuleLoad | |||
olcModuleLoad: lastbind | |||
EOF | |||
# Enable the overlay | |||
ldapadd -Y external -H ldapi:// <<EOF | |||
dn: olcOverlay=lastbind,olcDatabase={1}mdb,cn=config | |||
objectClass: olcLastBindConfig | |||
olcOverlay: lastbind | |||
olcLastBindPrecision: 60 | |||
EOF | EOF |