Presently the directory server supports only simple authentication and anonymous binds while storing passwords in clear text within userPassword attributes in user entries.
Within a short while we'll be able to store passwords using the authPassword property which uses strong one way hashes for authentication such as MD5 and SHA1. These schemes and the schema used are described in detail here in RFC 3112.
So you just downloaded the server and fired her up. Now you're wondering how to get an LDAP client like jxplorer, gq, or ldapbrowser to bind to the server over the wire.
By default the super user or admin account is created when the system partition is created under the ou=system naming context. This occurs when the server is started for the first time. The admin user can be found under the following DN:
uid=admin,ou=system
The password is initially set to secret. You might want to change this after starting the server. So you can bind to the server as this user with secret as the password for the first time.
If you did not disable anonymous binds by setting the respective property (described below), then you can bind anonymously to the server without any username or password.
A user in the server is any entry with a userPassword attribute that
contains a clear text password. The DN can be anything reachable
within one of the directory partitions. So if you add a partition to
hang off of dc=example,dc=com
then you can add user
entries anywhere under this naming context or just add user entries
under the ou=system
naming context. Above is an LDIF of
a user you can add to the directory as a test user.
dn: uid=jdoe,ou=users,ou=system cn: John Doe sn: Doe givenname: John objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson ou: Human Resources ou: People l: Las Vegas uid: jdoe mail: jdoe@apachecon.comm telephonenumber: +1 408 555 5555 facsimiletelephonenumber: +1 408 555 5556 roomnumber: 4613 userpassword: test
You can download this newuser.ldif file and
use it to add the user. If you are lazy another test user,
uid=akarasulu, ou=users, ou=system
already exists within the
directory. It is created by default. Simply replace jdoe's DN with
akarasulu's DN to search for this user and bind as this user. Below
we use the ldapadd OpenLDAP client to import the LDIF file presuming
the server was started on port 1024 on the localhost:
ldapadd -a -D 'uid=admin,ou=system' -f newuser.ldif -h localhost -p 1024 -x -w secret
You can confirm the add/import by performing a search for the user. This time using the OpenLDAP search client you use the following command:
ldapsearch -D 'uid=admin,ou=system' -h localhost -p 1024 -x -w secret -s one -b 'ou=users,ou=system' '(uid=jdoe)'
You can start searching the directory using this new user like so:
ldapsearch -D 'uid=jdoe,ou=users,ou=system' -h localhost -p 1024 -x -w test -s one -b 'ou=system' '(objectClass=*)'
At the moment there's a sweet spot for new users. This sweet
spot is immediately under the ou=users,ou=system context. Users
created here are hard protected right now. The server does not have
a formal authorization mechanism in place yet to protect entries from
other users. Authorization rules have been hardcoded into the system
for now to control access to user entries under ou=users,
ou=system
. Only the admin and the user him/her self can
access their entries for reads. Users cannot modify their group
membership properties but can change their own passwords. They do
not see each other's accounts at all. The admin is the only one that
can read and write anything.
So in the interim you're best off adding your users to this area to prevent others from reading clear text password stored in userPassword fields.
Note that anonymous binds and binds as users show different views of the ou=system naming context. So don't freak out if you don't see the usual suspects when binding anonymously! Anonymous users cannot see the admin account or any other user accounts. Users other than admin cannot see the admin account and can only see one user account: their own. The admin sees everything and can alter or remove any entry.
Anonymous binds come enabled out of the box. So you might want to turn off this feature especially since you cannot protect much of your data at the present moment from access using authorization rules. To do so you're going to have to restart the server while disallowing these binds. The server.disable.anonymous property when present as a key in the enviroment (regardless of value) will disable access by anonymous users. This applies to authentication via LDAP clients over the wire and via JNDI caller through the JNDI provider.
Authenticator SPI provides a way to implement your own authentication mechanism, for instance simple mechanism using password encryption such as MD5 or SHA1, or SASL mechanism. See the following example:
import javax.naming.NamingException; import org.apache.ldap.server.auth.AbstractAuthenticator; import org.apache.ldap.server.auth.LdapPrincipal; import org.apache.ldap.server.jndi.ServerContext; import org.apache.ldap.common.exception.LdapNoPermissionException; import org.apache.ldap.common.name.LdapName; public class MyAuthenticator extends AbstractAuthenticator { public MyAuthenticator( ) { // create authenticator that will handle "simple" authentication mechanism super( "simple" ); } public void init() throws NamingException { ... } public LdapPrincipal authenticate( ServerContext ctx ) throws NamingException { ... // return the authorization id LdapName principalDn = new LdapName( dn ); return new LdapPrincipal( principalDn ); } }
The authenticator class has to extend the org.apache.ldap.server.auth.AbstractAuthenticator. This class needs to have a no-argument constructor that calls the super() constructor with parameter the authentication mechanism it is going to handle. In the above example, MyAuthenticator class is going to handle the simple authentication mechanism. To implement a SASL mechanism you need to call super() with the name of the SASL mechanism, e.g. super( "DIGEST-MD5" ).
You can optionally implement the init() method to initialize your authenticator class. This will be called when the authenticator is loaded by ApacheDS during start-up.
When a client performs an authentication, ApacheDS will call the authenticate() method. You can get the client authentication info from the server context. After you authenticate the client, you need to return the authorization id. If the authentication fails, you should throw an LdapNoPermissionException.
When there are multiple authenticators registered with the same authentication type, ApacheDS will try to use them in the order it was registered. If one fails it will use the next one, until it finds one that successfully authenticates the client.
To tell ApacheDS to load your custom authenticators, you need to specify it in the JNDI Properties. You can also optionally specify the location of a .properties file containing the initialization parameters. See the following example:
server.authenticators=myauthenticator yourauthenticator server.authenticator.class.myauthenticator=com.mycompany.MyAuthenticator server.authenticator.properties.myauthenticator=myauthenticator.properties server.authenticator.class.yourauthenticator=com.yourcompany.YourAuthenticator server.authenticator.properties.yourauthenticator=yourauthenticator.properties