Presentation is loading. Please wait.

Presentation is loading. Please wait.

Making Productive Use of OpenLDAP Presented to the CALUG by John Unekis August 11,2004.

Similar presentations


Presentation on theme: "Making Productive Use of OpenLDAP Presented to the CALUG by John Unekis August 11,2004."— Presentation transcript:

1 Making Productive Use of OpenLDAP Presented to the CALUG by John Unekis August 11,2004

2 What Is OpenLDAP? - LDAP is the Lightweight Directory Access Protocol - Core LDAP Specification * RFC-2251 Lightweight Directory Access Protocol (v3) * RFC-2252 LDAPv3 Attribute Syntax Definitions * RFC-2253 UTF-8 String Representation of Distinguished Names * RFC-2254 The String Representation of LDAP Search Filters * RFC-2255 The LDAP URL Format * RFC-2256 A Summary of the X.500(96) User Schema for use with LDAPv3 - OpenLDAP is an open source implementation of LDAP

3 What Does OpenLDAP Do? Internet Linux xinetd Port 389 Port 80 etc. httpd slapd Some Sorta Data It makes data available over the web on port 389 using a standard query syntax

4 Where do I get OpenLDAP? - For Redhat, Fedora, and Suse openldap comes bundled as an RPM - For Debian, it comes as a.deb file - For Slackware, it is bundled as a.tgz file - You can also “do it” from source, obtained from http://www.openldap.org

5 What Do I Do With OpenLDAP? - Present data such as email addresses, passwords, photos - Make them available as a sort of “web service” - Information becomes available on port 389 (636 if encrypted) - Standard defines a syntax for queries - Most browsers used to support this syntax

6 What Data Can OpenLDAP Handle? - The default (under Fedora) is a GDBM database - You can also map your /etc/passwd file, or a MySQL DB - There are a series of include files that define the data objects include /usr/local/etc/openldap/schema/core.schema include /usr/local/etc/openldap/schema/cosine.schema include /usr/local/etc/openldap/schema/inetorgperson.schema include /usr/local/etc/openldap/schema/nis.schema include /usr/local/etc/openldap/schema/nisdomainobject.schema - Most are personnel oriented – email, phone, address, etc. - You can also embed pointers to files – photos, documents, etc.

7 What Kind of Apps Use OpenLDAP? - The most typical use is email directories - Outlook, Netscape, all the usual mail programs recognize LDAP directories - Cell phones can also access phone numbers from an LDAP directory - LDAP can be used for centralized authentication (see articles) http://www.linuxjournal.com/article.php?sid=6789 http://www.linuxjournal.com/article.php?sid=6876 http://www.linuxjournal.com/article.php?sid=6936 or http://www.mandrakesecure.net/en/docs/ldap-auth.php - You can also integrate custom applications - For example, a guard views an employee ID, and types the name into a web page, the page calls a CGI program which does an LDAP query, and retrieves the employees picture file, the picture is displayed so the guard can verify the employees identity.

8 So How Do We Set It Up? - First, of course, install the package(s) for your distribution i.e. rpm -Uvh openldap-*-2.2.15.i386.rpm (you may need support like cyrus-sasl and glibc) - If you use iptables, make sure to open port 389 (636 for ldaps) iptables -A INPUT -s 198.168.0.0 -p tcp --destination-port 389 -j ACCEPT iptables -A INPUT -s 198.168.0.0 -p udp --destination-port 389 -j ACCEPT - If your site has a firewall, open port 389 to your box - Configure /etc/openldap/slapd.conf - Build an initial data base - Start the service slapd on your machine

9 What's in /etc/openldap/slapd.conf (1)? # Sample access control policy: #Root DSE: allow anyone to read it #Subschema (sub)entry DSE: allow anyone to read it #Other DSEs: #Allow self write access #Allow authenticated users read access #Allow anonymous users to authenticate #Directives needed to implement policy: # access to dn.base="" by * read # access to dn.base="cn=Subschema" by * read # access to * #by self write #by users read #by anonymous auth # # if no access controls are present, the default policy is: #Allow read by all # # rootdn can always write!

10 # include/etc/openldap/schema/core.schema include/etc/openldap/schema/cosine.schema include/etc/openldap/schema/inetorgperson.schema include/etc/openldap/schema/nis.schema include/etc/openldap/schema/redhat/autofs.schema What's in /etc/openldap/slapd.conf (2)? The schemas: -The schemas define a series of tags that identify data elements and syntax - Records in the DB work like a “Christmas tree” First you build the base (tags like “C”, “DC”, “O”, and “OU”) then the branches (the individual “DN” or distinguished names) then hang the ornaments (tags like “address”, “title”, “mail” )

11 What's in /etc/openldap/slapd.conf (3)? One Example dc=com dc=mydomain o=mycompany ou=accounting ou=security cn=Bob Smith cn=Geraldine Jones Another Example c=US o=US Government ou=USITC ou=accounting ou=security cn=Bob Smith cn=Geraldine Jones ou=DOJ

12 What's in /etc/openldap/slapd.conf (4)? ####################################################################### # ldbm and/or bdb database definitions ####################################################################### databaseldbm suffix"dc=my-domain,dc=com" rootdn"cn=Manager,dc=my-domain,dc=com" # Cleartext passwords, especially for the rootdn, should # be avoided. See slappasswd(8) and slapd.conf(5) for details. # Use of strong authentication encouraged. # rootpwsecret # rootpw{crypt}ijFYNcSNctBYg # The database directory MUST exist prior to running slapd AND # should only be accessible by the slapd and slap tools. # Mode 700 recommended. directory/var/lib/ldap # Indices to maintain for this database index objectClass eq,pres index ou,cn,mail,surname,givenname eq,pres,sub index uidNumber,gidNumber,loginShell eq,pres index uid,memberUid eq,pres,sub index nisMapName,nisMapEntry eq,pres,sub The objectClass for a person is an inetorgPerson

13 What's in /etc/openldap/slapd.conf (5)? # Replicas of this database #replogfile /var/lib/ldap/openldap-master-replog #replica host=ldap-1.example.com:389 tls=yes # bindmethod=sasl saslmech=GSSAPI # authcId=host/ldap-master.example.com@EXAMPLE.COM You could make your LDAP server sych/duplicate another server One possible reason to do this would be to have local copies of the authentication server at remote sites

14 What's in /etc/openldap/lapd.conf ? - This is the config file for client commands on your box. - If you want local ldap transactions to be performed against a different computer, put the hostname in this file - There is also a timeout value in here which is useful to set to avoid accidental lockups on queries

15 Building The Initial Database - Data is provided to the LDAP database in LDIF format rfc 2849 documents the format and fields - OpenLDAP is obnoxiously unforgiving of syntax errors - Error messages are sparse and cryptic, if you get them - On your first couple of tries, watch for the initial build to hang - For the intial build, there are two ingest routines slapadd runs with the slapd server off (recommended) ldapadd runs with through the server slapd

16 dn: o=U.S. Government, c=US o: International Trade Commission objectclass: top objectclass: organization dn: ou=International Trade Commission, o=U.S. Government, c=US ou: International Trade Commission objectclass: top objectclass: organizationalUnit dn: ou=Department of Energy, o=U.S. Government, c=US ou: Department of Energy objectclass: top objectclass: organizationalUnit dn: OU=Headquarters, OU=Department of Energy, ou=Department of Energy, o=U.S. Government, c=US ou: Headquarters objectclass: top objectclass: organizationalUnit Building The Base This was part of the base of “directory.gov”

17 Another Example of a Base dn: o=stooges objectClass: top objectClass: organization o: stooges description: The Three Stooges dn: cn=StoogeAdmin,o=stooges objectClass: organizationalRole cn: StoogeAdmin description: LDAP Directory Administrator dn: ou=MemberGroupA,o=stooges ou: MemberGroupA objectClass: top objectClass: organizationalUnit description: Members of MemberGroupA dn: ou=MemberGroupB,o=stooges ou: MemberGroupB objectClass: top objectClass: organizationalUnit description: Members of MemberGroupB From the website http://www.yolinux.com/TUTORIALS/LinuxTutorialLDAP.html

18 - The most efficient way is to add records with the slapd service turned off slapadd -l -f - This can also be done with the service running ldapadd -f entries.ldif -x -D "cn=Manager,dc=example,dc=com" -w secret - The -c option to continue in case of a syntax error is highly recommended - The LDIF format is unusual, it makes use of tags, but is also position sensitive - Each line begins with a tag, then a full colon, then ONE space, then data - A space in column one denotes a continuation of the previous line - Tabs are verbotten, and be very careful about hygeine errors like alphas in numeric fields Putting Data in the File

19 Adding the Data Records - LDAP files are typically used to store information on people - The LDIF schemas give a lot of useful data elements - Each LDIF record begins with a unique “distinguished name” usually a “common name” + the organization string i.e. dn: cn=Shemp howard, ou=MemberGroupB,o=stooges - This is followed by several data elements, some mandatory LDIF record requires: * objectClass: organizationalPerson * objectClass: person (Inherited from object organizationalPerson) * objectClass: top (Inherited from object person) * sn (Surename/Last Name - Inherited from object person) * cn (Common Name - Inherited from object person)

20 LDIF Data Elements An LDIF record may have : * o (Organization Name) * displayName (RFC2798: Preferred name of a person to be used when displaying entries) * audio * businessCategory * carLicense * departmentNumber * employeeNumber * employeeType (i.e. "Contractor", "Employee", "Intern", "Temp", "External", "Unknown", etc...) * givenName * homePhone * homePostalAddress (After street number and name use line separator "$" in LDIF file: street$ st postalCode) * initials (MS/Outlook considers this to be the middle name) * jpegPhoto (See the OpenLDAP FAQ: Turn a jpeg into ldif format) * labeledURI * mail (e-Mail address) * manager (Specify dn entry of manager) * mobile * pager * photo * roomNumber * secretary (Specify dn entry of secretary) * uid * userCertificate * x500uniqueIdentifier * preferredLanguage * userSMIMECertificate (RFC2633: A PKCS#7 [RFC2315] SignedData) * userPKCS12 (PKCS #12 [PKCS12] provides a format for exchange of personal identity information.)

21 LDIF Data Elements (cont'd) Also optional: # Attributes inherited from object organizationalPerson: * ou (Organization unit) * title * x121Address * registeredAddress * destinationIndicator * preferredDeliveryMethod * telexNumber * teletexTerminalIdentifier * telephoneNumber (MS/Outlook considers this to be the "Business Phone") * internationaliSDNNumber * facsimileTelephoneNumber * postOfficeBox * postalAddress (MS/Outlook and Netscape both use this for the business address.) * physicalDeliveryOfficeName (MS/Outlook considers this to be the field "Office") * street (Don't use "street" because Netscape can't use it. Use "postalAddress".) * l (Locality/City/Town) * st (State/Province) * postalCode (Zip code) # Attributes inherited from object person: * userPassword * telephoneNumber (work phone) * seeAlso (URL for more info) * description

22 Example of Directory.Gov Records dn: cn=John Unekis,ou=Directors Office,ou=Information Services,ou=Operations,ou=International Trade Commission, o=U.S. Government, c=US mail: junekis@usitc.gov givenname: John sn: Unekis telephoneNumber: (202) 555-3189 title: Sr. IT Project Manager cn: John Unekis dn: cn=Kristin Krake,ou=Directors Office,ou=Information Services,ou=Operations,ou=International Trade Commission, o=U.S. Government, c=US mail: krake@usitc.gov givenname: Kristin sn: Krake telephoneNumber: (202) 555-2744 title: Management Analyst 412-G cn: Kristin Krake dn: cn=Kue Lin,ou=Directors Office,ou=Information Services,ou=Operations,ou=International Trade Commission, o=U.S. Government, c=US mail: klin@usitc.gov givenname: Kue sn: Lin telephoneNumber: title: Contractor cn: Kue Lin (remember: data records are added with either slapadd or ldapadd)

23 Starting the slapd Service - Under Redhat/Fedora, you could use the chkconfig command chkconfig –level 345 slapd on service will then be active at each of those runlevels - Individual start/stop/restart operations could use the init script /etc/init.d/rc.d/slapd [start/stop/restart]

24 Accessing the LDAP Data - If your LDAP directory is an email directory most readers will accept it - Authentication services with LDAP require an LDAP-capable client - Supposedly ActiveDirectory will recognize LDAP (the author has not tried) - For looking up general data, the ldap protocol works on most browsers i.e. ldap://208.188.34.109/cn=Larry Anderson,ou=MemberGroupA,o=stooges See http://www.cis.ohio-state.edu/cgi-bin/rfc/rfc2255.html for URL formathttp://www.cis.ohio-state.edu/cgi-bin/rfc/rfc2255.html - The ldapsearch command also works either locally, or with the -h option to a remote host, this allows ldap queries to be used in scripts or “c” programs ldapsearch -h "ldap.domain-name" -L -b "o=domain-name" "(sn=Anderson)" - Cgi-bin or tomcat java applets can be used to create interactive websites

25 Accessing OpenLDAP on a Website User enters search data into HTML form HTML form invokes cgi-bin program, sends data as stdin Cgi-bin program does LDAP lookup Cgi-bin program uses stdout to send HTML with search results back to user With CGI-BIN User enters search data into HTML form Tomcat invokes Java program, sends data as stdin Java program does LDAP lookup Java program uses stdout to send HTML with search results back to user With Java/Tomcat Tomcat invokes Java server-side program to generate HTML form as stdout

26 Front Page From Former Directory.gov Website Java source code attached as appendix

27 Updating/Modifying/Deleting Records - The LDIF format can have a “changetype:” field in the record which allows add/modify/delete - Combine “changetype: modify” with a “replace: tag”and “tag: value” to replace an existing value - Every change record requires a unique DN: i.e. dn: cn=Shemp howard, ou=MemberGroupB,o=stooges changetype: delete or dn: cn=Shemp howard, ou=MemberGroupB,o=stooges changetype: modify replace: mail mail: newemail@mail.com - One technique is to batch the changes in an LDIF file - Use ldapmodify to run the changes

28 A Few Words on Performance - The default database under Fedora/Redhat is GDBM - GDBM is a modest performance simple relational DB - A 1.2GHz CPU, 384MB memory, 3x8GB SCSI-2 drives in RAID 5 gave: ~3 record insertions/second ~10 lookups/second - To increase performance you could: Add RAM and increase the buffer size on the DB Partition the DB across multiple drives Try a RamDisk

29 Useful Resources http://www.yolinux.com/TUTORIALS/LinuxTutorialaWebDap.html

30 Useful Resources http://www.webalizer.org

31 Useful Resources http://www.openldap.org http://www.umich.edu/~dirsvcs/ldap/doc/guides/slapd/ http://www.rudedog.org/auth_ldap/1.4/auth_ldap.html http://www.iit.edu/~gawojar/ldap/

32 Java Code that Ran Directory.gov under Tomcat U.S. Federal White Pages Directory TOP LEVEL Welcome to the Federal White Pages <% // this is commented out. To uncomment, remove the line above, the leading slases, and the second line below // New! Now you can add info to your own White Pages entry! Register to get a password. Then you can edit your info. %> <% // New! // We are wireless!! Bookmark "directory.gov" on your cell phone to find & dial phone numbers from anywhere! %> Use this free service to find e-mail addresses or phone numbers of Federal employees in 22 Departments & agencies Warning! Questions? Problems? Privacy Stats Who We Are Appendix – Source code from Directory.gov jsp files

33 <%Attributes attribs = null; NamingEnumeration names = null; NamingEnumeration ne = null; DirContext dctx = null; Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, "ldap://localhost:389/o=U.S. Government,c=US"); env.put("java.naming.security.authentication", "none"); env.put("java.naming.ldap.version", "3"); SearchControls ctls = new SearchControls(); String[] returnAttrs = {"cn", "mail", "telephoneNumber", "title", "labeleduri", "pager", "description", "mobile", "facsimiletelephonenumber"}; String[] returnNothing = {}; ctls.setReturningAttributes(returnAttrs); String max; // Set maximum items returned from a search if (request.getParameter("max") != null ) max = request.getParameter("max"); else max = "200"; if (max.equals("")) max = "200"; if (Integer.valueOf(max).intValue() > 1000) max = "1000"; ctls.setCountLimit(Integer.valueOf(max).longValue()); String context; String separator = ""; if (request.getParameter("context") != null) context = request.getParameter("context"); else context = ""; if (context.equals("")) separator = "" ; else separator = ", "; SearchResult item; Attribute mail, phone, title; NamingEnumeration attrvals; String pstring, tstring, namestring, ns, ns2, nsfixed, sc; String href = ""; String actualfilter = ""; int ins = 0; //set the search filter if it's provided in the request String filter = "(|(CN=*)(OU=*))"; if (request.getParameter("filter") != null && ((String)request.getParameter("filter")).trim() != "") filter = request.getParameter("filter"); //set the simple name search values if provided in the request String cnvals = ""; if (request.getParameter("cnvals") != null ) cnvals = request.getParameter("cnvals"); //Combine info in filter and cnvals into "actualfilter" for actual search filter if (cnvals.equals("")) actualfilter = filter; else { java.util.StringTokenizer st = new java.util.StringTokenizer(cnvals); actualfilter = "(&" + filter ; while (st.hasMoreTokens()) { actualfilter = actualfilter + "(cn=*" + st.nextToken() + "*) "; } actualfilter = actualfilter + ")"; }

34 //Decide whether to use subtree or one-level search String scope = "ONELEVEL_SCOPE"; if (request.getParameter("scope") != null) scope = request.getParameter("scope"); if (scope.equals("ONELEVEL_SCOPE")) ctls.setSearchScope(SearchControls.ONELEVEL_SCOPE); else if (scope.equals("SUBTREE_SCOPE")) ctls.setSearchScope(SearchControls.SUBTREE_SCOPE); else if (cnvals.equals("")) ctls.setSearchScope(SearchControls.ONELEVEL_SCOPE); else ctls.setSearchScope(SearchControls.SUBTREE_SCOPE); //See if children are wanted String children = "N"; if ((request.getParameter("children") != null) && (request.getParameter("children").equals("Y")) ) children = "Y"; try { dctx = new InitialDirContext(env); names = (NamingEnumeration)dctx.search(context, actualfilter, ctls); ctls.setSearchScope(SearchControls.ONELEVEL_SCOPE); ctls.setReturningAttributes(returnNothing); try { if ((names != null) && names.hasMore()) { int i=0; %> Find "> "> example: " beth ander " will find "Elizabeth Anderson", "Beth Sanderson" and "Elizabeth VanderPutten" List of Directory Entries in this Context Name--Click to drill down Title Phone E-Mail / Web <% while (names.hasMore()) { i++; item = (SearchResult)names.next(); if (item.getName().equals("ou=Agencies")) {i = i-1; continue; } attribs = item.getAttributes(); ns = ((String)item.getName()).replace('"',' ').trim(); ns2 = ns; // find location of "/" (an int) ; concat before ss + '\' + rest; loop sc = "/"; ins = ns.indexOf(sc, 0); while (ins > -1) { nsfixed = ns.substring(0, ins) + "\\" + ns.substring(ins); // out.println("nsfixed=" + nsfixed + ": ns=" + ns); ns = nsfixed; ins = ns.indexOf(sc, ins + 2); }

35 try { if ( ns.toUpperCase().startsWith("OU=") ) { href = "wpv2beta1.jsp?context=" + java.net.URLEncoder.encode(ns + separator + context) + "&scope=ONELEVEL_SCOPE" ; namestring = ns2; if (children.equals("Y")) { namestring = namestring + " (Entries at next level: "; int ii = 0; try { // getting count of items under an item ne = dctx.search(ns + separator + context, "(|(CN=*)(OU=*))", ctls ); while (ne.hasMore()) {ii++; ne.next();} } catch (SizeLimitExceededException sle) {namestring = namestring + " over "; } catch (NamingException nee) {out.println("exception at count:" + nee);} namestring = namestring + " " + String.valueOf(ii) + ")"; } else {href="wpv2beta1_detail.jsp?context=" + java.net.URLEncoder.encode(ns + separator + context); namestring = (String)(attribs.get("CN").getAll().next()); } } catch (Exception eek) { namestring = "Error"; //out.println("Exception in href processing. " + eek); } %> "> <%pstring = " "; try { title = attribs.get("title"); attrvals = title.getAll(); while (attrvals.hasMore()) pstring = pstring + " " + attrvals.next(); } catch (Exception e) { } %> <%pstring = " "; try { phone = attribs.get("telephonenumber"); attrvals = phone.getAll(); while (attrvals.hasMore()) pstring = pstring + " " + attrvals.next() + " "; } catch (Exception e) { } try { phone = attribs.get("facsimiletelephonenumber"); attrvals = phone.getAll(); while (attrvals.hasMore()) pstring = pstring + " FAX: " + attrvals.next() + " "; } catch (Exception e) { } try { phone = attribs.get("mobile"); attrvals = phone.getAll(); while (attrvals.hasMore()) pstring = pstring + " Mobile: " + attrvals.next() + " "; } catch (Exception e) { } %>

36 <% pstring = " "; try { mail = attribs.get("mail"); attrvals = mail.getAll(); while (attrvals.hasMore()) { tstring = (String)attrvals.next(); pstring = pstring + " " + tstring + " ";} } catch (Exception e) { } try { mail = attribs.get("labeleduri"); attrvals = mail.getAll(); while (attrvals.hasMore()) { tstring = (String)attrvals.next(); pstring = pstring + " URL: <A HREF=" + tstring.substring(0,tstring.indexOf(" ")) + ">" + tstring.substring(tstring.indexOf(" ")) + " ";} } catch (Exception e) { } %> <% } // End while clause } // End if clause else { href="wpv2beta1_detail.jsp?context=" + java.net.URLEncoder.encode(context); out.println("No subordinate items in context " + context + ". Click to view item attributes."); } // End else clause } // End try catch (SizeLimitExceededException es) { out.println(" NOTE: Number of items found exceeded search size limit. ");} catch (NamingException e) { out.println("Another darn Naming error: " + e); } // End catch NamingException catch (Exception ex) { out.println("Another darn General error: " + ex); } // End catch general exception dctx.close(); } // end try catch (Exception e) { System.out.println("No person objects found in " + context); } %> This search used: scope=, filter=, directory context=" ". Basic Search Part of directory to search (blank=entire directory) "> Names or parts of name to search for:(example: "beth anders") "> Advanced Search Options Search filter Examples "> <% // UserID (not used) // This is commented out // Password (not used) %>

37 Search scope Default Entire subtree Single level Show number of entries below each item (can be VERY slow!)? No Yes Maximum items to be retrieved (there's a max of 1,000 anyhow, since more than that will blow out your browser.) <input type="text" name="max" size=4 value="200">,

38 U.S. Federal White Pages Directory--Entry Detail Please report problems with this service. HOME Welcome to the Federal White Pages New! We are wireless!! Bookmark "directory.gov" on your cell phone to find & dial phone numbers from anywhere! <% Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, "ldap://localhost:389/o=U.S. Government,c=US"); env.put("java.naming.security.authentication", "none"); // env.put("java.naming.security.principal", "cn=manager"); // env.put("java.naming.security.credentials", "secret"); env.put("java.naming.ldap.version", "3"); DirContext dctx = null; String context = "ou=Agencies"; BasicAttributes ats; NamingEnumeration attribs = null; BasicAttribute at; NamingEnumeration attrvals; String pstring; if (request.getParameter("context") != null) context = request.getParameter("context"); try { dctx = new InitialDirContext(env); ats = (BasicAttributes)dctx.getAttributes(context); attribs = ats.getAll(); %>

39 Details for This Directory Entry: Attribute Value(s) Entry name (RDN) <%while (attribs.hasMore()) { at = (BasicAttribute)attribs.next(); %> <% pstring = ""; try { attrvals = at.getAll(); if (attrvals.hasMore()) pstring = (String)attrvals.next(); while (attrvals.hasMore()) pstring = pstring + " " + attrvals.next(); } catch (Exception e) { out.println("Barfing on value in " + at.getID() + e); } %> <% } // End while clause %>, <% dctx.close(); } // End try catch (NamingException e) { out.println("Another darn Naming error: " + e); } // End catch NamingException catch (Exception ex) { out.println("Another darn General error: " + ex); } // End catch general exception %>

40


Download ppt "Making Productive Use of OpenLDAP Presented to the CALUG by John Unekis August 11,2004."

Similar presentations


Ads by Google