ldapsearch Phone Directory

By | August 9, 2013

Back in the day we kept phone number in a dataset which we’d browse with ISPF and find the number we needed.  Then we improved it a bit with an ISPF BRIF service program that filtered the lines of the dataset based upon an input search parameter saving the “FIND” step.  At first we maintained the dataset manually, then someone found a way to get a weekly feed from the payroll or HR system to keep it up to date.

Alas, then it was all  taken away from us.  All of this directory information was moved to Active Directory or something, we lost the weekly feed and we have to go through several steps to look up a phone number using Outlook or whatever.  We lost our subsecond response times, that’s for sure.

After living with this for awhile, I searched for a way to access the directory information from TSO.  And there is a way with ldapsearch a.k.a. GLDSRCH.  ldapsearch is currently documented in IBM Tivoli Directory Server Client Programming for z/OS and the information on running under TSO is here.  The fact the this is the same as GLDSRCH which is (now) in the linklist, is not well documented but you can see this in SGLDEXEC(LDAPSRCH).

You’ll need to know the hostname or IP address and the port to access your directory and whether you need to provide credentials to log into it or use kerberos.  (Let’s hope not.) In my case, the directory is not secured from reading.

I would also use and have used an ldap browser such as the one from Softerra to figure the base dn (distinguished name) and the attributes your company’s directory has that you want to show.  Using a reasonable base dn will improve performance by narrowing the searching down the appropriate tree of the ldap directory.

The ldapsearch filter is not really described in the IBM manual other than referring you to the RFC and with a few examples.  But using a proper filter may be necessary to weed out unnecessary results.  For example, for one Active Directory system I have used, I needed to filter out Computers from the results,

(&(objectclass=person)(!(objectClass=Computer))(cn=*John*))

which selects records with objectclass of person and not objectclass Computer and with a cn (common name) that has the word John in it.

In the GLDSRCH command you specify the filter and the attributes you want to be returned.  For example, you might want cn and telephoneNumber and Department.  GLDSRCH returns the results like

dn: Distinguished Name (DN)
attributename=value
attributename=value
attributename=value

dn: Distinguished Name (DN)
attributename=value
attributename=value
attributename=value

etc.

So a Rexx program could use Interpret to assign values to attribute variables.  One wrinkle is that binary data gets encoded in base64.  I ran across garbage in one directory that would be returned this way which was a bit confusing at first.

My approach to a phone number lookup utility is to 1) build a search from the input parameter, 2) do the ldap search routing the output to a dataset, 3) read the dataset into a stem variable with EXECIO, 4) parse the results building a new stem variable for each result,  5) browse the resulting stem variable with STEMVIEW, a freeware utility from the CBT Tape. (FILE 183 download), and 6) implement with an ISPF command table entry.  Lionel B. Dyke has a project similar to mine, LDAPMAIL, which also does an ldapsearch in Rexx.

Here is and example of the basic guts of calling the LDAP search with a filter and some attributes specified and picking up the results:

/* Rexx */                                        

ldaphost = "directory.mycompany.com"              
ldapPort = "389"                                  
ldapbase = "o=InternalUsers,dc=mycompany,dc=com"  

filter = "(&(objectClass=Person)(CN=*Quigley*))"  

ddname = "LDAP" || Random(9999)                   
"ALLOCATE FILE("ddname") UNIT(VIO) SPACE(1 1) CYL"

'GLDSRCH /-L -h' ldapHost '-p' ldapPort '-s sub', 
 '-b' ldapbase,                                   
 '"'filter'" 2>&1 >//DD:'ddname,                  
 'uid',                                           
 'cn',                                            
 'telephoneNumber',                               
 'title',                                         
 'department',                                    
 'companyname',                                   
 'mail',                                          
 'l'                                                                                 

"EXECIO * DISKR" ddname "(STEM LDAP. FINIS"       
"FREE     FILE("ddname")"                         

Do i = 1 to ldap.0                                
  Say ldap.i                                      
  End

Some of these attributes are, no doubt, unique to this directory, as should be the ldapbase value.   The output from running this looks something like this:

dn: uid=xx0886,o=InternalUsers,dc=MyCompany,dc=com
l: SPF                                            
mail: Abigale.M.Quigley@MyCompany.com             
cn: Abigale M Quigley                             
uid: xx0886                                       

dn: uid=yyopy4,o=InternalUsers,dc=MyCompany,dc=com
l: SPF                                            
mail: Lola.Quigley@MyCompany.com                  
companyname: MYCOMPANY SECURI                     
department: SPRNGFLD LD PROCESSING                
title: LOSS DRAFTS TEAM LEAD                      
telephoneNumber: (555)555-3224 ext. 43224         
cn: Lola Quigley                                  
uid: yyopy4                                       

dn: uid=zzooap,o=InternalUsers,dc=MyCompany,dc=com
l: BRE                                            
mail: Melissa.Quigley@MyCompany.com               
companyname: MYCOMPANY SECURI                     
department: CITIMORTGAGE                          
title: CUSTOMER CARE SPECIALIST                   
telephoneNumber: 555-555-8460 ext. 24625          
cn: Melissa Quigley                               
uid: zzooap

Note that not all attributes exist for each directory entry found.  Play around with different filters and see what you get. Occasionally I would get attributes that look like this:

telephoneNumber:: KDU1NSk1NTUtNDAzMSBleHQuIMI=

which happens when there is non-printable characters in the value. This example is a base64 encoded value of the ASCII string “(555)555-4031 ext. ”.  Somehow, some garbage characters got into the phone number.

This is what I ended up with:  phone.rexx.

 

One thought on “ldapsearch Phone Directory

  1. Rob Johns

    Thank you Phil! That was exactly what I was looking for without all of the effort of figuring it out myself.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *