libnet-ldap-perl-0.6500+dfsg.orig/0000755000175000017500000000000012521705575016120 5ustar gregoagregoalibnet-ldap-perl-0.6500+dfsg.orig/MANIFEST0000644000175000017500000000647012521705575017260 0ustar gregoagregoabin/ldapdelete bin/ldapmodrdn bin/ldapsearch Changes contrib/dot.tklkup contrib/isMember.pl contrib/jpegDisplay.pl contrib/jpegLoad.pl contrib/ldapmodify.pl contrib/ldifdiff.pl contrib/ldifsort.pl contrib/ldifuniq.pl contrib/LWPsearch.pl contrib/printMembers.pl contrib/README contrib/recursive-ldap-delete.pl contrib/schema2ad.pl contrib/simple-proxy.pl contrib/tklkup CREDITS data/00-cmp.ldif data/00-cmp2.ldif data/00-in.ldif data/05-cmp.dsml data/10-in.ldif data/40-cmp.ldif data/40-in.ldif data/41-in.ldif data/41a-cmp.ldif data/41b-cmp.ldif data/41c-cmp.ldif data/41d-cmp.ldif data/42-cmp.ldif data/42-in.ldif data/42-mod.ldif data/cert.pem data/cosine.schema data/inetorgperson.schema data/key.pem data/man.jpg data/openldap.schema data/openssl.cnf data/postalAddress.txt data/regenerate_cert.sh data/schema.in data/slapd.conf.in data/woman.jpg inc/Module/AutoInstall.pm inc/Module/Install.pm inc/Module/Install/AutoInstall.pm inc/Module/Install/Base.pm inc/Module/Install/Can.pm inc/Module/Install/Fetch.pm inc/Module/Install/Include.pm inc/Module/Install/Makefile.pm inc/Module/Install/Metadata.pm inc/Module/Install/Win32.pm inc/Module/Install/WriteAll.pm INSTALL install-nomake lib/Bundle/Net/LDAP.pm lib/LWP/Protocol/ldap.pm lib/LWP/Protocol/ldapi.pm lib/LWP/Protocol/ldaps.pm lib/Net/LDAP.pm lib/Net/LDAP.pod lib/Net/LDAP/ASN.pm lib/Net/LDAP/Bind.pm lib/Net/LDAP/Constant.pm lib/Net/LDAP/Control.pm lib/Net/LDAP/Control/Assertion.pm lib/Net/LDAP/Control/DontUseCopy.pm lib/Net/LDAP/Control/EntryChange.pm lib/Net/LDAP/Control/ManageDsaIT.pm lib/Net/LDAP/Control/MatchedValues.pm lib/Net/LDAP/Control/Paged.pm lib/Net/LDAP/Control/PasswordPolicy.pm lib/Net/LDAP/Control/PersistentSearch.pm lib/Net/LDAP/Control/PostRead.pm lib/Net/LDAP/Control/PreRead.pm lib/Net/LDAP/Control/ProxyAuth.pm lib/Net/LDAP/Control/Relax.pm lib/Net/LDAP/Control/Sort.pm lib/Net/LDAP/Control/SortResult.pm lib/Net/LDAP/Control/SyncDone.pm lib/Net/LDAP/Control/SyncRequest.pm lib/Net/LDAP/Control/SyncState.pm lib/Net/LDAP/Control/VLV.pm lib/Net/LDAP/Control/VLVResponse.pm lib/Net/LDAP/DSML.pm lib/Net/LDAP/Entry.pm lib/Net/LDAP/Entry.pod lib/Net/LDAP/Examples.pod lib/Net/LDAP/Extension.pm lib/Net/LDAP/Extension/Cancel.pm lib/Net/LDAP/Extension/Refresh.pm lib/Net/LDAP/Extension/SetPassword.pm lib/Net/LDAP/Extension/WhoAmI.pm lib/Net/LDAP/Extra.pm lib/Net/LDAP/Extra/AD.pm lib/Net/LDAP/Extra/eDirectory.pm lib/Net/LDAP/FAQ.pod lib/Net/LDAP/Filter.pm lib/Net/LDAP/Filter.pod lib/Net/LDAP/FilterMatch.pm lib/Net/LDAP/Intermediate.pm lib/Net/LDAP/Intermediate/SyncInfo.pm lib/Net/LDAP/LDIF.pm lib/Net/LDAP/LDIF.pod lib/Net/LDAP/Message.pm lib/Net/LDAP/Message.pod lib/Net/LDAP/Reference.pod lib/Net/LDAP/RFC.pod lib/Net/LDAP/RootDSE.pm lib/Net/LDAP/Schema.pm lib/Net/LDAP/Schema.pod lib/Net/LDAP/Search.pm lib/Net/LDAP/Search.pod lib/Net/LDAP/Security.pod lib/Net/LDAP/Util.pm lib/Net/LDAPI.pm lib/Net/LDAPS.pm Makefile.PL MANIFEST This list of files MANIFEST.SKIP META.json README SIGNATURE t/00ldif-entry.t t/01canon_dn.t t/02filter.t t/03schema.t t/04refloop.t t/05dsml.t t/06constant.t t/07filtermatch.t t/08time.t t/09ldif-http-url.t t/10ldif-controls.t t/40connect.t t/41populate.t t/42search.t t/43modify.t t/44schema.t t/45dse.t t/46ssl.t t/47ipc.t t/48url.t t/49lwp.t t/60cancel.t t/70sortctrl.t t/71preread.t t/72postread.t t/73assert.t t/74matchedvalues.t t/common.pl test.cfg TODO libnet-ldap-perl-0.6500+dfsg.orig/Changes0000644000175000017500000006272512510542723017417 0ustar gregoagregoa0.65 -- Mon Apr 6 19:43:37 CEST 2015 Enhancements: * t/74matchedvalues.t: more tests * {ASN,Extension}.pm: update ExtendedResponse to RFC 4511 * Constant.pm: add LDAP_NOTICE_OF_DISCONNECTION * Control/DontUseCopy.pm: new * Control/ProxyAuth.pm: make sure criticality does not get changed * Control/Relax.pm: make sure value & criticality do not get changed * Control/ManageDsaIT.pm: make sure value never gets set Bug Fixes * LDAP.pm: do not set default sslversion for start_tls() & LDAPS Instead of second-guessing a default sslversion for start_tls() and LDAPS, rely on the - known to be sane - default value used by IO::Socket::SSL. * RT#100151: LDAP.pm: localize $SIG{__DIE__} in IPv6 support check Thanks to Troy Loveday for the detailed bug report and patch. * FAQ.pod: fix error in search() example * RFC.pod: typo fix 0.64 -- Thu Jun 19 17:48:08 CEST 2014 Bug Fixes: * LDAP.pm: set SSL_cipher_list correctly * RT#96203: LDAP.pm: use correct length for syswrite * LDIF.pm: fix next outside loop in _write_one_entry * Entry.pod: fix typo 0.63 -- Sun Jun 1 12:42:59 CEST 2014 Enhancements: * Entry.pm: accept options for update() in the LDIF case * LDIF.pm: - implement writing controls - refactor _write_entry - check for decoding errors in LWP-based URLs Bug Fixes: * RT#95001: Do not set SSL_ciphers to ALL by default * Entry.pm: delete(): return $self if called w/o args 0.62 -- Sun Apr 6 11:25:05 CEST 2014 Enhancements: Util.pm: remove superfluous space from POD FAQ.pm: update perl-ldap & Perl version numbers Bug Fixes: RT#94357: t/08time.t: skip tests on too old Perl versions RT#94341: FAQ.pm: fix incorrect instruction jpegDisplay.pl: overhaul to make it work again 0.61 -- Sat Mar 29 17:21:45 CET 2014 Enhancements: * {LDAP,LDIF}.pod: update documentation of raw => REGEX * support LWP-supproted URLs when reading LDIFs (incl. tests) * add test for Net::LDAP::Util's time functions * tests: set default OpenLDAP DB type to mdb Bug Fixes: * RT#94047: Control.pm: add missing word in POD * RT#93945: Util.pm: make sure $dec is defined * LDIF.pm: when reading LDIFs, allow control values to be absent * Control/ProxyAuth.pm: fix initialization using value => ... * Util.pm: fix corner cases in time conversion functions 0.60 -- Sat Mar 8 14:00:02 CET 2014 Enhancements: * IO::Socket::IP support - if installed in version 0.20 or higher, prefer it over IO::Socket::INET* - use IO::Socket::INET* as fallback if it isn't installed - this solves RT#93122, which IMHO is not really a bug of perl-ldap * remove trailing whitespace in contrib/* 0.59 -- Tue Mar 4 16:21:15 CET 2014 Bug Fixes: * Handle SASL security layers correctly on rebind Thanks Ben Morrow * Control/Paged.pm: fix typo in POD sample code Enhancements: * t/60cancel.t: add explanation about potential cause of failure * LDAP.pm: accessor method sasl for Authen::SASL object * LDAP.pm: adapt socket() to support SASL layers * Message.pod: consolidate dcwocumentation of control() * Control.pm: documentation update * LDAP.pod: add note about IO::Socket::IP and Timeout * LDIF.pm: overhaul - set error when write fails - simplify _read_entry - simplify _write_entry - coding style harmonization - error checks when reading changetype: delete - make _error() return undef/empty list, adapt callers - refactor handling DNs when reading - new method _read_attribute_value() 0.58 -- Mon Dec 23 17:35:53 CET 2013 Bug Fixes: * RT#91210: Paged.pm: fix example code * RT#90459: LDAP.pm: make LDAPS work after LDAP+start_tls * RT#91177: AD.pm: fix change_ADpassword() * RT#88792: Constant.pm: add LDAP_CONTROL_SORTRESPONSE Enhancements: * Filter.pod: remove misleading text * typo fixes * RT#91156: add META.json * DSML.pm, Protocol/ldap.pm: use MIME::Base64::decode() * make MIME::Base64 mandatory * README: update optional modules, slight reorganization * Entry.pod: update documentation of N:L:E->update * Makefile.PL: require Text::Soundex for tests 0.57 -- Sun Jul 21 18:35:12 CEST 2013 COMPATIBILITY WARNING: The bug fix "LDAP.pm: new parameter bind(sasl_host => SASLHOST)" is an incompatible change that may break some corner-case configurations * that use SASL for authentication and * where the SASL host name differs from the host name connecting to. The incompatible change was necessary as it was not possible to fix the issue which was introduced in perl-ldap 0.37 in a compatible way. See Net::LDAP's manual page for the details on "sasl_host". Bug Fixes: * LDAP.pm: new parameter bind(sasl_host => SASLHOST) * Entry.pm: ignore options when update()ing LDIF * Entry.pm: let update() fail correctly on illegal target * RT#86053: FAQ.pod: fix spelling error * *.{pm,pod}: lots of more grammar & spelling fixes / harmonizations Enhancements: * LDAP.pm: use data_ready() in process() * Util.pm: simplify return on error * Constant.pm: add constant LDAP_CONTROL_NOOP * Schema.pm: call isa() as recommented in UNIVERSAL.pm 0.56 -- Sat Jun 8 13:14:47 CEST 2013 Bug Fixes: * RT#85941: LDAP.pm: new method data_ready() * RT#84886: Control/Relax.pm: fix typo in documentation Enhancements: * FAQ.pod: add more directory servers * t/07filtermatch.t: skip some tests unless Text::Soundex is installed * t/74matchedvalues.t: new, tests for MatchedValues control * t/73assert.t: new, tests for Assertion control * LDIF.pm: overhaul - flexibilize mode handling, accept PerlIO layers - get rid of dependency on Symbol & SelectSaver - convert _write_... to object methods - use indirect file handles for URLs * LWP/Protocol/ldap.pm: use regex as 1st arg to split() 0.55 -- Tue Apr 23 11:18:15 CEST 2013 Bug Fixes: RT#84410: PersistentSearch.pm: use $message->pop_entry() in example RT#84774: Constant.pm: unbreak Novell eDirectory constants Enhancements: Control/ManageDsaIT.pm: update documentation & simplify a bit Control/Relax.pm: new Constant.pm: add LDAP_CONTROL_RELAX LDAP.pod: omit space from filter in synopsis FAQ.pod: don't talk of "2 lines" when there's only one Extra/eDirectory.pm: fix typo, space police 0.54 -- Fri Mar 29 12:07:40 CET 2013 Bug Fixes: * RT#73202: LDIF.pm: Base64-encode values ending in spaces * RT#83815: fix typo/bug in example for root_dse Enhancements: * FAQ.pod: mention Dancer::Plugin::LDAP, update example * Extra/eDirectory.pm: new; extensions for eDirectory * Constant.pm: add constants for Novell eDirectory * LDIF.pm: clean up handling of mode parameter * LDIF.pm: partially support controls when reading * Util.pm: add time conversion functions * Makefile.PL: update recommends, add comments on core modules * FAQ.pod: update info on required/optional modules * LDAP.pod,FAQ.pod: harmonize documentation of scope values 0.53 -- Sat Jan 26 18:23:35 CET 2013 Bug Fixes: * various clarification & fixes in documentation * t/7{1pre,2post}read.t: don't use deprecated methods Enhancements: * Filter.pm: new method negate() * Util.pm: new function ldap_url_parse() * RT#77716: LDAP.pm: new option keepalive for new() * LDAP.pm: convert scheme to lowercase in new() * FAQ.pod: how to search all members of a large AD group * FAQ.pod: how to do nested group searches in AD 0.52 -- Tue Jan 1 13:54:22 CET 2013 Bug Fixes: * fix PreRead & PostRead controls * AD.pm: fix typo in documentation Enhancements: * add tests for PreRead & PostRead controls * FAQ.pm: example for certificateExactMatch * coding style overhaul: * use single-quoted strings where possible * 2 SPACEs before postfix if,unless,or,and * SPACE after comma * SPACE between if,elsif,unless,while,for and ( * make private lexical variables more private * unquote identifiers before => * unquote identifiers used as hash keys 0.51 -- Sat Dec 1 14:37:35 CET 2012 Bug Fixes: * RT#81380: in Filter.pm unescape hexpairs and ( ) \ * only * tests: compare files in "text mode" * Makefile.PL: mention all requirements for tests Enhancements: * Schema.pod: document attribute_syntax() * contrib/schema2ad.pl: new, convert schema file to something AD can digest 0.50 -- Sat Nov 24 13:03:45 CET 2012 Bug Fixes: * t/07filtermatch.t: use core module Text::Soundex instead of String::Approx * Message.pm: fix regression w.r.t. Net::LDAP::Message::Dummy Enhancements: * Makefile.PL: make dependencies reflect reality better * LDAP.pm: avoid warning in new() that might have occurred in corner cases 0.50_01 -- Sat Nov 17 18:05:15 CET 2012 Bug Fixes: * RT#80482 fix display of =item inet6 in LDAP.pod * RT#66753: new key & cert for SSL server tests * RT#79763 Net::LDAP::Util's $VERSION increased * t/06constant.t: numbering glitch in t/06constant.t * FilterMatch.pm: fix mapping of greaterOrEqual * FAQ.pod: small fixes Enhancements: * add constant LDAP_PROXY_AUTHZ_FAILURE * FilterMatch.pm: complete overhaul - update matching rules known in OpenLDAP - support matching rules for extensibleMatch - avoid warning if no matching rule is found - add specific implementations for a lot of rules * global overhaul towards Perl 5.8 features - declare @ISA and $VERSION as package-local - replace 'use vars' by 'our'. * Makefile.PL: overhaul * tests: cleanup & extensions - convert to Test::More - t/common.pl: allow client() to take options for Net::LDAP - t/common.pl: get rid of local compare function - t/03schema.t: overhaul, update data/schema.in - t/07filtermatch.t: new, tests for Net::LDAP::FilterMatch - t/40connect.t: new, test for IPv4 / IPv6 connections - reorganize servers tests: rename t/5X*.t -> t/4(X+1)*.t - t/47ipc.t: add TLS tests - t/60cancel.t: new, tests for Net::LDAP::Extension::Cancel - t/70sortctrl.t: make it a server test & add multi-attribute testcase 0.49 -- Sat Oct 5 10:00:30 CEST 2012 Bug Fixes: * RT#79763 extend ldap_explode_dn() for RFC 4514 * RT#77291 canonicalize host name with ldapi:// * LDAP.pm: don't try to set errors on undefined objects Extensions: * Net/LDAP/Extra/AD.pm: convenience functions for AD * various documentation updates 0.48 -- Thu Sep 20 10:55:20 CEST 2012 Bug Fixes: * Util.pm: fix bug in escape_dn_value() * t/55ssl.t: fix typos in output text * LDIF.pm: with encode => 'canonical', do mbcescape DNs * the usual typo fixes in docs Enhancements: * ASN.pm: adapt to RFC 4511 * Extension/{SetPassword,Refresh}.pm: polish ASN.1 definition * LWP/Protocol/ldap.pm: respond with requested MIME type * LWP/Protocol/ldap.pm: document 'x-format' URI extension * LWP/Protocol/ldap.pm: add DSMLv1 as output format * test routines updated to work with recent OpenLDAP * removed trailing spaces * support OpenLDAP extension: scope => "children" 0.47 -- Sun Sep 16 12:00:30 CEST 2012 Bug Fixes * contrib/ldifdiff.pl: fix POD * Intermediate/SyncInfo.pm: fix newcookie() method * LWP/Protocol/ldap.pm: complete overhaul Enhancements * more feature constants in Net/LDAP/Constant.pm * new features & documentation for LWP/Protocol/ldap.pm * LWP/Protocol/ldapi.pm: support ldapi:// URIs with LWP * contrib/LWPsearch.pl: demo program for LWP::Protocol::ldap* * update link list in the FAQ * update references to RFCs 0.46 -- Wed Sep 5 18:09:00 CEST 2012 Bug Fixes * LDAP.pm: unbreak - make done a real sub * Message.pm: fix typo, i.e. add forgotten ';' Enhancements: * FAQ.pod: update URLs a bit more 0.45 -- Wed Sep 5 11:20:46 CEST 2012 Bug Fixes * RT#72108 fix non-blocking IO with SSL * RT#74572 fix $entry->update($ldif) * RT#74759 fix POD spelling/grammar errors * RT#77180 use "sslv23" instead of "sslv2/3" for sslversion * work around a warning in Authen::SASL::Perl <= 2.1.5 * various typo fixes in documentation Enhancements * RT#77458 re-work IPv6 support * Don't accumulate intermediate messages passed to a callback. * slightly extend Net::LDAP::Entry->update() and document it * convenience alias done() for Net::LDAP->unbind() * various updates to the FAQ 0.44 -- Sun Jan 29 10:36:08 CET 2012 Bug Fixes * un-break certificate verification * fixes for the ProxyAuthorization control * fix typos & spelling errors in POD Enhancements * MANIFEST.SKIP: sync with Perl 5.14.2's ExtUtils version * Makefile.PL: update resource info on repository * new extended operation Net::LDAP::Extension::Cancel * new control Net::LDAP::Control::MatchedValues * new control Net::LDAP::Control::Assertion * update reference documents in POD * extend documentation for Pre-Read & Post-Read controls * add error string for LDAP_VLV_ERROR * add result codes for VLV and cancel * add constant for DontUseCopy control * add constant for PermissiveModify control 0.43 -- Sat Sep 3 12:50:49 CDT 2011 * Fix copy & paste errors in Net::LDAP::Message 0.42 -- Sat Sep 3 07:46:06 CDT 2011 * Check whether LDAP socket object has a peerhost() method defined before calling it. This fixes SASL authentication over UNIX domain (ldapi://) sockets. [Chris Mikkelson] 0.41 -- Sat Sep 3 07:37:31 CDT 2011 * use of non-localised $_ in Net::LDAP::Constant causes prolems in lemonldap-ng [Damyan Ivanov] * Added cn,o,ou to the default set of case-insensitive attributes [Kartik Subbarao] * Entry.pod: fix typos [Peter Marschall] * extend Net::LDAP::Entry->update() to take LDIF objects [Peter Marschall] * Specify that we want to use the 'ldap' scheme to verify certificates. [Kevan Carstensen] 0.4001 -- Wed Mar 24 14:54:35 CDT 2010 * Update Module::Install and generate META.yml 0.40 -- Thu Mar 11 20:56:28 CST 2010 * Avoid 'cookie parsing error' on OpenLDAP 2.3 [Mathieu Parent] * Added e-syncRefreshRequired constant [Mathieu Parent] * Minor typo fix in documentation [Quanah Gibson-Mount] * Update CREDITS for Mathieu Parent * Remove runtime dependency on DATA handle for constants * Clarify documentation for gen_password * Allow caller to pass Authen::SASL client_new object * fix typo [Peter Marschall] * use current IO::Socket::SSL's method start_SSL instead of deprecated function socketToSSL; raise required IO::Socket:SSL version appropriately [Peter Marschall] * FilterMatch.pm: fix regex treatment in _{cis,exact}_substrings(). [Peter Marschall] * FilterMatch.pm: correct # of args in function declarations/definitions [Peter Marschall] * Don't duplicate documentation [Mathieu Parent] * Added numcmp option to compare attributes numerically. [Kartik Subbarao] * Avoid infinite loop when authenticating with EXTERNAL mechanism * Add Net::LDAP::Extension::Refresh as described in RFC2589 [Etienne Bagnoud] * RT#40068 Fix tests to work with 2.4.11 * Add ldif method to Net::LDAP::Entry * RT#46111 Make LWP::Protocol::ldap return ldif when requested * RT#51165 Compact multiple consecutive spaces in Net::LDAP::Util::canonical_dn * RT#46125 Add LWP::Protocol::ldaps to support ldaps: urls * RT#44110 Fix Net::LDAP::LDIF->current_lines perl-ldap 0.39 -- Mon Oct 27 15:02:37 CDT 2008 ============================================== Bug Fixes * Several fixes to the handling of IntermediateMessage and LDAP Content synchronisation * Fix dsmt test to not fail on win32 * Fix Net::LDAP::Util to not cause Undefined subroutine &Net::LDAP::Util::ldap_error_desc perl-ldap 0.38 -- Sun Sep 21 09:17:25 CDT 2008 ============================================== Bug Fixes * Fix bug in Net::LDAP::Extension using wrong field for resultCode * Fix Net::LDAP::Control::PasswordPolicy decoding bug. Enhancements * Net::LDAP::Extension::SetPassword now supports controls perl-ldap 0.37 -- Thu Aug 28 07:48:13 CDT 2008 ============================================== Bug Fixes * Pass correct hostname to SASL when connecting to a round-robin * Return the SASL error message when sasl client_start fails Enhancements * Add Modify Increment (RFC 4525) support * Add Content Synchronization (RFC 4453) support perl-ldap 0.36 -- Mon Apr 21 10:00:09 CDT 2008 ============================================== Bug Fixes * Fixed Net::LDAP::constant to return correct names for values 0 - 9 * Fixed DSML test to be more tolerant of whitespace Enhancements * Added controls for PreRead & PostRead perl-ldap 0.35 -- Sun Mar 30 13:35:04 CDT 2008 ============================================== Bug Fixes * Fix wrapping in Net::LDAP::LDIF * Patch from Gergely Santa to allow entries with no attributes in LDIF * Fix modr?dn to fetch values in sclar context * send packets in sizes that IO::Socket::SSL can chew * Avoid attept to use undef as hash reference in ->sync * Ensure Bind.pm presents final server response to SASL object Enhancements * Added vendorName/vendorVersion (RFC 3045) to root_dse() * add option to support IPv6 * Allow Entry->deleted to be called with a single value is well as array ref * Added Net::LDAP::Control::PasswordPolicy to support draft RFC perl-ldap 0.34 -- Sat Feb 10 17:39:49 CST 2007 ============================================== Bug Fixes * Improve dealing with mixed case attributes in Net::LDAP::Entry * Documentation fixes & updates * Don't let Net::LDAP->bind() die on SASL errors * Fix case-folding in Net::LDAP::Util::ldap_explode_dn() * Saner default for ldapi socket * Update test suite to work with recent OpenLDAP versions * The usual bunch of typo fixes * Fix escaping on non-ascii characters in Net::LDAP::Filter Enhancements * Flexible handling of line ends in Net::LDAP::LDIF when reading * Improve writing speed in Net::LDAP::LDIF * Net::LDAP accessor methods for scheme, host, port, URI connected to * New checkcrl option to Net::LDAP->new() to do CRL checking * New package Net::LDAP::Filtermatch for client side filtering * More ASN1 messages handled in Net::LDAP:ASN: IntermediateResponse * Option 'raw' to return Perl UTF-8 strings from queries (requires Perl 5.8) * Support Active Directory's extendedAttributeInfo schema information * Method to find matchingrule for an attribute in Net::LDAP:Schema * Updated build dependecies: GSSAPI support, .. perl-ldap 0.33 -- Mon Apr 25 08:02:26 CDT 2005 ============================================== Bug Fixes * Removed superfluous "print" in Net::LDAP::LDIF before _write_attr on writing * Base64 encode any value starting with < in Net::LDAP::LDIF * Documentation updates * Fix case insensitivity issues in contrib/ldifdiff.pl Enhancements * Added Net::LDAP::Extension::WhoAmI * Added write_version() and handle() methods to Net::LDAP::LDIF * Updated Net::LDAP::Control::ProxyAuth to support new OID from latest rfc-draft * Added contrib/recursive-ldap-delete.pl * Added ability to do case in comparisons to contrib/ldifsort.pl perl-ldap 0.3202 -- Mon Jul 19 11:44:08 BST 2004 ================================================ Bug Fixes * Fixed case typo in Makefile.PL perl-ldap 0.3201 -- Wed Jul 14 21:52:59 BST 2004 Bug Fixes * Fixed dependancies in Makefile.PL perl-ldap 0.32 -- Bug Fixes * Documentation updates * Fixed LDIF output from ldapsearch command * Return an error if no filter is passed to Net::LDAP::filter->parse * Fixed bug handling comments in LDIF parser * Fix to ldapsearch for passing scope with -s * Do not send a fake userid in SASL binds * Net::LDAP::Schema->parse() now returns undef on errors Enhancements * Added supportedFeatures to the default list of attributes fetched by ->root_dse * Added option to sort attributes in LDIF output, with objectclass being first floowed by all other attributes in alphabetical order * Add escape/unescape filters/DN utility functions * Added support for reading LDIF URL attributes using file:// * The socket created by new can now be bound to a local address & port * Any controls returned by the server with each entry as a result from a search are now available in the callback function * Added classes for EntryChange, PersistentSearch and ManageDsaIT controls * Allow options passed to Net::LDAP::Entry-.update to be passed to the Net::LDAP method that is finally called perl-ldap 0.31 1 Jan 2004 ========================== * Fixed bug that could cause methods to return an integer instead of an object * Fixed bug causing Schema.pm to ignore superior classes that had no attributes * Documentation updates * Updates to LDIF module perl-ldap 0.30 17 Oct 2003 ========================== * Documentation updates * Fixed bug checking return value of client_step in bind() * Fixed bug in Entry.pm causing method calls on unblessed references perl-ldap 0.29 24 Jun 2003 ========================== * Workaround bug in IO::Socket::SSL when startTLS fails * Fix reference loop memory leak problem * Add a SIGNATURE to the distribution * Re-added support for :all in the import list to get all constants * New methods error_name, error_text, error_desc added to Message.pm perl-ldap 0.28 19 May 2003 ========================== * Net::LDAP::Entry object can now be cloned * New class Net::LDAP::RootDSE * Net::LDAP->new can now accept URLs for the host * Added support for ldapi: * Now supports Notice of disconnection * Net::LDAP::Constant now implements its own import function, it no longer inherits from Exporter. So :all and /^LDAP_CONTROL/ etc are no longer valid arguments for import. The result is that Net::LDAP::Constant only defined the subs that are needed. perl-ldap 0.27 27 Jan 2003 ========================== * Default protocol version is now version 3 * Fixed support for multiple hosts to be passed to new perl-ldap 0.26 18 Jul 2002 ========================== * canonical_dn and ldap_explode_dn have a new implementation. * Net::LDAP::DSML reimplemented using XML::SAX * Net::LDAP::Schema reimplemented. API needed to change to fix many bugs in previous implementation * Added support for version number in Net::LDAP::LDIF (support for fill version still todo) perl-ldap 0.251 15 May 2002 =========================== * Added support for Adamson's SASL authentication * Both Cyrus SASL and Perl SASL modules are sought perl-ldap 0.25 29 Oct 2001 ========================== * Added support for EXTERNAL SASL authentication * Caller can now specify attributes to return from root_dse * More scripts added to contrib * Various bug fixes * Caller can now specify sslversion for LDAPS and start_tls perl-ldap 0.24 17 July 2001 =========================== * Added support for startTLS * Better error checking in Net::LDAP methods * VLV control now works * Can now use oid or name for the matchingRule in filter extensible matches * Major overhaul of LDIF.pm * $schema->name2oid is now context sensetive * test suite now works with openldap2 perl-ldap 0.23 April 20 2001 ============================ * Fixed bug in Net::LDAP::Filter when the filter contained an escaped * * Fixed SASL bind to call challenge with serverSaslCreds * Fixed some uninit errors in Net::LDAP::Entry * Various documention updates * Added Net::LDAP::Util::canonical_dn * Net::LDAP::LDIF will now call canonical_dn for any DN which contains non-printable characters * Added support for matchingruleuse, ditstructurerules, ditcontentrules and nameForms into Net::LDAP::Schema * The ->schema method in Net::LDAP has changed how it finds the schema to return. The new method is more correct, but there may be a possibility that this change has created an incompatability. * New control module Net::LDAP::Control::ProxyAuth from Olivier Dubois added * Added support for moddn in Net::LDAP::LDIF. * Minor fixes to the DSML output (fixing illegal XML.) perl-ldap 0.22 September 14 2000 ================================ * Quick release to fix memory problem with 5.6.0 perl-ldap 0.21 September 12 2000 ================================ * Change ->get back to return what 0.19 returned * Deprecate ->get in favor of ->get_value * Net::LDAP::Schema now supports matchingRules * Added experimental onerror option to ->new * New FAQ by Clif Harden perl-ldap 0.20 August 3 2000 ============================ * Added INSTALL and CREDITS files * Net::LDAP::Entry ->get and ->attributes methods now support options * Added Net::LDAP::DSML from Mark Wilcox * Added Net::LDAPS from Chris Ridd * Many documentation updates * Several fixes to ::Control::* classes, they should now work as intended. * Net::LDAP::Entry->get now always returns a scalar result as documented. * bin/ldapsearch now requires URI-1.08 perl-ldap 0.19 June 8 2000 ============================ * Fixed bug which caused 2nd and subsequent binds to be anonymous. * Fixed bug in moddn. * Fix bug which caused a call to ->pop_entry or ->shift_entry to hang forever. perl-ldap 0.18 May 22 2000 ============================ * Now passes -wc with 5.004, 5.005_03 and 5.6.0 * Bundle now correctly references Convert::ASN1 instead of the non-existant Convert::ASN * Net::LDAP::Filter will now catch the case of unmatched ()'s and return an error * as_struct, which was broken in the changeover to Convert::ASN1, now works again. KNOWN PROBLEMS -------------- Test t/02filter.t fails with perl 5.6.0 compiled with threads enabled This is due to a bug in 5.6.0 when compiled with threads, see http://bugs.perl.org/perlbug.cgi?req=tidmids&tidmids=20000409.003&range=32323&format=h perl-ldap 0.17 May 12 2000 ============================ * Change to use asn_read instead of asn_resc. This seems to have fixed the known problem with 0.16 * Various bug fixes, see ChangeLog perl-ldap 0.16 April 27 2000 ============================ * This is the first release which uses Convert::ASN1 instead of Convert::BER. This should show an increase in performance. * Added support for LDAPv3 controls. Controls supported are - VirtualListView - Sort - Paged * HTML version of the documentation is now included in the distribution * Added Bundle::Net::LDAP * Net::LDAP->schema can now be told where to search for the schema. KNOWN PROBLEMS -------------- In a pre-release of 0.16 it has been seen that a search result may not contain all entries and $mesg->code will be LDAP_DECODING_ERROR. This has been seen when the client is running on NT or Linux and the server is an Exchange server. libnet-ldap-perl-0.6500+dfsg.orig/install-nomake0000755000175000017500000000153712350606574020771 0ustar gregoagregoa#!/bin/sh # # This script is included in this distribution for the benefit # of those users who cannot use MakeMaker and make to install. # Run this script with # # perl install-nomake [-s ] # # -s Install into this directory instead of the system site_lib # (This directory must already exist) # eval 'exec perl -x -S $0 ${1+"$@"}' if $running_under_some_shell; #! -*- perl -*- use Config; use File::Spec; use Getopt::Long; use ExtUtils::Install qw(install); my $sitelib = $Config{'sitelibexp'}; GetOptions( 'sitelib=s' => \$sitelib ); die "$sitelib is not a directory: $!" unless -d $sitelib; my $src = File::Spec->catdir(File::Spec->curdir, 'lib'); die "This script must be run from the perl-ldap distribution directory: $!\n" unless -f File::Spec->catfile($src, qw(Net LDAP.pm)); install( { $src => $sitelib }, 1,0,0); libnet-ldap-perl-0.6500+dfsg.orig/MANIFEST.SKIP0000644000175000017500000000162112350606574020015 0ustar gregoagregoa# Avoid version control files. \bRCS\b \bCVS\b \bSCCS\b ,v$ \B\.svn\b \B\.git\b \B\.gitignore\b \b_darcs\b \B\.cvsignore$ # Avoid VMS specific MakeMaker generated files \bDescrip.MMS$ \bDESCRIP.MMS$ \bdescrip.mms$ # Avoid Makemaker generated and utility files. \bMANIFEST\.bak \bMakefile$ \bblib/ \bMakeMaker-\d \bpm_to_blib\.ts$ \bpm_to_blib$ \bblibdirs\.ts$ # 6.18 through 6.25 generated this # Avoid Module::Build generated and utility files. \bBuild$ \b_build/ \bBuild.bat$ \bBuild.COM$ \bBUILD.COM$ \bbuild.com$ # Avoid temp and backup files. ~$ \.old$ \#$ \b\.# \.bak$ \.tmp$ \.# \.rej$ # Avoid OS-specific files/dirs # Mac OSX metadata \B\.DS_Store # Mac OSX SMB mount metadata files \B\._ # Avoid Devel::Cover and Devel::CoverX::Covered files. \bcover_db\b \bcovered\b # Avoid MYMETA files ^MYMETA\. # perl-ldap-sepcifc extensions \b_dev/ \b_test/ \btemp/ \bperl-ldap-\d \bmy.cfg$ # EOF libnet-ldap-perl-0.6500+dfsg.orig/INSTALL0000644000175000017500000000252012350606574017147 0ustar gregoagregoaIf you are on a system where you can run the Makefile.PL and use make, then the package can be installed using the normal MakeMaker process, that is gunzip perl-ldap-*.**.tar.gz tar xvf perl-ldap-*.** cd perl-ldap-*.** perl Makefile.PL make make test make install If you are on a system where this is not possible you will need to perform the following, after ensuring that any dependant libraries are installed (see README) perl -V This will output information about your perl installation. Near the end of this you will see something like @INC: /usr/local/lib/perl5/5.6.0/i686-linux /usr/local/lib/perl5/5.6.0 /usr/local/lib/perl5/site_perl/5.6.0/i686-linux /usr/local/lib/perl5/site_perl/5.6.0 /usr/local/lib/perl5/site_perl . You need to find the site_perl directory with the perl version specified, in this case it is /usr/local/lib/perl5/site_perl/5.6.0 You then need to copy the contents of the lib/ directory from the distribution with the equivalent of the following for your platform. gunzip perl-ldap-*.**.tar.gz tar xvf perl-ldap-*.** cd perl-ldap-*.**/lib cp -r * /usr/local/lib/perl5/site_perl/5.6.0 To use the basics of perl-ldap there is only one dependancy, Convert::ASN1, all others are optional depending on if you want to use a given functionality. See the README file for a list. libnet-ldap-perl-0.6500+dfsg.orig/CREDITS0000644000175000017500000000255612350606574017147 0ustar gregoagregoaAlthough the Net::LDAP module was originally written by Graham Barr it has grown far beyond initial expectations and scope. In fact it has gone far beyond a lot of things. As Net::LDAP has grown into the perl-ldap distribution credit can no longer be given to any single individual, but instead belongs to a group of people who have contributed. Some more than others, but whos counting :) --------------- CAST AND CREW --------------- To give due honor to those who have made perl-ldap what is is today, here are some of the people who have contributed, either in code, documentation or just ideas/feedback. If I have missed anyone, please let me know. Graham Barr Russell Fulton Rusty Biggs Clif Harden Chris Ridd Mark Wilcox Robbie Allen Bryan Thale Jim Harle Kurt D. Zeilenga Simon Wilcox Kartik Subbarao Norbert Klasen David Faltermier Ziya Suzen Damon Brodie Peter Marschall Paul David Fardy Derik Pates Mathieu Parent libnet-ldap-perl-0.6500+dfsg.orig/README0000644000175000017500000000421012507234571016772 0ustar gregoagregoaperl-ldap - A Client interface to LDAP servers Copyright (c) 1997-2004 Graham Barr. All rights reserved. This package is free software; you can redistribute it and/or modify it under the same terms as Perl itself. ******************************************************************************* This code should be considered very much as work-in-progress. Any part of this release could be subject to change. The development of the distribution is discussed on a mailing list at perl-ldap@perl.org To subscribe send an empty email to perl-ldap-subscribe@perl.org ******************************************************************************* For the latest information see http://ldap.perl.org/ QUICK START GUIDE: perl-ldap uses the following modules/distributions. MIME::Base64 - required, core module since Perl 5.7.3 Convert::ASN1 - required IO::Socket::SSL - optional, for LDAPS / start_tls support IO::Socket::INET6 - optional, for IPv6 support IO::Socket::IP - optional, for IPv6 support Authen::SASL - optional, for SASL authentication Digest::MD5 - optional, for SASL DIGEST-MD5 mechanism GSSAPI - optional, for SASL GSSAPI mechanism URI::ldap - optional, for URL parsing XML::SAX::Writer - optional, for Net::LDAP::DSML Time::Local - optional, for Net::LDAP::Util's time conversion functions If IO::Socket::IP 0.20 or higher is installed, it is dynamically (at runtime) preferred over IO::Socket::INET6. First ensure the above modules/distributions are installed then build/test/install Net::LDAP by doing perl Makefile.PL make make test make install Several modules in the distribution contain documentation. Once installed you can use the 'perldoc Net::LDAP' command to obtain the documentation. This documentation will contain pointers to the other modules. ******************************************************************************* NOTE: Everything that has been deprecated will be removed when V1.00 is released, but who knows when that will be. ******************************************************************************* Share and Enjoy! libnet-ldap-perl-0.6500+dfsg.orig/TODO0000644000175000017500000000340512350606574016611 0ustar gregoagregoaproxy server Write a proxy server that can dump PDU's from the real server to a file. Then later play these back. This would allow benchmarking to produce more reliable figures. Net::LDAP::LDIF Still need to add support for moddn Authentication Authen::SASL Needs completion and documentation command line utilities ldapmodify ldapadd Net::LDAP::Utils utility functions like explode_dn CLDAP performance testing/tuning Documentation, Modules The docs need to be "beefed up" with more descriptions of what the operation performs, instead of assuming the user knows and just describing the arguments. Maybe steal^Wborrow from other docs and the RFCs FAQ Need an active maintainer Examples Needs to be rewritten so that all code is in a consistant format. Net::LDAP::Intro An introduction to LDAP POD Website Need to find an active maintainer with a creative touch Testcases Need more tests for anything that can be tested without a server. Referral Add a rebind option new() which is a sub. The sub will be passed a hostname and should return a new ldap object. For this to work we need to be able to chain multiple requests behind a single message object so that it looks seamless to the calling script. This would be useful for LDAPiranah Errors local vs protocol errors Controls rfc2649 - Operation Signatures dup ent control General Move the TCP connect out of new() and into a connect() method Add a configure/cget methods for options, async and version methods become deprecated rename _recvresp and document to make available for async users if bind() is passed options then require an auth option, stop accidental anon binds. make bind(password => '') illegal, force then to use noauth => '' libnet-ldap-perl-0.6500+dfsg.orig/t/0000755000175000017500000000000012510544053016351 5ustar gregoagregoalibnet-ldap-perl-0.6500+dfsg.orig/t/09ldif-http-url.t0000644000175000017500000000162512507234571021415 0ustar gregoagregoa#!perl use Test::More; use Net::LDAP::LDIF; use Net::LDAP::Entry; BEGIN { require "t/common.pl" } (eval { require LWP::UserAgent } && $HTTP_JPEG_URL && $HTTP_TEXT_URL) ? plan tests => 4 : plan skip_all => 'LWP::UserAgent module not installed or HTTP_JPEG_URL, HTTP_TEXT_URL not set'; my $ldifdata = <<"LDIF"; dn: cn=Sam One,ou=People,o=University of Michigan,c=US jpegPhoto:< $HTTP_JPEG_URL objectclass: OpenLDAPperson cn: Sam One uid: sam sn: One postalAddress:< $HTTP_TEXT_URL LDIF open(my $ldifhandle, '<', \$ldifdata); my $ldif = Net::LDAP::LDIF->new($ldifhandle); isa_ok($ldif, Net::LDAP::LDIF, "object"); my $entry = $ldif->read_entry; isa_ok($entry, Net::LDAP::Entry, "entry"); my $photo = $entry->get_value('jpegPhoto'); ok(length($photo), 'jpegPhoto not empty'); my $address = $entry->get_value('postalAddress'); ok(length($address), 'postalAddress not empty'); #print STDERR $entry->dump ."\n"; libnet-ldap-perl-0.6500+dfsg.orig/t/73assert.t0000644000175000017500000001367412507234571020233 0ustar gregoagregoa#!perl use Test::More; use Net::LDAP; use Net::LDAP::Constant qw(LDAP_CONTROL_ASSERTION); use Net::LDAP::Control::Assertion; BEGIN { require "t/common.pl" } my @tests; { # parse DATA into a list (= tests) of hashes (= test parameters) of lists (= parameter values) local $/ = ''; while(my $para = ) { my @lines = split(/\n/, $para); my %params; chomp(@lines); @lines = grep(!/^\s*(?:#.*?)?$/, @lines); map { push(@{$params{$1}}, $2) if (/^(\w+):\s*(.*)$/) } @lines; push(@tests, \%params) if (%params); } } start_server() ? plan tests => 4 + 2 * scalar(@tests) : plan skip_all => 'no server'; $ldap = client(); isa_ok($ldap, Net::LDAP, "client"); $rootdse = $ldap->root_dse; isa_ok($rootdse, Net::LDAP::RootDSE, "root_dse"); SKIP: { skip("RootDSE does not offer Assertion control", 2 + 2 * scalar(@tests)) unless($rootdse->supported_control(LDAP_CONTROL_ASSERTION)); #$mesg = $ldap->start_tls; #ok(!$mesg->code, "start_tls: " . $mesg->code . ": " . $mesg->error); $mesg = $ldap->bind($MANAGERDN, password => $PASSWD); ok(!$mesg->code, "bind: " . $mesg->code . ": " . $mesg->error); ok(ldif_populate($ldap, "data/40-in.ldif"), "data/40-in.ldif"); foreach my $test (@tests) { $control = Net::LDAP::Control::Assertion->new(assertion => $test->{assertion}->[0]); isa_ok($control, Net::LDAP::Control::Assertion, "control object"); if ($test->{action}->[0] eq 'search') { $mesg = $ldap->search(base => $test->{dn}->[0], filter => $test->{filter} ? $test->{filter}->[0] : '(objectclass=*)', scope => $test->{scope} ? $test->{scope}->[0] : 'sub', control => $control); is($mesg->code, $test->{code}->[0] || 0, ($test->{code}->[0] ? "search [expecting ".$test->{code}->[0]."]: " : "search: ") . $mesg->code . ": " . $mesg->error); } elsif ($test->{action}->[0] eq 'compare') { $mesg = $ldap->compare($test->{dn}->[0], attr => $test->{attr}->[0], value => $test->{value}->[0], control => $control); is($mesg->code, $test->{code}->[0] || 6, ($test->{code}->[0] ? "compare [expecting ".$test->{code}->[0]."]: " : "search: ") . $mesg->code . ": " . $mesg->error); } elsif ($test->{action}->[0] eq 'modify') { $mesg = $ldap->modify($test->{dn}->[0], $test->{changetype}->[0] => { map { $_ => $test->{$_} } @{$test->{attrs}} }, control => $control); is($mesg->code, $test->{code}->[0] || 0, ($test->{code}->[0] ? "modify [expecting ".$test->{code}->[0]."]: " : "modify: ") . $mesg->code . ": " . $mesg->error); } elsif ($test->{action}->[0] eq 'moddn') { my %sup = $test->{newsuperior} ? ( newsuperior => $test->{newsuperior}->[0] ) : (); $mesg = $ldap->moddn($test->{dn}->[0], newrdn => $test->{newrdn}->[0], %sup, control => $control); is($mesg->code, $test->{code}->[0] || 0, ($test->{code}->[0] ? "moddn [expecting ".$test->{code}->[0]."]: " : "moddn: ") . $mesg->code . ": " . $mesg->error); } elsif ($test->{action}->[0] eq 'delete') { $mesg = $ldap->delete($test->{dn}->[0], control => $control); is($mesg->code, $test->{code}->[0] || 0, ($test->{code}->[0] ? "delete [expecting ".$test->{code}->[0]."]: " : "delete: ") . $mesg->code . ": " . $mesg->error); } else { ok(0, "illegal action"); note("test: ", explain($test)); } } } __DATA__ ## each section below represents one test; logic similar to , structure similar to LDIF # each tests needs at least the elements # - assertion: the assertion filter to use # - action: the action on which the assertion is to be tested # - dn: (base-)DN to use in the operation # - ...: all other elements depend on the operation [see above] # search (expect failing assertion) action: search dn: ou=People, o=University of Michigan, c=US filter: (cn=Babs Jensen) assertion: (title=Mythical Manager, Research Systems) code: 122 # search action: search dn: cn=Barbara Jensen, ou=Information Technology Division, ou=People, o=University of Michigan, c=US filter: (cn=Babs Jensen) assertion: (title=Mythical Manager, Research Systems) # modify action: modify dn: cn=Barbara Jensen, ou=Information Technology Division, ou=People, o=University of Michigan, c=US assertion: (title=MegaMythical Manager, Research Systems) changetype: replace attrs: title title: Uber-Mythical Manager, Research Systems title: Hyper-Mythical Manager, Research Systems code: 122 # modify action: modify dn: cn=Barbara Jensen, ou=Information Technology Division, ou=People, o=University of Michigan, c=US assertion: (title=Mythical Manager, Research Systems) changetype: replace attrs: title title: Uber-Mythical Manager, Research Systems title: Hyper-Mythical Manager, Research Systems # compare (expect failing assertion) action: compare dn: cn=Barbara Jensen, ou=Information Technology Division, ou=People, o=University of Michigan, c=US filter: (cn=Babs Jensen) assertion: (title=HyperMythical Manager, Research Systems) attr: sn value: Jensen code: 122 # compare action: compare dn: cn=Barbara Jensen, ou=Information Technology Division, ou=People, o=University of Michigan, c=US filter: (cn=Babs Jensen) assertion: (title=Hyper-Mythical Manager, Research Systems) attr: sn value: Jensen # moddn action: moddn dn: cn=Barbara Jensen, ou=Information Technology Division, ou=People, o=University of Michigan, c=US newrdn: cn=Babs Jensen assertion: (title=HyperMythical Manager, Research Systems) code: 122 # moddn action: moddn dn: cn=Barbara Jensen, ou=Information Technology Division, ou=People, o=University of Michigan, c=US newrdn: cn=Babs Jensen assertion: (title=Hyper-Mythical Manager, Research Systems) # delete action: delete dn: cn=Babs Jensen, ou=Information Technology Division, ou=People, o=University of Michigan, c=US assertion: (title=HyperMythical Manager, Research Systems) code: 122 # delete action: delete dn: cn=Babs Jensen, ou=Information Technology Division, ou=People, o=University of Michigan, c=US assertion: (title=Hyper-Mythical Manager, Research Systems) libnet-ldap-perl-0.6500+dfsg.orig/t/04refloop.t0000644000175000017500000000175112507234571020363 0ustar gregoagregoa#!perl use Test::More; use Net::LDAP qw(LDAP_UNAVAILABLE); my $devnull = eval { require File::Spec; File::Spec->devnull } || "/dev/null"; (-e $devnull) ? plan tests => 5 : plan skip_all => 'no null device'; $::destroy = 0; { my $ldap = Net::LDAP::Dummy->new("host", async => 1); $ldap->bind; # create an internal ref loop note(explain($ldap->inner)) if $ENV{TEST_VERBOSE}; } ok($::destroy, ''); my $ref; my $mesg; $::destroy = 0; { my $ldap = Net::LDAP::Dummy->new("host", async => 1); $mesg = $ldap->bind; # create an internal ref loop $ref = $ldap->inner->outer; is($ref == $ldap, ''); } ok(!$::destroy, ''); $ref = undef; ok($mesg->code == LDAP_UNAVAILABLE, ''); undef $mesg; ok($::destroy, ''); package Net::LDAP::Dummy; use IO::File; BEGIN { @ISA = qw(Net::LDAP); } sub connect_ldap { my $ldap = shift; $ldap->{net_ldap_socket} = IO::File->new("+> $devnull"); } sub DESTROY { my $self = shift; $::destroy = 1 unless tied(%$self); $self->SUPER::DESTROY; } libnet-ldap-perl-0.6500+dfsg.orig/t/60cancel.t0000644000175000017500000000403512507234571020142 0ustar gregoagregoa#!perl use Test::More; use Net::LDAP; use Net::LDAP::Entry; use Net::LDAP::Constant qw(LDAP_EXTENSION_CANCEL LDAP_CANCELED); use Net::LDAP::Extension::Cancel; BEGIN { require "t/common.pl" } start_server() ? plan tests => 7 : plan skip_all => 'no server'; $ldap = client(); isa_ok($ldap, Net::LDAP, "client"); $rootdse = $ldap->root_dse; isa_ok($rootdse, Net::LDAP::RootDSE, "root_dse"); SKIP: { skip("RootDSE does not offer cancel extension", 5) unless($rootdse->supported_extension(LDAP_EXTENSION_CANCEL)); #$mesg = $ldap->start_tls; #ok(!$mesg->code, "start_tls: " . $mesg->code . ": " . $mesg->error); $mesg = $ldap->bind($MANAGERDN, password => $PASSWD); ok(!$mesg->code, "bind: " . $mesg->code . ": " . $mesg->error); ok(ldif_populate($ldap, "data/40-in.ldif"), "data/40-in.ldif"); # cancel undef => should fail $cancel = $ldap->cancel(undef); ok($cancel->code, "cancel an undefined operation: " . $cancel->code . ": " . $cancel->error); # perform a search my $search = $ldap->search( base => $BASEDN, filter => '(objectclass=*)' ); # cancel the finished search => should fail $cancel = $ldap->cancel($search); ok($cancel->code, "cancel a finished operation: " . $cancel->code . ": " . $cancel->error); # switch to async mode $ldap->async(1); # perform a search (asynchronously) $search = $ldap->search( base => $BASEDN, filter => '(objectclass=*)', callback => \&process_entry, # Call this sub for each entry ); # cancel the running search => should work [may fail, as it depends on the server's speed] $cancel = $ldap->cancel($search); ok(!$cancel->code, "cancel a running operation: " . $cancel->code . ": " . $cancel->error) or diag("This test may have failed because the server was too fast"); } sub process_entry { my $m = shift; my $e = shift; note($m->mesg_id.':'.$e->dn()) if ($ENV{TEST_VERBOSE} && ref($e)); } libnet-ldap-perl-0.6500+dfsg.orig/t/48url.t0000644000175000017500000000145412507234571017527 0ustar gregoagregoa#!perl use Test::More; BEGIN { require "t/common.pl" } start_server() ? plan tests => scalar(@URL) * 5 + 7 : plan skip_all => 'no server'; $ldap = client(); ok($ldap, "client"); $mesg = $ldap->bind($MANAGERDN, password => $PASSWD); ok(!$mesg->code, "bind: " . $mesg->code . ": " . $mesg->error); ok(ldif_populate($ldap, "data/40-in.ldif"), "data/40-in.ldif"); $mesg = $ldap->search(base => $BASEDN, filter => 'objectclass=*'); ok(!$mesg->code, "search: " . $mesg->code . ": " . $mesg->error); compare_ldif("40", $mesg, $mesg->sorted); for my $url (@URL) { $ldap = client(url => $url); ok($ldap, "$url client"); $mesg = $ldap->search(base => $BASEDN, filter => 'objectclass=*'); ok(!$mesg->code, "search: " . $mesg->code . ": " . $mesg->error); compare_ldif("40", $mesg, $mesg->sorted); } libnet-ldap-perl-0.6500+dfsg.orig/t/49lwp.t0000644000175000017500000000541512507234571017531 0ustar gregoagregoa#!perl use Test::More; BEGIN { require "t/common.pl" } start_server() ? plan tests => 6 : plan skip_all => 'no server'; SKIP: { skip('LWP::UserAgent not installed', 6) unless (eval { require LWP::UserAgent }); $ldap = client(); ok($ldap, "client"); $mesg = $ldap->bind($MANAGERDN, password => $PASSWD); ok(!$mesg->code, "bind: " . $mesg->code . ": " . $mesg->error); ok(ldif_populate($ldap, "data/41-in.ldif"), "data/41-in.ldif"); my $ua = LWP::UserAgent->new; my $res; # now search the database $res = $ua->get("ldap://${HOST}:$PORT/$BASEDN??sub?sn=jensen"); ok($res->content =~ /2 Matches found/); my $expect = <<'LDIF'; version: 1 dn: cn=Barbara Jensen,ou=Information Technology Division,ou=People,o=Universit y of Michigan,c=US objectClass: OpenLDAPperson cn: Barbara Jensen cn: Babs Jensen uid: babs sn: Jensen title: Mythical Manager, Research Systems postalAddress: ITD Prod Dev & Deployment $ 535 W. William St. Room 4212 $ Ann Arbor, MI 48103-4943 seeAlso: cn=All Staff,ou=Groups,o=University of Michigan,c=US userPassword: bjensen mail: bjensen@mailgw.umich.edu homePostalAddress: 123 Wesley $ Ann Arbor, MI 48103 description: Mythical manager of the rsdd unix project drink: water homePhone: +1 313 555 2333 pager: +1 313 555 3233 facsimileTelephoneNumber: +1 313 555 2274 telephoneNumber: +1 313 555 9022 dn: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,o=University of Michigan,c=US objectClass: OpenLDAPperson cn: Bjorn Jensen cn: Biiff Jensen uid: bjorn sn: Jensen seeAlso: cn=All Staff,ou=Groups,o=University of Michigan,c=US userPassword: bjorn homePostalAddress: 19923 Seven Mile Rd. $ South Lyon, MI 49999 drink: Iced Tea description: Hiker, biker title: Director, Embedded Systems postalAddress: Info Tech Division $ 535 W. William St. $ Ann Arbor, MI 48103 mail: bjorn@mailgw.umich.edu homePhone: +1 313 555 5444 pager: +1 313 555 4474 facsimileTelephoneNumber: +1 313 555 2177 telephoneNumber: +1 313 555 0355 LDIF $res = $ua->get("ldap://${HOST}:$PORT/$BASEDN??sub?(sn=jensen)", Accept => 'text/ldif'); is($res->content,$expect,'ldif result'); $res = $ua->get("ldap://${HOST}:$PORT/$BASEDN??sub?(sn=jensen)?x-format=ldif"); is($res->content,$expect,'ldif result'); } __END__ # Exact searching $mesg = $ldap->search(base => $BASEDN, filter => 'sn=jensen'); compare_ldif("41a",$mesg,$mesg->sorted); # Or searching $mesg = $ldap->search(base => $BASEDN, filter => '(|(objectclass=groupofnames)(sn=jones))'); compare_ldif("41b",$mesg,$mesg->sorted); # And searching $mesg = $ldap->search(base => $BASEDN, filter => '(&(objectclass=groupofnames)(cn=A*))'); compare_ldif("41c",$mesg,$mesg->sorted); # Not searching $mesg = $ldap->search(base => $BASEDN, filter => '(!(objectclass=person))'); compare_ldif("41d",$mesg,$mesg->sorted); libnet-ldap-perl-0.6500+dfsg.orig/t/00ldif-entry.t0000644000175000017500000001075612507234571020773 0ustar gregoagregoa#!perl BEGIN { require "t/common.pl"; } use Test::More tests => 16; use File::Compare qw(compare_text); use Net::LDAP::LDIF; my $infile = "data/00-in.ldif"; my $outfile1 = "$TEMPDIR/00-out1.ldif"; my $outfile2 = "$TEMPDIR/00-out2.ldif"; my $cmpfile1 = "data/00-cmp.ldif"; my $cmpfile2 = $infile; my $ldif = Net::LDAP::LDIF->new($infile,"r"); my $entry0_ldif = <<'LDIF'; dn: o=University of Michigan, c=US objectclass: top objectclass: organization objectclass: domainRelatedObject objectclass: quipuObject objectclass: quipuNonLeafObject l: Ann Arbor, Michigan st: Michigan streetaddress: 535 West William St. o: University of Michigan o: UMICH o: UM o: U-M o: U of M description: The University of Michigan at Ann Arbor postaladdress: University of Michigan $ 535 W. William St. $ Ann Arbor, MI 481 09 $ USpostalcode: 48109 telephonenumber: +1 313 764-1817 lastmodifiedtime: 930106182800Z lastmodifiedby: cn=manager, o=university of michigan, c=US associateddomain: umich.edu LDIF my $e = $ldif->read_entry; my @lines = $ldif->current_lines; is(join("",@lines),$entry0_ldif,"ldif lines"); my @entry = ($e, $ldif->read); ok($ldif->version == 1, "version == 1"); Net::LDAP::LDIF->new($outfile1,"w")->write_entry(@entry); Net::LDAP::LDIF->new($outfile2,"w", version => 1)->write_entry(@entry); ok(!compare_text($cmpfile1,$outfile1), $cmpfile1); ok(!compare_text($cmpfile2,$outfile2), $cmpfile2); is($e->ldif, "\n$entry0_ldif", "ldif method"); is($e->ldif(change => 1), <<'LDIF', "ldif method"); dn: o=University of Michigan, c=US changetype: add objectclass: top objectclass: organization objectclass: domainRelatedObject objectclass: quipuObject objectclass: quipuNonLeafObject l: Ann Arbor, Michigan st: Michigan streetaddress: 535 West William St. o: University of Michigan o: UMICH o: UM o: U-M o: U of M description: The University of Michigan at Ann Arbor postaladdress: University of Michigan $ 535 W. William St. $ Ann Arbor, MI 481 09 $ USpostalcode: 48109 telephonenumber: +1 313 764-1817 lastmodifiedtime: 930106182800Z lastmodifiedby: cn=manager, o=university of michigan, c=US associateddomain: umich.edu LDIF $e->changetype('modify'); $e->delete('objectclass'); $e->delete('o',['UM']); $e->add('counting',[qw(one two three)]); $e->add('first',[qw(1 2 3)], 'second',[qw(a b c)]); $e->replace('telephonenumber' => ['911']); is($e->ldif, <<'LDIF',"changes ldif"); dn: o=University of Michigan, c=US changetype: modify delete: objectclass - delete: o o: UM - add: counting counting: one counting: two counting: three - add: first first: 1 first: 2 first: 3 - add: second second: a second: b second: c - replace: telephonenumber telephonenumber: 911 LDIF is($e->ldif(change => 0), <<'LDIF',"changes ldif"); dn: o=University of Michigan, c=US l: Ann Arbor, Michigan st: Michigan streetaddress: 535 West William St. o: University of Michigan o: UMICH o: U-M o: U of M description: The University of Michigan at Ann Arbor postaladdress: University of Michigan $ 535 W. William St. $ Ann Arbor, MI 481 09 $ USpostalcode: 48109 telephonenumber: 911 lastmodifiedtime: 930106182800Z lastmodifiedby: cn=manager, o=university of michigan, c=US associateddomain: umich.edu counting: one counting: two counting: three first: 1 first: 2 first: 3 second: a second: b second: c LDIF $outfile = "$TEMPDIR/00-out3.ldif"; $cmpfile = "data/00-cmp2.ldif"; $ldif = Net::LDAP::LDIF->new($outfile,"w"); $ldif->write_entry($e); $ldif->write_cmd($e); $ldif->done; ok(!compare_text($cmpfile,$outfile), $cmpfile); $e->add('name' => 'Graham Barr'); $e->add('name;en-us' => 'Bob'); is(join(":",sort $e->attributes), "associateddomain:counting:description:first:l:lastmodifiedby:lastmodifiedtime:name:name;en-us:o:postaladdress:second:st:streetaddress:telephonenumber", 'attributes'); is(join(":",sort $e->attributes(nooptions => 1)), "associateddomain:counting:description:first:l:lastmodifiedby:lastmodifiedtime:name:o:postaladdress:second:st:streetaddress:telephonenumber", "attributes - nooptions"); $r = $e->get_value('name', asref => 1); ok(($r and @$r == 1 and $r->[0] eq 'Graham Barr'), "name eq Graham Barr"); $r = $e->get_value('name;en-us', asref => 1); ok(($r and @$r == 1 and $r->[0] eq 'Bob'), "name;en-us eq Bob"); $r = $e->get_value('name', alloptions => 1, asref => 1); ok(($r and join("*", sort keys %$r) eq "*;en-us"), "name keys"); ok(($r and $r->{''} and @{$r->{''}} == 1 and $r->{''}[0] eq 'Graham Barr'), "name alloptions"); ok(($r and $r->{';en-us'} and @{$r->{';en-us'}} == 1 and $r->{';en-us'}[0] eq 'Bob'), "name alloptions Bob"); libnet-ldap-perl-0.6500+dfsg.orig/t/72postread.t0000644000175000017500000001066612507234571020550 0ustar gregoagregoa#!perl use Test::More; use Net::LDAP; use Net::LDAP::Constant qw(LDAP_CONTROL_POSTREAD); use Net::LDAP::Control::PostRead; BEGIN { require "t/common.pl" } my @tests; { # parse DATA into a list (= tests) of hashes (= test parameters) of lists (= parameter values) local $/ = ''; while(my $para = ) { my @lines = split(/\n/, $para); my %params; chomp(@lines); @lines = grep(!/^\s*(?:#.*?)?$/, @lines); map { push(@{$params{$1}}, $2) if (/^(\w+):\s*(.*)$/) } @lines; push(@tests, \%params) if (%params); } } start_server() ? plan tests => 4 + 6 * scalar(@tests) : plan skip_all => 'no server'; $ldap = client(); isa_ok($ldap, Net::LDAP, "client"); $rootdse = $ldap->root_dse; isa_ok($rootdse, Net::LDAP::RootDSE, "root_dse"); SKIP: { skip("RootDSE does not offer PostRead control", 2 + 6 * scalar(@tests)) unless($rootdse->supported_control(LDAP_CONTROL_POSTREAD)); #$mesg = $ldap->start_tls(%tlsargs); #ok(!$mesg->code, "start_tls yields: ". $m->error); my $mesg = $ldap->bind($MANAGERDN, password => $PASSWD); ok(!$mesg->code, "bind: " . $mesg->code . ": " . $mesg->error); ok(ldif_populate($ldap, "data/40-in.ldif"), "data/40-in.ldif"); foreach my $test (@tests) { my $entry = Net::LDAP::Entry->new(@{$test->{dn}} ? $test->{dn}[0] : ''); my $control = Net::LDAP::Control::PostRead->new(attrs => $test->{attrs}); isa_ok($control, Net::LDAP::Control::PostRead, "control object"); $entry->changetype('modify'); foreach my $attr (@{$test->{attrs}}) { $entry->replace($attr => $test->{$attr} || []); } $mesg = $entry->update($ldap, control => $control); ok(!$mesg->code, "modify: " . $mesg->code . ": " . $mesg->error); my ($previous) = $mesg->control( LDAP_CONTROL_POSTREAD ); isa_ok($control, Net::LDAP::Control::PostRead, "response object"); $entry = $previous->entry(); isa_ok($entry, Net::LDAP::Entry, "entry object"); my $postreadValue = join(':', map { sort $entry->get_value($_) } @{$test->{attrs}}); $mesg = $ldap->search(base => @{$test->{dn}} ? $test->{dn}[0] : '', filter => '(objectclass=*)', scope => 'base', attrs => $test->{attrs}); ok(!$mesg->code, "search: ". $mesg->code . ": " . $mesg->error); $entry = $mesg->entry(0); my $origValue = join(':', map { sort $entry->get_value($_) } @{$test->{attrs}}); is($postreadValue, $origValue, "value in PostRead control matches"); } } __DATA__ ## each section below represents one test; logic similar to , structure similar to LDIF # each tests needs at least the elements # - dn: the object to modify/perform the test on # - attrs: the attributes to change and use in PostRead control # - $attr: optional - the new values (if any) for the attribute $attr # one attribute: replace a single value with another one dn: cn=Barbara Jensen, ou=Information Technology Division, ou=People, o=University of Michigan, c=US attrs: title title: HyperMythical Manager, Research Systems # one attribute: replace a single value attribute with multiple values dn: cn=Barbara Jensen, ou=Information Technology Division, ou=People, o=University of Michigan, c=US attrs: title title: Uber-Mythical Manager, Research Systems title: Cyber-Mythical Manager, Research Systems # one attribute: delete all values dn: cn=Barbara Jensen, ou=Information Technology Division, ou=People, o=University of Michigan, c=US attrs: title # multiple attribute: replace some values dn: cn=All Staff,ou=Groups,o=University of Michigan,c=US attrs: member attrs: description member: cn=Barbara Jensen, ou=Information Technology Division, ou=People, o=University of Michigan, c=US member: cn=Jane Doe, ou=Alumni Association, ou=People, o=University of Michigan, c=US member: cn=John Doe, ou=Information Technology Division, ou=People, o=University of Michigan, c=US member: cn=Mark Elliot, ou=Alumni Association, ou=People, o=University of Michigan, c=US member: cn=James A Jones 1, ou=Alumni Association, ou=People, o=University of Michigan, c=US member: cn=Ursula Hampster, ou=Alumni Association, ou=People, o=University of Michigan, c=US member: cn=Bjorn Jensen, ou=Information Technology Division, ou=People, o=University of Michigan, c=US description: Some of the sample data # multiple attribute: delete one, update the other dn: cn=All Staff,ou=Groups,o=University of Michigan,c=US attrs: member attrs: description member: cn=Manager, o=University of Michigan, c=US libnet-ldap-perl-0.6500+dfsg.orig/t/41populate.t0000644000175000017500000000101612507234571020541 0ustar gregoagregoa#!perl use Test::More; BEGIN { require "t/common.pl" } start_server() ? plan tests => 7 : plan skip_all => 'no server'; $ldap = client(); ok($ldap, "client"); $mesg = $ldap->bind($MANAGERDN, password => $PASSWD); ok(!$mesg->code, "bind: " . $mesg->code . ": " . $mesg->error); ok(ldif_populate($ldap, "data/40-in.ldif"), "data/40-in.ldif"); $mesg = $ldap->search(base => $BASEDN, filter => 'objectclass=*'); ok(!$mesg->code, "search: " . $mesg->code . ": " . $mesg->error); compare_ldif("40",$mesg,$mesg->sorted); libnet-ldap-perl-0.6500+dfsg.orig/t/05dsml.t0000644000175000017500000000214712507234571017655 0ustar gregoagregoa#!perl use Test::More; use File::Compare qw(compare_text); BEGIN { require "t/common.pl" } (eval { require XML::SAX::Base } && eval { require XML::SAX::Writer }) ? plan tests => 1 : plan skip_all => 'XML::SAX::Base and XML::SAX::Writer need to be installed'; require Net::LDAP::LDIF; require Net::LDAP::DSML; my $infile = "data/00-in.ldif"; my $outfile1 = "$TEMPDIR/05-out1.dsml"; my $cmpfile1 = "data/05-cmp.dsml"; my $ldif = Net::LDAP::LDIF->new($infile,"r"); @entry = $ldif->read; open(FH,">$outfile1"); binmode FH; my $dsml = Net::LDAP::DSML->new(output => \*FH,pretty_print => 1); $dsml->write_entry($_) for @entry; $dsml->end_dsml; close(FH); # postprocess generated DSML file for more flexible comparison # (don't rely on unpatched XML::SAX::Writer [e.g. Debian]) { open(FH, "+<$outfile1"); binmode FH; local $/; # slurp mode my $txt = ; $txt =~ s/>\n[\n\t ]+/>\n/g; # remove empty lines & leading spaces after tags $txt =~ s/\"/'/g; # convert " to ' in tag attribute values seek(FH, 0, 0); print FH $txt; truncate(FH, length($txt)); close(FH); } ok(!compare_text($cmpfile1,$outfile1), $cmpfile1); libnet-ldap-perl-0.6500+dfsg.orig/t/46ssl.t0000644000175000017500000000230112507234571017514 0ustar gregoagregoa#!perl use Test::More; BEGIN { require "t/common.pl" } start_server(version => 3, ssl => 1) ? plan tests => 15 : plan skip_all => 'no server'; SKIP: { skip('IO::Socket::SSL not installed', 15) unless (eval { require IO::Socket::SSL; } ); $ldap = client(); ok($ldap, "client"); $mesg = $ldap->bind($MANAGERDN, password => $PASSWD, version => 3); ok(!$mesg->code, "bind: " . $mesg->code . ": " . $mesg->error); ok(ldif_populate($ldap, "data/40-in.ldif"), "data/40-in.ldif"); $mesg = $ldap->start_tls; ok(!$mesg->code, "start_tls: " . $mesg->code . ": " . $mesg->error); $mesg = $ldap->start_tls; ok($mesg->code, "start_tls: " . $mesg->code . ": " . $mesg->error); $mesg = $ldap->search(base => $BASEDN, filter => 'objectclass=*'); ok(!$mesg->code, "search: " . $mesg->code . ": " . $mesg->error); compare_ldif("40",$mesg,$mesg->sorted); $ldap = client(ssl => 1); ok($ldap, "ssl client"); $mesg = $ldap->start_tls; ok($mesg->code, "start_tls: " . $mesg->code . ": " . $mesg->error); $mesg = $ldap->search(base => $BASEDN, filter => 'objectclass=*'); ok(!$mesg->code, "search: " . $mesg->code . ": " . $mesg->error); compare_ldif("40",$mesg,$mesg->sorted); } libnet-ldap-perl-0.6500+dfsg.orig/t/03schema.t0000644000175000017500000000463312507234571020156 0ustar gregoagregoa#!perl -w use Test::More tests => 14; use Net::LDAP::Schema; my $schema = Net::LDAP::Schema->new( "data/schema.in" ) or die "Cannot open schema"; isa_ok($schema, Net::LDAP::Schema, 'load schema file'); my @atts = $schema->all_attributes(); is(@atts, 265, 'number of attribute types in schema'); print "The schema contains ", scalar @atts, " attributes\n"; my @ocs = $schema->all_objectclasses(); is(@ocs, 66, 'number of object classes in schema'); print "The schema contains ", scalar @ocs, " object classes\n"; my @mrs = $schema->all_matchingrules(); is(@mrs, 40, 'number of matching rules in schema'); print "The schema contains ", scalar @mrs, " matching rules\n"; my @mrus = $schema->all_matchingruleuses(); is(@mrus, 34, 'number of matching rule uses in schema'); print "The schema contains ", scalar @mrus, " matching rule uses\n"; my @stxs = $schema->all_syntaxes(); is(@stxs, 32, 'number of LDAP syntaxes in schema'); print "The schema contains ", scalar @stxs, " LDAP syntaxes\n"; %namechildren = map { $_->{name} => 1 } grep { grep(/^name$/i, @{$_->{sup}}) } $schema->all_attributes(); is(scalar(keys(%namechildren)), 13, "attributes derived from 'name'"); @atts = $schema->must( "person" ); is(join(' ', sort map { lc $_->{name} } @atts), join(' ', sort map lc, qw(cn sn objectClass)), 'mandatory attributes'); print "The 'person' OC must have these attributes [", join(',', map $_->{name}, @atts), "]\n"; @atts = $schema->may( "mhsOrganizationalUser" ); ok(!@atts, 'optional attributes'); print "The 'mhsOrganizationalUser' OC may have these attributes [", join(',', map $_->{name}, @atts), "]\n"; @super = $schema->superclass('OpenLDAPperson'); is(join(' ', sort map lc, @super), join(' ', sort map lc, qw(pilotPerson inetOrgPerson)), 'superclass'); $mru = $schema->matchingruleuse('generalizedtimematch'); is(join(' ', sort map lc, @{$mru->{applies}}), join(' ', sort map lc, qw(createTimestamp modifyTimestamp)), 'attribute types a matching rule applies to'); @binarysyntaxes = map { $_->{name} } grep { $_->{'x-binary-transfer-required'} } $schema->all_syntaxes(); is(scalar(@binarysyntaxes), 5, "number of syntaxes that need ';binary' appended to the attribute type"); ok(! defined($schema->attribute('distinguishedName')->{max_length}), 'infinite length attribute type'); is($schema->attribute('userPassword')->{max_length}, 128, 'attribute type max. length'); libnet-ldap-perl-0.6500+dfsg.orig/t/47ipc.t0000644000175000017500000000233212507234571017473 0ustar gregoagregoa#!perl use Test::More; BEGIN { require "t/common.pl" } start_server(ipc => 1) ? plan tests => 18 : plan skip_all => 'no server'; $ldap = client(); ok($ldap, "client"); $mesg = $ldap->bind($MANAGERDN, password => $PASSWD); ok(!$mesg->code, "bind: " . $mesg->code . ": " . $mesg->error); ok(ldif_populate($ldap, "data/40-in.ldif"), "data/40-in.ldif"); $mesg = $ldap->search(base => $BASEDN, filter => 'objectclass=*'); ok(!$mesg->code, "search: " . $mesg->code . ": " . $mesg->error); compare_ldif("40",$mesg,$mesg->sorted); $ldap = client(ipc => 1); ok($ldap, "ipc client"); $mesg = $ldap->search(base => $BASEDN, filter => 'objectclass=*'); ok(!$mesg->code, "search: " . $mesg->code . ": " . $mesg->error); compare_ldif("40",$mesg,$mesg->sorted); SKIP: { skip('IO::Socket::SSL not installed') unless (eval { require IO::Socket::SSL; } ); $mesg = $ldap->start_tls; ok(!$mesg->code, "start_tls: " . $mesg->code . ": " . $mesg->error); $mesg = $ldap->start_tls; ok($mesg->code, "start_tls: " . $mesg->code . ": " . $mesg->error); $mesg = $ldap->search(base => $BASEDN, filter => 'objectclass=*'); ok(!$mesg->code, "search: " . $mesg->code . ": " . $mesg->error); compare_ldif("40",$mesg,$mesg->sorted); } libnet-ldap-perl-0.6500+dfsg.orig/t/07filtermatch.t0000644000175000017500000001371512507234571021225 0ustar gregoagregoa#!perl use Test::More; use Net::LDAP::Entry; use Net::LDAP::Filter; use Net::LDAP::FilterMatch qw(Text::Soundex); # Each line consists of an OPCODE-LIST and a DN, # where # - OPCODE-LIST is a comma separated list of OPCODES, # each potentially prefixed with a TESTCASE prefix followed by : # OPCODE-LIST = OPCODE (, [ TESTCASE:] OPCODE )+ # - within the OPCODE-LIST each TESTCASE prefix needs to be unique # - no TESTCASE prefix means: default result # - OPCODES are # yes $filter->match() returns true # no $filter->match() returns false # fail $filter->match() returns undef # To keep the order of tests, @tests is an array of ($filterstring => @ops) tuples my @tests = map { /^([\w:,]+)\s+(\(.*\))/ && { $2 => [ split(/,/, $1) ] } } grep(/^[\w:,]+\s+\(.*\)/, ); # The elements of the @testcases array are the TESTCASE prefixes described above my @testcases = qw/raw schema/; # calculate number of tests: plan tests => 3 + # general preparation scalar(@tests) * # @tests is a list of ($filter => \@ops) pairs ( 1 + # one Net::LDAP::Filter test per ... scalar(@testcases)); # ... every test case my $entry = Net::LDAP::Entry->new( 'cn=John Doe, ou=Information Technology Division, ou=People, o=University of Michigan, c=US', objectClass => [ 'OpenLDAPperson' ], cn => [ 'John Doe', 'Jonathon Doe' ], uid => [ 'john' ], sn => [ 'Doe' ], givenName => [ qw/John Jonathon/ ], mailPreferenceOption => 2, # uidnumber is not a legal attribute of OpenLDAPperson: # does not matter here, but will not load into an LDAP server uidNumber => 1012, o => 'University of Michigan', postalAddress => [ 'ITD $ 535 W. William $ Ann Arbor, MI 48109' ], seeAlso => [ 'cn=All Staff, ou=Groups, o=University of Michigan, c=US' ], homePostalAddress => [ '912 East Bllvd $ Ann Arbor, MI 48104' ], title => [ 'System Administrator, Information Technology Division' ], description => [ 'overworked!' ], mail => [ 'johnd@mailgw.umich.edu' ], homePhone => [ '+1 313 555 3774' ], pager => [ '+1 313 555 6573' ], facsimileTelephoneNumber => [ '+1 313 555 4544' ], telephoneNumber => [ '+1 313 555 9394' ], createTimestamp => '20090209123456Z', creatorsName => 'cn=James A Jones 2, ou=Information Technology Division, ou=People, o=University of Michigan, c=US', modifyTimestamp => '20121102212634Z', modifiersName => 'cn=John Doe, ou=Information Technology Division, ou=People, o=University of Michigan, c=US'); isa_ok($entry, Net::LDAP::Entry, 'entry object created'); my $schema = Net::LDAP::Schema->new(); isa_ok($schema, Net::LDAP::Schema, 'schema object created'); ok($schema->parse('data/schema.in'), "schema loaded: ".($schema->error ? $schema->error : '')); note('Schema: ', explain($schema)) if ($ENV{TEST_VERBOSE}); foreach my $elem (@tests) { my ($filterstring, $ops) = %{$elem}; my $filter = Net::LDAP::Filter->new($filterstring); isa_ok($filter, Net::LDAP::Filter, 'filter object created'); #note("$filterstring => ", explain($filter)); SKIP: { eval { require Text::Soundex }; skip("Text::Soundex not installed", scalar(@testcases)) if ($@); for my $case (@testcases) { my ($op) = grep(/^$case:/, @{$ops}); ($op) = grep(/^[^:]+$/, @{$ops}) if (!$op); $op =~ s/^$case://; my $match = $filter->match($entry, $case eq 'schema' ? $schema : undef); foreach ($op) { /fail/ && ok(!defined($match), "$filterstring should cause failure in $case mode"); /yes/ && ok($match, "$filterstring should match in $case mode"); /(todo|no)/ && ok(!$match, "$filterstring should not match in $case mode"); } } } } __DATA__ ## "basic" match # caseIgnoreIA5Match yes (mail=johnd@mailgw.umich.edu) # caseIgnoreListMatch yes (postaladdress=ITD $ 535 W. William $ Ann Arbor, MI 48109) # caseIgnoreMatch no (cn=Babs Jensen) yes (!(cn=Tim Howes)) yes (cn=John Doe) # distinguishedNameMatch yes,raw:no (seeAlso=cn=All Staff, OU=Groups, o=University of Michigan,c=US) # facsimileNumberMatch #yes (facsimiletelephoneNumber=+1 313 555 4544) # generalizedTimeMatch yes (createTimestamp>=19970101120000Z) yes (createTimestamp<=25250101000000Z) # integerMatch yes (uidNumber=1012) no (uidNumber=1011) # integerMatch not listed in attributeType => fail with schema fail,raw:yes (mailPreferenceOption=2) # objectIdentifierMatch no (objectclass=top) yes (objectclass=OpenLDAPPerson) # telephoneNumberMatch yes (telephoneNumber=+1 313 555 9394) yes,raw:no (homephone=+13135553774) yes,raw:no (homephone=001313 5553774) # generalizedTimeOrderingMatch yes (createTimestamp>=19970101120000Z) yes (createTimestamp<=25250101000000Z) # integerOrderingMatch yes (uidNumber>=1000) yes (uidNumber<=2000) # integerOrderingMatch not listed in attributeType => fail with schema fail,raw:yes (mailpreferenceOption>=2) # caseIgnoreIA5SubstringsMatch yes (mail=johnd@*) yes (mail=johnd*@*umich.edu) # caseIgnoreListSubstringsMatch yes (postaladdress=ITD $ * William $ Ann Arbor, MI 48109) # caseIgnoreSubstringsMatch yes (cn=j*) no (cn=*a) yes (cn=*a*) yes (o=univ*of*mich*) # facsimileNumberSubstringsMatch #yes (facsimiletelephoneNumber=*1 313 555 4544) #yes (facsimiletelephoneNumber=+1*555*) # telephoneNumberSubstringsMatch yes (telephoneNumber=+1*313 555 9394) yes (telephoneNumber=+1*313*) yes,raw:no (homephone=+131355*) yes,raw:no (homephone=0013*774) ## presence match yes (cn=*) ## approx match yes (cn~=Jonathon Doe) yes (cn~=jonathon doe) yes (cn~=jonathan doe) yes (cn~=jonothan doe) yes (cn~=jonathan do) yes (cn~=john doe) yes (cn~=jon doe) yes (cn~=jomatan doe) yes (cn~=jonatan oe) yes (cn~=jon dee) ## extensible match yes (cn:dn:=John Doe) yes (:dn:caseIgnoreMatch:=People) yes (mailPreferenceOption:integerBitAndMatch:=2) yes,raw:no (mailPreferenceOption:integerBitOrMatch:=3) yes (!(mailPreferenceOption:integerBitAndMatch:=1)) yes (!(mailPreferenceOption:integerBitAndMatch:=3)) yes,raw:fail (:caseignoreMatch:=University of michigan) # EOF libnet-ldap-perl-0.6500+dfsg.orig/t/02filter.t0000644000175000017500000004435612507234571020210 0ustar gregoagregoa#!perl # Testcase contributed by Julian Onions use Test::More; use Net::LDAP::Filter; use Net::LDAP::ASN qw(Filter); use Convert::ASN1 qw(asn_dump); my $asn = $Filter; my @tests = do { local $/=""; }; plan tests => 4 * scalar(@tests); my $testno = 0; my $test; foreach $test (@tests) { my ($filter, $ber, $filter_out) = $test =~ /^ (?:\#.*\n)* (.*)\n ((?:[\da-fA-F]+:.*\n)+) (.*) /x or die "Cannot parse test\n$test\n"; $filter_out ||= $filter; my $binary = pack("H*", join("", map { /\w+/g } $ber =~ /:((?: [\dA-Fa-f]{2}){1,16})/g)); my $filt = new Net::LDAP::Filter $filter; isa_ok($filt, Net::LDAP::Filter, "$filter");; my $data = $asn->encode($filt); ok($data, "$filter ASN.1 encode(".($asn->error || 0).')'); is($data, $binary, "$filter asn_dump"); unless($data eq $binary) { note(explain($filt)) if ($ENV{TEST_VERBOSE}); print "got ", unpack("H*", $data), "\n"; asn_dump(\*STDOUT, $data); print "wanted ", unpack("H*", $binary), "\n"; asn_dump(\*STDOUT, $binary); } my $str = $filt->as_string; is($str, $filter_out, "$filter as_string"); } __DATA__ (objectclass=foo) 0000: A3 12 04 0B 6F 62 6A 65 63 74 63 6C 61 73 73 04 ....objectclass. 0010: 03 66 6F 6F __ __ __ __ __ __ __ __ __ __ __ __ .foo (objectclass=) 0000: A3 0F 04 0B 6F 62 6A 65 63 74 63 6C 61 73 73 04 ....objectclass. 0010: 00 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ . createTimestamp>=199701011200Z 0000: A5 20 04 0F 63 72 65 61 74 65 54 69 6D 65 73 74 . ..createTimest 0010: 61 6D 70 04 0D 31 39 39 37 30 31 30 31 31 32 30 amp..19970101120 0020: 30 5A __ __ __ __ __ __ __ __ __ __ __ __ __ __ 0Z (createTimestamp>=199701011200Z) createTimestamp<=199801011210Z 0000: A6 20 04 0F 63 72 65 61 74 65 54 69 6D 65 73 74 . ..createTimest 0010: 61 6D 70 04 0D 31 39 39 38 30 31 30 31 31 32 31 amp..19980101121 0020: 30 5A __ __ __ __ __ __ __ __ __ __ __ __ __ __ 0Z (createTimestamp<=199801011210Z) (cn=a*) 0000: A4 09 04 02 63 6E 30 03 80 01 61 __ __ __ __ __ ....cn0...a (cn=*a) 0000: A4 09 04 02 63 6E 30 03 82 01 61 __ __ __ __ __ ....cn0...a cn=*a* 0000: A4 09 04 02 63 6E 30 03 81 01 61 __ __ __ __ __ ....cn0...a (cn=*a*) (cn=*) 0000: 87 02 63 6E __ __ __ __ __ __ __ __ __ __ __ __ ..cn (cn~=foo) 0000: A8 09 04 02 63 6E 04 03 66 6F 6F __ __ __ __ __ ....cn..foo (cn=Babs Jensen) 0000: A3 11 04 02 63 6E 04 0B 42 61 62 73 20 4A 65 6E ....cn..Babs Jen 0010: 73 65 6E __ __ __ __ __ __ __ __ __ __ __ __ __ sen (!(cn=Tim Howes)) 0000: A2 11 A3 0F 04 02 63 6E 04 09 54 69 6D 20 48 6F ......cn..Tim Ho 0010: 77 65 73 __ __ __ __ __ __ __ __ __ __ __ __ __ wes !(cn=Tim Howes) 0000: A2 11 A3 0F 04 02 63 6E 04 09 54 69 6D 20 48 6F ......cn..Tim Ho 0010: 77 65 73 __ __ __ __ __ __ __ __ __ __ __ __ __ wes (!(cn=Tim Howes)) (&(objectClass=Person)(|(sn=Jensen)(cn=Babs J*))) 0000: A0 37 A3 15 04 0B 6F 62 6A 65 63 74 43 6C 61 73 .7....objectClas 0010: 73 04 06 50 65 72 73 6F 6E A1 1E A3 0C 04 02 73 s..Person......s 0020: 6E 04 06 4A 65 6E 73 65 6E A4 0E 04 02 63 6E 30 n..Jensen....cn0 0030: 08 80 06 42 61 62 73 20 4A __ __ __ __ __ __ __ ...Babs J (o=univ*of*mich*) 0000: A4 15 04 01 6F 30 10 80 04 75 6E 69 76 81 02 6F ....o0...univ..o 0010: 66 81 04 6D 69 63 68 __ __ __ __ __ __ __ __ __ f..mich (cn:1.2.3.4.5:=Fred Flintstone) 0000: A9 20 81 09 31 2E 32 2E 33 2E 34 2E 35 82 02 63 .#..1.2.3.4.5..c 0010: 6E 83 0F 46 72 65 64 20 46 6C 69 6E 74 73 74 6F n..Fred Flintsto 0020: 6E 65 __ __ __ __ __ __ __ __ __ __ __ __ __ __ ne (sn:dn:2.4.6.8.10:=Barney Rubble) 0000: A9 22 81 0A 32 2E 34 2E 36 2E 38 2E 31 30 82 02 ."..2.4.6.8.10.. 0010: 73 6E 83 0D 42 61 72 6E 65 79 20 52 75 62 62 6C sn..Barney Rubbl 0020: 65 84 01 FF __ __ __ __ __ __ __ __ __ __ __ __ e... (o:dn:=Ace Industry) 0000: A9 14 82 01 6F 83 0C 41 63 65 20 49 6E 64 75 73 ....o..Ace Indus 0010: 74 72 79 84 01 FF __ __ __ __ __ __ __ __ __ __ try... (:dn:2.4.6.8.10:=Dino) 0000: A9 15 81 0A 32 2E 34 2E 36 2E 38 2E 31 30 83 04 ....2.4.6.8.10.. 0010: 44 69 6E 6F 84 01 FF __ __ __ __ __ __ __ __ __ Dino... (o=univ*of*mich*an) 0000: A4 19 04 01 6F 30 14 80 04 75 6E 69 76 81 02 6F ....o0...univ..o 0010: 66 81 04 6D 69 63 68 82 02 61 6E __ __ __ __ __ f..mich..an (&(cn=fred)(!(objectclass=organization))) 0000: A0 2B A3 0A 04 02 63 6E 04 04 66 72 65 64 A2 1D .+....cn..fred.. 0010: A3 1B 04 0B 6F 62 6A 65 63 74 63 6C 61 73 73 04 ....objectclass. 0020: 0C 6F 72 67 61 6E 69 7A 61 74 69 6F 6E __ __ __ .organization (| (& (cn=test)) (| (cn=foo))) 0000: A1 1B A0 0C A3 0A 04 02 63 6E 04 04 74 65 73 74 ........cn..test 0010: A1 0B A3 09 04 02 63 6E 04 03 66 6F 6F __ __ __ ......cn..foo (|(&(cn=test))(|(cn=foo))) (| (cn=foo) (cn=test)) 0000: A1 17 A3 09 04 02 63 6E 04 03 66 6F 6F A3 0A 04 ......cn..foo... 0010: 02 63 6E 04 04 74 65 73 74 __ __ __ __ __ __ __ .cn..test (|(cn=foo)(cn=test)) (& (| (cn=test) (cn=foo) (sn=bar)) (| (c=GB) (c=AU))) 0000: A0 38 A1 22 A3 0A 04 02 63 6E 04 04 74 65 73 74 .8."....cn..test 0010: A3 09 04 02 63 6E 04 03 66 6F 6F A3 09 04 02 73 ....cn..foo....s 0020: 6E 04 03 62 61 72 A1 12 A3 07 04 01 63 04 02 47 n..bar......c..G 0030: 42 A3 07 04 01 63 04 02 41 55 __ __ __ __ __ __ B....c..AU (&(|(cn=test)(cn=foo)(sn=bar))(|(c=GB)(c=AU))) (| (& (c=GB) (cn=test)) (& (c=AU) (cn=test)) (& (c=GB) (cn=foo)) (& (c=AU) (cn=foo)) (& (c=GB) (sn=bar)) (& (c=AU) (sn=bar))) 0000: A1 81 86 A0 15 A3 07 04 01 63 04 02 47 42 A3 0A .........c..GB.. 0010: 04 02 63 6E 04 04 74 65 73 74 A0 15 A3 07 04 01 ..cn..test...... 0020: 63 04 02 41 55 A3 0A 04 02 63 6E 04 04 74 65 73 c..AU....cn..tes 0030: 74 A0 14 A3 07 04 01 63 04 02 47 42 A3 09 04 02 t......c..GB.... 0040: 63 6E 04 03 66 6F 6F A0 14 A3 07 04 01 63 04 02 cn..foo......c.. 0050: 41 55 A3 09 04 02 63 6E 04 03 66 6F 6F A0 14 A3 AU....cn..foo... 0060: 07 04 01 63 04 02 47 42 A3 09 04 02 73 6E 04 03 ...c..GB....sn.. 0070: 62 61 72 A0 14 A3 07 04 01 63 04 02 41 55 A3 09 bar......c..AU.. 0080: 04 02 73 6E 04 03 62 61 72 __ __ __ __ __ __ __ ..sn..bar (|(&(c=GB)(cn=test))(&(c=AU)(cn=test))(&(c=GB)(cn=foo))(&(c=AU)(cn=foo))(&(c=GB)(sn=bar))(&(c=AU)(sn=bar))) (& (| (cn=test) (cn=foo) (sn=bar)) (c=GB)) 0000: A0 2D A1 22 A3 0A 04 02 63 6E 04 04 74 65 73 74 .-."....cn..test 0010: A3 09 04 02 63 6E 04 03 66 6F 6F A3 09 04 02 73 ....cn..foo....s 0020: 6E 04 03 62 61 72 A3 07 04 01 63 04 02 47 42 __ n..bar....c..GB (&(|(cn=test)(cn=foo)(sn=bar))(c=GB)) (| (& (sn=bar) (c=GB)) (& (cn=foo) (c=GB)) (& (cn=test) (c=GB))) 0000: A1 43 A0 14 A3 09 04 02 73 6E 04 03 62 61 72 A3 .C......sn..bar. 0010: 07 04 01 63 04 02 47 42 A0 14 A3 09 04 02 63 6E ...c..GB......cn 0020: 04 03 66 6F 6F A3 07 04 01 63 04 02 47 42 A0 15 ..foo....c..GB.. 0030: A3 0A 04 02 63 6E 04 04 74 65 73 74 A3 07 04 01 ....cn..test.... 0040: 63 04 02 47 42 __ __ __ __ __ __ __ __ __ __ __ c..GB (|(&(sn=bar)(c=GB))(&(cn=foo)(c=GB))(&(cn=test)(c=GB))) (& (& (cn=foo) (| (cn=bar) (cn=xyz))) (& (cn=foo2) (| (cn=1) (cn=2)))) 0000: A0 47 A0 23 A3 09 04 02 63 6E 04 03 66 6F 6F A1 .G.#....cn..foo. 0010: 16 A3 09 04 02 63 6E 04 03 62 61 72 A3 09 04 02 .....cn..bar.... 0020: 63 6E 04 03 78 79 7A A0 20 A3 0A 04 02 63 6E 04 cn..xyz. ....cn. 0030: 04 66 6F 6F 32 A1 12 A3 07 04 02 63 6E 04 01 31 .foo2......cn..1 0040: A3 07 04 02 63 6E 04 01 32 __ __ __ __ __ __ __ ....cn..2 (&(&(cn=foo)(|(cn=bar)(cn=xyz)))(&(cn=foo2)(|(cn=1)(cn=2)))) (& (& (cn=foo) (! (cn=bar))) (| (cn=oof) (cn=foobie))) 0000: A0 35 A0 18 A3 09 04 02 63 6E 04 03 66 6F 6F A2 .5......cn..foo. 0010: 0B A3 09 04 02 63 6E 04 03 62 61 72 A1 19 A3 09 .....cn..bar.... 0020: 04 02 63 6E 04 03 6F 6F 66 A3 0C 04 02 63 6E 04 ..cn..oof....cn. 0030: 06 66 6F 6F 62 69 65 __ __ __ __ __ __ __ __ __ .foobie (&(&(cn=foo)(!(cn=bar)))(|(cn=oof)(cn=foobie))) (| (& (cn=foobie) (cn=foo) (! (cn=bar))) (& (cn=oof) (cn=foo) (! (cn=bar)))) 0000: A1 4D A0 26 A3 0C 04 02 63 6E 04 06 66 6F 6F 62 .M.&....cn..foob 0010: 69 65 A3 09 04 02 63 6E 04 03 66 6F 6F A2 0B A3 ie....cn..foo... 0020: 09 04 02 63 6E 04 03 62 61 72 A0 23 A3 09 04 02 ...cn..bar.#.... 0030: 63 6E 04 03 6F 6F 66 A3 09 04 02 63 6E 04 03 66 cn..oof....cn..f 0040: 6F 6F A2 0B A3 09 04 02 63 6E 04 03 62 61 72 __ oo......cn..bar (|(&(cn=foobie)(cn=foo)(!(cn=bar)))(&(cn=oof)(cn=foo)(!(cn=bar)))) (| (cn=foo) (cn=bar) (! (& (cn=a) (cn=b) (cn=c)))) 0000: A1 35 A3 09 04 02 63 6E 04 03 66 6F 6F A3 09 04 .5....cn..foo... 0010: 02 63 6E 04 03 62 61 72 A2 1D A0 1B A3 07 04 02 .cn..bar........ 0020: 63 6E 04 01 61 A3 07 04 02 63 6E 04 01 62 A3 07 cn..a....cn..b.. 0030: 04 02 63 6E 04 01 63 __ __ __ __ __ __ __ __ __ ..cn..c (|(cn=foo)(cn=bar)(!(&(cn=a)(cn=b)(cn=c)))) (| (! (cn=a)) (! (cn=b)) (! (cn=c)) (cn=foo) (cn=bar)) 0000: A1 37 A2 09 A3 07 04 02 63 6E 04 01 61 A2 09 A3 .7......cn..a... 0010: 07 04 02 63 6E 04 01 62 A2 09 A3 07 04 02 63 6E ...cn..b......cn 0020: 04 01 63 A3 09 04 02 63 6E 04 03 66 6F 6F A3 09 ..c....cn..foo.. 0030: 04 02 63 6E 04 03 62 61 72 __ __ __ __ __ __ __ ..cn..bar (|(!(cn=a))(!(cn=b))(!(cn=c))(cn=foo)(cn=bar)) (& (cn=foo) (cn=bar) (! (& (cn=a) (cn=b) (cn=c)))) 0000: A0 35 A3 09 04 02 63 6E 04 03 66 6F 6F A3 09 04 .5....cn..foo... 0010: 02 63 6E 04 03 62 61 72 A2 1D A0 1B A3 07 04 02 .cn..bar........ 0020: 63 6E 04 01 61 A3 07 04 02 63 6E 04 01 62 A3 07 cn..a....cn..b.. 0030: 04 02 63 6E 04 01 63 __ __ __ __ __ __ __ __ __ ..cn..c (&(cn=foo)(cn=bar)(!(&(cn=a)(cn=b)(cn=c)))) (| (& (! (cn=a)) (cn=bar) (cn=foo)) (& (! (cn=b)) (cn=bar) (cn=foo)) (& (! (cn=c)) (cn=bar) (cn=foo))) 0000: A1 69 A0 21 A2 09 A3 07 04 02 63 6E 04 01 61 A3 .i.!......cn..a. 0010: 09 04 02 63 6E 04 03 62 61 72 A3 09 04 02 63 6E ...cn..bar....cn 0020: 04 03 66 6F 6F A0 21 A2 09 A3 07 04 02 63 6E 04 ..foo.!......cn. 0030: 01 62 A3 09 04 02 63 6E 04 03 62 61 72 A3 09 04 .b....cn..bar... 0040: 02 63 6E 04 03 66 6F 6F A0 21 A2 09 A3 07 04 02 .cn..foo.!...... 0050: 63 6E 04 01 63 A3 09 04 02 63 6E 04 03 62 61 72 cn..c....cn..bar 0060: A3 09 04 02 63 6E 04 03 66 6F 6F __ __ __ __ __ ....cn..foo (|(&(!(cn=a))(cn=bar)(cn=foo))(&(!(cn=b))(cn=bar)(cn=foo))(&(!(cn=c))(cn=bar)(cn=foo))) (| (cn=foo\(bar\)) (cn=test)) 0000: A1 1C A3 0E 04 02 63 6E 04 08 66 6F 6F 28 62 61 ......cn..foo(ba 0010: 72 29 A3 0A 04 02 63 6E 04 04 74 65 73 74 __ __ r)....cn..test (|(cn=foo\28bar\29)(cn=test)) (cn=foo\*) 0000: A3 0A 04 02 63 6E 04 04 66 6F 6F 2A __ __ __ __ ....cn..foo* (cn=foo\2a) (cn=foo\\*) 0000: A4 0C 04 02 63 6E 30 06 80 04 66 6F 6F 5C __ __ ....cn0...foo\ (cn=foo\5c*) (cn=\\*foo) 0000: A4 0E 04 02 63 6E 30 08 80 01 5C 82 03 66 6F 6F ....cn0...\..foo (cn=\5c*foo) (cn=\\*foo\\*) 0000: A4 0F 04 02 63 6E 30 09 80 01 5C 81 04 66 6F 6F ....cn0...\..foo 0010: 5C __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ \ (cn=\5c*foo\5c*) (ou:dn:caseIgnoreMatch:=people) 0000: A9 20 81 0F 63 61 73 65 49 67 6E 6F 72 65 4D 61 . ..caseIgnoreMa 0010: 74 63 68 82 02 6F 75 83 06 70 65 6F 70 6C 65 84 tch..ou..people. 0020: 01 FF __ __ __ __ __ __ __ __ __ __ __ __ __ __ .. (sn:caseIgnoreMatch:=barr) 0000: A9 1B 81 0F 63 61 73 65 49 67 6E 6F 72 65 4D 61 ....caseIgnoreMa 0010: 74 63 68 82 02 73 6E 83 04 62 61 72 72 __ __ __ tch..sn..barr (attr=*) 0000: 87 04 61 74 74 72 __ __ __ __ __ __ __ __ __ __ ..attr (attr;x-tag=*) 0000: 87 0A 61 74 74 72 3B 78 2D 74 61 67 __ __ __ __ ..attr;x-tag (attr=) 0000: A3 08 04 04 61 74 74 72 04 00 __ __ __ __ __ __ ....attr.. (1.2.3.4.5=) 0000: A3 0D 04 09 31 2E 32 2E 33 2E 34 2E 35 04 00 __ ....1.2.3.4.5.. (1.2.3.4.5;x-tag=) 0000: A3 13 04 0F 31 2E 32 2E 33 2E 34 2E 35 3B 78 2D ....1.2.3.4.5;x- 0010: 74 61 67 04 00 __ __ __ __ __ __ __ __ __ __ __ tag.. (attr=value) 0000: A3 0D 04 04 61 74 74 72 04 05 76 61 6C 75 65 __ ....attr..value (space= ) 0000: A3 0A 04 05 73 70 61 63 65 04 01 20 __ __ __ __ ....space.. (null=\00) 0000: A3 09 04 04 6E 75 6C 6C 04 01 00 __ __ __ __ __ ....null... (bell=\07) 0000: A3 09 04 04 62 65 6C 6C 04 01 07 __ __ __ __ __ ....bell... (bell=) 0000: A3 09 04 04 62 65 6C 6C 04 01 07 __ __ __ __ __ ....bell... (bell=\07) (attr;x-star=\2a) 0000: A3 10 04 0B 61 74 74 72 3B 78 2D 73 74 61 72 04 ....attr;x-star. 0010: 01 2A __ __ __ __ __ __ __ __ __ __ __ __ __ __ .* (attr;x-star=\2a) (attr;x-escape=\5C) 0000: A3 12 04 0D 61 74 74 72 3B 78 2D 65 73 63 61 70 ....attr;x-escap 0010: 65 04 01 5C __ __ __ __ __ __ __ __ __ __ __ __ e..\ (attr;x-escape=\5c) (attr=initial*) 0000: A4 11 04 04 61 74 74 72 30 09 80 07 69 6E 69 74 ....attr0...init 0010: 69 61 6C __ __ __ __ __ __ __ __ __ __ __ __ __ ial (attr=*any*) 0000: A4 0D 04 04 61 74 74 72 30 05 81 03 61 6E 79 __ ....attr0...any (attr=*final) 0000: A4 0F 04 04 61 74 74 72 30 07 82 05 66 69 6E 61 ....attr0...fina 0010: 6C __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ l (attr=initial*final) 0000: A4 18 04 04 61 74 74 72 30 10 80 07 69 6E 69 74 ....attr0...init 0010: 69 61 6C 82 05 66 69 6E 61 6C __ __ __ __ __ __ ial..final (attr=initial*any*any*final) 0000: A4 22 04 04 61 74 74 72 30 1A 80 07 69 6E 69 74 ."..attr0...init 0010: 69 61 6C 81 03 61 6E 79 81 03 61 6E 79 82 05 66 ial..any..any..f 0020: 69 6E 61 6C __ __ __ __ __ __ __ __ __ __ __ __ inal (attr=initial*any*) 0000: A4 16 04 04 61 74 74 72 30 0E 80 07 69 6E 69 74 ....attr0...init 0010: 69 61 6C 81 03 61 6E 79 __ __ __ __ __ __ __ __ ial..any (attr=*any*final) 0000: A4 14 04 04 61 74 74 72 30 0C 81 03 61 6E 79 82 ....attr0...any. 0010: 05 66 69 6E 61 6C __ __ __ __ __ __ __ __ __ __ .final (attr=*any*any*) 0000: A4 12 04 04 61 74 74 72 30 0A 81 03 61 6E 79 81 ....attr0...any. 0010: 03 61 6E 79 __ __ __ __ __ __ __ __ __ __ __ __ .any (attr=**) 0000: A4 0A 04 04 61 74 74 72 30 02 81 00 __ __ __ __ ....attr0... (attr=initial**) 0000: A4 13 04 04 61 74 74 72 30 0B 80 07 69 6E 69 74 ....attr0...init 0010: 69 61 6C 81 00 __ __ __ __ __ __ __ __ __ __ __ ial.. (attr=**final) 0000: A4 11 04 04 61 74 74 72 30 09 81 00 82 05 66 69 ....attr0.....fi 0010: 6E 61 6C __ __ __ __ __ __ __ __ __ __ __ __ __ nal (attr=initial**final) 0000: A4 1A 04 04 61 74 74 72 30 12 80 07 69 6E 69 74 ....attr0...init 0010: 69 61 6C 81 00 82 05 66 69 6E 61 6C __ __ __ __ ial....final (attr=initial***final) 0000: A4 1C 04 04 61 74 74 72 30 14 80 07 69 6E 69 74 ....attr0...init 0010: 69 61 6C 81 00 81 00 82 05 66 69 6E 61 6C __ __ ial......final (attr~=) 0000: A8 08 04 04 61 74 74 72 04 00 __ __ __ __ __ __ ....attr.. (attr~=fubar) 0000: A8 0D 04 04 61 74 74 72 04 05 66 75 62 61 72 __ ....attr..fubar (attr>=fubar) 0000: A5 0D 04 04 61 74 74 72 04 05 66 75 62 61 72 __ ....attr..fubar (attr<=fubar) 0000: A6 0D 04 04 61 74 74 72 04 05 66 75 62 61 72 __ ....attr..fubar # attribute 'attr' matching 'fubar' using matching rule '1.2.3' (attr:1.2.3:=fubar) 0000: A9 14 81 05 31 2E 32 2E 33 82 04 61 74 74 72 83 ....1.2.3..attr. 0010: 05 66 75 62 61 72 __ __ __ __ __ __ __ __ __ __ .fubar # attribute 'attr' in DN matching 'fubar' using default equality matching rule (attr:dn:=fubar) 0000: A9 10 82 04 61 74 74 72 83 05 66 75 62 61 72 84 ....attr..fubar. 0010: 01 FF __ __ __ __ __ __ __ __ __ __ __ __ __ __ .. # attribute 'attr' in DN matching 'fubar' using default equality matching rule (attr:DN:=fubar) 0000: A9 11 81 02 44 4E 82 04 61 74 74 72 83 05 66 75 ....DN..attr..fu 0010: 62 61 72 __ __ __ __ __ __ __ __ __ __ __ __ __ bar # attribute 'attr' in DN matching 'fubar' using matching rule '1.2.3' (attr:dn:1.2.3:=fubar) 0000: A9 17 81 05 31 2E 32 2E 33 82 04 61 74 74 72 83 ....1.2.3..attr. 0010: 05 66 75 62 61 72 84 01 FF __ __ __ __ __ __ __ .fubar... # any attribute matching 'fubar' with matching rule '1.2.3' (:1.2.3:=fubar) 0000: A9 0E 81 05 31 2E 32 2E 33 83 05 66 75 62 61 72 ....1.2.3..fubar # any attribute matching 'fubar' with matching rule 'caseExactMatch' (:caseExactMatch:=fubar) 0000: A9 17 81 0E 63 61 73 65 45 78 61 63 74 4D 61 74 ....caseExactMat 0010: 63 68 83 05 66 75 62 61 72 __ __ __ __ __ __ __ ch..fubar # any attribute from DN matching 'fubar' using matching rule '1.2.3' (:dn:1.2.3:=fubar) 0000: A9 11 81 05 31 2E 32 2E 33 83 05 66 75 62 61 72 ....1.2.3..fubar 0010: 84 01 FF __ __ __ __ __ __ __ __ __ __ __ __ __ ... (:dn:caseIgnoreMatch:=fubar) 0000: A9 1B 81 0F 63 61 73 65 49 67 6E 6F 72 65 4D 61 ....caseIgnoreMa 0010: 74 63 68 83 05 66 75 62 61 72 84 01 FF __ __ __ tch..fubar... (!(objectClass=*)) 0000: A2 0D 87 0B 6F 62 6A 65 63 74 43 6C 61 73 73 __ ....objectClass (!(|(&(!(objectClass=*))))) 0000: A2 13 A1 11 A0 0F A2 0D 87 0B 6F 62 6A 65 63 74 ..........object 0010: 43 6C 61 73 73 __ __ __ __ __ __ __ __ __ __ __ Class (&(objectClass=*)) 0000: A0 0D 87 0B 6F 62 6A 65 63 74 43 6C 61 73 73 __ ....objectClass (&(objectClass=*)(name~=)) 0000: A0 17 87 0B 6F 62 6A 65 63 74 43 6C 61 73 73 A8 ....objectClass. 0010: 08 04 04 6E 61 6D 65 04 00 __ __ __ __ __ __ __ ...name.. (|(objectClass=*)) 0000: A1 0D 87 0B 6F 62 6A 65 63 74 43 6C 61 73 73 __ ....objectClass (|(objectClass=*)(name~=)) 0000: A1 17 87 0B 6F 62 6A 65 63 74 43 6C 61 73 73 A8 ....objectClass. 0010: 08 04 04 6E 61 6D 65 04 00 __ __ __ __ __ __ __ ...name.. # multi-valued RDN (member=sn=Doe+givenName=John,ou=People,o=University of Michigan,c=US) 0000: A3 47 04 06 6D 65 6D 62 65 72 04 3D 73 6E 3D 44 .G..member.=sn=D 0001: 6F 65 2B 67 69 76 65 6E 4E 61 6D 65 3D 4A 6F 68 oe+givenName=Joh 0002: 6E 2C 6F 75 3D 50 65 6F 70 6C 65 2C 6F 3D 55 6E n,ou=People,o=Un 0003: 69 76 65 72 73 69 74 79 20 6F 66 20 4D 69 63 68 iversity of Mich 0004: 69 67 61 6E 2C 63 3D 55 53 __ __ __ __ __ __ __ igan,c=US # RDN containing a plus sign (dimension=width=2\5c+height=2,unit=meters) 0000: A3 2A 04 09 64 69 6D 65 6E 73 69 6F 6E 04 1D 77 .*..dimension..w 0001: 69 64 74 68 3D 32 5C 2B 68 65 69 67 68 74 3D 32 idth=2\+height=2 0002: 2C 75 6E 69 74 3D 6D 65 74 65 72 73 __ __ __ __ ,unit=meters # literal asterisk needs to be hexpair-escaped (cn=\2a) 0000: A3 07 04 02 63 6E 04 01 2A __ __ __ __ __ __ __ ....cn..* # literal backslash needs to be hexpair-escaped (cn=\5c) 0000: A3 07 04 02 63 6E 04 01 5C __ __ __ __ __ __ __ ....cn..\ # literal braces need to be hexpair-escaped (cn=\28braces\29) 0000: A3 0E 04 02 63 6E 04 08 28 62 72 61 63 65 73 29 ....cn..(braces) # non-ASCII UTF-8 character umlaut-a (cn=Hägar) 0000: A3 0C 04 02 63 6E 04 06 48 C3 A4 67 61 72 __ __ ....cn..H..gar (cn=H\c3\a4gar) # perl-ldap extension - strictly speaking a violation of the RFC (cn=\*) 0000: A3 07 04 02 63 6E 04 01 2A __ __ __ __ __ __ __ ....cn..* (cn=\2a) # perl-ldap extension - strictly speaking a violation of the RFC (cn=\\) 0000: A3 07 04 02 63 6E 04 01 5C __ __ __ __ __ __ __ ....cn..\ (cn=\5c) # perl-ldap extension - strictly speaking a violation of the RFC (cn=\(braces\)) 0000: A3 0E 04 02 63 6E 04 08 28 62 72 61 63 65 73 29 ....cn..(braces) (cn=\28braces\29) libnet-ldap-perl-0.6500+dfsg.orig/t/08time.t0000644000175000017500000000733112507234571017657 0ustar gregoagregoa#!perl use Test::More; use Net::LDAP::Util qw(:time); # Each line consists of a OPCDODE, a RESULT, DATETIME, and a EXPECTED # where # - OPCDODE is a TESTCASE followed by a RESULT sepaated by a colon # - TESTCASE is the check to be performed: one of # g2t generalizedTime_to_time # t2g time_to_generalizedTime # - RESULT is the expected result, one of: # yes TESTCASE succeeds and matches EXPECTED # no TESTCASE succeeds, but may not match EXPECTED # fail TESTCASE failes # - DATETIME is a date-time combination to be checked. # Depending on TESTCASE it may be either a string in LDAP's generalizedTime # format or a UNIX time string denoting the seconds since the epoch, # optionally extended by sub-second parts as decimal fractions # - EXPECTED is the expected value on successful conversion # To keep the order of tests, @tests is an array of ($filterstring => @ops) tuples my @tests = map { /^(g2t|t2g):(\w+)\s+(\S+)\s+(\S+)/ && [ $1, $2, $3, $4 ] } grep(/^(:?g2t|t2g):\w+\s+\S+\s+\S+/, ); # The elements of the @testcases array are the TESTCASE prefixes described above my %testcases = ( g2t => "generalizedTime_to_time", t2g => "time_to_generalizedTime" ); # calculate number of tests: ($] >= 5.012) ? plan tests => scalar(@tests) # @tests is a list of tests : plan skip_all => 'Perl version too old'; foreach my $elem (@tests) { my ($testcase, $result, $datetime, $expected) = @{$elem}; my $function = $testcases{$testcase}; my $got = &$function($datetime); foreach ($result) { /fail/ && ok(!defined($got), "$function('$datetime') should fail"); /no/ && is(defined($got), $expected, "$function('$datetime') should succeed"); /yes/ && is($got, $expected, "$function('$datetime') should yield $expected"); } } __DATA__ ## generalizedTime -> time g2t:yes 19691231235958.9Z -1.1 g2t:yes 19691231235959Z -1 g2t:yes 19691231235959.9Z -0.1 g2t:yes 19700101000000Z 0 g2t:yes 19700101000000.1Z 0.1 g2t:yes 19700101000001Z 1 g2t:yes 19700101000001.1Z 1.1 # "abbreviated" formats gt2:yes 196912312253.9Z -3966 gt2:yes 196912312254Z -3960 gt2:yes 1969123122.9Z -3960 g2t:yes 1969123123Z -3600 g2t:yes 1970010100Z 0 g2t:yes 1970010101Z 3600 gt2:yes 1970010101.1Z 3960 gt2:yes 197001010106Z 3960 gt2:yes 197001010106.1Z 3966 # formats wih offsets g2t:yes 19700101000000+0130 -5400 g2t:yes 19700101000000+01 -3600 g2t:yes 19700101000000-01 3600 g2t:yes 19700101000000-0130 5400 ## time -> generalizedTime t2g:yes -1.1 19691231235958.9Z t2g:yes -1 19691231235959Z t2g:yes -0.1 19691231235959.9Z t2g:yes 0 19700101000000Z t2g:yes 0.1 19700101000000.1Z t2g:yes 1 19700101000001Z t2g:yes 1.1 19700101000001.1Z t2g:yes -33358996800 09121123120000Z # illegally formatted generalizedTimes g2t:fail 9999 ? g2t:fail 2013Z ? g2t:fail 201303Z ? g2t:fail 20130315Z ? g2t:fail 20130315000000+1 ? g2t:fail 20130315000000+115 ? # wrong date: 2013 is/was no leap year g2t:fail 20130229000000Z ? # wrong date: gap between Julian & Gregorian calendar - this really should fail #g2t:yes 15821013000000Z -12219552000 # wrong date: second out of range g2t:fail 20130315000060Z ? # wrong date: minute out of range g2t:fail 20130315006000Z ? # wrong date: hour out of range g2t:fail 20130315240000Z ? # wrong date: day out of range g2t:fail 20130100000000Z ? g2t:fail 20131232000000Z ? # wrong date: month out of range g2t:fail 20130029000000Z ? g2t:fail 20131329000000Z ? # wrong date: year out of range g2t:fail -01230101000000Z ? g2t:fail 123450101000000Z ? # wrong date: year not supported by Time::Local g2t:fail 09991259235959Z ? g2t:fail 09121123120000Z -33358996800 # EOF libnet-ldap-perl-0.6500+dfsg.orig/t/44schema.t0000644000175000017500000000054512507234571020161 0ustar gregoagregoa#!perl use Test::More; BEGIN { require "t/common.pl" } start_server(version => 3) ? plan tests => 4 : plan skip_all => 'no server'; $ldap = client(); ok($ldap, "client"); $schema = $ldap->schema; ok($schema, "schema"); $ob = $schema->attribute('objectClass'); ok($ob, 'objectClass'); ok($ob->{syntax} eq '1.3.6.1.4.1.1466.115.121.1.38', 'syntax'); libnet-ldap-perl-0.6500+dfsg.orig/t/42search.t0000644000175000017500000000165012507234571020162 0ustar gregoagregoa#!perl use Test::More; BEGIN { require "t/common.pl" } start_server() ? plan tests => 15 : plan skip_all => 'no server'; $ldap = client(); ok($ldap, "client"); $mesg = $ldap->bind($MANAGERDN, password => $PASSWD); ok(!$mesg->code, "bind: " . $mesg->code . ": " . $mesg->error); ok(ldif_populate($ldap, "data/41-in.ldif"), "data/41-in.ldif"); # now search the database # Exact searching $mesg = $ldap->search(base => $BASEDN, filter => 'sn=jensen'); compare_ldif("41a",$mesg,$mesg->sorted); # Or searching $mesg = $ldap->search(base => $BASEDN, filter => '(|(objectclass=groupofnames)(sn=jones))'); compare_ldif("41b",$mesg,$mesg->sorted); # And searching $mesg = $ldap->search(base => $BASEDN, filter => '(&(objectclass=groupofnames)(cn=A*))'); compare_ldif("41c",$mesg,$mesg->sorted); # Not searching $mesg = $ldap->search(base => $BASEDN, filter => '(!(objectclass=person))'); compare_ldif("41d",$mesg,$mesg->sorted); libnet-ldap-perl-0.6500+dfsg.orig/t/01canon_dn.t0000644000175000017500000001142612507234571020471 0ustar gregoagregoa#!perl use Test::More; use Net::LDAP::Util qw(canonical_dn); # Each line has an opcode and a DN, opcode are # bad cacnonical_dn should return undef # ref Set new reference DN # same Should be the same as the current refdn # diff Should be different to the current refdn my @tests = map { /^(\w+)\s+(.*)/ } ; plan tests => scalar(@tests) >> 1; my $refdn; while(my($op,$dn) = splice(@tests,0,2)) { my $canon = canonical_dn($dn); my $failed = 0; if ($op eq 'ref') { $refdn=$dn; if ($failed = !defined $canon) { print "'$dn' should have parsed\n"; } } elsif ($op eq 'bad') { if ($failed = defined $canon) { print "'$dn' should not have parsed\n '$canon'\n"; } } elsif ( $op eq 'same' ) { if ($failed = !defined $canon) { print "'$dn' failed to parse\n"; } elsif ($failed = $canon ne $refdn) { print "'$refdn'\n\ndid not match\n\n from '$dn'\n got '$canon'\n"; } } elsif ($op eq 'diff' ) { if ($failed = !defined $canon) { print "'$dn' failed to parse\n"; } elsif ($failed = $canon eq $refdn) { print "'$refdn'\n\nmatched\n\n'$dn'\n'$canon'\n"; } } else { $failed = 1; warn "Bad opcode $op\n"; } ok(!$failed, "$dn is " . (($op eq 'bad') ? 'illegal' : 'legal')); } __DATA__ bad OU=Sales+CN=J. Smith,O=Widget Inc.,C=US, ref CN=J. Smith+OU=Sales,O=Widget Inc.,C=US same ou=Sales+cn=J. Smith,O=Widget Inc.,C=US same cn=J. Smith+ou=Sales,O=Widget Inc.,C=US same cn=J.\20Smith+ou=Sales,O=Widget\20Inc.,C=US same OU=Sales+CN=J. Smith;O=Widget Inc.;C=US same OU=Sales + CN=J. Smith,O=Widget Inc.,C=US same OU=Sales+CN=J. Smith , O=Widget Inc. , C=US same OU = Sales+CN =J. Smith,O= Widget Inc.,C=US same OU="Sales"+CN=J. Smith,O=Widget Inc.,C=US diff OU="Sales+CN=J. Smith",O=Widget Inc.,C=US ref cn=J.\20Smith\+ou=Sales,O=Widget\20Inc.,C=US ref cn=Clerk #1\+ou=Sales,O=Widget\20Inc.,C=US ref CN=Babs Jensen,O=Widget Inc.,C=US same cn=Babs Jensen,o=Widget Inc.,c=US # This is here to test a restriction that # canonical_dn does not decode BER encoded values ref 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB same 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB diff 1.3.6.1.4.1.1466.0=\04\02Hi,O=Test,C=GB ref 1.3.6.1.4.1.1466.0=Hi,O=Test,C=GB same oid.1.3.6.1.4.1.1466.0=Hi,O=Test,C=GB same OID.1.3.6.1.4.1.1466.0=Hi,O=Test,C=GB ref CN=Clif Harden+IDNUMBER=a0125589\20,OU=tiPerson,OU=person,O=ti,C=us diff cn=Clif Harden+IDNumber=a0125589,ou=tiPerson,ou=person,o=ti,c=us same cn=Clif Harden+IDNumber=a0125589\ ,ou=tiPerson,ou=person,o=ti,c=us same cn=Clif Harden+IDNumber=a0125589\20 ,ou=tiPerson,ou=person,o=ti,c=us same cn=Clif Harden+IDNumber="a0125589 ",ou=tiPerson,ou=person,o=ti,c=us ref CN=\20\20Graham Barr\20\20,OU=person,O=vc,C=us same Cn=" Graham Barr ",OU=person,O=vc,C=us same cn=" Graham \20Barr\20 ",OU=person,O=vc,C=us # empty ref ref UID=jsmith,DC=example,DC=net same UID=jsmith,DC=example,DC=net ref CN=J. Smith+OU=Sales,DC=example,DC=net same OU=Sales+CN=J. Smith,DC=example,DC=net ref CN=John Smith\2c III,DC=example,DC=net same CN=John Smith\, III,DC=example,DC=net same CN=John Smith\2C III,DC=example,DC=net ref CN=Before\0dAfter,DC=example,DC=net same CN=Before\0dAfter,DC=example,DC=net ref CN=\23John Smith\20,DC=example,DC=net same CN=\23John Smith\20,DC=example,DC=net same CN=\#John Smith\ ,DC=example,DC=net ref 1.3.6.1.4.1.1466.0=#04024869,DC=example,DC=com same 1.3.6.1.4.1.1466.0=#04024869,DC=example,DC=com ref CN=LuÄić same CN=Lu\C4\8Di\C4\87 # empty value ref 1.1.1= # option bad uid;x-option=jsmith # invalid attribute type name bad at_tr=jsmith # invalid attribute type name bad -attr=jsmith # invalid attribute type name #bad OID.1.1=jsmith # invalid numeric OID bad 1..1=jsmith # invalid numeric OID bad 1.1.=jsmith # invalid numeric OID #bad 01.1=jsmith # invalid numeric OID bad 1.ff=jsmith # invalid HEX form bad 1.1.1=#GG # invalid HEX form bad 1.1.1=#000 # invalid HEX form bad 1.1.1=#F # invalid HEX form bad 1.1.1=# # spaces #bad UID=jsmith, DC=example, DC=net # extra comma bad UID=jsmith,,DC=example,DC=net # semi-colons #bad UID=jsmith;DC=example;DC=net # quotes #bad CN="John Smith",DC=example,DC=net # brackets bad # unescaped , bad UID=john,smith # unescaped + bad UID=john+smith # invalid escape of ? or unescaped \ bad UID=john\?smith # invalid hex escape bad UID=john\Fsmith # invalid hex escape bad UID=john\GGsmith ref CN=John Smith \2c III,DC=example,DC=net same CN=John Smith \, III,DC=example,DC=net same CN=John Smith \2C III,DC=example,DC=net ref DISTINGUISHEDNAMETABLEKEY=cn\3dDSA\2c c\3dGB,CN=bilateral table,CN=DSA,C=US same distinguishedNameTableKey=cn\=DSA\, c\=GB, cn=bilateral table, cn=DSA, c=US # RT 51165 ref CN=tester\2c karl,OU=test,DC=example,DC=com same cn=tester\, karl,ou=test,dc=example,dc=com libnet-ldap-perl-0.6500+dfsg.orig/t/10ldif-controls.t0000644000175000017500000000320012507234571021460 0ustar gregoagregoa#!perl use Test::More; use File::Compare qw(compare_text); BEGIN { require "t/common.pl" } plan tests => 9; require Net::LDAP::LDIF; require Net::LDAP::Control::ManageDsaIT; require Net::LDAP::Control::ProxyAuth; my $infile = "data/10-in.ldif"; my $outfile1 = "$TEMPDIR/10-out.ldif"; my $cmpfile1 = "data/10-in.ldif"; my $ldifin = Net::LDAP::LDIF->new($infile,"r"); isa_ok($ldifin, Net::LDAP::LDIF, 'input object'); my @entries = (); while (my $entry = $ldifin->read_entry) { push(@entries, $entry); # push(@entries, control => \@controls) if (@controls); } is(scalar(@entries), 6, 'entries read'); $ldifin->done; #use Data::Dumper; #print STDERR Dumper(@entries); my $manage = Net::LDAP::Control::ManageDsaIT->new(critical => 1); isa_ok($manage, Net::LDAP::Control::ManageDsaIT, "control object"); my $auth1 = Net::LDAP::Control::ProxyAuth->new(authzID => 'dn:cn=me,ou=people,o=myorg.com'); isa_ok($auth1, Net::LDAP::Control::ProxyAuth, "control object"); my $auth2 = Net::LDAP::Control::ProxyAuth->new(authzID => 'dn:cn=Hägar,ou=people,o=myorg.com'); isa_ok($auth2, Net::LDAP::Control::ProxyAuth, "control object"); splice(@entries, 2, 0, control => [ $auth1 ]); splice(@entries, 1, 0, control => [ $manage, $auth2 ]); push(@entries, control => $manage); my $manage = $entries[-1]; isa_ok($manage, Net::LDAP::Control::ManageDsaIT, "control object read"); my $ldifout = Net::LDAP::LDIF->new($outfile1, 'w', change => 1); isa_ok($ldifout, Net::LDAP::LDIF, 'output object'); # write all entres at once my $x = $ldifout->write_entry(@entries); ok($x, 'entries written'); $ldifout->done; ok(!compare_text($cmpfile1,$outfile1), $cmpfile1); libnet-ldap-perl-0.6500+dfsg.orig/t/70sortctrl.t0000644000175000017500000000601212507234571020567 0ustar gregoagregoa#!perl # # The attribute given must have unique values over the entries # returned from the search. This is because this test checks # that the order of entries returned by 'attr' is the exact # opposite of '-attr' this is not guaranteed if two entries have # the same value for attr. use Test::More; BEGIN { require "t/common.pl" } use Net::LDAP::LDIF; use Net::LDAP::Control::Sort; use Net::LDAP::Constant qw( LDAP_CONTROL_SORTREQUEST LDAP_CONTROL_SORTRESULT LDAP_SUCCESS ); # @testcases is a list of ($order => $reversed) tuples my @testcases = ( [ 'cn:2.5.13.3' => '-cn:2.5.13.3' ] , [ 'sn:2.5.13.3 uid:2.5.13.3' => '-sn:2.5.13.3 -uid:2.5.13.3' ] ); start_server() ? plan tests => (4 + scalar(@testcases) * 9) : plan skip_all => 'no server'; $ldap = client(); isa_ok($ldap, Net::LDAP, "client"); $rootdse = $ldap->root_dse; isa_ok($rootdse, Net::LDAP::RootDSE, "root_dse"); SKIP: { skip("RootDSE does not offer sort control", 2 + scalar(@testcases) * 9) unless($rootdse->supported_control(LDAP_CONTROL_SORTREQUEST)); #$mesg = $ldap->start_tls; #ok(!$mesg->code, "start_tls: " . $mesg->code . ": " . $mesg->error); $mesg = $ldap->bind($MANAGERDN, password => $PASSWD); ok(!$mesg->code, "bind: " . $mesg->code . ": " . $mesg->error); ok(ldif_populate($ldap, "data/40-in.ldif"), "data/40-in.ldif"); foreach my $elem (@testcases) { my ($ordered,$reversed) = @{$elem}; my @attrs = map { s/:.*$//; $_ } split(/\s+/, $ordered); my $sort = Net::LDAP::Control::Sort->new(order => $ordered); isa_ok($sort, Net::LDAP::Control::Sort, "sort control object"); my $mesg = $ldap->search( base => $BASEDN, filter => '(objectclass=OpenLDAPperson)', control => [ $sort ], ); is($mesg->code, LDAP_SUCCESS, "search: " . $mesg->code . ": " . $mesg->error); my ($resp) = $mesg->control( LDAP_CONTROL_SORTRESULT ); ok($resp, 'LDAP_CONTROL_SORTRESULT response'); ok($resp && $resp->result == LDAP_SUCCESS , 'LDAP_CONTROL_SORTRESULT success'); if ($ENV{TEST_VERBOSE}) { my $rank = 0; foreach my $e ($mesg->entries) { note(++$rank, '. ', join(':', map { join(',',$e->get_value($_)) } @attrs)); } } my $dn1 = join ";", map { $_->dn } $mesg->entries; $sort = Net::LDAP::Control::Sort->new(order => $reversed); isa_ok($sort, Net::LDAP::Control::Sort, "sort control object (reversed)"); $mesg = $ldap->search( base => $BASEDN, filter => '(objectclass=OpenLDAPperson)', control => [ $sort ], ); is($mesg->code, LDAP_SUCCESS, 'search result'); ($resp) = $mesg->control( LDAP_CONTROL_SORTRESULT ); ok($resp, 'LDAP_CONTROL_SORTRESULT response'); ok($resp && $resp->result == LDAP_SUCCESS , 'LDAP_CONTROL_SORTRESULT success'); if ($ENV{TEST_VERBOSE}) { my $rank = 0; foreach my $e (reverse $mesg->entries) { note(++$rank,'. ',join(':', map { join(',',$e->get_value($_)) } @attrs)); } } my $dn2 = join ";", map { $_->dn } reverse $mesg->entries; is($dn1, $dn2, 'sort order'); } } libnet-ldap-perl-0.6500+dfsg.orig/t/71preread.t0000644000175000017500000001047112507234571020342 0ustar gregoagregoa#!perl use Test::More; use Net::LDAP; use Net::LDAP::Constant qw(LDAP_CONTROL_PREREAD); use Net::LDAP::Control::PreRead; BEGIN { require "t/common.pl" } my @tests; { # parse DATA into a list (= tests) of hashes (= test parameters) of lists (= parameter values) local $/ = ''; while(my $para = ) { my @lines = split(/\n/, $para); my %params; chomp(@lines); @lines = grep(!/^\s*(?:#.*?)?$/, @lines); map { push(@{$params{$1}}, $2) if (/^(\w+):\s*(.*)$/) } @lines; push(@tests, \%params) if (%params); } } start_server() ? plan tests => 4 + 6 * scalar(@tests) : plan skip_all => 'no server'; $ldap = client(); isa_ok($ldap, Net::LDAP, "client"); $rootdse = $ldap->root_dse; isa_ok($rootdse, Net::LDAP::RootDSE, "root_dse"); SKIP: { skip("RootDSE does not offer PreRead control", 2 + 6 * scalar(@tests)) unless($rootdse->supported_control(LDAP_CONTROL_PREREAD)); #$mesg = $ldap->start_tls(%tlsargs); #ok(!$mesg->code, "start_tls yields: ". $m->error); my $mesg = $ldap->bind($MANAGERDN, password => $PASSWD); ok(!$mesg->code, "bind: " . $mesg->code . ": " . $mesg->error); ok(ldif_populate($ldap, "data/40-in.ldif"), "data/40-in.ldif"); foreach my $test (@tests) { $mesg = $ldap->search(base => @{$test->{dn}} ? $test->{dn}[0] : '', filter => '(objectclass=*)', scope => 'base', attrs => $test->{attrs}); ok(!$mesg->code, "search: ". $mesg->code . ": " . $mesg->error); my $entry = $mesg->entry(0); my $origValue = join(':', map { sort $entry->get_value($_) } @{$test->{attrs}}); $control = Net::LDAP::Control::PreRead->new(attrs => $test->{attrs}); isa_ok($control, Net::LDAP::Control::PreRead, "control object"); foreach my $attr (@{$test->{attrs}}) { $entry->replace($attr => $test->{$attr} || []); } $mesg = $entry->update($ldap, control => $control); ok(!$mesg->code, "modify: " . $mesg->code . ": " . $mesg->error); my ($previous) = $mesg->control( LDAP_CONTROL_PREREAD ); isa_ok($control, Net::LDAP::Control::PreRead, "response object"); $entry = $previous->entry(); isa_ok($entry, Net::LDAP::Entry, "entry object"); my $prereadValue = join(':', map { sort $entry->get_value($_) } @{$test->{attrs}}); is($prereadValue, $origValue, "value in PreRead control matches"); } } __DATA__ ## each section below represents one test; logic similar to , structure similar to LDIF # each tests needs at least the elements # - dn: the object to modify/perform the test on # - attrs: the attributes to change and use in PreRead control # - $attr: optional - the new values (if any) for the attribute $attr # one attribute: replace a single value with another one dn: cn=Barbara Jensen, ou=Information Technology Division, ou=People, o=University of Michigan, c=US attrs: title title: HyperMythical Manager, Research Systems # one attribute: replace a single value attribute with multiple values dn: cn=Barbara Jensen, ou=Information Technology Division, ou=People, o=University of Michigan, c=US attrs: title title: Uber-Mythical Manager, Research Systems title: Cyber-Mythical Manager, Research Systems # one attribute: delete all values dn: cn=Barbara Jensen, ou=Information Technology Division, ou=People, o=University of Michigan, c=US attrs: title # multiple attribute: replace some values dn: cn=All Staff,ou=Groups,o=University of Michigan,c=US attrs: member attrs: description member: cn=Barbara Jensen, ou=Information Technology Division, ou=People, o=University of Michigan, c=US member: cn=Jane Doe, ou=Alumni Association, ou=People, o=University of Michigan, c=US member: cn=John Doe, ou=Information Technology Division, ou=People, o=University of Michigan, c=US member: cn=Mark Elliot, ou=Alumni Association, ou=People, o=University of Michigan, c=US member: cn=James A Jones 1, ou=Alumni Association, ou=People, o=University of Michigan, c=US member: cn=Ursula Hampster, ou=Alumni Association, ou=People, o=University of Michigan, c=US member: cn=Bjorn Jensen, ou=Information Technology Division, ou=People, o=University of Michigan, c=US description: Some of the sample data # multiple attribute: delete one, update the other dn: cn=All Staff,ou=Groups,o=University of Michigan,c=US attrs: member attrs: description member: cn=Manager, o=University of Michigan, c=US libnet-ldap-perl-0.6500+dfsg.orig/t/43modify.t0000644000175000017500000000110712507234571020202 0ustar gregoagregoa#!perl use Test::More; BEGIN { require "t/common.pl" } start_server() ? plan tests => 7 : plan skip_all => 'no server'; $ldap = client(); ok($ldap, "client"); $mesg = $ldap->bind($MANAGERDN, password => $PASSWD); ok(!$mesg->code, "bind: " . $mesg->code . ": " . $mesg->error); ok(ldif_populate($ldap, "data/42-in.ldif"), "data/42-in.ldif"); # load modify LDIF ok(ldif_populate($ldap, "data/42-mod.ldif", 'modify'), "data/42-mod.ldif"); # now search the database $mesg = $ldap->search(base => $BASEDN, filter => 'objectclass=*'); compare_ldif("42",$mesg,$mesg->sorted); libnet-ldap-perl-0.6500+dfsg.orig/t/40connect.t0000644000175000017500000000134212507234571020342 0ustar gregoagregoa#!perl use Test::More; BEGIN { require "t/common.pl" } start_server() ? plan tests => 3 : plan skip_all => 'no server'; $ldap = client(); ok($ldap, 'client with IPv4/IPv6 auto-selection' . ($ldap ? (', bound to ' . $ldap->{net_ldap_socket}->peerhost) : '')); $ldap = client(inet4 => 1); ok($ldap, 'client with IPv4' . ($ldap ? (', bound to ' . $ldap->{net_ldap_socket}->peerhost) : '')); SKIP: { skip('No IPv6 capable IO::Socket module installed', 1) unless (eval { require IO::Socket::INET6; } or eval { require IO::Socket::IP; IO::Socket::IP->VERSION(0.20); }); $ldap = client(inet6 => 1); ok($ldap, 'client with IPv6' . ($ldap ? (', bound to ' . $ldap->{net_ldap_socket}->peerhost) : '')); } libnet-ldap-perl-0.6500+dfsg.orig/t/common.pl0000644000175000017500000001240512507234571020207 0ustar gregoagregoaBEGIN { foreach (qw(my.cfg test.cfg)) { -f and require "$_" and last; } undef $SERVER_EXE unless $SERVER_EXE and -x $SERVER_EXE; # fallback for the host to connect - needs to support IPv4 & IPv6 $HOST ||= 'localhost'; # Where to put temporary files while testing # the Makefile is setup to delete temp/ when make clean is run $TEMPDIR = "./temp"; $SLAPD_SCHEMA_DIR ||= "./data"; $SLAPD_DB ||= 'mdb'; $SLAPD_MODULE_DIR ||= ''; $TESTDB = "$TEMPDIR/test-db"; $CONF = "$TEMPDIR/conf"; $PASSWD = 'secret'; $BASEDN = "o=University of Michigan, c=US"; $MANAGERDN= "cn=Manager, o=University of Michigan, c=US"; $JAJDN = "cn=James A Jones 1, ou=Alumni Association, ou=People, o=University of Michigan, c=US"; $BABSDN = "cn=Barbara Jensen, ou=Information Technology Division, ou=People, o=University of Michigan, c=US"; $PORT = 9009; @URL = (); my @server_opts; ($SERVER_TYPE,@server_opts) = split(/\+/, $SERVER_TYPE || 'none'); if ($SERVER_TYPE =~ /^openldap$/i) { $CONF_IN = "./data/slapd.conf.in"; $CONF = "$TEMPDIR/slapd.conf"; $SSL_PORT = 9010 if grep /^ssl$/i, @server_opts and eval { require IO::Socket::SSL; 1}; ($IPC_SOCK = "$TEMPDIR/ldapi_sock") =~ s,/,%2f,g if grep /^ipc$/i, @server_opts; $SASL = 1 if grep /^sasl$/i, @server_opts and eval { require Authen::SASL; 1 }; push @URL, "ldap://${HOST}:$PORT/"; push @URL, "ldaps://${HOST}:$SSL_PORT/" if $SSL_PORT; push @URL, "ldapi://$IPC_SOCK/" if $IPC_SOCK; @LDAPD = ($SERVER_EXE, '-f', $CONF, '-h', "@URL", qw(-d 1)); } $LDAP_VERSION ||= 3; mkdir($TEMPDIR,0777); die "$TEMPDIR is not a directory" unless -d $TEMPDIR; } use Test::More; use Net::LDAP; use Net::LDAP::LDIF; use Net::LDAP::Util qw(canonical_dn); use File::Path qw(rmtree); use File::Basename qw(basename); use File::Compare qw(compare_text); my $pid; sub start_server { my %arg = (version => 3, @_); return 0 unless ($LDAP_VERSION >= $arg{version} and $LDAPD[0] and -x $LDAPD[0] and (!$arg{ssl} or $SSL_PORT) and (!$arg{ipc} or $IPC_SOCK)); if ($CONF_IN and -f $CONF_IN) { # Create slapd config file open(CONFI, "<$CONF_IN") or die "$!"; open(CONFO, ">$CONF") or die "$!"; while() { # this will choke if a variable is not defined s/\$([A-Z]\w*)/${$1}/g; s/^TLS/#TLS/ unless $SSL_PORT; s/^(sasl.*)/#$1/ unless $SASL; s/^#module/module/ if $SLAPD_MODULE_DIR; print CONFO; } close(CONFI); close(CONFO); } rmtree($TESTDB) if ( -d $TESTDB ); mkdir($TESTDB, 0777); die "$TESTDB is not a directory" unless -d $TESTDB; note("@LDAPD") if $ENV{TEST_VERBOSE}; my $log = $TEMPDIR . "/" . basename($0,'.t'); unless ($pid = fork) { die "fork: $!" unless defined $pid; open(STDERR, ">$log"); open(STDOUT, ">&STDERR"); close(STDIN); exec(@LDAPD) or die "cannot exec @LDAPD"; } sleep 2; # wait for server to start return 1; } sub kill_server { if ($pid) { kill 9, $pid; sleep 2; undef $pid; } } END { kill_server(); } sub client { my %arg = @_; my $ldap; my $count; local $^W = 0; my %opt = map { $_ => $arg{$_} } grep { exists($arg{$_}) } qw/inet4 inet6 debug/; if ($arg{ssl}) { require Net::LDAPS; until($ldap = Net::LDAPS->new($HOST, %opt, port => $SSL_PORT, version => 3)) { die "ldaps://$HOST:$SSL_PORT/ $@" if ++$count > 10; sleep 1; } } elsif ($arg{ipc}) { require Net::LDAPI; until($ldap = Net::LDAPI->new($IPC_SOCK)) { die "ldapi://$IPC_SOCK/ $@" if ++$count > 10; sleep 1; } } elsif ($arg{url}) { print "Trying $arg{url}\n"; until($ldap = Net::LDAP->new($arg{url}, %opt)) { die "$arg{url} $@" if ++$count > 10; sleep 1; } } else { until($ldap = Net::LDAP->new($HOST, %opt, port => $PORT, version => $LDAP_VERSION)) { die "ldap://$HOST:$PORT/ $@" if ++$count > 10; sleep 1; } } $ldap; } sub compare_ldif { my($test,$mesg) = splice(@_,0,2); unless (ok(!$mesg->code, $mesg->error)) { skip($mesg->error, 2); return; } my $ldif = Net::LDAP::LDIF->new("$TEMPDIR/${test}-out.ldif","w", lowercase => 1); unless (ok($ldif, "Read ${test}-out.ldif")) { skip("Read error", 1); return; } my @canon_opt = (casefold => 'lower', separator => ', '); foreach $entry (@_) { $entry->dn(canonical_dn($entry->dn, @canon_opt)); foreach $attr ($entry->attributes) { $entry->delete($attr) if $attr =~ /^(modifiersname|modifytimestamp|creatorsname|createtimestamp)$/i; if ($attr =~ /^(seealso|member|owner)$/i) { $entry->replace($attr => [ map { canonical_dn($_, @canon_opt) } $entry->get_value($attr) ]); } } $ldif->write($entry); } $ldif->done; # close the file; ok(!compare_text("$TEMPDIR/${test}-out.ldif", "data/${test}-cmp.ldif"), "data/${test}-cmp.ldif"); } sub ldif_populate { my ($ldap, $file, $change) = @_; my $ok = 1; my $ldif = Net::LDAP::LDIF->new($file,"r", changetype => $change || 'add') or return; while (my $e = $ldif->read_entry) { $mesg = $e->update($ldap); if ($mesg->code) { $ok = 0; Net::LDAP::LDIF->new(qw(- w))->write_entry($e); print "# ",$mesg->code,": ",$mesg->error,"\n"; } } $ok; } 1; libnet-ldap-perl-0.6500+dfsg.orig/t/45dse.t0000644000175000017500000000067112507234571017475 0ustar gregoagregoa#!perl use Test::More; BEGIN { require "t/common.pl" } start_server(version => 3) ? plan tests => 4 : plan skip_all => 'no server'; $ldap = client(); ok($ldap, "client"); $dse = $ldap->root_dse; ok($dse, "dse"); $dse->dump if $dse and $ENV{TEST_VERBOSE}; my @extn = $dse->get_value('supportedExtension'); ok($dse->supported_extension(@extn), 'supported_extension'); ok(!$dse->supported_extension('foobar'), 'extension foobar'); libnet-ldap-perl-0.6500+dfsg.orig/t/06constant.t0000644000175000017500000000401512507234571020544 0ustar gregoagregoa#!perl -w use Test::More; BEGIN { for (1,2) { require Net::LDAP::Constant; } } use Net::LDAP::Util qw(ldap_error_name);; my @constant = qw( LDAP_SUCCESS LDAP_OPERATIONS_ERROR LDAP_PROTOCOL_ERROR LDAP_TIMELIMIT_EXCEEDED LDAP_SIZELIMIT_EXCEEDED LDAP_COMPARE_FALSE LDAP_COMPARE_TRUE LDAP_STRONG_AUTH_NOT_SUPPORTED LDAP_STRONG_AUTH_REQUIRED LDAP_PARTIAL_RESULTS LDAP_REFERRAL LDAP_ADMIN_LIMIT_EXCEEDED LDAP_UNAVAILABLE_CRITICAL_EXT LDAP_CONFIDENTIALITY_REQUIRED LDAP_SASL_BIND_IN_PROGRESS 15 LDAP_NO_SUCH_ATTRIBUTE LDAP_UNDEFINED_TYPE LDAP_INAPPROPRIATE_MATCHING LDAP_CONSTRAINT_VIOLATION LDAP_TYPE_OR_VALUE_EXISTS LDAP_INVALID_SYNTAX 22 23 24 25 26 27 28 29 30 31 LDAP_NO_SUCH_OBJECT LDAP_ALIAS_PROBLEM LDAP_INVALID_DN_SYNTAX LDAP_IS_LEAF LDAP_ALIAS_DEREF_PROBLEM 37 38 39 40 41 42 43 44 45 46 LDAP_PROXY_AUTHZ_FAILURE LDAP_INAPPROPRIATE_AUTH LDAP_INVALID_CREDENTIALS LDAP_INSUFFICIENT_ACCESS LDAP_BUSY LDAP_UNAVAILABLE LDAP_UNWILLING_TO_PERFORM LDAP_LOOP_DETECT 55 56 57 58 59 LDAP_SORT_CONTROL_MISSING LDAP_INDEX_RANGE_ERROR 62 63 LDAP_NAMING_VIOLATION LDAP_OBJECT_CLASS_VIOLATION LDAP_NOT_ALLOWED_ON_NONLEAF LDAP_NOT_ALLOWED_ON_RDN LDAP_ALREADY_EXISTS LDAP_NO_OBJECT_CLASS_MODS LDAP_RESULTS_TOO_LARGE LDAP_AFFECTS_MULTIPLE_DSAS 72 73 74 75 LDAP_VLV_ERROR 77 78 79 LDAP_OTHER LDAP_SERVER_DOWN LDAP_LOCAL_ERROR LDAP_ENCODING_ERROR LDAP_DECODING_ERROR LDAP_TIMEOUT LDAP_AUTH_UNKNOWN LDAP_FILTER_ERROR LDAP_USER_CANCELED LDAP_PARAM_ERROR LDAP_NO_MEMORY LDAP_CONNECT_ERROR LDAP_NOT_SUPPORTED LDAP_CONTROL_NOT_FOUND LDAP_NO_RESULTS_RETURNED LDAP_MORE_RESULTS_TO_RETURN LDAP_CLIENT_LOOP LDAP_REFERRAL_LIMIT_EXCEEDED ); plan tests => scalar(@constant); my $i = 0; while (my $const = $constant[$i]) { my $name = ldap_error_name($i); $const = sprintf("LDAP error code %d(0x%02X)",$i,$i) unless $const =~ /\D/; ok($name && $name eq $const, "$const"); ++$i; } libnet-ldap-perl-0.6500+dfsg.orig/t/74matchedvalues.t0000644000175000017500000000714112510541205021535 0ustar gregoagregoa#!perl use Test::More; use Net::LDAP; use Net::LDAP::Constant qw(LDAP_CONTROL_MATCHEDVALUES); use Net::LDAP::Control::MatchedValues; BEGIN { require "t/common.pl" } my @tests; { # parse DATA into a list (= tests) of hashes (= test parameters) of lists (= parameter values) local $/ = ''; while(my $para = ) { my @lines = split(/\n/, $para); my %params; chomp(@lines); @lines = grep(!/^\s*(?:#.*?)?$/, @lines); map { push(@{$params{$1}}, $2) if (/^(\w+):\s*(.*)$/) } @lines; push(@tests, \%params) if (%params); } } start_server() ? plan tests => 4 + 3 * scalar(@tests) : plan skip_all => 'no server'; $ldap = client(); isa_ok($ldap, Net::LDAP, "client"); $rootdse = $ldap->root_dse; isa_ok($rootdse, Net::LDAP::RootDSE, "root_dse"); SKIP: { skip("RootDSE does not offer MatchedValues control", 2 + 3 * scalar(@tests)) unless($rootdse->supported_control(LDAP_CONTROL_MATCHEDVALUES)); #$mesg = $ldap->start_tls(%tlsargs); #ok(!$mesg->code, "start_tls yields: ". $m->error); $mesg = $ldap->bind($MANAGERDN, password => $PASSWD); ok(!$mesg->code, "bind: " . $mesg->code . ": " . $mesg->error); ok(ldif_populate($ldap, "data/40-in.ldif"), "data/40-in.ldif"); foreach my $test (@tests) { $control = Net::LDAP::Control::MatchedValues->new(matchedValues => $test->{match}->[0]); isa_ok($control, Net::LDAP::Control::MatchedValues, "control object"); $mesg = $ldap->search(base => $test->{dn}->[0], filter => $test->{filter} ? $test->{filter}->[0] : '(objectclass=*)', scope => $test->{scope} ? $test->{scope}->[0] : 'sub', attrs => $test->{attrs} || [ '*' ], control => $control); ok(!$mesg->code, "search: " . $mesg->code . ": " . $mesg->error); my $success = 1; my $entry = $mesg->entry(0); foreach $attr (@{$test->{attrs}}) { my $vals = join(':', sort $entry->get_value($attr)); my $expected = $test->{$attr} ? join(':', sort @{$test->{$attr}}) : ''; $success = 0 if ($vals ne $expected); } ok($success, "values match expectations"); } } __DATA__ ## each section below represents one test; logic similar to , structure similar to LDIF # each tests needs at least the elements # - match: the value of the MatchedValues control # - dn: the base-DN of the search # - filter: the filter to use (first element important only) # one attribute, no wildcards match: ((cn=Babs Jensen)) dn: cn=Barbara Jensen, ou=Information Technology Division, ou=People, o=University of Michigan, c=US filter: (mail=bjensen@mailgw.umich.edu) scope: base attrs: cn cn: Babs Jensen # one attribute, wildcards match: ((cn=Babs*Jensen)) dn: cn=Barbara Jensen, ou=Information Technology Division, ou=People, o=University of Michigan, c=US filter: (mail=bjensen@mailgw.umich.edu) scope: base attrs: cn cn: Babs Jensen # one attribute, wildcards, attrs beyond match match: ((cn=Babs*Jensen)) dn: cn=Barbara Jensen, ou=Information Technology Division, ou=People, o=University of Michigan, c=US filter: (mail=bjensen@mailgw.umich.edu) scope: base attrs: cn attrs: title cn: Babs Jensen # one attribute, wildcards, no matching value match: ((description=*LDAP*)) dn: cn=Barbara Jensen, ou=Information Technology Division, ou=People, o=University of Michigan, c=US filter: (mail=bjensen@mailgw.umich.edu) scope: base attrs: description # multiple attributes, wildcards match: ((cn=* Jensen)(title=*Myth*)) dn: cn=Barbara Jensen, ou=Information Technology Division, ou=People, o=University of Michigan, c=US filter: (mail=bjensen@mailgw.umich.edu) scope: base attrs: title attrs: cn title: Mythical Manager, Research Systems cn: Barbara Jensen cn: Babs Jensen libnet-ldap-perl-0.6500+dfsg.orig/lib/0000755000175000017500000000000012510544053016654 5ustar gregoagregoalibnet-ldap-perl-0.6500+dfsg.orig/lib/Net/0000755000175000017500000000000012510544053017402 5ustar gregoagregoalibnet-ldap-perl-0.6500+dfsg.orig/lib/Net/LDAPI.pm0000644000175000017500000000313112507234571020576 0ustar gregoagregoa# Copyright (c) 2003-2004 Derrik Pates and Graham Barr # . All rights reserved. This program is free # software; you can redistribute it and/or modify it under the same # terms as Perl itself. package Net::LDAPI; use strict; use Net::LDAP; our @ISA = qw(Net::LDAP); our $VERSION = '0.04'; sub new { shift->SUPER::new(@_, scheme => 'ldapi'); } 1; __END__ =head1 NAME Net::LDAPI - use LDAP over a UNIX domain socket =head1 SYNOPSIS use Net::LDAPI; $ldapi = Net::LDAPI->new('/var/run/ldapi'); # alternate way use Net::LDAP; $ldapi = Net::LDAP->new('ldapi://'); =head1 DESCRIPTION Communicate using the LDAP protocol to a directory server using a UNIX domain socket. This mechanism is non-standard, UNIX-specific and not widely supported. All the normal C methods can be used with a C object; see L for details. =head1 CONSTRUCTOR =over 4 =item new ( [SOCKPATH] ) Create a new connection. SOCKPATH can optionally be specified, to specify the location of the UNIX domain socket to connect to. If SOCKPATH is not given, the environment variable C is evaluated, and if that does not exist, the value C is used. See L for further details. =back =head1 SEE ALSO L, L =head1 BUGS None yet. =head1 AUTHOR Derrik Pates Edpates@dsdk12.netE =head1 COPYRIGHT Copyright (c) 2003-2004, Derrik Pates and Graham Barr. All rights reserved. This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut libnet-ldap-perl-0.6500+dfsg.orig/lib/Net/LDAP.pm0000644000175000017500000007011612510542541020465 0ustar gregoagregoa# Copyright (c) 1997-2004 Graham Barr . All rights reserved. # This program is free software; you can redistribute it and/or # modify it under the same terms as Perl itself. package Net::LDAP; use strict; use Socket qw(AF_INET AF_INET6 AF_UNSPEC SOL_SOCKET SO_KEEPALIVE); use IO::Socket; use IO::Select; use Tie::Hash; use Convert::ASN1 qw(asn_read); use Net::LDAP::Message; use Net::LDAP::ASN qw(LDAPResponse); use Net::LDAP::Constant qw(LDAP_SUCCESS LDAP_OPERATIONS_ERROR LDAP_SASL_BIND_IN_PROGRESS LDAP_DECODING_ERROR LDAP_PROTOCOL_ERROR LDAP_ENCODING_ERROR LDAP_FILTER_ERROR LDAP_LOCAL_ERROR LDAP_PARAM_ERROR LDAP_INAPPROPRIATE_AUTH LDAP_SERVER_DOWN LDAP_USER_CANCELED LDAP_EXTENSION_START_TLS LDAP_UNAVAILABLE ); # check for IPv6 support: prefer IO::Socket::IP 0.20+ over IO::Socket::INET6 use constant CAN_IPV6 => do { local $SIG{__DIE__}; eval { require IO::Socket::IP; IO::Socket::IP->VERSION(0.20); } ? 'IO::Socket::IP' : eval { require IO::Socket::INET6; } ? 'IO::Socket::INET6' : ''; }; our $VERSION = '0.65'; our @ISA = qw(Tie::StdHash Net::LDAP::Extra); our $LDAP_VERSION = 3; # default LDAP protocol version # Net::LDAP::Extra will only exist is someone use's the module. But we need # to ensure the package stash exists or perl will complain that we inherit # from a non-existent package. I could just use the module, but I did not # want to. $Net::LDAP::Extra::create = $Net::LDAP::Extra::create = 0; sub import { shift; unshift @_, 'Net::LDAP::Constant'; require Net::LDAP::Constant; goto &{Net::LDAP::Constant->can('import')}; } sub _options { my %ret = @_; my $once = 0; for my $v (grep { /^-/ } keys %ret) { require Carp; $once++ or Carp::carp('deprecated use of leading - for options'); $ret{substr($v, 1)} = $ret{$v}; } $ret{control} = [ map { (ref($_) =~ /[^A-Z]/) ? $_->to_asn : $_ } ref($ret{control}) eq 'ARRAY' ? @{$ret{control}} : $ret{control} ] if exists $ret{control}; \%ret; } sub _dn_options { unshift @_, 'dn' if @_ & 1; &_options; } sub _err_msg { my $mesg = shift; my $errstr = $mesg->dn || ''; $errstr .= ': ' if $errstr; $errstr . $mesg->error; } my %onerror = ( die => sub { require Carp; Carp::croak(_err_msg(@_)) }, warn => sub { require Carp; Carp::carp(_err_msg(@_)); $_[0] }, undef => sub { require Carp; Carp::carp(_err_msg(@_)) if $^W; undef }, ); sub _error { my ($ldap, $mesg) = splice(@_, 0, 2); $mesg->set_error(@_); $ldap->{net_ldap_onerror} && !$ldap->{net_ldap_async} ? scalar &{$ldap->{net_ldap_onerror}}($mesg) : $mesg; } sub new { my $self = shift; my $type = ref($self) || $self; my $host = shift if @_ % 2; my $arg = &_options; my $obj = bless {}, $type; foreach my $uri (ref($host) ? @$host : ($host)) { my $scheme = $arg->{scheme} || 'ldap'; my $h = $uri; if (defined($h)) { $h =~ s,^(\w+)://,, and $scheme = lc($1); $h =~ s,/.*,,; # remove path part $h =~ s/%([A-Fa-f0-9]{2})/chr(hex($1))/eg; # unescape } my $meth = $obj->can("connect_$scheme") or next; if (&$meth($obj, $h, $arg)) { $obj->{net_ldap_uri} = $uri; $obj->{net_ldap_scheme} = $scheme; last; } } return undef unless $obj->{net_ldap_socket}; $obj->{net_ldap_socket}->setsockopt(SOL_SOCKET, SO_KEEPALIVE, $arg->{keepalive} ? 1 : 0) if (defined($arg->{keepalive})); $obj->{net_ldap_rawsocket} = $obj->{net_ldap_socket}; $obj->{net_ldap_resp} = {}; $obj->{net_ldap_version} = $arg->{version} || $LDAP_VERSION; $obj->{net_ldap_async} = $arg->{async} ? 1 : 0; $obj->{raw} = $arg->{raw} if ($arg->{raw}); if (defined(my $onerr = $arg->{onerror})) { $onerr = $onerror{$onerr} if exists $onerror{$onerr}; $obj->{net_ldap_onerror} = $onerr; } $obj->debug($arg->{debug} || 0 ); $obj->outer; } sub connect_ldap { my ($ldap, $host, $arg) = @_; my $port = $arg->{port} || 389; my $class = (CAN_IPV6) ? CAN_IPV6 : 'IO::Socket::INET'; my $domain = $arg->{inet4} ? AF_INET : ($arg->{inet6} ? AF_INET6 : AF_UNSPEC); # separate port from host overwriting given/default port $host =~ s/^([^:]+|\[.*\]):(\d+)$/$1/ and $port = $2; if ($arg->{inet6} && !CAN_IPV6) { $@ = 'unable to load IO::Socket::INET6; no IPv6 support'; return undef; } $ldap->{net_ldap_socket} = $class->new( PeerAddr => $host, PeerPort => $port, LocalAddr => $arg->{localaddr} || undef, Proto => 'tcp', Domain => $domain, MultiHomed => $arg->{multihomed}, Timeout => defined $arg->{timeout} ? $arg->{timeout} : 120 ) or return undef; $ldap->{net_ldap_host} = $host; $ldap->{net_ldap_port} = $port; } # Different OpenSSL verify modes. my %ssl_verify = qw(none 0 optional 1 require 3); sub connect_ldaps { my ($ldap, $host, $arg) = @_; my $port = $arg->{port} || 636; my $domain = $arg->{inet4} ? AF_INET : ($arg->{inet6} ? AF_INET6 : AF_UNSPEC); if ($arg->{inet6} && !CAN_IPV6) { $@ = 'unable to load IO::Socket::INET6; no IPv6 support'; return undef; } require IO::Socket::SSL; # separate port from host overwriting given/default port $host =~ s/^([^:]+|\[.*\]):(\d+)$/$1/ and $port = $2; $arg->{sslserver} = $host unless defined $arg->{sslserver}; $ldap->{net_ldap_socket} = IO::Socket::SSL->new( PeerAddr => $host, PeerPort => $port, LocalAddr => $arg->{localaddr} || undef, Proto => 'tcp', Domain => $domain, Timeout => defined $arg->{timeout} ? $arg->{timeout} : 120, _SSL_context_init_args($arg) ) or return undef; $ldap->{net_ldap_host} = $host; $ldap->{net_ldap_port} = $port; } sub _SSL_context_init_args { my $arg = shift; my $verify = 0; my %verifycn_ctx = (); my ($clientcert, $clientkey, $passwdcb); if (exists $arg->{verify}) { my $v = lc $arg->{verify}; $verify = 0 + (exists $ssl_verify{$v} ? $ssl_verify{$v} : $verify); if ($verify) { $verifycn_ctx{SSL_verifycn_scheme} = 'ldap'; $verifycn_ctx{SSL_verifycn_name} = $arg->{sslserver} if (defined $arg->{sslserver}); } } if (exists $arg->{clientcert}) { $clientcert = $arg->{clientcert}; if (exists $arg->{clientkey}) { $clientkey = $arg->{clientkey}; } else { require Carp; Carp::croak('Setting client public key but not client private key'); } } if ($arg->{checkcrl} && !$arg->{capath}) { require Carp; Carp::croak('Cannot check CRL without having CA certificates'); } if (exists $arg->{keydecrypt}) { $passwdcb = $arg->{keydecrypt}; } # allow deprecated "sslv2/3" in addition to IO::Socket::SSL's "sslv23" if (defined $arg->{sslversion}) { $arg->{sslversion} =~ s:sslv2/3:sslv23:io; } ( defined $arg->{ciphers} ? ( SSL_cipher_list => $arg->{ciphers} ) : (), defined $arg->{sslversion} ? ( SSL_version => $arg->{sslversion} ) : (), SSL_ca_file => exists $arg->{cafile} ? $arg->{cafile} : '', SSL_ca_path => exists $arg->{capath} ? $arg->{capath} : '', SSL_key_file => $clientcert ? $clientkey : undef, SSL_passwd_cb => $passwdcb, SSL_check_crl => $arg->{checkcrl} ? 1 : 0, SSL_use_cert => $clientcert ? 1 : 0, SSL_cert_file => $clientcert, SSL_verify_mode => $verify, %verifycn_ctx, ); } sub connect_ldapi { my ($ldap, $peer, $arg) = @_; $peer = $ENV{LDAPI_SOCK} || '/var/run/ldapi' unless length $peer; require IO::Socket::UNIX; $ldap->{net_ldap_socket} = IO::Socket::UNIX->new( Peer => $peer, Timeout => defined $arg->{timeout} ? $arg->{timeout} : 120 ) or return undef; # try to get canonical host name [to allow start_tls on the connection] require Socket; if (Socket->can('getnameinfo') && Socket->can('getaddrinfo')) { my @addrs; my ($err, $host, $path) = Socket::getnameinfo($ldap->{net_ldap_socket}->peername, &Socket::AI_CANONNAME); ($err, @addrs) = Socket::getaddrinfo($host, 0, { flags => &Socket::AI_CANONNAME } ) unless ($err); map { $ldap->{net_ldap_host} = $_->{canonname} if ($_->{canonname}) } @addrs unless ($err); } $ldap->{net_ldap_host} ||= 'localhost'; $ldap->{net_ldap_peer} = $peer; } sub message { my $ldap = shift; shift->new($ldap, @_); } sub async { my $ldap = shift; @_ ? ($ldap->{net_ldap_async}, $ldap->{net_ldap_async} = shift)[0] : $ldap->{net_ldap_async}; } sub debug { my $ldap = shift; require Convert::ASN1::Debug if $_[0]; @_ ? ($ldap->{net_ldap_debug}, $ldap->{net_ldap_debug} = shift)[0] : $ldap->{net_ldap_debug}; } sub sasl { $_[0]->{sasl}; } sub socket { my $ldap = shift; my %opt = @_; (exists($opt{sasl_layer}) && !$opt{sasl_layer}) ? $ldap->{net_ldap_rawsocket} : $ldap->{net_ldap_socket}; } sub host { my $ldap = shift; ($ldap->{net_ldap_scheme} ne 'ldapi') ? $ldap->{net_ldap_host} : $ldap->{net_ldap_peer}; } sub port { $_[0]->{net_ldap_port} || undef; } sub scheme { $_[0]->{net_ldap_scheme}; } sub uri { $_[0]->{net_ldap_uri}; } sub unbind { my $ldap = shift; my $arg = &_options; my $mesg = $ldap->message('Net::LDAP::Unbind' => $arg); my $control = $arg->{control} and $ldap->{net_ldap_version} < 3 and return _error($ldap, $mesg, LDAP_PARAM_ERROR, 'Controls require LDAPv3'); $mesg->encode( unbindRequest => 1, controls => $control, ) or return _error($ldap, $mesg, LDAP_ENCODING_ERROR, "$@"); $ldap->_sendmesg($mesg); } # convenience alias *done = \&unbind; sub ldapbind { require Carp; Carp::carp('->ldapbind deprecated, use ->bind') if $^W; goto &bind; } my %ptype = qw( password simple krb41password krbv41 krb42password krbv42 kerberos41 krbv41 kerberos42 krbv42 sasl sasl noauth anon anonymous anon ); sub bind { my $ldap = shift; my $arg = &_dn_options; require Net::LDAP::Bind; my $mesg = $ldap->message('Net::LDAP::Bind' => $arg); $ldap->version(delete $arg->{version}) if exists $arg->{version}; my $dn = delete $arg->{dn} || ''; my $control = delete $arg->{control} and $ldap->{net_ldap_version} < 3 and return _error($ldap, $mesg, LDAP_PARAM_ERROR, 'Controls require LDAPv3'); my %stash = ( name => ref($dn) ? $dn->dn : $dn, version => $ldap->version, ); my($auth_type, $passwd) = scalar(keys %$arg) ? () : (simple => ''); keys %ptype; # Reset iterator while (my($param, $type) = each %ptype) { if (exists $arg->{$param}) { ($auth_type, $passwd) = $type eq 'anon' ? (simple => '') : ($type, $arg->{$param}); return _error($ldap, $mesg, LDAP_INAPPROPRIATE_AUTH, 'No password, did you mean noauth or anonymous ?') if $type eq 'simple' and $passwd eq ''; last; } } return _error($ldap, $mesg, LDAP_INAPPROPRIATE_AUTH, 'No AUTH supplied') unless $auth_type; if ($auth_type eq 'sasl') { return _error($ldap, $mesg, LDAP_PARAM_ERROR, 'SASL requires LDAPv3') if $ldap->{net_ldap_version} < 3; my $sasl = $passwd; my $sasl_conn; if (ref($sasl) and $sasl->isa('Authen::SASL')) { # If we're talking to a round-robin, the canonical name of # the host we are talking to might not match the name we # requested. Look at the rawsocket because SASL layer filehandles # don't support socket methods. my $sasl_host; if (exists($arg->{sasl_host})) { if ($arg->{sasl_host}) { $sasl_host = $arg->{sasl_host}; } elsif ($ldap->{net_ldap_rawsocket}->can('peerhost')) { $sasl_host = $ldap->{net_ldap_rawsocket}->peerhost; } } $sasl_host ||= $ldap->{net_ldap_host}; $sasl_conn = eval { local ($SIG{__DIE__}); $sasl->client_new('ldap', $sasl_host); }; } else { $sasl_conn = $sasl; } return _error($ldap, $mesg, LDAP_LOCAL_ERROR, "$@") unless defined($sasl_conn); # Tell SASL the local and server IP addresses $sasl_conn->property( sockname => $ldap->{net_ldap_rawsocket}->sockname, peername => $ldap->{net_ldap_rawsocket}->peername, ); my $initial = $sasl_conn->client_start; return _error($ldap, $mesg, LDAP_LOCAL_ERROR, $sasl_conn->error) unless defined($initial); $passwd = { mechanism => $sasl_conn->mechanism, credentials => $initial, }; # Save data, we will need it later $mesg->_sasl_info($stash{name}, $control, $sasl_conn); } $stash{authentication} = { $auth_type => $passwd }; $mesg->encode( bindRequest => \%stash, controls => $control ) or return _error($ldap, $mesg, LDAP_ENCODING_ERROR, "$@"); $ldap->_sendmesg($mesg); } my %scope = qw(base 0 one 1 single 1 sub 2 subtree 2 children 3); my %deref = qw(never 0 search 1 find 2 always 3); sub search { my $ldap = shift; my $arg = &_options; require Net::LDAP::Search; $arg->{raw} = $ldap->{raw} if ($ldap->{raw} && !defined($arg->{raw})); my $mesg = $ldap->message('Net::LDAP::Search' => $arg); my $control = $arg->{control} and $ldap->{net_ldap_version} < 3 and return _error($ldap, $mesg, LDAP_PARAM_ERROR, 'Controls require LDAPv3'); my $base = $arg->{base} || ''; my $filter; unless (ref ($filter = $arg->{filter})) { require Net::LDAP::Filter; my $f = Net::LDAP::Filter->new; $f->parse($filter) or return _error($ldap, $mesg, LDAP_PARAM_ERROR, 'Bad filter'); $filter = $f; } my %stash = ( baseObject => ref($base) ? $base->dn : $base, scope => 2, derefAliases => 2, sizeLimit => $arg->{sizelimit} || 0, timeLimit => $arg->{timelimit} || 0, typesOnly => $arg->{typesonly} || $arg->{attrsonly} || 0, filter => $filter, attributes => $arg->{attrs} || [] ); if (exists $arg->{scope}) { my $sc = lc $arg->{scope}; $stash{scope} = 0 + (exists $scope{$sc} ? $scope{$sc} : $sc); } if (exists $arg->{deref}) { my $dr = lc $arg->{deref}; $stash{derefAliases} = 0 + (exists $deref{$dr} ? $deref{$dr} : $dr); } $mesg->encode( searchRequest => \%stash, controls => $control ) or return _error($ldap, $mesg, LDAP_ENCODING_ERROR, "$@"); $ldap->_sendmesg($mesg); } sub add { my $ldap = shift; my $arg = &_dn_options; my $mesg = $ldap->message('Net::LDAP::Add' => $arg); my $control = $arg->{control} and $ldap->{net_ldap_version} < 3 and return _error($ldap, $mesg, LDAP_PARAM_ERROR, 'Controls require LDAPv3'); my $entry = $arg->{dn} or return _error($ldap, $mesg, LDAP_PARAM_ERROR, 'No DN specified'); unless (ref $entry) { require Net::LDAP::Entry; $entry = Net::LDAP::Entry->new; $entry->dn($arg->{dn}); $entry->add(@{$arg->{attrs} || $arg->{attr} || []}); } $mesg->encode( addRequest => $entry->asn, controls => $control ) or return _error($ldap, $mesg, LDAP_ENCODING_ERROR, "$@"); $ldap->_sendmesg($mesg); } my %opcode = ( add => 0, delete => 1, replace => 2, increment => 3 ); sub modify { my $ldap = shift; my $arg = &_dn_options; my $mesg = $ldap->message('Net::LDAP::Modify' => $arg); my $control = $arg->{control} and $ldap->{net_ldap_version} < 3 and return _error($ldap, $mesg, LDAP_PARAM_ERROR, 'Controls require LDAPv3'); my $dn = $arg->{dn} or return _error($ldap, $mesg, LDAP_PARAM_ERROR, 'No DN specified'); my @ops; my $opcode; if (exists $arg->{changes}) { my $opcode; my $j = 0; while ($j < @{$arg->{changes}}) { return _error($ldap, $mesg, LDAP_PARAM_ERROR, "Bad change type '" . $arg->{changes}[--$j] . "'") unless defined($opcode = $opcode{$arg->{changes}[$j++]}); my $chg = $arg->{changes}[$j++]; if (ref($chg)) { my $i = 0; while ($i < @$chg) { push @ops, { operation => $opcode, modification => { type => $chg->[$i], vals => ref($chg->[$i+1]) ? $chg->[$i+1] : [$chg->[$i+1]] } }; $i += 2; } } } } else { foreach my $op (qw(add delete replace increment)) { next unless exists $arg->{$op}; my $opt = $arg->{$op}; my $opcode = $opcode{$op}; if (ref($opt) eq 'HASH') { while (my ($k, $v) = each %$opt) { push @ops, { operation => $opcode, modification => { type => $k, vals => ref($v) ? $v : [$v] } }; } } elsif (ref($opt) eq 'ARRAY') { my $k = 0; while ($k < @{$opt}) { my $attr = ${$opt}[$k++]; my $val = $opcode == 1 ? [] : ${$opt}[$k++]; push @ops, { operation => $opcode, modification => { type => $attr, vals => ref($val) ? $val : [$val] } }; } } else { push @ops, { operation => $opcode, modification => { type => $opt, vals => [] } }; } } } $mesg->encode( modifyRequest => { object => ref($dn) ? $dn->dn : $dn, modification => \@ops }, controls => $control ) or return _error($ldap, $mesg, LDAP_ENCODING_ERROR, "$@"); $ldap->_sendmesg($mesg); } sub delete { my $ldap = shift; my $arg = &_dn_options; my $mesg = $ldap->message('Net::LDAP::Delete' => $arg); my $control = $arg->{control} and $ldap->{net_ldap_version} < 3 and return _error($ldap, $mesg, LDAP_PARAM_ERROR, 'Controls require LDAPv3'); my $dn = $arg->{dn} or return _error($ldap, $mesg, LDAP_PARAM_ERROR, 'No DN specified'); $mesg->encode( delRequest => ref($dn) ? $dn->dn : $dn, controls => $control ) or return _error($ldap, $mesg, LDAP_ENCODING_ERROR, "$@"); $ldap->_sendmesg($mesg); } sub moddn { my $ldap = shift; my $arg = &_dn_options; my $del = $arg->{deleteoldrdn} || $arg->{delete} || 0; my $newsup = $arg->{newsuperior}; my $mesg = $ldap->message('Net::LDAP::ModDN' => $arg); my $control = $arg->{control} and $ldap->{net_ldap_version} < 3 and return _error($ldap, $mesg, LDAP_PARAM_ERROR, 'Controls require LDAPv3'); my $dn = $arg->{dn} or return _error($ldap, $mesg, LDAP_PARAM_ERROR, 'No DN specified'); my $new = $arg->{newrdn} || $arg->{new} or return _error($ldap, $mesg, LDAP_PARAM_ERROR, 'No NewRDN specified'); $mesg->encode( modDNRequest => { entry => ref($dn) ? $dn->dn : $dn, newrdn => ref($new) ? $new->dn : $new, deleteoldrdn => $del, newSuperior => ref($newsup) ? $newsup->dn : $newsup, }, controls => $control ) or return _error($ldap, $mesg, LDAP_ENCODING_ERROR, "$@"); $ldap->_sendmesg($mesg); } # now maps to the V3/X.500(93) modifydn map sub modrdn { goto &moddn } sub compare { my $ldap = shift; my $arg = &_dn_options; my $mesg = $ldap->message('Net::LDAP::Compare' => $arg); my $control = $arg->{control} and $ldap->{net_ldap_version} < 3 and return _error($ldap, $mesg, LDAP_PARAM_ERROR, 'Controls require LDAPv3'); my $dn = $arg->{dn} or return _error($ldap, $mesg, LDAP_PARAM_ERROR, 'No DN specified'); my $attr = exists $arg->{attr} ? $arg->{attr} : exists $arg->{attrs} #compat ? $arg->{attrs}[0] : ''; my $value = exists $arg->{value} ? $arg->{value} : exists $arg->{attrs} #compat ? $arg->{attrs}[1] : ''; $mesg->encode( compareRequest => { entry => ref($dn) ? $dn->dn : $dn, ava => { attributeDesc => $attr, assertionValue => $value } }, controls => $control ) or return _error($ldap, $mesg, LDAP_ENCODING_ERROR, "$@"); $ldap->_sendmesg($mesg); } sub abandon { my $ldap = shift; unshift @_, 'id' if @_ & 1; my $arg = &_options; my $id = $arg->{id}; my $mesg = $ldap->message('Net::LDAP::Abandon' => $arg); my $control = $arg->{control} and $ldap->{net_ldap_version} < 3 and return _error($ldap, $mesg, LDAP_PARAM_ERROR, 'Controls require LDAPv3'); $mesg->encode( abandonRequest => ref($id) ? $id->mesg_id : $id, controls => $control ) or return _error($ldap, $mesg, LDAP_ENCODING_ERROR, "$@"); $ldap->_sendmesg($mesg); } sub extension { my $ldap = shift; my $arg = &_options; require Net::LDAP::Extension; my $mesg = $ldap->message('Net::LDAP::Extension' => $arg); return _error($ldap, $mesg, LDAP_LOCAL_ERROR, 'ExtendedRequest requires LDAPv3') if $ldap->{net_ldap_version} < 3; $mesg->encode( extendedReq => { requestName => $arg->{name}, requestValue => $arg->{value} }, controls => $arg->{control} ) or return _error($ldap, $mesg, LDAP_ENCODING_ERROR, "$@"); $ldap->_sendmesg($mesg); } sub sync { my $ldap = shift; my $mid = shift; my $table = $ldap->{net_ldap_mesg}; my $err = LDAP_SUCCESS; return $err unless defined $table; $mid = $mid->mesg_id if ref($mid); while (defined($mid) ? exists $table->{$mid} : %$table) { last if $err = $ldap->process($mid); } $err; } sub disconnect { my $self = shift; _drop_conn($self, LDAP_USER_CANCELED, 'Explicit disconnect'); } sub _sendmesg { my $ldap = shift; my $mesg = shift; my $debug; if ($debug = $ldap->debug) { require Convert::ASN1::Debug; print STDERR "$ldap sending:\n"; Convert::ASN1::asn_hexdump(*STDERR, $mesg->pdu) if $debug & 1; Convert::ASN1::asn_dump(*STDERR, $mesg->pdu) if $debug & 4; } my $socket = $ldap->socket or return _error($ldap, $mesg, LDAP_SERVER_DOWN, "$!"); # send packets in sizes that IO::Socket::SSL can chew # originally it was: #syswrite($socket, $mesg->pdu, length($mesg->pdu)) # or return _error($ldap, $mesg, LDAP_LOCAL_ERROR, "$!") my $to_send = \( $mesg->pdu ); my $offset = 0; while ($offset < length($$to_send)) { my $s = substr($$to_send, $offset, 15000); my $n = syswrite($socket, $s, length($s)) or return _error($ldap, $mesg, LDAP_LOCAL_ERROR, "$!"); $offset += $n; } # for CLDAP, here we need to recode when we were sent # so that we can perform timeouts and resends my $mid = $mesg->mesg_id; my $sync = not $ldap->async; unless ($mesg->done) { # may not have a response $ldap->{net_ldap_mesg}->{$mid} = $mesg; if ($sync) { my $err = $ldap->sync($mid); return _error($ldap, $mesg, $err, $@) if $err; } } $sync && $ldap->{net_ldap_onerror} && $mesg->is_error ? scalar &{$ldap->{net_ldap_onerror}}($mesg) : $mesg; } sub data_ready { my $ldap = shift; my $sock = $ldap->socket or return; my $sel = IO::Select->new($sock); return defined $sel->can_read(0) || (ref($sock) eq 'IO::Socket::SSL' && $sock->pending()); } sub process { my $ldap = shift; my $what = shift; my $sock = $ldap->socket or return LDAP_SERVER_DOWN; for (my $ready = 1; $ready; $ready = $ldap->data_ready) { my $pdu; asn_read($sock, $pdu) or return _drop_conn($ldap, LDAP_OPERATIONS_ERROR, 'Communications Error'); my $debug; if ($debug = $ldap->debug) { require Convert::ASN1::Debug; print STDERR "$ldap received:\n"; Convert::ASN1::asn_hexdump(\*STDERR, $pdu) if $debug & 2; Convert::ASN1::asn_dump(\*STDERR, $pdu) if $debug & 8; } my $result = $LDAPResponse->decode($pdu) or return LDAP_DECODING_ERROR; my $mid = $result->{messageID}; my $mesg = $ldap->{net_ldap_mesg}->{$mid}; unless ($mesg) { if (my $ext = $result->{protocolOp}{extendedResp}) { if (($ext->{responseName} || '') eq '1.3.6.1.4.1.1466.20036') { # notice of disconnection return _drop_conn($ldap, LDAP_SERVER_DOWN, 'Notice of Disconnection'); } } print STDERR "Unexpected PDU, ignored\n" if $debug & 10; next; } $mesg->decode($result) or return $mesg->code; last if defined $what && $what == $mid; } # FIXME: in CLDAP here we need to check if any message has timed out # and if so do we resend it or what return LDAP_SUCCESS; } *_recvresp = \&process; # compat sub _drop_conn { my ($self, $err, $etxt) = @_; delete $self->{net_ldap_rawsocket}; my $sock = delete $self->{net_ldap_socket}; close($sock) if $sock; if (my $msgs = delete $self->{net_ldap_mesg}) { foreach my $mesg (values %$msgs) { next unless (defined $mesg); $mesg->set_error($err, $etxt); } } $err; } sub _forgetmesg { my $ldap = shift; my $mesg = shift; my $mid = $mesg->mesg_id; delete $ldap->{net_ldap_mesg}->{$mid}; } #Mark Wilcox 3-20-2000 #now accepts named parameters #dn => "dn of subschema entry" # # # Clif Harden 2-4-2001. # corrected filter for subschema search. # added attributes to retrieve on subschema search. # added attributes to retrieve on rootDSE search. # changed several double quote character to single quote # character, just to be consistent throughout the schema # and root_dse functions. # sub schema { require Net::LDAP::Schema; my $self = shift; my %arg = @_; my $base; my $mesg; if (exists $arg{dn}) { $base = $arg{dn}; } else { my $root = $self->root_dse( attrs => ['subschemaSubentry'] ) or return undef; $base = $root->get_value('subschemaSubentry') || 'cn=schema'; } $mesg = $self->search( base => $base, scope => 'base', filter => '(objectClass=subschema)', attrs => [qw( objectClasses attributeTypes matchingRules matchingRuleUse dITStructureRules dITContentRules nameForms ldapSyntaxes extendedAttributeInfo )], ); $mesg->code ? undef : Net::LDAP::Schema->new($mesg->entry); } sub root_dse { my $ldap = shift; my %arg = @_; my $attrs = $arg{attrs} || [qw( subschemaSubentry namingContexts altServer supportedExtension supportedControl supportedFeatures supportedSASLMechanisms supportedLDAPVersion vendorName vendorVersion )]; my $root = $arg{attrs} && $ldap->{net_ldap_root_dse}; return $root if $root; my $mesg = $ldap->search( base => '', scope => 'base', filter => '(objectClass=*)', attrs => $attrs, ); require Net::LDAP::RootDSE; $root = $mesg->entry; bless $root, 'Net::LDAP::RootDSE' if $root; # Naughty, but there you go :-) $ldap->{net_ldap_root_dse} = $root unless $arg{attrs}; return $root; } sub start_tls { my $ldap = shift; my $arg = &_options; my $sock = $ldap->socket; require IO::Socket::SSL; require Net::LDAP::Extension; my $mesg = $ldap->message('Net::LDAP::Extension' => $arg); return _error($ldap, $mesg, LDAP_OPERATIONS_ERROR, 'TLS already started') if $sock->isa('IO::Socket::SSL'); return _error($ldap, $mesg, LDAP_PARAM_ERROR, 'StartTLS requires LDAPv3') if $ldap->version < 3; $mesg->encode( extendedReq => { requestName => LDAP_EXTENSION_START_TLS, } ); $ldap->_sendmesg($mesg); $mesg->sync(); return $mesg if $mesg->code; delete $ldap->{net_ldap_root_dse}; $arg->{sslserver} = $ldap->{net_ldap_host} unless defined $arg->{sslserver}; my $sock_class = ref($sock); return $mesg if IO::Socket::SSL->start_SSL($sock, {_SSL_context_init_args($arg)}); my $err = $@ || $IO::Socket::SSL::SSL_ERROR || $IO::Socket::SSL::SSL_ERROR || ''; # avoid use on once warning if ($sock_class ne ref($sock)) { $err = $sock->errstr; bless $sock, $sock_class; } _error($ldap, $mesg, LDAP_OPERATIONS_ERROR, $err); } sub cipher { my $ldap = shift; $ldap->socket->isa('IO::Socket::SSL') ? $ldap->socket->get_cipher : undef; } sub certificate { my $ldap = shift; $ldap->socket->isa('IO::Socket::SSL') ? $ldap->socket->get_peer_certificate : undef; } # what version are we talking? sub version { my $ldap = shift; @_ ? ($ldap->{net_ldap_version}, $ldap->{net_ldap_version} = shift)[0] : $ldap->{net_ldap_version}; } sub outer { my $self = shift; return $self if tied(%$self); my %outer; tie %outer, ref($self), $self; ++$self->{net_ldap_refcnt}; bless \%outer, ref($self); } sub inner { tied(%{$_[0]}) || $_[0]; } sub TIEHASH { $_[1]; } sub DESTROY { my $ldap = shift; my $inner = tied(%$ldap) or return; _drop_conn($inner, LDAP_UNAVAILABLE, 'Implicit disconnect') unless --$inner->{net_ldap_refcnt}; } 1; libnet-ldap-perl-0.6500+dfsg.orig/lib/Net/LDAP/0000755000175000017500000000000012510544053020122 5ustar gregoagregoalibnet-ldap-perl-0.6500+dfsg.orig/lib/Net/LDAP/Reference.pod0000644000175000017500000000212012350606574022530 0ustar gregoagregoa=head1 NAME Net::LDAP::Reference - search reference =head1 SYNOPSIS use Net::LDAP; $ldap->search( @search_args, callback => \&process); sub process { my $mesg = shift; my $obj = shift; if (!$obj) { # Search complete } elsif ($obj->isa('Net::LDAP::Reference')) { my $ref; foreach $ref ($obj->references) { # process ref } } else { # Process Net::LDAP::Entry } } =head1 DESCRIPTION The B object represents a reference (sometimes called a "referral") returned by the directory from a search. =head1 METHODS =over 4 =item references Returns a list of references from the server. =back =head1 SEE ALSO L, L =head1 AUTHOR Graham Barr Egbarr@pobox.comE. Please report any bugs, or post any suggestions, to the perl-ldap mailing list Eperl-ldap@perl.orgE. =head1 COPYRIGHT Copyright (c) 1997-2004 Graham Barr. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut libnet-ldap-perl-0.6500+dfsg.orig/lib/Net/LDAP/RootDSE.pm0000644000175000017500000000440312507234571021747 0ustar gregoagregoa# Copyright (c) 2003-2004 Chris Ridd and # Graham Barr . All rights reserved. This program is # free software; you can redistribute it and/or modify it under the # same terms as Perl itself. package Net::LDAP::RootDSE; use Net::LDAP::Entry; our @ISA = qw(Net::LDAP::Entry); our $VERSION = '0.02'; use strict; sub supported_feature { _supported_feature( @_, 'supportedFeatures' ) } sub supported_extension { _supported_feature( @_, 'supportedExtension' ) } sub supported_version { _supported_feature( @_, 'supportedLDAPVersion' ) } sub supported_control { _supported_feature( @_, 'supportedControl' ) } sub supported_sasl_mechanism { _supported_feature( @_, 'supportedSASLMechanisms' ) } sub _supported_feature { my $root = shift; my $attr = pop; my %ext; @ext{ $root->get_value( $attr ) } = (); @_ == grep exists $ext{$_}, @_; } 1; __END__ =head1 NAME Net::LDAP::RootDSE - An LDAP RootDSE object =head1 SYNOPSIS my $dse = $ldap->root_dse(); # get naming Contexts my @contexts = $dse->get_value('namingContexts'); # get supported LDAP versions as an array reference my $versions = $dse->get_value('supportedLDAPVersion', asref => 1); =head1 DESCRIPTION =head2 Methods =over 4 =item get_value C is identical to L =item supported_extension ( OID_LIST ) Returns true if the server supports all of the specified extension OIDs =item supported_feature ( OID_LIST ) Returns true if the server supports all of the specified feature OIDs =item supported_version ( VERSION_LIST ) Returns true if the server supports all of the specified versions =item supported_control ( OID_LIST ) Returns true if the server supports all of the specified control OIDs =item supported_sasl_mechanism ( SASL_MECH_LIST ) Returns true if the server supports all of the specified SASL mechanism names =back =head1 SEE ALSO L, L =head1 AUTHOR Chris Ridd Echris.ridd@isode.comE, Graham Barr Egbarr@pobox.comE. =head1 COPYRIGHT Copyright (c) 2003-2004, Chris Ridd and Graham Barr. All rights reserved. This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut libnet-ldap-perl-0.6500+dfsg.orig/lib/Net/LDAP/Util.pm0000644000175000017500000006234712507234571021420 0ustar gregoagregoa# Copyright (c) 1999-2004 Graham Barr and # Norbert Klasen All Rights Reserved. # This program is free software; you can redistribute it and/or modify # it under the same terms as Perl itself. package Net::LDAP::Util; =head1 NAME Net::LDAP::Util - Utility functions =head1 SYNOPSIS use Net::LDAP::Util qw(ldap_error_text ldap_error_name ldap_error_desc ); $mesg = $ldap->search( .... ); die "Error ",ldap_error_name($mesg) if $mesg->code; =head1 DESCRIPTION B is a collection of utility functions for use with the L modules. =head1 FUNCTIONS =over 4 =cut require Exporter; require Net::LDAP::Constant; our @ISA = qw(Exporter); our @EXPORT_OK = qw( ldap_error_name ldap_error_text ldap_error_desc canonical_dn ldap_explode_dn escape_filter_value unescape_filter_value escape_dn_value unescape_dn_value ldap_url_parse generalizedTime_to_time time_to_generalizedTime ); our %EXPORT_TAGS = ( error => [ qw(ldap_error_name ldap_error_text ldap_error_desc) ], filter => [ qw(escape_filter_value unescape_filter_value) ], dn => [ qw(canonical_dn ldap_explode_dn escape_dn_value unescape_dn_value) ], escape => [ qw(escape_filter_value unescape_filter_value escape_dn_value unescape_dn_value) ], url => [ qw(ldap_url_parse) ], time => [ qw(generalizedTime_to_time time_to_generalizedTime) ], ); our $VERSION = '0.19'; =item ldap_error_name ( ERR ) Returns the name corresponding with ERR. ERR can either be an LDAP error number, or a C object containing an error code. If the error is not known the a string in the form C<"LDAP error code %d(0x%02X)"> is returned. =cut # Defined in Constant.pm =item ldap_error_text ( ERR ) Returns the text from the POD description for the given error. ERR can either be an LDAP error code, or a C object containing an LDAP error code. If the error code given is unknown then C is returned. =cut # Defined in Constant.pm =item ldap_error_desc ( ERR ) Returns a short text description of the error. ERR can either be an LDAP error code or a C object containing an LDAP error code. =cut my @err2desc = ( 'Success', # 0x00 LDAP_SUCCESS 'Operations error', # 0x01 LDAP_OPERATIONS_ERROR 'Protocol error', # 0x02 LDAP_PROTOCOL_ERROR 'Timelimit exceeded', # 0x03 LDAP_TIMELIMIT_EXCEEDED 'Sizelimit exceeded', # 0x04 LDAP_SIZELIMIT_EXCEEDED 'Compare false', # 0x05 LDAP_COMPARE_FALSE 'Compare true', # 0x06 LDAP_COMPARE_TRUE 'Strong authentication not supported', # 0x07 LDAP_STRONG_AUTH_NOT_SUPPORTED 'Strong authentication required', # 0x08 LDAP_STRONG_AUTH_REQUIRED 'Partial results and referral received', # 0x09 LDAP_PARTIAL_RESULTS 'Referral received', # 0x0a LDAP_REFERRAL 'Admin limit exceeded', # 0x0b LDAP_ADMIN_LIMIT_EXCEEDED 'Critical extension not available', # 0x0c LDAP_UNAVAILABLE_CRITICAL_EXT 'Confidentiality required', # 0x0d LDAP_CONFIDENTIALITY_REQUIRED 'SASL bind in progress', # 0x0e LDAP_SASL_BIND_IN_PROGRESS undef, 'No such attribute', # 0x10 LDAP_NO_SUCH_ATTRIBUTE 'Undefined attribute type', # 0x11 LDAP_UNDEFINED_TYPE 'Inappropriate matching', # 0x12 LDAP_INAPPROPRIATE_MATCHING 'Constraint violation', # 0x13 LDAP_CONSTRAINT_VIOLATION 'Type or value exists', # 0x14 LDAP_TYPE_OR_VALUE_EXISTS 'Invalid syntax', # 0x15 LDAP_INVALID_SYNTAX undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, 'No such object', # 0x20 LDAP_NO_SUCH_OBJECT 'Alias problem', # 0x21 LDAP_ALIAS_PROBLEM 'Invalid DN syntax', # 0x22 LDAP_INVALID_DN_SYNTAX 'Object is a leaf', # 0x23 LDAP_IS_LEAF 'Alias dereferencing problem', # 0x24 LDAP_ALIAS_DEREF_PROBLEM undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, 'Proxy authorization failure', # 0x2F LDAP_PROXY_AUTHZ_FAILURE 'Inappropriate authentication', # 0x30 LDAP_INAPPROPRIATE_AUTH 'Invalid credentials', # 0x31 LDAP_INVALID_CREDENTIALS 'Insufficient access', # 0x32 LDAP_INSUFFICIENT_ACCESS 'DSA is busy', # 0x33 LDAP_BUSY 'DSA is unavailable', # 0x34 LDAP_UNAVAILABLE 'DSA is unwilling to perform', # 0x35 LDAP_UNWILLING_TO_PERFORM 'Loop detected', # 0x36 LDAP_LOOP_DETECT undef, undef, undef, undef, undef, 'Sort control missing', # 0x3C LDAP_SORT_CONTROL_MISSING 'Index range error', # 0x3D LDAP_INDEX_RANGE_ERROR undef, undef, 'Naming violation', # 0x40 LDAP_NAMING_VIOLATION 'Object class violation', # 0x41 LDAP_OBJECT_CLASS_VIOLATION 'Operation not allowed on nonleaf', # 0x42 LDAP_NOT_ALLOWED_ON_NONLEAF 'Operation not allowed on RDN', # 0x43 LDAP_NOT_ALLOWED_ON_RDN 'Already exists', # 0x44 LDAP_ALREADY_EXISTS 'Cannot modify object class', # 0x45 LDAP_NO_OBJECT_CLASS_MODS 'Results too large', # 0x46 LDAP_RESULTS_TOO_LARGE 'Affects multiple servers', # 0x47 LDAP_AFFECTS_MULTIPLE_DSAS undef, undef, undef, undef, 'VLV error', # 0x4C LDAP_VLV_ERROR undef, undef, undef, 'Unknown error', # 0x50 LDAP_OTHER 'Can\'t contact LDAP server', # 0x51 LDAP_SERVER_DOWN 'Local error', # 0x52 LDAP_LOCAL_ERROR 'Encoding error', # 0x53 LDAP_ENCODING_ERROR 'Decoding error', # 0x54 LDAP_DECODING_ERROR 'Timed out', # 0x55 LDAP_TIMEOUT 'Unknown authentication method', # 0x56 LDAP_AUTH_UNKNOWN 'Bad search filter', # 0x57 LDAP_FILTER_ERROR 'Canceled', # 0x58 LDAP_USER_CANCELED 'Bad parameter to an ldap routine', # 0x59 LDAP_PARAM_ERROR 'Out of memory', # 0x5a LDAP_NO_MEMORY 'Can\'t connect to the LDAP server', # 0x5b LDAP_CONNECT_ERROR 'Not supported by this version of the LDAP protocol', # 0x5c LDAP_NOT_SUPPORTED 'Requested LDAP control not found', # 0x5d LDAP_CONTROL_NOT_FOUND 'No results returned', # 0x5e LDAP_NO_RESULTS_RETURNED 'More results to return', # 0x5f LDAP_MORE_RESULTS_TO_RETURN 'Client detected loop', # 0x60 LDAP_CLIENT_LOOP 'Referral hop limit exceeded', # 0x61 LDAP_REFERRAL_LIMIT_EXCEEDED ); sub ldap_error_desc { my $code = (ref($_[0]) ? $_[0]->code : $_[0]); $err2desc[$code] || sprintf('LDAP error code %d(0x%02X)', $code, $code); } =item canonical_dn ( DN [ , OPTIONS ] ) Returns the given B in a canonical form. Returns undef if B is not a valid Distinguished Name. (Note: The empty string "" is a valid DN.) B can either be a string or reference to an array of hashes as returned by ldap_explode_dn, which is useful when constructing a DN. It performs the following operations on the given B: =over 4 =item * Removes the leading 'OID.' characters if the type is an OID instead of a name. =item * Escapes all RFC 4514 special characters (",", "+", """, "\", "E", "E", ";", "#", "=", " "), slashes ("/"), and any other character where the ASCII code is E 32 as \hexpair. =item * Converts all leading and trailing spaces in values to be \20. =item * If an RDN contains multiple parts, the parts are re-ordered so that the attribute type names are in alphabetical order. =back B is a list of name/value pairs, valid options are: =over 4 =item casefold Controls case folding of attribute type names. Attribute values are not affected by this option. The default is to uppercase. Valid values are: =over 4 =item lower Lowercase attribute type names. =item upper Uppercase attribute type names. This is the default. =item none Do not change attribute type names. =back =item mbcescape If TRUE, characters that are encoded as a multi-octet UTF-8 sequence will be escaped as \(hexpair){2,*}. =item reverse If TRUE, the RDN sequence is reversed. =item separator Separator to use between RDNs. Defaults to comma (','). =back =cut sub canonical_dn($%) { my ($dn, %opt) = @_; return $dn unless defined $dn and $dn ne ''; # create array of hash representation my $rdns = ref($dn) eq 'ARRAY' ? $dn : ldap_explode_dn( $dn, casefold => $opt{casefold} || 'upper') or return undef; #error condition # assign specified or default separator value my $separator = $opt{separator} || ','; # flatten all RDNs into strings my @flatrdns = map { my $rdn = $_; my @types = sort keys %$rdn; join('+', map { my $val = $rdn->{$_}; if ( ref($val) ) { $val = '#' . unpack('H*', $$val); } else { #escape insecure characters and optionally MBCs if ( $opt{mbcescape} ) { $val =~ s/([\x00-\x1f\/\\",=+<>#;\x7f-\xff])/ sprintf('\\%02x', ord($1))/xeg; } else { $val =~ s/([\x00-\x1f\/\\",=+<>#;])/ sprintf('\\%02x', ord($1))/xeg; } #escape leading and trailing whitespace $val =~ s/(^\s+|\s+$)/ '\\20' x length $1/xeg; #compact multiple spaces $val =~ s/\s+/ /g; } # case fold attribute type and create return value if ( !$opt{casefold} || $opt{casefold} eq 'upper' ) { (uc $_)."=$val"; } elsif ( $opt{casefold} eq 'lower' ) { (lc $_)."=$val"; } else { "$_=$val"; } } @types); } @$rdns; # join RDNs into string, optionally reversing order $opt{reverse} ? join($separator, reverse @flatrdns) : join($separator, @flatrdns); } =item ldap_explode_dn ( DN [ , OPTIONS ] ) Explodes the given B into an array of hashes and returns a reference to this array. Returns undef if B is not a valid Distinguished Name. A Distinguished Name is a sequence of Relative Distinguished Names (RDNs), which themselves are sets of Attributes. For each RDN a hash is constructed with the attribute type names as keys and the attribute values as corresponding values. These hashes are then stored in an array in the order in which they appear in the DN. For example, the DN 'OU=Sales+CN=J. Smith,DC=example,DC=net' is exploded to: [ { 'OU' =E 'Sales', 'CN' =E 'J. Smith' }, { 'DC' =E 'example' }, { 'DC' =E 'net' } ] (RFC4514 string) DNs might also contain values, which are the bytes of the BER encoding of the X.500 AttributeValue rather than some LDAP string syntax. These values are hex-encoded and prefixed with a #. To distinguish such BER values, ldap_explode_dn uses references to the actual values, e.g. '1.3.6.1.4.1.1466.0=#04024869,DC=example,DC=com' is exploded to: [ { '1.3.6.1.4.1.1466.0' =E "\004\002Hi" }, { 'DC' =E 'example' }, { 'DC' =E 'com' } ]; It also performs the following operations on the given DN: =over 4 =item * Unescape "\" followed by ",", "+", """, "\", "E", "E", ";", "#", "=", " ", or a hexpair and strings beginning with "#". =item * Removes the leading 'OID.' characters if the type is an OID instead of a name. =back B is a list of name/value pairs, valid options are: =over 4 =item casefold Controls case folding of attribute types names. Attribute values are not affected by this option. The default is to uppercase. Valid values are: =over 4 =item lower Lowercase attribute types names. =item upper Uppercase attribute type names. This is the default. =item none Do not change attribute type names. =back =item reverse If TRUE, the RDN sequence is reversed. =back =cut sub ldap_explode_dn($%) { my ($dn, %opt) = @_; return undef unless defined $dn; return [] if $dn eq ''; my $pair = qr/\\(?:[\\"+,;<> #=]|[0-9A-F]{2})/i; my (@dn, %rdn); while ( $dn =~ /\G(?: \s* ((?i)[A-Z][-A-Z0-9]*|(?:oid\.)?\d+(?:\.\d+)*) # attribute type \s* = [ ]* ( # attribute value (?:(?:[^\x00 "\#+,;<>\\\x80-\xBF]|$pair) # string (?:(?:[^\x00"+,;<>\\]|$pair)* (?:[^\x00 "+,;<>\\]|$pair))?)? | \#(?:[0-9a-fA-F]{2})+ # hex string | "(?:[^\\"]+|$pair)*" # "-quoted string, only for v2 ) [ ]* (?:([;,+])\s*(?=\S)|$) # separator )\s*/gcx) { my($type, $val, $sep) = ($1, $2, $3); $type =~ s/^oid\.//i; #remove leading "oid." if ( !$opt{casefold} || $opt{casefold} eq 'upper' ) { $type = uc $type; } elsif ( $opt{casefold} eq 'lower' ) { $type = lc($type); } if ( $val =~ s/^#// ) { # decode hex-encoded BER value my $tmp = pack('H*', $val); $val = \$tmp; } else { # remove quotes $val =~ s/^"(.*)"$/$1/; # unescape characters $val =~ s/\\([\\ ",=+<>#;]|[0-9a-fA-F]{2}) /length($1)==1 ? $1 : chr(hex($1)) /xeg; } $rdn{$type} = $val; unless (defined $sep and $sep eq '+') { if ( $opt{reverse} ) { unshift @dn, { %rdn }; } else { push @dn, { %rdn }; } %rdn = (); } } length($dn) == (pos($dn)||0) ? \@dn : undef; } =item escape_filter_value ( VALUES ) Escapes the given B according to RFC 4515 so that they can be safely used in LDAP filters. Any control characters with an ASCII code E 32 as well as the characters with special meaning in LDAP filters "*", "(", ")", and "\" the backslash are converted into the representation of a backslash followed by two hex digits representing the hexadecimal value of the character. Returns the converted list in list mode and the first element in scalar mode. =cut ## convert a list of values into its LDAP filter encoding ## # Synopsis: @escaped = escape_filter_value(@values) sub escape_filter_value(@) { my @values = @_; map { $_ =~ s/([\x00-\x1F\*\(\)\\])/'\\'.unpack('H2', $1)/oge; } @values; return(wantarray ? @values : $values[0]); } =item unescape_filter_value ( VALUES ) Undoes the conversion done by B. Converts any sequences of a backslash followed by two hex digits into the corresponding character. Returns the converted list in list mode and the first element in scalar mode. =cut ## convert a list of values from its LDAP filter encoding ## # Synopsis: @values = unescape_filter_value(@escaped) sub unescape_filter_value(@) { my @values = @_; map { $_ =~ s/\\([0-9a-fA-F]{2})/pack('H2', $1)/oge; } @values; return(wantarray ? @values : $values[0]); } =item escape_dn_value ( VALUES ) Escapes the given B according to RFC 4514 so that they can be safely used in LDAP DNs. The characters ",", "+", """, "\", "E", "E", ";", "#", "=" with a special meaning in section 2.4 of RFC 4514 are preceded by a backslash. Control characters with an ASCII code E 32 are represented as \hexpair. Finally all leading and trailing spaces are converted to sequences of \20. Returns the converted list in list mode and the first element in scalar mode. =cut ## convert a list of values into its DN encoding ## # Synopsis: @escaped = escape_dn_value(@values) sub escape_dn_value(@) { my @values = @_; map { $_ =~ s/([\\",=+<>#;])/\\$1/og; $_ =~ s/([\x00-\x1F])/'\\'.unpack('H2', $1)/oge; $_ =~ s/(^ +| +$)/'\\20' x length($1)/oge; } @values; return(wantarray ? @values : $values[0]); } =item unescape_dn_value ( VALUES ) Undoes the conversion done by B. Any escape sequence starting with a backslash - hexpair or special character - will be transformed back to the corresponding character. Returns the converted list in list mode and the first element in scalar mode. =cut ## convert a list of values from its LDAP filter encoding ## # Synopsis: @values = unescape_dn_value(@escaped) sub unescape_dn_value(@) { my @values = @_; map { $_ =~ s/\\([\\",=+<>#;]|[0-9a-fA-F]{2}) /(length($1)==1) ? $1 : pack('H2', $1) /ogex; } @values; return(wantarray ? @values : $values[0]); } =item ldap_url_parse ( LDAP-URL [, OPTIONS ] ) Parse an B conforming to RFC 4516 into a hash containing its elements. For easy cooperation with LDAP queries, the hash keys for the elements used in LDAP search operations are named after the parameters to L. In extension to RFC 4516, the socket path for URLs with the scheme C will be stored in the hash key named C. If any element is omitted, the result depends on the setting of the option C. B is a list of key/value pairs with the following keys recognized: =over 4 =item defaults A Boolean option that determines whether default values according to RFC 4516 shall be returned for missing URL elements. If set to TRUE, default values are returned, with C using the following defaults in extension to RFC 4516. =over 4 =item * The default port for C URLs is C<636>. =item * The default path for C URLs is the contents of the environment variable C. If that is not defined or empty, then C is used. This is consistent with the behaviour of L. =item * The default C name for C and C URLs is C. =back When set to FALSE, no default values are used. This leaves all keys in the resulting hash undefined where the corresponding URL element is empty. To distinguish between an empty base DN and an undefined base DN, C uses the slash between the host:port resp. path part of the URL and the base DN part of the URL. With the slash present, the hash key C is set to the empty string, without it, it is left undefined. Leaving away the C option entirely is equivalent to setting it to TRUE. =back Returns the hash in list mode, or the reference to the hash in scalar mode. =cut ## parse an LDAP URL into its various elements # Synopsis: {$elementref,%elements} = ldap_url_parse($url) sub ldap_url_parse($@) { my $url = shift; my %opt = @_; eval { require URI }; return if ($@); my $uri = URI->new($url); return unless ($uri && ref($uri) =~ /^URI::ldap[is]?$/); $opt{defaults} = 1 unless (exists($opt{defaults})); my %elements = ( scheme => $uri->scheme ); $uri = $uri->canonical; # canonical form $url = $uri->as_string; # normalize if ($elements{scheme} eq 'ldapi') { $elements{path} = $uri->un_path || $ENV{LDAPI_SOCK} || '/var/run/ldapi' if ($opt{defaults} || $uri->un_path); } else { $elements{host} = $uri->host || 'localhost' if ($opt{defaults} || $uri->host); $elements{port} = $uri->port || ($elements{scheme} eq 'ldaps' ? 636 : 389) if ($opt{defaults} || $uri->port); } $elements{base} = $uri->dn if ($opt{defaults} || $uri->dn || $url =~ m{^ldap[is]?://[^/]*/}); $elements{attrs} = [ $uri->attributes ] if ($opt{defaults} || $uri->attributes); $elements{scope} = $uri->scope if ($opt{defaults} || $uri->_scope); $elements{filter} = $uri->filter if ($opt{defaults} || $uri->_filter); $elements{extensions} = [ $uri->extensions ] if ($opt{defaults} || $uri->extensions); #return _error($ldap, $mesg, LDAP_LOCAL_ERROR, "unhandled critical URL extension") # if (grep(/^!/, keys(%extns))); return wantarray ? %elements : \%elements; } =item generalizedTime_to_time ( GENERALIZEDTIME ) Convert the generalizedTime string B, which is expected to match the template C to a floating point number compatible with UNIX time (i.e. the integral part of the number is a UNIX time). Returns an extended UNIX time or C on error. Times in years smaller than 1000 will lead to C being returned. This restriction is a direct effect of the year value interpretation rules in Time::Local. B this function depends on Perl's implementation of time and Time::Local. See L, L, and L for restrictions in older versions of Perl. =cut sub generalizedTime_to_time($) { my $generalizedTime = shift; if ($generalizedTime =~ /^\s*(\d{4})(\d{2})(\d{2}) (\d{2})(?:(\d{2})(\d{2})?)? (?:[.,](\d+))?\s*(Z|[+-]\d{2}(?:\d{2})?)\s*$/x) { my ($year,$month,$day,$hour,$min,$sec,$dec,$offset) = ($1,$2,$3,$4,$5,$6,$7,$8); # Time::Local's timegm() interpret years strangely if ($year >= 1000) { $dec = defined($dec) ? "0.$dec" : 0; # decimals in case of missing minutes / seconds - see RFC 4517 if (!defined($min)) { $min = 0; if ($dec) { $min = int(60 * $dec); $dec = sprintf('%.4f', 60 * $dec - $min); } } if (!defined($sec)) { $sec = 0; if ($dec) { $sec = int(60 * $dec); $dec = sprintf('%.2f', 60 * $dec - $sec); } } eval { require Time::Local; }; unless ($@) { my $time; eval { $time = Time::Local::timegm($sec,$min,$hour,$day,$month-1,$year); }; unless ($@) { if ($offset =~ /^([+-])(\d{2})(\d{2})?$/) { my ($direction,$hourdelta,$mindelta) = ($1,$2,$3); $mindelta = 0 if (!$mindelta); $time += ($direction eq '-') ? 3600 * $hourdelta + 60 * $mindelta : -3600 * $hourdelta - 60 * $mindelta; } # make decimal part directional if ($dec != 0) { my $sign = ''; if ($time < 0) { $dec = 1 - $dec; $time++; $sign = '-' if ($time == 0); } $dec =~ s/^0\.//; $time = "${sign}${time}.${dec}"; } return $time; } } } } return undef; } =item time_to_generalizedTime ( TIME [, OPTIONS ] ) Convert the UNIX time B