internal package Foswiki::Contrib::LdapContrib

See PublishedAPI for packages intended to be used by Plugin and Contrib authors, or browse all packages.
See also Developing plugins, Developer's Bible, Technical Overview

On this page:

Foswiki::Contrib::LdapContrib

General LDAP services module. This class encapsulates the platform-specific means to integrate an LDAP directory service. Used by Foswiki::Users::LdapPasswdUser for authentication, Foswiki::Users::LdapUserMapping for group definitions and Foswiki:Plugins/LdapNgPlugin to interface general query services.

Typical usage

my $ldap = new Foswiki::Contrib::LdapContrib;

$ldap->search(
  filter => 'mail=*@gmx*',
  callback => sub {
    my ($ldap, $entry) = @_;
    # process entry
  } 
);
my $errorMsg = $ldap->getError();

my $count = $result->count();

my @entries = $result->sorted('sn');
my $entry = $result->entry(0);

my $dn = $this->getDN($entry);
my $commonName = $this->getValue($entry, 'cn');
my $email = $this->getValue($entry, 'mail');

Cache storage format

The cache stores a series of key-value pairs in a DB_File. The following keys are used:

  • WIKINAMES - list of all wikiNames
  • LOGINNAMES - list of all loginNames
  • GROUPS - list of all groups
  • UNKWNUSERS - list of all usernames that could not be found in LDAP (to avoid future LDAP lookups in case caching is OFF)
  • UNKWNGROUPS - list of all group names that could not be found in LDAP (to avoid future LDAP lookups in case caching is OFF)
  • GROUPS::$groupName - list of all loginNames in group groupName (membership)
  • GROUP2UNCACHEDMEMBERSDN::$groupName - list of all DNs (when in memberIndirection mode) that could not be resolved to a user or group existing in the cache when $groupName was retreived from LDAP
  • EMAIL2U::$emailAddr - stores the loginName of an emailAddr
  • U2EMAIL::$loginName - stores the emailAddr of a loginName
  • U2W::$loginName - stores the wikiName of a loginName
  • W2U::$wikiName - stores the loginName of a wikiName
  • DN2U::$dn - stores the loginName of a distinguishedName
  • U2DN::$loginName - stores the distinguishedName of a loginName

writeDebug($msg)

Static Method to write a debug messages.

writeWarning($msg)

Static Method to write a warning messages.

new($session, host=>'...', base=>'...', ...) -> $ldap

Construct a new Foswiki::Contrib::LdapContrib object

Possible options are:
  • host: ip address (or hostname)
  • base: the base DN to use in searches
  • port: port address used when binding to the LDAP server
  • version: protocol version
  • userBase: list of sub-trees containing user accounts
  • groupBase: list of sub-trees containing group definitions
  • loginAttribute: user login name attribute
  • loginFilter: filter to be used to find login accounts
  • groupAttribute: the group name attribute
  • groupFilter: filter to be used to find groups
  • memberAttribute: the attribute that should be used to collect group members
  • innerGroupAttribute: the attribute that should be used to collect inner groups of a group
  • bindDN: the dn to use when binding to the LDAP server
  • bindPassword: the password used when binding to the LDAP server

Options not passed to the constructor are taken from the global settings in lib/LocalSite.cfg.

getLdapContrib($session) -> $ldap

Returns a standard singleton Foswiki::Contrib::LdapContrib object based on the site-wide configuration.

connect($dn, $passwd, $host, $port) -> $boolean

Connect to LDAP server. If a $dn parameter and a $passwd is given then a bind is done. Otherwise the communication is anonymous. You don't have to connect() explicitely by calling this method. The methods below will do that automatically when needed.

disconnect()

Unbind the LDAP object from the server. This method can be used to force a reconnect and possibly rebind as a different user.

finish()

finalize this ldap object.

checkError($msg) -> $errorCode

Private method to check a Net::LDAP::Message object for an error, sets $ldap->{error} and returns the ldap error code. This method is called internally whenever a message object is returned by the server. Use $ldap->getError() to return the actual error message.

getError() -> $errorMsg

Returns the error message of the last LDAP action or undef it no error occured.

getCode() -> $errorCode

Returns the error code of the last LDAP action

getAccount($loginName) -> Net::LDAP::Entry object

Fetches an account entry from the database and returns a Net::LDAP::Entry object on success and undef otherwise. Note, the login name is match against the attribute defined in $ldap->{loginAttribute}. Account records are search using $ldap->{loginFilter} in one of the the subtrees defined in $ldap->{userBase}.

search($filter, %args) -> $msg

Returns an Net::LDAP::Search object for the given query on success and undef otherwise. If $args{base} is not defined $ldap->{base} is used. If $args{scope} is not defined 'sub' is used (searching down the subtree under $args{base}. If no $args{sizelimit} is set all matching records are returned. The $attrs is a reference to an array of all those attributes that matching entries should contain. If no $args{attrs} is defined all attributes are returned.

If undef is returned as an error occured use $ldap->getError() to get the cleartext message of this search() operation.

Typical usage:
$ldap->search(
  filter=>'uid=TestUser',
  callback => sub {
    my ($ldap, $entry) = @_;
    return unless defined $entry;
    # process entry
  }
);

cacheBlob($entry, $attribute, $refresh) -> $pubUrlPath

Takes an Net::LDAP::Entry and an $attribute name, and stores its value into a file. Returns the pubUrlPath to it. This can be used to store binary large objects like images (jpegPhotos) into the filesystem accessible to the httpd which can serve it in return to the client browser.

Filenames containing the blobs are named using a hash value that is generated using its DN and the actual attribute name whose value is extracted from the database. If the blob already exists in the cache it is not extracted once again except the $refresh parameter is defined.

Typical usage:
my $blobUrlPath = $ldap->cacheBlob($entry, $attr);

tieCache($mode)

tie the cache with $mode. $mode 'read' ties the cache successfully given that there is only other 'read' locks on it. $mode 'write' ties the cache successfully given that there is no locks on it.

untieCache()

unties the cache

initCache()

loads/connects to the LDAP cache

initTopicUserMapping()

reads a topic-based user mapping from a predefined topic and initializes the internal _topicUserMapping hash

refreshCache($mode) -> $boolean

download all relevant records from the LDAP server and store it into a database.

  • mode = 0: no refersh
  • mode = 1: normal refersh
  • mode = 2: nuke previous decisions on wikiName clashes

refreshUsersCache($data, $userBase) -> $boolean

download all user records from the LDAP server and cache it into the given hash reference

returns true if new records have been loaded

resolveWikiNameClashes($data, %wikiNames, %loginNames) -> $integer

if there have been name clashes those entry records have not yet been added to the cache. They are kept until all clashes have been found and a deterministic renaming scheme can be applied. Clashed WikiNames will be enumerated - WikiName1, WikiName2, WikiName3 etc - and finally added to the database. The renaming is kept stable by sorting the dn entry of all clashed entries.

returns the number of additional entries that have been cached

refreshGroupsCache($data, $groupBase) -> $boolean

download all group records from the LDAP server

returns true if new records have been loaded

cacheUserFromEntry($entry, $data, $wikiNames, $loginNames, $wikiName) -> $boolean

store a user LDAP::Entry to our internal cache

If the $wikiName parameter is given explicitly then this will be the name under which this record will be cached.

returns true if new records have been created

cacheGroupFromEntry($entry, $data, $groupNames) -> $boolean

store a group LDAP::Entry to our internal cache

returns true if new records have been created

normalizeWikiName($name) -> $string

normalizes a string to form a proper WikiName

normalizeLoginName($name) -> $string

normalizes a string to form a proper login

rewriteName($in, $rules) -> $out

rewrites a name based on a set of rewrite rules

transliterate($string) -> $string

transliterate some essential utf8 chars to a common replacement in latin1 encoding. the list above is not exhaustive.

use http://www.ltg.ed.ac.uk/~richard/utf-8.html to add more recodings

getGroupNames($data) -> @array

Returns a list of known group names.

isGroup($wikiName, $data) -> $boolean

check if a given user is an ldap group actually

getEmails($loginName, $data) -> @emails

fetch emails from LDAP

getLoginOfEmail($email, $data) \@users

get all users matching a given email address

getGroupMembers($groupName, $data) -> \@array

isGroupMember($loginName, $groupName, $data) -> $boolean

check if a given user is member of an ldap group

getWikiNameOfLogin($loginName, $data) -> $wikiName

returns the wikiName of a loginName or undef if it does not exist

getLoginOfWikiName($wikiName, $data) -> $loginName

returns the loginNAme of a wikiName or undef if it does not exist

getAllWikiNames($data) -> \@array

returns a list of all known wikiNames

getAllLoginNames($data) -> \@array

returns a list of all known loginNames

getDnOfLogin($loginName, $data) -> $dn

returns the Distinguished Name of the LDAP record of the given name

getDnOfWikiName($wikiName, $data) -> $dn

returns the Distinguished Name of the LDAP record of the given name

getWikiNameOfDn($dn, $data) -> $wikiName

returns the wikiName used by a given Distinguished Name; reverse of getDnOfWikiName()

changePassword($loginName, $newPassword, $oldPassword) -> $boolean

checkCacheForLoginName($loginName, $data) -> $boolean

grant that the current loginName is cached. If not, it will download the LDAP record for this specific user and update the LDAP cache with this single record.

This happens when the user is authenticated externally, e.g. using apache's mod_authz_ldap or some other SSO, and the internal cache is not yet updated. It is completely updated regularly on a specific time interval (default every 24h). See the LdapContrib settings.

removeGroupFromCache($groupName, $data) -> $boolean

Remove a group from the cache

removeUserFromCache($wikiName, $data) -> $boolean

removes a wikiName from the cache

addIgnoredUser($loginName, $data) -> \@array

Insert a new user in the list of unknown users that should not be lookedup in LDAP

isUnknownUser($loginName, $data) -> $boolean

returns 1 if $loginName is an unknown user that should not be relookedup in LDAP

addIgnoredGroup($groupName, $data) -> \@array

Insert a new group in the list of unknown groups that should not be lookedup in LDAP

isUnknownGroup($groupName, $data) -> $boolean

returns 1 if $groupName is an unknown groups that should not be relookedup in LDAP

checkCacheForLoginName($groupName, $data) -> $boolean

grant that the current groupName is cached. If not, it will download the LDAP record for this specific group and its subgroups and update the LDAP cache with the retreived records.

This happens when the precache mode is off. See the LdapContrib settings.

getGroup($groupName) -> Net::LDAP::Entry object

Fetches a group entry from the database and returns a Net::LDAP::Entry object on success and undef otherwise. Note, the group name is match against the attribute defined in $ldap->{groupAttribute}. Account records are search using $ldap->{groupFilter} in the subtree defined by $ldap->{groupBase}.

fromLdapCharSet($string) -> $string

decode strings coming from ldap

getValue($entry, $key) -> $value

returns a decoded string from an Net::LDAP::Entry object

getDN($entry, $key) -> $value

returns the decoded distinguished name from an Net::LDAP::Entry object

getValues($entry, $key) -> @values

returns a decoded an array of strings from an Net::LDAP::Entry object

getValueMap($entry, $key) -> \%result

returns a decoded an array of strings from an Net::LDAP::Entry object

ObjectMethod loadSession()

Load the session, sanitize the login name and make sure its user information are already cached.

Topic revision: r1 - 27 Feb 2018, UnknownUser
This site is powered by FoswikiCopyright © by the contributing authors. All material on this site is the property of the contributing authors.
Ideas, requests, problems regarding Foswiki? Send feedback