Você está na página 1de 143

ApacheDS Advanced User

Guide v1.5.8-SNAPSHOT
Draft Draft

ApacheDS Advanced User Guide v1.5.8-SNAPSHOT


Copyright © 2003-2010 The Apache Software Foundation

Licensed to the Apache Software Foundation (ASF) under one


or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,


software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.

2
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Draft

Table of Contents
Work in progress ......................................................................................................... xi
1. Community .............................................................................................................. 1
1.1. Reporting Bugs .............................................................................................. 1
1.1.1. Introduction ......................................................................................... 1
1.1.2. Creating a testcase project: using the apacheds-archetype-testcase .................. 1
1.1.3. Installing the apacheds-archetype-testcase ................................................. 1
1.1.4. Invoking (running) the archetype: generating the testcase project ................... 1
1.1.4.1. For IDEA ................................................................................. 2
1.1.4.2. For Eclipse ............................................................................... 3
1.1.4.3. For Netbeans ............................................................................. 3
1.1.5. Note about version ............................................................................... 3
1.1.6. Why a Maven Archetype for Testing? ...................................................... 3
1.2. Building trunks ............................................................................................... 3
1.2.1. Project Hierarchy ................................................................................. 4
1.2.2. Prerequisites for building ....................................................................... 4
1.2.2.1. Maven ..................................................................................... 4
1.2.2.2. JDK 5 ...................................................................................... 4
1.2.3. Getting the code ................................................................................... 4
1.2.4. Building the trunks ............................................................................... 5
1.2.4.1. Enabling Snapshot Repositories .................................................... 5
1.2.4.2. Building the trunks .................................................................. 6
1.2.5. Building the installers ........................................................................... 6
1.2.6. Starting the server without installation ...................................................... 6
1.2.7. Integration test ..................................................................................... 6
1.2.8. Eclipse ............................................................................................... 7
1.2.8.1. Building eclipse files .................................................................. 7
1.2.8.2. Maven settings .......................................................................... 7
1.2.8.3. Eclipse hints ............................................................................. 7
1.2.8.4. Eclipse plugins .......................................................................... 7
1.2.8.5. Coding standards ....................................................................... 7
1.3. Contributing ................................................................................................... 7
2. Architecture .............................................................................................................. 8
2.1. Architectural Overview .................................................................................... 8
2.1.1. Partitions ............................................................................................ 8
2.2. Interceptors .................................................................................................... 8
2.2.1. What is it? .......................................................................................... 8
2.2.2. How does it work? ............................................................................... 8
2.2.3. JNDI Implementation ............................................................................ 8
2.2.4. The nexus proxy object ......................................................................... 9
2.2.5. Operation handling within interceptors .................................................... 10
2.2.6. Bind Operation ................................................................................... 11
2.2.7. Normalization interceptor ..................................................................... 11
2.2.8. Authentication interceptor .................................................................... 12
2.2.9. Add operation .................................................................................... 12
2.3. The Administrative Model .............................................................................. 12
2.3.1. Introduction ....................................................................................... 12
2.3.2. What exactly are subentries? ................................................................. 13
2.3.3. Administrative Areas, Entries and Points ................................................. 13
2.3.4. How are administrative areas defined? .................................................... 14
2.3.5. Subentries under an IAA or an AAA ...................................................... 15
2.3.6. Base parameter ................................................................................... 15
2.3.7. Chop parameters ................................................................................. 15
2.3.7.1. chopBefore and chopAfter ......................................................... 15
2.3.7.2. minimum and maximum ............................................................ 15
2.3.8. Specification filter parameter ................................................................ 16

iii
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft ApacheDS Advanced User Draft
Guide v1.5.8-SNAPSHOT

2.3.9. Subentry types in ApacheDS ................................................................. 16


2.3.10. How to specify a subentry's subtreeSpecification ..................................... 16
2.3.11. Future Possibilities ............................................................................ 18
2.3.12. Conclusions ..................................................................................... 18
2.4. Supported RFCs ............................................................................................ 18
3. Authentication & Authorization .................................................................................. 25
3.1. SASL Authentication to ApacheDS .................................................................. 25
3.1.1. Introduction ....................................................................................... 25
3.1.2. Architecture ....................................................................................... 25
3.1.3. CRAM-MD5 ...................................................................................... 25
3.1.4. DIGEST-MD5 .................................................................................... 25
3.1.5. GSSAPI ............................................................................................ 26
3.1.6. Anonymous queries ............................................................................. 26
3.1.7. SASL queries ..................................................................................... 26
3.1.8. Resources .......................................................................................... 26
3.2. HOWTO do SASL GSSAPI Authentication to ApacheDS ..................................... 27
3.2.1. Introduction ....................................................................................... 27
3.2.2. Getting Started ................................................................................... 27
3.3. Start TLS with ApacheDS .............................................................................. 31
3.3.1. Introduction ....................................................................................... 31
3.3.2. Testing LDAP binds with TLS .............................................................. 31
3.3.3. Resources .......................................................................................... 31
3.4. Writing a custom authenticator ........................................................................ 31
3.4.1. Using custom authenticators ................................................................. 31
3.5. Authorization ................................................................................................ 32
3.5.1. Enabling Basic Access Controls ............................................................ 32
3.5.2. Types of ACI (Access Control Information) ............................................. 33
3.5.2.1. Entry ACI ............................................................................... 33
3.5.2.2. Prescriptive ACI ...................................................................... 33
3.5.2.3. Subentry ACI .......................................................................... 33
3.5.3. Some Simple Examples ....................................................................... 33
3.5.3.1. ACI Trails .............................................................................. 34
3.5.4. ACAreas ........................................................................................... 34
3.5.4.1. Introduction ............................................................................. 34
3.5.4.2. Creating Access Control Specific Areas (ACSA) ............................ 34
3.5.4.2.1. Adding an 'administrativeRole' Attribute ............................. 34
3.5.4.3. Creating an Access Control Inner Administrative Area ..................... 35
3.5.4.4. Access Control Subentries .......................................................... 35
3.5.5. AllowSelfPasswordModify ................................................................... 35
3.5.5.1. Commentary ............................................................................ 36
3.5.6. EnableSearchForAllUsers ..................................................................... 36
3.5.6.1. Enable Authenticated Users to Browse and Read Entries in a
Subtree .............................................................................................. 36
3.5.6.1.1. Check for insufficientAccessRights for Normal Users ............ 36
3.5.6.1.2. Partition and Access Control Area Setup ............................. 36
3.5.6.1.3. Adding the Subentry ....................................................... 36
3.5.6.1.4. ACIItem Description ...................................................... 37
3.5.7. UserClasses ....................................................................................... 39
3.5.7.1. What are User Classes? ............................................................. 39
3.5.7.2. Simple User Classes ................................................................. 39
3.5.7.3. User Class: userGroup ............................................................... 39
3.5.7.4. User Class: subtree ................................................................... 40
3.5.8. Combining Multiple UserClass Specification Mechanisms .......................... 40
4. Attributes, Entries & Schemas ................................................................................... 41
4.1. Add your first elements to the schema .............................................................. 41
4.1.1. Motivation ......................................................................................... 41
4.1.2. Browsing the schema of ApacheDS ........................................................ 41
4.1.3. Which OIDs should you use? ................................................................ 43

iv
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft ApacheDS Advanced User Draft
Guide v1.5.8-SNAPSHOT

4.1.3.1. Some OID background information .............................................. 43


4.1.3.2. OIDs in the example ................................................................. 44
4.1.3.3. OIDs for your own custom schema elements .................................. 44
4.1.4. A simple example ............................................................................... 44
4.1.4.1. attribute type numberOfGuns ...................................................... 44
4.1.4.2. object class ship ....................................................................... 45
4.1.5. Using Apache Directory Studio Schema Editor to load the new schema
elements .................................................................................................... 45
4.1.6. Using LDIF to load schema elements in RFC 4512 format .......................... 48
4.1.7. Using JNDI to add the schema elements programmatically .......................... 48
4.1.7.1. Some simple Java programs ....................................................... 48
4.1.8. Using JNDI to add schema elements in RFC 4512 format programmatically
................................................................................................................. 49
4.1.9. Resources .......................................................................................... 50
4.2. Collective Attributes ...................................................................................... 50
4.2.1. Introduction ....................................................................................... 50
4.2.1.1. Use Case ................................................................................ 50
4.2.2. Setting up a Collective Attribute Administration Area (AA) ........................ 51
4.2.2.1. Example ................................................................................. 51
4.2.3. Collective Attribute Types .................................................................... 52
5. Embedding ApacheDS .............................................................................................. 55
5.1. Embedding ApacheDS into an application ......................................................... 55
5.1.1. Setting up the environment ................................................................... 55
5.1.2. Creating the application ....................................................................... 55
5.1.3. Initializing the server ........................................................................... 56
5.1.4. Building the sample ............................................................................ 58
5.1.5. Running the sample ............................................................................ 58
5.2. Using ApacheDS for unit tests ......................................................................... 59
5.2.1. First steps .......................................................................................... 59
5.2.2. Creating a blank test ........................................................................... 59
5.2.2.1. Test description ........................................................................ 62
5.2.2.1.1. Annotations .................................................................. 62
5.2.2.1.2. Server startup ................................................................ 63
5.2.2.1.3. Writing your own test using JNDI ..................................... 63
5.2.2.1.4. Writing your own tests using the Netscape API .................... 63
5.2.3. Creating our own partition .................................................................... 64
5.2.4. Adding some data into the partition ........................................................ 65
5.2.5. Cleanup the code ................................................................................ 66
5.2.6. Searching for entries ........................................................................... 67
5.2.7. Adding your own schema ..................................................................... 68
5.2.8. Conclusion ........................................................................................ 68
5.2.9. Resources .......................................................................................... 69
5.3. Embedding ApacheDS as a Web Application ..................................................... 69
5.3.1. Solution Outline ................................................................................. 69
5.3.1.1. A Servlet Context Listener to start and stop ApacheDS .................... 69
5.3.1.2. A client within ......................................................................... 70
5.3.2. Step 1: The web component which starts and stops the server ...................... 70
5.3.2.1. Deployment descriptor .............................................................. 72
5.3.3. Packaging and Deploying the WebApp ................................................... 72
5.3.3.1. Creating the WebApp using the ApacheDS Maven Archetype ........... 72
5.3.3.2. Run on embedded Jetty ............................................................. 73
5.3.3.3. Deploying on Apache Tomcat ..................................................... 73
5.3.3.4. Connecting to ApacheDS from the outside .................................... 73
5.3.3.5. Other Web Application Servers ................................................... 76
5.3.4. Step 2: Adding functionality: A servlet which displays the Root DSE ............ 77
6. Protocol Providers ................................................................................................... 80
6.1. Protocol Providers ......................................................................................... 80
6.1.1. Apache Directory Protocol Providers ...................................................... 80

v
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft ApacheDS Advanced User Draft
Guide v1.5.8-SNAPSHOT

6.1.2. Service Configuration .......................................................................... 80


6.1.3. Changes from 1.5 to 1.5.1 .................................................................... 80
6.1.4. Protocol Providers ............................................................................... 80
6.2. Common Parameters for Configuration .............................................................. 81
6.2.1. Changes to Configuration ..................................................................... 81
6.2.1.1. Changes to LDAP configuration in 1.5.1 ....................................... 82
6.2.1.2. Changes to the other protocols in 1.5.1 ......................................... 82
6.2.2. Configuration Parameters Reference ....................................................... 82
6.2.2.1. Environment parameters ............................................................ 82
6.2.2.2. Protocol providers .................................................................... 83
6.2.2.2.1. Parameters common to all protocol providers ....................... 83
6.2.2.2.2. LDAP-Specific Configuration Parameters ........................... 85
6.2.2.2.3. Kerberos-Specific Configuration Parameters ........................ 87
6.2.2.2.4. Change Password-Specific Configuration Parameters ............ 87
6.2.2.2.5. NTP-Specific configuration parameters .............................. 88
6.2.2.2.6. DHCP-Specific configuration parameters ............................ 88
6.2.2.3. Server Startup Configuration ...................................................... 88
6.2.2.3.1. Replication ................................................................... 88
6.2.2.4. Partition Configuration .............................................................. 89
6.3. LDAP Protocol Provider ................................................................................. 89
6.3.1. Before .............................................................................................. 89
6.3.2. After ................................................................................................ 89
6.3.3. Common Service Configuration Parameters ............................................. 90
6.3.4. LDAP-Specific Configuration Parameters ................................................ 91
6.3.5. More Information ............................................................................... 92
6.4. Kerberos Protocol Provider ............................................................................. 92
6.4.1. Introduction ....................................................................................... 92
6.4.2. More Information ............................................................................... 93
6.4.3. Resources .......................................................................................... 93
6.4.3.1. Kerberos Articles ..................................................................... 93
6.4.3.2. Microsoft Interoperability .......................................................... 93
6.4.3.3. Standards ................................................................................ 93
6.4.4. Kerberos Protocol Configuration ............................................................ 93
6.4.4.1. Before .................................................................................... 93
6.4.4.2. After ...................................................................................... 94
6.4.4.3. Common Service Configuration Parameters ................................... 94
6.4.4.4. Kerberos-Specific Configuration Parameters .................................. 95
6.4.4.5. More Information ..................................................................... 95
6.4.5. Kerberos and Unlimited Strength Policy .................................................. 96
6.4.5.1. Introduction ............................................................................. 96
6.4.5.2. Installation .............................................................................. 96
6.4.6. Kerberos in ApacheDS 1.5.5 ................................................................. 96
6.4.6.1. Overview ................................................................................ 97
6.4.6.2. Activate Kerberos ..................................................................... 97
6.4.6.3. Optional: Logging .................................................................... 97
6.4.6.4. Restart the Server ..................................................................... 97
6.4.6.5. Load User Data ........................................................................ 98
6.4.6.6. Authenticate using kinit (Unix/Linux) .......................................... 98
6.4.6.7. Authenticate using Apache Directory Studio .................................. 99
6.5. Change Password Protocol Provider .................................................................. 99
6.5.1. Introduction ....................................................................................... 99
6.5.2. Changing Passwords with Windows 2003 .............................................. 100
6.5.2.1. Configure the Windows 2003 workstation to use an Apache Change
Password server ................................................................................. 100
6.5.2.2. Change a password using Windows Security ................................ 100
6.5.2.3. Or change a password using the Command Prompt ........................ 101
6.5.3. Change Password Configuration ........................................................... 101
6.5.3.1. Before .................................................................................. 101

vi
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft ApacheDS Advanced User Draft
Guide v1.5.8-SNAPSHOT

6.5.3.2. After .................................................................................... 101


6.5.3.3. Common Service Configuration Parameters ................................. 102
6.5.3.4. Change Password-Specific Configuration Parameters ..................... 103
6.5.3.5. More Information ................................................................... 103
6.5.4. Change Password in ApacheDS 1.5.5 .................................................... 103
6.5.4.1. Activating the Change Password Server ...................................... 103
6.6. DNS Protocol Provider ................................................................................. 104
6.6.1. Introduction ..................................................................................... 104
6.6.1.1. Basic Testing ......................................................................... 104
6.6.1.2. ApacheDS schema for storing DNS zones in LDAP ....................... 104
6.6.1.2.1. Abstract objectClass used to build all DNS record
objectclasses ............................................................................. 104
6.6.1.2.2. Address (A) record ....................................................... 105
6.6.1.2.3. Pointer (PTR) record ..................................................... 105
6.6.1.2.4. Name Server (NS) record ............................................... 105
6.6.1.2.5. Start Of Authority (SOA) record ..................................... 105
6.6.1.3. Configuring DNS Zones .......................................................... 106
6.6.1.3.1. The STRUCTURAL 'dcObject' objectClass ....................... 106
6.6.1.3.2. The AUXILIARY 'domain' objectClass ............................ 107
6.6.2. DNS Best Practices ........................................................................... 107
6.6.2.1. DNS Testing Tool .................................................................. 107
6.6.3. Notes .............................................................................................. 107
6.6.3.1. A Zone is a Pruned Subtree ...................................................... 107
6.6.3.2. Sender Permitted From ............................................................ 108
6.6.3.3. Secret Key Transaction Authentication for DNS (TSIG) ................. 108
6.6.4. DNS Protocol Configuration ............................................................... 108
6.6.4.1. Common Service Configuration Parameters ................................. 108
6.6.4.2. More Information ................................................................... 109
6.7. NTP Protocol Provider ................................................................................. 109
6.7.1. Introduction ..................................................................................... 109
6.7.2. Basic Testing ................................................................................... 110
6.7.3. Resources ........................................................................................ 110
6.7.3.1. SNTP RFC's .......................................................................... 110
6.7.4. NTP Protocol Configuration ................................................................ 110
6.7.4.1. Common Service Configuration Parameters ................................. 110
6.7.4.2. More Information ................................................................... 111
6.8. DHCP Protocol Provider ............................................................................... 111
6.8.1. Introduction ..................................................................................... 111
6.8.1.1. DHCP Notes .......................................................................... 112
6.8.2. More Information .............................................................................. 112
7. Extending the server ............................................................................................... 113
7.1. How to write a simple custom partition for ApacheDS ........................................ 113
7.1.1. What exactly is a partition? ................................................................. 113
7.1.2. Hello world. A minimal partition ......................................................... 113
7.1.2.1. The sources ........................................................................... 114
7.1.2.2. Implementing the class HelloWorldPartition ................................. 114
7.1.2.3. Using the partition .................................................................. 115
7.1.2.3.1. Embedded mode .......................................................... 115
7.1.2.3.2. Adding it to a server.xml file .......................................... 116
7.1.2.4. Verification ........................................................................... 116
7.1.3. To be continued ................................................................................ 117
7.2. Implementing a simple custom Interceptor ....................................................... 117
7.2.1. What exactly is an interceptor? ............................................................ 118
7.2.2. Password hash. A simple interceptor ..................................................... 118
7.2.2.1. The sources ........................................................................... 119
7.2.2.2. Implementing the class PasswordHashInterceptor .......................... 119
7.2.2.3. Using the interceptor ............................................................... 120
7.2.2.3.1. Adding it to a standard server installation (server.xml) ......... 120

vii
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft ApacheDS Advanced User Draft
Guide v1.5.8-SNAPSHOT

7.2.2.3.2. Embedded mode .......................................................... 121


7.2.2.4. Verification ........................................................................... 122
7.2.2.5. Limitations of the example ....................................................... 123
7.2.3. Further reading ................................................................................. 124
8. Partitioning & Replication ....................................................................................... 125
8.1. Referrals .................................................................................................... 125
8.2. Replication ................................................................................................. 125
9. Triggers & Stored Procedures .................................................................................. 126
9.1. Stored Procedures ........................................................................................ 126
9.1.1. What are Stored Procedures in LDAP? .................................................. 126
9.1.1.1. Java as the Native SP Language ................................................ 126
9.1.1.2. Storing Classes within the DIT .................................................. 126
9.1.1.3. Code Security and Class Conflicts ............................................. 126
9.1.1.4. Searching and Search Order for Classes ...................................... 127
9.1.1.5. Stored Procedure Call Specification ............................................ 127
9.1.1.6. Stored Procedure Execution Request Value .................................. 127
9.1.1.6.1. BER .......................................................................... 127
9.1.1.6.2. The State Machine ........................................................ 127
9.1.1.7. Explanations .......................................................................... 128
9.1.1.8. Security ................................................................................ 128
9.2. LDAP Triggers ........................................................................................... 128
9.2.1. Introduction ..................................................................................... 128
9.2.2. Trigger Specification ......................................................................... 128
9.2.3. Action Time for Triggers .................................................................... 129
9.2.4. Trigger Events: LDAP Operations ........................................................ 129
9.2.5. Triggered Actions: LDAP Stored Procedures .......................................... 129
9.2.6. Planned New Features for Triggers ....................................................... 129
10. Tuning ................................................................................................................ 130
10.1. Performance Tuning ................................................................................... 130
10.1.1. Balancing Cache w/ Heap Memory Indexing Attributes .......................... 130
Index ....................................................................................................................... 132

viii
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Draft

List of Figures
2.1. Interceptors .......................................................................................................... 10
2.2. Interceptor chaining ............................................................................................... 11
4.1. Schema Browser Person ......................................................................................... 42
4.2. Schema Browser Tree ............................................................................................ 43
4.3. Schemas view ....................................................................................................... 46
4.4. Schemas view with loaded schemas .......................................................................... 46
4.5. Schema browser ship ............................................................................................. 47
4.6. Entry editor with ship ............................................................................................ 47
4.7. SubEntry ............................................................................................................. 52
5.1. ApacheDS as a Web Application ............................................................................. 70
5.2. Tomcat Manager App in Browser ............................................................................ 73
5.3. New LDAP Connection Directory Studio 1 ................................................................ 74
5.4. New LDAP Connection Directory Studio 2 ................................................................ 75
5.5. Properties New LDAP Connection Directory Studio .................................................... 76
5.6. WebSphere Admin Console .................................................................................... 77
5.7. RootDSE Servlet in a Browser ................................................................................ 79
6.1. The activated keyDerivationInterceptor automatically creates the krb5Key attributes ........... 98
6.2. Authenticate using Apache Directory Studio .............................................................. 99
6.3. Windows Security ............................................................................................... 100
6.4. Windows Change Password ................................................................................... 101
6.5. ........................................................................................................................ 106
7.1. Hello World UML ............................................................................................... 114
7.2. Hello World LDAP Browser ................................................................................. 116
7.3. Hello World Entry Editor ...................................................................................... 117
7.4. PasswordHash Interceptor UML ............................................................................. 119
7.5. PasswordHash Interceptor PasswordEditor ............................................................... 122
7.6. PasswordHash Interceptor ModificationLog .............................................................. 123
7.7. PasswordHash Interceptor EntryEditor ..................................................................... 123

ix
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Draft

List of Tables
2.1. Nexus Proxy Object ................................................................................................ 9
2.2. Administrative areas .............................................................................................. 14
2.3. LDAP related RFCs ............................................................................................... 19
3.1. SASL QoP levels .................................................................................................. 28
3.2. To be named ........................................................................................................ 30
3.3. ACI Trails ........................................................................................................... 34
3.4. Access Control Subentries ...................................................................................... 35
3.5. ACIItem fields ...................................................................................................... 37
3.6. Simple User Classes .............................................................................................. 39
5.1. Test Annotations ................................................................................................... 62
6.1. Protocol Providers ................................................................................................. 80
6.2. Environment parameters ......................................................................................... 83
6.3. Parameters common to all protocol providers ............................................................. 83
6.4. Parameters common to all protocol providers 1 ........................................................... 84
6.5. LDAP-Specific Configuration Parameters 1 ............................................................... 86
6.6. LDAP-Specific Configuration Parameters 2 ............................................................... 86
6.7. Kerberos-Specific Configuration Parameters ............................................................... 87
6.8. Change Password-Specific Configuration Parameters ................................................... 87
6.9. NTP-Specific configuration parameters ..................................................................... 88
6.10. Replication Startup Configuration ........................................................................... 89
6.11. Common Service Configuration Parameters .............................................................. 90
6.12. LDAP-Specific Configuration Parameters ................................................................ 91
6.13. Common Service Configuration Parameters .............................................................. 94
6.14. Kerberos-Specific Configuration Parameters ............................................................. 95
6.15. Download the unlimited strength policy JAR files ..................................................... 96
6.16. Extract the unlimited strength policy JAR files .......................................................... 96
6.17. Install the unlimited strength policy JAR files ........................................................... 96
6.18. Common Service Configuration Parameters ............................................................ 102
6.19. Change Password-Specific Configuration Parameters ................................................ 103
6.20. Abstract objectClass used to build all DNS record objectclasses .................................. 104
6.21. Address (A) record ............................................................................................. 105
6.22. Pointer (PTR) record .......................................................................................... 105
6.23. Name Server (NS) record .................................................................................... 105
6.24. Start Of Authority (SOA) record ........................................................................... 105
6.25. Common Service Configuration Parameters ............................................................ 108
6.26. Common Service Configuration Parameters ............................................................ 110

x
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Draft

Work in progress
Unfortunately the Basic User's Guide for ApacheDS 1.5 is not finished yet. We have started to move
and revise the content, things you find here are work in progress but should be valid for ApacheDS
1.5.5. In the meantime you can have a look at the ApacheDS 1.0 Basic User's Guide, which is currently
more complete.

xi
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Draft

Chapter 1. Community
1.1. Reporting Bugs
This site was updated for ApacheDS 1.5.5.

1.1.1. Introduction
So you found a bug in ApacheDS. Don't worry this is a good thing! We can fix it really fast but need
your help. There are different degrees to your ability to help out. Some of you have developer skills
so you might be able to write a test case that pin points that bug. If you can do this we will prioritize
your bug report above all others. Yes we will put your bug to the top most important fixes that should
be fixed first. But if you can't do this and your bug is serious then we're prioritize it ahead of others
anyway.

This wiki page shows you how you can help us to help you!!!

1.1.2. Creating a testcase project: using the apacheds-


archetype-testcase
We've created a simple archetype for you to rapidly create a Maven project that fires up ApacheDS
in embedded mode within a JUnit testcase. This test case will start up ApacheDS as a server on any
available port above 1024 on your machine. You can then use JNDI or the Netscape LDAP API (more
APIs to come) going over the wire on that port above 1024. You can also use the ApacheDS core API
to access the data directly.

So you can write client code in your test case immediately. Just add your code, tar gzip the project,
and attach it to your JIRA issue on the ApacheDS JIRA here:

https://issues.apache.org/jira/browse/DIRSERVER

We'll prioritize your bug higher than others and probably fix it rapidly because the problem is isolated
thanks to your testcase submission. We will in fact strip out your testcase and add it to our suite of test
cases to make sure ApacheDS always passes this integration test you've provided.

1.1.3. Installing the apacheds-archetype-testcase


To use the archetype you'll need to check it out and install it. Here's how you can do that for the
leading edge of 1.5.5:

svn co http://svn.apache.org/repos/asf/directory/samples/trunk/apacheds-archetype-testcase
cd apacheds-archetype-testcase
mvn install

This will install the archetype onto your local repository. Now you can invoke the archetype.

1.1.4. Invoking (running) the archetype: generating the


testcase project
Once you checkout the archetype plugin and install it you can use it like so to generate a foo-test
project:

1
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Community Draft

mvn archetype:generate -DarchetypeGroupId=org.apache.directory.samples \


-DarchetypeArtifactId=apacheds-archetype-testcase \
-DarchetypeVersion=1.5.5-SNAPSHOT \
-DgroupId=com.acme -DartifactId=foo-test -Dpackage=com.acme

This will generate the default test case project with the following tree structure:

~/foo-test$ tree
.
|-- pom.xml
`-- src
|-- main
| `-- java
| `-- com
| `-- acme
| `-- Dummy.java
`-- test
|-- java
| `-- com
| `-- acme
| |-- AdvancedTest.java
| |-- AdvancedTestApacheDsFactory.java
| `-- MinimalTest.java
`-- resources
|-- log4j.properties
|-- sevenSeas_data.ldif
`-- sevenSeas_schema.ldif

10 directories, 8 files

• Dummy.java - this is just a placeholder file to make sure that Maven works properly.

• MinimalTest - a minimal ApacheDS Integration Test. It contains two test methods to demonstrate
usage of JNDI and the ApacheDS core API. Add your own test method here.

• AdvancedTest - an advanced ApacheDS Integration Test in case you need a special configuration
for your test. It demonstrates how to add a new partition, how to enable LDAPS, how to enable a
disabled schema, how to inject a custom schema, and how to inject custom test data.

• AdvancedTestApacheDsFactory - configures ApacheDS for the advanced test

• pom.xml - the Maven Project Object Model (POM) for your new testcase project (can remain as is).

• log4j.properties - Log4j configuration file that controls ApacheDS logging for your convenience;
edit this file to control logging output.

• sevenSeas_data.ldif - sample custom test data used by the advanced test.

• sevenSeas_schema.ldif - sample custom schema used by the advanced test.

Once you do this you can cd into foo-test and just build and test it for fun to see what happens. This
will build, and test the sample test cases (they should pass) that comes packaged with the project you
just created. CD into foo-test and run the following command:

mvn test

Now you can customize the MinimalTest.java or AdvancedTest.java file to isolate your bug. Open the
classes with your favorite editor and goto town. However if you want to pull this project into your IDE
and edit it there you can use Maven's IDEA, Eclipse and Netbeans integration to create IDE project
descriptors for them. Then you can import this project into your IDE. Here's how:

1.1.4.1. For IDEA


mvn idea:idea

2
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Community Draft

1.1.4.2. For Eclipse


mvn eclipse:eclipse

1.1.4.3. For Netbeans


See this page: http://maven.apache.org/guides/mini/guide-ide-netbeans/guide-ide-netbeans.html

mvn eclipse:eclipse

1.1.5. Note about version


Note that this archetype is specific for ApacheDS 1.5.5.

1.1.6. Why a Maven Archetype for Testing?


1. Easy and fast to start integration testing ApacheDS.

2. We (developers of ApacheDS) can use it ourselves.

3. We want users of ApacheDS to help us help them.

4. Users need to customize a project with perhaps additional dependencies.

5. Users can add many test cases to the project.

6. Tests isolating custom bugs can be incorporated into our community test suite for ApacheDS.

1.2. Building trunks


This page give some information about the layout of Apache DS 1.5 trunks, and try to explain how
it is built.

• Section 1.2.1, “Project Hierarchy”

• Section 1.2.2, “Prerequisites for building”

• Section 1.2.2.1, “Maven”

• Section 1.2.2.2, “JDK 5”

• Section 1.2.3, “Getting the code”

• Section 1.2.4, “Building the trunks”

• Section 1.2.4.1, “Enabling Snapshot Repositories”

• Section 1.2.4.2, “ Building the trunks ”

• Section 1.2.5, “Building the installers”

• Section 1.2.6, “Starting the server without installation”

• Section 1.2.7, “Integration test”

• Section 1.2.8, “Eclipse”

• Section 1.2.8.1, “Building eclipse files”

3
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Community Draft

• Section 1.2.8.2, “Maven settings”

• Section 1.2.8.3, “Eclipse hints”

• Section 1.2.8.4, “Eclipse plugins”

• Section 1.2.8.5, “Coding standards”

1.2.1. Project Hierarchy


The actual project hierarchy is the following (as of 1.5.5-SNAPSHOT) :

This hierarchy represent the projects being built.

1.2.2. Prerequisites for building


You must have installed Maven 2.0.9 and have a JDK 5 installed on your computer. A working
internet connection is also mandatory.

If the build hangs or you get an out of memory exception please increase the heap space:

• For Linux:

MAVEN_OPTS="-Xmx256m" mvn clean install

• For Windows:

SET MAVEN_OPTS="-Xmx256m"
mvn clean install

1.2.2.1. Maven
Download [http://maven.apache.org/download.html] and install Maven 2.0.9. (ATTENTION !!! Do
NOT use an older version of Maven )

Add a MAVEN_HOME environment variable and add MAVEN_HOME/bin to your system path:

On a Linux box you could add the following to the .bashrc file (.bashrc is a file you'll find in your
home directory)

...
export MAVEN_HOME=/opt/maven-2.0.9
export PATH=$JAVA_HOME:$JAVA_HOME/bin:$MAVEN_HOME/bin:$PATH
...

Windows users, use Control Panel -> System -> Advanced -> Environment Variables

1.2.2.2. JDK 5

1.2.3. Getting the code


To download the sources, you must have installed a Subversion client.

With readonly access :

svn co http://svn.apache.org/repos/asf/directory/apacheds/trunk-with-dependencies/ apacheds-trunk

4
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Community Draft

With read/write access (for committers only) :

svn co https://svn.apache.org/repos/asf/directory/apacheds/trunk-with-dependencies/ apacheds-trunk

1.2.4. Building the trunks


1.2.4.1. Enabling Snapshot Repositories
The following information is only needed if one want to setup its own maven repo. There is
no need to define a settings.xml file for generic usage.

Before building the trunks, you must configure Maven 2 to use the snapshot repository for
Apache. Snapshot repositories are typically configured per user at ~/.m2/settings.xml. The
following example, added to your settings.xml, will add a profile for the Apache snapshot
repository.

<settings>
<profiles>
...
<profile>
<id>apache</id>
<repositories>
<repository>
<id>apache.org</id>
<name>Maven Snapshots</name>
<url>http://people.apache.org/repo/m2-snapshot-repository</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>apache.org</id>
<name>Maven Plugin Snapshots</name>
<url>http://people.apache.org/repo/m2-snapshot-repository</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
...
</profiles>
</settings>

You may either specify the profile at the command-line, each time you use 'mvn', or you may configure
the profile to always be active.

To use a profile at the command-line:

# mvn -Papache [options] [<goal(s)>] [<phase(s)>]

To specify the 'apache' profile to always be active:

<settings>
...
<activeProfiles>
<activeProfile>apache</activeProfile>
</activeProfiles>

5
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Community Draft

...
</settings>

1.2.4.2. Building the trunks


Now, we can compile the project.

The command is simple :

cd apacheds-trunk
mvn clean install

You must make sure you build the shared, installers, and daemon project modules in addition
to the apacheds module to prevent problems with stale Maven SNAPSHOT jars in the snapshot
repository from causing compilation errors. This can be guaranteed by performing all Maven
operations above in the top directory that you checked out: the apacheds-trunk directory.

A lot of plugins will be downloaded. If you are curious, you can then look at .m2/repository to see
what has been downloaded on this step. Building should finish with these lines:

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 8 minutes 30 seconds
[INFO] Finished at: Mon Oct 30 23:32:41 CET 2006
[INFO] Final Memory: 18M/32M
[INFO] ------------------------------------------------------------------------

1.2.5. Building the installers


Building the installers is a two phase process :

cd apacheds-trunk
mvn install
cd installers/apacheds
mvn -Pserver-installer install

That's it, the jars will be find in target/images/apacheds-1.5.?SNAPSHOT <XXXXXX>-setup.jar


where XXXXXX is your local system and ? is the feature release minor number for the 1.5 branch.

1.2.6. Starting the server without installation


The directory apacheds-trunk/installers/apacheds-noarch contains a script for Linux (apacheds.sh) and
one for Windows (apacheds.bat) which can be used for starting the server without the need to install
it first (as non-root-user on Linux and non-Windows-service on Windows).

Linux:

cd apacheds-trunk/installers/apacheds-noarch
./apacheds.sh

1.2.7. Integration test


To run integration tests, just use the following command :

cd apacheds-trunk
mvn -Dintegration test

6
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Community Draft

1.2.8. Eclipse
1.2.8.1. Building eclipse files
To build the .project and .classpath files for eclipse, type the following commands :

cd apacheds-trunk
mvn clean install
mvn eclipse:eclipse
cd apacheds/bootstrap-partition
mvn clean install

(The last command is necessary because eclipse:eclipse purge the target directory, and we need some
generated files which has been removed. This is why we do another *mvn clean install* in the boostrap-
partition module then import all the existing project which has been created.

1.2.8.2. Maven settings


Don't forget to declare a classpath variable named M2_REPO, pointing to ~/.m2/repository, otherwise
many links to existing jars will be broken.

You can declare new variables in Eclipse in -> Preferences... and selecting -> Build Path ->
Classpath Variables

1.2.8.3. Eclipse hints


Add an eclipse-apacheDS.sh file in your eclipse root directory, to allow eclipse to get more memory
(e.g. 750MB)

You may also declare a specific workspace when launching eclipse. I have created a workspace-
apacheDS directory in my HOME directory, where all the ApacheDS project is built when I use
Eclipse.

<eclipse_root>/eclipse -data $HOME/workspace-apacheDS -vm java -vmargs -Xmx750M

Launch eclipse :

<eclipse_root>/eclipse-apacheDS.sh

1.2.8.4. Eclipse plugins


1.2.8.5. Coding standards
The coding standards including an eclipse code formatting profile is available here [http://
directory.apache.org/apacheds/DIRxDEV/coding-standards.html] .

1.3. Contributing

7
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Draft

Chapter 2. Architecture
2.1. Architectural Overview
2.1.1. Partitions
A partition is a physically distinct store for a subset of the entries contained within a DSA (Directory
Server/Service Agent A.K.A the LDAP server). The entries of a partition all share the same
suffix which is the distinguished name of the namingContext from which the stored entries in the
partition are hung from the DIT. A partition can be implemented using any storage mechanism
or can even be backed in memory. The default storage mechanism for a partition is JDBM. The
addition of such a partition is described in the Basic User's Guide [http://directory.apache.org/
apacheds/1.5/apacheds-v15-basic-users-guide.html] . A partition with a different storage mechanism
simply has to implement the Partition interface and by doing so can be mounted in the server at it's
suffix/namingContext (described here [http://cwiki.apache.org/confluence/pages/createpage.action?
spaceKey=DIRxSRVx11&title=6.1.%20Implementing%20an%20alternative
%20Backend&linkCreation=true&fromPageId=55216] ).

The server can have any number of partitions (with any implementation) attached to various
namingContexts which are published by the RootDSE (empty string dn "") using the namingContexts
operational attribute. So if you want to see the partitions served by the server you can query the
RootDSE for this information.

2.2. Interceptors
2.2.1. What is it?
The mechanism is a means for injecting and isolating orthogonal services into calls against the nexus.
The nexus is the hub used to route calls to partitions to perform CRUD operations upon entries.
By injecting these services at this level, partition implementators need not duplicate fuctionality.
Services such as authentication, authorization, schema checking, normalization, operational attribute
maintenance and more are introduced using Interceptors. By using interceptors, partition implementors
need not be concerned with these aspects and can focus on raw CRUD operations against their backing
stores what ever they may be.

2.2.2. How does it work?


Before we talk more about interceptors we must quickly cover the JNDI provider implementation
since it is somewhat related.

2.2.3. JNDI Implementation


The JNDI implementation is composed of a set of JNDI Context implementations, a ContextFactory
implementation and a set of helper classes.

• DeadContext

• JavaLdapSupport

• ServerContext

• ServerDirContext

• ServerLdapContext

8
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Architecture Draft

• AbstractContextFactory

• CoreContextFactory

• ServerDirObjectFactory

• ServerDirStateFactory

Every JNDI Context implementation in the provider holds a dedicated reference to a nexus proxy
object. This proxy contains all the operations that the nexus contains . The proxy object is at the heart
of the mechanism. We will disuss it more after covering the rest of the JNDI provider.

Calls made against JNDI Contexts take relative names as arguments. These names are relative to the
distinguished name of the JNDI Context. Within the Context implementations these relative names
are transformed into absolute distinguished names. The transformed names are used to make calls
against the proxy.

Additional processing may occur before or after a call is made by a context on its proxy to manage
JNDI provider specific functions. One such example is the handling of Java objects for serialization
and the use of object and state factories.

2.2.4. The nexus proxy object


As mentioned above, each Context that is created has a nexus proxy. The proxy maintains a handle
on the context as well.

Table 2.1. Nexus Proxy Object


The primary job of the proxy is to inject The following picture describe the Interceptors
Interceptor based services. It does so by mechanisms :
invoking a chain of Interceptors managed by
the system. Interceptors mirror the methods that
are intercepted on the nexus interface. When
an intercepted method is invoked on the proxy,
the proxy pushes an Invocation object on to
the InvocationStack associated with the current
executing Thread. The proxy then calls the same
method on a chain of Interceptors. The results of
the call are returned after the InvocationStack is
popped.

The InvocationStack is used to track the calls


being intercepted. Invocation objects pushed onto
the stack track the context making the call to
the proxy, the name of the intercepted call
and its arguments. A stack is used because in
the case of Triggers, stored procedures may be
invoked which operate against the DIT using
JNDI. These JNDI calls will also be intercepted.
Their Invocation object will be stacked on top of
the Invocation which raised the Trigger. This way
identities and context of operations can be tracked
and used by the Trigger management system to
prevent runnaway cascades or to limit the cascade
depth. There are other areas besides just triggers
where this stack will serve a purpose.

The InterceptorChain is a container of


Interceptors which has the same or analogous

9
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Architecture Draft

methods as do Interceptors. These are for the Figure 2.1. Interceptors


interceptable methods. A call against the chain
invokes the first Interceptor which then usually
invokes the next interceptor in the chain. An
Interceptor need not call the next interceptor
however. It can raise an exception before making
the call to the next interceptor or it can completely
bypass the rest of the chain by just returning
before calling the next Interceptor. Interceptors
can preprocess the arguments, or perform other
tasks before they invoke the next Interceptor.
They can also catch exceptions raised by other
downstream interceptors and respond to them
to handle errors. Finally they can perform post
processing operations on the results of returned
values from downstream Interceptors.

One might ask when is the call made against


the actual nexus. This happens using a special
Interceptor which resides at the end of the chain.
It actually makes the call against the nexus and
returns the results.

Interceptors can be seen as Servlet Filters :


they can be added, removed, bypassed
either by configuration or, for embeded
servers, on the fly.

2.2.5. Operation handling within interceptors


Each operation is associated with a method in each interceptors, even if it does nothing else than
calling the next interceptor.

The base idea is to allow pre and post actions to be executed before and after the call of the next
interceptors :

10
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Architecture Draft

Figure 2.2. Interceptor chaining

Each interceptor process the pre action, call the next interceptor, wait for the response, execute the
post action, and returns. We have to implement this chain of interceptors in a way which allows us
to add new interceptors, or new pre or post actions, without having to modify the existing code or
mechanism.

2.2.6. Bind Operation


The Bind operation call the interceptor chain in the PartitionNexusProxy class, where we can found
a bind method :

public void bind( LdapDN bindDn, byte[] credentials, List mechanisms, String saslAuthId,
Collection bypass ) throws NamingException
{ ...
this.configuration.getInterceptorChain().bind( bindDn, credentials, mechanisms, saslAuthId );
...
}

this will call the first configured interceptor from a chain which is declared in the configuration file
server.xml . The first interceptor is the NormalizationService .

The information which are passed are :

• The DN used to bind

• The password (credentials)

• The list of supported mechanisms

• The SASL authent

We will often use only the two first elements.

2.2.7. Normalization interceptor


This interceptor will just normalize the DN used to bind. If the DN is invalid, an exception will be
thrown.

It is the first interceptor in the chain because as we will manupulate the DN through all interceptors,
it is important that we normalize it as soon as possible.

The normalized DN will be stored in an special form, usefull for internal comparizons. This operation
can be costly, but as the DN has already been parsed, this is quite efficient.

11
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Architecture Draft

We can call the next interceptor :

2.2.8. Authentication interceptor


We must check that this bind request is valid, that is the DN and the associated password are known
by the server. We have two cases :

1. The user have already been authenticated

2. This is the first time this user try to bind

What we call user is the DN of a known entry stored in the server.

In the first case, we will have to search the password in the backend, and this will be a lookup operation,
which will be applied through another chain of interceptors.

Let's assume we are in the second case, because if we are in the first case, we will have to ask the
backend about the entry which DN is equal to the one we received, to get its associated password, thus
callaing a specific chain of interceptors ( FINAL_INTERCEPTOR ).

The password is compared using the given mechanism (which should be simple on a new server), and
if it matches, we create a principal object which will be stored in the connection context for future
usage.

We are done with the bind operation.

2.2.9. Add operation


An add operation is more complex. What we need to do is to check if the current user has enough
right to add an entry, and that the entry can be added.

A new entry is a composition of three elements :

• A partition name

• A path from this partition

• An entry name

For instance, when adding an entry which DN is cn=acme, ou=users, ou=system , we will have :

• Partition = ""ou=system"

• Path = "ou=users, ou=system"

• Entry name = "cn=acme"

The two first elements must exist in the base. We can't add an entry in an not existing partition, and
we can't add an entry which path is not existing.

2.3. The Administrative Model


2.3.1. Introduction
Subentries are used for managing the administration of different aspects of the directory. LDAP has
just recently formalized the notion of subentires in RFC 3672 [http://www.faqs.org/rfcs/rfc3672.html]
. Subentries have existed within X.500 Directories for years with clear specifications for administering
collective attributes, schema, and access controls. With the exception of managing collective attributes
LDAP has no equivalent yet for administering these aspects. However with RFC 3672, LDAP is on
its way towards adopting and adapting these mechanisms from X.500 Directories. It is only a matter
of time.

12
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Architecture Draft

For this reason we intend to remain ahead of the curve by implementing these aspects of administration
using Subentries and Administrative Areas similar to X.500 Directories.

2.3.2. What exactly are subentries?


To explain this properly we're going to need to discuss a couple other things like administrative areas
(AA) and administrative points (AP) within the directory. However for the impatient here's a quick
attempt to describe what subentries are:

Subentries are hidden leaf entries (which cannot have children). These entries immediately subordinate
to an administrative point (AP) within the directory. They are used to specify administrative
information for a part of the Directory Information Tree (DIT). Subentries can contain administrative
information for aspects of access control, schema administration, and collective attributes (and others
which have not been defined in any specification yet).

2.3.3. Administrative Areas, Entries and Points


First some definitions as provided by X.501:

• 11.1.1 administrative area: A subtree of the DIT considered from the perspective of administration.

• 11.1.2 administrative entry: An entry located at an administrative point.

• 11.1.3 administrative point: The root vertex of an administrative area.

• 11.1.5 autonomous administrative area: A subtree of the DIT whose entries are all administered by
the same Administrative Authority. Autonomous administrative areas are non-overlapping.

• 11.1.11 inner administrative area: A specific administrative area whose scope is wholly contained
within the scope of another specific administrative area of the same type.

• 11.1.17 specific administrative area: A subset (in the form of a subtree) of an autonomous
administrative area defined for a particular aspect of administration: access control, subschema or
entry collection administration. When defined, specific administrative areas of a particular kind
partition an autonomous administrative area.

• 11.1.18 specific administrative point: The root vertex of a specific administrative area.

Now take a step back because the above definitions are, well, from a sleep inducing spec. Let's just
talk about some situations.

Presume you're the uber directory administrator over at WallyWorld (a Walmart competitor). Let's
say WallyWorld uses their corporate directory for various things including their product catalog. As
the uber admin you're going to have a bunch of people wanting access, update and even administer
your directory. Entire departments within WallyWorld are going to want to control different parts of
the directory. Sales may want to manage the product catalog, while operations may want to manage
information in other areas dealing with suppliers and store locations. Whatever the domain some
department will need to manage the information as the authority.

Each department will probably designate different people to manage different aspects of their domain.
You're not going to want to deal with their little fiefdoms instead you can delegate the administration
of access control policy to a departmental contact. You will want to empower your users and
administrative contacts in these departments so they can do part of the job for you. Plus it's much
better than having to communicate with everyone in the company to meet their needs. This is where
the delegation of authority comes into the picture.

Usually administrators do this already to an extent without defining administrative areas. Giving users
the ability to change their own passwords for example is a form of delegation. This is generally a
good idea because you don't want to set passwords for people. First because you don't want to see the
password and secondly because of the management nightmare you'd have to deal with. Expand this

13
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Architecture Draft

idea out a little further and think about delegating administration not of users on their passwords but
of entire subtrees in the directory to administrative contacts in various departments.

Do you really want to manage the corporate product catalog or just let the sales department manage it?
But what do we mean by manage? You want sales people to create, and delete entries but they may only
trust a few people to do this. Others may just view the catelog. Who are the people with add/remove
powers and why should you have to be involved with deciding this ever changing departmental policy?
Instead you can delegate the management of access controls in this area to a administrative contact
in the sales department. The sales contact can then administer access controls for their department.
They're closer to the people in sales than you are and they probably have more bandwidth to handle
sales related needs than you do. Delegating authority in this fashion is what X.500 engineers pioneered
in the early 80's with the telecom boom in Europe. They knew different authorities will want to manage
different aspects of directory administration for themselves. These X.500 definitions are there to be
able to talk about administrative areas within the directory. Now let's get back to what these things
are exactly.

An administrative area is some part of the directory tree that is arbitrarily defined. The tree can
be split into different administrative areas to delegate authority for managing various aspects of
administration. For example you can have a partition hanging off of 'dc=example,dc=com' with an
'ou=product catalog' area. You may want this area to be managed by the sales department with respect
to the content, schema, it's visibility, and collective attributes. Perhaps you only want to delegate
only one aspect of administration , access control, since you don't want people messing around with
schema. To do so you can define everything under 'ou=product catalog' to be an administrative
area specifically for access control and delegate that aspect only. In that case the entry, 'ou=product
catalog,dc=example,dc=com' becomes an administrative entry. It is also the administrative point for
the area which is the tree rooted at this entry.

Not all administrative areas are equal. There are really two kinds : autonomous and inner areas.
Autonomous areas are areas of administration that cannot overlap. Meaning someone is assigned as
the supreme authority for that subtree. Inner areas are, as their name suggests, nested administrative
areas within autonomous areas and other inner areas. Yes, you can nest these inner areas as deep as
you like. You may be asking yourself what the point to all this is. Well, say you're the supreme admin
of admins. You delegate the authority to manage access control for the corporate catalog to the sales
admin. That admin may in turn decide to delegate yet another area of the catalog to another contact
within a different department. You delegate access control management to the sales admin over the
product catalog. The sales admin realizes that the job is way bigger than he can manage so he delegates
administration of subtrees in the catalog to various contacts in different departments. For example
regions of the catalog under 'ou=electronics' and 'ou=produce' may be delegated to different contacts
in their respective departments. However the sales admin still reserves the ability to override access
controls in the catalog. The sales admin can change who manages access controls for different parts
of the catalog. This chain of delegation is possible using inner administrative areas.

2.3.4. How are administrative areas defined?


Usually an entry is selected as the administrative point and marked with an operational attribute. The
attributeType of the operational attribute is 'administrativeRole'. This attribute can have the following
values:

Table 2.2. Administrative areas


OID NAME
2.5.23.1 autonomousArea
2.5.23.2 accessControlSpecificArea
2.5.23.3 accessControlInnerArea
2.5.23.4 subschemaAdminSpecificArea
2.5.23.5 collectiveAttributeSpecificArea

14
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Architecture Draft

OID NAME
2.5.23.6 collectiveAttributeInnerArea

As you can see, 3 aspects, schema , collective attributes , and access control are considered. An
autonomous administrative area can hence be considered with respect to all three specific aspect of
administration. If an AP is marked as an autonomousArea it generally means that administration of
all aspects are allowed by the authority. If marked with a specific aspect then only that aspect of
administration is delegated. The administrativeRole operational attribute is multivalued so the uber
admin can delegate any number of specific administration aspects as he likes.

Also notice that two aspects, collective attribute and access controls, allow administrative points to
be inner areas. Delegated authorities for these two aspects can create inner administrative areas to
further delegate their administrative powers. The schema aspect unlike the others cannot have inner
areas because of potential conflicts this may cause which would lead to data integrity issues. For this
reason only the authority of an automomous area can manage schema for the entire subtree.

An autonomous administrative area (AAA) includes the AP and spans all descendants below the AP
down to the leaf entries of the subtree with one exception. If another AAA, let's call it AAA' (prime)
is present and rooted below the first AAA then the first AAA does not include the entries of AAA'.
Translation: an AAA spans down until other AAAs or leaf entries are encountered within the subtree.
This is due to the fact that AAAs do not overlap as do inner AAs (IAA).

2.3.5. Subentries under an IAA or an AAA


Subentries hold administrative information for an IAA or an AAA. These entries are of the objectClass
'subentry'. The subentry must contain two attributes: a commonName and a subtreeSpecification .
The commonName (or cn) is used as the subentry's rdn attribute. The subtreeSpecification describes
the collection of entries within the AA (IAA or AAA) that the administrative instruction applies to.

A subtree specification uses various parameters described below to define the set of entries. Note that
entries need not exist for them to be included in the collection on addition.

2.3.6. Base parameter


This is the relative name of the root vertex of the subtree relative to the AP. So if the AP is 'ou=system'
and the base is 'ou=users' , the subtree begins at 'ou=users,ou=system' . The base can be any length
of name components including 0 where it's the empty name "". In this case, the subtree begins at the
AP, 'ou=system' in the example above.

2.3.7. Chop parameters


Chop specification parameters define specific nodes to be excluded from the collection as well as how
deep the subtree spans and even where it starts relative to the base.

2.3.7.1. chopBefore and chopAfter


These parameters are names relative to the root vertex of the subtree, hence they are relative to the
base parameter. They specify whether or not an entry and its descendants are to be excluded from
the collection.

When chopBefore is used, the entry specified is excluded from the collection. When chopAfter is
used the entry is included however all descendants below the entry are excluded.

2.3.7.2. minimum and maximum


The minimum parameter describes the minimum number of name components (arc) between the base
and the target entry required to include entries within the selection. The maximum parameter describes

15
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Architecture Draft

the maximum arc length between the base and the target allowed before entries are excluded from
the collection.

2.3.8. Specification filter parameter


The specification filter is a unique beast. It's a filter like a search filter, however its syntax and
expressivity is radically different. Think of a specification filter as a simplified form of search filters
where all terms only test the objectClass attribute and only equality checks can be performed. Oh and
yes, you do have logical operators like and , or and not .

So with a filter you have the ability to "refine" the subtree already specified with chop, and base
parameters. This "refinement" makes it so the collection is not really a contiguous subtree of entries
but a possibly disconnected set of selected based on the objectClass characteristics of entries. This
feature of a subtreeSpecification is very powerful. For example, I can define a subtree to cover a region
of an AA yet include only inetOrgPersons within this region.

2.3.9. Subentry types in ApacheDS


Different subentry objectClasses exist for applying different aspects of administration to the entry
collection described by their subtreeSpecification attribute. By the way the subtreeSpecification
attribute is single valued so there can only be one in a subentry. However you can have several
subentries of various kinds under an AP. Furthermore their collections can intersect.

The kinds of subentries allowed though are limited by the administrativeRole of the AP. If the AP is
for an access control AA then you can't add a subentry to it for schema administration. The AP must
have the role for schema administration as well to allow both types of subentries.

ApacheDS does not manage schema using subentries in the formal X.500 sense right now. There is a
single global subentry defined at 'cn=schema' for the entire DSA. The schema is static and cannot be
updated at runtime even by the administrator. Pretty rough for now but it's the only lagging subsystem.
We'll of course make sure this subsystem catches up.

ApacheDS does however manage collective attributes using subentries. An AP that takes the
administrativeRole for managing collective attributes can have subentries added. These subentries are
described in greater detail here: Section 4.2, “Collective Attributes” . In short, collective attributes
added to subentries show up within entries included by the subtreeSpecification. Adding, removing,
and modifying the values of collective attributes within the subentries instantly manifest changes in
the entries selected by the subtreeSpecification. Again consult Section 4.2, “Collective Attributes” for
a hands on explanation of how to use this feature.

ApacheDS performs access control and allows delegation using subentries, AAAs, and IAAs.
ApacheDS uses the Basic Access Control Scheme from X.501 to manage access control. By default
this subsystem is deactivated because it locks down everything except access by the admin. More
information about hands on use is available here: Section 3.5, “Authorization” However to summarize
its association with subentries, access control information (ACI) can be added to subentries under
an AP for access control AAs. When one or more ACI are added in this fashion, the access rules of
the ACI set apply to all entries selected by the subtreeSpecification. Even with this powerful feature
individual entries can have ACI added to them for controlling access to them. Also there are things you
can do with ACI added to subentries that cannot be done with entry level ACI. For example you cannot
allow entry addition with entry ACI. You must use subtreeSpecifications to define where entries may
be added because those entries and their parents may not exist yet.

2.3.10. How to specify a subentry's


subtreeSpecification
The best way to demonstrate subtreeSpecification values are through examples. Here's the simplest
filter of them all:

16
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Architecture Draft

{}

This basically selects the entire contiguous subtree below the AP. The base is the empty name and
it's rooted at the AP.

Next step let's add a base:

{ base "ou=users" }

If this is the subtreeSpecification under the AP, 'ou=system' , then it selects every entry under
'ou=users,ou=system' .

OK that was easy so now let's slice and dice the tree now using the minimum and maximum chop
parameters.

{ minimum 3, maximum 5 }

This selects all entries below 'ou=system' which have a DN size equal to 3 name components,
but no more than 5. So for example 'uid=jdoe,ou=users,ou=system' would be included but
'uid=jack,ou=do,ou=not,ou=select,ou=users,ou=system' would not be included. Let's continue and
combine the base with just a minimum parameter:

{ base "ou=users", minimum 4 }

Here the subtree starts at 'ou=users,ou=system' if the subentry subordinates to the AP at 'ou=system'
. The user 'uid=jdoe,ou=deepenough,ou=users,ou=system' is selected by the spec where as
'uid=jbean,ou=users,ou=system' is not.

It's time to add some chop exclusions:

{
base "ou=users",
minimum 4,
specificExclusions { chopBefore: "ou=untrusted" }
}

Again if placed at the AP 'ou=system' this subtree would begin at 'ou=users,ou=system' .


It would not include users that subordinate to it though because of the minimum constraint
since these users would have 3 components in their DN. The specific exclusions prevent
'ou=untrusted,ou=users,ou=system' and all its descendants from being included in the collection.
However 'uid=jbean,ou=trusted,ou=users,ou=system' would be included since it meets the
minimum requirement, is a descendant of 'ou=users,ou=system' and is not under the excluded DN,
'ou=untrusted,ou=users,ou=system' .

Note that you can add as many exclusions as you like by comma delimiting them. For example:

{
base "ou=users",
minimum 4,
specificExclusions { chopBefore: "ou=untrusted", chopAfter: "ou=ugly", chopBefore: "ou=bad" }
}

The final example includes a refinement. Again any combination of chop, filter and base parameters
can be used. The following refinement makes sure the users selected are of the objectClass
inetOrgPerson and specialUser where the OID for the specialUser class is 32.5.2.1 (fictitious).

17
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Architecture Draft

base "ou=users",
minimum 4,
specificExclusions { chopBefore: "ou=untrusted", chopAfter: "ou=ugly", chopBefore: "ou=bad" }
specificationFilter and:{ item:32.5.2.1, item:inetOrgPerson }
}

If you'd like to see the whole specification of the grammar used for the subtreeSpecification take a
look at Appendix A in RFC 3672 [http://www.faqs.org/rfcs/rfc3672.html] .

2.3.11. Future Possibilities


In the immediate future we intend to introduce Section 9.2, “LDAP Triggers” , stored procedures and
views into ApacheDS. Subentries will play a critical role in the administration and application of these
features. For example a Trigger specification need not include information on what entries it applies
to since the subtreeSpecification handles this. The question of "on what" a trigger applies to is nicely
disassociated from the "which operation" part of the specification. This makes for much better reuse
of triggers. It also allows for the pin point application of triggers to entries in the DIT. Likewise a
view itself will be defined by a specification. A view for example in a subentry can define a region
of the tree that does not exist but is shadowed from another region all together. The possibilities here
are limitless.

Of course we will revamp the schema subsystem of ApacheDS to use subentries in AAA to manage
the schema in effect within different regions of the DIT. Today most LDAP servers just have a global
scheme in effect for the entire DIT served by a DSA. We don't think that is reasonable at all. So expect
some serious advances in the design of a new schema subsystem based on subentries.

Replication is yet another excellent candidate for using subentries. Replication of specific collections
of entries can be managed for each cluster rather than replicating the entire DIT served by a DSA to
replicas. This way we don't only control what is replicated but we can also control how and where
it is replicated.

2.3.12. Conclusions
ApacheDS has implemented subentries for the administration of various aspects of the directory
and gains several powerful features as a result: namely precision application of control to entry
collections and the ability to delegate administrative authority. For details on the administration of each
aspect using subentries ( Collective [http://cwiki.apache.org/confluence/pages/createpage.action?
spaceKey=DIRxSRVx11&title=Collective&linkCreation=true&fromPageId=55219] and
Section 3.5, “Authorization” ) please see the respective documentation.

As ApacheDS progresses it will gain an immense advantage from subentries. Both for existing LDAP
features like scheme and for new experimental features like triggers, and replication.

2.4. Supported RFCs


Here is a list of all LDAP related RFCs (grey and marked

are obsoleted RFCs) in the current 1.5 version of ADS. The flag

is used for implemented RFCs into ADS. The flag

is used for partially implemented RFCs into ADS . The flag

is used for RFC not supported by ADS :

18
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Architecture Draft

Table 2.3. LDAP related RFCs

RFC num status Description


RFC 1274 The COSINE and Internet X.500
Schema.
RFC 1485 A String Representation of
Distinguished Names (OSI-DS
23 (v5)).
RFC 1487 X.500 Lightweight Directory
Access Protocol
RFC 1558 A String Representation of
LDAP Search Filters.
RFC 1777 Lightweight Directory Access
Protocol.
RFC 1779 A String Representation of
Distinguished Names.
RFC 1823 The LDAP Application Program
Interface.
RFC 1959 An LDAP URL Format.

RFC 1960 A String Representation of


LDAP Search Filters.
RFC 2164 Use of an X.500/LDAP directory
to support MIXER address
mapping.
RFC 2247 Using Domains in LDAP/X.500
Distinguished Names.
RFC 2251 Lightweight Directory Access
Protocol (v3).

RFC 2252 Lightweight Directory Access


Protocol (v3)| Attribute Syntax
Definitions.

RFC 2253 Lightweight Directory Access


Protocol (v3)| UTF-8 String
Representation of Distinguished
Names.
RFC 2254 The String Representation of
LDAP Search Filters.

RFC 2255 The LDAP URL Format.

RFC 2256 A Summary of the X.500(96)


User Schema for use with
LDAPv3.

RFC 2307 An Approach for Using LDAP as


a Network Information Service.

19
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Architecture Draft

RFC num status Description


RFC 2559 Internet X.509 Public
Key Infrastructure Operational
Protocols - LDAPv2.
RFC 2587 Internet X.509 Public Key
Infrastructure LDAPv2 Schema.
RFC 2596 Use of Language Codes in LDAP

RFC 2649 An LDAP Control and


Schema for Holding Operation
Signatures.
RFC 2657 LDAPv2 Client vs. the Index
Mesh.
RFC 2696 LDAP Control Extension
for Simple Paged Results
Manipulation.

RFC 2713 Schema for Representing


Java(tm) Objects in an LDAP
Directory.
RFC 2714 Schema for Representing
CORBA Object References in an
LDAP Directory.
RFC 2739 Calendar Attributes for vCard
and LDAP.
RFC 2798 Definition of the inetOrgPerson
LDAP Object Class.

RFC 2820 Access Control Requirements for


LDAP
RFC 2829 Authentication Methods for
LDAP
RFC 2830 Lightweight Directory Access
Protocol (v3)| Extension for
Transport Layer Security.
RFC 2849 The LDAP Data Interchange
Format (LDIF) - Technical
Specification.

RFC 2891 LDAP Control Extension for


Server Side Sorting of Search
Results.
RFC 2926 Conversion of LDAP Schemas to
and from SLP Templates.
RFC 3045 Storing Vendor Information in
the LDAP root

RFC 3062 LDAP Password Modify


Extended Operation.

20
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Architecture Draft

RFC num status Description


RFC 3088 OpenLDAP Root Service An
experimental LDAP referral
service.
RFC 3112 LDAP Authentication Password
Schema.
RFC 3296 Named Subordinate References
in Lightweight Directory Access
Protocol (LDAP) Directories.

RFC 3377 Lightweight Directory Access


Protocol (v3)| Technical
Specification.

RFC 3383 Internet Assigned Numbers


Authority (IANA)
Considerations for the
Lightweight Directory Access
Protocol (LDAP).
RFC 3384 Lightweight Directory Access
Protocol (version 3) Replication
Requirements.
RFC 3663 Domain Administrative Data in
Lightweight Directory Access
Protocol (LDAP).
RFC 3671 Collective Attributes in the
Lightweight Directory Access
Protocol (LDAP).

RFC 3672 Subentries in the Lightweight


Directory Access Protocol
(LDAP).

RFC 3673 All Operational Attributes

RFC 3674 Feature Discovery in


Lightweight Directory Access
Protocol (LDAP).
RFC 3687 Lightweight Directory Access
Protocol (LDAP) and X.500
Component Matching Rules.
RFC 3698 Lightweight Directory Access
Protocol (LDAP): Additional
Matching Rules.
RFC 3703 Policy Core Lightweight
Directory Access ProTocol
(LDAP) Schema.
RFC 3712 Lightweight Directory Access
Protocol (LDAP): Schema for
Printer Services.

21
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Architecture Draft

RFC num status Description


RFC 3771 The Lightweight Directory
Access Protocol (LDAP)
Intermediate Response Message.
RFC 3727 ASN.1 Module Definition for the
LDAP and X.500 Component
Matching Rules.
RFC 3771 The Lightweight Directory
Access Protocol (LDAP)
Intermediate Response Message.
RFC 3829 Lightweight Directory Access
Protocol (LDAP) Authorization
Identity Request and Response
Controls.
RFC 3866 Language Tags and Ranges in the
Lightweight Directory Access
Protocol (LDAP).
RFC 3876 Returning Matched Values
with the Lightweight Directory
Access Protocol version 3
(LDAPv3).
RFC 3909 Lightweight Directory Access
Protocol (LDAP) Cancel
Operation.
RFC 3928 Lightweight Directory Access
Protocol (LDAP) Client Update
Protocol (LCUP).
RFC 4104 Policy Core Extension
Lightweight Directory Access
Protocol Schema (PCELS).
RFC 4370 Lightweight Directory Access
Protocol (LDAP) Proxied
Authorization Control.

RFC 4373 Lightweight Directory Access


Protocol (LDAP) Bulk Update/
Replication Protocol (LBURP).
RFC 4403 Lightweight Directory Access
Protocol (LDAP) Schema
for Universal Description,
Discovery, and Integration
version 3 (UDDIv3).
RFC 4510 Lightweight Directory Access
Protocol (LDAP): Technical
Specification Road Map.

RFC 4511 Lightweight Directory Access


Protocol (LDAP): The Protocol.

RFC 4512 Lightweight Directory Access


Protocol (LDAP): Directory
Information Models.

22
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Architecture Draft

RFC num status Description


RFC 4513 Lightweight Directory Access
Protocol (LDAP): Authentication
Methods and Security
Mechanisms.
RFC 4514 Lightweight Directory Access
Protocol (LDAP): String
Representation of Distinguished
Names.
RFC 4515 Lightweight Directory Access
Protocol (LDAP): String
Representation of Search Filters.

RFC 4516 Lightweight Directory Access


Protocol (LDAP): Uniform
Resource Locator.

RFC 4517 Lightweight Directory Access


Protocol (LDAP): Syntaxes and
Matching Rules.

RFC 4518 Lightweight Directory Access


Protocol (LDAP):
Internationalized String
Preparation.
RFC 4519 Lightweight Directory Access
Protocol (LDAP): Schema for
User Applications.

RFC 4520 Internet Assigned Numbers


Authority (IANA)
Considerations for the
Lightweight Directory Access
Protocol (LDAP).
RFC 4521 Considerations for Lightweight
Directory Access Protocol
(LDAP) Extensions.
RFC 4522 Lightweight Directory Access
Protocol (LDAP): The Binary
Encoding Option.
RFC 4523 Lightweight Directory Access
Protocol (LDAP) Schema
Definitions for X.509
Certificates.
RFC 4524 COSINE LDAP/X.500 Schema.

RFC 4525 Lightweight Directory Access


Protocol (LDAP) Modify-
Increment Extension.
RFC 4526 Lightweight Directory Access
Protocol (LDAP) Absolute True
and False Filters.

23
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Architecture Draft

RFC num status Description


RFC 4527 Lightweight Directory Access
Protocol (LDAP) Read Entry
Controls.
RFC 4528 Lightweight Directory Access
Protocol (LDAP) Assertion
Control.
RFC 4529 Requesting Attributes by Object
Class in the Lightweight
Directory Access Protocol.
RFC 4530 Lightweight Directory Access
Protocol (LDAP) entryUUID
Operational Attribute.
RFC 4531 Lightweight Directory Access
Protocol (LDAP) Turn
Operation.
RFC 4532 Lightweight Directory Access
Protocol (LDAP) "Who am I?"
Operation.
RFC 4533 The Lightweight Directory
Access Protocol (LDAP) Content
Synchronization Operation.
RFC 4876 A Configuration Profile Schema
for Lightweight Directory Access
Protocol (LDAP)-Based Agents.
RFC 5020 The Lightweight Directory
Access Protocol (LDAP)
entryDN Operational Attribute.

Here is a list of drafts :

I-Ds List Working Group, LDAP Extension (ldapext) [https://datatracker.ietf.org/public/idindex.cgi?


command=show_wg_id&id=1363]

24
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Draft

Chapter 3. Authentication &


Authorization
3.1. SASL Authentication to ApacheDS
3.1.1. Introduction
Apache Directory currently supports the CRAM-MD5, DIGEST-MD5, and GSSAPI SASL
mechanisms. SASL is used during LDAP Binds to authenticate users. Additionally, with the
DIGEST-MD5 and GSSAPI mechanisms, SASL can also provide message integrity (checksums) and,
optionally, message privacy (encryption). When using SASL message privacy, connections do not
need SSL to protect communications.

3.1.2. Architecture
SASL workflow is implemented in the LDAP Protocol Provider's BindHandler. At the start of a
Bind, the BindHandler handles SASL negotiation. During SASL negotiation, the LDAP client is
first authenticated. After successful authentication, an LDAP context is established and a SUCCESS
message is returned.

Inbound --> decoder --> BindHandler <--> Backend #1, #2


Outbound <-- encoder <------'

Backend #1 is a lookup to authenticate the user using an administrative (internal) directory context.

Backend #2 is an LdapContext establishment for the user that is stored in the user's MINA session.

The DIGEST-MD5 and GSSAPI SASL mechanisms can provide message integrity and, optionally,
message confidentiality by "wrapping" or "unwrapping" data with a security layer. After the Bind has
completed the BindHandler will insert a MINA filter that handles security layer processing into the
IoFilterChain for the session that was SASL-authenticated. All subsequent LDAP operations will be
wrapped or unwrapped by the SaslFilter (assuming message integrity or privacy are negotiated). For
example, a subsequent search would arrive wrapped and thus must be unwrapped by the SaslFilter
prior to being ASN.1 decoded into a SearchRequest. Similarly, all outbound responses, including
errors and unbinds, will be wrapped by the SaslFilter.

Inbound --> SaslFilter --> decoder --> SearchHandler <--> backend


Outbound <-- SaslFilter <-- encoder <-------'

3.1.3. CRAM-MD5
Password must be stored as plaintext in the 'userPassword' attribute.

Username is matched to 'uid' under a base DN.

3.1.4. DIGEST-MD5
Password must be stored as plaintext in the 'userPassword' attribute.

Username is matched to 'uid' under a base DN.

Realm must match realms advertised by the LDAP server, but there is no multi-realm support yet.

25
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Authentication & Authorization Draft

3.1.5. GSSAPI
Principal name is matched to the 'krb5PrincipalName' attribute under a base DN.

No multi-realm support yet.

Principal configuration (user, service, krbtgt) can all occur on LDIF load.

3.1.6. Anonymous queries


RootDSE queries will never require authentication.

$ ldapsearch -s base -LLL supportedSASLMechanisms -x


supportedSASLMechanisms: GSSAPI
supportedSASLMechanisms: DIGEST-MD5
supportedSASLMechanisms: CRAM-MD5

When anonymous authentication is disabled , queries below the RootDSE will require authentication.
The following command will fail if anonymous access is disabled.

$ ldapsearch -b "dc=example,dc=com" "(uid=hnelson)" -x

3.1.7. SASL queries


CRAM-MD5 is a username/password mechanism.

$ ldapsearch -b "dc=example,dc=com" "(uid=hnelson)" -U hnelson -w secret -Y CRAM-MD5

DIGEST-MD5 is a username/password mechanism. DIGEST-MD5 also supports the concept of


"realm."

$ ldapsearch -b "dc=example,dc=com" "(uid=hnelson)" -U hnelson -w secret -Y DIGEST-MD5 -R example.com

GSSAPI will use the Kerberos credentials of the current user. GSSAPI supports the concept of "realm,"
but the realm is part of the username, eg 'hnelson@EXAMPLE.COM'.

$ ldapsearch -b "dc=example,dc=com" "(uid=hnelson)" -Y GSSAPI

3.1.8. Resources
IMAP/POP AUTHorize Extension for Simple Challenge/Response
http://www.ietf.org/rfc/rfc2195.txt

Using Digest Authentication as a SASL Mechanism


http://www.ietf.org/rfc/rfc2831.txt

RFC 4422 - Simple Authentication and Security Layer (SASL)


http://www.faqs.org/rfcs/rfc4422.html
This document obsoletes RFC 2222.

Lightweight Directory Access Protocol (LDAP): Directory Information Models


http://www.faqs.org/rfcs/rfc4512.html

RFC 4513 - Lightweight Directory Access Protocol (LDAP): Authentication Methods and Security
Mechanisms
http://www.faqs.org/rfcs/rfc4513.html
This document obsoletes RFC 2251, RFC 2829, and RFC 2830.

26
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Authentication & Authorization Draft

Simple Authentication and Security Layer (SASL) Mechanisms


http://www.iana.org/assignments/sasl-mechanisms

RFC 3829 - LDAP Authorization Identity Request and Response Controls


http://www.faqs.org/rfcs/rfc3829.html

3.2. HOWTO do SASL GSSAPI Authentication


to ApacheDS
3.2.1. Introduction
Apache Directory currently supports the SASL GSSAPI mechanism. SASL GSSAPI allows Kerberos
authentication to be used during LDAP Binds. Additionally, the GSSAPI mechanism can provide
message integrity (checksums) and, optionally, message privacy (encryption). When using SASL
message privacy, connections do not need SSL to protect communications.

3.2.2. Getting Started


1. Make sure you are using ApacheDS 1.5.1, which is currently (4-JUN-2007) only available from
the HEAD of trunk in svn. ( Section 1.2, “Building trunks” )

2. You can double-check your version of ApacheDS by interrogating the RootDSE for the supported
SASL mechanisms. Note the use of the fully-qualified domain name (FQDN), 'ldap.example.com'.
Regardless of the enabled authentication mechanisms, you will always be able to query the
RootDSE. You must see 'GSSAPI' in this returned list.

$ ldapsearch -H ldap://ldap.example.com:10389 -s base -LLL supportedSASLMechanisms -x


dn:
supportedSASLMechanisms: GSSAPI
supportedSASLMechanisms: DIGEST-MD5
supportedSASLMechanisms: CRAM-MD5

3. (OPTIONAL) Install GSSAPI support for LDAP tools on Linux. By default, some Linux variants
do not have SASL GSSAPI support installed. If Cyrus SASL GSSAPI is not present, install it with
an RPM maintenance tool such as 'yum'. Note that the SASL support in ApacheDS is unrelated to
the SASL library implementation being installed here.

$ rpm -qa | grep sasl


cyrus-sasl-lib-2.1.22-4
cyrus-sasl-2.1.22-4
...
cyrus-sasl-gssapi-2.1.22-4

$ yum install cyrus-sasl-gssapi

4. Open the server.xml for editing.

$ cd <trunk>/server-main
$ vi server.xml

5. Enable GSSAPI as a mechanism. GSSAPI is disabled by default.

<!-- The list of supported authentication mechanisms. -->


<property name="supportedMechanisms">
<list>
...
<value>GSSAPI</value>

27
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Authentication & Authorization Draft

</list>
</property>

6. Set the FQDN of the host. The FQDN must resolve, by hosts file, or DNS. Elements of the SASL
GSSAPI mechanism are extremely picky about the FQDN you use. The FQDN should be the top-
most entry in your hosts file or matching A and PTR records in DNS. If you are running the client
and the server on the same machine, you may need to set the FQDN to be your hostname. You
will likely find a sniffer (like WireShark) very handy for figuring out what hostnames are being
assumed and whether DNS is working properly.

<!-- The FQDN of this SASL host, validated during SASL negotiation. -->
<property name="saslHost" value="ldap.example.com" />

7. Set the service principal name that the server-side of the LDAP protocol provider will use to
"accept" a GSSAPI context initiated by the LDAP client. The SASL principal MUST follow
the name-form ldap/<fqdn>@<realm>. The 'ldap' name component and the @<realm> will be
automatically added to the FQDN by the LDAP client. The LDAP client will then use this as the
service principal name when requesting a service ticket from a KDC. In our case, the KDC is
ApacheDS, itself.

<!-- The Kerberos principal name for this LDAP service, used by GSSAPI. -->
<property name="saslPrincipal" value="ldap/ldap.example.com@EXAMPLE.COM" />

8. (OPTIONAL) Enforce quality-of-protection (QoP). The QoP level directly maps to the JNDI levels.
Listing all possible levels means any level will be accepted. Listing only 'auth-conf' will allow
only 'auth-conf' connections. These SASL QoP levels are global; they affect all connections using
DIGEST-MD5 or GSSAPI.

Table 3.1. SASL QoP levels


QoP Description
auth Use SASL for authentication only (no integrity
or confidentiality protection).
auth-int Use SASL with integrity protection. Integrity
basically means "with a checksum." For
GSSAPI integrity is always enabled.
auth-conf Use SASL with confidentiality protection.
Confidentiality means "with encryption."
Confidentiality is sometimes called privacy.
When Confidentiality is enabled, you do not
need SSL/TLS to protect connections.

<!-- The desired quality-of-protection, used by DIGEST-MD5 and GSSAPI. -->


<property name="saslQop">
<list>
<value>auth</value>
<value>auth-int</value>
<value>auth-conf</value>
</list>
</property>

9. Configure SASL realms. If the realm is not enabled, the connection will be rejected. Note that if
your realm does not appear here, you will see an error similar to "Nonexistent realm: dummy.com."

<!-- The realms serviced by this SASL host, used by DIGEST-MD5 and GSSAPI. -->
<property name="saslRealms">
<list>
<value>example.com</value>
<value>apache.org</value>

28
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Authentication & Authorization Draft

</list>
</property>

10.Set the search base DN. The search base DN is where a subtree-scoped DIT search will be
performed. This is BOTH where the LDAP service principal must reside, as well as where user
principals must reside. That all principals must reside in a single sub-tree is currently (4-JUN-2007)
a limitation of the SASL implementation. Work is underway to enable "multi-realm" capability, as
well as "split realm" capability. "Split realm" capability will allow you to split principals (users,
admins, services, machines) into separate subtrees.

<!-- The base DN containing users that can be SASL authenticated. -->
<property name="searchBaseDn" value="ou=users,dc=example,dc=com" />

11.Configure your host so that it knows where to get Kerberos tickets. On linux this is configured in '/
etc/krb5.conf'. The minimum config file must list the default Kerberos realm and the location of at
least one key distribution center (KDC). With ApacheDS, the KDC and LDAP server are the same,
so we'll re-use our 'ldap.example.com' hostname here.

[libdefaults]
default_realm = EXAMPLE.COM

[realms]
EXAMPLE.COM = {
kdc = ldap.example.com
}

[domain_realm]
.example.com = EXAMPLE.COM
example.com = EXAMPLE.COM

12.Enable the Kerberos protocol provider. By default, the LDAP protocol is enabled, but the Kerberos
protocol is not. You may also change the Kerberos port so that Kerberos can bind if you're logged-
in as a non-root user. If you change the default port of '88', you must change the KDC port in the
krb5.conf, as well.

<bean id="kdcConfiguration" class="org.apache.directory.server.kerberos.kdc.KdcConfiguration">


<!-- Whether to enable the Kerberos protocol. -->
<property name="enabled" value="true" />
<!-- The port to run the Kerberos protocol on. -->
<property name="ipPort" value="88" />
</bean>

13.Enable the KeyDerivationService. In contrast to the SIMPLE, CRAM-MD5, and DIGEST-MD5


SASL mechanisms, Kerberos authentication is based on symmetric keys. Since a user can't be
expected to remember a symmetric key, there are "key derivation functions" that will produce
symmetric key material based on the concatenation of the password, realm, and username. Any
changes to the user's password must result in new keys being generated. Luckily, ApacheDS has
the "KeyDerivationService" interceptor. This service will intercept any adds or modifications to the
user's 'userPassword' attribute and generate keys. Service principals typically use random keys, so
the interceptor will generate random keys when the special keyword 'randomKey' is used. Unlike
other combinations of separate LDAP and Kerberos servers, we do not need to export the service
principal keys to a keytab file from the KDC and use it to configure the LDAP server. Since
ApacheDS' LDAP and Kerberos protocol both have access to the DIT, we simply need to enable
the KeyDerivationService and add some principals.

<bean class="org.apache.directory.server.core.configuration.MutableInterceptorConfiguration">
<property name="name" value="keyDerivationService" />
<property name="interceptor">
<bean class="org.apache.directory.server.core.kerberos.KeyDerivationService" />
</property>
</bean>

29
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Authentication & Authorization Draft

14.Pre-load principals using an LDIF file. If the LDAP SASL GSSAPI mechanism is enabled but
the service principal is not found then you may see a WARN'ing in the server logs. With the
KeyDerivationService enabled, you should be able to use LDIFs or LDAP to configure principals
on-the-fly. For this example, since the LDIF format is concise, we review some LDIF entries.
You will find attached to this page an example LDIF. Download the LDIF [data/sasl-gssapi-
example.ldif] and configure the 'ldifDirectory' in server.xml.

<property name="ldifDirectory">
<value>/path/to/sasl-gssapi-example.ldif</value>
</property>

15.Review the LDIF entries. The metaphor for Kerberos comes from the fact that it is "three-headed";
there is always a KDC principal, service principal, and user principal. All of these principals use
the same objectClass'es. The attributes are the minimum to satisfy their respective schema, with
the exception of the Kerberos schema. Because we are using the KeyDerivationService, we don't
need to specify the Kerberos key, key types, or key version number (kvno); they are automatically
added by the interceptor, which will also increment the kvno when the password changes. Looking
at the LDIF file you'll see the ASL license, an organizational unit (ou) for our 'users' subcontext,
and the following entries:

Table 3.2. To be named


Entry RDN Password Principal Name Description
uid=hnelson userpassword: s3crEt krb5PrincipalName: Our user principal.
hnelson@EXAMPLE.COMNote the user
password.
uid=krbtgt userpassword: krb5PrincipalName: The KDC principal,
randomKey krbtgt/ with a random key.
EXAMPLE.COM@EXAMPLE.COM
uid=hostldap userpassword: krb5PrincipalName: The LDAP principal,
randomKey ldap/ with a random key.
ldap.example.com@EXAMPLE.COM

16.You are now ready to start the server. Upon startup, the server will load the entries from the LDIF.

$ cd <trunk>/server-main
$ ./apacheds.sh

17.Request a ticket-granting ticket (TGT) using 'kinit'. If you have not already "logged in," you must
request a fresh TGT. Without a TGT, 'ldapsearch', for example, will fail with error "No credentials
cache found." Also, if you don't specify the user principal, kinit will guess the principal name based
on the logged-in user and the realm configured in the krb5.conf.

$ kinit hnelson@EXAMPLE.COM
Password for hnelson@EXAMPLE.COM: <s3crEt>

18.You should now be able to query the DIT using Kerberos credentials. GSSAPI will use the Kerberos
credentials (TGT) of the current user. GSSAPI supports the concept of "realm," but the realm is part
of the username, eg 'hnelson@EXAMPLE.COM'. This is in contrast to other SASL mechanisms
where the realm is separately and explicitly specified.

$ ldapsearch -H ldap://ldap.example.com:10389 -b "dc=example,dc=com" "(uid=hnelson)" -Y GSSAPI

19.(OPTIONAL) List your Kerberos credentials. You'll see that in addition to a TGT, you also now
have a service ticket for the LDAP server.

30
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Authentication & Authorization Draft

$ klist -5fea
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: hnelson@EXAMPLE.COM
Valid starting Expires Service principal
06/04/07 20:42:19 06/05/07 20:41:37 krbtgt/EXAMPLE.COM@EXAMPLE.COM
Etype (skey, tkt): DES cbc mode with RSA-MD5, DES cbc mode with RSA-MD5
Addresses: (none)
06/04/07 20:42:22 06/05/07 20:41:37 ldap/ldap.example.com@EXAMPLE.COM
Etype (skey, tkt): DES cbc mode with RSA-MD5, DES cbc mode with RSA-MD5
Addresses: (none)

3.3. Start TLS with ApacheDS


3.3.1. Introduction
With Start TLS, the client sends an extended operation to the server that says 'after you send me a
positive response to this operation, flip the connection over to TLS'. Start TLS is a mechanism for
avoiding the need to listen on a separate port for SSL connections.

3.3.2. Testing LDAP binds with TLS


The following commands perform anonymous binds with TLS.

$ ldapsearch -H ldap://ldap.example.com/ -s base -LLL supportedSASLMechanisms -x -ZZ

can also use TLS (and SSL) with the SASL authentication mechanisms.

$ ldapsearch -H ldap://ldap.example.com -b "dc=example,dc=com" "(uid=hnelson)" -ZZ -Y DIGEST-MD5 -U hnelson -R exa


$ ldapsearch -H ldap://ldap.example.com -b "dc=example,dc=com" "(uid=hnelson)" -ZZ -Y CRAM-MD5 -U hnelson -w secre
$ ldapsearch -H ldap://ldap.example.com -b "dc=example,dc=com" "(uid=hnelson)" -ZZ -Y GSSAPI

Note that SSL certificates may be verified, depending on the LDAP client, so you should use the
FQDN of the ldap server that matches the cn in the certificate.

3.3.3. Resources
RFC 2830 - Lightweight Directory Access Protocol (v3): Extension for Transport Layer Security
http://www.faqs.org/rfcs/rfc2830.html

SSL and Custom Sockets


http://java.sun.com/products/jndi/tutorial/ldap/security/ssl.html

3.4. Writing a custom authenticator


This page is out of date

3.4.1. Using custom authenticators


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.directory.server.core.authn.AbstractAuthenticator;
import org.apache.directory.server.core.authn.LdapPrincipal;
import org.apache.directory.server.core.jndi.ServerContext;
import org.apache.directory.shared.ldap.aci.AuthenticationLevel;

31
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Authentication & Authorization Draft

import org.apache.directory.shared.ldap.name.LdapDN;

public class CustomAuthenticator extends AbstractAuthenticator {


public CustomAuthenticator() {
// create authenticator that will handle "simple" authentication mechanism
super("simple");
}

public void init() throws NamingException {


// ...
}

public LdapPrincipal authenticate(LdapDN bindDn, ServerContext ctx) throws NamingException {


// ...

LdapPrincipal principal = AbstractAuthenticator.createLdapPrincipal(bindDn.toNormName(), AuthenticationLev


// ..
return principal;

}
}

The authenticator class has to extend the


org.apache.directory.server.core.authn.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.

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 server.xml. You
can also optionally specify the location of a .properties file containing the initialization parameters.
See the following example:

EXAMPLE BELOW IS NO LONGER VALID WITH XML CONFIGURATION

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

3.5. Authorization
ApacheDS uses an adaptation of the X.500 basic access control scheme in combination with X.500
subentries to control access to entries and attributes within the DIT. This document will show you
how to enable the basic access control mechanism and how to define access control information to
manage access to protected resources.

3.5.1. Enabling Basic Access Controls


By default the access control subsystem is turned off. Once enabled everything is tightly locked down.
Only the special admin user, 'uid=admin,ou=system' , is not affected by permissions. Access to all

32
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Authentication & Authorization Draft

operations are denied by default until enabled using an ACIItem. For this reason enabling basic access
controls is a configuration option.

To turn on the basic access control mechanism you need to set the accessControlEnabled property
in the configuration to true. This can be set programatically on the StartupConfiguration or via the
server.xml.

3.5.2. Types of ACI (Access Control Information)


Three different types of ACI exist. All types use the same specification syntax for an ACIITem. These
types differ in their placement and manner of use within the directory.

3.5.2.1. Entry ACI


Entry ACI are access controls added to entries to protect that entry specifically. Meaning the protoected
entry is the entry where the ACI resides. When performing an operation on an entry, ApacheDS
checks for the presence of the multivalued operational attribute, entryACI. The values of the entryACI
attribute contain ACIItems.

There is one exception to the rule of consulting entryACI attributes within ApacheDS: add
operations do not consult the entryACI within the entry being added. This is a security
precaution. If allowed users can arbitrarily add entries where they wanted by putting entryACI
into the new entry being added. This could comprimise the DSA.

3.5.2.2. Prescriptive ACI


Prescriptive ACI are access controls that are applied to a collection of entries, not just to a single
entry. Collections of entries are defined by the subtreeSpecifications of subentries. Hence prescriptive
ACI are added to subentries as attributes and are applied by ApacheDS to the entries selected by
the subentry's subtreeSpecification. ApacheDS uses the prescriptiveACI multivalued operational
attribute within subentries to contain ACIItems that apply to the entry collection.

Prescriptive ACI can save much effort when trying to control access to a collection of resources.
Prescriptive ACI can even be specified to apply access controls to entries that do not yet exist within
the DIT. They are a very powerful mechanism and for this reason they are the prefered mechanism
for managing access to protected resources. ApacheDS is optimized specifically for managing access
to collections of entries rather than point entries themselves.

Users should try to avoid entry ACIs whenever possible, and use prescriptive ACIs instead. Entry
ACIs are more for managing exceptional cases and should not be used excessively.

3.5.2.3. Subentry ACI


Access to subentries also needs to be controlled. Subentries are special in ApacheDS. Although
they subordinate to an administrative entry (entry of an Administrative Point), they are technically
considered to be in the same context as their administrative entry. ApacheDS considers the perscriptive
ACI applied to the administrative entry, to also apply to its subentries.

This however is not the most intuitive mechanism to use for explicitly controlling access to subentries.
A more explicit mechanism is used to specify ACIs specifically for protecting subentries. ApacheDS
uses the multivalued operational attribute, subentryACI , within administrative entries to control
access to immediately subordinate subentries.

Protection policies for ACIs themselves can be managed within the entry of an administrative point.

3.5.3. Some Simple Examples


The ACIItem syntax is very expressive and that makes it extremely powerful for specifying complex
access control policies. However the syntax is not very easy to grasp for beginners. For this reason

33
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Authentication & Authorization Draft

we start with simple examples that focus on different protection mechanisms offered by the ACIItem
syntax. We do this instead of specifying the grammar which is not the best way to learn a language.

Please don't go any further until you have read up on the use of Subentries. Knowledge of
subentries, subtreeSpecifications, administrative areas, and administrative roles are required
to properly digest the following material.

Before going on to these trails you might want to set up an Administrative Area for managing
access control via prescriptiveACI. Both subentryACI and prescriptiveACI require the presence of an
Administrative Point entry. For more information and code examples see Section 3.5.4, “ACAreas” .

3.5.3.1. ACI Trails


Here are some trails that resemble simple HOWTO guides. They're ordered with the most pragmatic
usage first. We will add to these trails over time.

Table 3.3. ACI Trails


Trail Description
Section 3.5.6, “EnableSearchForAllUsers” access to browse and read all entries and their
attributes by authenticated users.
DenySubentryAccess (TBW) Protecting access to subentries themselves.
Section 3.5.5, “AllowSelfPasswordModify” Granting users the rights needed to change their
own passwords.
GrantAddDelModToGroup (TBW) Granting add, delete, and modify permissions to a
group of users.
GrantModToEntry (TBW) Applying ACI to a single entry.

3.5.4. ACAreas
3.5.4.1. Introduction
This guide will show you how to create an Access Control Specific Area and Access Control
Inner Areas for administering access controls within ApacheDS. Basic knowledge of the X.500
administrative model is presumed along with an understanding of the Basic Access Control Scheme
in X.501. For quick primers please take a look at the following documentation:

• ??? and the Section 2.3, “The Administrative Model”

• Section 3.5, “Authorization”

3.5.4.2. Creating Access Control Specific Areas (ACSA)


An access control specific area is an Autonomous Administrative Area (AAA) for managing access
control specific aspects of a subtree within the DIT. Like all administrative areas, an access control
specific area is rooted at a vertex entry called the Administrative Point (AP). The ACSA spans down
until leaf entries are encountered or until another ACSA is encountered. Access control specific areas
do not overlap.

Under the AP, you can add subentries that contain prescriptiveACI attributes. Zero or more subentries
can be added, each with one or more prescriptiveACI. These subentries apply access control
information (ACI) in these prescriptiveACI attributes to collections of entries within the ACSA.

3.5.4.2.1. Adding an 'administrativeRole' Attribute


An entry becomes an AP when it has an administrativeRole attribute added to it with the appropriate
value(s). For an ACSA, we need to add the 'accessControlSpecificArea' value to this attribute.

34
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Authentication & Authorization Draft

Most of the time users will create partitions in the server and set the root context of the partition
(its suffix) to be the AP for a ACSA. For example the default server.xml for ApacheDS ships with a
partition with the suffix, 'dc=example,dc=com'. We can use this suffix entry as the AP and our ACSA
can cover all entries under and including 'dc=example,dc=com'.

The code below binds to the server as admin ('uid=admin,ou=system') and modifies the suffix entry
to become an ACSA. Note that we check to make sure the attribute does not already exist before
attempting the add operation.

...
// Get a DirContext on the dc=example,dc=com entry
Hashtable env = new Hashtable();
env.put( "java.naming.factory.initial", "com.sun.jndi.ldap.LdapCtxFactory" );
env.put( "java.naming.provider.url", "ldap://localhost:389/dc=example,dc=com" );
env.put( "java.naming.security.principal", "uid=admin,ou=system" );
env.put( "java.naming.security.credentials", "secret" );
env.put( "java.naming.security.authentication", "simple" );
ctx = new InitialDirContext( env );

// Lookup the administrativeRole specifically since it is operational


Attributes ap = ctx.getAttributes( "", new String[] { "administrativeRole" } );
Attribute administrativeRole = ap.get( "administrativeRole" );

// If it does not exist or has no ACSA value then add the attribute
if ( administrativeRole == null || ! administrativeRole.contains( "accessControlSpecificArea" ) )
{
Attributes changes = new BasicAttributes( "administrativeRole", "accessControlSpecificArea", true );
ctx.modifyAttributes( "", DirContext.ADD_ATTRIBUTE, changes );
}
...

This simple modification of adding the value 'accessControlSpecificArea' to the administrativeRole


makes the suffix entry 'dc=example,dc=com' an AP for an access control specific area. Now you can
add subentries to your heart's content which subordinate to the AP.

3.5.4.3. Creating an Access Control Inner Administrative Area


Creating an inner area involves the same process. In fact the same code can be used by
changing the value added to the administrativeRole attribute. To create the inner area just add
'accessControlInnerArea' for the administrativeRole within the AP: same steps, same code, different
value for the administrativeRole.

3.5.4.4. Access Control Subentries


After creating the access control area you can create subentries that subordinate to this AP for
managing access to it and anything below. Access control subentries are entries with the objectClasses:
'subentry' and 'accessControlSubentry'. An access control subentry must contain 3 attributes other than
the obvious objectClass attribute. These required attributes are listed below:

Table 3.4. Access Control Subentries


Attribute SINGLE-VALUED Description
cn no The name of the subentry used as
its RDN
subtreeSpecification yes The specification for the
collection of entries the ACI is to
be applied to.
prescriptiveACI no The attribute holding the
ACIItem

3.5.5. AllowSelfPasswordModify

35
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Authentication & Authorization Draft

{
identificationTag "allowSelfAccessAndModification",
precedence 14,
authenticationLevel none,
itemOrUserFirst userFirst:
{
userClasses { thisEntry },
userPermissions
{
{ protectedItems {entry}, grantsAndDenials { grantModify, grantBrowse, grantRead } },
{ protectedItems {allAttributeValues {userPassword}}, grantsAndDenials { grantAdd, grantRemove } }
}
}
}

3.5.5.1. Commentary
Note that two different user permissions are used to accurately specify self access and self modification
of the userPassword attribute within the entry. So with the first userPermission of this ACI a user
would be able to read all attributes and values within his/her entry. They also have the ability to modify
the entry but this is moot since they cannot add, remove or replace any attributes within their entry. The
second user permission completes the picture by granting add and remove permissions to all values
of userPassword. This means the user can replace the password.

3.5.6. EnableSearchForAllUsers
3.5.6.1. Enable Authenticated Users to Browse and Read Entries
in a Subtree
We presume this is your first encounter and so many bases will be covered this time around.
Every other trail will build on this information. So expect a little less to read as you gain
momentum.

Since the entire directory is locked down for all but the superuser, you're going to want to grant read
and browse access to users for certain regions of the DIT. This will probably be the first thing you'll
want to do after turning on access controls.

3.5.6.1.1. Check for insufficientAccessRights for Normal Users


Just to make sure everything is locked down login as admin and create a new non-superuser. For more
information on how to do this see ??? . After creating the normal user make sure you cannot bind
to dc=example,dc=com with access controls enabled. You should get an error trying to bind with a
result code of 50 (insufficientAccessRights). If using JNDI to connect to the server you should get a
NoPermissionException. After we apply the following ACI you can check again.

3.5.6.1.2. Partition and Access Control Area Setup


For this example we presume you have setup a partition at the namingContext dc=example,dc=com
and have turned on access controls. Now you want to grant browse and read access to entries and
their attributes.

Before you can add a subentry with the prescriptiveACI you'll need to create an administrative area.
For now we'll make the root of the partition the adminstrative point (AP). Every entry including this
entry and those underneath it will be part of the autonous administrative area for managing access
controls. To do this we must add the administrativeRole operational attribute to the AP entry. See ???
for code and information about creating access control administrative areas.

3.5.6.1.3. Adding the Subentry


The subentry can be added using an LDIF or via code. We'll show the code but the LDIF can be
accessed here enableSearchForAllUsers.ldif [data/enableSearchForAllUsers.ldif] :

36
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Authentication & Authorization Draft

// Get a DirContext on the dc=example,dc=com entry


Hashtable env = new Hashtable();
env.put( "java.naming.factory.initial", "com.sun.jndi.ldap.LdapCtxFactory" );
env.put( "java.naming.provider.url", "ldap://localhost:" + port + "/dc=example,dc=com" );
env.put( "java.naming.security.principal", "uid=admin,ou=system" );
env.put( "java.naming.security.credentials", "secret" );
env.put( "java.naming.security.authentication", "simple" );
ctx = new InitialDirContext( env );

// now add the A/C subentry below dc=example,dc=com


Attributes subentry = new BasicAttributes( "cn", "enableSearchForAllUsers", true );
Attribute objectClass = new BasicAttribute( "objectClass" );
subentry.put( objectClass );
objectClass.add( "top" );
objectClass.add( "subentry" );
objectClass.add( "accessControlSubentry" );
subentry.put( "subtreeSpecification", "{}" );
subentry.put( "prescriptiveACI",
"{ \n" +
" identificationTag \"enableSearchForAllUsers\",\n" +
" precedence 14,\n" +
" authenticationLevel simple,\n" +
" itemOrUserFirst userFirst: \n" +
" { \n" +
" userClasses { allUsers }, \n" +
" userPermissions \n" +
" { \n" +
" {\n" +
" protectedItems {entry, allUserAttributeTypesAndValues}, \n" +
" grantsAndDenials { grantRead, grantReturnDN, grantBrowse } \n" +
" }\n" +
" } \n" +
" } \n" +
"}" );
ctx.createSubcontext( "cn=enableSearchForAllUsers", subentry );

Before we cover the anatomy of this ACIItem, you might want to add the subentry and test access
with a normal non-super user to make sure access is now granted.

3.5.6.1.4. ACIItem Description


Here's the ACIItem you just added above without all the Java clutter:

{
identificationTag "enableSearchForAllUsers",
precedence 14,
authenticationLevel simple,
itemOrUserFirst userFirst:
{
userClasses { allUsers },
userPermissions
{
{
protectedItems {entry, allUserAttributeTypesAndValues},
grantsAndDenials { grantRead, grantReturnDN, grantBrowse }
}
}
}
}

There are several parameters to this simple ACIItem. Here's a breif exaplanation of each field and it's
meaning or significance.

Table 3.5. ACIItem fields


Fields Description
identificationTag Identifies the ACIItem within an entry.
precedence Determine which ACI to apply with conflicting
ACIItems.
authenticationLevel User's level of trust with values of none, simple,
strong

37
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Authentication & Authorization Draft

Fields Description
itemOrUserFirst Determines order of item permissions or user
permissions.
userClasses The set of users the permissions apply to.
userPermissions Permissions on protected items

3.5.6.1.4.1. identificationTag

The identificationTag is just that a tag. It's often used with a subtring search filter to lookup a specific
ACIItem within an entry. One or more ACIItems may be present within a subentry, zero or more in
entries, so this serves as a means to address the ACIItem within entries.

3.5.6.1.4.2. precedence

Precendence is used to determine the ACI to apply when two or more ACIItem's applied to an entry
conflict. The ACIItem with the highest precedence is applied over other conflicting ACIItems.

When two or more conflicting ACIItems are encountered with the same precedence the
ACIItems with denials overpower ACIItems with grants.

Right now the use of this field may not mean too much to you. We're dealing with a very simple
situation with a single access control area. Later as you add more subentries their subtreeSpecifications
may define collections that intersect. When this happens two or more conflicting ACIItems may apply
to the same entry. Precendence is then applied to determine which permissions apply.

Another complex situation requiring precedence is the use of inner areas. These nested inner
administrative areas overlap and so do their effects. The authority within an AA may deny some
operation to all entries but grant access to subentries of inner areas so minor authorities can control
access to inner areas. Their grants to users may need to have a higher precedence over denials in outer
areas. Such situations will arise and precedence will need to be used. In this example we just assign
an arbitrary value to the precedence.

3.5.6.1.4.3. authenticationLevel

The authenticationLevel is the minimum authentication requirement for requestor for the ACI to by
applied: According to X.501:

The authenticationLevel can have three values: none, simple and strong. It's used to be able to associate
permissions with the level of trust in users. For none, the identity of the user is anonymous or does
not matter. The user can be anyone. The simple authenticationLevel means the user has authenticated
but is using a simple bind with clear text passwords. The strong authenticationLevel represents users
that bind to the directory using strong authentication mechanisms via SASL.

SASL can allow annonynous binds as well so there is a distinction here. Using SASL alone does
not mean the authenticationLevel is strong. As we add SASL mechanisms to the server, we'll qualify
each one with none, simple or strong. This will be reflected in the authenticationLevel property of the
principal making requests.

3.5.6.1.4.4. itemOrUserFirst

This field describes the order of information within the ACI whether protected items are described first
or user classes and permissions are described first. For simplicity we will only describe the userFirst
configuration in this tutorial.

3.5.6.1.4.5. userClasses

UserClasses is used to list the sets of users to which this permission applies. Several mechanisms can
be used here to define userClasses. They can be defined by name per user, by group membership, or
by the superset of all users possible and many more. In our example we have applied the ACI to all
users that have authenticated by simple or strong means.

38
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Authentication & Authorization Draft

For more information see Section 3.5.7, “UserClasses” .

3.5.6.1.4.6. userPermissions

These are the permissions granted or denied to those users included by the userClasses field. The
grants or denials however are qualified by the protected items operated upon. In our example we grant
read, return DN and browse to all entries, their attributes and all possible values they may have.

For more information see ??? .

3.5.7. UserClasses
3.5.7.1. What are User Classes?
A large part of managing access control information involves the specification of who can perform
which operation on what protected resource (entries, attributes, values etc). At evaluation time a
requestor of an operation is known. The identity of the requestor is checked to see if it falls into the
set of users authorized to perform the operation. User classes are hence definitions of a set of zero or
more users permissions apply to. Several constructs exist for specifying a user class.

3.5.7.2. Simple User Classes


There are 3 really simple constructs for specifying the user. These constructs are listed in the table
below:

Table 3.6. Simple User Classes


User Class Construct Meaning Example
allUsers Any user with possible allUsers
requirements for
AuthenticationLevel
thisEntry The user with the same DN as thisEntry
the entry being accessed
name The user with the specified DN name
{ "uid=admin,ou=system" }

These are pretty intuitive. Two other user classes may be a bit less easy to understand or may require
some explanation. For these we discuss them in the sections below.

3.5.7.3. User Class: userGroup


The userGroup user class construct is also pretty intuitive. It does however require some background
information about how group membership is determined for this purpose.

ApacheDS associates users within a group using the groupOfNames and groupOfUniqueNames
objectClasses. To define groups an entry of either of these objectClasses is added anywhere in the
server's DIT. member or uniqueMember attributes whose values are the DN of user entries are
present within the entry to represent membership within the group.

Although such group entries can be added anywhere within the DIT to be recognized by the
Authorization subsystem, a recommended convention exists. Use the 'ou=groups' container
under a namingContext/partition within the server to localize groups. Most of the time group
information can be stored under 'ou=groups,ou=system'.

Just like the name construct, the userGroup construct takes a single parameter: the DN of the group
entry. During ACI evaluation ApacheDS checks to see if the requestor's DN is contained within the
group. Below is a section from X.501 specification which explains just how this is done:

39
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Authentication & Authorization Draft

Section 18.4.2.5 Determining group membership (b)

In order to determine whether the requestor is a member of a userGroup user class, the following
criteria apply:

• The entry named by the userGroup specification shall be an instance of the object class
groupOfNames or groupOfUniqueNames.

• The name of the requestor shall be a value of the member or uniqueMember attribute of that entry.

3.5.7.4. User Class: subtree


Here the user class specification construct is a subtree specification without a refinement filter. Such
a specification is simple yet very powerful. The subtree defines a collection of entries. During ACI
evaluation, ApacheDS will check to see if the requestor's DN is included by this collection.

For more information on how to define a subtreeSpecification please see ??? and Section 2.3, “The
Administrative Model” .

For this purpose a subtree is not refined. Meaning it does not evaluate refinement filters. This
is to restrict the information needed to make a determination to just the DN of the requestor
and not the entry of the requestor.

3.5.8. Combining Multiple UserClass Specification


Mechanisms
The same userClass mechanism can be specified more than once if it makes sense. There is no reason
to specify allUsers more than once. More than one type of user class mechanism can be used as well.
Again some combinations just will not make sense like having a name based userClass then allUsers.
The following ACIItem grants delete abilities to a set of users using more than one machanism. It
allows jbean, jdoe, all users in the Administrators group to delete entries. It also allows requestors to
delete their own user entry.

{ identificationTag "deleteAci"
precedence 255,
authenticationLevel simple,
itemOrUserFirst userFirst:
{
userClasses
{
thisEntry,
name { "uid=jbean,ou=users,ou=system" },
name { "uid=jdoe,ou=users,ou=system" },
userGroup { "cn=Administrators,ou=groups,ou=system" }
},
userPermissions { { protectedItems {entry}, grantsAndDenials { grantRemove } } }
}
}

40
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Draft

Chapter 4. Attributes, Entries &


Schemas
4.1. Add your first elements to the schema
This section shows how to define custom schema elements, and how to add them to an ApacheDS
1.5 instance.

• Section 4.1.1, “Motivation”

• Section 4.1.2, “Browsing the schema of ApacheDS”

• Section 4.1.3, “Which OIDs should you use?”

• Section 4.1.4, “A simple example”

• Section 4.1.5, “Using Apache Directory Studio Schema Editor to load the new schema elements”

• Section 4.1.6, “Using LDIF to load schema elements in RFC 4512 format”

• Section 4.1.7, “Using JNDI to add the schema elements programmatically”

• Section 4.1.8, “Using JNDI to add schema elements in RFC 4512 format programmatically”

• Section 4.1.9, “Resources”

4.1.1. Motivation
The schema of an LDAP server is comprised of object classes, attributes, syntaxes and matching rules.
Basically it defines which entries are allowed within the server and how the server should handle them.
In contrast to the 1.0 release, ApacheDS 1.5.0 comes with a completely redesigned schema subsystem.
It enables dynamic schema updates, like the creation of new attribute types or object classes at runtime
(i.e. without restarting the server).

No. ApacheDS comes with a comprehensive set of predefined, standardized schema elements
(like inetOrgPerson ). It is quite common to solely use the predefined schema. The same holds
true for other directory servers, by the way.

In the following text the addition of user defined schema elements to the schema is described in tutorial
style.

4.1.2. Browsing the schema of ApacheDS


LDAPv3 servers publish their schema via LDAP. Thus it is possible to list the schema elements with
standard LDAP tools. For instance it is possible to use the ldapsearch command line tool to list all
object classes

$ ldapsearch -h zanzibar -p 10389 -D "uid=admin,ou=system" -w ****** \


-b "cn=schema" -s base "(objectclass=subschema)" objectclasses
...
objectClasses: ( 2.5.6.6 NAME 'person' DESC 'RFC2256: a person' SUP top
STRUCTURAL MUST ( sn $ cn ) MAY ( userPassword $ telephoneNumber $
seeAlso $ description ) X-SCHEMA 'core' )
...

41
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Attributes, Entries & Schemas Draft

The output (formatted as defines in RFC 4512 [http://www.ietf.org/rfc/rfc4512.txt] ) contains all things
which are interesting to know about an object class (required attributes, optional attributes etc.), but
is not easy to read by a human user. It is therefore often appropriate to use a GUI tool to browse the
schema (which basically performs the same search operations but presents the output prettily). One
option is Apache Directory Studio [http://directory.apache.org/studio/] , an Eclipse based LDAP tool
set which contains a powerful graphical Schema browser:

Figure 4.1. Schema Browser Person

The techniques described above work for all LDAP v3 compliant servers. The ability to browse the
schema gives us a chance to check whether our future changes to the schema really took place.

The schema subsystem of ApacheDS 1.5 stores the schema elements as entries in the DIT. You can
find them within a special partition with suffix ou=schema ; simply browse the content with your
favorite LDAP Browser. With Apache Directory Studio, it looks like this:

42
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Attributes, Entries & Schemas Draft

Figure 4.2. Schema Browser Tree

Browsing the schema like this gives a good impression of the ApacheDS implementation of the schema
subsystem and an even better way to analyze effects during schema updates. But keep in mind that the
storage scheme is server dependent; not all LDAP server implementations store the schema elements
in the DIT.

4.1.3. Which OIDs should you use?


If you plan to add custom schema elements, you need numerical OIDs (object identifiers) for them. If
you implement schema elements defined somewhere else (like eduPerson [http://www.educause.edu/
eduperson/] ), you can use the OIDs which are are part of their descriptions. But what if you plan to
design your own?

4.1.3.1. Some OID background information


An OID is a string formed by a series of numbers which are seperated by a dot (like "12.4.1971.0.1").
Many elements in directory world use OIDs: Controls, extended operations and schema elements (like
"2.5.6.6" for object class person). They identify these objects in a unique fashion and therefore avoid
name clashes.

How is this accomplished? OIDs are assigned hierarchically: The owner of an OID is allowed to create
new IDs by simply appending numbers. S/he is also allowed to delegate ownership of newly created

43
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Attributes, Entries & Schemas Draft

OIDs to someone else. This way every person or organization is able to allocate an arbitrary number
of new OIDs after obtaining one from "higher command", and they are still unique world-wide.

4.1.3.2. OIDs in the example


OIDs starting with 1.3.6.1.4.1 represent IANA-registered private enterprises, Apache Software
Foundation for instance owns the OID 1.3.6.1.4.1.18060. The 1.3.6.1.4.1.18060.0 has been
assigned to the Apache Directory project by the ASF, and we have decided to use the branch
"1.3.6.1.4.1.18060.0.4.3" for schema elements used as examples in the documentation.

4.1.3.3. OIDs for your own custom schema elements


If you just want to play around with the schema subsystem, want to explore the capabilities, or learn
about LDAP in general, you will probably not mind about unique OIDs. This is comparable to using
self-signed certificates for SSL experiments. But it is nevertheless necessary that you use OIDs which
are not used in the schema yet (otherwise addition will fail).

But if you plan to use your schema elements in a production environment (an object class for instance
which describes employees with company specific attributes), or to ship your schema elements with
a product (e.g. a CRM or portal solution), you should definitely use unique OIDs. In order to do this
you have to obtain OIDs from a branch assigned to your company or organization (your network
administrators will be helpful here, do not invent OIDs without asking or obtaining a branch from
someone who owns the prefix OID). If your company or organization does not own on OID, there
are several option to obtain one, one is the IANA (Internet Assigned Numbers Authority). It is also
possible to get an OID branch as an individual.

You can ask for your own PEN (Private Enterprise Number) here : http://pen.iana.org/pen/
PenApplication.page It takes a few weeks to have a private OID assigned to you, so be patient,
or do it early !

4.1.4. A simple example


The goal is to store ship entries in our directory, backing the "Seven Seas" example used throughout
the Basic User's Guide. There are no schema elements shipped with ApacheDS covering our naval
requirements. So we add some.

Here is a sample entry for a ship in LDIF:

dn: cn=HMS Victory,ou=ships,o=sevenSeas


objectClass: top
objectClass: ship
cn: HMS Victory
numberOfGuns: 104
description: a ship of the line of the Royal Navy
description: built between 1759 and 1765

A ship entry is comprised of a mandatory value for common name ( cn ) of the ship, description values
and the number of guns ( numberOfGuns ). Thus a new object class ship and a new attribute type
numberOfGuns have to be added to the schema. There are different ways to accomplish the task. In
any case, we have to add the attribute type first, because the object class refers to it.

4.1.4.1. attribute type numberOfGuns


Here is the definition of our custom attribute type numberOfGuns formatted according to RFC 4512.

( 1.3.6.1.4.1.18060.0.4.3.2.1
NAME 'numberOfGuns' DESC 'Number of guns of a ship'
EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27

44
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Attributes, Entries & Schemas Draft

SINGLE-VALUE
)

4.1.4.2. object class ship


Custom object class ship is defined as follows

( 1.3.6.1.4.1.18060.0.4.3.3.1
NAME 'ship' DESC 'An entry which represents a ship'
SUP top STRUCTURAL
MUST cn MAY ( numberOfGuns $ description )
)

4.1.5. Using Apache Directory Studio Schema Editor to


load the new schema elements
A very convenient way to add your own schema elements to Apache Directory Server is to use the
Schema Editor of Apache Directory Studio. It is even possible to define/design them within the UI,
but we opt here use a prepared file in OpenLDAP format and import it using Studio. This is a good
choice if you have the schema to add already described that way.

Our file sevenSeas.schema [data/sevenSeas.schema] looks like this:

attributetype ( 1.3.6.1.4.1.18060.0.4.3.2.1
NAME 'numberOfGuns'
DESC 'Number of guns of a ship'
EQUALITY integerMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
SINGLE-VALUE
)
objectclass ( 1.3.6.1.4.1.18060.0.4.3.3.1
NAME 'ship'
DESC 'An entry which represents a ship'
SUP top
STRUCTURAL
MUST cn
MAY ( numberOfGuns $ description )
)

In Eclipse with the Apache Directory Studio plugins installed (or alternatively the standalone RCP
application of Apache Directory Studio, if you prefer this), open the Schemas view.

45
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Attributes, Entries & Schemas Draft

Figure 4.3. Schemas view

When it is shown, press the Open a schema file button in the toolbar of it. In the file dialog, open the
sevenSeas.schema . It is loaded and added to the schemas within the view.

Figure 4.4. Schemas view with loaded schemas

Select Export For ApacheDS ... in the context menu of the sevenSeas elements. The schema will
be stored in an LDIF file which can directly be imported into ApacheDS (we choose the file name
sevenSeas.ldif [data/sevenSeas.ldif] ).

Use Apache Directory Studio to open a connection to your ApacheDS server, bind as administrator,
and select Import | LDIF Import ... in the context menu of the DIT. Choose the LDIF file previously
stored, and import the file. Alternatively, you can use command line tools like ldapmodify to load the
file. If no errors are displayed, you are done.

There are several options to check whether the additions has be successful. One is to use the browse
techniques described above. You can also use specific search commands like this one:

46
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Attributes, Entries & Schemas Draft

$ ldapsearch -h zanzibar -p 10389 -D "uid=admin,ou=system" -w ****** \\


-b "ou=schema" -s sub "(m-name=numberOfGuns)"
version: 1
dn: m-oid=1.3.6.1.4.1.18060.0.4.3.2.1,ou=attributeTypes,cn=other,ou=schema
m-usage: USER_APPLICATIONS
m-equality: integerOrderingMatch
objectClass: metaAttributeType
objectClass: metaTop
objectClass: top
m-name: numberOfGuns
m-oid: 1.3.6.1.4.1.18060.0.4.3.2.1
m-singleValue: TRUE
m-description: Number of guns of a ship
m-collective: FALSE
m-obsolete: FALSE
m-noUserModification: FALSE
m-syntax: 1.3.6.1.4.1.1466.115.121.1.27

Of course it visible possible within the Apache Directory Studio UI as well. You will likely have to
refresh the schema to see the new elements in the schema browser

Figure 4.5. Schema browser ship

Now you are done: The schema elements are ready to use. Feel free to add your fleet!

Figure 4.6. Entry editor with ship

47
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Attributes, Entries & Schemas Draft

4.1.6. Using LDIF to load schema elements in RFC


4512 format
You could write an LDIF with your schema elements in RFC 4512 format and import the LDIF using
command line or Apache Directory Studio. The LDIF for our example looks like this:

dn: cn=schema
changetype: modify
add: attributeTypes
attributeTypes: ( 1.3.6.1.4.1.18060.0.4.3.2.1
NAME 'numberOfGuns'
DESC 'Number of guns of a ship'
EQUALITY integerMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
SINGLE-VALUE
)
-
add: objectClasses
objectClasses: ( 1.3.6.1.4.1.18060.0.4.3.3.1
NAME 'ship'
DESC 'An entry which represents a ship'
SUP top
STRUCTURAL
MUST cn
MAY ( numberOfGuns $ description )
)
-

4.1.7. Using JNDI to add the schema elements


programmatically
You may want to add schema elements programmatically (for instance in a unit test) via a Java program
acting as a client. One option here is to use JNDI and its LDAP provider. The advantage of this
approach is that it is server independent; it works on LDAP servers other than ApacheDS as well as
long as the server supports dynamic updates and the bind user is allowed to perform these operations
(normally only admistrators are allowed to do this).

4.1.7.1. Some simple Java programs


In the following you find source code examples on how to add the two elements. The proceeding
is described in more detail in the JNDI Tutorial [http://java.sun.com/products/jndi/tutorial/] (Chapter
"Tips for LDAP Users // Schema "). Both use connection data provided by jndi.properties of the
following form

java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory
java.naming.provider.url=ldap://zanzibar:10389/
java.naming.security.principal=uid=admin,ou=system
java.naming.security.credentials=******
java.naming.security.authentication=simple

This simple program (file CreateAttributeType.java [data/CreateAttributeType.java] ) creates the


attribute type numberOfGuns

import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;

public class CreateAttributeType {

public static void main(String[] args) throws NamingException {

DirContext ctx = new InitialDirContext();


DirContext schema = ctx.getSchema("");

48
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Attributes, Entries & Schemas Draft

Attributes attrs = new BasicAttributes(true);


attrs.put("NUMERICOID", "1.3.6.1.4.1.18060.0.4.3.2.1");
attrs.put("NAME", "numberOfGuns");
attrs.put("DESC", "Number of guns of a ship");
attrs.put("EQUALITY", "integerOrderingMatch");
attrs.put("SYNTAX", "1.3.6.1.4.1.1466.115.121.1.27");
attrs.put("SINGLE-VALUE", "true");

schema.createSubcontext("AttributeDefinition/numberOfGuns", attrs);
}
}

and this one (file CreateObjectClass.java [data/CreateObjectClass.java] ) the object class ship

import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;

public class CreateObjectClass {

public static void main(String[] args) throws NamingException {

DirContext ctx = new InitialDirContext();


DirContext schema = ctx.getSchema("");

Attributes attrs = new BasicAttributes(true);


attrs.put("NUMERICOID", "1.3.6.1.4.1.18060.0.4.3.3.1");
attrs.put("NAME", "ship");
attrs.put("DESC", "An entry which represents a ship");
attrs.put("SUP", "top");
attrs.put("STRUCTURAL", "true");

Attribute must = new BasicAttribute("MUST");


must.add("cn");
attrs.put(must);

Attribute may = new BasicAttribute("MAY");


may.add("numberOfGuns");
may.add("description");
attrs.put(may);

schema.createSubcontext("ClassDefinition/ship", attrs);
}
}

After successfully running the programs against the LDAP server defined in the connection data. The
schema elements can also be found within a schema browser, but you may have to refresh the schema
here as well. They are also ready to use

A final note for the JNDI approach: With the code shown above, the elements will be created by the
ApacheDS schema subsystem within the other schema (in contrast to the sevenSeas schema ). You
can also create them programmatically in a specific schema with the help of the X-SCHEMA attribute:

...
attrs.put("X-SCHEMA", "sevenSeas");
...

but in this case you have to create the skeleton entries for the sevenSeas schema before (loading an
LDIF file like the one generated by Apache Directory Studio as depicted above). Otherwise you will
get an NamingException ("LDAP: error code 54 - failed to modify entry cn=schema ...").

4.1.8. Using JNDI to add schema elements in RFC 4512


format programmatically
It is also possible to add schema elements in RFC 4512 format using JNDI:

49
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Attributes, Entries & Schemas Draft

import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;

public class CreateSevenSeasSchema


{

public static void main(String[] args) throws NamingException


{
DirContext ctx = new InitialDirContext();

Attributes atAttrs = new BasicAttributes(true);


atAttrs.put("attributeTypes",
"( 1.3.6.1.4.1.18060.0.4.3.2.1 NAME 'numberOfGuns' DESC 'Number of guns of a ship' EQUALITY integerMatch
ctx.modifyAttributes("cn=schema", DirContext.ADD_ATTRIBUTE, atAttrs);

Attributes ocAttrs = new BasicAttributes(true);


ocAttrs.put("objectClasses",
"( 1.3.6.1.4.1.18060.0.4.3.3.1 NAME 'ship' DESC 'An entry which represents a ship' SUP top STRUCTURAL MU
ctx.modifyAttributes("cn=schema", DirContext.ADD_ATTRIBUTE, ocAttrs);
}

4.1.9. Resources
• Internet Assigned Numbers Authority (IANA)
http://www.iana.org

• Apache Directory Studio [http://directory.apache.org/ldapstudio/] , a complete LDAP tooling


platform

• RFC 4512 [http://www.ietf.org/rfc/rfc4512.txt] Lightweight Directory Access Protocol (LDAP):


Directory Information Models, Section 4: Directory Schema

• The JNDI Tutorial [http://java.sun.com/products/jndi/tutorial/] at Sun Microsystems

4.2. Collective Attributes


This page needs to be overworked

4.2.1. Introduction
Collective attributes are attributes whose values are shared across a collection of entries. It's very
common to encounter situations where a bunch of entries have the same value for an attribute.
Collective attributes for LDAP are defined in RFC 3671 [http://www.faqs.org/rfcs/rfc3671.html] .
ApacheDS implements this RFC.

4.2.1.1. Use Case


For example one might organize everyone in an engineering department under an ou, 'ou=engineering'.
If the engineering team is located in the same area and building then several attributes in each user
entry within engineering will have the same value. An example of such an attribute would be the locale.
If engineering is located in Sunnyvale CA then all locale attributes of entries under 'ou=engineering'
would be set to Sunnyvale.

Rather than manage the value for this attribute in each entry a single collective attribute can be used
in a subentry. Changes to the value of this attribute would immediately be reflected to those entries
selected by the subtreeSpecification of subentry. For more information on specifying subtrees take
at ??? .

50
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Attributes, Entries & Schemas Draft

4.2.2. Setting up a Collective Attribute Administration


Area (AA)
To manage collective attributes for a collection of entries you must add collective subentries to
the Administrative Point (AP) of the collective AA. For more information on AAs see ??? . These
collective subentries must have the objectClass subentry as well as collectiveAttributeSubentry.
Also the AP, of the AA, must have an administrativeRole value of collectiveAttributeSpecificArea
(2.5.23.5) or collectiveAttributeInnerArea (2.5.23.6).

4.2.2.1. Example
For the use case above we can presume a partition at the namingContext 'dc=example,dc=com' with an
'ou=engineering' entry below containing users from the engineering team in Sunnyvale. Let's presume
no AA has yet been defined so we have to create one. We'll set the partition root 'dc=example,dc=com'
as the AP of an AA that spans the entire subtree. For this simple example the AA will be autonomous
for the collective aspect. Setting this up is just a matter of modifying the 'dc=example,dc=com' entry so
it contains the operational attribute administrativeRole with the value collectiveAttributeSpecificArea.
The code below sets up this AAA for collective attribute administration.

// Get a DirContext on the dc=example,dc=com entry


Hashtable env = new Hashtable();
env.put( "java.naming.factory.initial", "com.sun.jndi.ldap.LdapCtxFactory" );
env.put( "java.naming.provider.url", "ldap://localhost:" + port + "/dc=example,dc=com" );
env.put( "java.naming.security.principal", "uid=admin,ou=system" );
env.put( "java.naming.security.credentials", "secret" );
env.put( "java.naming.security.authentication", "simple" );
ctx = new InitialDirContext( env );

// Modify the entry to make it an AAA for collective attribute administration


Attributes mods = new BasicAttributes( "administrativeRole", "collectiveAttributeSpecificArea", true );
ctx.modifyAttributes( "", DirContext.ADD_ATTRIBUTE, mods );

Now 'dc=example,dc=com' is the AP for a collective attribute AAA that spans the entire subtree under
and including it down to every leaf entry. All that remains is the addition of the subentry with the
collective attributes we want included in the entries of all engineering users. Here's what the LDIF
would look like for this subentry given that its commonName is 'engineeringLocale'.

dn: cn=engineeringLocale,dc=example,dc=com
objectClass: top
objectClass: subentry
objectClass: collectiveAttributeSubentry
cn: engineeringLocale
c-l: Sunnyvale
subtreeSpecification: {base "ou=engineering", minimum 4}

The following picture present the structure of our tree :

51
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Attributes, Entries & Schemas Draft

Figure 4.7. SubEntry

A couple points regarding this subentry's LDIF:

1. It subordinates to the AP ('dc=example,dc=com')

2. It contains the objectClasses: subentry and collectiveAttributeSubentry

3. It contains the collective version of locale (l): c-l

4. Its subtreeSpecification excludes entries whose number of DN name components is less than 4

Note that the minimum value of 4 is used in the subtreeSpecification to make sure that the entry
'ou=engineering,dc=example,dc=com' does not have c-l: Sunnyvale added to it. It's got 3 components
to the DN so minimum 4 chops it out of the collection.

4.2.3. Collective Attribute Types


As one can see from the example above, special collective attributes are used for regular attributes: c-
l for l. These attributes are derived from the original attribute and are marked as COLLECTIVE. RFC
3671 defines a bunch of these which are listed below. If you don't find what you're looking for just
add it to your own schema using this pattern.

We have included this list from RFC 3671 into the collective.schema which comes standard with
ApacheDS.

3.1. Collective Locality Name

The c-l attribute type specifies a locality name for a collection of


entries.

( 2.5.4.7.1 NAME 'c-l'


SUP l COLLECTIVE )

3.2. Collective State or Province Name

The c-st attribute type specifies a state or province name for a


collection of entries.

( 2.5.4.8.1 NAME 'c-st'


SUP st COLLECTIVE )

3.3. Collective Street Address

52
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Attributes, Entries & Schemas Draft

The c-street attribute type specifies a street address for a


collection of entries.

( 2.5.4.9.1 NAME 'c-street'


SUP street COLLECTIVE )

3.4. Collective Organization Name

The c-o attribute type specifies an organization name for a


collection of entries.

( 2.5.4.10.1 NAME 'c-o'


SUP o COLLECTIVE )

3.5. Collective Organizational Unit Name

The c-ou attribute type specifies an organizational unit name for a


collection of entries.

( 2.5.4.11.1 NAME 'c-ou'


SUP ou COLLECTIVE )

3.6. Collective Postal Address

The c-PostalAddress attribute type specifies a postal address for a


collection of entries.

( 2.5.4.16.1 NAME 'c-PostalAddress'


SUP postalAddress COLLECTIVE )

3.7. Collective Postal Code

The c-PostalCode attribute type specifies a postal code for a


collection of entries.

( 2.5.4.17.1 NAME 'c-PostalCode'


SUP postalCode COLLECTIVE )

3.8. Collective Post Office Box

The c-PostOfficeBox attribute type specifies a post office box for a


collection of entries.

( 2.5.4.18.1 NAME 'c-PostOfficeBox'


SUP postOfficeBox COLLECTIVE )

3.9. Collective Physical Delivery Office Name

The c-PhysicalDeliveryOfficeName attribute type specifies a physical


delivery office name for a collection of entries.

( 2.5.4.19.1 NAME 'c-PhysicalDeliveryOfficeName'


SUP physicalDeliveryOfficeName COLLECTIVE )

3.10. Collective Telephone Number

The c-TelephoneNumber attribute type specifies a telephone number for


a collection of entries.

53
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Attributes, Entries & Schemas Draft

( 2.5.4.20.1 NAME 'c-TelephoneNumber'


SUP telephoneNumber COLLECTIVE )

3.11. Collective Telex Number

The c-TelexNumber attribute type specifies a telex number for a


collection of entries.

( 2.5.4.21.1 NAME 'c-TelexNumber'


SUP telexNumber COLLECTIVE )

3.13. Collective Facsimile Telephone Number

The c-FacsimileTelephoneNumber attribute type specifies a facsimile


telephone number for a collection of entries.

( 2.5.4.23.1 NAME 'c-FacsimileTelephoneNumber'

SUP facsimileTelephoneNumber COLLECTIVE )

3.14. Collective International ISDN Number

The c-InternationalISDNNumber attribute type specifies an


international ISDN number for a collection of entries.

( 2.5.4.25.1 NAME 'c-InternationalISDNNumber'


SUP internationalISDNNumber COLLECTIVE )

54
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Draft

Chapter 5. Embedding ApacheDS


5.1. Embedding ApacheDS into an
application
The idea is to use the server directly without having to communicate with a remote server, eliminating
all the network layer. This is one of the reason ADS has been developed in Java: to allow such usage.

will go through a very simple example step by step to show you how this can be done.

5.1.1. Setting up the environment


We first need to define a base for our project. We use Maven (2.0.9 or above) to build our project,
so the structure we will use looks like this:

.
|-- pom.xml
`-- src
`-- main
`-- java
`-- org
`-- apache
`-- directory
`-- EmbeddedADS.java

You could download both files here:

• data/EmbeddedADS.java

• pom.xml [data/pom.xml]

If you don't want to use Maven you need to add the following dependencies to your classpath
in order to compile and run this sample.

• apacheds-all-1.5.5.jar

• slf4j-api-1.5.6.jar

• slf4j-log4j12-1.5.6.jar

• log4j-1.2.14.jar

5.1.2. Creating the application


So let's start with the code. It's quite simple: we define a class, add a main() method, and initialize
the server, before using it. In the code snippet below, we have removed all the initialization part to
keep only the main() method.

package org.apache.directory;

/**
* A simple example exposing how to embed Apache Directory Server
* into an application.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
* @version $Rev: 985583 $, $Date: 2010-08-14 23:19:48 +0200 (Sat, 14 Aug 2010) $
*/
public class EmbeddedADS
{

55
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Embedding ApacheDS Draft

/** The directory service */


private DirectoryService service;

...

/**
* Creates a new instance of EmbeddedADS. It initializes the directory service.
*
* @throws Exception If something went wrong
*/
public EmbeddedADS() throws Exception
{
init();
}

/**
* Main class. We just do a lookup on the server to check that it's available.
*
* @param args Not used.
*/
public static void main( String[] args ) //throws Exception
{
try
{
// Create the server
EmbeddedADS ads = new EmbeddedADS();

// Read an entry
Entry result = ads.service.getAdminSession().lookup( new LdapDN( "dc=apache,dc=org" ) );

// And print it if available


System.out.println( "Found entry : " + result );
}
catch ( Exception e )
{
// Ok, we have something wrong going on ...
e.printStackTrace();
}
}
}

As you can see, we first initialize the server, and immediately do a lookup to check that we can read
an entry from it.

Let's focus on the initialization part now.

5.1.3. Initializing the server


This is done in the init() method. It will create the DirectoryService global object ( service ), and
create a partition in which we will store the entries.

A partition is a storage point, associated with a DN, root point for this partition. It's a bit like
a mounting point on Unix. We also need a context entry associated to this DN.

Here, we will create the apache partition, associated with the 'dc=apache,dc=org' DN.

Here is the code for this method :

...

/**
* Initialize the server. It creates the partition, adds the index, and
* injects the context entries for the created partitions.
*
* @throws Exception if there were some problems while initializing the system
*/
private void init() throws Exception
{
// Initialize the LDAP service
service = new DefaultDirectoryService();

// Disable the ChangeLog system


service.getChangeLog().setEnabled( false );

56
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Embedding ApacheDS Draft

// Create a new partition named 'apache'.


Partition apachePartition = addPartition( "apache", "dc=apache,dc=org" );

// Index some attributes on the apache partition


addIndex( apachePartition, "objectClass", "ou", "uid" );

// And start the service


service.startup();

// Inject the apache root entry if it does not already exist


if ( !service.getAdminSession().exists( apachePartition.getSuffixDn() ) )
{
LdapDN dnApache = new LdapDN( "dc=Apache,dc=Org" );
ServerEntry entryApache = service.newEntry( dnApache );
entryApache.add( "objectClass", "top", "domain", "extensibleObject" );
entryApache.add( "dc", "Apache" );
service.getAdminSession().add( entryApache );
}

// We are all done !


}

...

We disabled the ChangeLog service because it's useless in our case. As you can see, the steps to
initialize the server are:

• create a new DirectoryService instance

• add a partition

• add some index

• start the service

• add the context entry

One important point: as the data are remanent, we have to check that the added context entry does
not exist already before adding it.

Some helper methods have been used : addPartition and addIndex . Here they are :

...

/**
* Add a new partition to the server
*
* @param partitionId The partition Id
* @param partitionDn The partition DN
* @return The newly added partition
* @throws Exception If the partition can't be added
*/
private Partition addPartition( String partitionId, String partitionDn ) throws Exception
{
// Create a new partition named 'foo'.
Partition partition = new JdbmPartition();
partition.setId( partitionId );
partition.setSuffix( partitionDn );
service.addPartition( partition );

return partition;
}

/**
* Add a new set of index on the given attributes
*
* @param partition The partition on which we want to add index
* @param attrs The list of attributes to index
*/
private void addIndex( Partition partition, String... attrs )
{
// Index some attributes on the apache partition

57
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Embedding ApacheDS Draft

HashSet<Index<?, ServerEntry>> indexedAttributes = new HashSet<Index<?, ServerEntry>>();

for ( String attribute:attrs )


{
indexedAttributes.add( new JdbmIndex<String,ServerEntry>( attribute ) );
}

((JdbmPartition)partition).setIndexedAttributes( indexedAttributes );
}

...

That's it! (the attached code will contain the needed imports)

5.1.4. Building the sample


Using Maven this is easy:

$ mvn clean compile


[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building ApacheDS embedded sample
[INFO] task-segment: [clean, compile]
[INFO] ------------------------------------------------------------------------
[INFO] [clean:clean {execution: default-clean}]
[INFO] Deleting directory /tmp/EmbeddedADS/target
[INFO] [resources:resources {execution: default-resources}]
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /tmp/EmbeddedADS/src/main/resources
[INFO] [compiler:compile {execution: default-compile}]
[INFO] Compiling 1 source file to /tmp/EmbeddedADS/target/classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2 seconds
[INFO] Finished at: Sat Nov 28 20:02:23 CET 2009
[INFO] Final Memory: 17M/76M
[INFO] ------------------------------------------------------------------------

The resulting jar can be found in the target directory.

5.1.5. Running the sample


Using Maven this is easy:

$ mvn exec:java -Dexec.mainClass=org.apache.directory.EmbeddedADS


[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'exec'.
[INFO] ------------------------------------------------------------------------
[INFO] Building ApacheDS embedded sample
[INFO] task-segment: [exec:java]
[INFO] ------------------------------------------------------------------------
[INFO] Preparing exec:java
[INFO] No goals needed for project - skipping
[INFO] [exec:java {execution: default-cli}]

When the main method is run, you should obtain something like :

log4j:WARN No appenders could be found for logger (org.apache.directory.server.schema.registries.DefaultNormalizer


log4j:WARN Please initialize the log4j system properly.
Found entry : ServerEntry
dn[n]: dc=Apache,dc=Org
objectClass: extensibleObject
objectClass: domain
objectClass: top
dc: Apache

That's it!

58
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Embedding ApacheDS Draft

5.2. Using ApacheDS for unit tests


This page describes how to define your own unit tests, using ApacheDS 1.5.6.

The idea is to use ADS as an embedded server for Ldap junit tests. We will build an environment in
which it will be convenient to test Ldap applications.

We also want to avoid launching the server for every test, as it's an expensive operation. We have built
ApacheDS so that you can start a server, inject some data, launch a test, then revert the data and go
on to another test. At the end of the tests, the server is stopped.

5.2.1. First steps


We have two choices : either we launch the server totally embedded, without having to communicate
with it using the Ldap Protocol, or we want to use the server as a remote server, with Ldap protocol
in the middle (it can be useful if one want to test specific applications). In both cases, the server is
started and stopped by the unit test.

We will simply launch only one server (if one want to test referrals, it might be necessary to initialize
2 or more servers)

We are using JUnit 4.7

We have to define a layout for the files and directory we will use in this tutorial. Let's use the maven
layout :

/
|
+--src
|
+--test
|
+--java : we will put all the sources into this directory
|
+--resources : we will put the resources files into this directory

5.2.2. Creating a blank test


So let's define the framework we need for a simple unit test, using a server which will be invoked
through socket (the first free port above 1023 will be used). This first test will do a search operation
on a server.

package org.apache.directory.server.test;

import static org.apache.directory.server.integ.ServerIntegrationUtils.getWiredContext;


import static org.junit.Assert.assertTrue;

import javax.naming.NamingEnumeration;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.LdapContext;

import org.apache.directory.server.annotations.CreateLdapServer;
import org.apache.directory.server.annotations.CreateTransport;
import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
import org.apache.directory.server.core.integ.FrameworkRunner;
import org.apache.directory.server.ldap.LdapServer;
import org.junit.Test;
import org.junit.runner.RunWith;

/**
* Tests
*

59
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Embedding ApacheDS Draft

* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>


* @version $Rev: 985583 $, $Date: 2010-08-14 23:19:48 +0200 (Sat, 14 Aug 2010) $
*/
@RunWith(FrameworkRunner.class)
@CreateLdapServer(
transports =
{
@CreateTransport(protocol = "LDAP")
})
public class SearchTests extends AbstractLdapTestUnit
{
public static LdapServer ldapServer;

@Test
public void testSearchAllAttrs() throws Exception
{
LdapContext ctx = ( LdapContext ) getWiredContext( ldapServer, null ).lookup( "ou=system" );

SearchControls controls = new SearchControls();


controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
controls.setReturningAttributes( new String[]
{ "+", "*" } );

NamingEnumeration<SearchResult> res = ctx.search( "", "(ObjectClass=*)", controls );

assertTrue( res.hasMore() );

while ( res.hasMoreElements() )
{
SearchResult result = ( SearchResult ) res.next();

System.out.println( result.getName() );
}
}
}

In order to have this test running, you will need to declare some libraries. The best solution is clearly
to define a pom.xml file for that purpose. Here it is :

<?xml version="1.0" encoding="UTF-8"?>


<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.directory.server</groupId>
<artifactId>apacheds-unit-test</artifactId>
<version>1.5.5-SNAPSHOT</version>
<name>ApacheDS Server Unit</name>
<packaging>jar</packaging>

<description>
Unit test for ApacheDS Server JNDI Provider
</description>

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.5.10</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>org.apache.directory.server</groupId>
<artifactId>apacheds-all</artifactId>
<version>1.5.6-SNAPSHOT</version>

60
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Embedding ApacheDS Draft

</dependency>

<dependency>
<groupId>org.apache.directory.server</groupId>
<artifactId>apacheds-server-integ</artifactId>
<version>1.5.6-SNAPSHOT</version>
</dependency>

<dependency>
<groupId>org.apache.directory.server</groupId>
<artifactId>apacheds-core-integ</artifactId>
<version>1.5.6-SNAPSHOT</version>
</dependency>

<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>1.4</version>
</dependency>
</dependencies>

<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<source>1.5</source>
<target>1.5</target>

<optimize>true</optimize>
<showDeprecations>true</showDeprecations>
<encoding>ISO-8859-1</encoding>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-Xmx1024m</argLine>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

Is that it ? Pretty much. All you have to do now is to run the test, using a Java 5 JVM and Maven 2.0.9 :

#user:~/ws-ads-1.5.4/UnitTest$ mvn test


[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building ApacheDS Server Unit
[INFO] task-segment: [test]
[INFO] ------------------------------------------------------------------------
[INFO] [resources:resources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:compile]
[INFO] No sources to compile
[INFO] [resources:testResources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:testCompile]
[INFO] Nothing to compile - all classes are up to date
[INFO] [surefire:test]
[INFO] Surefire report directory: /home/elecharny/ws-ads-1.5.4/UnitTest/target/surefire-reports

-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running SimpleTest
log4j:WARN No appenders could be found for logger (org.apache.directory.server.integ.SiRunner).
log4j:WARN Please initialize the log4j system properly.
Ldap service started.
Ldap service stopped.
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 5.114 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

61
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Embedding ApacheDS Draft

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 10 seconds
[INFO] Finished at: Fri Nov 21 15:40:32 CET 2008
[INFO] Final Memory: 11M/83M
[INFO] ------------------------------------------------------------------------
#user:~/ws-ads-1.5.4/UnitTest$

You have written your very first test using the test framework provided in ADS 1.5.5 !

Here are the test files :

• SearchTests.java [data/unit-tests/SearchTests.java]

• pom.xml [data/unit-tests/pom.xml]

5.2.2.1. Test description


Ok, we have a running test, but when it comes to write your own, you need a bit more information.
Let's try to explain the different parts of this test.

5.2.2.1.1. Annotations

The first interesting part is the annotations we are using. As we said, the server is launched
automatically, and we are using the ChangeLog mechanism to restore the base in a pristine state
between each test. This is done with annotations.

Table 5.1. Test Annotations

Annotation Parameter Default value Description


@RunWith FrameworkRunner.class none Run the test with the
defined Runner, instead
of the default JUNIT
one.
This is mandatory to
add this annotation, as
it determinate the way
the server will be clean
when each test has run
@CreateLdapServer transports none Create the LdapServer
that will be used for the
tests
@CreateTransports protocol none Define the transport to
use
@ApplyLdifs A list of entries in a none This is one of the most
LDIF format interesting new feature :
you can define the
data you need to be
present when the server
is started, they will
be injected before the
first test is run (it
will also depend on the
CleanupLevel).
@ApplyLdifFiles A list of files containing none Give sthe list of files
LDIF entries to be injected into the

62
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Embedding ApacheDS Draft

Annotation Parameter Default value Description


server before the tests
are run.

5.2.2.1.2. Server startup


As you can see in the test, there is no place where you tell the server to be started. This is done by
the FrameworkRunner. When the tests are all done, the server is also automatically shutdown, and all
the created files are removed.

The initialization will update a static ldapServer instance which is declared in the inherited
AbstractLdapTestUnit class.

You just have to focus on writing your own tests !

5.2.2.1.3. Writing your own test using JNDI


All the LDAP operation are supported, you just have to use the JNDI API to write your tests. The only
difference is the way you get a context : you have to use one of those methods :

/**
* Creates a JNDI LdapContext with a connection over the wire using the
* SUN LDAP provider. The connection is made using the administrative
* user as the principalDN. The context is to the rootDSE.
*
* @param ldapServer the LDAP server to get the connection to
* @return an LdapContext as the administrative user to the RootDSE
* @throws Exception if there are problems creating the context
*/
public static LdapContext getWiredContext( LdapServer ldapServer )

/**
* Creates a JNDI LdapContext with a connection over the wire using the
* SUN LDAP provider. The connection is made using the administrative
* user as the principalDN. The context is to the rootDSE.
*
* @param ldapServer the LDAP server to get the connection to
* @return an LdapContext as the administrative user to the RootDSE
* @throws Exception if there are problems creating the context
*/
public static LdapContext getWiredContext( LdapServer ldapServer, Control[] controls )

/**
* Creates a JNDI LdapContext with a connection over the wire using the
* SUN LDAP provider. The connection is made using the administrative
* user as the principalDN. The context is to the rootDSE.
*
* @param ldapServer the LDAP server to get the connection to
* @return an LdapContext as the administrative user to the RootDSE
* @throws Exception if there are problems creating the context
*/
public static LdapContext getWiredContext( LdapServer ldapServer, String principalDn, String password )

That's it ! Everything else is just pure JNDI

5.2.2.1.4. Writing your own tests using the Netscape API


If you don't like JNDI, or prefer to use the Netscape API (LdapSdk-4.1), you have two major
differences :

• first you have to add this API jar into the dependencies in the pom.xml file

• second you will use the getWiredConnection() method instead of the getWiredContext().

The API is :

63
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Embedding ApacheDS Draft

public static LDAPConnection getWiredConnection( LdapServer ldapServer )


public static LDAPConnection getWiredConnection( LdapServer ldapServer,
String principalDn, String password )

Both methods are similar to the getWiredContext which has been described before, except that they
return a LdapConnection instance.

Starting here, the document has to be reviewed...

5.2.3. Creating our own partition


At the moment, we have created a server which is not totally empty : one partition is created by default,
the system partition. We won't use it for our tests, so we will need to create our own partition to play
with. Let's call it 'o=sevenseas' ( o stands for organization )

The setUp() method will be completed with all the needed instruction to create a new partition

import java.io.File;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Set;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;

import org.apache.directory.server.core.configuration.MutablePartitionConfiguration;
import org.apache.directory.server.unit.AbstractServerTest;
...

/**
* Initialize the server.
*/
public void setUp() throws Exception
{
// Add partition 'sevenSeas'
MutablePartitionConfiguration pcfg = new MutablePartitionConfiguration();
pcfg.setName( "sevenSeas" );
pcfg.setSuffix( "o=sevenseas" );

// Create some indices


Set<String> indexedAttrs = new HashSet<String>();
indexedAttrs.add( "objectClass" );
indexedAttrs.add( "o" );
pcfg.setIndexedAttributes( indexedAttrs );

// Create a first entry associated to the partition


Attributes attrs = new BasicAttributes( true );

// First, the objectClass attribute


Attribute attr = new BasicAttribute( "objectClass" );
attr.add( "top" );
attr.add( "organization" );
attrs.put( attr );

// The the 'Organization' attribute


attr = new BasicAttribute( "o" );
attr.add( "sevenseas" );
attrs.put( attr );

// Associate this entry to the partition


pcfg.setContextEntry( attrs );

// As we can create more than one partition, we must store


// each created partition in a Set before initialization
Set<MutablePartitionConfiguration> pcfgs = new HashSet<MutablePartitionConfiguration>();
pcfgs.add( pcfg );

configuration.setContextPartitionConfigurations( pcfgs );

64
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Embedding ApacheDS Draft

// Create a working directory


File workingDirectory = new File( "server-work" );
configuration.setWorkingDirectory( workingDirectory );

// Now, let's call the upper class which is responsible for the
// partitions creation
super.setUp();
}

Ok, now the partition sevenseas should be created. How can we be sure of that ? let's write a test to
replace the emptytest() method :

/**
* Test that the partition has been correctly created
*/
public void testPartition() throws NamingException
{
Hashtable<Object, Object> env = new Hashtable<Object, Object>( configuration.toJndiEnvironment() );

// Create a new context pointing to the overseas partition


env.put( Context.PROVIDER_URL, "o=sevenSeas" );
env.put( Context.SECURITY_PRINCIPAL, "uid=admin,ou=system" );
env.put( Context.SECURITY_CREDENTIALS, "secret" );
env.put( Context.SECURITY_AUTHENTICATION, "simple" );
env.put( Context.INITIAL_CONTEXT_FACTORY, "org.apache.directory.server.jndi.ServerContextFactory" );

// Let's open a connection on this partition


InitialContext initialContext = new InitialContext( env );

// We should be able to read it


DirContext appRoot = ( DirContext ) initialContext.lookup( "" );
assertNotNull( appRoot );

// Let's get the entry associated to the top level


Attributes attributes = appRoot.getAttributes( "" );
assertNotNull( attributes );
assertEquals( "sevenseas", attributes.get( "o" ).get() );

Attribute attribute = attributes.get( "objectClass" );


assertNotNull( attribute );
assertTrue( attribute.contains( "top" ) );
assertTrue( attribute.contains( "organization" ) );
// Ok, everything is fine
}

The test should succeed. Is that all ? Well, almost. As you can see, a working space has been created
( "server-work", at the end of the setup). Do we have to take care of this working space? No. It has
been cleaned by the super class !

So everything is fine, the partition is up and running, you are ready to add more tests.

One line in the logs is interesting :

3879 [main] INFO org.apache.directory.server.jndi.ServerContextFactory -


LDIF load directory not specified. No LDIF files will be loaded.

The setup has tried to load an LDIF file to inject some data into the partition, but as we didn't specify
any Ldif file to be loaded, nothing has been done. let's add some data !

5.2.4. Adding some data into the partition


The AbstractServerTest class provide a method called importLdif( InputStream in ) . It allows you
to inject some entries into the newly created partition. How d we use it?

First, we need to have a valid LDIF file containing your entries. We will create two branches in our
sevenseas organization :

• one for groups

65
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Embedding ApacheDS Draft

• one for people

Here is the ldif file we will create :

dn: ou=groups,o=sevenSeas
objectClass: organizationalUnit
objectClass: top
ou: groups
description: Contains entries which describe groups (crews, for instance)

dn: ou=people,o=sevenSeas
objectClass: organizationalUnit
objectClass: top
ou: people
description: Contains entries which describe persons (seamen)

Save it as a text file into a directory where we will be able to read it directly. But where?

We have created the test into a directory src/test/java/org/apache/directory/demo. This is the maven
way to organized the sources, as seen before. Let's create another directory for the resources : src/test/
resources/org/apache/directory/demo. Tis is the place where we will save the ldif file.

Now, to let the server know about the ldif file, just add this line after the call to the setup() method :

...
// Now, let's call the upper class which is responsible for the
// partitions creation
super.setUp();

// Load a demo ldif file


importLdif( this.getClass().getResourceAsStream( "demo.ldif" ) );
}

This is important to add the import after the setup : you can't import data while the partition
has not been created ...

The getResourceAsStream call will automatically read the file from the resources directory, based
on the current class package.

How can we be sure that the data has been imported ? Let's do a search request !

5.2.5. Cleanup the code


Before that, let's do some cleanup. The context creation is something we will have to do in each test.
We should create a common method called every time to avoid duplicating this code. Let's create this
method :

/**
* Create a context pointing to a partition
*/
private DirContext createContext( String partition ) throws NamingException
{
// Create a environment container
Hashtable<Object, Object> env =
new Hashtable<Object, Object>( configuration.toJndiEnvironment() );

// Create a new context pointing to the partition


env.put( Context.PROVIDER_URL, partition );
env.put( Context.SECURITY_PRINCIPAL, "uid=admin,ou=system" );
env.put( Context.SECURITY_CREDENTIALS, "secret" );
env.put( Context.SECURITY_AUTHENTICATION, "simple" );
env.put( Context.INITIAL_CONTEXT_FACTORY,
"org.apache.directory.server.jndi.ServerContextFactory" );

// Let's open a connection on this partition


InitialContext initialContext = new InitialContext( env );

// We should be able to read it


DirContext appRoot = ( DirContext ) initialContext.lookup( "" );

66
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Embedding ApacheDS Draft

assertNotNull( appRoot );

return appRoot;
}

This method is added into the body of the test class. This method is very simple and quite
straightforward : we just create an initial context pointing to the requested partition, and return a
directory context on this partition. It takes a parameter, the partition name.

Let's modify the test partition method :

/**
* Test that the partition has been correctly created
*/
public void testPartition() throws NamingException
{
DirContext appRoot = createContext( "o=sevenSeas" );

// Let's get the entry associated to the top level


Attributes attributes = appRoot.getAttributes( "" );
...

We just replaced the first lines by a call to the newly created createContext() method.

If you launch the unit test, it should still be ok.

5.2.6. Searching for entries


This is really simple. What we will do is to search for the imported entries. Let's go directly to the
code. We will add a new unit test

/**
* Test that the ldif data has correctly been imported
*/
public void testImport() throws NamingException
{
// Searching for all
Set<String> result = searchDNs( "(ObjectClass=*)", "o=sevenSeas", "",
SearchControls.ONELEVEL_SCOPE );

assertTrue( result.contains( "ou=groups,o=sevenSeas" ) );


assertTrue( result.contains( "ou=people,o=sevenSeas" ) );
}

Here, we are looking for all the entries starting at the top level of the partition, within the level. We
should only get two entries.

It's not enough : the searchDNs() method does not exist. It is a private method we have created to
avoid duplicating some code all over the unit tests. Here is its code :

/**
* Performs a single level search from a root base and
* returns the set of DNs found.
*/
private Set<String> searchDNs( String filter, String partition, String base, int scope )
throws NamingException
{
DirContext appRoot = createContext( partition );

SearchControls controls = new SearchControls();


controls.setSearchScope( scope );
NamingEnumeration result = appRoot.search( base, filter, controls );

// collect all results


HashSet<String> entries = new HashSet<String>();

while ( result.hasMore() )
{
SearchResult entry = ( SearchResult ) result.next();

67
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Embedding ApacheDS Draft

entries.add( entry.getName() );
}

return entries;
}

As for the test partiton, we call the createContext() method, then we just do some JNDI magic :

• creating a SearchControl,

• setting the scope,

• calling the search

• and gathering the returned DN if any

If the test is successful, you get the imported DNs !

5.2.7. Adding your own schema


This paragraph is totally outdated. It should be rewriten from scratch !

Ok, let's go deeper into the server configuration. Working with default schema is fine, but some point,
you may want to use your own ObjectClasses and AttributeTypes. let's assume you have created them,
and that you have been throw the process of generating the class files for it (this process is described
in Custom Schema [http://directory.apache.org/apacheds/DIRxSRVx10/custom-schema.html] ) into a
new package (org.apache.directory.demo.schema) where all the generated files will be put.

You will just have to add those lines at the end of the setUp() method (just before the call to the super()
method) :

...
import org.apache.directory.server.core.configuration.MutablePartitionConfiguration;
import org.apache.directory.server.core.schema.bootstrap.AbstractBootstrapSchema;
import org.apache.directory.server.unit.AbstractServerTest;

import org.apache.directory.demo.schema.DemoSchema;

...
...
///
/// add the Demo schema
///
Set<AbstractBootstrapSchema> schemas = configuration.getBootstrapSchemas();
schemas.add( new DemoSchema() );

configuration.setBootstrapSchemas(schemas);

// Now, let's call the upper class which is responsible for the
// partitions creation
super.setUp();
}

If we launch the test, nothing special will happen, except that the test will succeed. That's not very
impressive...

5.2.8. Conclusion
Ok, this tutorial was a short one, but you get everything you need to play with Apache Directory
Server as a Unit Test Engine for your Ldap application. Just create your own partition, define
your schema, import your ldif file, and add all the tests you need. it's as simple as explained

68
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Embedding ApacheDS Draft

If you have any problem, just feel free to post a mail to users@directory.apache.org, we will be there
to help !

5.2.9. Resources
Embedding ApacheDS - Conference Materials [http://directory.apache.org/community%26resources/
embedding-apacheds.html]

5.3. Embedding ApacheDS as a Web


Application
This site was updated for ApacheDS 1.5.5.

My initial aim was to demonstrate embedding ApacheDS in a very simple, but nevertheless impressive
way. I thought about embedding the server in Apache Tomcat first. But then I got a better plan:
Creating a standard web application which wraps ApacheDS and can be deployed on any compliant
application server. ApacheDS in a war-archive!

• Section 5.3.1, “Solution Outline”

• Section 5.3.2, “Step 1: The web component which starts and stops the server”

• Section 5.3.3, “Packaging and Deploying the WebApp”

• Section 5.3.4, “Step 2: Adding functionality: A servlet which displays the Root DSE”

Although the concepts depicted below apply to all version of ApacheDS (even before 1.0),
the configuration for starting and stopping the embedded server uses the style introduced with
ApacheDS 1.5.5. Be sure that you use this version of the server, or a later one.

5.3.1. Solution Outline


Although it works well, please note that this is just an example on how to embed ApacheDS
in an application! If you plan to run the server as LDAP production system, this is not the first
option to consider. Some more steps have to be done, especially in the area of configuration.

The solution is quite simple. A web application carries all the necessary jar files for ApacheDS within
the lib-directory of the WEB-INF folder. When the web application is started by the servlet container,
appropriate code has to be executed to start ApacheDS. And the server has to be stopped, if the
web application goes down (for instance if the server shuts down). There are (at least) two standard
compliant ways to acomplish this:

• A Servlet (automatically started with the web application, using the lifecycle methods init and
destroy)

• A ServletContextListener

In the following we have choosen the second option.

5.3.1.1. A Servlet Context Listener to start and stop ApacheDS


A servlet context listener receives notifications about changes to the servlet context of the web
application it is part of. Documentation of the ServletContextListener interface can be found
here [http://java.sun.com/products/servlet/2.3/javadoc/javax/servlet/ServletContextListener.html] .
To receive notification events, the implementation class must be configured in the deployment
descriptor for the web application. The two life cycle methods contextInitialized and contextDestroyed
are suitable to start and stop ApacheDS.

69
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Embedding ApacheDS Draft

5.3.1.2. A client within


After the server has been started from the Listener, it will be accessible from the outside via the network
using LDAP. In order to demonstrate how to interact with the server from within the VM, a simple
servlet is shown. It allows you to communicate with the embedded server via web browser. This is so
simple, because the server already lives within a web application, only a servlet has to added to act as
an entry point. Our sample servlet will display the Root DSE of the server.

The following class diagram visualizes the complete example. The gray elements will be developed
in two steps and use Servlet and ApacheDS API.

Figure 5.1. ApacheDS as a Web Application

5.3.2. Step 1: The web component which starts and


stops the server
The ApacheDS core is comprised of JavaBeans components, and can easily be instantiated started and
stopped with simple Java code. This is done by the following listener.

The class StartStopListener [http://svn.apache.org/repos/asf/directory/samples/trunk/apacheds-


archetype-webapp/src/main/resources/archetype-resources/src/main/java/StartStopListener.java]
implements ServletContextListener and therefore contains the following two life cycle methods:

• contextInitialized() is executed if the web application is started by the servlet container, it starts
ApacheDS embedded

70
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Embedding ApacheDS Draft

• contextDestroyed() is executed if the web application is stopped by the servlet container, it stops
the embedded server

The contextInitialized method creates a DefaultDirectoryService object. It configures the LDAP


protocol and determines an appropriate working directory for the server. This directory is need to
persist the partition data (entries). Our example uses a simple yet portable way for this task: the context
attribute javax.servlet.context.tempdir .

Afterwards the method starts network protocol and directory service.

Finally the DirectoryService component is stored in the application context of the web application.
This is done in order to provided it to embedded clients in the same web app (see the servlet below
for an example).

The method contextDestroyed simply stops the protocol and shuts down the service.

StartStopListener.java

package org.apache.directory.samples.embed.webapp;

import java.io.File;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.apache.directory.server.core.DefaultDirectoryService;
import org.apache.directory.server.core.DirectoryService;
import org.apache.directory.server.ldap.LdapServer;
import org.apache.directory.server.protocol.shared.transport.TcpTransport;

/**
* A Servlet context listener to start and stop ApacheDS.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
public class StartStopListener implements ServletContextListener
{
private DirectoryService directoryService;

private LdapServer ldapServer;

/**
* Startup ApacheDS embedded.
*/
public void contextInitialized( ServletContextEvent evt )
{
try
{
directoryService = new DefaultDirectoryService();
directoryService.setShutdownHookEnabled( true );

ldapServer = new LdapServer();


ldapServer.setDirectoryService( directoryService );
ldapServer.setAllowAnonymousAccess( true );

// Set LDAP port to 10389


TcpTransport ldapTransport = new TcpTransport( 10389 );
ldapServer.setTransports( ldapTransport );

// Determine an appropriate working directory


ServletContext servletContext = evt.getServletContext();
File workingDir = ( File ) servletContext.getAttribute( "javax.servlet.context.tempdir" );
directoryService.setWorkingDirectory( workingDir );

directoryService.startup();
ldapServer.start();

// Store directoryService in context to provide it to servlets etc.


servletContext.setAttribute( DirectoryService.JNDI_KEY, directoryService );
}
catch ( Exception e )
{
throw new RuntimeException( e );
}
}

71
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Embedding ApacheDS Draft

/**
* Shutdown ApacheDS embedded.
*/
public void contextDestroyed( ServletContextEvent evt )
{
try
{
ldapServer.stop();
directoryService.shutdown();
}
catch ( Exception e )
{
throw new RuntimeException( e );
}
}
}

5.3.2.1. Deployment descriptor


In order to execute the listener code, the class has to be defined in the deployment descriptor of a web
application, as depicted below:

web.xml

<?xml version="1.0" encoding="UTF-8"?>


<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<display-name>ApacheDS embedded in a WebApp</display-name>
<description>
A simple yet portable way to run ApacheDS within a servlet
container
</description>

<listener>
<listener-class>
org.apache.directory.samples.embed.webapp.StartStopListener
</listener-class>
</listener>
</web-app>

5.3.3. Packaging and Deploying the WebApp


A standard web archive (war-File) is needed in order to deploy the application to a servlet container.
The easiest way to create such a web archive including all dependencies is to use an Maven archetype
we provide.

5.3.3.1. Creating the WebApp using the ApacheDS Maven


Archetype
We assume you have Java Subversion and Maven 2.0.9 installed on your system.

To use the archetype you'll need to check it out and install it to your local repository:

svn co http://svn.apache.org/repos/asf/directory/samples/trunk/apacheds-archetype-webapp
cd apacheds-archetype-webapp
mvn install

Then change to your preferred location to create the new project and execute following command:

mvn archetype:generate -DarchetypeGroupId=org.apache.directory.samples \


-DarchetypeArtifactId=apacheds-archetype-webapp \
-DarchetypeVersion=1.5.5-SNAPSHOT \
-DgroupId=org.apache.directory.samples.embed.webapp \
-DartifactId=ApacheDS -Dversion=1.0-SNAPSHOT

72
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Embedding ApacheDS Draft

Then change to the created directory and run the following command:

mvn package

This creates an ApacheDS.war file below the target folder.

5.3.3.2. Run on embedded Jetty


The fastest way to run the web application is to use the Maven Jetty plugin:

mvn jetty:run

5.3.3.3. Deploying on Apache Tomcat


In order to run the application within Tomcat, simply put the ApacheDS.war file in the webapps
directory of your Tomcat installation and start the server. If you have the manager application enabled
(as described here [http://tomcat.apache.org/tomcat-6.0-doc/manager-howto.html] ), you can see and
"manage" (start/stop) ApacheDS within its list view:

Figure 5.2. Tomcat Manager App in Browser

5.3.3.4. Connecting to ApacheDS from the outside


ApacheDS is up and running within the servlet container. Besides the administration tool listing, it
seems to be invisible. But because we have configured network access via port 10389, you can easily
access the server with an arbitrary LDAP client from outside.

One option is a command line tool like ldapsearch (see ApacheDS Basic User's Guide
[http://directory.apache.org/apacheds/1.5/apacheds-v15-basic-users-guide.html] for details on how to

73
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Embedding ApacheDS Draft

connect to ApacheDS with such tools in general). Here is an example how to connect as administrator
(simple bind) and fetch the Root DSE of our embedded ApacheDS instance:

$ ldapsearch -h localhost -p 10389 -D "uid=admin,ou=system" -w secret \\


-b "" -s base "(objectClass=*)" * +
version: 1
dn:
supportedControl: 2.16.840.1.113730.3.4.3
supportedControl: 2.16.840.1.113730.3.4.7
supportedControl: 1.3.6.1.4.1.4203.1.10.1
supportedControl: 2.16.840.1.113730.3.4.2
supportedControl: 1.3.6.1.4.1.18060.0.0.1
namingContexts: ou=system
namingContexts: ou=schema
supportedLDAPVersion: 3
objectClass: extensibleObject
objectClass: top
supportedFeatures: 1.3.6.1.4.1.4203.1.5.1
supportedExtension: 1.3.6.1.4.1.1466.20036
subschemaSubentry: cn=schema
vendorName: Apache Software Foundation
vendorVersion: 1.5.4
$

Another choice are graphical LDAP clients (see ApacheDS Basic User's Guide [http://
directory.apache.org/apacheds/1.5/apacheds-v15-basic-users-guide.html] for details on how to
connect to ApacheDS with such tools in general).

With our popular Eclipse RCP application Directory studio [http://directory.apache.org/studio/] for
instance, connecting goes like this: In the Connections view, select "New connection ...". Within a
wizard dialog, you provide the connection data (host name, port, bind DN and password).

Figure 5.3. New LDAP Connection Directory Studio 1

74
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Embedding ApacheDS Draft

Figure 5.4. New LDAP Connection Directory Studio 2

After successfully connecting to the embedded ApacheDS, you can browse the tree, add and
manipulate entries and so on. If you check the connection properties, you can study the Root DSE
as well.

75
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Embedding ApacheDS Draft

Figure 5.5. Properties New LDAP Connection Directory Studio

5.3.3.5. Other Web Application Servers


The web application described here has been successfully deployed on

• Apache Tomcat 5.5.20 and 6.0.18 ( Homepage [http://tomcat.apache.org/] )

• IBM WebSphere Application Server 6.1 ( Homepage [http://www.ibm.com/software/webservers/


appserv/was/] )

• Jetty 6.1.0 ( Homepage [http://jetty.mortbay.org/] )

Here is a screen shot of the web based administration console of WebSphere Application Server 6.1
with the ApacheDS.war deployed and running, no changes in the deployment archive were needed.

76
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Embedding ApacheDS Draft

Figure 5.6. WebSphere Admin Console

5.3.4. Step 2: Adding functionality: A servlet which


displays the Root DSE
To finish with, here is a simple example on how to access the server internally (Note: the servlet was
already created by the maven archetype).

The following servlet, which will be deployed together with the other class in the web archive, connects
to ApacheDS directly, i.e. via the internal JNDI provider. No network access is needed. In the doGet
method it performs a search operation against the Root DSE of the server, as the examples above do.

RootDseServlet.java
package org.apache.directory.samples.embed.webapp;

import java.io.PrintWriter;
import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.directory.server.core.DirectoryService;
import org.apache.directory.server.core.jndi.CoreContextFactory;

77
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Embedding ApacheDS Draft

/**
* A servlet which displays the Root DSE of the embedded server.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory
* Project</a>
*/
public class RootDseServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

protected void doGet(HttpServletRequest req, HttpServletResponse resp)


throws ServletException {

try {
resp.setContentType("text/plain");
PrintWriter out = resp.getWriter();

out.println("*** ApacheDS RootDSE ***\n");

DirContext ctx = new InitialDirContext(this.createEnv());

SearchControls ctls = new SearchControls();


ctls.setReturningAttributes(new String[] { "*", "+" });
ctls.setSearchScope(SearchControls.OBJECT_SCOPE);

NamingEnumeration<SearchResult> result = ctx.search("",


"(objectClass=*)", ctls);
if (result.hasMore()) {
SearchResult entry = result.next();
Attributes as = entry.getAttributes();

NamingEnumeration<String> ids = as.getIDs();


while (ids.hasMore()) {
String id = ids.next();
Attribute attr = as.get(id);
for (int i = 0; i < attr.size(); ++i) {
out.println(id + ": " + attr.get(i));
}
}
}
ctx.close();

out.flush();
} catch (Exception e) {
throw new ServletException(e);
}
}

/**
* Creates an environment configuration for JNDI access.
*/
protected Hashtable<Object, Object> createEnv() {

// Fetch directory servive from servlet context


ServletContext servletContext = this.getServletContext();
DirectoryService directoryService = (DirectoryService) servletContext
.getAttribute(DirectoryService.JNDI_KEY);

Hashtable<Object, Object> env = new Hashtable<Object, Object>();


env.put(DirectoryService.JNDI_KEY, directoryService);
env.put(Context.PROVIDER_URL, "");
env.put(Context.INITIAL_CONTEXT_FACTORY, CoreContextFactory.class
.getName());

env.put(Context.SECURITY_PRINCIPAL, "uid=admin,ou=system");
env.put(Context.SECURITY_CREDENTIALS, "secret");
env.put(Context.SECURITY_AUTHENTICATION, "simple");

return env;
}
}

In order to make the servlet available to clients, it has to be declared in the deployment descriptor
web.xml , here are the additions (a servlet named RootDseServlet for the class above, and a URL
mapping)

web.xml, extended
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">

78
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Embedding ApacheDS Draft

<web-app>

...
<servlet>
<servlet-name>RootDseServlet</servlet-name>
<servlet-class>
org.apache.directory.samples.embed.webapp.RootDseServlet
</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>RootDseServlet</servlet-name>
<url-pattern>/RootDse</url-pattern>
</servlet-mapping>
</web-app>

Redeploy the web application. If you point to your tomcat server with the appropriate URL ( http://
localhost:8080/ApacheDS/RootDse ), you'll see the content of the Root DSE as depicted below:

Figure 5.7. RootDSE Servlet in a Browser

79
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Draft

Chapter 6. Protocol Providers


6.1. Protocol Providers
This site is in the process of being reviewed and updated.

You are viewing pre-release documentation that contains changes to configuration that are
scheduled for the Apache Directory 1.5.1 release.

6.1.1. Apache Directory Protocol Providers


The Apache Directory Project's Protocol Providers are Java implementations of standard Internet
services. These Protocol Providers, in conjunction with the MINA network layer and the Apache
Directory read-optimized backing store, provide easy-to-use yet fully-featured Internet services. As
implemented within the Apache Directory, these services benefit from:

• Standard directory model and schema support

• Standard LDAP data interchange format (LDIF) (RFC 2849)

• Optional LDAP management

• UDP and TCP Support (MINA)

• Easy POJO embeddability for containers such as Geronimo, JBoss, and OSGi

6.1.2. Service Configuration


All protocol providers are configured in a similar manner. Behind the scenes, all protocol provider
Configuration beans inherit from the same ServiceConfiguration and, therefore, they share many of
the same configuration parameters. For more information on the service configuration common to all
protocol providers, please see Section 6.2, “Common Parameters for Configuration” .

6.1.3. Changes from 1.5 to 1.5.1


Configuration has been revamped for the 1.5.1 release, along with the addition of SASL support in the
LDAP protocol. For more information on changes to configuration, please see Section 6.2.1, “Changes
to Configuration”

6.1.4. Protocol Providers


Table 6.1. Protocol Providers
Name Configuration Description
Section 6.3, “LDAP Protocol ??? A Lightweight Directory
Provider” Access Protocol (LDAP)
implementation based on RFC
2251 [http://www.faqs.org/rfcs/
rfc2251.html] . Apache LDAP
provides lightweight access to the
Apache Directory backing store.
Section 6.4, “Kerberos Protocol Section 6.4.4, “Kerberos A Kerberos implementation
Provider” Protocol Configuration” based on RFC 1510 [http://

80
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Protocol Providers Draft

Name Configuration Description


www.faqs.org/rfcs/rfc1510.html]
. Apache Kerberos verifies
the identities of principals
(users or services) on an
unprotected network using
principal information stored in
the Apache Directory backing
store.
Section 6.5, “Change Password Section 6.5.3, “Change A Change Password
Protocol Provider” Password Configuration” implementation based on
RFC 3244 [http://www.faqs.org/
rfcs/rfc3244.html] . Apache
Change Password uses Kerberos
infrastructure to allow users to
securely set initial passwords
or to change existing passwords
stored in the Apache Directory
backing store.
Section 6.6, “DNS Protocol Section 6.6.4, “DNS Protocol A Domain Name System (DNS)
Provider” Configuration” implementation based on RFC
1034 [http://www.faqs.org/rfcs/
rfc1034.html] . Apache DNS
serves host name to address
mappings and other resource
record types using resource
records stored in the Apache
Directory backing store.
Section 6.7, “NTP Protocol Section 6.7.4, “NTP Protocol A Network Time Protocol (NTP)
Provider” Configuration” implementation based on RFC
2030 [http://www.faqs.org/rfcs/
rfc2030.html] . Apache NTP
supports time synchronization
for LDAP replication and the
Kerberos protocol, eliminating
the need for external
infrastructure.
Section 6.8, “DHCP Protocol n/a A Dynamic Host Configuration
Provider” Protocol (DHCP)
implementation based on RFC
2131 [http://www.faqs.org/rfcs/
rfc2131.html] . Apache DHCP
helps configure hosts using
configuration information stored
in the Apache Directory backing
store.

6.2. Common Parameters for Configuration


This site is in the process of being reviewed and updated.

6.2.1. Changes to Configuration


This site is in the process of being reviewed and updated.

81
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Protocol Providers Draft

6.2.1.1. Changes to LDAP configuration in 1.5.1


LDAP and LDAPS now use separate beans for configuration. The only difference is that the use of
SSL is determined by parameter 'enabledLdaps'. Both LDAP and LDAPS must support certificate
configuration because LDAP may use Start TLS, while LDAPS has SSL enabled "full time." Both
LDAP and LDAPS follow parameter naming conventions with all the other protocol providers. So,
the former ldapPort is now ipPort and the former ldapsPort is also now ipPort.

Also due to the common configuration used by all protocol providers, individual protocols are no
longer enabled in MutableServerStartupConfiguration. Instead, individual services are enabled using
the parameter 'enabled' on their individual beans.

6.2.1.2. Changes to the other protocols in 1.5.1


All protocols except LDAP are disabled by default.

The Kerberos protocol provider is no longer configured with a Map of properties. All configuration
properties are now available on a bean and configurable using Spring XML.

The Change Password protocol provider is no longer configured with a Map of properties. All
configuration properties are now available on a bean and configurable using Spring XML.

The NTP protocol provider is no longer configured with a Map of properties. All configuration
properties are now available on a bean and configurable using Spring XML.

DNS has now been enabled in ServerContextFactory. The DNS protocol provider is no longer
configured with a Map of properties. All configuration properties are now available on a bean and
configurable using Spring XML.

6.2.2. Configuration Parameters Reference

This page lists all configuration parameters which can be used in conf/server.xml in Version 1.5.1.
For a more detailed description look at the corresponding section in the Advanced User's Guide.

• Section 6.2.2.1, “Environment parameters”

• Section 6.2.2.2, “Protocol providers”

• Section 6.2.2.2.1, “Parameters common to all protocol providers”

• Section 6.3.4, “LDAP-Specific Configuration Parameters”

• Section 6.2.2.2.3, “Kerberos-Specific Configuration Parameters”

• Section 6.2.2.2.4, “Change Password-Specific Configuration Parameters”

• Section 6.2.2.2.5, “NTP-Specific configuration parameters”

• Section 6.2.2.2.6, “DHCP-Specific configuration parameters”

• Section 6.2.2.3, “Server Startup Configuration”

• Section 6.2.2.3.1, “Replication”

• Section 6.2.2.4, “Partition Configuration”

6.2.2.1. Environment parameters


Those parameters are loaded in the org.apache.directory.server.Service.java class, when the server
is started, in the init method :

82
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Protocol Providers Draft

public void init( InstallationLayout install, String[] args ) throws Exception


{
...

if ( install != null )
{
log.info( "server: loading settings from ", install.getConfigurationFile() );
...
env = ( Properties ) factory.getBean( "environment" );
...

They are used everywhere in the server.

The "environment" bean is read from the Spring configuration file, server.xml , shown below :

<bean id="environment" class="org.springframework.beans.factory.config.PropertiesFactoryBean">


<property name="properties">
<props>
<!-- JNDI security properties used to get initial contexts. -->
<prop key="java.naming.security.authentication">simple</prop>
<prop key="java.naming.security.principal">uid=admin,ou=system</prop>
<prop key="java.naming.security.credentials">secret</prop>
<!--
<prop key="java.naming.ldap.attributes.binary"></prop>
-->
</props>
</property>
</bean>

The bean name ("environment") may be renamed to something more explicit, like
"serverEnvironment", IMHO

Table 6.2. Environment parameters


Parameter Default value Description Comment
java.naming.security.authentication
simple The kind of Shouldn't it be SASL
authentication used for now ?
the admin.
java.naming.security.principal
uid=admin,ou=system The admin DN Can be changed to
another DN
java.naming.security.credentials
secret The principal password must be changed at
startup!!!
java.naming.ldap.attributes.binary
empty The list of binary In LDAP, only a few AT
attributes are declared as binary.
This is were we should
describe the other ones

The admin password should be changed when the server is started. A good thing would be that
the server cannot start if this password is kept as is.

6.2.2.2. Protocol providers


6.2.2.2.1. Parameters common to all protocol providers
Since all protocol provider Configuration beans inherit from the same ServiceConfiguration, they
share many of the same configuration parameters.

Table 6.3. Parameters common to all protocol providers


Parameter Default value Description
enabled false Whether this service is enabled.

83
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Protocol Providers Draft

Parameter Default value Description


ipPort No default. The IP port for this service.
ipAddress No default. The IP address for this service.
searchBaseDn "ou=users,ou=system" The single location where users
that can be SASL authenticated
are stored. <to be clarified> The
definition of "entries" depends
on the protocol. For example,
for LDAP, Kerberos, and Change
Password, entries are users
for purposes of authentication.
For DNS, entries are resource
records. If this property is not
set the store will search the
system partition configuration for
catalog entries. Catalog support
is highly experimental and is
only tested in the OSGi build
of ApacheDS using the Config
Admin service.<to be clarified/>

This last parameter has been included with the last SASL addition. The description is not giving
a lot of information about what is this parameter about, except for SASL authentication. The
parameter name is not significant, and another one should be selected, IMHO.

Can soemone elaborate what this parameter is about ?

Table 6.4. Parameters common to all protocol providers 1


Parameter Default value Description
initialContextFactory "org.apache.directory.server.core.jndi.CoreContextFactory"
The JNDI initial context factory
to use.
securityAuthentication "simple" The authentication mechanism
to use for establishing a JNDI
context.
securityPrincipal "uid=admin,ou=system" The principal to use for
establishing a JNDI context.
securityCredentials "secret" The credentials to use for
establishing a JNDI context.
serviceName No default. The friendly name of this service.
servicePid No default. The PID for this service. A PID is
a unique identifier for an instance
of a service. PID's are used by
OSGi's Config Admin service to
dynamically inject configuration
into a service when the service is
started.
bufferSize No default. The MINA buffer size for this
service.
catalogBaseDn No default. The single location where catalog
entries are stored. A catalog entry
is a mapping of a realm (or zone
for DNS) to a search base DN. If
this property is not set the store

84
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Protocol Providers Draft

Parameter Default value Description


will expect a single search base
DN to be set. Catalog support
is highly experimental and is
only tested in the OSGi build
of ApacheDS using the Config
Admin service.

It would be good to have more insight about catalogs.

6.2.2.2.2. LDAP-Specific Configuration Parameters


We have had a lot of modification in this part. Some of them are really going in the
right direction, some other needs to be tuned. First, all the previous configuration has
been moved from the common part to a specific LdapConfiguration part : that is a good
move Second, we now have a new configuration called "ldapsConfiguration", but I'm afraid
that some informations are missing. Third, I don't know if we should have only one
configuration called "ldapConfiguration", or three ("ldapConfiguration", "ldapsConfiguration"
and" ldapSASLConfiguration". Atm, we have two.

Here is the latest version of the ldap configuration :

<bean id="ldapConfiguration" class="org.apache.directory.server.ldap.LdapConfiguration">


<!-- The port to run the LDAP protocol on. -->
<property name="ipPort" value="10389" />

<!-- Whether to allow anonymous access. -->


<property name="allowAnonymousAccess" value="false" />

<!-- The list of supported authentication mechanisms. -->


<property name="supportedMechanisms">
<list>
<value>SIMPLE</value>
<value>CRAM-MD5</value>
<value>DIGEST-MD5</value>
<!--<value>GSSAPI</value>-->
</list>
</property>

<!-- The FQDN of this SASL host, validated during SASL negotiation. -->
<property name="saslHost" value="ldap.example.com" />

<!-- The Kerberos principal name for this LDAP service, used by GSSAPI. -->
<property name="saslPrincipal" value="ldap/ldap.example.com@EXAMPLE.COM" />

<!-- The desired quality-of-protection, used by DIGEST-MD5 and GSSAPI. -->


<property name="saslQop">
<list>
<value>auth</value>
<value>auth-int</value>
<value>auth-conf</value>
</list>
</property>

<!-- The realms serviced by this SASL host, used by DIGEST-MD5 and GSSAPI. -->
<property name="saslRealms">
<list>
<value>example.com</value>
<value>apache.org</value>
</list>
</property>

<!-- The base DN containing users that can be SASL authenticated. -->
<property name="searchBaseDn" value="ou=users,ou=system" />

<!-- SSL CONFIG CAN GO HERE-->

<!-- limits searches by non-admin users to a max time of 15000 -->


<!-- milliseconds and has a default value of 10000 -->
<property name="maxTimeLimit" value="15000" />

<!-- limits searches to max size of 1000 entries: default value is 100 -->

85
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Protocol Providers Draft

<property name="maxSizeLimit" value="1000" />

<!-- the collection of extended operation handlers to install -->


<property name="extendedOperationHandlers">
<list>
<!--<bean class="org.apache.directory.server.ldap.support.starttls.StartTlsHandler"/>-->
<bean class="org.apache.directory.server.ldap.support.extended.GracefulShutdownHandler"/>

<bean class="org.apache.directory.server.ldap.support.extended.LaunchDiagnosticUiHandler"/>
</list>
</property>
</bean>

Table 6.5. LDAP-Specific Configuration Parameters 1


Parameter Default value Description Comments
ipPort 10389 The IP port used by the We are using a port
ldap server above 1024 to allow non
root users to launch the
server
allowAnonymousAccess false Whether to allow Was true in the
anonymous access previous version
supportedMechanisms SIMPLE, CRAM-MD5, The supported The GSSAPI
DIGEST-MD5 authentication mechanism has been
mechanisms temporarilly disabled

We have to figure out if we should reactivate this GSSAPI configuration, or not. Not a simple
matter, right now. If SASL is to be moved to another configuration, then maybe it should be
activated as a default value. TO BE DISCUSSED...

Table 6.6. LDAP-Specific Configuration Parameters 2


Parameter Default value Description Comments
saslHost ldap.example.com The name of this host, The host name must
validated during SASL be selected with great
negotiation. caution
saslPrincipal ldap/ The service principal,
ldap.example.com@EXAMPLE.COM
used by GSSAPI.
saslQop auth, auth-int, auth-conf The quality of
protection (QoP), used
by DIGEST-MD5 and
GSSAPI.
saslRealms example.com The list of realms
serviced by this host.
maxSizeLimit 100 The maximum size
limit.
maxTimeLimit 10000 The maximum time
limit.
enableLdaps false Whether LDAPS is
enabled.
ldapsCertificateFile server-work/ The path to the
certificates/server.cert certificate file.
ldapsCertificatePasswordchangeit The certificate
password.
extendedOperationHandlers
No default. The extended operation
handlers.

86
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Protocol Providers Draft

6.2.2.2.3. Kerberos-Specific Configuration Parameters

<bean id="kdcConfiguration" class="org.apache.directory.server.kerberos.kdc.KdcConfiguration">


<!-- Whether to enable the Kerberos protocol. -->
<property name="enabled" value="false" />
<!-- The port to run the Kerberos protocol on. -->
<property name="ipPort" value="88" />
</bean>

Table 6.7. Kerberos-Specific Configuration Parameters


Parameter Default value Description
encryptionTypes des-cbc-md5 The encryption types.
primaryRealm EXAMPLE.COM The primary realm.
servicePrincipal krbtgt/ The service principal name.
EXAMPLE.COM@EXAMPLE.COM
allowableClockSkew 5 minutes The allowable clock skew.
paEncTimestampRequired true Whether pre-authentication by
encrypted timestamp is required.
maximumTicketLifetime 1440 (24 hours) The maximum ticket lifetime.
maximumRenewableLifetime 10080 (1 week) The maximum renewable
lifetime.
emptyAddressesAllowed true Whether ticket issuance for
empty Host Addresses is allowed.
forwardableAllowed true Whether forwardable tickets are
allowed.
proxiableAllowed true Whether proxiable tickets are
allowed.
postdateAllowed true Whether postdated tickets are
allowed.
renewableAllowed true Whether renewable tickets are
allowed.

6.2.2.2.4. Change Password-Specific Configuration Parameters

<bean id="changePasswordConfiguration" class="org.apache.directory.server.changepw.ChangePasswordConfiguration">


<!-- Whether to enable the Change Password protocol. -->
<property name="enabled" value="false" />
<!-- The port to run the Change Password protocol on. -->
<property name="ipPort" value="464" />
</bean>

Table 6.8. Change Password-Specific Configuration Parameters


Parameter Default value Description
encryptionTypes des-cbc-md5 The encryption types.
primaryRealm EXAMPLE.COM The primary realm.
servicePrincipal kadmin/ The service principal name.
changepw@EXAMPLE.COM
allowableClockSkew 5 minutes The allowable clock skew.
emptyAddressesAllowed true Whether tickets issued with
empty Host Addresses are
allowed.

87
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Protocol Providers Draft

Parameter Default value Description


policyPasswordLength 6 characters The policy for minimum
password length.
policyCategoryCount 3 (out of 4) The policy for number of
character categories required (A
- Z), (a - z), (0 - 9), non-
alphanumeric (!, $, #, %, ... ).
policyTokenSize 3 characters The policy for minimum
token size. Passwords must
not contain tokens larger than
'policyTokenSize' that occur in
the user's principal name.

6.2.2.2.5. NTP-Specific configuration parameters


The NTP parameters are very limited :

<bean id="ntpConfiguration" class="org.apache.directory.server.ntp.NtpConfiguration">


<!-- Whether to enable the NTP protocol. -->
<property name="enabled" value="true" />

<!-- The port to run the NTP protocol on. -->


<property name="ipPort" value="123" />
</bean>

Here is the table containing the default configuration :

Table 6.9. NTP-Specific configuration parameters


Parameter Default value Description Comments
enabled true Tells if the service is on Should be OFF by
or off default
ipPort 123 The default port

Just wanted to know if the UDP and TCP should be enabled or if the server just accept TCP ?

6.2.2.2.6. DHCP-Specific configuration parameters


There is no description about DHCP parameters atm.

6.2.2.3. Server Startup Configuration


6.2.2.3.1. Replication

<bean class="org.apache.directory.server.core.configuration.MutableInterceptorConfiguration">
<property name="name" value="replicationService" />
<property name="interceptor">
<bean class="org.apache.directory.mitosis.service.ReplicationService">
<property name="configuration">
<bean class="org.apache.directory.mitosis.configuration.ReplicationConfiguration">
<property name="replicaId">
<bean class="org.apache.directory.mitosis.common.ReplicaId">
<constructor-arg>
<value>instance_a</value>
</constructor-arg>
</bean>
</property>
<property name="serverPort" value="10390" />
<property name="peerReplicas" value="instance_b@localhost:10392" />
</bean>
</property>
</bean>

88
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Protocol Providers Draft

</property>
</bean>

Table 6.10. Replication Startup Configuration


Parameter Default value Description Comments

6.2.2.4. Partition Configuration


TODO ???

6.3. LDAP Protocol Provider


This site is in the process of being reviewed and updated.

LDAP Protocol configuration is currently being revamped in the SASL branch, as part of
making SASL configurable.

6.3.1. Before
Previously, LDAP protocol configuration existed in the MutableServerStartupConfiguration, along
with Core and Partition configuration.

<bean id="configuration" class="org.apache.directory.server.configuration.MutableServerStartupConfiguration">


<property name="ldapPort" value="389" />
<property name="allowAnonymousAccess" value="false" />

<!-- limits searches by non-admin users to a max time of 15000 -->


<!-- milliseconds and has a default value of 10000 -->
<property name="maxTimeLimit" value="15000" />

<!-- limits searches to max size of 1000 entries: default value is 100 -->
<property name="maxSizeLimit" value="1000" />

<property name="extendedOperationHandlers">
<list>
<bean class="org.apache.directory.server.ldap.support.starttls.StartTlsHandler"/>
<bean class="org.apache.directory.server.ldap.support.extended.GracefulShutdownHandler"/>
<bean class="org.apache.directory.server.ldap.support.extended.LaunchDiagnosticUiHandler"/>
</list>
</property>
</bean>

6.3.2. After
At the same time as the addition of numerous configuration parameters for SASL, LDAP protocol
configuration has all moved to an LdapConfiguration bean.

<bean id="ldapConfiguration" class="org.apache.directory.server.ldap.LdapConfiguration">


<!-- The port to run the LDAP protocol on. -->
<property name="ipPort" value="389" />
<!-- Whether to allow anonymous access. -->
<property name="allowAnonymousAccess" value="true" />

<!-- BEGIN NEW SASL CONFIG -->

<!-- The list of supported authentication mechanisms. -->


<property name="supportedMechanisms">
<list>
<value>SIMPLE</value>
<value>CRAM-MD5</value>
<value>DIGEST-MD5</value>
<value>GSSAPI</value>

89
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Protocol Providers Draft

</list>
</property>

<!-- The FQDN of this SASL host, validated during SASL negotiation. -->
<property name="saslHost" value="ldap.example.com" />

<!-- The Kerberos principal name for this LDAP service, used by GSSAPI. -->
<property name="saslPrincipal" value="ldap/ldap.example.com@EXAMPLE.COM" />

<!-- The desired quality-of-protection, used by DIGEST-MD5 and GSSAPI. -->


<property name="saslQop">
<list>
<value>auth</value>
<value>auth-int</value>
<value>auth-conf</value>
</list>
</property>

<!-- The realms serviced by this SASL host, used by DIGEST-MD5 and GSSAPI. -->
<property name="saslRealms">
<list>
<value>example.com</value>
<value>apache.org</value>
</list>
</property>

<!-- The base DN containing users that can be SASL authenticated. -->
<property name="searchBaseDn" value="ou=users,dc=example,dc=com" />

<!-- END NEW SASL CONFIG -->

<!-- SSL CONFIG CAN GO HERE-->

<!-- limits searches by non-admin users to a max time of 15000 -->


<!-- milliseconds and has a default value of 10000 -->
<property name="maxTimeLimit" value="15000" />
<!-- limits searches to max size of 1000 entries: default value is 100 -->
<property name="maxSizeLimit" value="1000" />
<!-- the collection of extended operation handlers to install -->
<property name="extendedOperationHandlers">
<list>
<bean class="org.apache.directory.server.ldap.support.starttls.StartTlsHandler"/>
<bean class="org.apache.directory.server.ldap.support.extended.GracefulShutdownHandler"/>
<bean class="org.apache.directory.server.ldap.support.extended.LaunchDiagnosticUiHandler"/>
</list>
</property>
</bean>

The LdapConfiguration bean is subordinate to the MutableServerStartupConfiguration.

<bean id="configuration" class="org.apache.directory.server.configuration.MutableServerStartupConfiguration">


...
<property name="ldapConfiguration" ref="ldapConfiguration" />
...
</bean>

6.3.3. Common Service Configuration Parameters


Table 6.11. Common Service Configuration Parameters
Parameter Default value Description
enabled true Whether this service is enabled.
ipPort 389 The IP port for this service.
ipAddress No default. The IP address for this service.
searchBaseDn "ou=users,dc=example,dc=com" The single location where users
are stored. If this property is
not set the store will search the
system partition configuration for
catalog entries. Catalog support
is highly experimental and is

90
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Protocol Providers Draft

Parameter Default value Description


only tested in the OSGi build
of ApacheDS using the Config
Admin service.
initialContextFactory "org.apache.directory.server.core.jndi.CoreContextFactory"
The JNDI initial context factory
to use.
securityAuthentication "simple" The authentication mechanism
to use for establishing a JNDI
context.
securityPrincipal "uid=admin,ou=system" The principal to use for
establishing a JNDI context.
securityCredentials secret The credentials to use for
establishing a JNDI context.
serviceName Apache LDAP Service The friendly name of this service.
servicePid org.apache.directory.server.ldap The PID for this service. A PID is
a unique identifier for an instance
of a service. PID's are used by
OSGi's Config Admin service to
dynamically inject configuration
into a service when the service is
started.
catalogBaseDn No default. The single location where catalog
entries are stored. A catalog entry
is a mapping of a realm (or zone
for DNS) to a search base DN. If
this property is not set the store
will expect a single search base
DN to be set. Catalog support
is highly experimental and is
only tested in the OSGi build
of ApacheDS using the Config
Admin service.

6.3.4. LDAP-Specific Configuration Parameters


Table 6.12. LDAP-Specific Configuration Parameters
Parameter Default value Description
allowAnonymousAccess true Whether to allow anonymous
access.
maxSizeLimit 100 The maximum size limit.
maxTimeLimit 10000 The maximum time limit.
enableLdaps false Whether LDAPS is enabled.
ldapsCertificateFile server-work/certificates/ The path to the certificate file.
server.cert
ldapsCertificatePassword changeit The certificate password.
extendedOperationHandlers No default. The extended operation handlers.
supportedMechanisms SIMPLE, CRAM-MD5, The supported authentication
DIGEST-MD5, GSSAPI mechanisms.
saslHost ldap.example.com The name of this host, validated
during SASL negotiation.

91
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Protocol Providers Draft

Parameter Default value Description


saslPrincipal ldap/ The service principal, used by
ldap.example.com@EXAMPLE.COM
GSSAPI.
saslQop auth, auth-int, auth-conf The quality of protection (QoP),
used by DIGEST-MD5 and
GSSAPI.
saslRealms example.com The list of realms serviced by this
host.

6.3.5. More Information


For help with more advanced configurations, check out our Interoperability Guide [http://
cwiki.apache.org/confluence/pages/viewpage.action?
spaceKey=DIRxSRVx10&title=Interoperability] .

6.4. Kerberos Protocol Provider


This site is in the process of being reviewed and updated.

• ???

• Section 6.4.5, “Kerberos and Unlimited Strength Policy”

• Section 6.4.6, “Kerberos in ApacheDS 1.5.5”

6.4.1. Introduction
The Kerberos provider for Apache Directory implements RFC 1510 [http://www.ietf.org/rfc/
rfc1510.txt] , the Kerberos V5 Network Authentication Service. The purpose of Kerberos is to verify
the identities of principals (users or services) on an unprotected network. While generally thought
of as a single-sign-on technology, Kerberos' true strength is in authenticating users without ever
sending their password over the network. Kerberos is designed for use on open (untrusted) networks
and, therefore, operates under the assumption that packets traveling along the network can be read,
modified, and inserted at will. This chart [http://www.computerworld.com/computerworld/records/
images/pdf/kerberos_chart.pdf] provides a good description of the protocol workflow.

Kerberos is named for the three-headed dog that guards the gates to Hades. The three heads are the
client, the Kerberos server, and the network service being accessed.

The Apache Directory Kerberos provider is implemented as a protocol-provider plugin. As a plugin,


the Kerberos provider leverages Apache Directory's MINA for front-end services and the Apache
Directory read-optimized backing store via JNDI for persistent directory services.

The Kerberos provider for Apache Directory, in conjunction with MINA and the Apache Directory
store, provides an easy-to-use yet fully-featured network authentication service. As implemented
within the Apache Directory, the Kerberos provder will provide:

• Authentication service (RFC 1510)

• Ticket-granting service (RFC 1510)

• Pre-authentication support (RFC 1510)

• DES encryption systems (RFC 1510)

• Triple-DES (DES3) encryption systems

• UDP and TCP Support (MINA)

92
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Protocol Providers Draft

• Easy POJO embeddability for containers such as Geronimo, JBoss, and OSGi

6.4.2. More Information


For help with Kerberos client configurations, check out our Interoperability Guide [http://
cwiki.apache.org/DIRxINTEROP] .

6.4.3. Resources
6.4.3.1. Kerberos Articles
• Centralized Authentication with Kerberos 5, Part I [http://www.linuxjournal.com/article/7336]

• Centralized Authorization Using a Directory Service, Part II [http://www.linuxjournal.com/


article/7334]

6.4.3.2. Microsoft Interoperability


• HTTP-Based Cross-Platform Authentication via the Negotiate Protocol [http://
msdn.microsoft.com/library/default.asp?url=%2Flibrary%2Fen-us%2Fdnsecure%2Fhtml
%2Fhttp-sso-2.asp]

• RFC 2478 - The Simple and Protected GSS-API Negotiation Mechanism

6.4.3.3. Standards
• Encryption and Checksum Specifications for Kerberos 5 [http://www.ietf.org/internet-drafts/draft-
ietf-krb-wg-crypto-07.txt]

• Key Derivation for Kerberos V5 [http://mirrors.isc.org/pub/www.watersprings.org/pub/id/draft-


ietf-cat-kerb-key-derivation-00.txt]

• Key Derivation for Authentication, Integrity, and Privacy [http://mirrors.isc.org/pub/


www.watersprings.org/pub/id/draft-horowitz-key-derivation-00.txt]

• RFC 1510 - The Kerberos Network Authentication Service (V5) [http://www.faqs.org/rfcs/


rfc1510.html]

• RFC 1964 - The Kerberos Version 5 GSS-API Mechanism [http://www.faqs.org/rfcs/rfc1964.html]

• Simplify enterprise Java authentication with single sign-on [http://www-106.ibm.com/


developerworks/java/library/j-gss-sso/]

• Lock down J2ME applications with Kerberos, Part 1: Introducing Kerberos data formats [http://
www-106.ibm.com/developerworks/wireless/library/wi-kerberos/]

• Lock down J2ME applications with Kerberos, Part 2: Authoring a request for a Kerberos ticket
[http://www-106.ibm.com/developerworks/wireless/library/wi-kerberos2.html]

• Lock down J2ME applications with Kerberos, Part 3: Establish secure communication with an e-
bank [http://www-106.ibm.com/developerworks/wireless/library/wi-kerberos3/]

6.4.4. Kerberos Protocol Configuration


This site is in the process of being reviewed and updated.

6.4.4.1. Before
Previously, Kerberos protocol configuration existed in a PropertiesFactoryBean, along with JNDI
environment properties.

93
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Protocol Providers Draft

<bean id="environment" class="org.springframework.beans.factory.config.PropertiesFactoryBean">


<property name="properties">
<props>
<prop key="java.naming.security.authentication">simple</prop>
<prop key="java.naming.security.principal">uid=admin,ou=system</prop>
<prop key="java.naming.security.credentials">secret</prop>
<prop key="kdc.entryBaseDn">ou=users,dc=example,dc=com</prop>
<prop key="kdc.java.naming.security.credentials">secret</prop>
</props>
</property>
</bean>

6.4.4.2. After
At the same time as the addition of numerous configuration parameters for SASL to the LDAP
protocol, Kerberos configuration has all moved to a KdcConfiguration bean.

<bean id="kdcConfiguration" class="org.apache.directory.server.kerberos.kdc.KdcConfiguration">


<!-- The port to run the Kerberos protocol on. -->
<property name="ipPort" value="88" />
</bean>

The KdcConfiguration bean is subordinate to the MutableServerStartupConfiguration.

<bean id="configuration" class="org.apache.directory.server.configuration.MutableServerStartupConfiguration">


...
<property name="kdcConfiguration" ref="kdcConfiguration" />
...
</bean>

6.4.4.3. Common Service Configuration Parameters


Table 6.13. Common Service Configuration Parameters
Parameter Default value Description
enabled false Whether this service is enabled.
ipPort 88 The IP port for this service.
ipAddress No default. The IP address for this service.
searchBaseDn "ou=users,dc=example,dc=com" The single location where
principals are stored. If this
property is not set the store
will search the system partition
configuration for catalog entries.
Catalog support is highly
experimental and is only
tested in the OSGi build of
ApacheDS using the Config
Admin service.
initialContextFactory "org.apache.directory.server.core.jndi.CoreContextFactory"
The JNDI initial context factory
to use.
securityAuthentication "simple" The authentication mechanism
to use for establishing a JNDI
context.
securityPrincipal "uid=admin,ou=system" The principal to use for
establishing a JNDI context.
securityCredentials "secret" The credentials to use for
establishing a JNDI context.

94
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Protocol Providers Draft

Parameter Default value Description


serviceName Apache Kerberos Service The friendly name of this service.
servicePid org.apache.kerberos The PID for this service. A PID is
a unique identifier for an instance
of a service. PID's are used by
OSGi's Config Admin service to
dynamically inject configuration
into a service when the service is
started.
catalogBaseDn No default. The single location where catalog
entries are stored. A catalog entry
is a mapping of a realm (or zone
for DNS) to a search base DN. If
this property is not set the store
will expect a single search base
DN to be set. Catalog support
is highly experimental and is
only tested in the OSGi build
of ApacheDS using the Config
Admin service.

6.4.4.4. Kerberos-Specific Configuration Parameters


Table 6.14. Kerberos-Specific Configuration Parameters
Parameter Default value Description
encryptionTypes des-cbc-md5 The encryption types.
primaryRealm EXAMPLE.COM The primary realm.
servicePrincipal krbtgt/ The service principal name.
EXAMPLE.COM@EXAMPLE.COM
allowableClockSkew 5 minutes The allowable clock skew.
paEncTimestampRequired true Whether pre-authentication by
encrypted timestamp is required.
maximumTicketLifetime 1440 (24 hours) The maximum ticket lifetime.
maximumRenewableLifetime 10080 (1 week) The maximum renewable
lifetime.
emptyAddressesAllowed true Whether ticket issuance for
empty Host Addresses is allowed.
forwardableAllowed true Whether forwardable tickets are
allowed.
proxiableAllowed true Whether proxiable tickets are
allowed.
postdateAllowed true Whether postdated tickets are
allowed.
renewableAllowed true Whether renewable tickets are
allowed.

6.4.4.5. More Information


For help with more advanced configurations, check out our Interoperability Guide [http://
cwiki.apache.org/DIRxINTEROP] .

95
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Protocol Providers Draft

6.4.5. Kerberos and Unlimited Strength Policy


This site is in the process of being reviewed and updated.

6.4.5.1. Introduction
Due to export control restrictions, JDK 5.0 environments do not ship with support for AES-256
enabled. Kerberos uses AES-256 in the 'aes256-cts-hmac-sha1-96' encryption type. To enable
AES-256, you must download "unlimited strength" policy JAR files for your JRE. Policy JAR files
are signed by the JRE vendor so you must download policy JAR files for Sun, IBM, etc. separately.
Also, policy files may be different for each platform, such as i386, Solaris, or HP.

6.4.5.2. Installation
1. Download the unlimited strength policy JAR files.

Table 6.15. Download the unlimited strength policy JAR files


Vendor Link Details
IBM IBM Security information Scroll down to "IBM SDK
[http://www.ibm.com/ Policy files." The same files are
developerworks/java/jdk/ used for the Version 1.4 and
security/50/] Version 5 SDKs.
Sun Java SE Downloads - Scroll down to "Java
Previous Release - JDK Cryptography Extension (JCE)
5 [http://java.sun.com/javase/ Unlimited Strength Jurisdiction
downloads/index_jdk5.jsp] Policy Files 5.0" under "Other
Downloads"

2. Extract the unlimited strength policy JAR files.

Table 6.16. Extract the unlimited strength policy JAR files


File Description
local_policy.jar Unlimited strength local policy file
US_export_policy.jar Unlimited strength US export policy file

3. Install the unlimited strength policy JAR files by copying them to the standard location. <jre-home>
refers to the directory where the J2SE Runtime Environment (JRE) was installed. Adjust pathname
separators for your environment.

Table 6.17. Install the unlimited strength policy JAR files


Standard Location Platform
<jre-home>/lib/security Solaris
<jre-home>\lib\security Win32

4. Optionally, create subfolders in <jre-home>/lib/security, named, for example, "limited" and


"unlimited" so you can switch between policy files easily, by copying the policy JAR files from
one of the subfolders to the <jre-home>/lib/security directory.

6.4.6. Kerberos in ApacheDS 1.5.5


This site was updated for ApacheDS 1.5.5.

96
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Protocol Providers Draft

6.4.6.1. Overview
This page shows how to activate and setup the KDC server of ApacheDS 1.5.5 (build from trunk
2009-08-04). This is a very simple setup (host: localhost, realm: EXAMPLE.COM). Need to check
the setup for other hosts and realms...

6.4.6.2. Activate Kerberos


Acivate the keyDerivationInterceptor and the kdcServer. Also set saslHost and saslPrincipal to
localhost. Add entries for users not before you have activated those elements, otherwise the krb5Key
won't be created!

server.xml

<spring:beans ...>
<defaultDirectoryService ...>
...
<interceptors>
...
<keyDerivationInterceptor/>
...
</interceptors>
</defaultDirectoryService>
...

<!--
+============================================================+
| Kerberos server configuration |
+============================================================+
-->
<kdcServer id="kdcServer" searchBaseDn="ou=Users,dc=example,dc=com">
<transports>
<tcpTransport port="60088" nbThreads="4" backLog="50"/>
<udpTransport port="60088" nbThreads="4" backLog="50"/>
</transports>
<directoryService>#directoryService</directoryService>
</kdcServer>

...

<ldapServer ...
saslHost="localhost"
saslPrincipal="ldap/localhost@EXAMPLE.COM"
searchBaseDn="ou=users,dc=example,dc=com"
...>
...

</spring:beans>

Here is a complete server.xml: server.xml [data/server.xml]

6.4.6.3. Optional: Logging


Configure debug level logging in log4j.properties:

log4j.logger.org.apache.directory.server.kerberos=DEBUG

6.4.6.4. Restart the Server


Restart the server, you should see the following output:

Starting the Kerberos server


_ _ _ __ ____ ___
/ \ _ __ ___ ___| |__ ___| |/ /| _ \ / __|
/ _ \ | '_ \ / _` |/ __| '_ \ / _ \ ' / | | | / /
/ ___ \| |_) | (_| | (__| | | | __/ . \ | |_| \ \__
/_/ \_\ .__/ \__,_|\___|_| |_|\___|_|\_\|____/ \___|
|_|

97
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Protocol Providers Draft

[19:28:03] INFO [org.apache.directory.server.kerberos.kdc.KdcServer] - Kerberos service started.


Kerberos service started.
Kerberos server started

6.4.6.5. Load User Data


Load the following data into the server, e.g. using Apache Directory Studio: kdc-data.ldif [data/kdc-
data.ldif]

Note: The activated keyDerivationInterceptor automatically creates the krb5Key attributes:

Figure 6.1. The activated keyDerivationInterceptor automatically creates the


krb5Key attributes

6.4.6.6. Authenticate using kinit (Unix/Linux)


Make sure kinit is installed.

A minimal /etc/krb5.conf file looks as follows (make sure the port matches!):

[libdefaults]
default_realm = EXAMPLE.COM

[realms]
EXAMPLE.COM = {
kdc = localhost:60088
}

[domain_realm]
.example.com = EXAMPLE.COM
example.com = EXAMPLE.COM

[login]
krb4_convert = true
krb4_get_tickets = false

Then try to authenticate, password is 'secret':

stefan@r61:~$ kinit hnelson@EXAMPLE.COM


Password for hnelson@EXAMPLE.COM:

stefan@r61:~$ klist

98
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Protocol Providers Draft

Ticket cache: FILE:/tmp/krb5cc_1000


Default principal: hnelson@EXAMPLE.COM

Valid starting Expires Service principal


08/04/09 19:54:22 08/05/09 19:54:21 krbtgt/EXAMPLE.COM@EXAMPLE.COM

Kerberos 4 ticket cache: /tmp/tkt1000


klist: You have no tickets cached

6.4.6.7. Authenticate using Apache Directory Studio


You can also configure Apache Directory Studio to use Kerberos (GSSAPI) for authentication. If you
use the following authentication parameters you don't need to configure any Kerberos settings in your
native operating system.

Figure 6.2. Authenticate using Apache Directory Studio

6.5. Change Password Protocol Provider


6.5.1. Introduction
The Change Password service is a protocol provider that implements RFC 3244 [http://www.faqs.org/
rfcs/rfc3244.html] to service Kerberos Change Password and Set Password Protocol requests. Change
Password is a request-reply protocol that uses Kerberos infrastructure to allow users to securely set
initial passwords or to change existing passwords. The Change Password protocol interoperates with

99
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Protocol Providers Draft

the original Kerberos Change Password protocol, while adding the ability for an administrator to set
a password for a new user.

The Change Password service is implemented as a protocol-provider plugin for the Apache Directory
server. As a plugin, Change Password leverages Apache MINA for front-end services and the Apache
Directory read-optimized backing store via JNDI for persistent directory services.

Change Password, in conjunction with MINA and the Apache Directory, provides an easy-to-use yet
fully-featured password service. As implemented within the Apache Directory, Change Password will
provide:

• Original Kerberos password changing service

• Initial password setting service (RFC 3244)

• Optional LDAP management

• UDP and TCP Support (MINA)

• Easy POJO embeddability for containers such as Geronimo, JBoss, and OSGi

6.5.2. Changing Passwords with Windows 2003


6.5.2.1. Configure the Windows 2003 workstation to use an
Apache Change Password server
C:> Ksetup /addkpasswd REALM.EXAMPLE.COM kdc.realm.example.com

6.5.2.2. Change a password using Windows Security


1. After logging on, press CTRL+ALT+DEL.

Figure 6.3. Windows Security

2. Click on the button labeled "Change Password ..."

3. Enter the Old Password and New Password (twice) and click OK.

100
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Protocol Providers Draft

Figure 6.4. Windows Change Password

6.5.2.3. Or change a password using the Command Prompt


C:> Ksetup /domain /changepassword <old-password> <new-password>

6.5.3. Change Password Configuration


This site is in the process of being reviewed and updated.

6.5.3.1. Before
Previously, Change Password protocol configuration existed in a PropertiesFactoryBean, along with
JNDI environment properties.

<bean id="environment" class="org.springframework.beans.factory.config.PropertiesFactoryBean">


<property name="properties">
<props>
<prop key="java.naming.security.authentication">simple</prop>
<prop key="java.naming.security.principal">uid=admin,ou=system</prop>
<prop key="java.naming.security.credentials">secret</prop>
<prop key="changepw.entryBaseDn">ou=users,dc=example,dc=com</prop>
<prop key="changepw.java.naming.security.credentials">secret</prop>
</props>
</property>
</bean>

6.5.3.2. After
At the same time as the addition of numerous configuration parameters for SASL to the LDAP
protocol, Change Password configuration has all moved to a ChangePasswordConfiguration bean.

<bean id="changePasswordConfiguration" class="org.apache.directory.server.changepw.ChangePasswordConfiguration">


<!-- Whether to enable the Change Password protocol. -->
<property name="enabled" value="true" />
<!-- The port to run the Change Password protocol on. -->
<property name="ipPort" value="464" />

101
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Protocol Providers Draft

</bean>

The ChangePasswordConfiguration bean is subordinate to the MutableServerStartupConfiguration.

<bean id="configuration" class="org.apache.directory.server.configuration.MutableServerStartupConfiguration">


...
<property name="changePasswordConfiguration" ref="changePasswordConfiguration" />
...
</bean>

6.5.3.3. Common Service Configuration Parameters


Table 6.18. Common Service Configuration Parameters
Parameter Default value Description
enabled false Whether this service is enabled.
ipPort 464 The IP port for this service.
ipAddress No default. The IP address for this service.
searchBaseDn "ou=users,dc=example,dc=com" The single location where
principals are stored. If this
property is not set the store
will search the system partition
configuration for catalog entries.
Catalog support is highly
experimental and is only
tested in the OSGi build of
ApacheDS using the Config
Admin service.
initialContextFactory "org.apache.directory.server.core.jndi.CoreContextFactory"
The JNDI initial context factory
to use.
securityAuthentication "simple" The authentication mechanism
to use for establishing a JNDI
context.
securityPrincipal "uid=admin,ou=system" The principal to use for
establishing a JNDI context.
securityCredentials "secret" The credentials to use for
establishing a JNDI context.
serviceName Apache Change Password The friendly name of this service.
Service
servicePid org.apache.changepw The PID for this service. A PID is
a unique identifier for an instance
of a service. PID's are used by
OSGi's Config Admin service to
dynamically inject configuration
into a service when the service is
started.
catalogBaseDn No default. The single location where catalog
entries are stored. A catalog entry
is a mapping of a realm (or zone
for DNS) to a search base DN. If
this property is not set the store
will expect a single search base
DN to be set. Catalog support
is highly experimental and is

102
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Protocol Providers Draft

Parameter Default value Description


only tested in the OSGi build
of ApacheDS using the Config
Admin service.

6.5.3.4. Change Password-Specific Configuration Parameters


Table 6.19. Change Password-Specific Configuration Parameters
Parameter Default value Description
encryptionTypes des-cbc-md5 The encryption types.
primaryRealm EXAMPLE.COM The primary realm.
servicePrincipal kadmin/ The service principal name.
changepw@EXAMPLE.COM
allowableClockSkew 5 minutes The allowable clock skew.
emptyAddressesAllowed true Whether tickets issued with
empty Host Addresses are
allowed.
policyPasswordLength 6 characters The policy for minimum
password length.
policyCategoryCount 3 (out of 4) The policy for number of
character categories required (A
- Z), (a - z), (0 - 9), non-
alphanumeric (!, $, #, %, ... ).
policyTokenSize 3 characters The policy for minimum
token size. Passwords must
not contain tokens larger than
'policyTokenSize' that occur in
the user's principal name.

6.5.3.5. More Information


For help with more advanced configurations, check out our Interoperability Guide [http://
cwiki.apache.org/DIRxINTEROP] .

6.5.4. Change Password in ApacheDS 1.5.5


WARNING: Don't use this in a productive environment!

6.5.4.1. Activating the Change Password Server


This requires that the Change Password Server is active and that the allowable Clock Skew for the
Kerberos Server as well as the Change Password Server is less than 5 minutes (5 * 6000 milliseconds).
This is because the ticket lifetime for kpasswd is 5 minutes per default and the ticket lifetime has to
greater than the allowable clock skew + network latency.

<changePasswordServer id="changePasswordServer" allowableClockSkew="24000">


<tcpTransport>
<tcpTransport port="60464" nbThreads="2" backLog="50"/>
</tcpTransport>
<udpTransport>
<udpTransport port="60464" nbThreads="2" backLog="50"/>
</udpTransport>

<directoryService>#directoryService</directoryService>
</changePasswordServer>

103
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Protocol Providers Draft

<kdcServer id="kdcServer" allowableClockSkew="24000">


...
</kdcServer>

6.6. DNS Protocol Provider


This site is in the process of being reviewed and updated.

6.6.1. Introduction
ApacheDS Domain Name Service (DNS) provider implements RFC 1034 [http://www.faqs.org/
rfcs/rfc1034.html] and RFC 1035 [http://www.faqs.org/rfcs/rfc1034.html] to service DNS Protocol
requests.

The DNS provider plugins into the Apache Directory server. As a plugin, the DNS provider uses the
network layer (MINA) for front-end services and the Apache Directory read-optimized backing store
via JNDI for a persistent store.

The ApacheDS DNS provider, in conjunction with MINA and the ApacheDS LDAP JNDI store,
provides an easy-to-use yet fully-featured name resolution service. As implemented within the Apache
Directory, it will provide:

• Domain name service (RFC 1034, 1035)

• Service location support (SRV) (RFC 2782)

• Certificate support (CERT) (RFC 2782)

• Security Extensions (DNSSEC) (RFC 2535)

• Secure query and dynamic update support (GSS-TSIG) (RFC 3645)

• LDAP/JMX management

• UDP and TCP Support (MINA)

• Easy POJO embeddability for containers such as Geronimo, JBoss, and OSGi

6.6.1.1. Basic Testing


On Linux, a typical invocation of dig looks like:

dig @server name type

If no type argument is supplied, dig will perform a lookup for an A record. For example:

bash-2.05b# dig @localhost www.example.com

6.6.1.2. ApacheDS schema for storing DNS zones in LDAP


6.6.1.2.1. Abstract objectClass used to build all DNS record objectclasses

Table 6.20. Abstract objectClass used to build all DNS record objectclasses
objectclass apacheDnsAbstractRecord
apacheDnsName A sequence of labels representing a domain name
or host name

104
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Protocol Providers Draft

objectclass apacheDnsAbstractRecord
apacheDnsType The type of a resource record
apacheDnsClass The class of a resource record
apacheDnsTtl An integer denoting time to live

6.6.1.2.2. Address (A) record

Table 6.21. Address (A) record


objectclass apacheDnsAddressRecord
apacheDnsName A sequence of labels representing a domain name
or host name
apacheDnsType The type of a resource record
apacheDnsClass The class of a resource record
apacheDnsTtl An integer denoting time to live
apacheDnsIpAddress A 4 octet IP address

6.6.1.2.3. Pointer (PTR) record

Table 6.22. Pointer (PTR) record


objectclass apacheDnsPointerRecord
apacheDnsName A sequence of labels representing a domain name
or host name
apacheDnsType The type of a resource record
apacheDnsClass The class of a resource record
apacheDnsTtl An integer denoting time to live
apacheDnsDomainName A domain or sequence dotted labels

6.6.1.2.4. Name Server (NS) record

Table 6.23. Name Server (NS) record


objectclass apacheDnsNameServerRecord
apacheDnsName A sequence of labels representing a domain name
or host name
apacheDnsType The type of a resource record
apacheDnsClass The class of a resource record
apacheDnsTtl An integer denoting time to live
apacheDnsDomainName A domain or sequence dotted labels

6.6.1.2.5. Start Of Authority (SOA) record

Table 6.24. Start Of Authority (SOA) record


objectclass apacheDnsStartOfAuthorityRecord
apacheDnsName A sequence of labels representing a domain name
or host name
apacheDnsType The type of a resource record
apacheDnsClass The class of a resource record

105
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Protocol Providers Draft

objectclass apacheDnsStartOfAuthorityRecord
apacheDnsTtl An integer denoting time to live
apacheDnsSoaMName A domain of the server that was the primary
source of data for this zone
apacheDnsSoaRName The domain which specifies the mailbox of the
person responsible for this zone
apacheDnsSoaSerial The unsigned 32 bit ver num of the original copy
of the zone
apacheDnsSoaRefresh A 32 bit time interval before the zone should be
refreshed
apacheDnsSoaRetry A 32 bit time interval that should elapse before a
failed refresh should be retired
apacheDnsSoaExpire A 32 bit time value that specifies the upper limit
on the time interval that can elapse before the zone
is no longer authoritative
apacheDnsSoaMinimum The unsigned 32 bit minimum TTL field that
should be exported with any RR from this zone.

6.6.1.3. Configuring DNS Zones


Figure 6.5.

6.6.1.3.1. The STRUCTURAL 'dcObject' objectClass


( 1.3.6.1.4.1.1466.344 NAME 'dcObject' SUP top AUXILIARY MUST dc )

6.6.1.3.1.1. An example entry using the STRUCTURAL objectClass domain

dn: dc=tcp,dc=example,dc=com
objectClass: top
objectClass: domain
dc: tcp
description: a placeholder entry used with SRV records

106
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Protocol Providers Draft

6.6.1.3.2. The AUXILIARY 'domain' objectClass


( 0.9.2342.19200300.100.4.13 NAME 'domain' SUP top STRUCTURAL
MUST dc
MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $
x121Address $ registeredAddress $ destinationIndicator $
preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $
street $ postOfficeBox $ postalCode $ postalAddress $
physicalDeliveryOfficeName $ st $ l $ description $ o $
associatedName ) )

6.6.1.3.2.1. An example entry using the AUXILIARY objectClass dcObject

dn: dc=example,dc=com
objectClass: top
objectClass: organization
objectClass: dcObject
dc: example
o: Example Inc.

6.6.1.3.2.2. Resources

• RFC 2247 - Using Domains in LDAP/X.500 Distinguished Names [http://www.faqs.org/rfcs/


rfc2247.html]

6.6.2. DNS Best Practices


6.6.2.1. DNS Testing Tool
Useful tool for testing DNS configuration: www.dnsreport.com [http://www.dnsreport.com/]

There are other tools available from the same people, at www.dnsstuff.com [http://www.dnsstuff.com/
] , but I have not tested any of them.

1. MX - Change MX records from CNAME's to A records. This is supposed to improve lookup speed
and MX pointing to CNAME's is an RFC violation.

2. SOA - Change SOA values to come in line with recommended values, per dnsreports.com.

3. PTR - Add PTR records for server1.example.com. This is to address an error being generated by
AOL and Hotmail, which use reverse lookups on mail servers to weed out spam. Mail on the
example.com mailing lists has increasingly been bounced by AOL and Hotmail as spam and header
inspection points to lack of PTR record. Setting PTR records at the hosting provider is a relatively
new feature, probably added to address this problem.

6.6.3. Notes
6.6.3.1. A Zone is a Pruned Subtree
4.2 Zone "pruned subtree."
Subtree of 1..n nodes/domainNames
Zones are split by org control
A zone is a set of types.
Highest node contains SOA. SOA is 1..1 with highest node.
Below SOA is authoritative.
Highest node contains 1..n NS.
Authoritative NS only at top of zone.
A domain name id's a node.

107
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Protocol Providers Draft

A node is a set of RR's.

NS in leaf is:

• non-authoritative

• referral

• aka "delegation NS RR"

A in leaf is:

• non-authoritative

• aka "glue RR"

Iterative - server refers client (preferred, required)


Recursive - server persues query for client (optional)
Cache - in-memory partition non-authoritative
Authority - points to authority

Non-recursive 4.3.1

1. error

2. answer

3. referral

Unit tests for all 6.2.*


Key algorithm 4.3.1 & 4.3.2

6.6.3.2. Sender Permitted From


• Sender Permitted From [http://spf.pobox.com/] is a DNS-based method for preventing SMTP
spoofing.

6.6.3.3. Secret Key Transaction Authentication for DNS (TSIG)


• RFC 2845 [http://www.faqs.org/rfcs/rfc2845.html]

6.6.4. DNS Protocol Configuration


This site is in the process of being reviewed and updated.

6.6.4.1. Common Service Configuration Parameters


Table 6.25. Common Service Configuration Parameters
Parameter Default value Description
enabled false Whether this service is enabled.
ipPort 53 The IP port for this service.
ipAddress No default. The IP address for this service.
searchBaseDn "ou=users,dc=example,dc=com" The single location where
resource records are stored.
If this property is not set
the store will search the
system partition configuration for

108
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Protocol Providers Draft

Parameter Default value Description


catalog entries. Catalog support
is highly experimental and is
only tested in the OSGi build
of ApacheDS using the Config
Admin service.
initialContextFactory "org.apache.directory.server.core.jndi.CoreContextFactory"
The JNDI initial context factory
to use.
securityAuthentication "simple" The authentication mechanism
to use for establishing a JNDI
context.
securityPrincipal "uid=admin,ou=system" The principal to use for
establishing a JNDI context.
securityCredentials "secret" The credentials to use for
establishing a JNDI context.
serviceName Apache DNS Service The friendly name of this service.
servicePid org.apache.dns The PID for this service. A PID is
a unique identifier for an instance
of a service. PID's are used by
OSGi's Config Admin service to
dynamically inject configuration
into a service when the service is
started.
catalogBaseDn No default. The single location where catalog
entries are stored. A catalog entry
is a mapping of a zone to a search
base DN. If this property is not
set the store will expect a single
search base DN to be set. Catalog
support is highly experimental
and is only tested in the OSGi
build of ApacheDS using the
Config Admin service.

6.6.4.2. More Information


For help with more advanced configurations, check out our Interoperability Guide [http://
cwiki.apache.org/DIRxINTEROP] .

6.7. NTP Protocol Provider


This site is in the process of being reviewed and updated.

6.7.1. Introduction
The Apache NTP Protocol Provider is a Java server that implements RFC 2030 [http://www.faqs.org/
rfcs/rfc2030.html] to service Simple Network Time Protocol requests. The Network Time Protocol is
used to synchronize computer clocks on the Internet.

Apache NTP, in conjunction with MINA and the Apache Directory, provides an easy-to-use yet fully-
featured network time synchronization service. As implemented within the Apache Directory, Apache
NTP will provide:

• Simple Network Time Protocol (SNTP) service (RFC 2030)

109
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Protocol Providers Draft

• JMX remote management (JSR 160, JSR 28)

• UDP and TCP Support (MINA)

• Easy POJO embeddability for containers such as Geronimo, JBoss, and OSGi

6.7.2. Basic Testing


On Linux:

bash-2.05b# ntpdate -u localhost

6.7.3. Resources
6.7.3.1. SNTP RFC's
• RFC 2030 - Simple Network Time Protocol (SNTP) Version 4 for IPv4, IPv6 and OSI http://
www.faqs.org/rfcs/rfc2030.html

• RFC 1305 - Network Time Protocol (Version 3) Specification, Implementation and Analysis http://
www.faqs.org/rfcs/rfc1305.html

6.7.4. NTP Protocol Configuration


This page is only valid with ADS 1.5.5 !

The server.xml file contains the bas configuration for the NTP server :

<ntpServer id="ntpServer" ipPort="60123" nbThreads="2"/>

With such a configuration, the NTP server will listen to port 60123, with UDP and TCP transports
selected.

6.7.4.1. Common Service Configuration Parameters


Here is the list of parameters you can set. The bold parameters are mandatory.

Table 6.26. Common Service Configuration Parameters


Parameter value Description Optional
id "ntpServer" Do not change this NA
value : it is used
internally to identify the
NTP server instance
serviceName Apache NTP Service The friendly name of yes
this service.
enabled true Tells if the server is yes
enabled or not.
ipAddress localhost The IP address for this yes
service.
ipBacklog 50 The backlog size for yes
both UDP and TCP
transport

110
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Protocol Providers Draft

Parameter value Description Optional


ipPort 123 The IP port for this yes
service. It is valid for
both UDP and TCP
transports. To define
only one of those two
transports, or to set a
specific port for each
transport, use the two
following parameters
nbThreads 2 The number of thread yes
used by the service
IoProcessor
tcpBacklog 50 The backlog size for the yes
TCP transport.
tcpPort 123 The TCP port for this yes
service.
nbTcpThreads 2 The number of thread yes
used by the TCP service
IoProcessor
udpBacklog 50 The backlog size for the yes
UDP transport
udpPort 123 The UDP port for this yes
service.
nbUdpThreads 2 The number of thread yes
used by the UDP service
IoProcessor

The last six parameters should be used only if one want to set up only a single transport, or
when UDP and TCP transport don't share the same port.

6.7.4.2. More Information


For help with more advanced configurations, check out our Interoperability Guide [http://
cwiki.apache.org/DIRxINTEROP/] .

6.8. DHCP Protocol Provider


This site is in the process of being reviewed and updated.

6.8.1. Introduction
The ApacheDS Dynamic Host Configuration Protocol (DHCP) provider implements RFC 2131
[http://www.faqs.org/rfcs/rfc2131.html] and RFC 2132 [http://www.faqs.org/rfcs/rfc2132.html] to
pass configuration information to hosts on a TCP/IP network.

The DHCP provider is implemented plugin into the ApacheDS network layer (MINA). As a plugin,
DHCP leverages Apache MINA for front-end services and the Apache Directory read-optimized
backing store via JNDI for a persistent store.

The ApacheDS DHCP plugin, in conjunction with MINA and the Apache Directory store, provides
an easy-to-use yet fully-featured dynamic configuration service. As implemented within the Apache
Directory, DHCP will provide:

111
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Protocol Providers Draft

• DHCP service (RFC 2131, 2132)

• Vendor extensions (RFC 1497)

• Service Location Protocol (SLP) support (RFC 2608)

• Optional LDAP management

• UDP and TCP Support (MINA)

• Easy POJO embeddability for containers such as Geronimo, JBoss, and OSGi

6.8.1.1. DHCP Notes


• Setting up DHCP and TFTP servers [http://www.linux.com/howtos/Clone-HOWTO/setting-
up.shtml]

• PXE using etherboot: HOWTO [http://204.182.52.180/fom-serve/cache/7.html]

• How DHCP works [http://www.j51.com/~sshay/tcpip/dhcp/dhcp.htm]

• RFC 1533 [http://www.faqs.org/rfcs/rfc1533.html] - DHCP Options and BOOTP Vendor


Extensions

• RFC 1534 [http://www.faqs.org/rfcs/rfc1534.html] - Interoperation Between DHCP and BOOTP

• RFC 3118 [http://www.faqs.org/rfcs/rfc3118.html] - Authentication for DHCP Messages

6.8.2. More Information


For help with more advanced configurations, check out our Interoperability Guide [http://
cwiki.apache.org/DIRxINTEROP/] .

112
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Draft

Chapter 7. Extending the server


Work in progress

7.1. How to write a simple custom partition


for ApacheDS
Work in progress. Any feedback highly appreciated!

This site was updated for ApacheDS 1.5.5.

On the mailing list, people ask regularly on how to write a custom partition. If you simply plan to add
another suffix to ApacheDS (besides dc=example,dc=com, for instance) in order to store data, it is not
necessary to write any code. You can simply add some lines to the configuration. The following is for
developers who plan to implement another storage mechanism than the provided default.

• Section 7.1.1, “What exactly is a partition?”

• Section 7.1.2, “Hello world. A minimal partition”

• Section 7.1.2.1, “The sources”

• Section 7.1.2.2, “Implementing the class HelloWorldPartition”

• Section 7.1.2.3, “Using the partition”

• Section 7.1.2.4, “Verification”

• Section 7.1.3, “To be continued”

7.1.1. What exactly is a partition?


Within ApacheDS, a partition is a physically distinct store for a subset of the entries contained within
the server. A partition can be implemented using any storage mechanism or can even be backed in
memory. The default storage mechanism for a partition is JDBM [http://jdbm.sourceforge.net/] .

Implementing your own partition is basically implementing the Partition interface from the
org.apache.directory.server.core.partition package. Please note that this is not an easy task.
Nevertheless I try to give you a starting point with some simple examples.

7.1.2. Hello world. A minimal partition


Let's start with a minimal partition, the hello world [http://en.wikipedia.org/wiki/
Hello_world_program] . Minimal means here, that it is possible to add it to ApacheDS and see it with
an LDAP browser. The partition ...

• correctly implements the Partition interface

• is pluggable in the server (embedded and declarative in the configuration)

• is visible for clients like ldapsearch or Apache Directory Studio

• contains one entry, which contains the famous "hello, world" message in an attribute value
113
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Extending the server Draft

• does not support any modification operations like delete, add etc.

• does not take account of filters in search requests, ...

7.1.2.1. The sources


Currently, the sources are checked in here

• http://svn.apache.org/repos/asf/directory/sandbox/szoerner/helloWorldPartition

In order to build it, simply check it out and type "mvn install".

7.1.2.2. Implementing the class HelloWorldPartition


The following UML class diagram depicts the structure of the little example.

Figure 7.1. Hello World UML

In order to be a partition, class HelloWorldPartition implements the corresponding interface from


org.apache.directory.server.core.partition . It has an association to it's only entry (which will hold
the "hello, world" method). This entry is created in the init life cycle method of the partition, which
looks like this:

...
public void init(DirectoryService core) throws Exception {

// Create LDAP DN
suffixDn = new LdapDN(suffix);
suffixDn.normalize(core.getRegistries().getAttributeTypeRegistry().getNormalizerMapping());
Rdn rdn = suffixDn.getRdn();

// Create the only entry in this partition


ServerEntry entry = new DefaultServerEntry(core
.getRegistries(), this.suffixDn);
entry.put(SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC,
SchemaConstants.ORGANIZATIONAL_UNIT_OC);

114
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Extending the server Draft

entry.put(SchemaConstants.OU_AT, rdn.getUpValue().toString());
entry.put("description", "hello, world", "a minimal partition");

this.helloEntry = entry;
}
...

We assume that the suffix starts with "ou=" in order to create an entry of object class organizational
unit. If someone tries to set a suffix which starts with another attribute for the RDN, the setSuffix will
throw an exception.

The Partition interface requires to implement many methods for all the operations a partition should
support (adding, deleting, modifying entries ...). Due to the fact, that this is a read only partition, the
implementation in our case is minimalistic. Here is the delete method as an example.

...
public void delete(DeleteOperationContext opContext)
throws LdapOperationNotSupportedException {
throw new LdapOperationNotSupportedException(
MODIFICATION_NOT_ALLOWED_MSG, ResultCodeEnum.UNWILLING_TO_PERFORM);
}
...

Although this example should be minimal, some methods need more attention. At least if we want to
see the partitiion in an LDAP and not only in the error logs ...

The important methods are hasEntry , lookup and search . The following code is the search method.
Please note that it ignores search scopes other than BASE and search filters completely in order to
have simple code.

public EntryFilteringCursor search(SearchOperationContext ctx)


throws Exception {

if (ctx.getDn().equals(this.suffixDn)) {
switch (ctx.getScope()) {
case OBJECT:
// return a result with the only entry we have
return new BaseEntryFilteringCursor(
new SingletonCursor<ServerEntry>(this.helloEntry), ctx);
}
}

// return an empty result


return new BaseEntryFilteringCursor(new EmptyCursor<ServerEntry>(), ctx);
}

For the other methods, take a look in the source


code [http://svn.apache.org/repos/asf/directory/sandbox/szoerner/helloWorldPartition/src/main/java/
org/apache/directory/samples/partition/hello/HelloWorldPartition.java] .

7.1.2.3. Using the partition


7.1.2.3.1. Embedded mode

package org.apache.directory.samples.partition.hello;

import org.apache.directory.server.core.DefaultDirectoryService;
import org.apache.directory.server.core.DirectoryService;
import org.apache.directory.server.ldap.LdapServer;
import org.apache.directory.server.protocol.shared.transport.TcpTransport;

/**
* Starts the server with the HelloWorld partition.
*/
public class Main {

public static void main(String[] args) throws Exception {

115
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Extending the server Draft

DirectoryService directoryService = new DefaultDirectoryService();


directoryService.setShutdownHookEnabled(true);

LdapServer ldapServer = new LdapServer();


ldapServer.setDirectoryService(directoryService);
ldapServer.setAllowAnonymousAccess(true);

TcpTransport ldapTransport = new TcpTransport(10389);


ldapServer.setTransports(ldapTransport);

HelloWorldPartition helloPartition = new HelloWorldPartition();


helloPartition.setSuffix("ou=helloWorld");
helloPartition.init(directoryService);

directoryService.addPartition(helloPartition);

directoryService.startup();
ldapServer.start();
}
}

7.1.2.3.2. Adding it to a server.xml file


In order to use the partition in a standard installation of ApacheDS, simply add it to the server.xml
configuration. Provide a "native" Spring bean like this.

server.xml
<spring:beans xmlns:spring="http://xbean.apache.org/schemas/spring/1.0"
xmlns:s="http://www.springframework.org/schema/beans"
xmlns="http://apacheds.org/config/1.0">

...
<defaultDirectoryService ...>
...
<partitions>
...
<s:bean
id="helloPartition"
class="org.apache.directory.samples.partition.hello.HelloWorldPartition">
<s:property name="suffix" value="ou=helloWorld" />
</s:bean>
</partitions>
...
</defaultDirectoryService>
...

Note that the class HelloWorldPartition has to be in the class path of the server. Without, starting the
server leads to a ClassNotFoundException . You can copy the jar file which results from the build
to the lib/ext directory.

7.1.2.4. Verification
After adding the HelloWorldPartition to the directory service like above (embedded or via
configuration in server.xml ), you can browse it with an LDAP browser like the one from Apache
Directory Studio. Here are some screen shots.

Figure 7.2. Hello World LDAP Browser

116
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Extending the server Draft

Figure 7.3. Hello World Entry Editor

Of course using a command line tool works as well ...

$ ldapsearch -h localhost -p 10389 -D "uid=admin,ou=system" -w secret \\


-b "" -s base "(objectclass=*)" namingContexts
version: 1
dn:
namingContexts: ou=system
namingContexts: ou=helloWorld
namingContexts: ou=schema
$
$ ldapsearch -h localhost -p 10389 -D "uid=admin,ou=system" -w secret \\
-b "ou=helloWorld" -s base "(objectclass=*)"

version: 1
dn: ou=helloWorld
objectClass: organizationalUnit
objectClass: top
description: hello, world
description: a minimal partition
ou: helloWorld
$

7.1.3. To be continued
We plan to add more sophistic examples on this topic in the near feature. Stay tuned on the mailing lists.

Here is an older example on the topic: http://svn.apache.org/viewvc/directory/sandbox/akarasulu/


custom-partition

It is outdated, but may still inspire you.

7.2. Implementing a simple custom


Interceptor
This site was updated for ApacheDS 1.5.5.

The following is for developers who plan to implement their own interceptors in order to extend or
modify the functionality of Apache Directory Server. It contains a simple example as a starting point.

• Section 7.2.1, “What exactly is an interceptor?”

• Section 7.2.2, “Password hash. A simple interceptor”

• Section 7.2.2.1, “The sources”

• Section 7.2.2.2, “Implementing the class PasswordHashInterceptor”

117
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Extending the server Draft

• Section 7.2.2.3, “Using the interceptor”

• Section 7.2.2.4, “Verification”

• Section 7.2.2.5, “Limitations of the example”

• Section 7.2.3, “Further reading”

7.2.1. What exactly is an interceptor?


An interceptor filters method calls performed on on the DefaultPartitionNexus just like Servlet filters
do. The ApacheDS configuration contains a chain of filters performing several tasks. In order to
illustrate this, here is the list of interceptors from the default server configuration of ApacheDS 1.5.5

• org.apache.directory.server.core.normalization.NormalizationInterceptor

• org.apache.directory.server.core.authn.AuthenticationInterceptor

• org.apache.directory.server.core.referral.ReferralInterceptor

• org.apache.directory.server.core.authz.AciAuthorizationInterceptor

• org.apache.directory.server.core.authz.DefaultAuthorizationInterceptor

• org.apache.directory.server.core.exception.ExceptionInterceptor

• org.apache.directory.server.core.changelog.ChangeLogInterceptor

• org.apache.directory.server.core.operational.OperationalAttributeInterceptor

• org.apache.directory.server.core.schema.SchemaInterceptor

• org.apache.directory.server.core.subtree.SubentryInterceptor

• org.apache.directory.server.core.collective.CollectiveAttributeInterceptor

• org.apache.directory.server.core.event.EventInterceptor

• org.apache.directory.server.core.trigger.TriggerInterceptor

• org.apache.directory.server.core.journal.JournalInterceptor

Interceptors should usually pass the control of current invocation to the next interceptor by calling
an appropriate method on NextInterceptor . The flow control is returned when the next interceptor's
filter method returns. You can therefore implement pre-, post-, around- invocation handler by how
you place the statement.

Interceptors are a powerful way to extend and modify the server behavior. But be warned. A mistakenly
written interceptor may lead to a dis-functional or corrupt server.

7.2.2. Password hash. A simple interceptor


In order to demonstrate how to write an interceptor, here is a simple but realistic example. The
following requirement should be fulfilled by an interceptor.

• No user password should be stored in the directory in clear text.

To be more concrete:

• If a userpassword is set by an LDAP client in plain text, a message digest algorithm [http://
en.wikipedia.org/wiki/Cryptographic_hash_function] should be applied to the value, and the one-
way encrypted value should be stored

118
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Extending the server Draft

• the algorithm should be applied if new entries are created or existing entries are modified (hence
modify and add operations will be intercepted)

• If the value given by the client is already provided in hashed form, nothing happens, and the given
value is stored in the directory without modification

7.2.2.1. The sources


Currently, the sources are checked in here

• http://svn.apache.org/repos/asf/directory/sandbox/szoerner/passwordHashInterceptor

In order to build it, simply check it out and type "mvn install".

7.2.2.2. Implementing the class PasswordHashInterceptor


The following UML class diagram depicts the structure of the little example. Classes in white are
given by Apache Directory Server as extension points. The two gray classes comprise the example
interceptor.

Figure 7.4. PasswordHash Interceptor UML

The class HashTools contains two simple methods w.r.t. hashing. isAlreadyHashed detects whether a
value has already been hashed with a known message digest algorithm. applyHashAlgorithm applies
a hash algorithm to a sequence of bytes. See the source code and the unit tests of this class for details,
it has not that much to do with the interceptor stuff.

The central class is PasswordHashInterceptor . Every interceptor has to implement the Interceptor
interface from package org.apache.directory.server.core.interceptor . PasswordHashInterceptor does
so by extended the convenience class BaseInterceptor from the same package.

The property hashAlgorithm allows to configure the alhorithm used for hashing the passwords. It
defaults to MD5 (Message-Digest algorithm 5) [http://en.wikipedia.org/wiki/MD5] . The property
passwordAttributeName allows configuration of the attribute type which stores the user password. Its
value will be hashed if needed. The property defaults to "userPassword", which is quite common and
used for instance in the inetOrgPerson [http://www.ietf.org/rfc/rfc2798.txt] object class.

The most interesting methods of the class are add and modify . They intercept the requests ans modify
the attribute values, if needed. See below the complete source code of the class.

package org.apache.directory.samples.interceptor.pwdhash;

import static org.apache.directory.samples.interceptor.pwdhash.HashTools.applyHashAlgorithm;


import static org.apache.directory.samples.interceptor.pwdhash.HashTools.isAlreadyHashed;

import java.util.List;

import org.apache.directory.server.core.entry.ClonedServerEntry;
import org.apache.directory.server.core.interceptor.BaseInterceptor;
import org.apache.directory.server.core.interceptor.NextInterceptor;
import org.apache.directory.server.core.interceptor.context.AddOperationContext;
import org.apache.directory.server.core.interceptor.context.ModifyOperationContext;
import org.apache.directory.shared.ldap.entry.EntryAttribute;
import org.apache.directory.shared.ldap.entry.Modification;
import org.apache.directory.shared.ldap.entry.ModificationOperation;

public class PasswordHashInterceptor extends BaseInterceptor {

private String hashAlgorithm = "MD5";

private String passwordAttributeName = "userPassword";

119
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Extending the server Draft

public void setHashAlgorithm(String hashAlgorithm) {


this.hashAlgorithm = hashAlgorithm;
}

public void setPasswordAttributeName(String passwordAttributeName) {


this.passwordAttributeName = passwordAttributeName;
}

/**
* Intercepts the add operation in order to replace plain password values
* with hashed ones.
*/
@Override
public void add(NextInterceptor next, AddOperationContext opContext)
throws Exception {

ClonedServerEntry entry = opContext.getEntry();


EntryAttribute attribute = entry.get(passwordAttributeName);
if (attribute != null) {
hashPasswordIfNeccessary(attribute);
}

super.add(next, opContext);
}

/**
* Intercepts the modify operation in order to replace plain password values
* with hashed ones.
*/
@Override
public void modify(NextInterceptor next, ModifyOperationContext opContext)
throws Exception {

List<Modification> items = opContext.getModItems();


for (Modification modification : items) {
ModificationOperation operation = modification.getOperation();
if (operation == ModificationOperation.ADD_ATTRIBUTE
|| operation == ModificationOperation.REPLACE_ATTRIBUTE) {
EntryAttribute attribute = modification.getAttribute();
if (attribute.getId().equalsIgnoreCase(passwordAttributeName)) {
hashPasswordIfNeccessary(attribute);
}
}
}
super.modify(next, opContext);
}

protected void hashPasswordIfNeccessary(EntryAttribute attribute) {


try {
byte[] password = attribute.getBytes();
if (!isAlreadyHashed(password)) {
byte[] hashed = applyHashAlgorithm(hashAlgorithm, password);
attribute.clear();
attribute.add(hashed);
}
} catch (Exception e) {
throw new RuntimeException("Password hash failed", e);
}
}
}

7.2.2.3. Using the interceptor


You may use a custom interceptor both in a standard ApacheDS installation and in a server started
embedded.

7.2.2.3.1. Adding it to a standard server installation (server.xml)


In order to get the interceptor installed in a default installation of ApacheDS 1.5.5., just copy the jar-
File resulting from the Maven build, which contains the custom classes, to APACHEDS_INSTALLDIR/
lib/ext .

After that, add the interceptor to the server.xml file in APACHEDS_INSTALLDIR/conf/ . Make sure
to backup the file before your modifications. Within server.xml find the XML elements which list the
interceptors. The easiest way to add a custom interceptor is to add a spring bean (namespace "s"). You
mya set configuration properties to the interceptor as well, if it supports some.

120
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Extending the server Draft

The following fragment shows the interceptor list with the example interceptor added just behind
normalization. For demonstration purposes, the hash algorithm is set to "MD5" (which is the default
of our interceptor anyway).

...
<interceptors>
<normalizationInterceptor/>
<s:bean class="org.apache.directory.samples.interceptor.pwdhash.PasswordHashInterceptor">
<s:property name="hashAlgorithm" value="MD5" />
</s:bean>
<authenticationInterceptor/>
<referralInterceptor/>
<aciAuthorizationInterceptor/>
<defaultAuthorizationInterceptor/>
<exceptionInterceptor/>
<operationalAttributeInterceptor/>
...
</interceptors>
...

7.2.2.3.2. Embedded mode

As an alternative, the following Java code starts an ApacheDS embedded in a main method. The
list of interceptors is complemented with the example interceptor. We insert it exactly behind the
NormalizingInterceptor (the position is a little bit tricky to determine).

package org.apache.directory.samples.interceptor.pwdhash;

import java.util.List;

import org.apache.directory.server.core.DefaultDirectoryService;
import org.apache.directory.server.core.DirectoryService;
import org.apache.directory.server.core.interceptor.Interceptor;
import org.apache.directory.server.core.normalization.NormalizationInterceptor;
import org.apache.directory.server.ldap.LdapServer;
import org.apache.directory.server.protocol.shared.transport.TcpTransport;

/**
* Main class which starts an embedded server with the interceptor inserted into
* the chain.
*/
public class Main {

public static void main(String[] args) throws Exception {

DirectoryService directoryService = new DefaultDirectoryService();


directoryService.setShutdownHookEnabled(true);

List<Interceptor> interceptors = directoryService.getInterceptors();

// Find Normalization interceptor in chain


int insertionPosition = -1;
for (int pos = 0; pos < interceptors.size(); ++pos) {
Interceptor interceptor = interceptors.get(pos);
if (interceptor instanceof NormalizationInterceptor) {
insertionPosition = pos;
}
}

// insert our new interceptor just behind


interceptors.add(insertionPosition + 1, new PasswordHashInterceptor());
directoryService.setInterceptors(interceptors);

LdapServer ldapServer = new LdapServer();


ldapServer.setDirectoryService(directoryService);
ldapServer.setAllowAnonymousAccess(true);

TcpTransport ldapTransport = new TcpTransport(10389);


ldapServer.setTransports(ldapTransport);

directoryService.startup();
ldapServer.start();
}
}

121
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Extending the server Draft

7.2.2.4. Verification
Let's check whether our new interceptor does its job! In order to do so, we use Apache Directory
Studio and connect to the server with the interceptor enabled (see above).

First we create a new entry with the following data, using "New Entry ..." within Studio.

dn: cn=Kate Bush,ou=users,ou=system


objectClass: person
objectClass: top
cn: Kate Bush
sn: Bush

Then we add a new attribute userPassword in the entry editor. For the value, a special editor appears:

Figure 7.5. PasswordHash Interceptor PasswordEditor

Select "Plaintext" as the hash method and enter a new password. We selected "secret" (see screen shot
above). After pressing OK, a modify operation is sent to the server, which will be intercepted by our
example class.

122
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Extending the server Draft

Figure 7.6. PasswordHash Interceptor ModificationLog

After that, the value for userPassword is not "secret", but the MD5 digested value of it.

Figure 7.7. PasswordHash Interceptor EntryEditor

The user Kate Bush is still capable of authenticating with the password "secret", because Apache
Directory Server supports authentication with passwords hashed with this algorithm. You can verify
this by connecting with Studio and the using "cn=Kate Bush,ou=users,ou=system" as bind DN.

Here it is demonstrated with the help of the ldapsearch command line tool. The result also shows that
the userPassword value is hashed with MD5.

$ ldapsearch -h localhost -p 10389 -D "cn=Kate Bush,ou=users,ou=system" \\


-w secret -b "ou=users,ou=system" -s one "(objectClass=*)"
version: 1
dn: cn=Kate Bush,ou=users,ou=system
objectClass: person
objectClass: top
cn: Kate Bush
sn: Bush
userPassword: {MD5}Xr4ilOzQ4PCOq3aQ0qbuaQ==
$

7.2.2.5. Limitations of the example


This example is intended as a demonstration, on how to write your custom interceptor. Don't consider
it bullet proof. It has not been tested under production conditions, etc.

At least the following limitation should be mentioned

123
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Extending the server Draft

• The default hash algorithm MD5 is considered weak.

• Exception handling is poor. E.g. if someone configures an unsupported hash algorithm, the
interceptor fails to create an appropriate LDAP error.

• If a multivalued password attribute is used, the interceptor will simply ignore that fact (does not
apply to userPassword as of RFC 2256).

7.2.3. Further reading


Learn more about interceptors in Section 2.2, “Interceptors” , check out the source code of some
implementations of the Interceptor interface, and/or read the javadoc comments.

124
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Draft

Chapter 8. Partitioning & Replication


8.1. Referrals
TODO ...

8.2. Replication
TODO ...

125
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Draft

Chapter 9. Triggers & Stored


Procedures
Work in progress

9.1. Stored Procedures


This site is in the process of being reviewed and updated.

9.1.1. What are Stored Procedures in LDAP?


The closest thing to a Stored Procedure in LDAP is an Extended Operation. This is how the outside
world would have access to procedures defined within the server. From this we can infer something:
stored procedures are static operations. They can also have return values.

9.1.1.1. Java as the Native SP Language


Rather than complicate things with scripting languages and frameworks like BSF to implement stored
procedures we'll keep this first round really simple. Java is a natural fit for us too so I'm not going to
worry about leaving scripting languages out of the picture. Also with ClassLoaders we can dynamically
install and load new Java classes carrying stored procedures.

9.1.1.2. Storing Classes within the DIT


Classes will be stored within entries in the DIT. These entries like others can be protected by ACI to
prevent exposure. All classes stored in the DIT will not be for stored proc entry points. Some classes
will be supporting classes, and some used to form libraries. So before we start talking about stored
procedures we need to consider code in the DIT and how it might be used.

We already defined a simplistic objectClass and attributeTypes for representing a class within an entry.
A very primitive ClassLoader (CL) was able to load classes on demand by searching for them within
the DIT. We need to go a step further though. Every user will have their own view of the DIT with
ACI in effect, so every user will need to execute procedures in their own CL. A user's CL needs to
pull in all classes in the DIT visible to the user. This CL can be used to execute stored procedures.

Thus the user specific CL needs to load the visible classes (seen by a user) as they are needed to
execute procedures. This could really slow things down though. Some caching may be in order here
but how that's to be done properly and efficiently is yet to be determined.

9.1.1.3. Code Security and Class Conflicts


As we pointed out code is stored in the DIT and ACIs are used to control the code entries visible to
users. Hence this changes the classes loaded into different user CLs. Note that multiple versions or
copies of the same class may exist within the server. This is ok. Conflicts can result as they do with
standard fs based classloaders. The fact that each user has its own CL helps limit the collisions.

We proposed some ACIItem extensions to make sure we can easily and efficiently isolate code
across users. The new creator and notCreator userClasses have been proposed here: ??? . With these
userClasses we can define a single ACIItem in a subentry at each ACSA with a subtreeSpecification
refinement that makes javaClass entries only visible to their creators.

Code reuse will also come into the picture here. The administrator may expose some classes as libraries
that users can build on. Making these classes visible to all users may in turn result in some conflicts.

126
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Triggers & Stored Procedures Draft

For example users may load libraries of a newer version. What will be our policy here? Should this
policy be something that should be decided by the Administrator? Should users be able to override
this policy?

9.1.1.4. Searching and Search Order for Classes


We are not going to constrain users and administrators to have to maintain classes within a specific
region of the DIT. javaClass entries can reside anywhere within the DIT, within any namingContext.
This makes searching for these entries a bit inefficient since the RootDSE must be used and multiple
searches must be conducted on each namingContext until a javaClass is found.

Convensions are good but admins should have options. By default the java subsystem will exhaust
the possibilities. We will allow administrators to configure the java subsystem by specifying
a specific search order for classes. This search order is a list of search operations. Under the
ou=configuration,ou=system area we can manage this list of operations. Basically the admin can
specify each search operation as a LDAP URL to search under for javaClasses. Perhaps each URL can
be prefixed with an 'insert' directive that defines how it is inserted into the list of search operations.

User profiles can also manage this configuration by inserting their own search operations into the list.
The resultant list of search operations is used by the user's ClassLoader to discover classes within the
DIT. Users should be able to see the search order of the system so they can override or inject their own
bypass. This may be a good mechanism for users to control situations where libraries and classes in
the system might conflict with their own version. Perhaps the CL search order for the system should
be published either in the RootDSE or exposed in the ou=system configuration area.

9.1.1.5. Stored Procedure Call Specification


This is no longer valid

As stated before, a stored procedure is close to an LDAP extended operation. However, we will not
register a new extended operation for each stored procedure. Instead of that, we'll have a generic
Stored Procedure extended operation where the stored procedure to be called will be specified in the
parameter list of the extended operation. (Of course this does not prevent some stored procedures to
be published as standalone extended operations.) Here is the proposed stored procedure specification
in ASN.1 format:

StoredProcedure ::= SEQUENCE {


language OCTETSTRING,
procedure OCTETSTRING,
parameters SEQUENCE OF Parameter
}

Parameter ::= SEQUENCE OF {


type OCTETSTRING,
value OCTETSTRING
}

9.1.1.6. Stored Procedure Execution Request Value


??? The wiki is wrong ???

9.1.1.6.1. BER
0x30 LL 0x04 LL abcd [ [ 0x31 LL 0x12 LL abcd 0x30 LL ( 0xc04 LL abcd... [ 0x0A 0x01 0x0[0..2] ] )
[ 0x30 LL 0x30 LL [ 0x04 LL abcd ] 0x84 LL abcd ] | [ 0x30 LL 0x30 LL [ 0x04 LL abcd ] 0x84
LL abcd ] ]

9.1.1.6.2. The State Machine


??? The wiki is wrong ???

127
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Triggers & Stored Procedures Draft

9.1.1.7. Explanations
The language field is used to specify the implementation language of stored procedure to be
called. This field allows the server to provide any kind or more than one kind of stored procedure
implementations. We'll support compiled Java SPs as default and support forJython is scheduled for
after 1.0 release.

The procedure field is used to specify the fully qualified name of the procedure to be called. An
example can be "For.Bar.proc".

The parameters field is used to specify a list of parameters (with their types and values ) to be
given to the procedure to be called. Type information is needed to enable maximum implementation
generalization. Encoding these fields with OCTETSTRING also helps generalization. Interpreting
these fields' values are up to the server. By default we'll require type field to include fully qualified
class name of a Java type and we'll require value field to include a string representation of the parameter
value if it's a primitive one and as byte[] if it's a complex Java object.

The return value of stored procedures will be provided by extended operation responses with same
semantics mentioned above.

As an implementation tip, what we're doing here is like adding reflection capability to our server
to call stored procedures. Thinking in terms of Java reflection mechanish helps us better design the
system here.

According to definitions here, stored procedures in our server will enable users to define and use
their own standard extended operations. We'll explore new usage scenarios of stored procedures like
Triggers, Task Scheduling in the near future.

Our approach provides independence of any client, any server and any language implementation which
will make us write a good IETF RFC about the enhancement.

9.1.1.8. Security
http://www.oracle.com/technology/oramag/oracle/03-jul/o43devjvm.html

9.2. LDAP Triggers


9.2.1. Introduction
This guide serves as an introduction to architectural concepts related to and administration of Triggers
in ApacheDS. ApacheDS is the first server to provide Triggers for LDAP like their counterparts in
RDBMS world. The Trigger Model in ApacheDS has been carefully designed to be LDAP standards
compliant and to take advantage of powerful aspects of ApacheDS like The Administrative Model.
A Trigger basically provides a mechanism to register some sort of action to be fired upon an event.
To restate this considering ApacheDS Triggers, Triggers allow you to register Stored Procedure
invocations to be fired upon any change-inducing LDAP operations on some set of selected entries.
Triggers also provides some facilities to make them even more usable like allowing to pass request
parameters to stored procedures. To make the most sense of this powerful construct you need to first
understand The Administrative Model and have a look at Stored Procedures.

9.2.2. Trigger Specification


A Trigger can be specified with three basic components: Action Time , Trigger Event and Triggered
Action . According to a Trigger specification, when a tracked Event occurs an Action gets invoked
with respect to the Action Time. For example if an Add operation (Event) is performed, information
related to it may be logged with a Stored Procedure (Triggered Action), just After (Action Time) the
Add operation ended. Here is a sample Trigger Specification:

128
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Triggers & Stored Procedures Draft

AFTER Add CALL "Logger.logAddOperation" ($entry,$attributes,$operationPrincipal);

In this example a Stored Procedure named "Logger.logAddOperation" is executed with three operation
specific arguments After an LDAP Add operation is performed. The operation specific arguments will
be discussed later as well as the not-yet-specified set of entries the Trigger is defined on.

9.2.3. Action Time for Triggers


ApacheDS LDAP Triggers currently support only AFTER action time scheme. An AFTER Triggers
is executed just after the tracked event occurs but before the end of request. So before invoking
a Triggered Action with respect to a tracked LDAP operation as a Trigger Event, the operation is
executed essentially. After the Triggered Action is invoked the operation end completely.

TODO: Order of execution of Triggered Actions when there are more than one Triggered Actions
with respect to an Event.

9.2.4. Trigger Events: LDAP Operations


Change inducing LDAP operations can be specified as Trigger Events in a Trigger Specification. The
following are valid identifiers as Trigger Events:

• Modify

• Add

• Delete

• ModifyDN.Rename

• ModifyDN.Export:Base

• ModifyDN.Export:Subtree

• ModifyDN.Import:Base

• ModifyDN.Import:Subtree

9.2.5. Triggered Actions: LDAP Stored Procedures


9.2.6. Planned New Features for Triggers
LDAP Triggers support change inducing LDAP operations as Triggering Events. A more granular
approach can be leveraging operation details, especially for the Modify operation.

An Extended Trigger Specification can be as follows:

AFTER Modify
WHEN ChangedAttributes or:{ userPassword, sambaNTPassword }
CALL "com.mycompany.ldap.utils.sp.Logger:logModifiedEntry" ( $object, $modification );

129
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Draft

Chapter 10. Tuning


Work in progress

10.1. Performance Tuning


This site is in the process of being reviewed and updated.

10.1.1. Balancing Cache w/ Heap Memory Indexing


Attributes
The default partition implementation is based on JDBM. By default it may already index some
common attributes like objectClass and ou for example. However you really want to index attributes
that your applications use frequently in canned queries.

Adding an index on an attribute is pretty simple. The configuration in the server.xml file needs to be
altered before bulk loading data into the server. Otherwise your index will not work properly.

Indices must be configured before loading data into the server. Indices configured after loading
entries into the server will NOT work properly unless they are built using the index builder
command supplied with the ApacheDS tools command line program. More information on this
in the Building Indices section below.

Indices are configured in the partition configuration section of your


server.xml. Each partition will have it's own set of indexed attributes.
These index configurations reside under the indexedAttributes property of
the org.apache.directory.server.core.partition.impl.btree.MutableBTreePartitionConfiguration spring
bean. Here's that section for the stock dc=example,dc=com partition that is configured out of the box
with ApacheDS.

<property name="indexedAttributes">
<set>
<bean class="org.apache.directory.server.core.partition.impl.btree.MutableIndexConfiguration">
<property name="attributeId"><value>1.2.6.1.4.1.18060.1.1.1.3.1</value></property>
<property name="cacheSize"><value>100</value></property>
</bean>
<bean class="org.apache.directory.server.core.partition.impl.btree.MutableIndexConfiguration">
<property name="attributeId"><value>1.2.6.1.4.1.18060.1.1.1.3.2</value></property>
<property name="cacheSize"><value>100</value></property>
</bean>
<bean class="org.apache.directory.server.core.partition.impl.btree.MutableIndexConfiguration">
<property name="attributeId"><value>1.2.6.1.4.1.18060.1.1.1.3.3</value></property>
<property name="cacheSize"><value>100</value></property>
</bean>
<bean class="org.apache.directory.server.core.partition.impl.btree.MutableIndexConfiguration">
<property name="attributeId"><value>1.2.6.1.4.1.18060.1.1.1.3.4</value></property>
<property name="cacheSize"><value>100</value></property>
</bean>
<bean class="org.apache.directory.server.core.partition.impl.btree.MutableIndexConfiguration">
<property name="attributeId"><value>1.2.6.1.4.1.18060.1.1.1.3.5</value></property>
<property name="cacheSize"><value>10</value></property>
</bean>
<bean class="org.apache.directory.server.core.partition.impl.btree.MutableIndexConfiguration">
<property name="attributeId"><value>1.2.6.1.4.1.18060.1.1.1.3.6</value></property>
<property name="cacheSize"><value>10</value></property>
</bean>
<bean class="org.apache.directory.server.core.partition.impl.btree.MutableIndexConfiguration">
<property name="attributeId"><value>1.2.6.1.4.1.18060.1.1.1.3.7</value></property>
<property name="cacheSize"><value>10</value></property>
</bean>

<bean class="org.apache.directory.server.core.partition.impl.btree.MutableIndexConfiguration">
<property name="attributeId"><value>dc</value></property>
<property name="cacheSize"><value>100</value></property>
</bean>

130
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Tuning Draft

<bean class="org.apache.directory.server.core.partition.impl.btree.MutableIndexConfiguration">
<property name="attributeId"><value>ou</value></property>
<property name="cacheSize"><value>100</value></property>
</bean>
<bean class="org.apache.directory.server.core.partition.impl.btree.MutableIndexConfiguration">
<property name="attributeId"><value>krb5PrincipalName</value></property>
<property name="cacheSize"><value>100</value></property>
</bean>
<bean class="org.apache.directory.server.core.partition.impl.btree.MutableIndexConfiguration">
<property name="attributeId"><value>uid</value></property>
<property name="cacheSize"><value>100</value></property>
</bean>
<bean class="org.apache.directory.server.core.partition.impl.btree.MutableIndexConfiguration">
<property name="attributeId"><value>objectClass</value></property>
<property name="cacheSize"><value>100</value></property>
</bean>
</set>
</property>

As you can see indices are specified using a MutableIndexConfiguration spring bean. Just add one
of these to your existing configuration setting the attributeId to the OID or name of the attribute you
want to index. There is cacheSize parameter used to set the amount of cache on your index as well.
Most of the time 100 will suffice no matter how big in capacity your server is.

This number (100) is the number of entries stored in the cache, regardless to their size. Be carefull
when dealing with huge entries - those which contains jpeg images -

So if I wanted to index the attribute initials all I have to do is append the following xml fragment to
this set of indexed attributes:

<bean class="org.apache.directory.server.core.partition.impl.btree.MutableIndexConfiguration">
<property name="attributeId"><value>initials</value></property>
<property name="cacheSize"><value>100</value></property>
</bean>

That's it. Now queries on initials alone should perform about 50X faster.

131
© 2003-2010 The Apache Software Foundation Privacy Policy
Draft Draft

Index

132
© 2003-2010 The Apache Software Foundation Privacy Policy

Você também pode gostar