<?xml version="1.0" encoding="UTF-8"?> <chapter version="5.0" xml:id="sdiLdap" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:svg="http://www.w3.org/2000/svg" xmlns:m="http://www.w3.org/1998/Math/MathML" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:db="http://docbook.org/ns/docbook"> <title><xref linkend="glo_LDAP"/></title> <section xml:id="ldapPrepare"> <title>Recommended Preparations</title> <para>Introductory Material</para> <itemizedlist> <listitem> <para><uri xlink:href="http://www.zytrax.com/books/ldap">LDAP for Rocket Scientists</uri></para> </listitem> <listitem> <para><uri xlink:href="https://www.novell.com/coolsolutions/feature/15359.html">An Introduction to LDAP: Part 1</uri></para> </listitem> <listitem> <para><uri xlink:href="http://quark.humbug.org.au/publications/ldap/ldap_tut.html">Introduction to LDAP</uri></para> </listitem> <listitem> <para><uri xlink:href="http://www-cs-students.stanford.edu/~hgberg/Links/LDAP.pdf">Slides ldap.pdf</uri></para> </listitem> <listitem> <para><uri xlink:href="http://ldapman.org/articles/intro_to_ldap.html">ldapman.org, An Introduction to LDAP</uri></para> </listitem> </itemizedlist> <para>Since we use the <uri xlink:href="http://www.openldap.org">OpenLDAP</uri> server during the exercises a lot of useful material can be collected from <uri xlink:href="http://www.openldap.org">http://www.openldap.org</uri>.</para> <para>The following questions might arise when starting practical work:</para> <itemizedlist> <listitem> <para>What is the <acronym>LDAP</acronym> Protocol? What is the difference between the two protocols <acronym>ldap</acronym> and <acronym>ldaps </acronym>?</para> </listitem> <listitem> <para>What does the acronym <acronym>dc</acronym> in <acronym>dc=somedomain, dc=org</acronym> stand for?</para> </listitem> <listitem> <para>What is the role of <acronym>LDAP</acronym> <property>objectclass</property> definitions? How do they relate to <acronym>LDAP</acronym> schema definitions?</para> </listitem> <listitem> <para>Describe the relationship between <acronym>LDAP</acronym> entries and <code>objectClass</code> values.</para> </listitem> <listitem> <para>Is it possible to dynamically change an entries structure?</para> </listitem> <listitem> <para>What does the term <quote>bind to an <acronym>LDAP</acronym></quote> server mean? Which two types of bind operations are being distinguished?</para> </listitem> <listitem> <para>Do <acronym>LDAP</acronym> servers in general support database features like transactions, ACID semantic etc.?</para> </listitem> <listitem> <para>Explain the term <quote>replication</quote> in an <acronym>LDAP</acronym> server context.</para> </listitem> <listitem> <para>Why do organizations sometimes prefer <acronym>LDAP</acronym> data repositories rather than using relational database systems?</para> </listitem> <listitem> <para>How is the <acronym>LDIF</acronym> format being organized? Explain the practical use of <acronym>LDIF</acronym> data when running a <acronym>LDAP</acronym> service.</para> </listitem> <listitem> <para><acronym>LDAP</acronym> filters</para> <itemizedlist> <listitem> <para>How do <acronym>LDAP</acronym> filters work?</para> </listitem> <listitem> <para>What is the meaning of the term <emphasis>scope</emphasis> ?</para> </listitem> <listitem> <para>How do predicate based filters connected by logical <emphasis role="bold">and/or/not</emphasis> look like?</para> </listitem> </itemizedlist> </listitem> <listitem> <para><productname>OpenLDAP</productname> server software specific questions</para> <itemizedlist> <listitem> <para>What does the term <quote>database backend</quote> refer to with respect to <productname>OpenLDAP</productname> server implementation?</para> </listitem> <listitem> <para>Why is <acronym>LDAP</acronym> replication important?</para> </listitem> <listitem> <para>How do you restrict access to <acronym>LDAP</acronym> directories?</para> </listitem> <listitem> <para>How do you speed up predicate based queries?</para> </listitem> </itemizedlist> </listitem> </itemizedlist> </section> <section xml:id="ldapExercises"> <title>Exercises</title> <para>Our aim is to set up an <acronym>LDAP</acronym> Server being populated with thew following company structure of organisational units and persons:</para> <figure xml:id="sdiLdapBetrayerComTree"> <title>An example <acronym>LDAP</acronym> Tree</title> <mediaobject> <imageobject> <imagedata fileref="Ref/Fig/ldaptree.fig"/> </imageobject> </mediaobject> </figure> <section xml:id="sdiBrowseExistingLdap"> <title>Browse an existing <xref linkend="glo_LDAP"/> Server</title> <para>Before setting up we take a tour on <productname xlink:href="https://directory.apache.org/studio">Apache Directory Studio</productname>:</para> <itemizedlist> <listitem> <para>Setup Apache Directory Studio to anonymously connect to <code>ldap1.mi.hdm-stuttgart.de</code> using <xref linkend="glo_TLS"/>.</para> </listitem> <listitem> <para>Browse the <xref linkend="glo_DIT"/>.</para> </listitem> <listitem> <para>Find your own entry beneath <code>ou=userlist</code> by using a filter <code>(uid=xy234)</code>. Use the corresponding <xref linkend="glo_DN"/> to reconnect using password authentication. Then browse your own entry again. Can you spot any difference?</para> </listitem> <listitem> <para>Use the <command>ldapsearch</command> utility and find your own entry by using the command line.</para> </listitem> </itemizedlist> </section> <section xml:id="ldapServerSetup"> <title>Set up an <productname>OpenLdap</productname> server</title> <itemizedlist> <listitem> <para><link xlink:href="https://help.ubuntu.com/lts/serverguide/openldap-server.html">OpenLDAP Server</link> provides a good introduction how to install and configure OpenLdap.</para> </listitem> <listitem> <para><link xlink:href="http://krams915.blogspot.de/2011/01/ldap-apache-directory-studio-basic.html">http://krams915.blogspot.de/2011/01/ldap-apache-directory-studio-basic.html</link> provides some more details on populating your server with data.</para> </listitem> <listitem> <para>See <link xlink:href="http://chee-yang.blogspot.de/2012/03/ldap-introduction-to-openldap.html">http://chee-yang.blogspot.de/2012/03/ldap-introduction-to-openldap.html</link> for enabling OpenLdap server configuration by e.g. Apache Directory Studio.</para> </listitem> </itemizedlist> <tip> <orderedlist> <listitem> <para>Depending on your systems installation state you may want to add the dialog package which allows for feeding additional parameters during package installations (e.g. admin's credentials and base <xref linkend="glo_DN"/>).</para> </listitem> <listitem> <para>The <link xlink:href="https://help.ubuntu.com/lts/serverguide/openldap-server.html#openldap-server-installation">installation section</link> hints at your host system defined <xref linkend="glo_DNS"/> domain being used for deriving your server's <xref linkend="glo_DIT"/> root. You may circumvent this obstacle by calling <command>dpkg-reconfigure</command> <option>slapd</option> after installation allowing to specify additional parameters manually.</para> </listitem> <listitem> <para>In case you **ever** loose your master <code>admin</code> password see <link xlink:href="http://techiezone.rottigni.net/2011/12/change-root-dn-password-on-openldap">Change Root DN Password on OpenLDAP</link> for troubleshooting.</para> </listitem> </orderedlist> </tip> <para>You may have to install the dialog package as a prerequisite to the <productname>openldap</productname> server package:</para> <programlisting language="none">aptitude install dialog aptitude install slapd</programlisting> <para>based on the <xref linkend="glo_DNS"/> domain <code>mi.hdm-stuttgart.de</code> the default <command>slapd</command> package installer configures a <xref linkend="glo_DIT"/> having <code>dc=mi,dc=hdm-stuttgart,dc=de</code> as root by default. Change this to <code>dc=betrayer,dc=com</code> by executing <command>dpkg-reconfigure</command> <option>slapd</option>.</para> </section> <section xml:id="ldapCompanyLdif"> <title>Populating your <xref linkend="glo_DIT"/>.</title> <para>Add the content outlined in <xref linkend="sdiLdapBetrayerComTree"/>.</para> <para>For your convenience we have installed the <productname xlink:href="https://directory.apache.org/studio">Apache Directory Studio</productname> Eclipse plugin which allows for convenient editing of <xref linkend="glo_LDAP"/> trees.</para> <tip> <para>You may want to adjust occurrences of <code>dc=betrayer;dc=com</code> by your configured <xref linkend="glo_DIT"/> root.</para> <orderedlist> <listitem> <para>You need your initial configuration <code>admin</code> password to perform a bind operation using the <code>cn=admin,dc=betrayer,dc=com</code> <xref linkend="glo_DN"/>.</para> </listitem> <listitem> <para>If you choose <quote>Use existing entry as template</quote> don't forget to purge your copy's <property>entryCsn</property> attribute belonging to your template data record being unique within your <xref linkend="glo_DIT"/>.</para> </listitem> <listitem> <para>Suitable <property>objectClass</property> and other attribute choices:</para> <glosslist> <glossentry> <glossterm>Organisational units <property>department</property>, <property>software</property>, <property>financial</property>, <property>devel</property>, <property>testing</property></glossterm> <glossdef> <glosslist> <glossentry> <glossterm><property>objectClass</property>:</glossterm> <glossdef> <para><property>organizationalUnit</property></para> </glossdef> </glossentry> <glossentry> <glossterm><xref linkend="glo_RDN"/> attribute:</glossterm> <glossdef> <para><property>uid</property></para> </glossdef> </glossentry> </glosslist> </glossdef> </glossentry> <glossentry> <glossterm>Employees Jim Smith, Audrey Bean:</glossterm> <glossdef> <glosslist> <glossentry> <glossterm><property>objectClass</property>:</glossterm> <glossdef> <para><property>inetOrgPerson</property></para> </glossdef> </glossentry> <glossentry> <glossterm><xref linkend="glo_RDN"/> attribute:</glossterm> <glossdef> <para><property>uid</property></para> </glossdef> </glossentry> <glossentry> <glossterm>Other attributes:</glossterm> <glossdef> <para><property>sn</property>, <property>cn</property>, <property>givenName</property>, m<property>ail</property></para> </glossdef> </glossentry> </glosslist> </glossdef> </glossentry> </glosslist> </listitem> </orderedlist> </tip> <para>When you are finished an <productname xlink:href="https://directory.apache.org/studio">Apache Directory Studio</productname> export dump might look like:</para> <programlisting language="ldif">dn: dc=betrayer,dc=com objectClass: organization objectClass: dcObject objectClass: top dc: betrayer o: betrayer.com dn: cn=admin,dc=betrayer,dc=com objectClass: organizationalRole objectClass: simpleSecurityObject cn: admin userPassword:: e1NTSEF9cEhFK0VQT0cyZ3lSeU9nanZGcXNXT2I1ekdzR2w5Q0Q= description: LDAP administrator dn: ou=departments,dc=betrayer,dc=com objectClass: top objectClass: organizationalUnit ou: departments dn: ou=software,ou=departments,dc=betrayer,dc=com objectClass: top objectClass: organizationalUnit ou: software dn: ou=financial,ou=departments,dc=betrayer,dc=com objectClass: top objectClass: organizationalUnit ou: financial dn: ou=devel,ou=software,ou=departments,dc=betrayer,dc=com objectClass: top objectClass: organizationalUnit ou: devel dn: ou=testing,ou=software,ou=departments,dc=betrayer,dc=com objectClass: top objectClass: organizationalUnit ou: testing dn: uid=smith,ou=devel,ou=software,ou=departments,dc=betrayer,dc=com objectClass: top objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson cn: Jim Bean sn: Bean givenName: Jim mail: bean@betrayer.com uid: smith userPassword:: e3NtZDV9YVhKL2JlVkF2TDRENk9pMFRLcDhjM3ovYTZQZzBXeHA=</programlisting> </section> <section xml:id="sdiLdapTestBind"> <title>Testing a bind operation as non - <code>admin</code> user</title> <para>Use <productname xlink:href="https://directory.apache.org/studio">Apache Directory Studio</productname> to supply a <property>userPassword</property> to e.g. <code>uid=beam,ou=devel,ou=software,ou=departments,dc=betrayer;dc=com</code> (still binding as <code>cn=admin,dc=betrayer,dc=com</code>).</para> <para>Then configure a second <productname xlink:href="https://directory.apache.org/studio">Apache Directory Studio</productname> profile binding as <code>uid=beam,ou=devel,ou=software,ou=departments,dc=betrayer,dc=com</code>.</para> <tip> <para>Beware: Some hash types may not be supported. SMD5 is known to work.</para> </tip> </section> <section xml:id="ldapTest"> <title>Accessing <acronym>LDAP</acronym> data by a mail client</title> <para>The directory studio allows to reread the directory tree. As a different approach you shall configure your local mail client (e.g. <productname>thunderbird</productname>) to use your <acronym>LDAP</acronym> server for email address lookup.</para> </section> <section xml:id="sdiLdapConfig"> <title><xref linkend="glo_LDAP"/> configuration</title> <para>In contrast to many other server configurations OpenLdap supports parameter configuration within its own database backend. In other words: Some parameters are not being stored in configuration files.</para> <para>Actually OpenLdap still supports an alternate configuration file based approach which may be activated. Its use however is discouraged according to the documentation:</para> <note xlink:href="http://www.openldap.org/doc/admin24/slapdconf2.html"> <para>The older style <filename>slapd.conf</filename>(5) file is still supported, but its use is deprecated and support for it will be withdrawn in a future OpenLDAP release.</para> </note> <para>The <xref linkend="glo_DIT"/> style configuration may be altered by <xref linkend="glo_LDAP"/> clients like <command xlink:href="http://www.openldap.org/software/man.cgi?query=ldapmodify&apropos=0&sektion=0&manpath=OpenLDAP+2.4-Release&format=html">ldapmodify</command> using <filename>.ldif</filename> files. An alternate way requires altering the server's configuration <filename>/etc/ldap/slapd.d/cn\=config/olcDatabase\=\{0\}config.ldif</filename>. We start by gathering required information. Note: The <command>ldapsearch</command> command is part of the <package>openldap-utils</package> package:</para> <programlisting language="none">ldapsearch -Y EXTERNAL -H ldapi:/// -b cn=config # {0}config, config dn: olcDatabase={0}config,cn=config objectClass: olcDatabaseConfig olcDatabase: {0}config olcAccess: {0}to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external ,cn=auth manage by * break <emphasis role="bold">olcRootDN: cn=admin,cn=config</emphasis> # {1}mdb, config dn: olcDatabase={1}mdb,cn=config ... <emphasis role="bold">olcRootDN: cn=admin,dc=hdm-stuttgart,dc=de olcRootPW: {SSHA}7M0gUyHOH7cfK1z9amqgK0uQcn84AuYw</emphasis> ...</programlisting> <para>The above lines appear near in the tail section. We see two databases <code>{0}</code> and <code>{1}</code> representing two different <xref linkend="glo_DIT"/>s namely <code>cn=config</code> (the configuration database) and <code>dc=hdm-stuttgart,dc=de</code> (containing our <quote>actual</quote> directory data).</para> <para>The configuration database does have a <code>olcRootDN: cn=admin,cn=config</code> entry but a corresponding <parameter>olcRootPW</parameter> attribute is yet missing. This limits configuration access to <code>localhost</code>.</para> <para>External access e.g. by <productname xlink:href="https://directory.apache.org/studio">Apache Directory Studio</productname> requires adding this credential attribute. This first-time (bootstrapping) configuration must be done locally by means of an <xref linkend="glo_LDIF"/> file adding a (possibly different) hashed password:</para> <programlisting language="none">root@sdi8a:~# cat ~/add_olcRootPW.ldif dn: olcDatabase={0}config,cn=config add: olcRootPW olcRootPW: {ssha}pHE+EPOG2gyRyOgjvFqsWOb5zGsGl9CD</programlisting> <para>Activating this configuration my be effected by using <command xlink:href="http://www.openldap.org/software/man.cgi?query=ldapmodify&apropos=0&sektion=0&manpath=OpenLDAP+2.4-Release&format=html">ldapmodify</command>:</para> <programlisting language="none">root@sdi8a:~# ldapmodify -Q -Y EXTERNAL -H ldapi:/// -f ~/add_olcRootPW.ldif modifying entry "olcDatabase={0}config,cn=config"</programlisting> <para>This activation in turn enables a new account:</para> <glosslist> <glossentry> <glossterm>Bind DN:</glossterm> <glossdef> <para><option>cn=admin,cn=config</option></para> </glossdef> </glossentry> <glossentry> <glossterm>Bind password</glossterm> <glossdef> <para><option>*****</option></para> </glossdef> </glossentry> <glossentry> <glossterm>Base DN</glossterm> <glossdef> <para><option>cn=config</option></para> </glossdef> </glossentry> </glosslist> <para>When configuring a connection to access this configuration database you may have to untick Apache Directory Studio's <quote>Get base DNs from Root DSE</quote> box in the <quote>Browser Options</quote> tab. Then configure "cn=config" in the <quote>Base DN:</quote> manually.</para> <para>We may now dynamically alter server configuration parameters remotely using e.g. <link xlink:href="https://directory.apache.org/studio">Apache directory studio</link>:</para> <mediaobject> <imageobject> <imagedata fileref="Ref/Screen/ldapConfig.png"/> </imageobject> </mediaobject> <para>A prominent configuration change candidate is our server's log level: Depending on your success during subsequent exercises you may want to adjust <parameter xlink:href="http://www.zytrax.com/books/ldap/ch6/#loglevel">olcLogLevel</parameter> in <code>cn=config</code> appropriately.</para> <para>Consider <link xlink:href="https://serverfault.com/questions/324608/how-do-i-get-openldap-on-centos-6-to-write-anything-to-its-log-files#answer-499902">using olcLogFile</link>. Caveat: You <xref linkend="glo_LDAP"/> server daemon does runs from a non - root <property>uid</property>. Thus you have to assure sufficient writing permissions.</para> </section> <section xml:id="ldapFilter"> <title>Filter based search</title> <para>Execute the following <acronym>LDAP</acronym> filter based searches:</para> <itemizedlist> <listitem> <para>All users with a <code>uid</code> attribute value starting with the letter <quote>b</quote>.</para> </listitem> <listitem> <para>All entries either with either a defined <code>uid</code> attribute or a <code>ou</code> attribute starting with letter <quote>d</quote>.</para> </listitem> </itemizedlist> </section> <section xml:id="ldapExtendPosixAccount"> <title>Extending an existing entry</title> <para>The entry <code>uid=beam,ou=devel,ou=software,ou=departments,dc=betrayer;dc=com</code> may be extended by the <code>objectclass</code> <code>posixAccount</code>. Construct a <acronym>LDIF</acronym> file to add the attributes <code>uidNumber</code>, <code>gidNumber</code> and <code>homeDirectory</code> by a modify/add operation.</para> </section> <section xml:id="sdiLdapWebManagement"> <title>Providing WEB based user management</title> <para>Using Apache Directory Studio is a good choice during installation and may serve development and debugging purposes as well. However it is not an adequate tool for day to day administration tasks with respect to user management. We need a separate (WEB based) administration tool.</para> <para>Install <productname xlink:href="https://www.ldap-account-manager.org">LDAP Account Manager</productname> on top of an Apache Web Server. <productname>Ubuntu</productname> allows for <link xlink:href="https://www.ldap-account-manager.org/static/doc/manual/ch01.html">package based installation</link>.</para> </section> <section xml:id="diSectLdapBackupRestore"> <title>Backup and recovery / restore</title> <para>Take the hard way to test backup and restore:</para> <orderedlist> <listitem> <para>Set up a <quote>replica</quote> <xref linkend="glo_LDAP"/> Server on your second host system.</para> </listitem> <listitem> <para>Export both databases (configuration and <quote>real</quote> data) from your production server using <command xlink:href="http://linux.die.net/man/8/slapcat">slapcat</command>.</para> </listitem> <listitem> <para>Restore the exported data on your replica using <command xlink:href="http://linux.die.net/man/8/slapadd">slapadd</command>.</para> </listitem> </orderedlist> </section> <section xml:id="ldapReplication"> <title>Replication</title> <para><link xlink:href="???https://wiki.debian.org/LDAP/OpenLDAPSetup#with_cn.3Dconfig-1">Setting up an LDAP server with OpenLDAP</link> provides a replication configuration recipe. We advise using Apache Directory Studio in favour of <command>ldapmodify</command> and friends.</para> <para>Hints:</para> <orderedlist> <listitem> <para>Depending on your database backend choice during server installation you may have to alter the <link xlink:href="https://wiki.debian.org/LDAP/OpenLDAPSetup#with_cn.3Dconfig-1">installation procedure</link> by replacing <quote>hdb</quote> with <quote>mdb</quote> accordingly both on the provider and the consumer side.</para> </listitem> <listitem> <para>You may want to add the value <code>sync</code> to the <property>olcLogLevel</property> attribute. This will create related messages in <filename>/var/log/syslog</filename>.</para> </listitem> <listitem> <para>Activating the <code>syncprov</code> overlay requires an additional <property>olcModuleLoad</property> <coref linkend="sdiLdapCoSyncprov"/> value:</para> <programlisting language="none">dn: cn=module{0},cn=config objectClass: olcModuleList cn: module{0} olcModuleLoad: {0}back_mdb <emphasis role="bold">olcModuleLoad: {1}syncprov</emphasis> <co xml:id="sdiLdapCoSyncprov"/> olcModulePath: /usr/lib/ldap</programlisting> </listitem> <listitem> <para>Adding the <property>olcSyncProvConfig</property> objectclass property requires hitting the <quote>reload</quote> icon in Apache Directory Studio.</para> </listitem> </orderedlist> <para>Check for provider changes being propagated to the consumer by e.g. creating an <code>organisationalUnit</code> entry.</para> <note> <para>The current configuration contains a serious security flaw: The credentials are being sent in clear text and are thus subject to network sniffing (e.g. by using <link xlink:href="https://www.wireshark.org">.Wireshark</link>) attacks. In a professional setup you will have to configure <xref linkend="glo_TLS"/> for encrypting your communication channel.</para> </note> </section> <section xml:id="sdiSectLdapByJava"> <title>Accessing <xref linkend="glo_LDAP"/> by a <xref linkend="glo_Java"/> application.</title> <para>Accessing <xref linkend="glo_LDAP"/> requires a suitable client component. A standard <xref linkend="glo_JDK"/> or <xref linkend="glo_JRE"/> ships with a <acronym xlink:href="https://docs.oracle.com/javase/7/docs/technotes/guides/jndi/jndi-ldap.html">JNDI</acronym> provider. The <xref linkend="glo_API"/> however requires a lot of boilerplate code.</para> <para><orgname xlink:href="http://www.ldaptive.org">Ldaptive</orgname> offers a promising client provider <xref linkend="glo_API"/>. Start a <xref linkend="glo_Maven"/> based <xref linkend="glo_Soft_Eclipse"/> project which reads your own HdM <xref linkend="glo_LDAP"/> data being provided by the MI replica server <code>ldap1.mi.hdm-stuttgart.de</code>.</para> <para>This server allows for retrieving all attributes belonging to your personal records. Thus an authenticated bind using your HdM credentials is mandatory. Use <xref linkend="glo_TLS"/> to prevent password sniffing!</para> <tip> <itemizedlist> <listitem> <para>Read the <link xlink:href="http://www.ldaptive.org/#quick-start-guide">quick start guide</link> and consult the <link xlink:href="http://www.ldaptive.org/javadocs">Ldaptive API</link>.</para> </listitem> <listitem> <para>Using <orgname xlink:href="http://www.ldaptive.org">Ldaptive</orgname> may be accomplished by adding the following <xref linkend="glo_Maven"/> dependencies to your project's <filename>pom.xml</filename> file:</para> <programlisting language="xml"><dependencies> <dependency> <groupId>org.ldaptive</groupId> <artifactId>ldaptive</artifactId> <version>1.1.0</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.21</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.7.21</version> </dependency> </dependencies></programlisting> </listitem> </itemizedlist> </tip> <para>The idea is reading your own <xref linkend="glo_LDAP"/> entry and write the corresponding attributes according to the following rules:</para> <itemizedlist> <listitem> <para>If an attribute is of binary type just output its name omitting the value(s).</para> <tip> <para><classname xlink:href="http://www.ldaptive.org/javadocs/org/ldaptive/LdapAttribute.html">LdapAttribute</classname>.<methodname xlink:href="http://www.ldaptive.org/javadocs/org/ldaptive/LdapAttribute.html#isBinary()">isBinary()</methodname> is your friend.</para> </tip> </listitem> <listitem> <para>If an attribute is single valued write its name and value to standard output.</para> <tip> <para>Read <classname xlink:href="http://www.ldaptive.org/javadocs/org/ldaptive/LdapAttribute.html">LdapAttribute</classname>.<methodname xlink:href="http://www.ldaptive.org/javadocs/org/ldaptive/LdapAttribute.html#getName()">getName()</methodname>, <classname xlink:href="http://www.ldaptive.org/javadocs/org/ldaptive/LdapAttribute.html">LdapAttribute</classname>.<methodname xlink:href="http://www.ldaptive.org/javadocs/org/ldaptive/LdapAttribute.html#size()">size()</methodname>and <classname xlink:href="http://www.ldaptive.org/javadocs/org/ldaptive/LdapAttribute.html">LdapAttribute</classname>.<methodname xlink:href="http://www.ldaptive.org/javadocs/org/ldaptive/LdapAttribute.html#getStringValue()">getStringValue()</methodname>.</para> </tip> </listitem> <listitem> <para>If an attribute is multivalued write its name and all values among with a corresponding index to standard output.</para> <tip> <para>Read <classname xlink:href="http://www.ldaptive.org/javadocs/org/ldaptive/LdapAttribute.html">LdapAttribute</classname>.<methodname xlink:href="http://www.ldaptive.org/javadocs/org/ldaptive/LdapAttribute.html#getStringValues()">getStringValues()</methodname> .</para> </tip> </listitem> </itemizedlist> <para>If your <xref linkend="glo_DN"/> was <code>uid=mistudent, ou=userlist, dc=hdm-stuttgart, dc=de</code> the result should look like:</para> <programlisting language="none">mail: mistudent@mi.hdm-stuttgart.de gidNumber: 31104 cn: MI Negative Testuser objectClass[0]: posixAccount objectClass[1]: hdmSambaDomain objectClass[2]: hdmAccount objectClass[3]: hdmStudent objectClass[4]: inetOrgPerson objectClass[5]: eduPerson objectClass[6]: shadowAccount loginShell: /bin/sh <emphasis role="bold">Not displaying value of binary attribute</emphasis> 'userPassword' hdmCategory: 1 uid: mistudent uidNumber: 32669 shadowLastChange: 16749 homeDirectory: /home/stud/MI/mistudent sambaNTPassword: C1E13066AA936CBF9260913EE962B8C2 sn: Testuser matrikelNr: 98911</programlisting> <para>Solution available at:</para> <annotation role="make"> <para role="eclipse">Sdi/ReadMyData</para> </annotation> <para>Notice: The above project will read the required password from a <package>de.hdm_stuttgart.mi.sdai.readmydata.messages.properties</package> file corresponding to <filename>src/main/java/de/hdm_stuttgart/mi/sdai/readmydata/messages.properties</filename>. Due to password protection this file has been excluded from versioning. You will however find <filename>messages.properties.template</filename> next to the intended location containing the appropriate property key name. Using your own account data should enable you running the application.</para> <caution> <para>Do not miss changing the value of <code>ReadMyLdap.bindDn</code>!</para> </caution> </section> </section> </chapter>