| <?xml version="1.0" encoding="UTF-8"?> |
| <document> |
| <properties> |
| <author email="akarasulu@apache.org">Alex Karasulu</author> |
| <title>Server Authentication</title> |
| </properties> |
| |
| <body> |
| |
| <section name="Server Authentication"> |
| <subsection name="Status"> |
| <p> |
| Presently the directory server supports only simple authentication |
| and anonymous binds while storing passwords in clear text within |
| userPassword attributes in user entries. |
| </p> |
| |
| <p> |
| 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 <a href= |
| "http://www.faqs.org/rfcs/rfc3112.html">RFC 3112</a>. |
| </p> |
| </subsection> |
| |
| <subsection name="What password do I use?"> |
| <p> |
| 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. |
| </p> |
| |
| <p> |
| 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: |
| </p> |
| |
| <source> |
| uid=admin,ou=system |
| </source> |
| |
| <p> |
| The password is initially set to <b>secret</b>. You might want to |
| change this after starting the server. So you can bind to the server |
| as this user with <b>secret</b> as the password for the first time. |
| </p> |
| |
| <p> |
| 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. |
| </p> |
| </subsection> |
| |
| <subsection name="Adding and authenticating normal users"> |
| <p> |
| 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 <code>dc=example,dc=com</code> then you can add user |
| entries anywhere under this naming context or just add user entries |
| under the <code>ou=system</code> naming context. Above is an LDIF of |
| a user you can add to the directory as a test user. |
| </p> |
| |
| <source> |
| 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 |
| </source> |
| |
| <p> |
| You can download this <a href="newuser.ldif">newuser.ldif</a> file and |
| use it to add the user. If you are lazy another test user, <code> |
| uid=akarasulu, ou=users, ou=system</code> 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: |
| </p> |
| |
| <source> |
| ldapadd -a -D 'uid=admin,ou=system' -f newuser.ldif -h localhost -p 1024 -x -w secret |
| </source> |
| |
| <p> |
| 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: |
| </p> |
| |
| <source> |
| ldapsearch -D 'uid=admin,ou=system' -h localhost -p 1024 -x -w secret -s one |
| -b 'ou=users,ou=system' '(uid=jdoe)' |
| </source> |
| |
| <p> |
| You can start searching the directory using this new user like so: |
| </p> |
| |
| <source> |
| ldapsearch -D 'uid=jdoe,ou=users,ou=system' -h localhost -p 1024 -x -w test -s one -b 'ou=system' '(objectClass=*)' |
| </source> |
| |
| </subsection> |
| |
| <subsection name="Protecting User Passwords"> |
| <p> |
| 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 <code>ou=users, |
| ou=system</code>. 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. |
| </p> |
| |
| <p> |
| 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. |
| </p> |
| |
| <p> |
| 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. |
| </p> |
| </subsection> |
| |
| <subsection name="Disabling Anonymous Binds"> |
| <p> |
| 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 <b>server.disable.anonymous</b> 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. |
| </p> |
| </subsection> |
| |
| <subsection name="Custom Authenticator"> |
| <p> |
| 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: |
| </p> |
| |
| <source> |
| 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 ); |
| } |
| } |
| </source> |
| |
| <p> |
| 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" ). |
| </p> |
| |
| <p> |
| 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. |
| </p> |
| |
| <p> |
| 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. |
| </p> |
| |
| <p> |
| 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. |
| </p> |
| |
| <p> |
| 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: |
| </p> |
| |
| <source> |
| 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 |
| </source> |
| </subsection> |
| |
| </section> |
| </body> |
| </document> |