objectClasses are like classes/types. An objectClass definition is like a class or type definition. ou's are like table key columns. You can have lots of different key table columns with the same type. Records starting with ou= are really like table definitions. (The records list the objectClasses of this ou). [This is just conventional, "ou" really stands for Organizational Unit] other records are like key column values. These set real values in a data record. They either start with cn= (which is repeated below), or with some other var= which is repeated below*, and cn= is also below with the same exact value. (It's like "var" is an alias for "cn"). The record can list objectClasses which modify the base type of the objectClass. (i.e. the class of the cn record is really the ou objectClasses + the cn objectClasses). * This first element of the dn is the "RDN", Relative Distinguished Name. Command-line programs are ldapsearch, ldapadd, etc. Arguments are very different between Linux and Solaris. Linux man pages have examples (Wow. What a treat!) N.b.: "-h hostname" deprecated in favor of "-H ldap://uri" on Linux (but Solaris has only -h). (specifically on Solaris: "simple" is default auth method (no -x switch), Ldif is -L not -LL, no -H, -W is default. There is no file comparable to ldap.conf, so I have no idea how to set defaults for -b, -h, etc.). In Linux man pages, they put () around the "filter". Seems to be unnecessary for both Linux and Solaris. The server-side config file is /etc/openldap/slapd.conf. Uses standard ldap and ldaps port by default (389 and 636). Have to permit through hosts.allow (on Linux anyways). If using no SASL, then you have to give the -x switch for all of the command-line client commands. (But that's the default for Solaris). Hm, seems to not be so. If you specify no -D, then access is via "anonymous" without authenticating. To access as the root user, give the rootdn (from slapd.conf) as -D, and give the password as "-w password" or -W for interactive. On Linux, must give -x for anonymous access. I.e. must either -x or -D. (Another way of accessing anonymously is by giving -D and password as null: -D '' -w '') "Users" are created with records like the following ldif. you give the dn of these users as the final -D arg of the command line utilities (and as the user to ldappasswd). If you authenticate as one of these users, then you qualify as a "user" in the "access... by... users" blocks in slapd.conf. dn: cn=Brian,dc=admc,dc=com cn: Brian sn: Brian objectclass: top objectclass: person Encrypted passwords for entry into slapd.conf can be obtained by running ldappasswd and telling it the desired format, like slappasswd -h '{MD5}' slappasswd -h '{CRYPT}' This is definitely not a requirement, but it seems that the convention is a dn consists of the main cn (which is repeated below in the ldif) plus a possible ou and dc's. Every record has at least one "objectClass" which I guess specifies the allowable and/or required attributes. (As I said, one "attribute" is always the main cn of the dn). UNIX AUTHENTICATION VIA LDAP Does not use Pam. Uses NIS through the system calls. Set up via nsswitch.conf. ou's: ou objectClass --------- ------------ People.* top, organizationalUnit Group.* top, organizationalUnit Hosts.* top, organizationalUnit (where .* is .domain.name) LDAP is a lightweight version of ISO X.500's DAP (Directory Access Protocol). DAP is heaveyweight and does not run on TCP/IP. Inappropriate for frequently-written data, large records, unstructured objects (such as images). (could store URL's though). In general, "master" the data (write it) from only one server-side location (whether though LDAP or not). Can not "search" based on dn's. Can only search for attributes in an entry. (This is why there is an attribute equivalent to the RDN). The traditional RDN for "People" was "cn=Full Name". Due to name collisions, now it is normally uid (login ID or emp. no.), mail (unfortunately usually the domain is redundant), or employeeNumber (if an inetOrgPerson object class). Preferable if "readable". GROUPS are like filesystem directories containing sym links. Normally located under the ou=Groups branch. Disadvantage is the difficulty of finding all the groups of which X is a member. STATIC GROUPS. grouPfNames of groupOfUniqueNames object classes. For < 20,000 members member or uniqueMember attributes contain DN of each member. DYNAMIC GROUPS. groupOfUrls object class. memberURL attributes are LDAP URL filters. ROLES. Specified by the member entries, not the group entries (like GROUPS). nsRoleDN "virtual" attribute of members identifies the role's DN. It is not stored in the directory but is generated on-the-fly by the server. But clients read it like a normal attribute. MANAGED ROLES The role entry just determines the scope of possible members to be at the peer level or lower. FILTERED ROLES Exactly like managed roles from members' perspective. The role entry just like MANAGED ROLE, but has filters. NESTED ROLE A role entry that "includes" other roles CoS, CLASS OF SERVICE. Attribute value references. Pseudo-attributes. CoS definition entry. Location determines scope just like a role entry (peer level or lower). Names att + rule for geneating value. POINTER CoS Just points to a template entry for value. INDIRECT CoS Template entry and att within it determined dynamically. CLASSIC CoS Specifies template and specifier att. Templates are always of object class cosTemplate and can be kept right alongside the def entry. "Schema checking" determines if target entries can prohibit the Cos attribute. CoS template entries. The definition entry uses these to generate values. IPLANET When I installed it, I got the Solaris clients to work. Now I can't get them to do a damned thing other than saying "ldap_search: No such object". 389 is default ldap port, 636 is ldaps port (but I see that by default it does not run on ldaps). (need hosts.allow?) The "Administration Server" is an independent server for Admnistering any of the iPlanet server products. The "Console" is the GUI interface to the Admin Server. There are product-specific "parts" of the Console, like the iPlanet Directory Server Console. "Directory Manager DN" default is "cn=Directory Manager". Does not have to conform to your sufix. (Formerly the "root DN") "Configuration Directory Administrator". Who uses the iPlanet console. (install program calls it "administrator ID for config dir svr"). dflt "console" "Administration Server User" is for use when iPlanet is dead. Usually same user and password as CDA account. CONFIGURATION DIRECTORY o=NetscapeRoot tree stores cfg info for all kinds of iPlanet servers. All of your iPlanet servers can store their cfgs into one Dir Server's NR tree. Docs are ambiguous, but I _think_ I can run normal Dir svr as non-root on port 389 (default) as long as the Admin Server is run as root. Admin domain is for administrative groupings. (I'm not going to test) MY TEST SETTINGS Dir Svr instance: dsinst1 Config Dir Admin: console / losung1 (for iPlanet console) Dir Manager dn: cn=Directory Manager / shackboys "idsconfig" program for managing LDAP naming services. (in SUNWnisu) Setting admin port to 26080 Aegir LDAP cert keys password: flyri5ht WINDOWS iPLANET lapsearch -b dc=nextel,dc=com -h localhost objectclass=person AND lapsearch -b dc=nextel,dc=com -h mindbank-bsimpson cn=jan Directory Manager Settings: 'cn=Directory Manager' / adminadmin. Port 1000. (simba, ditto running slapd, none run ldaps. Simba isn't working for me.) ldapsearch -b dc=nextel,dc=com -h ditto objectclass=person Good Java Gui LDAP Browser: http://www.iit.edu/~gawojar/ldap/ (Their shell script sucks. Use my modified version.) Mon Sep 5 18:12:14 EDT 2005. From SUSE 9.3 Admin Guide. Object = single entry. (Either a container or a leaf). Attributes: Either "MUST" or "MAY". In the example below, the class "organizationalUnit" has a required attribute "ou". Object Class: Every object has class(es), including containers. I *guess* all objects ona single level must have the same classes? NO DIT = Directory Information Tree. Entire object map. DN = Distinguished Name = Unambiguous, complete path to an object. (RDN is just a non-absolute path segment). The first DN element (RDN) must be duplicated (name & val) in an attribute. The RDN can be any attribute, MAY or MUST, of a listed objectClass. Sample DN: cn=Geeko Linux,ou=doc,dc=suse,dc=de No reason to duplicate it here. The Admin Guide is pretty succinct about LDAP server. Goes from lowest level to highest level, but one level can have multiple atts. Schema: Specifications of classes. I don't understand it, but "rootdn" is the root Admin. He has an object path in slapd.conf, but he "does not need to have an LDAP entry" or exist as a regular user... then why does he have a "DN"? SERVER CONTROL /etc/init.d/ldap {start|stop|status} (N.b., rcldap is just a sym-link to same). To set the -H listener URLS, set env vars in /etc/sysconfig/openldap, like OPENLDAP_START_LDAPS=yes N.b.: NOT /etc/sysconfig/ldap!!!!!!!!! Also n.b., move the SLAPD_URLS setting below the "... . ... openldap" line if you don't want to serve the default URL in addition to what you spec. You can then set your base SLAPD_URLS in "openldap" (like "SLAPD_URLS="). LDIF I *guess* it lists the DN first, then lists classes not in the DN, then attributes of the additional classes. When you log into an LDAP server, you "bind" to it with your DN... I guess. This is the -D switch (for the most common utilities). ldapsearch. Outputs queries in LDIF format. Defaults in /etc/openldap/ldap.conf. Switches: ldapsearch -switches ['&((query=x)(query=y)'] [att1 [att2]...] Query defaults to '(objectClass=*)', which gives you everything. Att list defaults to *. (anything): the search -D: same as above -x: simple (non-encrypted, non-SASL) authent ("simple bind" I think) -W: interactively query for password for simple auth -w passwd -H hosturi -p port -b: search BASE. Search only below this point of the DIT. (This probably requires a DN value). Overrides default in /etc/ldap.conf. (On Linux ldap.conf has no dflt) Hm, does it truncate items above this level from output and query string values? -L: output in old (v1) LDIF format -LL: don't display comments -LLL: only display the data -U/R/X arg: SASL options -ZZ: Use StartTLS -Z: Try to use StartTLS, but proceed without if it don't work N.b., -b stands for "Base", not bind (the later is the login -D DN). Host URIs: Has good defaults for missing items. May use hostnames or IP adrs. Default protocols and ports are ldap://,ldaps:// and :389,:636 correspondingly. ldaps = SASL LDAP. I think rootdn is complete bullshit and isn't a DN at all. GOTCHA: You must restrict searches to what your server has visibility to (by "suffix" if it isn't networked to other LDAP servers). So, etc the default Base in /etc/openldap/ldap.conf, with -b, or elsewhere. gq: Graphical GTK LDAP client Right-click and refresh on elements in navigator panel (often the button to the right doesn't work). REQUIREDS ATTs top { objectClass } organization { o } LDIF FORMAT # comment continuation line begins with ONE space or tab char. cn:< file:///path/to/file.txt cn:: BASE64ENCODED DATA # next object... GOOD doc on Authentication with OpenLDAP: http://users.ameritech.net/mhwood/ldap-sec-setup.html UIDs only permitted in following ObjectClasses (with subclasses indented) * inetOrgPerson posixAccount ? shadowAccount (hidden) * uidObject userPassword only permitted in following ObjectClasses (with subs indented) dmd domain ipHost organization organizationalUnit * person organizationalPerson +inetOrgPerson +OpenLDAPperson residentialPerson posixAccount posixGroup ? shadowAccount (hidden) simpleSecurityObject * only ones appropriate for personal accounts SERVER-SIDE-ONLY SSL without SASL authent. # CA cert file. PEM format. TLSCACertificateFile /etc/openldap/certs/cacert.pem # The public server cert TLSCertificateFile /etc/openldap/certs/slapd_cert.pem # Unencrypted private key for cert above TLSCertificateKeyFile /etc/openldap/certs/slapd_pvk_nc.pem # TLSCipherSuite X # Run "openssl ciphers -v ALL". TLSv1, SSLv3, SSLv2? ldap* command-line clients Edit $HOME/.ldaprc (or /etc/openldap/ldap.conf) and add # TLS_CACERT /path/to/ca.pem.file Sample client run: ldapsearch -x -W -D uid=jenny,ou=dev,ou=it,dc=admc,dc=com \ -H ldaps://beyla.admc.com -b 'dc=admc,dc=com' Java client. Set -Djavax.net.ssl.trustStore=$TRUST_STORE to CA, and code new LDAPConnection(socketFactory). socketFactory = new netscape.ldap.factory.JSSESocketFactory(null); Thu Oct 28 21:01:19 EDT 2010 Creating new LDAP server from scratch. gq's Browse tab shows the actual entries. The Refresh button of gq does not see new entries. You must restart the damned thing! For some reason had to create the admc "dc". DN = Fully qualified path to record RDN are the key attributes of the current record. DN = RDN + RDN of all ancestor records dc just means Domain Component, as in a part of an Internet domain/hostname. sn just means Sur Name cn just means Common Name Everything is stored case-sensitive, but what you enter is usually not required to match case. That applies to both att. names and values. Even for authenticating DNs (but not passwords). The memberof function DOES NOT WORK so dynamically. The ldap server must be running with "overlay memberof" when the group is added... or perhaps when the members are added to the group. SECURITY. Bind = authenticate + set LDAP protocol version According to Wikipedia on LDAP, LDAPS / port 636 / "LDAP over SSL" is deprecated in favor of StartTLS. LDAPS not selected via command-line switch, but by URL schema "ldaps:". StartTLS: Server sends a X.509 and client may. SASL/EXTERNAL = Client cert TLS (+ server cert of course) See "SASL" sub-section below, as this is a SASL mechanism. Server Config Via slapd.conf TLSVerifyClient directive, defaulting to "never". Client Config Via $HOME/.ldaprc or lapd.conf. Command-line tools use -z or -zz. Needs to set CA cert files. Bind methods: Simple: DN + password in plaintext. Anonymous/Simple: w/ Empty DN + Empty password. Unauthenticated/Simple: w/ Non-Empty DN + Empty password. (I don't understand this, since the OpenSSL docs say: "An unsuccessful bind always results in the session having an anonyous auth. association.) SASL: Various StartTLS uses "ldap:" URL scheme, not "ldaps" which is only for LDAPS. Server cert must have dn with cn naming sever + fqdn, plus subjectAltNames are supported. ldapjdk DOES NOT SUPPORT StartTLS!!!! Must use JNDI for this, unless you want to manage a ton of custom code. Hashed password storage are stored in format {}. I think that whenever do this, you need to prevent clients from setting password attr. values directly, because they could eliminate or change the hashing algorithm. These are not very secure and are like pre-shadow UNIX passwords. There are Salted and un-salted algorithms. They require "simple bind" or "SASL Plain". Pass-Through authentication, and a user-by-user basis. Uses Cyrus SASL, but apparently != non-pass-through SASL. Supports PAM and all sorts of algorithms, but passwords are sent as plaintext. userPassword's are stored like: {SASL}username@realm Obviously need to use Access Control to prevent user password changes. SASL. Cyrus SASL, but apprently not Pass-Through SASL. This is used by client tools by default, unless -x switch given. "ldapwhoami" may be used to determine the identity associated with the user. Mechanisms: PLAIN: No stronger than simple (non-SASL). Need to use w/ TLS. LOGIN: No stronger than simple (non-SASL). Need to use w/ TLS. DIGEST-MD5: Required modern mech., but not strong as pub. keys et. al. Does not send password as cleartext. Client and server both apply some algorithm to the secret. Passwords must be stored in plaintext, but they don't have to be stored directly in LDAP entries. Seems that can freely intermix password storage means between databases, userPassword entries, and even slapd.conf's rootpw. For using 'rootpw', just add an authz-regexp for the client-side root uid that maps to the rootdn set in slapd.conf (remember there need not be any real corresponding LDAP entry). To do this storing the plaintext passwords in userPassword attrs, you must set alspd.conf directive: password-hash {CLEARTEXT} Do client tools need to specify "-Y DIGEST-MD5"? auth. request. DN format: uid=,[cn=,]cn=,cn=auth Client requests generate an "authentication request DN", which is nothing like your LDAP entries. Need an identity mapping function: auth.requestDN->userAuthDN (for LDAP entry password storage case, the userAuthDN entry will have a userPassword attr). Example mapping: authz-regexp uid=([^,]*),cn=[^,]*,cn=auth uid=$1,ou=people,dc=example,dc=com How access the system over LDAP as rootdn??? Sun JNDI LDAP w/ DIGEST MD5: http://sunschlichter0.informatik.tu-muenchen.de/Java/jnditutorial/ldap/security/digest.html TROUBLESHOOTING At least with DIGEST MD5, openldap will show "user not found: no secret in database" if the specified user name is not present. If just password is bad, openldap will show "client response doesn't match what we generated". DIGEST-MD5 sample invocation: ldapsearch -Y DIGEST-MD5 -H ldap://beyla.admc.com -LLL -w pwd -U straight -b 'ou=people,dc=admc,dc=com' 'uid=straight' com.sun.security.auth.module.LdapLoginModule Does not support StartTLS and supports LDAPS by default. authzIdentity can only set a single value (if set to an attr with more than one value, it will just return the first value). If set an attr value, may only set to a single attr like "{ATTRNAME}". I am forced to add the parent dn to the LDAP URL.