LDAP '''Lightweight Directory Access Protocol''' is a protocol for networked directories [http://en.wikipedia.org/wiki/LDAP].
This page is about both TCL ldap libraries and TCL ldap clients.
As of 2010, the mostly referred to TCL ldap library is the one provided by tcllib:
http://tcllib.sourceforge.net/doc/ldap.html
As of 2010, there is no up-to-date tcl GUI client. http://sourceforge.net/projects/legacytcl/%|%Legacy TCL project%|% has a collection of TCL programs, among them there is a ldap client more than a decade old.
----
[musashiXXX] 2010-May-10
I've written a CGI based interface to LDAP. It was designed for the sole purpose of allowing users to administer a single OU from a web interface. It's very basic at the moment but I plan on developing it further. The tarball is located here: http://nefaria.com/scriptz/tcl-ldap-cgi.tar.gz ... there is no README or instructions (I'm working on that) but if you need any help, feel free to contact me (musashiXXX) on irc.freenode.net #tcl or via e-mail (musashi@nefaria.com).
----
There are four independent (?) implementations, [ldapTcl],
[Matt Newman]'s LDAP extension [http://www.sensus.org/tcl/index.htm],
Jochen Loewer's (see below), a derivative of the latter available in [tcllib] as of 2004,
and [Gareth Owen]'s tclLdap-pkg [http://www-users.aston.ac.uk/~oweng/tclLdap-pkg/]
(but is this a derivative of an early tclLdap?).
It would be particularly useful to compare the latter two.
----
I did a pure Tcl implementation of a ldap interface in June 99.
See ([Jochen Loewer]).
It is running since then very nicely to query a large enterprise
wide people directory. Right now only the read/query parts
of the protocol are implemented. However, the internal [ASN]
layer is there, so it should be rather easy to extend it.
Unfortunately I didn't release the code to the public yet.
I thought about that several times. It would be ideal for tcllib
or even standard tcl (like the http package).
[CL]: ooooo. ASN.1 ''would'' be nice for [tcllib].
[ak]: Tcllib head provides an (incomplete) [asn] package.
Directly derived from the code in the ldap package.
----
Interesting LDAP-based applications include Owen's Ldapper
[http://www-users.aston.ac.uk/~oweng/ldapper-1.2/]
(which pages says it was last modified ''Wed Feb 3 17:46:54 GMT 1999'').
----
As of 2004, the major category of LDAP servers are instances of [Microsoft]'s [Active Directory].
----
CL observes that learning to work with LDAP can intimidate newcomers, if only
for the usual complication of client-server protocols ([SNMP] presents the same challenge):
one must have a working server ''and'' client before achieving the "Hello, world" level of progress.
In the '90s, there were quite a few public LDAP services, and it was inviting to connect
new client applications to them for quick exercise.
As far as I know, they're all gone now [[task: confirm this]].
Is there interest in Tclistan for a public LDAP server against which we can all practice?
I might set one up ... (again, same's true for SNMP).
----
[Patrick Finnegan] provided several [IBM]-pertinent example LDAP-using scripts
[http://aspn.activestate.com/ASPN/Cookbook/Tcl?kwd=LDAP] to the '''[Cookbook]'''.
----
In general, LDAP querying requires quoting of such characters as comma
[http://groups.google.com/group/comp.lang.tcl/browse_thread/thread/0c13fc6495fdaa34/742865a7048b8873].
----
[schlenk] The tcllib ldap client package was greatly enhanced in the 1.9 version of Tcllib.
* STARTTLS support ([RFC] 4513)
* SASL Auth support (RFC 4513)
* new ldapx subpackage to provide an OO API
* LDIF support in the ldapx package (RFC 2849)
* asynchronous operation, does no longer block your app during ldap queries
* Who am I extension supported (RFC 4532)
* New introspection commands to inspect the running connection
Using [LDIF] you can for example parse Mozilla Thunderbird Addressbooks, which can be exported in ldif format,
see the examples/ldap directory in the tcllib distribution.
----
[LV] 2009-Sep-15
Has anyone written a tutorial for learning to interact with LDAP (or even better, Active Directory) using Tcl? It would be nice to have a series of examples starting at something simple like looking for the current user's LDAP information, then on to listing all users along with their phone numbers, etc. and finally a few examples of things like adding a new user, updating an existing user, deleting a user. These examples would really help a novice administrator get started using Tcl.
----
'''[rojo] - 2011-04-26 10:20:20'''
@LV: Here's an example of an LDAP search in a MS environment for you.
======
#! /bin/sh
# \
exec tclsh "$0" ${1+"$@"}
namespace eval ldapsearch {
set settings(domain) your.domain
set settings(user) authorized_user
set settings(pass) p4sSwh1rRed
# timeout in seconds for LDAP queries... For some reason, when searching for cn
# or displayName, results return immediately; whereas searching any other field
# (employeeID for instance) will not return results until the timeout. This doesn't
# seem to be a TCL-only thing, as I've noticed it with ASP and .NET apps as well.
# Maybe my domain controllers have seen better days. But I digress. Set this
# low for faster queries, but not low enough that every search returns 0 results.
set settings(timeout) 5
# Wildcard searches seem to error with ldap::secure_connect
set settings(use-ssl) false
variable settings
package require ldap
if {$settings(use-ssl)} { package require tls }
proc isid {what} {
# What does an employee ID look like in your organization?
# For this example we'll say it's in the format of E01234567
return [regexp -nocase {^E\d{8}$} $what]
}
proc search {what} {
variable settings
if {$settings(use-ssl)} {
if {[catch {ldap::secure_connect $settings(domain)} idx]} { set idx [ldap::connect $settings(domain)] }
} { set idx [ldap::connect $settings(domain)] }
if {$settings(use-ssl) && [::ldap::info tls $idx]} {
puts "SSL connected to [::ldap::info ip $idx]"
} { puts "Connected to [::ldap::info ip $idx]" }
ldap::bind $idx $settings(user)@$settings(domain) $settings(pass)
set attributes {
sAMAccountName
name
displayName
employeeID
pwdLastSet
userAccountControl
memberOf
msExchHomeServerName
msExchHideFromAddressLists
}
if {[isid $what]} {
set filter "|(employeeID=$what)"
} elseif {[string match *,* $what]} {
set filter "|(displayName=$what*)"
} else {
set filter "|(cn=$what)"
}
if {[catch {
set dc "dc=[string map {. ,dc=} $settings(domain)]"
ldap::searchInit $idx $dc $filter $attributes [list -scope sub -timelimit $settings(timeout)]
} fail]} { puts "Init failure: $fail"; ldap::unbind $idx; ldap::disconnect $idx; return }
while {![catch {ldap::searchNext $idx} flat]} {
set dn [lindex $flat 0]
set flat [lindex $flat 1]
if {![llength $flat]} { continue }
foreach attr $attributes { set res($attr) {} }
foreach {name val} $flat { set res($name) $val }
# $res(pwdLastSet) is measured in 100 nanosecond intervals since 1/1/1601
# convert to seconds
set res(pwdLastSet) [expr {wide($res(pwdLastSet) * pow(10,-7))}]
# convert to 1970 epoch
incr res(pwdLastSet) [clock scan {1601-1-1} -format {%Y-%m-%d}]
# expires when?
set res(pwdExpires) [clock format [clock add $res(pwdLastSet) 90 days] -format {%H:%M:%S %b %d %Y}]
# Set how long ago?
set res(pwdAge) "[expr {([clock seconds] - $res(pwdLastSet)) / 60 / 60 / 24}] days"
# see http://support.microsoft.com/kb/305144 for $res(userAccountControl)
set UAC {
134217728 UF_USE_AES_KEYS
67108864 UF_PARTIAL_SECRETS_ACCOUNT
16777216 TRUSTED_TO_AUTH_FOR_DELEGATION
8388608 PASSWORD_EXPIRED
4194304 DONT_REQ_PREAUTH
2097152 USE_DES_KEY_ONLY
1048576 NOT_DELEGATED
524288 TRUSTED_FOR_DELEGATION
262144 SMARTCARD_REQUIRED
131072 MNS_LOGON_ACCOUNT
65536 DONT_EXPIRE_PASSWORD
8192 SERVER_TRUST_ACCOUNT
4096 WORKSTATION_TRUST_ACCOUNT
2048 INTERDOMAIN_TRUST_ACCOUNT
512 NORMAL_ACCOUNT
256 TEMP_DUPLICATE_ACCOUNT
128 ENCRYPTED_TEXT_PWD_ALLOWED
64 PASSWD_CANT_CHANGE
32 PASSWD_NOTREQD
16 LOCKOUT
8 HOMEDIR_REQUIRED
2 ACCOUNTDISABLE
1 SCRIPT
}
set flags [list]
foreach {dec flag} $UAC {
if {!$res(userAccountControl)} { break }
if {$res(userAccountControl) >= $dec} { lappend flags $flag; incr res(userAccountControl) -$dec }
}
set res(userAccountControl) $flags
set groups [list]
foreach group $res(memberOf) {
lappend groups [string map {CN= ""} [lindex [split $group ,] 0]]
}
set res(memberOf) $groups
set res(msExchHomeServerName) [lindex [split [lindex $res(msExchHomeServerName) end] =] end]
foreach {name val} [array get res] { puts "$name: $val" }
puts "\n"
}
# puts "Last value of \$flat: $flat"
ldap::searchEnd $idx
ldap::unbind $idx
ldap::disconnect $idx
return
}
}; # end namespace
if {[llength $argv]} { puts $argv; ldapsearch::search [lindex $argv 0] }
======
usage:<
>
$ tclsh<
>
% source thisfile.tcl<
>
% ldapsearch::search username<
>
- outputs records for all users matching username* similar to Active Directory Users & Computers<
>
% ldapsearch::search {lastname, f}<
>
- outputs records for all users matching "lastname, f*" similar to Active Directory Users & Computers<
>
% ldapsearch::search employeeID<
>
- outputs exact match where employeeID=searchterm<
>
<> Acronym | Internet