chap-ldap-operations.xml revision 7107
6443N/A<?xml version="1.0" encoding="UTF-8"?>
6443N/A<!--
6443N/A ! CCPL HEADER START
6443N/A !
6443N/A ! This work is licensed under the Creative Commons
6443N/A ! Attribution-NonCommercial-NoDerivs 3.0 Unported License.
6443N/A ! To view a copy of this license, visit
6443N/A ! http://creativecommons.org/licenses/by-nc-nd/3.0/
6443N/A ! or send a letter to Creative Commons, 444 Castro Street,
6443N/A ! Suite 900, Mountain View, California, 94041, USA.
6443N/A !
6443N/A ! You can also obtain a copy of the license at
6443N/A ! trunk/opendj3/legal-notices/CC-BY-NC-ND.txt.
6443N/A ! See the License for the specific language governing permissions
6443N/A ! and limitations under the License.
6443N/A !
6443N/A ! If applicable, add the following below this CCPL HEADER, with the fields
6443N/A ! enclosed by brackets "[]" replaced with your own identifying information:
6443N/A ! Portions Copyright [yyyy] [name of copyright owner]
6443N/A !
6443N/A ! CCPL HEADER END
6443N/A !
7082N/A ! Copyright 2011-2014 ForgeRock AS
6443N/A !
6443N/A-->
6443N/A<chapter xml:id='chap-ldap-operations'
6443N/A xmlns='http://docbook.org/ns/docbook' version='5.0' xml:lang='en'
6443N/A xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
7082N/A xsi:schemaLocation='http://docbook.org/ns/docbook
7082N/A http://docbook.org/xml/5.0/xsd/docbook.xsd'
6443N/A xmlns:xlink='http://www.w3.org/1999/xlink'
6443N/A xmlns:xinclude='http://www.w3.org/2001/XInclude'>
6443N/A <title>Performing LDAP Operations</title>
6443N/A
6443N/A <para>OpenDJ comes with a Control Panel browser for managing entries and also
6443N/A command-line tools for performing LDAP operations. This chapter demonstrates
6443N/A how to use the command line tools to script LDAP operations.</para>
6443N/A
6443N/A <section xml:id="search-ldap">
6443N/A <title>Searching the Directory</title>
6443N/A <indexterm><primary>Searching data</primary></indexterm>
6443N/A
6443N/A <para>Searching the directory resembles searching for a phone number in
6443N/A a paper phone book. You can look up a phone number because you know the
6443N/A last name of a subscriber's entry. In other words, you use the value of
6443N/A one attribute of the entry to find entries that have another attribute
6443N/A you want.</para>
6443N/A
6443N/A <para>Yet whereas a paper phone book has only one index (alphabetical order
6443N/A by name), the directory has many indexes. For a search you therefore always
6443N/A specify which index to use, by specifying which attribute(s) you are using
6443N/A to lookup entries.</para>
6443N/A
6443N/A <para>Your paper phone book might be divided into white pages for residential
6443N/A subscribers, and yellow pages for businesses. If you are looking up an
6443N/A individual's phone number, you limit your search to the white pages.
6443N/A Directory services divide entries in various ways, often to separate
6443N/A organizations, and to separate groups from user entries from printers for
6443N/A example, but potentially in other ways. When searching you therefore also
6443N/A specify where in the directory to search.</para>
6443N/A
6443N/A <para>The <command>ldapsearch</command> command thus takes at minimum a
6443N/A search base DN option and an LDAP filter. The search base DN identifies
6443N/A where in the directory to search for entries that match the filter.
6443N/A For example, if you are looking for printers, you might specify the base
6443N/A DN as <literal>ou=Printers,dc=example,dc=com</literal>. Perhaps you are
6443N/A visiting the <literal>GNB00</literal> office and are looking for a
6443N/A printer.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>ldapsearch --baseDN ou=Printers,dc=example,dc=com "(printerLocation=GNB00)"</userinput>
7097N/A </screen>
6443N/A
6443N/A <para>In the example, the LDAP filter indicates to the directory that you
6443N/A want to lookup printer entries where the <literal>printerLocation</literal>
6443N/A attribute is equal to <literal>GNB00</literal>.</para>
6443N/A
6443N/A <para>You also specify the host and port to access directory services,
6443N/A what protocol to use (for example, LDAP/SSL, or StartTLS to protect
6443N/A communication). If the directory service does not allow anonymous access
6443N/A to the data you want to search, you also identify who is performing the
6443N/A search and provide their credentials, such as a password or
6443N/A certificate. Finally, you can specify a list of attributes to return.
6443N/A If you do not specify attributes, then the search returns all user attributes
6443N/A for the entry.</para>
6443N/A
6443N/A <itemizedlist>
6443N/A <para>Review the following examples in this section to get a sense of how
6443N/A searches work.</para>
6443N/A <listitem><para><xref linkend="simple-filter-search"/></para></listitem>
6443N/A <listitem><para><xref linkend="complex-filter-search"/></para></listitem>
6443N/A <listitem><para><xref linkend="operational-attrs-search"/></para></listitem>
6443N/A <listitem><para><xref linkend="attr-desc-list-search"/></para></listitem>
6443N/A <listitem><para><xref linkend="escape-characters-in-filter"/></para></listitem>
6443N/A <listitem><para><xref linkend="extensible-match-search"/></para></listitem>
6443N/A <listitem><para><xref linkend="localized-search"/></para></listitem>
6443N/A </itemizedlist>
6443N/A
6443N/A <example xml:id="simple-filter-search">
6443N/A <title>Search: Simple Filter</title>
6443N/A
6443N/A <para>The following example searches for entries with user IDs
6443N/A (<literal>uid</literal>) containing <literal>jensen</literal>, returning
6443N/A only DNs and user ID values.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>ldapsearch --port 1389 --baseDN dc=example,dc=com "(uid=*jensen*)" uid</userinput>
7097N/A<computeroutput>dn: uid=ajensen,ou=People,dc=example,dc=com
6443N/Auid: ajensen
6443N/A
6443N/Adn: uid=bjensen,ou=People,dc=example,dc=com
6443N/Auid: bjensen
6443N/A
6443N/Adn: uid=gjensen,ou=People,dc=example,dc=com
6443N/Auid: gjensen
6443N/A
6443N/Adn: uid=jjensen,ou=People,dc=example,dc=com
6443N/Auid: jjensen
6443N/A
6443N/Adn: uid=kjensen,ou=People,dc=example,dc=com
6443N/Auid: kjensen
6443N/A
6443N/Adn: uid=rjensen,ou=People,dc=example,dc=com
6443N/Auid: rjensen
6443N/A
6443N/Adn: uid=tjensen,ou=People,dc=example,dc=com
6443N/Auid: tjensen
6443N/A
6443N/A
7097N/AResult Code: 0 (Success)</computeroutput>
7097N/A </screen>
6443N/A </example>
6443N/A
6443N/A <example xml:id="complex-filter-search">
6443N/A <title>Search: Complex Filter</title>
6443N/A
6443N/A <para>The following example returns entries with <literal>uid</literal>
6443N/A containing <literal>jensen</literal> for users located in Santa Clara. The
6443N/A command returns the attributes associated with the <literal>person</literal>
6443N/A object class.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>ldapsearch \
7097N/A --port 1389 \
7097N/A --baseDN ou=people,dc=example,dc=com \
7097N/A "(&amp;(uid=*jensen*)(l=Santa Clara))" \
7097N/A @person</userinput>
7097N/A<computeroutput>dn: uid=ajensen,ou=People,dc=example,dc=com
6443N/AobjectClass: person
6443N/AobjectClass: organizationalPerson
6443N/AobjectClass: inetOrgPerson
6443N/AobjectClass: posixAccount
6443N/AobjectClass: top
6443N/Acn: Allison Jensen
6443N/AtelephoneNumber: +1 408 555 7892
6443N/Asn: Jensen
6443N/A
6443N/Adn: uid=gjensen,ou=People,dc=example,dc=com
6443N/AobjectClass: person
6443N/AobjectClass: organizationalPerson
6443N/AobjectClass: inetOrgPerson
6443N/AobjectClass: posixAccount
6443N/AobjectClass: top
6443N/Acn: Gern Jensen
6443N/AtelephoneNumber: +1 408 555 3299
6443N/Asn: Jensen
6443N/A
6443N/Adn: uid=kjensen,ou=People,dc=example,dc=com
6443N/AobjectClass: person
6443N/AobjectClass: organizationalPerson
6443N/AobjectClass: inetOrgPerson
6443N/AobjectClass: posixAccount
6443N/AobjectClass: top
6443N/Acn: Kurt Jensen
6443N/AtelephoneNumber: +1 408 555 6127
6443N/Asn: Jensen
6443N/A
6443N/Adn: uid=tjensen,ou=People,dc=example,dc=com
6443N/AobjectClass: person
6443N/AobjectClass: organizationalPerson
6443N/AobjectClass: inetOrgPerson
6443N/AobjectClass: posixAccount
6443N/AobjectClass: top
6443N/Acn: Ted Jensen
6443N/AtelephoneNumber: +1 408 555 8622
6443N/Asn: Jensen
7097N/A</computeroutput>
6443N/A</screen>
6443N/A
6443N/A <para>Complex filters can use both "and" syntax,
6443N/A <literal>(&amp;(<replaceable>filtercomp</replaceable>)(<replaceable>filtercomp</replaceable>))</literal>,
6443N/A and "or" syntax,
6443N/A <literal>(|(<replaceable>filtercomp</replaceable>)(<replaceable>filtercomp</replaceable>))</literal>.</para>
6443N/A </example>
6443N/A
6443N/A <example xml:id="operational-attrs-search">
6443N/A <title>Search: Return Operational Attributes</title>
6443N/A
6443N/A <para>Use <literal>+</literal> in the attribute list after the filter
6443N/A to return all operational attributes. Alternatively, specify operational
6443N/A attributes by name.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>ldapsearch --port 1389 --baseDN dc=example,dc=com uid=bjensen +</userinput>
7097N/A<computeroutput>dn: uid=bjensen,ou=People,dc=example,dc=com
6443N/AnumSubordinates: 0
6443N/AstructuralObjectClass: inetOrgPerson
6443N/ApwdPolicySubentry: cn=Default Password Policy,cn=Password Policies,cn=config
6443N/AsubschemaSubentry: cn=schema
6443N/AhasSubordinates: false
6443N/AentryDN: uid=bjensen,ou=people,dc=example,dc=com
7097N/AentryUUID: fc252fd9-b982-3ed6-b42a-c76d2546312c</computeroutput>
7097N/A </screen>
6443N/A </example>
6443N/A
6443N/A <example xml:id="attr-desc-list-search">
6443N/A <title>Search: Return Attributes for an Object Class</title>
6443N/A
6443N/A <para>Use <literal>@<replaceable>objectClass</replaceable></literal> in the
6443N/A attribute list after the filter to return the attributes associated with
6443N/A a particular object class.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>ldapsearch --port 1389 --baseDN dc=example,dc=com uid=bjensen @person</userinput>
7097N/A<computeroutput>dn: uid=bjensen,ou=People,dc=example,dc=com
6443N/AobjectClass: person
6443N/AobjectClass: organizationalPerson
6443N/AobjectClass: inetOrgPerson
6443N/AobjectClass: posixAccount
6443N/AobjectClass: top
6443N/Acn: Barbara Jensen
6443N/Acn: Babs Jensen
6443N/AtelephoneNumber: +1 408 555 1862
7097N/Asn: Jensen</computeroutput>
7097N/A </screen>
6443N/A </example>
6443N/A
6443N/A <example xml:id="escape-characters-in-filter">
6443N/A <title>Search: Escaping Search Filter Characters</title>
6443N/A
6443N/A <para><link xlink:href='http://tools.ietf.org/html/rfc4515'>RFC 4515:
6443N/A Lightweight Directory Access Protocol (LDAP): String Representation
6443N/A of Search Filters</link> mentions a number of characters that you must
6443N/A handle with care when using them in search filters.</para>
6443N/A
6443N/A <itemizedlist>
6443N/A <para>For a filter like <literal>(attr=<replaceable
6443N/A >value</replaceable>)</literal>, the following list indicates characters
6443N/A that you must replace with a backslash ( <literal>\</literal> ) followed
6443N/A by two hexadecimal digits when using them as part of the
6443N/A <replaceable>value</replaceable> string.</para>
6443N/A <listitem>
6443N/A <para>Replace <literal>*</literal> with <literal>\2a</literal>.</para>
6443N/A </listitem>
6443N/A <listitem>
6443N/A <para>Replace <literal>(</literal> with <literal>\28</literal>.</para>
6443N/A </listitem>
6443N/A <listitem>
6443N/A <para>Replace <literal>)</literal> with <literal>\29</literal>.</para>
6443N/A </listitem>
6443N/A <listitem>
6443N/A <para>Replace <literal>\</literal> with <literal>\5c</literal>.</para>
6443N/A </listitem>
6443N/A <listitem>
6443N/A <para>Replace NUL (0x00) with <literal>\00</literal>.</para>
6443N/A </listitem>
6443N/A </itemizedlist>
6443N/A
6443N/A <para>The following example shows a filter with escaped characters matching
6443N/A an actual value.</para>
7097N/A
7097N/A <screen>
7097N/A$ <userinput>ldapsearch --port 1389 --baseDN dc=example,dc=com \
7097N/A "(description=\28*\5c*\2a\29)" description</userinput>
7097N/A<computeroutput>dn: uid=bjensen,ou=People,dc=example,dc=com
7097N/Adescription: (A \great\ description*)</computeroutput>
7097N/A </screen>
6443N/A </example>
6443N/A
6443N/A <example xml:id="extensible-match-search"><?dbfo keep-together="auto"?>
6443N/A <title>Search: List Active Accounts</title>
6443N/A
6443N/A <para>OpenDJ supports extensible matching rules, meaning you can pass in
6443N/A filters specifying a matching rule OID that extends your search beyond what
6443N/A you can do with standard LDAP. One specific matching rule of this type that
6443N/A OpenDJ supports is the generalized time based "later than" and "earlier
6443N/A than" matching rules. See the example, <link
7097N/A xlink:show="new"
7097N/A xlink:role="http://docbook.org/xlink/role/olink"
7097N/A xlink:href="admin-guide#extensible-match-index-example"><citetitle>Configure
6443N/A an Extensible Match Index</citetitle></link>, showing how to build an index
6443N/A for these matching rules.</para>
6443N/A
6443N/A <para>You can use these matching rules to list, for example, all users who
6443N/A have authenticated recently.</para>
6443N/A
6443N/A <para>First set up an attribute to store a last login timestamp.
6443N/A You can do this by adding a schema file for the attribute.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>ldapmodify \
7097N/A --port 1389 \
7097N/A --hostname opendj.example.com \
7097N/A --bindDN "cn=Directory Manager" \
6443N/A --bindPassword password
6443N/Adn: cn=schema
6443N/Achangetype: modify
6443N/Aadd: attributeTypes
6443N/AattributeTypes: ( lastLoginTime-oid
6443N/A NAME 'lastLoginTime'
6443N/A DESC 'Last time the user logged in'
6443N/A EQUALITY generalizedTimeMatch
6443N/A ORDERING generalizedTimeOrderingMatch
6443N/A SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
6443N/A SINGLE-VALUE
6443N/A NO-USER-MODIFICATION
6443N/A USAGE directoryOperation
7097N/A X-ORIGIN 'OpenDJ example documentation' )</userinput>
6443N/A
7097N/A<computeroutput>Processing MODIFY request for cn=schema
7097N/AMODIFY operation successful for DN cn=schema</computeroutput>
7097N/A </screen>
6443N/A
6443N/A <para>Configure the applicable password policy to write the last login
6443N/A timestamp when a user authenticates. The following command configures the
6443N/A default password policy to write the timestamp in generalized time format
6443N/A to the <literal>lastLoginTime</literal> operational attribute on the user's
6443N/A entry.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>dsconfig \
7097N/A set-password-policy-prop \
7097N/A --port 4444 \
7097N/A --hostname opendj.example.com \
7097N/A --bindDN "cn=Directory Manager" \
7097N/A --bindPassword password \
7097N/A --policy-name "Default Password Policy" \
7097N/A --set last-login-time-attribute:lastLoginTime \
7097N/A --set last-login-time-format:"yyyyMMddHH'Z'" \
7097N/A --trustAll \
7097N/A --no-prompt</userinput>
7097N/A </screen>
6443N/A
6443N/A <para>Wait a while for users to authenticate again (or test it yourself) so
6443N/A that OpenDJ writes the timestamps. The following search then returns users
6443N/A who have authenticated in the last three months (13 weeks) after you
6443N/A configured OpenDJ to keep the last login timestamps.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>ldapsearch \
7097N/A --port 1389 \
7097N/A --baseDN dc=example,dc=com \
7097N/A "(lastLoginTime:1.3.6.1.4.1.26027.1.4.6:=13w)" mail</userinput>
7097N/A<computeroutput>dn: uid=bjensen,ou=People,dc=example,dc=com
6443N/Amail: bjensen@example.com
6443N/A
6443N/Adn: uid=kvaughan,ou=People,dc=example,dc=com
7097N/Amail: kvaughan@example.com</computeroutput>
7097N/A </screen>
6443N/A </example>
6443N/A
6443N/A <example xml:id="localized-search"><?dbfo keep-together="auto"?>
6443N/A <title>Search: Language Subtype</title>
6443N/A
6443N/A <para>OpenDJ directory server supports many language subtypes. See the
6443N/A chapter on <link xlink:href="admin-guide#appendix-l10n"
6443N/A xlink:role="http://docbook.org/xlink/role/olink"
6443N/A ><citetitle>Localization</citetitle></link> for a list.</para>
6443N/A
6443N/A <para>When you perform a search you can request the language subtype by
6443N/A OID or by language subtype string. For example, the following search gets
6443N/A the French version of a common name. The example uses the
6443N/A <command>base64</command> command provided with OpenDJ directory server to
6443N/A decode the attribute value.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>ldapsearch \
7097N/A --port 1389 \
7097N/A --baseDN dc=example,dc=com \
7097N/A "(givenName:fr:=Fréderique)" cn\;lang-fr</userinput>
7097N/A<computeroutput>dn: uid=fdupont,ou=People,dc=example,dc=com
7097N/Acn;lang-fr:: RnJlZMOpcmlxdWUgRHVwb250</computeroutput>
6443N/A
7097N/A$ <userinput>base64 decode -d RnJlZMOpcmlxdWUgRHVwb250</userinput>
7097N/A<computeroutput>Fredérique Dupont</computeroutput>
7097N/A </screen>
6443N/A
6443N/A <itemizedlist>
6443N/A <para>At the end of the OID or language subtype, you further specify the
6443N/A matching rule as follows:</para>
6443N/A <listitem>
6443N/A <para>Add <literal>.1</literal> for less than</para>
6443N/A </listitem>
6443N/A <listitem>
6443N/A <para>Add <literal>.2</literal> for less than or equal to</para>
6443N/A </listitem>
6443N/A <listitem>
6443N/A <para>Add <literal>.3</literal> for equal to (default)</para>
6443N/A </listitem>
6443N/A <listitem>
6443N/A <para>Add <literal>.4</literal> for greater than or equal to</para>
6443N/A </listitem>
6443N/A <listitem>
6443N/A <para>Add <literal>.5</literal> for greater than</para>
6443N/A </listitem>
6443N/A <listitem>
6443N/A <para>Add <literal>.6</literal> for substring</para>
6443N/A </listitem>
6443N/A </itemizedlist>
6443N/A </example>
6443N/A
6443N/A <para>The following table describes the operators you can use in LDAP search
6443N/A filters.</para>
6443N/A <xinclude:include href="/shared/table-filter-operators.xml" />
6443N/A </section>
6443N/A
6443N/A <section xml:id="compare-ldap">
6443N/A <title>Comparing Attribute Values</title>
6443N/A <indexterm><primary>Comparing attribute values</primary></indexterm>
6443N/A
6443N/A <para>The compare operation checks whether an attribute value you specify
6443N/A matches the attribute value stored on one or more directory entries.</para>
6443N/A
6443N/A <example xml:id="compare-example">
6443N/A <title>Compare: Checking <literal>authPassword</literal></title>
6443N/A
6443N/A <para>In this example, Kirsten Vaughan checks whether the hashed password
6443N/A value matches the stored value on <literal>authPassword</literal>.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>ldapcompare \
7097N/A --port 1389 \
7097N/A --bindDN "uid=kvaughan,ou=people,dc=example,dc=com" \
7097N/A --bindPassword bribery \
7097N/A 'authPassword:MD5$dFHgpDxXUT8=$qlC4xMXvmVlusJLz9/WJ5Q==' \
6443N/A uid=kvaughan,ou=people,dc=example,dc=com</userinput>
7097N/A<computeroutput>Comparing type authPassword with value
6443N/A MD5$dFHgpDxXUT8=$qlC4xMXvmVlusJLz9/WJ5Q== in entry
6443N/A uid=kvaughan,ou=people,dc=example,dc=com
6443N/ACompare operation returned true for entry
7097N/A uid=kvaughan,ou=people,dc=example,dc=com</computeroutput>
7097N/A </screen>
6443N/A </example>
6443N/A </section>
6443N/A
6443N/A <section xml:id="write-ldap">
6443N/A <title>Updating the Directory</title>
6443N/A <indexterm><primary>Updating data</primary></indexterm>
6443N/A <indexterm><primary>LDIF</primary><secondary>Examples</secondary></indexterm>
6443N/A <para>Authorized users can change directory data using the LDAP add, modify,
6443N/A modify DN, and delete operations.</para>
6443N/A
6443N/A <section xml:id="add-ldap">
6443N/A <title>Adding Entries</title>
6443N/A
6443N/A <para>With the <command>ldapmodify -a</command> command, authorized users
6443N/A can add entire entries from the same sort of LDIF file used to import
6443N/A and export data.</para>
6443N/A
6443N/A <example xml:id="add-two-users">
6443N/A <title>Add: Two New Users</title>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>cat new-users.ldif</userinput>
7097N/A<computeroutput>dn: cn=Arsene Lupin,ou=Special Users,dc=example,dc=com
6443N/AobjectClass: person
6443N/AobjectClass: top
6443N/Acn: Arsene Lupin
6443N/AtelephoneNumber: +33 1 23 45 67 89
6443N/Asn: Lupin
6443N/A
6443N/Adn: cn=Horace Velmont,ou=Special Users,dc=example,dc=com
6443N/AobjectClass: person
6443N/AobjectClass: top
6443N/Acn: Horace Velmont
6443N/AtelephoneNumber: +33 1 12 23 34 45
7097N/Asn: Velmont</computeroutput>
6443N/A
7097N/A$ <userinput>ldapmodify \
7097N/A --defaultAdd \
7097N/A --port 1389 \
7097N/A --bindDN "uid=kvaughan,ou=people,dc=example,dc=com" \
7097N/A --bindPassword bribery \
7097N/A --filename new-users.ldif</userinput>
7097N/A<computeroutput>Processing ADD request for cn=Arsene Lupin,ou=Special Users,dc=example,dc=com
6443N/AADD operation successful for DN
6443N/A cn=Arsene Lupin,ou=Special Users,dc=example,dc=com
6443N/AProcessing ADD request for cn=Horace Velmont,ou=Special Users,dc=example,dc=com
6443N/AADD operation successful for DN
7097N/A cn=Horace Velmont,ou=Special Users,dc=example,dc=com</computeroutput>
7097N/A </screen>
6443N/A </example>
6443N/A </section>
6443N/A
6443N/A <section xml:id="modify-ldap">
6443N/A <title>Modifying Entry Attributes</title>
6443N/A
6443N/A <para>With the <command>ldapmodify</command> command, authorized users
6443N/A can change the values of attributes in the directory using LDIF as specified
6443N/A in <link xlink:href='http://tools.ietf.org/html/rfc2849'>RFC 2849</link>.</para>
6443N/A
6443N/A <example xml:id="modify-add-attribute">
6443N/A <title>Modify: Adding Attributes</title>
6443N/A
6443N/A <para>The following example adds a description and JPEG photo to Sam
6443N/A Carter's entry.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>cat scarter-mods.ldif</userinput>
7097N/A<computeroutput>dn: uid=scarter,ou=people,dc=example,dc=com
6443N/Achangetype: modify
6443N/Aadd: description
6443N/Adescription: Accounting Manager
6443N/A-
6443N/Aadd: jpegphoto
7097N/Ajpegphoto:&lt;file:///tmp/Samantha-Carter.jpg</computeroutput>
6443N/A
7097N/A$ <userinput>ldapmodify \
7097N/A --port 1389 \
7097N/A --bindDN "uid=kvaughan,ou=people,dc=example,dc=com" \
7097N/A --bindPassword bribery \
7097N/A --filename scarter-mods.ldif</userinput>
7097N/A<computeroutput>Processing MODIFY request for uid=scarter,ou=people,dc=example,dc=com
7097N/AMODIFY operation successful for DN uid=scarter,ou=people,dc=example,dc=com</computeroutput>
7097N/A </screen>
6443N/A </example>
6443N/A
6443N/A <example xml:id="modify-replace-attribute">
6443N/A <title>Modify: Changing an Attribute Value</title>
6443N/A
6443N/A <para>The following example replaces the description on Sam Carter's
6443N/A entry.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>cat scarter-newdesc.ldif</userinput>
7097N/A<computeroutput>dn: uid=scarter,ou=people,dc=example,dc=com
6443N/Achangetype: modify
6443N/Areplace: description
7097N/Adescription: Accounting Director</computeroutput>
6443N/A
7097N/A$ <userinput>ldapmodify \
7097N/A --port 1389 \
7097N/A --bindDN "uid=kvaughan,ou=people,dc=example,dc=com" \
7097N/A --bindPassword bribery \
7097N/A --filename scarter-newdesc.ldif</userinput>
7097N/A<computeroutput>Processing MODIFY request for uid=scarter,ou=people,dc=example,dc=com
7097N/AMODIFY operation successful for DN uid=scarter,ou=people,dc=example,dc=com</computeroutput>
7097N/A </screen>
6443N/A </example>
6443N/A
6443N/A <example xml:id="modify-delete-attribute">
6443N/A <title>Modify: Deleting an Attribute Value</title>
6443N/A
6443N/A <para>The following example deletes the JPEG photo on Sam Carter's
6443N/A entry.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>cat /path/to/scarter-deljpeg.ldif</userinput>
7097N/A<computeroutput>dn: uid=scarter,ou=people,dc=example,dc=com
6443N/Achangetype: modify
7097N/Adelete: jpegphoto</computeroutput>
6443N/A
7097N/A$ <userinput>ldapmodify \
7097N/A --port 1389 \
7097N/A --bindDN "uid=kvaughan,ou=people,dc=example,dc=com" \
7097N/A --bindPassword bribery \
7097N/A --filename scarter-deljpeg.ldif</userinput>
7097N/A<computeroutput>Processing MODIFY request for uid=scarter,ou=people,dc=example,dc=com
7097N/AMODIFY operation successful for DN uid=scarter,ou=people,dc=example,dc=com</computeroutput>
7097N/A </screen>
6443N/A </example>
6443N/A
6443N/A <example xml:id="modify-optimistic-concurrency"><?dbfo keep-together="auto"?>
6443N/A <title>Modify: Optimistic Concurrency</title>
6443N/A
6443N/A <para>Imagine you are writing an application that lets end users update
6443N/A user profiles through a browser. You store user profiles as OpenDJ entries.
6443N/A Your end users can look up user profiles and modify them. Your application
6443N/A assumes that the end users can tell the right information when they see it,
6443N/A and so aims to update profiles exactly as users see them on their
6443N/A screens.</para>
6443N/A
6443N/A <para>Consider two users, Alice and Bob, both busy and often interrupted.
6443N/A Alice has Babs Jensen's new phone and room numbers. Bob has Babs's new
6443N/A location and description. Both assume that they have all the information
6443N/A that has changed. What can you do to make sure that your application
6443N/A applies the right changes when Alice and Bob simulaneously update Babs
6443N/A Jensen's profile?</para>
6443N/A
6443N/A <para>OpenDJ offers a couple of features to help you in this situation.
6443N/A One of the features is the <link
6443N/A xlink:role="http://docbook.org/xlink/role/olink"
6443N/A xlink:href="admin-guide#assertion-request-control">LDAP Assertion
6443N/A Control</link>, used to tell OpenDJ to perform the modify only if
6443N/A an assertion you make stays true. The other feature is OpenDJ's support
6443N/A for <link xlink:href="http://tools.ietf.org/html/rfc2616#section-3.11"
6443N/A xlink:show="new">entity tag</link> (ETag) attributes, making it easy to
6443N/A check whether the entry in the directory is the same as the entry you
6443N/A read.</para>
6443N/A
6443N/A <para>Alice and Bob both get Babs's entry. In LDIF the relevant
6443N/A attributes from the entry look like this. Notice the ETag.</para>
6443N/A
6443N/A <programlisting language="ldif">dn: uid=bjensen,ou=People,dc=example,dc=com
6443N/AtelephoneNumber: +1 408 555 1862
6443N/AroomNumber: 0209
6443N/Al: Cupertino
6443N/AETag: 000000007a1999df</programlisting>
6443N/A
6443N/A <para>Bob prepares his changes in your application. Bob is almost ready
6443N/A to submit the new location and description when Carol stops by to ask Bob
6443N/A a few questions.</para>
6443N/A
6443N/A <para>Alice starts just after Bob, but manages to submit her changes
6443N/A without getting interrupted. Now Babs's entry looks like this.</para>
6443N/A
6443N/A <programlisting language="ldif">dn: uid=bjensen,ou=People,dc=example,dc=com
6443N/Adescription: Updated by Alice
6443N/AtelephoneNumber: +47 2108 1746
6443N/AroomNumber: 1389
6443N/Al: Cupertino
6443N/AETag: 00000000aec2c1e9</programlisting>
6443N/A
6443N/A <para>In your application, you use the ETag attribute value with the
6443N/A assertion control to prevent Bob's update from going through when the
6443N/A ETag value has changed. Your application tries the equivalent of the
6443N/A following commands with Bob's updates.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>cat /path/to/bobs.ldif</userinput>
7097N/A<computeroutput>dn: uid=bjensen,ou=People,dc=example,dc=com
6443N/Achangetype: modify
6443N/Areplace: l
6443N/Al: Grenoble
6443N/A-
6443N/Aadd: description
7097N/Adescription: Employee of the Month</computeroutput>
6443N/A
7097N/A$ <userinput>ldapmodify \
7097N/A --bindDN "cn=Directory Manager" \
7097N/A --bindPassword password \
7097N/A --port 1389 \
7097N/A --filename /path/to/bobs.ldif \
7097N/A --assertionFilter "(ETag=000000007a1999df)"</userinput>
7097N/A<computeroutput>Processing MODIFY request for uid=bjensen,ou=People,dc=example,dc=com
6443N/AMODIFY operation failed
6443N/AResult Code: 122 (Assertion Failed)
6443N/AAdditional Information: Entry uid=bjensen,ou=People,dc=example,dc=com
6443N/A cannot be modified because the request contained an LDAP assertion control
7097N/A and the associated filter did not match the contents of the that entry</computeroutput>
7097N/A </screen>
6443N/A
6443N/A <para>Your application therefore reloads Babs's entry, also getting the new
6443N/A ETag value, <literal>00000000aec2c1e9</literal>, and lets Bob try again.
6443N/A This time Bob's changes do not collide with other changes. Babs's entry is
6443N/A successfully updated.</para>
6443N/A
6443N/A <programlisting language="ldif">dn: uid=bjensen,ou=People,dc=example,dc=com
6443N/Adescription: Employee of the Month
6443N/AtelephoneNumber: +47 2108 1746
6443N/AroomNumber: 1389
6443N/Al: Grenoble
6443N/AETag: 00000000e882c35e</programlisting>
6443N/A </example>
6443N/A </section>
6443N/A
6443N/A <section xml:id="filter-adds-modifies">
6443N/A <title>Filtering Add &amp; Modify Operations</title>
6443N/A <indexterm>
6443N/A <primary>Updating data</primary>
6443N/A <secondary>Filtering</secondary>
6443N/A </indexterm>
6443N/A
6443N/A <para>Some client applications send updates including attributes with names
6443N/A that differ from the attribute names defined in OpenDJ. Other client
6443N/A applications might try to update attributes they should not update, such
6443N/A as the operational attributes <literal>creatorsName</literal>,
6443N/A <literal>createTimestamp</literal>, <literal>modifiersName</literal>,
6443N/A and <literal>modifyTimestamp</literal>. Ideally you would fix the client
6443N/A application behavior, but that is not always feasible.</para>
6443N/A
6443N/A <para>You can configure the attribute cleanup plugin to filter add and
6443N/A modify requests, renaming attributes in requests using incorrect names,
6443N/A and removing attributes that applications should not change.</para>
6443N/A
6443N/A <example xml:id="attr-cleanup-rename">
6443N/A <title>Renaming Incoming Attributes</title>
6443N/A
6443N/A <para>The following example renames incoming <literal>email</literal>
6443N/A attributes to <literal>mail</literal> attributes. First, configure the
6443N/A attribute cleanup plugin to rename the inbound attribute.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>dsconfig \
7097N/A create-plugin \
7097N/A --port 4444 \
7097N/A --hostname opendj.example.com \
7097N/A --bindDN "cn=Directory Manager" \
7097N/A --bindPassword password \
7097N/A --type attribute-cleanup \
7097N/A --plugin-name "Rename email to mail" \
7097N/A --set enabled:true \
7097N/A --set rename-inbound-attributes:email:mail \
7097N/A --trustAll \
7097N/A --no-prompt</userinput>
7097N/A </screen>
6443N/A
6443N/A <para>Next, see that it works as expected.</para>
6443N/A
7097N/A <screen>$ <userinput>cat email.ldif</userinput>
7097N/A<computeroutput>dn: uid=newuser,ou=People,dc=example,dc=com
6443N/Auid: newuser
6443N/AobjectClass: person
6443N/AobjectClass: organizationalPerson
6443N/AobjectClass: inetOrgPerson
6443N/AobjectClass: top
6443N/Acn: New User
6443N/Asn: User
6443N/Aou: People
6443N/Aemail: newuser@example.com
7097N/AuserPassword: changeme</computeroutput>
6443N/A
7097N/A$ <userinput>ldapmodify \
7097N/A --port 1389 \
7097N/A --bindDN "cn=Directory Manager" \
7097N/A --bindPassword password \
7097N/A --defaultAdd \
7097N/A --filename email.ldif</userinput>
7097N/A<computeroutput>Processing ADD request for uid=newuser,ou=People,dc=example,dc=com
7097N/AADD operation successful for DN uid=newuser,ou=People,dc=example,dc=com</computeroutput>
7097N/A
7097N/A$ <userinput>ldapsearch --port 1389 --baseDN dc=example,dc=com uid=newuser mail</userinput>
7097N/A<computeroutput>dn: uid=newuser,ou=People,dc=example,dc=com
7097N/Amail: newuser@example.com</computeroutput>
7097N/A </screen>
6443N/A </example>
6443N/A
6443N/A <example xml:id="attr-cleanup-remove">
6443N/A <title>Removing Incoming Attributes</title>
6443N/A
6443N/A <para>The following example prevents client applications from adding or
6443N/A modifying <literal>creatorsName</literal>,
6443N/A <literal>createTimestamp</literal>, <literal>modifiersName</literal>,
6443N/A and <literal>modifyTimestamp</literal> attributes. First, set up the
6443N/A attribute cleanup plugin.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>dsconfig \
7097N/A create-plugin \
7097N/A --port 4444 \
7097N/A --hostname opendj.example.com \
7097N/A --bindDN "cn=Directory Manager" \
7097N/A --bindPassword password \
7097N/A --type attribute-cleanup \
7097N/A --plugin-name "Remove attrs" \
7097N/A --set enabled:true \
7097N/A --set remove-inbound-attributes:creatorsName \
7097N/A --set remove-inbound-attributes:createTimestamp \
7097N/A --set remove-inbound-attributes:modifiersName \
7097N/A --set remove-inbound-attributes:modifyTimestamp \
7097N/A --trustAll \
7097N/A --no-prompt</userinput>
7097N/A </screen>
6443N/A
6443N/A <para>Next, see that it works as expected.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>cat badattrs.ldif</userinput>
7097N/A<computeroutput>dn: uid=badattr,ou=People,dc=example,dc=com
6443N/Auid: newuser
6443N/AobjectClass: person
6443N/AobjectClass: organizationalPerson
6443N/AobjectClass: inetOrgPerson
6443N/AobjectClass: top
6443N/Acn: Bad Attr
6443N/Asn: Attr
6443N/Aou: People
6443N/Amail: badattr@example.com
6443N/AuserPassword: changeme
6443N/AcreatorsName: cn=Bad Attr
6443N/AcreateTimestamp: Never in a million years.
6443N/AmodifiersName: cn=Directory Manager,cn=Root DNs,cn=config
7097N/AmodifyTimestamp: 20110930164937Z</computeroutput>
6443N/A
7097N/A$ <userinput>ldapmodify \
7097N/A --port 1389 \
7097N/A --bindDN "cn=Directory Manager" \
7097N/A --bindPassword password \
7097N/A --defaultAdd \
7097N/A --filename badattrs.ldif</userinput>
7097N/A<computeroutput>Processing ADD request for uid=badattr,ou=People,dc=example,dc=com
7097N/AADD operation successful for DN uid=badattr,ou=People,dc=example,dc=com</computeroutput>
7097N/A
7097N/A$ <userinput>ldapsearch --port 1389 --baseDN dc=example,dc=com uid=badattr +</userinput>
7097N/A<computeroutput>dn: uid=badattr,ou=People,dc=example,dc=com
6443N/AnumSubordinates: 0
6443N/AstructuralObjectClass: inetOrgPerson
6443N/ApwdPolicySubentry: cn=Default Password Policy,cn=Password Policies,cn=config
6443N/AsubschemaSubentry: cn=schema
6443N/AhasSubordinates: false
6443N/AentryDN: uid=badattr,ou=people,dc=example,dc=com
6443N/AentryUUID: 35e5cb0e-e929-49d8-a50f-2df036d60db9
6443N/ApwdChangedTime: 20110930165959.135Z
6443N/AcreatorsName: cn=Directory Manager,cn=Root DNs,cn=config
7097N/AcreateTimestamp: 20110930165959Z</computeroutput>
7097N/A </screen>
6443N/A </example>
6443N/A </section>
6443N/A
6443N/A <section xml:id="rename-ldap">
6443N/A <title>Renaming Entries</title>
6443N/A
6443N/A <para>The Relative Distinguished Name (RDN) refers to the part of an
6443N/A entry's DN that distinguishes it from all other DNs at the same level
6443N/A in the directory tree. For example <literal>uid=bjensen</literal> is
6443N/A the RDN of the entry having DN
6443N/A <literal>uid=bjensen,ou=People,dc=example,dc=com</literal>.</para>
6443N/A
6443N/A <para>With the <command>ldapmodify</command> command, authorized users
6443N/A can rename entries in the directory.</para>
6443N/A
6443N/A <para>When you change the RDN of the entry, you are renaming the entry,
6443N/A modifying the value of the naming attribute, but also modifying the entry's
6443N/A DN.</para>
6443N/A
6443N/A <example xml:id="rename-modrdn">
6443N/A <title>Rename: Modifying the DN</title>
6443N/A
6443N/A <para>Sam Carter is changing her last name to Jensen, and changing her
6443N/A login from <literal>scarter</literal> to <literal>sjensen</literal>.
6443N/A The following example renames and changes Sam Carter's entry accordingly.
6443N/A Notice the boolean field, <literal>deleteoldrdn: 1</literal>, which
6443N/A indicates that the previous RDN, <literal>uid: scarter</literal>, should
6443N/A be removed. (Setting <literal>deleteoldrdn: 0</literal> instead would
6443N/A preserve <literal>uid: scarter</literal> on the entry.)</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>cat /path/to/scarter-sjensen.ldif</userinput>
7097N/A<computeroutput>dn: uid=scarter,ou=people,dc=example,dc=com
6443N/Achangetype: modrdn
6443N/Anewrdn: uid=sjensen
6443N/Adeleteoldrdn: 1
6443N/A
6443N/Adn: uid=sjensen,ou=people,dc=example,dc=com
6443N/Achangetype: modify
6443N/Areplace: cn
6443N/Acn: Sam Jensen
6443N/A-
6443N/Areplace: sn
6443N/Asn: Jensen
6443N/A-
6443N/Areplace: homeDirectory
6443N/AhomeDirectory: /home/sjensen
6443N/A-
6443N/Areplace: mail
7097N/Amail: sjensen@example.com</computeroutput>
6443N/A
7097N/A$ <userinput>ldapmodify \
7097N/A --port 1389 \
7097N/A --bindDN "uid=kvaughan,ou=people,dc=example,dc=com" \
7097N/A --bindPassword bribery \
7097N/A --filename /path/to/scarter-sjensen.ldif</userinput>
7097N/A<computeroutput>Processing MODIFY DN request for uid=scarter,ou=people,dc=example,dc=com
6443N/AMODIFY DN operation successful for DN uid=scarter,ou=people,dc=example,dc=com
6443N/AProcessing MODIFY request for uid=sjensen,ou=people,dc=example,dc=com
7097N/AMODIFY operation successful for DN uid=sjensen,ou=people,dc=example,dc=com</computeroutput>
7097N/A </screen>
6443N/A </example>
6443N/A </section>
6443N/A
6443N/A <section xml:id="rename-moddn">
6443N/A <title>Moving Entries</title>
6443N/A
6443N/A <para>When you rename an entry with child entries, the directory has
6443N/A to move all the entries underneath.</para>
6443N/A
6443N/A <note>
6443N/A <para>The modify DN operation only works when moving entries in the same
6443N/A backend, under the same suffix. Also, depending on the number of entries
6443N/A you move, this can be a resource-intensive operation.</para>
6443N/A </note>
6443N/A
6443N/A <para>With the <command>ldapmodify</command> command, authorized users
6443N/A can move entries in the directory.</para>
6443N/A
6443N/A <example xml:id="move-entry-example"><?dbfo keep-together="auto"?>
6443N/A <title>Move: Merging Customer and Employees Under
6443N/A <literal>ou=People</literal></title>
6443N/A
6443N/A <para>The following example moves
6443N/A <literal>ou=Customers,dc=example,dc=com</literal> to
6443N/A <literal>ou=People,dc=example,dc=com</literal>, and then moves each
6443N/A employee under <literal>ou=Employees,dc=example,dc=com</literal>
6443N/A under <literal>ou=People,dc=example,dc=com</literal> as well, finally
6443N/A removing the empty <literal>ou=Employees,dc=example,dc=com</literal>
6443N/A container. Here, <literal>deleteoldrdn: 1</literal> indicates that the
6443N/A old RDN, <literal>ou: Customers</literal>, should be removed from the
6443N/A entry. For employees, <literal>deleteoldrdn: 0</literal> indicates that
6443N/A old RDNs, in this case <literal>uid</literal> attribute values, should
6443N/A be preserved.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>cat move-customers.ldif</userinput>
7097N/A<computeroutput>dn: ou=Customers,dc=example,dc=com
6443N/Achangetype: modrdn
6443N/Anewrdn: ou=People
6443N/Adeleteoldrdn: 1
7097N/Anewsuperior: dc=example,dc=com</computeroutput>
6443N/A
7097N/A$ <userinput>ldapmodify \
7097N/A --port 1389 \
7097N/A --bindDN "cn=Directory Manager" \
7097N/A --bindPassword password \
7097N/A --filename move-customers.ldif</userinput>
7097N/A<computeroutput>Processing MODIFY DN request for ou=Customers,dc=example,dc=com
7097N/AMODIFY DN operation successful for DN ou=Customers,dc=example,dc=com</computeroutput>
7097N/A
7097N/A$ <userinput>cat move-employees.pl</userinput>
7097N/A<computeroutput>#!/usr/bin/perl -w
6443N/A
6443N/A# For each employee, construct a spec to move under ou=People.
7097N/Awhile (&lt;>)
6443N/A{
6443N/A # Next line folded for readability only. Should not be split.
6443N/A $_ =~ s/dn: (.*?)(,.*)/dn: $1$2\nchangetype: moddn\nnewrdn: $1\n
6443N/A deleteoldrdn: 0\nnewsuperior: ou=People,dc=example,dc=com/;
6443N/A print;
7097N/A}</computeroutput>
7097N/A
7097N/A$ <userinput>ldapsearch --port 1389 --baseDN ou=Employees,dc=example,dc=com uid=* - \
7097N/A | move-employees.pl > /tmp/move-employees.ldif</userinput>
7097N/A
7097N/A$ <userinput>head -n 6 /tmp/move-employees.ldif</userinput>
7097N/A<computeroutput>dn: uid=abarnes,ou=Employees,dc=example,dc=com
6443N/Achangetype: moddn
6443N/Anewrdn: uid=abarnes
6443N/Adeleteoldrdn: 0
7097N/Anewsuperior: ou=People,dc=example,dc=com</computeroutput>
6443N/A
7097N/A$ <userinput>ldapmodify \
7097N/A --port 1389 \
7097N/A --bindDN "cn=Directory Manager" \
7097N/A --bindPassword password \
7097N/A --filename /tmp/move-employees.ldif</userinput>
7097N/A<computeroutput>Processing MODIFY DN request for uid=abarnes,ou=Employees,dc=example,dc=com
6443N/AMODIFY DN operation successful for DN uid=abarnes,ou=Employees,dc=example,dc=com
6443N/AProcessing MODIFY DN request for uid=abergin,ou=Employees,dc=example,dc=com
6443N/AMODIFY DN operation successful for DN uid=abergin,ou=Employees,dc=example,dc=com
6443N/A...
6443N/AProcessing MODIFY DN request for uid=wlutz,ou=Employees,dc=example,dc=com
7097N/AMODIFY DN operation successful for DN uid=wlutz,ou=Employees,dc=example,dc=com</computeroutput>
7097N/A
7097N/A$ <userinput>ldapdelete \
7097N/A --port 1389 \
7097N/A --bindDN "cn=Directory Manager" \
7097N/A --bindPassword password \
7097N/A ou=Employees,dc=example,dc=com</userinput>
7097N/A<computeroutput>Processing DELETE request for ou=Employees,dc=example,dc=com
7097N/ADELETE operation successful for DN ou=Employees,dc=example,dc=com</computeroutput>
7097N/A </screen>
6443N/A </example>
6443N/A </section>
6443N/A
6443N/A <section xml:id="delete-ldap">
6443N/A <title>Deleting Entries</title>
6443N/A
6443N/A <para>With the <command>ldapmodify</command> command, authorized users
6443N/A can delete entries from the directory.</para>
6443N/A
6443N/A <example xml:id="delete-subtree">
6443N/A <title>Delete: Removing a Subtree</title>
6443N/A
6443N/A <para>The following example uses the subtree delete option to remove
6443N/A all Special Users from the directory.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>ldapdelete \
7097N/A --port 1389 \
7097N/A --bindDN "cn=Directory Manager" \
7097N/A --bindPassword password \
7097N/A --deleteSubtree "ou=Special Users,dc=example,dc=com"</userinput>
7097N/A<computeroutput>Processing DELETE request for ou=Special Users,dc=example,dc=com
7097N/ADELETE operation successful for DN ou=Special Users,dc=example,dc=com</computeroutput>
7097N/A </screen>
6443N/A </example>
6443N/A </section>
6443N/A </section>
6443N/A
6443N/A <section xml:id="change-password">
6443N/A <title>Changing Passwords</title>
6443N/A <indexterm><primary>Passwords</primary><secondary>Changing</secondary></indexterm>
6443N/A
6443N/A <para>With the <command>ldappasswordmodify</command> command, authorized
6443N/A users can change and reset user passwords.</para>
6443N/A
6443N/A <example xml:id="password-reset">
6443N/A <title>Password Reset</title>
6443N/A <indexterm>
6443N/A <primary>Resetting passwords</primary>
6443N/A </indexterm>
6443N/A
6443N/A <para>The following example shows Kirsten Vaughan resetting Sam Carter's
6443N/A password. Kirsten has the appropriate privilege to reset Sam's
6443N/A password.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>ldappasswordmodify \
7097N/A --useStartTLS \
7097N/A --port 1389 \
7097N/A --bindDN "uid=kvaughan,ou=people,dc=example,dc=com" \
7097N/A --bindPassword bribery \
7097N/A --authzID "dn:uid=scarter,ou=people,dc=example,dc=com" \
7097N/A --newPassword ChangeMe</userinput>
7097N/A<computeroutput>The LDAP password modify operation was successful</computeroutput>
7097N/A </screen>
6443N/A
6443N/A <tip>
7082N/A <para>
7082N/A The <command>ldappasswordmodify</command> command uses
7082N/A the LDAP Password Modify extended operation.
7082N/A If this extended operation is performed on a connection
7082N/A that is already associated with a user
7082N/A &#8212;in other words, when a user first does a bind on the connection,
7082N/A and then requests the LDAP Password Modify extended operation&#8212;
7082N/A then the operation is performed as the user associated with the connection.
7082N/A If the user associated with the connection
7082N/A is not the user whose password is being changed,
7082N/A then OpenDJ considers it a password reset.
7082N/A </para>
7082N/A
7082N/A <para>
7082N/A Whenever one user changes another user's password,
7082N/A OpenDJ considers it a password reset.
7082N/A Often password policies specify that users
7082N/A must change their passwords again after a password reset.
7082N/A </para>
7082N/A
7082N/A <para>
7082N/A If you want your application to change a user's password,
7082N/A rather than reset a user's password,
7082N/A have your application request the password change
7082N/A as the user whose password is changing.
7082N/A </para>
7082N/A
7082N/A <para>
7082N/A To change the password as the user, you can
7082N/A bind as the user whose password should be changed,
7082N/A use the LDAP Password Modify extended operation
7082N/A with an authorization ID but without performing a bind,
7082N/A or use proxied authorization.
7082N/A For instructions on using proxied authorization, see the section on
7097N/A <link
7097N/A xlink:show="new"
7097N/A xlink:href="admin-guide#proxied-authz"
7097N/A xlink:role="http://docbook.org/xlink/role/olink"
7082N/A ><citetitle>Configuring Proxied Authorization</citetitle></link>.
7082N/A </para>
6443N/A </tip>
6443N/A
6443N/A <para>You could also accomplish password reset with the following command,
6443N/A but <command>set-password-is-reset</command> is a hidden option, supported
6443N/A only for testing.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>manage-account \
7097N/A set-password-is-reset \
7097N/A --bindDN "cn=Directory Manager" \
7097N/A --bindPassword password \
7097N/A --targetDN uid=scarter,ou=people,dc=example,dc=com \
7097N/A --operationValue true</userinput>
7097N/A<computeroutput>Password Is Reset: true</computeroutput></screen>
6443N/A </example>
6443N/A
6443N/A <example xml:id="change-own-password">
6443N/A <title>Change Own Password</title>
6443N/A
6443N/A <para>You can use the <command>ldappasswordmodify</command> command to
6443N/A change your password, as long as you know your current password.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>ldappasswordmodify \
7097N/A --port 1389 \
7097N/A --authzID "dn:uid=bjensen,ou=people,dc=example,dc=com" \
7097N/A --currentPassword hifalutin \
7097N/A --newPassword secret12</userinput>
7097N/A<computeroutput>The LDAP password modify operation was successful</computeroutput>
7097N/A </screen>
6443N/A
6443N/A <para>The same operation works for <literal>cn=Directory
6443N/A Manager</literal>.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>ldappasswordmodify \
7097N/A --port 1389 \
7097N/A --authzID "dn:cn=Directory Manager" \
7097N/A --currentPassword password \
7097N/A --newPassword secret12</userinput>
7097N/A<computeroutput>The LDAP password modify operation was successful</computeroutput>
7097N/A </screen>
6443N/A </example>
6443N/A
6443N/A <example xml:id="non-ascii-password">
6443N/A <title>Passwords With Special Characters</title>
6443N/A
6443N/A <para>OpenDJ expects passwords to be UTF-8 encoded (base64 encoded when
6443N/A included in LDIF).</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>echo $LANG</userinput>
7097N/A<computeroutput>en_US.utf8</computeroutput>
7097N/A
7097N/A$ <userinput>ldappasswordmodify \
7097N/A --port 1389 \
7097N/A --bindDN uid=bjensen,ou=People,dc=example,dc=com \
7097N/A --bindPassword hifalutin \
7097N/A --currentPassword hifalutin \
7097N/A --newPassword pàsswȏrd</userinput>
7097N/A<computeroutput>The LDAP password modify operation was successful</computeroutput>
7097N/A
7097N/A$ <userinput>ldapsearch \
7097N/A --port 1389 \
7097N/A --bindDN uid=bjensen,ou=People,dc=example,dc=com \
7097N/A --bindPassword pàsswȏrd \
7097N/A --baseDN dc=example,dc=com \
7097N/A "(uid=bjensen)" cn</userinput>
7097N/A<computeroutput>dn: uid=bjensen,ou=People,dc=example,dc=com
6443N/AuserPassword: {SSHA}k0eEeCxj9YRXUp8yJn0Z/mwqe+wrcFb1N1gg2g==
6443N/Acn: Barbara Jensen
7097N/Acn: Babs Jensen</computeroutput>
7097N/A </screen>
6443N/A </example>
6443N/A </section>
6443N/A
6443N/A <section xml:id="tools-properties">
6443N/A <title>Configuring Default Settings</title>
6443N/A <indexterm><primary>Ports</primary><secondary>Settings for tools</secondary></indexterm>
6443N/A <para>You can use <filename>~/.opendj/tools.properties</filename> to set
6443N/A the defaults for bind DN, host name, and port number as in the following
6443N/A example.</para>
6443N/A <programlisting language="ini">hostname=directory.example.com
6443N/Aport=1389
6443N/AbindDN=uid=kvaughan,ou=People,dc=example,dc=com
6443N/A
6443N/Aldapcompare.port=1389
6443N/Aldapdelete.port=1389
6443N/Aldapmodify.port=1389
6443N/Aldappasswordmodify.port=1389
6443N/Aldapsearch.port=1389</programlisting>
6443N/A <para>The location on Windows is
6443N/A <filename>%UserProfile%/.opendj/tools.properties</filename>.</para>
6443N/A </section>
6443N/A
6443N/A <section xml:id="client-auth">
6443N/A <title>Authenticating To the Directory Server</title>
6443N/A <indexterm><primary>Authenticating</primary></indexterm>
6443N/A
6443N/A <para>Authentication is the act of confirming the identity of a principal.
6443N/A Authorization is the act of determining whether to grant or to deny access to
6443N/A a principal. Authentication is done to make authorization decisions.</para>
6443N/A
6443N/A <para>As explained in <link xlink:href="admin-guide#chap-privileges-acis"
6443N/A xlink:role="http://docbook.org/xlink/role/olink"><citetitle>Configuring
6443N/A Privileges &amp; Access Control</citetitle></link>, OpenDJ directory server
6443N/A implements fine-grained access control for authorization. What is authorized
6443N/A depends on who is requesting the operation. Directory servers like OpenDJ must
6443N/A first therefore authenticate the principals using the clients before they can
6443N/A authorize or deny access. The LDAP bind operation, where a directory client
6443N/A authenticates with the directory server, is therefore the first LDAP operation
6443N/A in every LDAP session.</para>
6443N/A
6443N/A <para>Clients bind by providing both a means to find their principal's entry
6443N/A in the directory and also providing some credentials that the directory server
6443N/A can check against their entry.</para>
6443N/A
6443N/A <para>In the simplest bind operation, the client provides a zero-length
6443N/A name and a zero-length password. This results in an anonymous bind, meaning
6443N/A the client is authenticated as an anonymous user of the directory. In the
6443N/A simplest examples in <xref linkend="search-ldap" />, notice that no
6443N/A authentication information is provided. The examples work because the
6443N/A client commands default to requesting anonymous binds when you provide no
6443N/A credentials, and because access controls for the sample data allow anonymous
6443N/A clients to read, search, and compare some directory data.</para>
6443N/A
6443N/A <para>In a simple bind operation, the client provides an LDAP name, such as
6443N/A the DN identifying its entry, and the corresponding password stored on the
6443N/A <literal>userPassword</literal> attribute of the entry. In
6443N/A <xref linkend="write-ldap" />, notice that to change directory data the
6443N/A client provides the bind DN and bind password of a user who has permission
6443N/A to change directory data. The commands do not work with a bind DN and bind
6443N/A password because access controls for the sample data only allow authorized
6443N/A users to change directory data.</para>
6443N/A
6443N/A <para>Users rarely provide client applications with DNs, however. Instead
6443N/A users might provide a client application with an identity string like a user
6443N/A ID or an email address for example. Depending on how the DNs are constructed,
6443N/A the client application can either build the DN directly from the user's
6443N/A identity string, or use a session where the bind has been done with some
6443N/A other identity to search for the user entry based on the user's identity
6443N/A string. Given the DN constructed or found, the client application can then
6443N/A perform a simple bind.</para>
6443N/A
6443N/A <para>For example, suppose Babs Jensen enters her email address,
6443N/A <literal>bjensen@example.com</literal>, and her password in order to log in.
6443N/A The client application might search for the entry matching
6443N/A <literal>(mail=bjensen@example.com)</literal> under base DN
6443N/A <literal>dc=example,dc=com</literal>. Alternatively, the client application
6443N/A might know to extract the user ID <literal>bjensen</literal> from the address,
6443N/A and then build the corresponding DN,
6443N/A <literal>uid=bjensen,ou=people,dc=example,dc=com</literal> in order to
6443N/A bind.</para>
6443N/A
6443N/A <indexterm><primary>Identity mappers</primary></indexterm>
6443N/A <para>When an identifier string provided by the user can readily be mapped to
6443N/A the user's entry DN, OpenDJ directory server can do the translation between
6443N/A the identifier string and the entry DN. This translation is the job of a
6443N/A component called an identity mapper. Identity mappers are used to perform
6443N/A PLAIN SASL authentication (with a user name and password), SASL GSSAPI
6443N/A authentication (Kerberos V5), SASL CRAM MD5 and DIGEST MD5 authentication.
6443N/A They also handle authorization IDs during password modify extended operations
6443N/A and proxied authorization.</para>
6443N/A
6443N/A <para>One use of PLAIN SASL is to translate user names from HTTP Basic
6443N/A authentication to LDAP authentication. The following example shows PLAIN SASL
6443N/A authentication using the default Exact Match identity mapper. In this
6443N/A (contrived) example, Babs Jensen reads the hashed value of her password.
6443N/A (According to the access controls in the example data, Babs must authenticate
6443N/A to read her password.) Notice the authentication ID is her user ID,
6443N/A <literal>u:bjensen</literal>, rather than the DN of her entry.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>ldapsearch \
7097N/A --port 1389 \
7097N/A --useStartTLS \
7097N/A --baseDN dc=example,dc=com \
7097N/A --saslOption mech=PLAIN \
7097N/A --saslOption authid=u:bjensen \
7097N/A --bindPassword hifalutin \
7097N/A "(cn=Babs Jensen)" cn userPassword</userinput>
7097N/A<computeroutput>dn: uid=bjensen,ou=People,dc=example,dc=com
6443N/Acn: Barbara Jensen
6443N/Acn: Babs Jensen
7097N/AuserPassword: {SSHA}7S4Si+vPE513cYQ7otiqb8hjiCzU7XNTv0RPBA==</computeroutput>
7097N/A </screen>
6443N/A
6443N/A <para>The Exact Match identity mapper searches for a match between the string
6443N/A provided (here, <literal>bjensen</literal>) and the value of a specified
6443N/A attribute (by default the <literal>uid</literal> attribute). If
6443N/A you know users are entering their email addresses, you could create an
6443N/A exact match identity mapper for email addresses, and then use that for PLAIN
6443N/A SASL authentication as in the following example.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>dsconfig \
7097N/A create-identity-mapper \
7097N/A --hostname opendj.example.com \
7097N/A --port 4444 \
7097N/A --bindDN "cn=Directory Manager" \
7097N/A --bindPassword password \
7097N/A --mapper-name "Email Mapper" \
7097N/A --type exact-match \
7097N/A --set match-attribute:mail \
7097N/A --set enabled:true \
7097N/A --no-prompt</userinput>
7097N/A
7097N/A$ <userinput>dsconfig \
7097N/A set-sasl-mechanism-handler-prop \
7097N/A --hostname opendj.example.com \
7097N/A --port 4444 \
7097N/A --bindDN "cn=Directory Manager" \
7097N/A --bindPassword password \
7097N/A --handler-name PLAIN \
7097N/A --set identity-mapper:"Email Mapper" \
7097N/A --no-prompt</userinput>
7097N/A
7097N/A$ <userinput>ldapsearch \
7097N/A --port 1389 \
7097N/A --useStartTLS \
7097N/A --baseDN dc=example,dc=com \
7097N/A --saslOption mech=PLAIN \
7097N/A --saslOption authid=u:bjensen@example.com \
7097N/A --bindPassword hifalutin \
7097N/A "(cn=Babs Jensen)" cn userPassword</userinput>
7097N/A<computeroutput>dn: uid=bjensen,ou=People,dc=example,dc=com
6443N/Acn: Barbara Jensen
6443N/Acn: Babs Jensen
7097N/AuserPassword: {SSHA}7S4Si+vPE513cYQ7otiqb8hjiCzU7XNTv0RPBA==</computeroutput>
7097N/A </screen>
6443N/A
6443N/A <para>The Regular Expression identity mapper uses a regular expression to
6443N/A extract a substring from the string provided, and then searches for a match
6443N/A between the substring and the value of a specified attribute. In the case
6443N/A of example data where an email address is <replaceable>user ID</replaceable>
6443N/A + @ + <replaceable>domain</replaceable>, you can use the default Regular
6443N/A Expression identity mapper in the same way as the email mapper from the
6443N/A previous example. The default regular expression pattern is
6443N/A <literal>^([^@]+)@.+$</literal>, and the part of the identity string matching
6443N/A <literal>([^@]+)</literal> is used to find the entry by user ID.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>dsconfig \
7097N/A set-sasl-mechanism-handler-prop \
7097N/A --hostname opendj.example.com \
7097N/A --port 4444 \
7097N/A --bindDN "cn=Directory Manager" \
7097N/A --bindPassword password \
7097N/A --handler-name PLAIN \
7097N/A --set identity-mapper:"Regular Expression" \
7097N/A --no-prompt</userinput>
7097N/A
7097N/A$ <userinput>ldapsearch \
7097N/A --port 1389 \
7097N/A --useStartTLS \
7097N/A --baseDN dc=example,dc=com \
7097N/A --saslOption mech=PLAIN \
7097N/A --saslOption authid=u:bjensen@example.com \
7097N/A --bindPassword hifalutin \
7097N/A "(cn=Babs Jensen)" cn userPassword</userinput>
7097N/A<computeroutput>dn: uid=bjensen,ou=People,dc=example,dc=com
6443N/Acn: Barbara Jensen
6443N/Acn: Babs Jensen
7097N/AuserPassword: {SSHA}7S4Si+vPE513cYQ7otiqb8hjiCzU7XNTv0RPBA==</computeroutput>
7097N/A </screen>
6443N/A
6443N/A <para>Try the <command>dsconfig</command> command interactively to experiment
6443N/A with <literal>match-pattern</literal> and <literal>replace-pattern</literal>
6443N/A settings for the Regular Expression identity mapper. The
6443N/A <literal>match-pattern</literal> can be any regular expression supported by
6443N/A <literal>javax.util.regex.Pattern</literal>.</para>
6443N/A </section>
6443N/A
6443N/A <section xml:id="proxied-authz">
6443N/A <title>Configuring Proxied Authorization</title>
6443N/A <indexterm><primary>Proxied authorization</primary></indexterm>
6443N/A <para>Proxied authorization provides a standard control as defined in <link
6443N/A xlink:href='http://tools.ietf.org/html/rfc4370'>RFC 4370</link> (and an
6443N/A earlier Internet-Draft) for binding with the user credentials of a proxy, who
6443N/A carries out LDAP operations on behalf of other users. You might use proxied
6443N/A authorization, for example, to have your application bind with its
6443N/A credentials, and then carry out operations as the users who login to the
6443N/A application.</para>
6443N/A
6443N/A <para>Suppose you have an administrative directory client application that
6443N/A has an entry in the directory with DN
6443N/A <literal>cn=My App,ou=Apps,dc=example,dc=com</literal>. You can give that
6443N/A application the access rights and privileges to use proxied authorization.
6443N/A The default access control for OpenDJ permits authenticated users to use
6443N/A the proxied authorization control.</para>
6443N/A
6443N/A <para>Suppose also that when directory administrator, Kirsten Vaughan, logs
6443N/A in to your application to change Babs Jensen's entry, your application looks
6443N/A up Kirsten's entry, and finds that she has DN
6443N/A <literal>uid=kvaughan,ou=People,dc=example,dc=com</literal>. For the example
6443N/A commands in the following procedure. My App uses proxied authorization to
6443N/A make a change to Babs's entry as Kirsten.</para>
6443N/A
6443N/A <procedure xml:id="setup-proxied-authz">
6443N/A <title>To Set Up Proxied Authorization</title>
6443N/A <step>
6443N/A <para>Grant access to applications that can use proxied authorization.</para>
7097N/A
7097N/A <screen>
7097N/A$ <userinput>ldapmodify \
7097N/A --port 1389 \
7097N/A --bindDN "cn=Directory Manager" \
6443N/A --bindPassword password
6443N/Adn: dc=example,dc=com
6443N/Achangetype: modify
6443N/Aadd: aci
6443N/Aaci: (target="ldap:///dc=example,dc=com") (targetattr ="*
6443N/A ")(version 3.0; acl "Allow apps proxied auth"; allow(all, proxy
7097N/A )(userdn = "ldap:///cn=*,ou=Apps,dc=example,dc=com");)</userinput>
6443N/A
7097N/A<computeroutput>Processing MODIFY request for dc=example,dc=com
7097N/AMODIFY operation successful for DN dc=example,dc=com</computeroutput>
7097N/A </screen>
6443N/A </step>
7097N/A
6443N/A <step>
6443N/A <para>Grant the privilege to use proxied authorization to My App.</para>
7097N/A
7097N/A <screen>
7097N/A$ <userinput>ldapmodify \
7097N/A --port 1389 \
7097N/A --bindDN "cn=Directory Manager" \
6443N/A --bindPassword password
6443N/Adn: cn=My App,ou=Apps,dc=example,dc=com
6443N/Achangetype: modify
6443N/Aadd: ds-privilege-name
7097N/Ads-privilege-name: proxied-auth</userinput>
6443N/A
7097N/A<computeroutput>Processing MODIFY request for cn=My App,ou=Apps,dc=example,dc=com
7097N/AMODIFY operation successful for DN cn=My App,ou=Apps,dc=example,dc=com</computeroutput>
7097N/A </screen>
6443N/A </step>
7097N/A
6443N/A <step>
6443N/A <para>Test that My App can use proxied authorization.</para>
7097N/A
7097N/A <screen>
7097N/A$ <userinput>ldapmodify \
7097N/A --port 1389 \
7097N/A --bindDN "cn=My App,ou=Apps,dc=example,dc=com" \
7097N/A --bindPassword password \
6443N/A --proxyAs "dn:uid=kvaughan,ou=People,dc=example,dc=com"
6443N/Adn: uid=bjensen,ou=People,dc=example,dc=com
6443N/Achangetype: modify
6443N/Areplace: description
7097N/Adescription: Changed through proxied auth</userinput>
6443N/A
7097N/A<computeroutput>Processing MODIFY request for uid=bjensen,ou=People,dc=example,dc=com
7097N/AMODIFY operation successful for DN uid=bjensen,ou=People,dc=example,dc=com</computeroutput>
7097N/A </screen>
6443N/A </step>
6443N/A </procedure>
6443N/A
6443N/A <para>If you need to map authorization identifiers using the
6443N/A <literal>u:</literal> form rather than using <literal>dn:</literal>, you can
6443N/A set the identity mapper with the global configuration setting,
6443N/A <literal>proxied-authorization-identity-mapper</literal>. For example, if you
6443N/A get user ID values from the client, such as <literal>bjensen</literal>, you
6443N/A can use the Exact Match Identity Mapper to match those to DNs based on an
6443N/A attribute of the entry. Use the <command>dsconfig</command> command
6443N/A interactively to investigate the settings you need.</para>
6443N/A </section>
6443N/A
6443N/A <section xml:id="client-cert-auth">
6443N/A <title>Authenticating Using a Certificate</title>
6443N/A <indexterm><primary>Certificates</primary></indexterm>
6443N/A <indexterm><primary>StartTLS</primary></indexterm>
6443N/A <indexterm><primary>SSL</primary></indexterm>
6443N/A
6443N/A <para>One alternative to simple binds with user name/password combinations
6443N/A consists in storing a digital certificate on the user entry, and then using
6443N/A the certificate as credentials during the bind. You can use this mechanism for
6443N/A example to let applications bind without using passwords.</para>
6443N/A
6443N/A <para>Simply by setting up a secure connection with a certificate, the client
6443N/A is in effect authenticating to the server. The server must close the
6443N/A connection if it cannot trust the client certificate. However, the process
6443N/A of establishing a secure connection does not in itself identify the client
6443N/A to OpenDJ directory server.</para>
6443N/A
6443N/A <para>Instead when binding with a certificate, the client must request the
6443N/A SASL External mechanism by which OpenDJ directory server maps the certificate
6443N/A to the client entry in the directory. When it finds a match, OpenDJ sets the
6443N/A authorization identity for the connection to that of the client, and the bind
6443N/A is successful.</para>
6443N/A
6443N/A <para>For the whole process of authenticating with a certificate to work
6443N/A smoothly, OpenDJ and the client must trust each others' certificates, the
6443N/A client certificate must be stored on the client entry in the directory, and
6443N/A OpenDJ must be configured to map the certificate to the client entry.</para>
6443N/A
7107N/A <itemizedlist>
7107N/A <para>
7107N/A This section includes the following procedures and examples.
7107N/A </para>
7107N/A
7107N/A <listitem>
7107N/A <para>
7107N/A <xref linkend="add-client-cert" />
7107N/A </para>
7107N/A </listitem>
7107N/A
7107N/A <listitem>
7107N/A <para>
7107N/A <xref linkend="use-pkcs12-trust-store" />
7107N/A </para>
7107N/A </listitem>
7107N/A
7107N/A <listitem>
7107N/A <para>
7107N/A <xref linkend="config-cert-mappers" />
7107N/A </para>
7107N/A </listitem>
7107N/A
7107N/A <listitem>
7107N/A <para>
7107N/A <xref linkend="auth-with-client-cert" />
7107N/A </para>
7107N/A </listitem>
7107N/A </itemizedlist>
7107N/A
6443N/A <procedure xml:id="add-client-cert">
6443N/A <title>To Add Certificate Information to an Entry</title>
6443N/A
6443N/A <para>Before trying to bind to OpenDJ directory server using a certificate,
6443N/A create a certificate, and then add the certificate attributes to the
6443N/A entry.</para>
6443N/A
6443N/A <para><link xlink:href="http://opendj.forgerock.org/Example.ldif"
6443N/A xlink:show="new">Example.ldif</link> includes an entry for
6443N/A <literal>cn=My App,ou=Apps,dc=example,dc=com</literal>. Examples in this
6443N/A section use that entry, and use the Java <command>keytool</command> command
6443N/A to manage the certificate.</para>
6443N/A
6443N/A <step>
6443N/A <para>Create a certificate using the DN of the client entry as the
6443N/A distinguished name string.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>keytool \
7097N/A -genkey \
7097N/A -alias myapp-cert \
7097N/A -keyalg rsa \
7097N/A -dname "cn=My App,ou=Apps,dc=example,dc=com" \
7097N/A -keystore keystore \
7097N/A -storepass changeit \
7097N/A -keypass changeit</userinput>
7097N/A </screen>
6443N/A </step>
6443N/A
6443N/A <step>
6443N/A <para>Get the certificate signed.</para>
6443N/A
6443N/A <para>If you cannot get the certificate signed by a Certificate Authority,
6443N/A self-sign the certificate.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>keytool \
7097N/A -selfcert \
7097N/A -alias myapp-cert \
7097N/A -validity 7300 \
7097N/A -keystore keystore \
7097N/A -storepass changeit \
7097N/A -keypass changeit</userinput>
7097N/A </screen>
6443N/A </step>
6443N/A
6443N/A <step>
6443N/A <para>Make note of the certificate fingerprints.</para>
6443N/A
6443N/A <para>Later in this procedure you update the client application entry with
6443N/A the MD5 fingerprint, which in this example is
6443N/A <literal>48:AC:F9:13:11:E0:AB:C4:65:A2:83:9E:DB:FE:0C:37</literal>.</para>
7097N/A
7097N/A <screen>
7097N/A$ <userinput>keytool \
7097N/A -list \
7097N/A -v \
7097N/A -alias myapp-cert \
7097N/A -keystore keystore \
7097N/A -storepass changeit</userinput>
7097N/A<computeroutput>Alias name: myapp-cert
6443N/ACreation date: Jan 18, 2013
6443N/AEntry type: PrivateKeyEntry
6443N/ACertificate chain length: 1
6443N/ACertificate[1]:
6443N/AOwner: CN=My App, OU=Apps, DC=example, DC=com
6443N/AIssuer: CN=My App, OU=Apps, DC=example, DC=com
6443N/ASerial number: 5ae2277
6443N/AValid from: Fri Jan 18 18:27:09 CET 2013 until: Thu Jan 13 18:27:09 CET 2033
6443N/ACertificate fingerprints:
7097N/A MD5: 48:AC:F9:13:11:E0:AB:C4:65:A2:83:9E:DB:FE:0C:37
7097N/A SHA1: F9:61:54:37:AA:C1:BC:92:45:07:64:4B:23:6C:BC:C9:CD:1D:44:0F
7097N/A SHA256: 2D:B1:58:CD:33:40:E9:...:FD:61:EA:C9:FF:6A:19:93:FE:E4:84:E3
7097N/A Signature algorithm name: SHA256withRSA
7097N/A Version: 3
6443N/A
6443N/AExtensions:
6443N/A
6443N/A#1: ObjectId: 2.5.29.14 Criticality=false
6443N/ASubjectKeyIdentifier [
6443N/AKeyIdentifier [
6443N/A0000: 54 C0 C5 9C 73 37 85 4B F2 3B D3 37 FD 45 0A AB T...s7.K.;.7.E..
6443N/A0010: C9 6B 32 95 .k2.
6443N/A]
7097N/A]</computeroutput>
7097N/A </screen>
6443N/A </step>
6443N/A
6443N/A <step>
6443N/A <para>Export the certificate to a file in binary format.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>keytool \
7097N/A -export \
7097N/A -alias myapp-cert \
7097N/A -keystore keystore \
7097N/A -storepass changeit \
7097N/A -keypass changeit \
7097N/A -file myapp-cert.crt</userinput>
7097N/A<computeroutput>Certificate stored in file &lt;/path/to/myapp-cert.crt&gt;</computeroutput>
7097N/A </screen>
6443N/A </step>
6443N/A
6443N/A <step>
6443N/A <para>Modify the entry to add attributes related to the certificate.</para>
6443N/A
6443N/A <para>By default, you need the <literal>userCertificate</literal>
6443N/A value.</para>
6443N/A
6443N/A <para>If you want OpenDJ to map the certificate to its fingerprint, use
6443N/A <literal>ds-certificate-fingerprint</literal>. This example uses the MD5
6443N/A fingerprint, which corresponds to the default setting for the Fingerprint
6443N/A Certificate Mapper.</para>
6443N/A
6443N/A <para>If you want to map the certificate subject DN to an attribute of the
6443N/A entry, use <literal>ds-certificate-subject-dn</literal>.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>cat addcert.ldif</userinput>
7097N/A<computeroutput>dn: cn=My App,ou=Apps,dc=example,dc=com
6443N/Achangetype: modify
6443N/Aadd: objectclass
6443N/Aobjectclass: ds-certificate-user
6443N/A-
6443N/Aadd: ds-certificate-fingerprint
6443N/Ads-certificate-fingerprint: 48:AC:F9:13:11:E0:AB:C4:65:A2:83:9E:DB:FE:0C:37
6443N/A-
6443N/Aadd: ds-certificate-subject-dn
6443N/Ads-certificate-subject-dn: CN=My App, OU=Apps, DC=example, DC=com
6443N/A-
6443N/Aadd: userCertificate;binary
7097N/AuserCertificate;binary:&lt;file:///path/to/myapp-cert.crt</computeroutput>
6443N/A
7097N/A$ <userinput>ldapmodify \
7097N/A --port 1389 \
7097N/A --hostname opendj.example.com \
7097N/A --bindDN "cn=Directory Manager" \
7097N/A --bindPassword password \
7097N/A --filename addcert.ldif</userinput>
7097N/A<computeroutput>Processing MODIFY request for cn=My App,ou=Apps,dc=example,dc=com
7097N/AMODIFY operation successful for DN cn=My App,ou=Apps,dc=example,dc=com</computeroutput>
7097N/A </screen>
6443N/A </step>
6443N/A
6443N/A <step>
6443N/A <para>Check your work.</para>
6443N/A
7097N/A <screen>
7106N/A$ <userinput>ldapsearch \
7106N/A --port 1389 \
7106N/A --hostname opendj.example.com \
7106N/A --baseDN dc=example,dc=com \
7097N/A "(cn=My App)"</userinput>
7097N/A<computeroutput>dn: cn=My App,ou=Apps,dc=example,dc=com
6443N/Ads-certificate-fingerprint: 4B:F5:CF:2C:2D:B3:86:14:FF:43:A8:37:17:DD:E7:55
6443N/AuserCertificate;binary:: MIIDOzCCAiOgAwIBAgIESfC6IjANBgkqhkiG9w0BAQsFADBOMRMwEQY
6443N/A KCZImiZPyLGQBGRYDY29tMRcwFQYKCZImiZPyLGQBGRYHZXhhbXBsZTENMAsGA1UECxMEQXBwczEPMA
6443N/A 0GA1UEAxMGTXkgQXBwMB4XDTEzMDExNzE3MTEwM1oXDTEzMDQxNzE3MTEwM1owTjETMBEGCgmSJomT8
6443N/A ixkARkWA2NvbTEXMBUGCgmSJomT8ixkARkWB2V4YW1wbGUxDTALBgNVBAsTBEFwcHMxDzANBgNVBAMT
6443N/A Bk15IEFwcDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJQYq+jG4ZQdNkyBT4OQBZ0sFkl
6443N/A X5o2yBViDMGl1sSWIRGLpFwu6iq1chndPBJYTC+FkT66yEEOwWOpSfcYdFHkMQP0qp5A8mgP6bYkeH1
6443N/A ROvQ1nhLs0ILuksR10CVIQ5b1zv6bGEFhA9gSKmpHfQOSt9PXq8+kuz+4RgZk9Il28tgDNMm91wSJr7
6443N/A kqi5g7a2a7Io5s9L2FeLhVSBYwinWQnASk8nENrhcE0hHkrpGsaxdhIQBQQvm+SRC0dI4E9iwBGI3Lw
6443N/A lV3a4KTa5DlYD6cDREI6B8XlSdc1DaIhwC8CbsE0WJQoCERSURdjkuHrPck6f69HKUFRiC7JMT3dFbs
6443N/A CAwEAAaMhMB8wHQYDVR0OBBYEFFTAxZxzN4VL8jvTN/1FCqvJazKVMA0GCSqGSIb3DQEBCwUAA4IBAQ
6443N/A BXsAIEw7I5XUzLFHvXb2N0hmW/Vmhb/Vlv9LTT8JcCRJy4zaiyS9Q+Sp9zQUkrXauFnNAhJLwpAymjZ
6443N/A MCOq1Th1bw9LnIzbccPQ/1+ZHLKDU5pgnc5BcvaV6Zl6COLLH2OOt0XMZ/OrODBV1M6STfhChqcowff
6443N/A xp72pWMQe+kpZfzjeDBk4kK2hUNTZsimB9qRyrDAMCIXdmdmFv1o07orxjy8c/6S1329swiiVqFckBR
6443N/A aXIa8wCcXjpQbZacDODeKk6wZIKxw4miLg1YByCMa7vkUfz+Jj+JHgbHjyoT/G82mtDbX02chLgXbDm
6443N/A xJPFN3mwAC7NEkSPbqd35nJlf3
6443N/AobjectClass: person
6443N/AobjectClass: inetOrgPerson
6443N/AobjectClass: organizationalPerson
6443N/AobjectClass: ds-certificate-user
6443N/AobjectClass: top
6443N/Ads-certificate-subject-dn: CN=My App, OU=Apps, DC=example, DC=com
6443N/Acn: My App
7097N/Asn: App</computeroutput>
7097N/A </screen>
6443N/A </step>
6443N/A
6443N/A <step>
6443N/A <para>When using a self-signed certificate, import the client certificate
6443N/A into the trust store for OpenDJ.</para>
6443N/A
6443N/A <para>When the client presents its certificate to OpenDJ, by default OpenDJ
6443N/A has to be able to trust the client certificate before it can accept the
6443N/A connection. If OpenDJ cannot trust the client certificate, it cannot
6443N/A establish a secure connection.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>keytool \
7097N/A -import \
7097N/A -alias myapp-cert \
7097N/A -file /path/to/myapp-cert.crt \
7097N/A -keystore /path/to/opendj/config/truststore \
7097N/A -storepass `cat /path/to/opendj/config/keystore.pin`</userinput>
7097N/A<computeroutput>Owner: CN=My App, OU=Apps, DC=example, DC=com
6443N/AIssuer: CN=My App, OU=Apps, DC=example, DC=com
6443N/ASerial number: 5ae2277
6443N/AValid from: Fri Jan 18 18:27:09 CET 2013 until: Thu Jan 13 18:27:09 CET 2033
6443N/ACertificate fingerprints:
7097N/A MD5: 48:AC:F9:13:11:E0:AB:C4:65:A2:83:9E:DB:FE:0C:37
7097N/A SHA1: F9:61:54:37:AA:C1:BC:92:45:07:64:4B:23:6C:BC:C9:CD:1D:44:0F
7097N/A SHA256: 2D:B1:58:CD:33:40:E9:...:FD:61:EA:C9:FF:6A:19:93:FE:E4:84:E3
7097N/A Signature algorithm name: SHA256withRSA
7097N/A Version: 3
6443N/A
6443N/AExtensions:
6443N/A
6443N/A#1: ObjectId: 2.5.29.14 Criticality=false
6443N/ASubjectKeyIdentifier [
6443N/AKeyIdentifier [
6443N/A0000: 54 C0 C5 9C 73 37 85 4B F2 3B D3 37 FD 45 0A AB T...s7.K.;.7.E..
6443N/A0010: C9 6B 32 95 .k2.
6443N/A]
6443N/A]
6443N/A
7097N/ATrust this certificate? [no]:</computeroutput> <userinput>yes</userinput>
7097N/A<computeroutput>Certificate was added to keystore</computeroutput>
7097N/A </screen>
6443N/A </step>
6443N/A
6443N/A <step>
6443N/A <para>When using a certificate signed by a CA whose certificate is not
6443N/A delivered with the Java runtime environment<footnote>
6443N/A <para><filename>$JAVA_HOME/jre/lib/security/cacerts</filename> holds the
6443N/A certificates for many CAs. To get the full list, use the following
6443N/A command.</para>
7097N/A
7097N/A <screen>
7097N/A$ <userinput>keytool \
7097N/A -list \
7097N/A -v \
7097N/A -keystore $JAVA_HOME/jre/lib/security/cacerts \
7097N/A -storepass changeit</userinput>
7097N/A </screen></footnote>, import the CA certificate either
6443N/A into the Java runtime environment trust store, or into the OpenDJ trust
6443N/A store as shown in the following example.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>keytool \
7097N/A -import \
7097N/A -alias ca-cert \
7097N/A -file ca.crt \
7097N/A -keystore /path/to/opendj/config/truststore \
7097N/A -storepass `cat /path/to/opendj/config/keystore.pin`</userinput>
7097N/A<computeroutput>Owner: EMAILADDRESS=admin@example.com, CN=Example CA, O=Example Corp, C=FR
6443N/AIssuer: EMAILADDRESS=admin@example.com, CN=Example CA, O=Example Corp, C=FR
6443N/ASerial number: d4586ea05c878b0c
6443N/AValid from: Tue Jan 29 09:30:31 CET 2013 until: Mon Jan 24 09:30:31 CET 2033
6443N/ACertificate fingerprints:
7097N/A MD5: 8A:83:61:9B:E7:18:A2:21:CE:92:94:96:59:68:60:FA
7097N/A SHA1: 01:99:18:38:3A:57:D7:92:7B:D6:03:8C:7B:E4:1D:37:45:0E:29:DA
7097N/A SHA256: 5D:20:F1:86:CC:CD:64:50:1E:54:...:DF:15:43:07:69:44:00:FB:36:CF
7097N/A Signature algorithm name: SHA1withRSA
7097N/A Version: 3
6443N/A
6443N/AExtensions:
6443N/A
6443N/A#1: ObjectId: 2.5.29.35 Criticality=false
6443N/AAuthorityKeyIdentifier [
6443N/AKeyIdentifier [
6443N/A0000: 30 07 67 7D 1F 09 B6 E6 90 85 95 58 94 37 FD 31 0.g........X.7.1
6443N/A0010: 03 D4 56 7B ..V.
6443N/A]
6443N/A[EMAILADDRESS=admin@example.com, CN=Example CA, O=Example Corp, C=FR]
6443N/ASerialNumber: [ d4586ea0 5c878b0c]
6443N/A]
6443N/A
6443N/A#2: ObjectId: 2.5.29.19 Criticality=false
6443N/ABasicConstraints:[
6443N/A CA:true
6443N/A PathLen:2147483647
6443N/A]
6443N/A
6443N/A#3: ObjectId: 2.5.29.14 Criticality=false
6443N/ASubjectKeyIdentifier [
6443N/AKeyIdentifier [
6443N/A0000: 30 07 67 7D 1F 09 B6 E6 90 85 95 58 94 37 FD 31 0.g........X.7.1
6443N/A0010: 03 D4 56 7B ..V.
6443N/A]
6443N/A]
6443N/A
7097N/ATrust this certificate? [no]:</computeroutput> <userinput>yes</userinput>
7097N/A<computeroutput>Certificate was added to keystore</computeroutput>
7097N/A </screen>
6443N/A </step>
6443N/A
6443N/A <step>
6443N/A <para>If you updated the OpenDJ trust store to add a certificate, restart
6443N/A OpenDJ to make sure it reads the updated trust store and can recognize the
6443N/A certificate.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>stop-ds --restart</userinput>
7097N/A<computeroutput>Stopping Server...
6443N/A...
7097N/A... The Directory Server has started successfully</computeroutput>
7097N/A </screen>
6443N/A </step>
6443N/A </procedure>
6443N/A
7107N/A <procedure xml:id="use-pkcs12-trust-store">
7107N/A <title>To Use a PKCS #12 Trust Store</title>
7107N/A
7107N/A <para>
7107N/A The Java <command>keytool</command> command does not support
7107N/A importing trusted certificates into a PKCS #12 format store.
7107N/A Yet, Java does support
7107N/A creating a PKCS #12 format key store,
7107N/A and using an existing PKCS #12 format store as a trust store.
7107N/A You can use a PKCS #12 store as an OpenDJ trust store.
7107N/A </para>
7107N/A
7107N/A <!--
7107N/A
7107N/A The following example shows how to try the full procedure
7107N/A by using the keytool command with OpenDJ server and commands.
7107N/A
7107N/A Create key pair:
7107N/A
7107N/A$ cd /path/to
7107N/A$ keytool \
7107N/A -genkey \
7107N/A -alias myapp-cert \
7107N/A -keyalg rsa \
7107N/A -dname "cn=My App,ou=Apps,dc=example,dc=com" \
7107N/A -keystore truststore.p12 \
7107N/A -storepass changeit \
7107N/A -keypass changeit \
7107N/A -storetype pkcs12
7107N/A
7107N/A Sign certificate:
7107N/A
7107N/A$ keytool \
7107N/A -selfcert \
7107N/A -alias myapp-cert \
7107N/A -validity 7300 \
7107N/A -keystore truststore.p12 \
7107N/A -storepass changeit \
7107N/A -keypass changeit \
7107N/A -storetype pkcs12
7107N/A
7107N/A Note certificate fingerprints:
7107N/A
7107N/A$ keytool \
7107N/A -list \
7107N/A -v \
7107N/A -alias myapp-cert \
7107N/A -keystore truststore.p12 \
7107N/A -storepass changeit \
7107N/A -storetype pkcs12
7107N/AAlias name: myapp-cert
7107N/ACreation date: Apr 10, 2014
7107N/AEntry type: PrivateKeyEntry
7107N/ACertificate chain length: 1
7107N/ACertificate[1]:
7107N/AOwner: CN=My App, OU=Apps, DC=example, DC=com
7107N/AIssuer: CN=My App, OU=Apps, DC=example, DC=com
7107N/ASerial number: 1b93b494
7107N/AValid from: Thu Apr 10 08:25:01 CEST 2014 until: Wed Apr 05 08:25:01 CEST 2034
7107N/ACertificate fingerprints:
7107N/A MD5: 2B:8D:27:D6:1D:D1:A5:5F:14:E7:A8:C1:96:F9:C1:9F
7107N/A SHA1: 1D:A2:BF:A6:29:8C:13:81:A4:E5:77:9E:D5:67:CD:C8:E6:AD:6E:A3
7107N/A SHA256: 80:47:B8:5C:E7:22:BB:4E:5E:48:8B:84:38:9F:E8:2C:7C:87:6E:9C:20:A2:E2:5F:A7:7A:10:0E:C8:AE:60:85
7107N/A Signature algorithm name: SHA256withRSA
7107N/A Version: 3
7107N/A
7107N/AExtensions:
7107N/A
7107N/A#1: ObjectId: 2.5.29.14 Criticality=false
7107N/ASubjectKeyIdentifier [
7107N/AKeyIdentifier [
7107N/A0000: 93 C5 DE 6A 5D D4 84 99 38 A8 6D 9D BF B9 FF 5E ...j]...8.m....^
7107N/A0010: B5 05 F1 87 ....
7107N/A]
7107N/A]
7107N/A
7107N/A Export certificate:
7107N/A
7107N/A$ keytool \
7107N/A -export \
7107N/A -alias myapp-cert \
7107N/A -keystore truststore.p12 \
7107N/A -storepass changeit \
7107N/A -keypass changeit \
7107N/A -file myapp-cert.crt \
7107N/A -storetype pkcs12
7107N/ACertificate stored in file <myapp-cert.crt>
7107N/A
7107N/A Update My App entry with certificate:
7107N/A
7107N/A$ cat addcert.ldif
7107N/Adn: cn=My App,ou=Apps,dc=example,dc=com
7107N/Achangetype: modify
7107N/Aadd: objectclass
7107N/Aobjectclass: ds-certificate-user
7107N/A-
7107N/Aadd: ds-certificate-fingerprint
7107N/Ads-certificate-fingerprint: 2B:8D:27:D6:1D:D1:A5:5F:14:E7:A8:C1:96:F9:C1:9F
7107N/A-
7107N/Aadd: ds-certificate-subject-dn
7107N/Ads-certificate-subject-dn: CN=My App, OU=Apps, DC=example, DC=com
7107N/A-
7107N/Aadd: userCertificate;binary
7107N/AuserCertificate;binary:<file:///path/to/myapp-cert.crt
7107N/A
7107N/A XML comments cannot include two dashes in a row,
7107N/A so change - - in the following examples before trying these.
7107N/A
7107N/A$ cd opendj/bin
7107N/A$ ldapmodify \
7107N/A - -port 1389 \
7107N/A - -hostname opendj.example.com \
7107N/A - -bindDN "cn=Directory Manager" \
7107N/A - -bindPassword password \
7107N/A - -filename /path/to/addcert.ldif
7107N/AProcessing MODIFY request for cn=My App,ou=Apps,dc=example,dc=com
7107N/AMODIFY operation successful for DN cn=My App,ou=Apps,dc=example,dc=com
7107N/A
7107N/A$ ldapsearch \
7107N/A - -port 1389 \
7107N/A - -hostname opendj.example.com \
7107N/A - -baseDN dc=example,dc=com \
7107N/A "(cn=My App)"
7107N/Adn: cn=My App,ou=Apps,dc=example,dc=com
7107N/AobjectClass: person
7107N/AobjectClass: inetOrgPerson
7107N/AobjectClass: organizationalPerson
7107N/AobjectClass: ds-certificate-user
7107N/AobjectClass: top
7107N/AuserCertificate;binary:: MIIDOzCCAiOgAwIBAgIEG5O0lDANBgkqhkiG9w0BAQsFADBOMRMwEQY
7107N/A KCZImiZPyLGQBGRYDY29tMRcwFQYKCZImiZPyLGQBGRYHZXhhbXBsZTENMAsGA1UECxMEQXBwczEPMA
7107N/A 0GA1UEAxMGTXkgQXBwMB4XDTE0MDQxMDA2MjUwMVoXDTM0MDQwNTA2MjUwMVowTjETMBEGCgmSJomT8
7107N/A ixkARkWA2NvbTEXMBUGCgmSJomT8ixkARkWB2V4YW1wbGUxDTALBgNVBAsTBEFwcHMxDzANBgNVBAMT
7107N/A Bk15IEFwcDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJFg2rAIy3EyJWXWnBgqGTP9bSe
7107N/A AeykCC1lOF+AKDkybAn4igB6JDB+0V1n80G28TZrswnCxQj5G7KJg47OjvRG8ZKuMq96++sd9uKeIVU
7107N/A a+Ekl9lXzGmMXopVYOFyAWeciKQMGnMdNcaKXReoKU5QlR+nUeIYZKNCDMqwjVL7E3UibDQKfvyZ9B+
7107N/A O5CVfWWceVIw1A8xThtARipPppA0h3gopo760llhj/7urHmj84HkLWJqqOHEdujfO61q8tu0Hpld928
7107N/A BjkF/BcnzANkqrbnoc/v3ggsIVyIOoe+NqYkpoGz7phEBcap+/5EuR6tudlsXjaNyNmH4Ge8ictdlWU
7107N/A CAwEAAaMhMB8wHQYDVR0OBBYEFJPF3mpd1ISZOKhtnb+5/161BfGHMA0GCSqGSIb3DQEBCwUAA4IBAQ
7107N/A A3KEYJaEXXf5nzOfJXEX02tV+Fi9Chc7Cor37ldRYBQjjIqBr0Gsk9NbHwWPQE1mQ24aHcS2wqgQ+rT
7107N/A KxLWOC6WPrjwaL7Wx5jojqEc6utg7zqomvtDzxwqirdgnh5Fm+2QtRy3muC6WmjjsK6CMh5FrH/O9b9
7107N/A C9tqGMy4ukUVHpEIZ/sUiS8LvxsYUO+UPuV2A7OcWG3yOZD/lBoGm+o3Oh7NXM1vXXoZzU8PAP/HCF3
7107N/A DrLICKWO/imI8kvOTyrdjf2FSoEEXa4OXiXeh/ZXa/zWRSuYB1WJ/cg/aYRjCy1CJIDtpP9eRp3cJVE
7107N/A V41BUm1xdD26Boei/rlWsJdTPy
7107N/Ads-certificate-fingerprint: 2B:8D:27:D6:1D:D1:A5:5F:14:E7:A8:C1:96:F9:C1:9F
7107N/Ads-certificate-subject-dn: CN=My App, OU=Apps, DC=example, DC=com
7107N/Acn: My App
7107N/Asn: App
7107N/A
7107N/A Configure PKCS #12 trust store.
7107N/A
7107N/A$ mv /path/to/truststore.p12 /path/to/opendj/config/
7107N/A$ dsconfig \
7107N/A set-trust-manager-provider-prop \
7107N/A - -port 4444 \
7107N/A - -hostname opendj.example.com \
7107N/A - -bindDN "cn=Directory Manager" \
7107N/A - -bindPassword password \
7107N/A - -provider-name PKCS12 \
7107N/A - -set enabled:true \
7107N/A - -set trust-store-pin:changeit \
7107N/A - -no-prompt \
7107N/A - -trustAll
7107N/A$ dsconfig \
7107N/A get-trust-manager-provider-prop \
7107N/A - -port 4444 \
7107N/A - -hostname opendj.example.com \
7107N/A - -bindDN "cn=Directory Manager" \
7107N/A - -bindPassword password \
7107N/A - -provider-name PKCS12 \
7107N/A - -no-prompt \
7107N/A - -trustAll
7107N/A$ stop-ds - -restart
7107N/A
7107N/A Configure LDAPS connection handler to use PKCS #12 trust store.
7107N/A
7107N/A$ dsconfig \
7107N/A set-connection-handler-prop \
7107N/A - -port 4444 \
7107N/A - -hostname opendj.example.com \
7107N/A - -bindDN "cn=Directory Manager" \
7107N/A - -bindPassword password \
7107N/A - -handler-name "LDAPS Connection Handler" \
7107N/A - -set trust-manager-provider:PKCS12 \
7107N/A - -no-prompt \
7107N/A - -trustAll
7107N/A
7107N/A Create JKS key store from PKCS #12 key store.
7107N/A
7107N/A$ keytool \
7107N/A -importkeystore \
7107N/A -srckeystore /path/to/opendj/config/truststore.p12 \
7107N/A -srcstoretype pkcs12 \
7107N/A -srcstorepass changeit \
7107N/A -srckeypass changeit \
7107N/A -srcalias myapp-cert \
7107N/A -destkeystore keystore \
7107N/A -deststoretype jks \
7107N/A -deststorepass changeit \
7107N/A -destkeypass changeit \
7107N/A -v
7107N/A[Storing keystore]
7107N/A
7107N/A$ keytool \
7107N/A -list \
7107N/A -keystore keystore \
7107N/A -storepass changeit \
7107N/A -keypass changeit
7107N/A
7107N/AKeystore type: JKS
7107N/AKeystore provider: SUN
7107N/A
7107N/AYour keystore contains 1 entry
7107N/A
7107N/Amyapp-cert, Apr 10, 2014, PrivateKeyEntry,
7107N/ACertificate fingerprint (SHA1): 1D:A2:BF:A6:29:8C:13:81:A4:E5:77:9E:D5:67:CD:C8:E6:AD:6E:A3
7107N/Amark@Mark-Craigs-MacBook-Pro bin$ keytool -list -keystore keystore -storepass changeit -keypass changeit -v
7107N/A
7107N/AKeystore type: JKS
7107N/AKeystore provider: SUN
7107N/A
7107N/AYour keystore contains 1 entry
7107N/A
7107N/AAlias name: myapp-cert
7107N/ACreation date: Apr 10, 2014
7107N/AEntry type: PrivateKeyEntry
7107N/ACertificate chain length: 1
7107N/ACertificate[1]:
7107N/AOwner: CN=My App, OU=Apps, DC=example, DC=com
7107N/AIssuer: CN=My App, OU=Apps, DC=example, DC=com
7107N/ASerial number: 1b93b494
7107N/AValid from: Thu Apr 10 08:25:01 CEST 2014 until: Wed Apr 05 08:25:01 CEST 2034
7107N/ACertificate fingerprints:
7107N/A MD5: 2B:8D:27:D6:1D:D1:A5:5F:14:E7:A8:C1:96:F9:C1:9F
7107N/A SHA1: 1D:A2:BF:A6:29:8C:13:81:A4:E5:77:9E:D5:67:CD:C8:E6:AD:6E:A3
7107N/A SHA256: 80:47:B8:5C:E7:22:BB:4E:5E:48:8B:84:38:9F:E8:2C:7C:87:6E:9C:20:A2:E2:5F:A7:7A:10:0E:C8:AE:60:85
7107N/A Signature algorithm name: SHA256withRSA
7107N/A Version: 3
7107N/A
7107N/AExtensions:
7107N/A
7107N/A#1: ObjectId: 2.5.29.14 Criticality=false
7107N/ASubjectKeyIdentifier [
7107N/AKeyIdentifier [
7107N/A0000: 93 C5 DE 6A 5D D4 84 99 38 A8 6D 9D BF B9 FF 5E ...j]...8.m....^
7107N/A0010: B5 05 F1 87 ....
7107N/A]
7107N/A]
7107N/A
7107N/A
7107N/A
7107N/A*******************************************
7107N/A*******************************************
7107N/A
7107N/A
7107N/A Verify SSL mutual auth.
7107N/A
7107N/A$ ldapsearch \
7107N/A - -port 1636 \
7107N/A - -hostname opendj.example.com \
7107N/A - -baseDN dc=example,dc=com \
7107N/A - -useSSL \
7107N/A - -useSASLExternal \
7107N/A - -certNickName myapp-cert \
7107N/A - -keyStorePath keystore \
7107N/A - -keyStorePassword changeit \
7107N/A - -trustStorePath /path/to/opendj/config/keystore \
7107N/A - -trustStorePasswordFile /path/to/opendj/config/keystore.pin \
7107N/A "(cn=My App)" userPassword
7107N/Adn: cn=My App,ou=Apps,dc=example,dc=com
7107N/AuserPassword: {SSHA}9jjvsv9wlTW7Ikflzc2/wMNBjAN6G4CbbTKYIw==
7107N/A
7107N/A -->
7107N/A
7107N/A <step>
7107N/A <para>
7107N/A Add the PKCS #12 format store to OpenDJ's configuration.
7107N/A </para>
7107N/A
7107N/A <para>
7107N/A By default, OpenDJ expects the store
7107N/A to be <filename>/path/to/opendj/config/truststore.p12</filename>.
7107N/A The following example uses that default.
7107N/A </para>
7107N/A
7107N/A <screen>
7107N/A$ <userinput>cp /path/to/<replaceable>pkcs12-store</replaceable> /path/to/opendj/config/truststore.p12</userinput>
7107N/A </screen>
7107N/A
7107N/A <para>
7107N/A Here, <replaceable>pkcs12-store</replaceable> is the file name
7107N/A of the PKCS #12 format store.
7107N/A </para>
7107N/A </step>
7107N/A
7107N/A <step>
7107N/A <para>
7107N/A Configure the OpenDJ PKCS12 trust manager provider
7107N/A to use the PKCS #12 store,
7107N/A and restart OpenDJ server to force it to read the store.
7107N/A </para>
7107N/A
7107N/A <para>
7107N/A In the following example the store password is <literal>changeit</literal>.
7107N/A </para>
7107N/A
7107N/A <screen>
7107N/A$ <userinput>dsconfig \
7107N/A set-trust-manager-provider-prop \
7107N/A --port 4444 \
7107N/A --hostname opendj.example.com \
7107N/A --bindDN "cn=Directory Manager" \
7107N/A --bindPassword password \
7107N/A --provider-name PKCS12 \
7107N/A --set enabled:true \
7107N/A --set trust-store-pin:changeit \
7107N/A --no-prompt \
7107N/A --trustAll</userinput>
7107N/A$ <userinput>stop-ds --restart</userinput>
7107N/A </screen>
7107N/A </step>
7107N/A
7107N/A <step>
7107N/A <para>
7107N/A Configure a connection handler to use the PKCS12 trust manager provider.
7107N/A </para>
7107N/A
7107N/A <para>
7107N/A The following example configures the LDAPS connection handler.
7107N/A </para>
7107N/A
7107N/A <screen>
7107N/A$ <userinput>dsconfig \
7107N/A set-connection-handler-prop \
7107N/A --port 4444 \
7107N/A --hostname opendj.example.com \
7107N/A --bindDN "cn=Directory Manager" \
7107N/A --bindPassword password \
7107N/A --handler-name "LDAPS Connection Handler" \
7107N/A --set trust-manager-provider:PKCS12 \
7107N/A --no-prompt \
7107N/A --trustAll</userinput>
7107N/A </screen>
7107N/A </step>
7107N/A
7107N/A <step>
7107N/A <para>
7107N/A Verify SSL mutual authentication to check your work.
7107N/A </para>
7107N/A
7107N/A <para>
7107N/A The following example assumes the client certificate for My App
7107N/A is present in the PKCS #12 store,
7107N/A and that the certificate has been added to the entry for My App
7107N/A as in <xref linkend="add-client-cert" />.
7107N/A </para>
7107N/A
7107N/A <screen>
7107N/A$ <userinput>ldapsearch \
7107N/A --port 1636 \
7107N/A --hostname opendj.example.com \
7107N/A --baseDN dc=example,dc=com \
7107N/A --useSSL \
7107N/A --useSASLExternal \
7107N/A --certNickName myapp-cert \
7107N/A --keyStorePath keystore \
7107N/A --keyStorePassword changeit \
7107N/A --trustStorePath /path/to/opendj/config/keystore \
7107N/A --trustStorePasswordFile /path/to/opendj/config/keystore.pin \
7107N/A "(cn=My App)" userPassword</userinput>
7107N/A<computeroutput>dn: cn=My App,ou=Apps,dc=example,dc=com
7107N/AuserPassword: {SSHA}9jjvsv9wlTW7Ikflzc2/wMNBjAN6G4CbbTKYIw==</computeroutput>
7107N/A </screen>
7107N/A </step>
7107N/A </procedure>
7107N/A
6443N/A <procedure xml:id="config-cert-mappers">
6443N/A <title>To Configure Certificate Mappers</title>
6443N/A
6443N/A <variablelist>
6443N/A <para>OpenDJ uses certificate mappers during binds to establish a mapping
6443N/A between a client certificate and the entry that corresponds to that
6443N/A certificate. The certificate mappers provided out of the box include the
6443N/A following.</para>
6443N/A
6443N/A <varlistentry>
6443N/A <term>Fingerprint Certificate Mapper</term>
6443N/A <listitem>
6443N/A <para>Looks for the MD5 (default) or SHA1 certificate fingerprint in an
6443N/A attribute of the entry (default:
6443N/A <literal>ds-certificate-fingerprint</literal>).</para>
6443N/A </listitem>
6443N/A </varlistentry>
6443N/A
6443N/A <varlistentry>
6443N/A <term>Subject Attribute To User Attribute Mapper</term>
6443N/A <listitem>
6443N/A <para>Looks for a match between an attribute of the certificate subject
6443N/A and an attribute of the entry (default: match <literal>cn</literal> in
6443N/A the certificate to <literal>cn</literal> on the entry, or match
6443N/A <literal>emailAddress</literal> in the certificate to
6443N/A <literal>mail</literal> on the entry).</para>
6443N/A </listitem>
6443N/A </varlistentry>
6443N/A
6443N/A <varlistentry>
6443N/A <term>Subject DN to User Attribute Certificate Mapper</term>
6443N/A <listitem>
6443N/A <para>Looks for the certificate subject DN in an attribute of the entry
6443N/A (default: <literal>ds-certificate-subject-dn</literal>).</para>
6443N/A </listitem>
6443N/A </varlistentry>
6443N/A
6443N/A <varlistentry>
6443N/A <term>Subject Equals DN Certificate Mapper</term>
6443N/A <listitem>
6443N/A <para>Looks for an entry whose DN matches the certificate subject DN.</para>
6443N/A </listitem>
6443N/A </varlistentry>
6443N/A </variablelist>
6443N/A
6443N/A <para>If the default configurations for the certificate mappers are
6443N/A acceptable, you do not need to change them. They are enabled by
6443N/A default.</para>
6443N/A
6443N/A <para>The following steps demonstrate how to change the Fingerprint Mapper
6443N/A default algorithm of MD5 to SHA1.</para>
6443N/A
6443N/A <step>
6443N/A <para>List the certificate mappers to retrieve the correct name.</para>
6443N/A
7097N/A <screen width="83">
7097N/A$ <userinput>dsconfig \
7097N/A list-certificate-mappers \
7097N/A --port 4444 \
7097N/A --hostname opendj.example.com \
7097N/A --bindDN "cn=Directory Manager" \
7097N/A --bindPassword password</userinput>
7097N/A<computeroutput>
6443N/ACertificate Mapper : Type : enabled
6443N/A------------------------------------:-------------------------------------:--------
6443N/AFingerprint Mapper : fingerprint : true
6443N/ASubject Attribute to User Attribute : subject-attribute-to-user-attribute : true
6443N/ASubject DN to User Attribute : subject-dn-to-user-attribute : true
7097N/ASubject Equals DN : subject-equals-dn : true
7097N/A</computeroutput>
7097N/A </screen>
6443N/A </step>
6443N/A
6443N/A <step>
6443N/A <para>Examine the current configuration.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>dsconfig \
7097N/A get-certificate-mapper-prop \
7097N/A --port 4444 \
7097N/A --hostname opendj.example.com \
7097N/A --bindDN "cn=Directory Manager" \
7097N/A --bindPassword password \
7097N/A --mapper-name "Fingerprint Mapper"</userinput>
7097N/A<computeroutput>
6443N/AProperty : Value(s)
6443N/A----------------------:---------------------------
6443N/Aenabled : true
6443N/Afingerprint-algorithm : md5
6443N/Afingerprint-attribute : ds-certificate-fingerprint
7097N/Auser-base-dn : -</computeroutput>
7097N/A </screen>
6443N/A </step>
6443N/A
6443N/A <step>
6443N/A <para>Change the configuration as necessary.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>dsconfig \
7097N/A set-certificate-mapper-prop \
7097N/A --port 4444 \
7097N/A --hostname opendj.example.com \
7097N/A --bindDN "cn=Directory Manager" \
7097N/A --bindPassword password \
7097N/A --mapper-name "Fingerprint Mapper" \
7097N/A --set fingerprint-algorithm:sha1 \
7097N/A --no-prompt</userinput>
7097N/A </screen>
6443N/A </step>
6443N/A
6443N/A <step>
6443N/A <para>Set the External SASL Mechanism Handler to use the appropriate
6443N/A certificate mapper (default: Subject Equals DN).</para>
6443N/A
6443N/A <para>Clients applications use the SASL External mechanism during the bind
6443N/A to have OpenDJ set the authorization identifier based on the entry that
6443N/A matches the client certificate.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>dsconfig \
7097N/A set-sasl-mechanism-handler-prop \
7097N/A --port 4444 \
7097N/A --hostname opendj.example.com \
7097N/A --bindDN "cn=Directory Manager" \
7097N/A --bindPassword password \
7097N/A --handler-name External \
7097N/A --set certificate-mapper:"Fingerprint Mapper" \
7097N/A --no-prompt</userinput>
7097N/A </screen>
6443N/A </step>
6443N/A </procedure>
6443N/A
6443N/A <example xml:id="auth-with-client-cert"><?dbfo keep-together="auto"?>
6443N/A <title>Authenticate With Client Certificate</title>
6443N/A
6443N/A <para>Instead of providing a bind DN and password as for simple
6443N/A authentication, use the SASL EXTERNAL authentication mechanism, and provide
6443N/A the certificate. As a test with example data you can try an anonymous search,
6443N/A and then try with certificate-based authentication.</para>
6443N/A
6443N/A <para>Before you try this example, make sure OpenDJ is set up to accept
6443N/A StartTLS from clients, and that you have set up the client certificate
6443N/A as described above. Next, create a password .pin file for your client key
6443N/A store.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>echo changeit > keystore.pin</userinput>
7097N/A$ <userinput>chmod 400 keystore.pin</userinput>
7097N/A </screen>
6443N/A
6443N/A <para>Also, if OpenDJ directory server uses a certificate for StartTLS that
6443N/A was not signed by a well-known CA, import the appropriate certificate into
6443N/A the client key store, which can then double as a trust store. For example,
6443N/A if OpenDJ uses a self-signed certificate, import the server certificate into
6443N/A the key store.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>keytool \
7097N/A -export \
7097N/A -alias server-cert \
7097N/A -file server-cert.crt \
7097N/A -keystore /path/to/opendj/config/keystore \
7097N/A -storepass `cat /path/to/opendj/config/keystore.pin`</userinput>
7097N/A
7097N/A$ <userinput>keytool \
7097N/A -import \
7097N/A -trustcacerts \
7097N/A -alias server-cert \
7097N/A -file server-cert.crt \
7097N/A -keystore keystore \
7097N/A -storepass `cat keystore.pin`</userinput>
7097N/A </screen>
6443N/A
6443N/A <para>If OpenDJ directory server uses a CA-signed certificate, but the CA is
6443N/A not well known, import the CA certificate into your keystore.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>keytool \
7097N/A -import \
7097N/A -trustcacerts \
7097N/A -alias ca-cert \
7097N/A -file ca-cert.crt \
7097N/A -keystore keystore \
7097N/A -storepass `cat keystore.pin`</userinput>
7097N/A </screen>
6443N/A
6443N/A <para>Now that you can try the example, notice that OpenDJ does not return
6443N/A the <literal>userPassword</literal> value for an anonymous search.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>ldapsearch \
7097N/A --port 1389 \
7097N/A --hostname opendj.example.com \
7097N/A --baseDN dc=example,dc=com \
7097N/A --useStartTLS \
7097N/A --trustStorePath keystore \
7097N/A --trustStorePasswordFile keystore.pin \
7097N/A "(cn=My App)" userPassword</userinput>
7097N/A<computeroutput>dn: cn=My App,ou=Apps,dc=example,dc=com</computeroutput>
7097N/A </screen>
6443N/A
6443N/A <para>OpenDJ does let users read the values of their own
6443N/A <literal>userPassword</literal> attributes after they bind
6443N/A successfully.</para>
6443N/A
7097N/A <screen>
7097N/A$ <userinput>ldapsearch \
7097N/A --port 1389 \
7097N/A --hostname opendj.example.com \
7097N/A --baseDN dc=example,dc=com \
7097N/A --useStartTLS \
7097N/A --useSASLExternal \
7097N/A --certNickName myapp-cert \
7097N/A --keyStorePath keystore \
7097N/A --keyStorePasswordFile keystore.pin \
7097N/A --trustStorePath keystore \
7097N/A --trustStorePasswordFile keystore.pin \
7097N/A "(cn=My App)" userPassword</userinput>
7097N/A<computeroutput>dn: cn=My App,ou=Apps,dc=example,dc=com
7097N/AuserPassword: {SSHA}vy/vTthOQoV/wH3MciTOBKKR4OX+0dSN/a09Ew==</computeroutput>
7097N/A </screen>
6443N/A
6443N/A <para>You can also try the same test with other certificate mappers.</para>
6443N/A
7097N/A <screen>
7097N/A# Fingerprint mapper
7097N/A$ <userinput>dsconfig \
7097N/A set-sasl-mechanism-handler-prop \
7097N/A --port 4444 \
7097N/A --hostname opendj.example.com \
7097N/A --bindDN "cn=Directory Manager" \
7097N/A --bindPassword password \
7097N/A --handler-name External \
7097N/A --set certificate-mapper:"Fingerprint Mapper" \
7097N/A --no-prompt</userinput>
7097N/A
7097N/A$ <userinput>ldapsearch \
7097N/A --port 1389 \
7097N/A --hostname opendj.example.com \
7097N/A --baseDN dc=example,dc=com \
7097N/A --useStartTLS \
7097N/A --useSASLExternal \
7097N/A --certNickName myapp-cert \
7097N/A --keyStorePath keystore \
7097N/A --keyStorePasswordFile keystore.pin \
7097N/A --trustStorePath keystore \
7097N/A --trustStorePasswordFile keystore.pin \
7097N/A "(cn=My App)" userPassword</userinput>
7097N/A<computeroutput>dn: cn=My App,ou=Apps,dc=example,dc=com
7097N/AuserPassword: {SSHA}vy/vTthOQoV/wH3MciTOBKKR4OX+0dSN/a09Ew==</computeroutput>
6443N/A
6443N/A# Subject Attribute to User Attribute mapper
7097N/A$ <userinput>dsconfig \
7097N/A set-sasl-mechanism-handler-prop \
7097N/A --port 4444 \
7097N/A --hostname opendj.example.com \
7097N/A --bindDN "cn=Directory Manager" \
7097N/A --bindPassword password \
7097N/A --handler-name External \
7097N/A --set certificate-mapper:"Subject Attribute to User Attribute" \
7097N/A --no-prompt</userinput>
7097N/A
7097N/A$ <userinput>ldapsearch \
7097N/A --port 1389 \
7097N/A --hostname opendj.example.com \
7097N/A --baseDN dc=example,dc=com \
7097N/A --useStartTLS \
7097N/A --useSASLExternal \
7097N/A --certNickName myapp-cert \
7097N/A --keyStorePath keystore \
7097N/A --keyStorePasswordFile keystore.pin \
7097N/A --trustStorePath keystore \
7097N/A --trustStorePasswordFile keystore.pin \
7097N/A "(cn=My App)" userPassword</userinput>
7097N/A<computeroutput>dn: cn=My App,ou=Apps,dc=example,dc=com
7097N/AuserPassword: {SSHA}vy/vTthOQoV/wH3MciTOBKKR4OX+0dSN/a09Ew==</computeroutput>
6443N/A
6443N/A# Subject DN to User Attribute mapper
7097N/A$ <userinput>dsconfig \
7097N/A set-sasl-mechanism-handler-prop \
7097N/A --port 4444 \
7097N/A --hostname opendj.example.com \
7097N/A --bindDN "cn=Directory Manager" \
7097N/A --bindPassword password \
7097N/A --handler-name External \
7097N/A --set certificate-mapper:"Subject DN to User Attribute" \
7097N/A --no-prompt</userinput>
7097N/A
7097N/A$ <userinput>ldapsearch \
7097N/A --port 1389 \
7097N/A --hostname opendj.example.com \
7097N/A --baseDN dc=example,dc=com \
7097N/A --useStartTLS \
7097N/A --useSASLExternal \
7097N/A --certNickName myapp-cert \
7097N/A --keyStorePath keystore \
7097N/A --keyStorePasswordFile keystore.pin \
7097N/A --trustStorePath keystore \
7097N/A --trustStorePasswordFile keystore.pin \
7097N/A "(cn=My App)" userPassword</userinput>
7097N/A<computeroutput>dn: cn=My App,ou=Apps,dc=example,dc=com
7097N/AuserPassword: {SSHA}vy/vTthOQoV/wH3MciTOBKKR4OX+0dSN/a09Ew==</computeroutput>
7097N/A </screen>
6443N/A </example>
6443N/A </section>
6443N/A</chapter>