LDAP TCL Search Extension Library

 

 

 

Authored By:                          Scott Nichols

                       

Date:                        July 3rd, 2006


 

 

Table of Contents

LDAP TCL Extension Overview.. 3

LDAP TCL Extension Installation. 3

ldap_init 4

ldapssl_init 5

$ldapHandle ldap_simple_bind_s. 6

$ldapHanlde ldap_search. 7

$ldap_handle ldap_result 8

$ldapHandle  ldap_set_option option value. 10

$ldapHandle  ldap_unbind. 11

Known Issues and Limitations. 12

Bibliography and Additional Resources. 13

 


LDAP TCL Extension Overview

The LDAP TCL extension provides a way of performing LDAP directory searches from within the TCL language. The extension currently only supports LDAP searches; this seems to be the only thing people are interested in automating in TCL. I have not had any requests to do LDAP modifies or updates, but this could be added if needed. The TCL extension (DLL) has been written for version 8.3 of TCL or above and running in the Microsoft Windows operating systems (NT, 2000, 98, XP) environments. Two APIs are used in the C source code of the extension: The Netscape LDAP SDK v4.0 API and the TCL 8.3 API. The LDAP SDK Dlls need to be copied into the bin directory of where the Tcl executable is running or the Windows\System32 directory.

 

LDAP TCL Extension Installation

 

  1. Extract all of the contents of the LDAP_TCL.zip to a temporary location.
  2. Copy the folder, LDAP_TCL to your TCL lib directory. Example: \TCL\Lib\LDAP_TCL
  3. Copy the \system32\nsldapssl32v40.dll API to the Windows System 32 directory or the same directory as where the TCL executable is located.
  4. There are two ways to load the extension into the TCL interpreter:
    1. package require LDAP
    2. load <Insert File Path>/LDAP_TCL.dll

LDAP TCL Commands

ldap_init

This command initializes a connection with a LDAP server. If successful, a LDAP handle is returned to the TCL interpreter. The ldapssl_init iniatializes a connection for a secure socket layer (SSL) connection.

 

Parameters:

 

Ldap_init Server Port

Return Values:

  1. LDAP Handle
  2. ERROR {Description of Error}

 

Example  TCL Code:

 

if { [catch {

 

    # Load the LDAP package.

    package require LDAP

 

    # Connect to the LDAP Server and TCP Port.

    set ldapHandle [ldap_init "MAIL" "389"]

    puts $ ldapHandle

 


ldapssl_init

This command initializes a connection with a LDAP server for SSL use. If successful, a LDAP handle is returned to the TCL interpreter.

 

Parameters:

 

Ldapssl_init Server Port ClientCertificatePath AuthenticationMode

Return Values:

  1. LDAP Handle
  2. ERROR {Description of Error}

 

Example TCL Code:

 

if { [catch {

# Load the LDAP package.

load "D:/Apropos/TCL/Lib/LDAP/LDAP_TCL.dll"

puts  "Attributes: \"$systemValue(LDAP_PIL_Attributes)\""

 # Connect to the LDAP Server and TCP Port.

set ldapHandle [ldapssl_init "INSERTSERVER" “636” "D:/Cert7.db” "1"]

puts "LDAP Handle: $ldapHandle"

# Build a list request based off of system values

set myList [split “cn mail sn”]

puts "Retrieving result...please wait."

# Simple Bind.

set result [$ldapHandle ldap_simple_bind_s "Insert DN" "Insert Password"]

# Perform a search against a valid search base and search filter.

# set result [$ldapHandle ldap_search_ext_s "Insert_LDAP_Base" "Insert_Search_Filter" "$myList"]

$ldapHandle ldap_simple_bind_s

 

This command binds to an LDAP directory. Before using this command you must first get a valid LDAP handle using the ldap_init command. The ldap_simple_bind_s command has optional dn and password arguments.

 

Parameters:

$ldapHandle ldap_simple_bind_s  $Dn$ $password$


Return Values:

  1. SUCCEEDED
  2. ERROR {Description of Error}

 

Example TCL Code:

 

# Connect to the LDAP Server and TCP Port.

set ldapHandle [ldap_init "$command" "$command2"]

 

# set ldapHandle [ldap_init "ldap.fnal.gov" "389"]

$log insert end "LDAP Handle: $ldapHandle\n"

 

# Bind to the LDAP Directory

set result [$ldapHandle ldap_simple_bind_s]

 

 

 

$ldapHanlde ldap_search

 

Before using this command you must first bind to the LDAP server using the ldap_simple_bind_s command. This command is used to search an LDAP directory using an valid search filter and return arguments. The attributes parameter is optional and should be a space delimited TCL list. If the attributes parameter does not exist all attributes for the entry are returned.

 

Parameters:

$ldapHandle ldap_search Base SearchFilter {$Attributes$}


Return Values:

  1. The message ID of the search query.
  2. ERROR {followed by a description of the error}

 

Example Code:

    # Connect to the LDAP Server and TCP Port.

    set ldapHandle [ldap_init "$command" "$command2"]

   

    # set ldapHandle [ldap_init "ldap.fnal.gov" "389"]

    $log insert end "LDAP Handle: $ldapHandle\n"

   

    # Bind to the LDAP Directory

    set result [$ldapHandle ldap_simple_bind_s]

    $log insert end "LDAP Simple Bind: $result\n"

   

    # Perform a search against a valid search base and search filter.

    set msgID [$ldapHandle ldap_search "$command3" "($command4)" "$command5"]


$ldap_handle ldap_result

 

This command is used to retrieve the results from a previous ldap_search command. It supports both block requested (synchronous) and unblocked requests (asynchronous). The third parameter messageID should be the messageID returned from a previous ldap_search command. The fourth argument is optional, timeout. This is the number of seconds to wait for the search result. If it is not supplied than the calling TCL script should poll the server until the data arrives.

 

Parameters:

$ldapHandle ldap_result messageID {$timout$}

 

Return Values:

  1. A TCL list(s) of entries that matched the search filter.
  2. If no timeout is specified then the message ID result is returned. Possible return values are include below. If anything other than 100 is returned something has gone wrong. 100 means that the server is building a result set.

 

    # /* possible result types a server can return */

    # define LDAP_RES_BIND                                   0x61L   /* 97 */

    # define LDAP_RES_SEARCH_ENTRY                       0x64L   /* 100 */

    # define LDAP_RES_SEARCH_RESULT                      0x65L   /* 101 */

    # define LDAP_RES_MODIFY                             0x67L   /* 103 */

    # define LDAP_RES_ADD                                   0x69L   /* 105 */

    # define LDAP_RES_DELETE                                         0x6bL   /* 107 */

    # define LDAP_RES_MODDN                                          0x6dL   /* 109 */

    # define LDAP_RES_COMPARE                                        0x6fL   /* 111 */

    # define LDAP_RES_SEARCH_REFERENCE                  0x73L   /* 115 */

    # define LDAP_RES_EXTENDED                                       0x78L   /* 120 */

    # define LDAP_RES_ANY                                   (-1L)

    # define LDAP_RES_UNSOLICITED                                    0

 

 

Example TCL Code

 

if { [catch {

 

    # Load the LDAP package.

    package require LDAP

 

    # Connect to the LDAP Server and TCP Port.

    # set ldapHandle [ldap_init "mail.apropos.com" "389"]

    set ldapHandle [ldap_init "ldap.fnal.gov" "389"]

    puts "LDAP Handle: $ldapHandle"

   

    # Bind to the LDAP Directory

    set result [$ldapHandle ldap_simple_bind_s]

    puts "LDAP Simple Bind: $result"

   

    # Perform a search against a valid search base and search filter.

    # set msgID [$ldapHandle ldap_search "o=Apropos,c=US" (telephonenumber=630-575-*7840) "cn mail telephonenumber"]

    set msgID [$ldapHandle ldap_search "o=fnal" (sn=*)]

   

    puts "LDAP Search Msg ID: $msgID"

    puts "Retrieving result...please wait."

   

    # Get the Result with a 20sec timeout

    set result [$ldapHandle ldap_result $msgID 10]

    # /* possible result types a server can return */

    # define LDAP_RES_BIND                   0x61L   /* 97 */

    # define LDAP_RES_SEARCH_ENTRY           0x64L   /* 100 */

    # define LDAP_RES_SEARCH_RESULT          0x65L   /* 101 */

    # define LDAP_RES_MODIFY                 0x67L   /* 103 */

    # define LDAP_RES_ADD                    0x69L   /* 105 */

    # define LDAP_RES_DELETE                 0x6bL   /* 107 */

    # define LDAP_RES_MODDN          0x6dL   /* 109 */

    # define LDAP_RES_COMPARE                0x6fL   /* 111 */

    # define LDAP_RES_SEARCH_REFERENCE       0x73L   /* 115 */

    # define LDAP_RES_EXTENDED               0x78L   /* 120 */

    # define LDAP_RES_ANY                    (-1L)

    # define LDAP_RES_UNSOLICITED        0

 

    puts ""

   

    # Parse the LDAP record(s) returned in the TCL list.

    for {set j 0} {$j <[llength $result]} {incr j} {

        set myRecord [lindex $result $j]

        for {set i 0} {$i <[llength $myRecord] } {incr i 2} {

            puts "[lindex $myRecord $i]=[lindex $myRecord [expr $i + 1]]"

        }

        puts ""

    }

 

    # Unbind from the LDAP directory.

    set result [$ldapHandle ldap_unbind]

    puts "LDAP Unbind: $result"

 

} doRequestCatch] } {

    puts $doRequestCatch"}

$ldapHandle  ldap_set_option option value

 

Sets an option for the LDAP session

 

Parameters: $ldapHandle ldap_set_option option value

 

Possible Options (3rd Argument)

 

LDAP_OPT_API_INFO              

LDAP_OPT_DESC                  

LDAP_OPT_DEREF                 

LDAP_OPT_SIZELIMIT             

LDAP_OPT_TIMELIMIT             

LDAP_OPT_REFERRALS             

LDAP_OPT_RESTART               

LDAP_OPT_PROTOCOL_VERSION 

LDAP_OPT_SERVER_CONTROLS  

LDAP_OPT_CLIENT_CONTROLS     

LDAP_OPT_API_FEATURE_INFO    

LDAP_OPT_HOST_NAME                

LDAP_OPT_ERROR_NUMBER                     

LDAP_OPT_ERROR_STRING                       

LDAP_OPT_MATCHED_DN               

 


Return Values:

Tcl OK

Tcl Error


Example Code:

   

# Create an LDAP Handle

set ldapHandle [ldap_init "ldap.fnal.gov" "389"]

   

            # Called after we have a valid handle.

$ldapHandle ldap_set_option LDAP_OPT_REFERRALS 0

 


$ldapHandle  ldap_unbind

 

Unbinds from an LDAP directory and destroys the LDAP handle. Once the LDAP handle has been destroyed a new one must be created using the ldap_init command.

 

Parameters: $ldapHandle ldap_unbind


Return Values:

SUCCEEDED

FAILED {If no connection is currently open}


Example Code:

    # Unbind from the LDAP directory.

    set result [LDAP_Disconnect]

    puts $result


Known Issues and Limitations

 

  1. Many LDAP servers, Exchange, Lotus Notes, etc. have an administrative limit on the number or entries (records) that can be returned. This is usually not an issue if you are interested in only finding a match on a few records using a search filter.
  2. The LDAP TCL extension can raise a TCL error if something has gone wrong, because of this you should encapsulate all of your searches using the TCL catch command.

Bibliography and Additional Resources

 

[1] Practical Programming in TCL and TK / Brent B. Welch. – 3rd ed. P. cm. ISBN 0-13-022028-0

 

[2] LDAP: Programming Directory-Enabled Applications with Lightweight Directory Access Protocol / Timothy A Howes and Mark C. Smith – ISBN 1-57870-000-0