pax_global_header00006660000000000000000000000064145214013560014513gustar00rootroot0000000000000052 comment=7a73c883012f9d12a05563afbb3481a57055368c lualdap-1.4.0/000077500000000000000000000000001452140135600131375ustar00rootroot00000000000000lualdap-1.4.0/.circleci/000077500000000000000000000000001452140135600147725ustar00rootroot00000000000000lualdap-1.4.0/.circleci/config.yml000066400000000000000000000102641452140135600167650ustar00rootroot00000000000000version: 2.1 orbs: codecov: codecov/codecov@1.1.3 win: circleci/windows@2.2.0 jobs: build_rock: description: "Build with luarocks for a specific Lua version" parameters: lua: type: string docker: - image: circleci/python steps: - checkout - run: name: Install debian dependencies command: | sudo apt -y update sudo apt -y install libldap2-dev - run: name: Install hererocks command: | pip3 install hererocks hererocks bed --<> --no-readline --luarocks latest --verbose hererocks bed --show - run: name: "Build (with install)" command: | source bed/bin/activate luarocks make rockspec/lualdap-dev-2.rockspec - run: name: "Smoke" command: | source bed/bin/activate lua -v lua tests/smoke.lua test_with_coverage: description: "Test with coverage for a specific Lua version" parameters: lua: type: string docker: - image: circleci/python - image: docker.io/openshift/openldap-2441-centos7@sha256:b5619d4de8efec7973dbd280eb2cc462ebeb8ae6e457acef4b743b7374dd600d steps: - checkout - run: name: Install debian dependencies command: | sudo apt -y update sudo apt -y install libldap2-dev sudo apt -y install ldap-utils netcat - run: name: Install hererocks command: | pip3 install hererocks hererocks bed --<> --no-readline --luarocks latest --verbose hererocks bed --show - run: name: Install rocks dependencies command: | source bed/bin/activate luarocks install busted luarocks install cluacov luarocks install luacheck luarocks list - run: name: "Build (without install)" command: | source bed/bin/activate make LUA_INCDIR=bed/include COVERAGE=1 src/lualdap.so - run: name: "Luacheck" command: | source bed/bin/activate make luacheck - run: name: "Wait for OpenLDAP to spin up" command: while ! nc -z localhost 389 ; do sleep 1 ; done - run: name: Prime and test LDAP DB command: | make setup_slapd - run: name: "Test with coverage" command: | source bed/bin/activate make coverage - codecov/upload: file: "*.gcov" flags: default upload_name: <> - store_test_results: path: test-reports/ build_deb: description: "Build Debian packages" docker: - image: circleci/python steps: - checkout - run: name: Install debian dependencies command: | sudo apt -y update sudo apt -y install libldap2-dev sudo apt -y install fakeroot dh-lua - run: name: "Build" command: | rm debian/lua5.4.dh-lua.conf make deb build_win: description: "Build rock on Windows" executor: win/default steps: - checkout - run: name: Install hererocks command: | pip install hererocks hererocks bed --lua latest --no-readline --luarocks latest --verbose hererocks bed --show - run: name: "Build (with install)" command: | bed/bin/activate.ps1 luarocks make rockspec/lualdap-dev-2.rockspec - run: name: "Smoke" command: | bed/bin/activate.ps1 lua -v lua tests/smoke.lua workflows: version: 2 build_rock: jobs: - build_rock: name: "rock <>" matrix: parameters: lua: ["lua 5.1", "lua 5.2", "lua 5.3", "lua 5.4", "luajit 2.0", "luajit 2.1"] test_with_coverage: jobs: - test_with_coverage: name: "coverage <>" matrix: parameters: lua: ["lua 5.1", "lua 5.2", "lua 5.3", "lua 5.4", "luajit 2.0", "luajit 2.1"] build_deb: jobs: - build_deb: name: "deb" build_win: jobs: - build_win: name: "windows" lualdap-1.4.0/.gitignore000066400000000000000000000005341452140135600151310ustar00rootroot00000000000000*~ *.bak *.gcda *.gcno *.gcov *.json *.o *.out *.so *.so.* *.rock *.xml test-reports/ site 5*/ debian/.debhelper debian/.dh_lua-libtool debian/lua-ldap debian/lua-ldap-dev debian/tmp debian/trash debian/*.install debian/*.substvars debian/debhelper-build-stamp debian/files debian/lua_versions tests/slapd/slapd-config/ tests/slapd/slapd-data/ lualdap-1.4.0/.luacov000066400000000000000000000001641452140135600144320ustar00rootroot00000000000000return { root = ".", include = { -- Prevent coverage reports of the tests or helper utilities "src/.+", }, } lualdap-1.4.0/CONTRIBUTING.md000066400000000000000000000043541452140135600153760ustar00rootroot00000000000000# Releases ## Version numbers In the following `${VERSION}` represents the version to be released. If it is a release candidate, it ends in `-rc1`, `-rc2`, and so on. Example: `VERSION=1.2.4-rc1` Since LuaRocks does not support dashes in the version string, except for the build number, we replace eventual dashes (`-`) in `${VERSION}` with dots (`.`). With LuaRocks, the version number is followed by a dash and the build number, which is usually one (`1`), except for release candidates, where we use zero (`0`). We use `${LUAROCKS_VERSION}` to represent this version string below. Example: `LUAROCKS_VERSION=1.2.4.rc1-0` Since Windows libraries use a four number versioning scheme without the possibility for non-digit characters, we use the fourth and last number to distinguish between releases (`0` in the last position) and release candidates (previous version number in the first three positions, but `99`, `999` and so on in the last position). This number is represented by `${WINDOWS_VERSION}` in the following. Example: `WINDOWS_VERSION=1.2.3.99` Note that for Git tags we prefix `${VERSION}` with `v`. This is explicit in the instructions below. ## Release checklist - [ ] Copy `rockspecs/lualdap-dev-2.rockspec` to `rockspecs/lualdap-${LUAROCKS_VERSION}.rockspec` - [ ] In `Makefile` and `Makefile.win` adjust `V` to `${VERSION}` - [ ] In `src/lualdap.c` adjust `_VERSION` to `LuaLDAP ${VERSION}` - [ ] In `src/lualdap.def` adjust `VERSION` to `${WINDOWS_VERSION}` - [ ] In `README.md` adjust `badge/version-${VERSION}-blue` - [ ] In `docs/news.md`: - [ ] Rename "Unreleased" to `${VERSION}` - [ ] Adjust the link for `Unreleased` to show the changelog (commit log) between the previous version and `v${VERSION}` and rename it to `${VERSION}` - [ ] Add a new, empty "Unreleased" section - [ ] Add a new link for `Unreleased` to show the changelog between `v${VERSION}` and `HEAD` - [ ] Commit these changes with message "Release v${VERSION}" - [ ] Tag this commit with `v${VERSION}` - [ ] Run `make rock` in order to create `lualdap-${LUAROCKS_VERSION}.src.rock` - [ ] Upload on the new `rockspec` and `src.rock` - [ ] Run `make gh-pages` in order to update the site lualdap-1.4.0/Makefile000066400000000000000000000042041452140135600145770ustar00rootroot00000000000000T= lualdap V= 1.4.0 R= 1 CONFIG= ./config include $(CONFIG) SLAPD := openshift CFLAGS_WARN := -pedantic -Wall -W -Waggregate-return -Wcast-align -Wmissing-prototypes -Wnested-externs -Wshadow -Wwrite-strings override CPPFLAGS := $(CPPFLAGS) override CFLAGS := -O2 -fPIC $(CFLAGS_WARN) $(CFLAGS) ifdef BUILD_VARIANT REPORT_DIR := test-reports/$(BUILD_VARIANT) else REPORT_DIR := test-reports endif ifdef COVERAGE override CFLAGS := $(CFLAGS) -O0 -g --coverage endif OBJS= src/lualdap.o INCS := -I$(LUA_INCDIR) -I$(LDAP_INCDIR) -I$(LBER_INCDIR) LIBS := -L$(LUA_LIBDIR) $(LUA_LIB) -L$(LDAP_LIBDIR) $(LDAP_LIB) -L$(LBER_LIBDIR) $(LBER_LIB) override CPPFLAGS := $(INCS) $(CPPFLAGS) override LDFLAGS := $(LIBFLAG) $(LDFLAGS) LIBNAME=$(T).so src/$(LIBNAME): $(OBJS) $(CC) $(CFLAGS) -o src/$(LIBNAME) $(LDFLAGS) $(OBJS) $(LIBS) install: src/$(LIBNAME) $(INSTALL) -d $(DESTDIR)$(INST_LIBDIR) $(INSTALL) src/$(LIBNAME) $(DESTDIR)$(INST_LIBDIR) clean: $(RM) -r $(OBJS) src/$(LIBNAME) src/*.gcda src/*.gcno src/*.gcov luacov.*.out $(REPORT_DIR) luacheck: luacheck --std min tests/smoke.lua luacheck --std max+busted --config tests/.luacheckrc tests/test.lua luacheck --std min --config tests.old/.luacheckrc tests.old/test.lua smoke: @echo SMOKE with $(LUA) @LUA_CPATH="./src/?.so" $(LUA) tests/smoke.lua setup_slapd: ./tests/$(SLAPD)/setup.sh check: . tests/$(SLAPD)/test.env && LUA_CPATH="./src/?.so" busted tests/test.lua coverage: $(REPORT_DIR) . tests/$(SLAPD)/test.env && LUA_CPATH="./src/?.so" busted --coverage --output=junit -Xoutput $(REPORT_DIR)/report.xml tests/test.lua luacov mv luacov.*.out $(REPORT_DIR) $(REPORT_DIR): mkdir -p $@ rock: luarocks pack rockspec/lualdap-$(V)-$(R).rockspec pages: mkdocs build gh-pages: mkdocs gh-deploy --clean deb: echo "lua-ldap ($(V)) unstable; urgency=medium" > debian/changelog echo "" >> debian/changelog echo " * UNRELEASED" >> debian/changelog echo "" >> debian/changelog echo " -- $(shell git config --get user.name) <$(shell git config --get user.email)> $(shell date -R)" >> debian/changelog fakeroot debian/rules clean binary lualdap-1.4.0/Makefile.win000077500000000000000000000006471452140135600154050ustar00rootroot00000000000000T= lualdap V= 1.4.0 include config.win SRCS= src\$T.c OBJS= src\$T.obj lib: src\$(LIBNAME) .c.obj: $(CC) /c /Fo$@ $(CFLAGS) $< src\$(LIBNAME): $(OBJS) link /dll /def:src\$T.def /out:src\$(LIBNAME) $(OBJS) $(LUA_LIB) $(LDAP_LIB) install: src\$(LIBNAME) IF NOT EXIST $(LUA_LIBDIR) mkdir $(LUA_LIBDIR) copy src\$(LIBNAME) $(LUA_LIBDIR) clean: del src\$(LIBNAME) $(OBJS) src\$T.lib src\$T.exp lualdap-1.4.0/README.md000066400000000000000000000017301452140135600144170ustar00rootroot00000000000000 ![logo](docs/logo/lualdap-logo-512x512.png) # LuaLDAP [![CircleCI](https://circleci.com/gh/lualdap/lualdap.svg?style=shield)](https://circleci.com/gh/lualdap/lualdap) [![codecov](https://codecov.io/gh/lualdap/lualdap/branch/master/graph/badge.svg)](https://codecov.io/gh/lualdap/lualdap) [![License](http://img.shields.io/badge/Licence-MIT-brightgreen.svg)](docs/license.md) ![version](https://img.shields.io/badge/version-1.4.0-blue) LuaLDAP is a simple interface from Lua to an LDAP client, in fact it is a bind to [OpenLDAP](https://www.openldap.org) client or [ADSI](https://docs.microsoft.com/en-us/windows/win32/adsi/about-adsi). It enables a Lua program to: * Connect to an LDAP server; * Execute any operation (search, add, compare, delete, modify and rename); * Retrieve entries and references of the search result. # Links The homepage with documentation is at , and the sources are hosted at . lualdap-1.4.0/TESTING.md000066400000000000000000000056571452140135600146130ustar00rootroot00000000000000# TESTING Except the `tests/smoke.lua`, all tests require a LDAP server (by default available on localhost). Except the `tests/smoke.lua`, there is no test running on Windows. With old releases (ie. without `smoke.lua`), the following command could be a minimal smoke test : ``` $ LUA_CPATH="./src/?.so" lua -l lualdap -v ``` ## setup a LDAP server You could install/setup `slapd` (the OpenLDAP server) in your environment, or run a Docker image containing `slapd` [openshift/openldap-2441-centos7](https://hub.docker.com/r/openshift/openldap-2441-centos7) is an image on-the-shelf which was built from source available on . ``` # docker pull openshift/openldap-2441-centos7 # docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE openshift/openldap-2441-centos7 latest 9bae1ab605d5 2 years ago 355MB ``` ``` # docker run -d --rm --name openldap -p 389:389 -p 636:636 openshift/openldap-2441-centos7 3d557fc1136fffe91def479ee5cd445da1b974a4809520795a79e1836e62f23e # docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 3d557fc1136f openshift/openldap-2441-centos7 "/usr/local/bin/run-..." About a minute ago Up 56 seconds 0.0.0.0:389->389/tcp, 0.0.0.0:636->636/tcp openldap # docker kill openldap ``` ## tests.old/test.lua This is the original test suite coming from the Kepler Project. It is a pure lua script without any dependency. The following command: ``` $ LUA_CPATH="./src/?.so" tests.old/test.lua localhost:389 dc=example,dc=com cn=person,dc=example,dc=com cn=Manager,dc=example,dc=com admin ``` gives: ``` basic checking .......................... Warning! Couldn't connect with TLS. Trying again without it.................. OK ! checking compare operation ................. OK ! checking basic search operation ........................................... OK ! checking add operation .............. OK ! checking modify operation ................. OK ! checking advanced search operation .............. OK ! checking rename operation .................. OK ! checking delete operation ............... OK ! closing everything ... OK ! ``` ## tests/test.lua This is a port of the original test suite on the top of the framework [busted](http://olivinelabs.com/busted/). `busted` could generate a JUnit XML output which allows nice integration with CI. Previously, the parameters were passed by argument of the command line, now there are passed with environment variables (see `test.env`) The following command: ``` $ tests/openshift/setup.sh # one time, after starting the docker openshift $ . tests/openshift/test.env && tests/test.lua ``` gives: ``` 154 successes / 0 failures / 0 errors / 0 pending : 0.460882 seconds ``` Or via the `Makefile`, just `make check`. lualdap-1.4.0/config000066400000000000000000000021471452140135600143330ustar00rootroot00000000000000# Lua binary LUA := lua # Lua version number (first and second digits of target version) LUA_VERSION := $(shell $(LUA) -e 'print(_VERSION:match("%S+%s+(%S+)"))') # Lua library (set LUA_LIB explicitly, if required) LUA_LIB = # -llua$(LUA_VERSION) # Lua library directory LUA_LIBDIR = /usr/lib # Lua include directory LUA_INCDIR = /usr/include/lua$(LUA_VERSION) # Installation prefix INST_PREFIX = /usr # Lua binary directory INST_BINDIR = /usr/bin # Lua binary module directory INST_LIBDIR = /usr/lib/lua/$(LUA_VERSION) # Lua source module directory INST_LUADIR = /usr/share/lua/$(LUA_VERSION) # OpenLDAP library (an optional directory can be specified with -L) LDAP_LIB = -lldap # System's libraries directory (where binary libraries are installed) LDAP_LIBDIR = /usr/lib # OpenLDAP includes directory LDAP_INCDIR = /usr/include LBER_LIB = -llber LBER_LIBDIR = /usr/lib LBER_INCDIR = /usr/include # OS dependent LIBFLAG = -shared # for Linux #LIBFLAG = -bundle -undefined dynamic_lookup # for MacOS X # Compilation parameters CC= gcc INSTALL= install MACOSX_DEPLOYMENT_TARGET="10.3" export MACOSX_DEPLOYMENT_TARGET lualdap-1.4.0/config.win000066400000000000000000000012611452140135600151230ustar00rootroot00000000000000# Installation directories # System's libraries directory (where binary libraries are installed) LUA_LIBDIR= c:\lua5.1 # Lua includes directory LUA_INC= c:\lua5.1\include # OpenLDAP requires extra include. Comment this line if using ADSI (WinLDAP) #LDAP_INC=/IC:\openldap-2.1.17_bin\include # Lua library LUA_LIB= c:\lua5.1\lua5.1.lib # LDAP library #LDAP_LIB= C:\openldap-2.1.17_bin\DLLRelease\openldap.lib LDAP_LIB= Wldap32.lib LIBNAME= $T.dll # Compilation directives WARN= /O2 INCS= /I$(LUA_INC) $(LDAP_INC) # CFLAGS should include -DWINLDAP to use native windows library instead of OpenLDAP #CFLAGS= $(WARN) $(INCS) -DWIN32 CFLAGS= $(WARN) $(INCS) -DWIN32 -DWINLDAP CC= cl lualdap-1.4.0/debian/000077500000000000000000000000001452140135600143615ustar00rootroot00000000000000lualdap-1.4.0/debian/control000066400000000000000000000027051452140135600157700ustar00rootroot00000000000000Source: lua-ldap Section: interpreters Priority: optional Maintainer: Debian Lua Team Uploaders: Victor Seva , Build-Depends: debhelper-compat (= 13), dh-lua (>= 12), libldap2-dev, Standards-Version: 4.6.2 Vcs-Git: https://salsa.debian.org/lua-team/lua-ldap.git Vcs-Browser: https://salsa.debian.org/lua-team/lua-ldap Homepage: https://github.com/lualdap/lualdap Package: lua-ldap Architecture: any Multi-Arch: same Pre-Depends: ${misc:Pre-Depends}, Depends: ${misc:Depends}, ${shlibs:Depends}, Provides: ${lua:Provides}, XB-Lua-Versions: ${lua:Versions} Description: LDAP library for the Lua language This package contains the Lua LDAP library to: * Connect to an LDAP server (OpenLDAP or ADSI/WinLDAP); * Execute any operation (search, add, compare, delete, modify and rename); * Retrieve entries and references of the search result. . This package contains the runtime library. Package: lua-ldap-dev Architecture: any Multi-Arch: same Pre-Depends: ${misc:Pre-Depends}, Depends: lua-ldap (= ${binary:Version}), ${misc:Depends}, Provides: ${lua:Provides}, XB-Lua-Versions: ${lua:Versions} Section: libdevel Description: LDAP development files for the Lua language This package contains the development files of the Lua LDAP library, useful to create a statically linked binary (like a C application or a standalone Lua interpreter). . Documentation is also shipped within this package. lualdap-1.4.0/debian/lua5.1.dh-lua.conf000066400000000000000000000007071452140135600174120ustar00rootroot00000000000000PKG_NAME=ldap # pkg-config support is missing from upstream OpenLDAP # CLIB_LDFLAGS=-lldap CLIB_LDFLAGS_STATIC=-lldap -llber CLIB_OBJS=src/lualdap.lo LUA_HEADER= LUA_SOURCES= LUA_MODNAME=lualdap LUA_TEST=@@LUA@@ tests/smoke.lua LUA_MODNAME_CPART= PKG_VERSION=$(shell dpkg-parsechangelog|grep ^Ver|cut -d ' ' -f 2|cut -d '-' -f 1) PKG_LIBS_PRIVATE= PKG_URL=https://github.com/lualdap/lualdap PKG_REQUIRES= PKG_CONFLICTS= lualdap-1.4.0/debian/lua5.2.dh-lua.conf000077700000000000000000000000001452140135600224272lua5.1.dh-lua.confustar00rootroot00000000000000lualdap-1.4.0/debian/lua5.3.dh-lua.conf000077700000000000000000000000001452140135600224302lua5.1.dh-lua.confustar00rootroot00000000000000lualdap-1.4.0/debian/lua5.4.dh-lua.conf000077700000000000000000000000001452140135600224312lua5.1.dh-lua.confustar00rootroot00000000000000lualdap-1.4.0/debian/not-installed000066400000000000000000000000341452140135600170560ustar00rootroot00000000000000usr/lib/*/liblua5.*-ldap.la lualdap-1.4.0/debian/rules000077500000000000000000000000731452140135600154410ustar00rootroot00000000000000#!/usr/bin/make -f %: dh $@ --buildsystem=lua --with lua lualdap-1.4.0/doc.old/000077500000000000000000000000001452140135600144615ustar00rootroot00000000000000lualdap-1.4.0/doc.old/us/000077500000000000000000000000001452140135600151105ustar00rootroot00000000000000lualdap-1.4.0/doc.old/us/index.html000066400000000000000000000125311452140135600171070ustar00rootroot00000000000000 LuaLDAP: A Lua interface to an LDAP library
LuaLDAP
A Lua interface to an LDAP library

Overview

LuaLDAP is a simple interface from Lua to an LDAP client, in fact it is a bind to OpenLDAP or to ADSI. It enables a Lua program to:

  • Connect to an LDAP server;
  • Execute any operation (search, add, compare, delete, modify and rename);
  • Retrieve entries and references of the search result.

LuaLDAP is free software and uses the same license as Lua 5.1.

Status

Current version is 1.1. It was developed for both Lua 5.0 and Lua 5.1, and both OpenLDAP 2.1 or newer and ADSI.

Download

LuaLDAP can be downloaded in source code from the LuaForge page. If you are using LuaBinaries a Windows binary version of LuaLDAP can be found at the same LuaForge page.

History

Version 1.1 [14/Dec/2007]
Adapted to work on both Lua 5.0 and Lua 5.1 and to work with ADSI (WinLDAP). Thanks to Mark Edgar.
Version 1.0.1 [04/Apr/2006]
Compatible with Compat-5.1 R5.
Version 1.0 [10/Jun/2005]
Version 1.0 Alpha [10/Dec/2003]

Credits

LuaLDAP was designed by Roberto Ierusalimschy, André Carregal and Tomás Guisasola as part of the Kepler Project which holds its copyright. It was implemented by Tomás Guisasola and Leonardo Godinho with contributions by Mark Edgar.

LuaLDAP development was sponsored by Fábrica Digital and FINEP.

Contact us

For further information please contact us. Comments are welcome!

You can also reach other Kepler developers and users on the Kepler Project mailing list.

Valid XHTML 1.0!

$Id: index.html,v 1.37 2007-12-14 17:06:57 carregal Exp $

lualdap-1.4.0/doc.old/us/license.html000066400000000000000000000116641452140135600174300ustar00rootroot00000000000000 LuaLDAP: license
LuaLDAP
A Lua interface to the OpenLDAP library

License

LuaLDAP is free software: it can be used for both academic and commercial purposes at absolutely no cost. There are no royalties or GNU-like "copyleft" restrictions. LuaLDAP qualifies as Open Source software. Its licenses are compatible with GPL. LuaLDAP is not in the public domain and the Kepler Project keep its copyright. The legal details are below.

The spirit of the license is that you are free to use LuaLDAP for any purpose at no cost without having to ask us. The only requirement is that if you do use LuaLDAP, then you should give us credit by including the appropriate copyright notice somewhere in your product or its documentation.

The LuaLDAP library is designed and implemented by Roberto Ierusalimschy, André Carregal and Tomás Guisasola. The implementation is not derived from licensed software.


Copyright © 2003-2007 The Kepler Project.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Valid XHTML 1.0!

$Id: license.html,v 1.11 2007-12-14 16:46:15 carregal Exp $

lualdap-1.4.0/doc.old/us/lualdap.png000066400000000000000000000172741452140135600172530ustar00rootroot00000000000000PNG  IHDRL\;IDATxi\SW -}  PZ8u:vt:tZG[[mG,\Q@QDvKd'p;$fLs=<9 Ao#o00 ~ H*d2CGD? TQqss1111ttH$P(&&&}}}EEE7n4ttbv b8;;OvP(̛7vqqq%%%"H$:3Ǐ^~}|||;Db N.D"&)Jsrr&X,Dx.|>/ H"X[[3 d25//HJJbN̨Ri]]]{{;ޓO&IR"r=GGG)By%LP(t:d_O>}ZYYMd2А`xX$33# (\.gX<H$Ϟ=+//߸q#D{"`ddWv d2d͈cccr'))I$/JJ: |"#p8T E-]dbDxss3DˋABd2laa7hCCC Ox< &G&9S'zzxSvw.^xU11 P!] X,6Z[[O8:::&&&^pnaܾ}{hhL&j___2,HB!ʙaΜ9 T*ʕ+X,=::eZMkEȉ26RDDDM?~`$&&t #l[qWVsފܹgܷLMUVZXXMvA0((hll E"666 ,ݻwx61_BBgqO__ qqtEr}krM,[ Ǐ+>MBLvڵa*gaa1}~AŌ{55}px3$ pJ.;A,+ˁ׀#B\N͛7ݺu Ϟ8QKJ-aԨ>>33p@d2.\`0fscT@`GhhG켼`GL_QQa moッ|@*J02--IVV$''*A#.cHX$(=/^466::: s +++KKK?zNk訨UIIӧ]CC/hF!!aaffڴu&&DR2uԌ (??޾3 22u*/E*yE#Xp;hVo]|={{3G]piGGUVpcoo`jkke2D }UiS:B{wWZ)HlmpB?`0T&{孭uuu[liii9}tZZK`` bdgkzkfr/wɓUj1~Ӧn"""|||$INNNdd9s( J]`-CJJ:-:m[N{;WtjJghJU5R'z)`XtӳM x{{044AЛoxݻoS:CI~󩩷FF45fK~;U"FR8--.5x<^, dee"6;ee]Lf:s :y?c?18.S?`w_5 |`0,-- ***Νf+6nbgN+Ԕ4wr`Xޗ/4 0%kըJ4 jooɑJ111nnnrZMev>szFUs~{ɓ1FFŲ?ޱcehj-;xpž}A0<}Ȇ >|ᡲMJYYu}T0U K߻Eǩ*9΍7d2{mũdo_|5GfbcQ "{;ujj><<ٳp46PH$B166^v*>2fؐ:O `cc=XLQQd/rhr@_nkkFFKSTU~[o5Qp2PXaa>JyxyGLj^>Y1122Zt}U9|d|\Iё:A ҃y333SM;M=pJq8SxQϮV Y?ظS="WzUg?^ucc*T*?}N4iϞQ蟧{ccVY"H(Y+*jkk+PU]~HݣS-v&,G*U7WzI_-zY)*jW\kgg~U6-EGK$2$ MM'O:upv@a05;ROiizϋuԺlh`gg׫3:*z]xAX,G#w[tkqC)C{1hFKPؑڪ>$!'f#0033ۼy3P(5zT8ڵ4Btd_J??6&F4]?&oT,9TP)/)HM~% heeU@?gX~4̈[++{JJ0PAk4<]8fmAEE|pW ,VEvOu׏Q5&GF¿z<3@*M ^^ B$ Z/]bUVh~K rMMMaG@qq-n{00%.^P B45%$]B(ݾU'JJJT* QBE}rpppppꮮd2 v pO:rLư:KeR'DAD!̵C@HLLD_7Kid2F3" Z5@|.` P cgȏ >1K*oxOl7H~QQ d"ؘ}jOI@ hhhTp<@ 닮|=F aolHM <|x+{ H::~;r_|Ɖ)u~A5r9{{y|dbF3t)1(y  X (.ؘ<V{NS|}NtP'Ν@ pSG4ȨBgwp0C3>P||ߖO` c曟ʖ.u@iMasSOq!oL59'' y~Vs+-T81AFF-Ԕ`loc0~D`h4 xy![ <|PQĤ-4QU *tAMO,m^h :)sRllLLKM :q Inntnn TJGG&$ImmԃSIJgFj˜9ۖ@ۈ* 9{y>&AD\]Wd\4'.7m%Ni=4./)P> lsD{{d<ZD^2Q=xU팙qjeNY'a5z4Kأiԃj(";AXc kI1~P36w.EU169xp%ݻnU'uVUh77fd۟L͞=u^+|{NKAp]|y!z[[銋 ^xJ|GG7:'@kQټɜ;W;9J4[\ ]Rm{wkߖw2OO-[\ S;w2gH65W.e2K#D"263&pB33",/(ґ;NJM]wR(`]D뛦?+lfMAɓU=nm7UY㚛@PYkk~,(H;-|ȯ6 ڋ@ G PG[x<X9P(A';˅(55}+V?s&njW9:*cǞWھ{%*ɓ1 +ÇKB_~j5+lCX,}|ԍ_ h hi.[D%l67'mzKH=ʺ'kzDEv -s,*ڊ4ƛfDvvv>[Z,81;uuW][n?&RwFԪL}}} ^ٳxjeԴ4oQQJbΟྐ n+88/P-ϙczz ̯#ʕcS5Y5F۱c|U,?{6u1L1˖9) ;5wj*Ml/RV$'/@鹠tn|-bf_222: @*—#OءC+_O">t9ܗ7o@_g—/_&hCtLͮ]t?7pc"} twwSTnש,^;o}{Y TQNΛv-tNteܹӣ U\**v21lw,u vaaawѨ)svٰ<nwsC>5#h?jP(Dffh?yҹsͺ-/aaN%HΟ?bnE^Uʴ,GkH$??ȈaκɄ]KLvծm۶kiaǿ$-b&^H?\JMQ rڵkɈԠgtttTWW ژSxZZʼnZKKRjj] ml\+W\ Ss{,΋/:88$%%@x*"47ܹ6DÜc""[{DJB#fddXXX曚ߺ՘RXئ9 FdktAaZs%OOOgݑJMM]ϟwwN;; A7z9AAs==-QCLWOO/:"zAB^Hd\pp/HaKD"gaAR(hMcctzrr2c̖QlF&0̵kTr4A>0lK;***֭[:=5@"\p+444$$dڥi14׳k 5ArBG H~SEf0b0Eyxx>vVlvaaPJJ;[U>KDpY,N_z DqMMMCCCpp̤V=O X,Xd.;44DRLӶ6\8K#"JqsssssD=== zgΜp8x<a={Ld1JUQu5@=<O$IRT4QR)áP(FFFY! ?rT~M;13~ LuaLDAP: A Lua interface to an LDAP library
LuaLDAP
A Lua interface to an LDAP library

Introduction

LuaLDAP is a simple interface from Lua to an LDAP client, in fact it is a bind to OpenLDAP client or ADSI client

LuaLDAP defines one single global variable: a table called lualdap. This table holds the functions used to create an LDAP connection object.

A connection object offers methods to perform any operation on the directory such as comparing values, adding new entries, modifying attributes on existing entries, removing entries, and the most common of all: searching. Entries are represented as Lua tables; attributes are its fields. The attribute values can be strings or tables of strings (used to represent multiple values).

LuaLDAP is a bind to the OpenLDAP library or to ADSI library and it depends on a previous installation of any of this libraries. You can download OpenLDAP from the OpenLDAP download page. ADSI is included on Windows 2000 or newer. Windows NT/Me/98/95 requires an Active Directory Client Extension

Building

LuaLDAP could be built to Lua 5.0 or to Lua 5.1. In both cases, the language library and headers files for the target version must be installed properly.

LuaLDAP offers a Makefile and a separate configuration file, config, which should be edited to suit your installation before runnig make. The file has some definitions like paths to the external libraries, compiler options and the like. One important definition is the version of Lua language, which is not obtained from the installed software.

Installation

The LuaLDAP compiled binary should be copied to a directory in your C path. Lua 5.0 users should install Compat-5.1 also.

Windows users of ADSI can use the binary versions of LuaLDAP (lualdap.dll) available at LuaForge.

Representing attributes

Many LDAP operations manage sets of attributes and values. LuaLDAP provides a uniform way of representing them by using Lua tables. The table attributes can be Lua string, a binary string (a string of bits), or table of n values indexed from 1 to n. Some operations have different approaches that will be explained as necessary.

Here is a simple example:

entry = {
    an_attribute = "a value",
    other_attribute = {
        "first value of other attribute",
        "another value of other attribute",
    },
}
Attribute names cannot contain the '\0' character.

Distinguished names

The distinguished name (DN) is the term used to identify an entry on the directory information tree. It is formed by the relative distinguished name (RDN) of the entry and the distinguished name of its parent. LuaLDAP will always use a string to represent the DN of any entry.

A more precise definition can be found on the LDAP documentation. A list of some of these files can be found in Related documentation section.

Initialization functions

LuaLDAP provides a single way to connect to an LDAP server:

lualdap.open_simple (hostname, who, password, usetls)
Initializes a session with an LDAP server. This function requires a hostname, accordingly to the C LDAP API definition ("hostname contains a space-separated list of hostnames or dotted strings representing the IP address of hosts running an LDAP server to connect to. Each hostname in the list MAY include a port number which is separated from the host itself with a colon (:) character."). The argument who should be the distinguished name of the entry that has the password to be checked against the third argument, password. The optional argument usetls is a Boolean flag indicating if Transport Layer Security (TLS) should be used.
Returns a connection object if the operation was successful. In case of error it returns nil followed by an error string.

Connection objects

A connection object offers methods which implement LDAP operations. Almost all of them need a distinguished name to identify the entry on which the operation will be executed.

These methods execute asynchronous operations and return a function that should be called to obtain the results. The called functions will return true indicating the success of the operation. The only exception is the compare function which can return either true or false (as the result of the comparison) on a successful operation.

There are two types of errors: API errors, such as wrong parameters, absent connection etc.; and LDAP errors, such as malformed DN, unknown attribute etc. API errors will raise a Lua error, while LDAP errors will be reported by the function/method returning nil plus the error message provided by the OpenLDAP client.

A connection object can be created by calling the Initialization function.

Methods

conn:add (distinguished_name, table_of_attributes)
Adds a new entry to the directory with the given attributes and values.
conn:close()
Closes the connection conn.
conn:compare (distinguished_name, attribute, value)
Compares a value to an entry.
conn:delete (distinguished_name)
Deletes an entry from the directory.
conn:modify (distinguished_name, table_of_operations*)
Changes the values of attributes in the given entry. The tables of operations are tables of attributes with the value on index 1 indicating the operation to be performed. The valid operations are:
  • '+' to add the values to the attributes
  • '-' to delete the values of the attributes
  • '=' to replace the values of the attributes
Any number of tables of operations will be used in a single LDAP modify operation.
conn:rename (distinguished_name, new_relative_dn, new_parent)
Changes an entry name (i.e. change its distinguished name).
conn:search (table_of_search_parameters)
Performs a search operation on the directory. The parameters are described below:

attrs
a string or a list of attribute names to be retrieved (default is to retrieve all attributes).
attrsonly
a Boolean value that must be either false (default) if both attribute names and values are to be retrieved, or true if only names are wanted.
base
The distinguished name of the entry at which to start the search.
filter
A string representing the search filter as described in The String Representation of LDAP Search Filters (RFC 2254).
scope
A string indicating the scope of the search. The valid strings are: "base", "onelevel" and "subtree". The empty string ("") and nil will be treated as the default scope.
sizelimit
The maximum number of entries to return (default is no limit).
timeout
The timeout in seconds (default is no timeout). The precision is microseconds.

The search method will return a search iterator which is a function that requires no arguments. The search iterator is used to get the search result and will return a string representing the distinguished name and a table of attributes as returned by the search request.

Example

here is a some sample code that demonstrate the basic use of the library.

require "lualdap"

ld = assert (lualdap.open_simple ("ldap.server",
                "mydn=manoeljoaquim,ou=people,dc=ldap,dc=world",
                "mysecurepassword"))

for dn, attribs in ld:search { base = "ou=people,dc=ldap,dc=world" } do
    io.write (string.format ("\t[%s]\n", dn))
    for name, values in pairs (attribs) do
        io.write ("["..name.."] : ")
        if type (values) == "string" then
            io.write (values)
        elseif type (values) == "table" then
            local n = table.getn(values)
            for i = 1, (n-1) do
                io.write (values[i]..",")
            end
            io.write (values[n])
        end
        io.write ("\n")
    end
end

ld:add ("mydn=newuser,ou=people,dc=ldap,dc=world", {
    objectClass = { "", "", },
    mydn = "newuser",
    abc = "qwerty",
    tel = { "123456758", "98765432", },
    givenName = "New User",
})()

ld:modify {"mydn=newuser,ou=people,dc=ldp,dc=world",
    { '=', givenName = "New", cn = "New", sn = "User", },
    { '+', o = { "University", "College", },
           mail = "newuser@university.edu", },
    { '-', abc = true, tel = "123456758", },
    { '+', tel = "13579113", },
}()

ld:delete ("mydn=newuser,ou=people,dc=ldp,dc=world")()

Related documentation

Valid XHTML 1.0!

$Id: manual.html,v 1.34 2007-12-14 16:46:15 carregal Exp $

lualdap-1.4.0/docs/000077500000000000000000000000001452140135600140675ustar00rootroot00000000000000lualdap-1.4.0/docs/contributors.md000066400000000000000000000046641452140135600171600ustar00rootroot00000000000000 # Contributors LuaLDAP was originally created by the [Kepler Project](http://www.keplerproject.org/) (designed and implemented by Roberto Ierusalimschy, André Carregal and Tomás Guisasola). A CVS-to-Git conversion was done by [LuaForge](http://luaforge.net/) from their [project](http://luaforge.net/projects/lualdap/) to a [GitHub repository](https://github.com/luaforge/lualdap). From there, the community took over and moved in a new repository under the [LuaLDAP GitHub organisation](https://github.com/lualdap). The following maintainers curated fixes, improvements and releases: * [Brett Delle Grazie](https://github.com/bdellegrazie) : 2014 - 2015 * [Dennis Schridde](https://github.com/devurandom) : 2017 - 2019 * [François Perrad](https://github.com/fperrad) : 2021 - 2023 Significant contributions were made by (in order of appearance): * [Matthew Wild](https://github.com/mwild1) : Bugfixes; curation of community patches * [Dennis Schridde](https://github.com/devurandom) : Lua 5.1, 5.2, 5.3 compatibility; OpenLDAP 2.3 compatibility; initial CircleCI and Codecov setup; bugfixes; curation of community patches * Michael Bienia , Micah Gersten , Luca Capello : [Bugfix for Debian](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=722175) * [John Regan](https://github.com/jprjr) : Initial Rockspec * [Dan Callaghan](https://github.com/danc86) : Initial test harness using a live OpenLDAP server; bugfixes * [Brett Delle Grazie](https://github.com/bdellegrazie) : Documentation updates; curation of community patches * [Jakub Jirutka](https://github.com/jirutka) : Initial Travis CI setup; bugfixes * [Victor Seva](https://github.com/linuxmaniac) : `lualdap` global variable only with Lua 5.1 * [François Perrad](https://github.com/fperrad) : Lua 5.4 compatiblity, fix WinLDAP * [Daurnimator](https://github.com/daurnimator) - Cleanup * [Cyril Romain](https://github.com/cyrilRomain) : Fix segfault in `search()` with multiple attrs * [Will Robertson](https://github.com/wspr) : Improve example with `search()` in manual * [Alex Dowad](https://github.com/alexdowad) : Add optional timeout argument to open and open_simple lualdap-1.4.0/docs/index.md000066400000000000000000000023541452140135600155240ustar00rootroot00000000000000 ## Overview LuaLDAP is a simple interface from Lua to an LDAP client, in fact it is a bind to [OpenLDAP](https://www.openldap.org) client or [ADSI](https://docs.microsoft.com/en-us/windows/win32/adsi/about-adsi). It enables a Lua program to: * Connect to an LDAP server; * Execute any operation (search, add, compare, delete, modify and rename); * Retrieve entries and references of the search result. ## Status It's developed for Lua 5.1, 5.2, 5.3 & 5.4, and OpenLDAP 2.3 or newer. ## Download The sources are hosted on [Github](https://github.com/lualdap/lualdap). The Teal type definition of this library is available [here](https://github.com/teal-language/teal-types/blob/master/types/lualdap/lualdap.d.tl). ## Installation LuaLDAP is available via [LuaRocks](https://luarocks.org/modules/fperrad/lualdap): ```sh luarocks install lualdap ``` Debian packages are available on [Debian](https://packages.debian.org/sid/lua-ldap) or [Ubuntu](https://packages.ubuntu.com/jammy/lua-ldap). RPM packages are available on [Fedora](https://src.fedoraproject.org/rpms/lua-ldap). More downstreams on [repology.org](https://repology.org/projects/?search=lualdap&maintainer=&category=&inrepo=¬inrepo=&repos=&families=&repos_newest=&families_newest=). lualdap-1.4.0/docs/license.md000066400000000000000000000037721452140135600160440ustar00rootroot00000000000000 # License LuaLDAP is free software: it can be used for both academic and commercial purposes at absolutely no cost. There are no royalties or GNU-like "copyleft" restrictions. LuaLDAP qualifies as [Open Source](https://www.opensource.org/docs/definition.html) software. Its licenses are compatible with [GPL](https://www.gnu.org/licenses/#GPL). LuaLDAP is not in the public domain and the [Kepler Project](http://www.keplerproject.org) keep its copyright. The legal details are below. The spirit of the license is that you are free to use LuaLDAP for any purpose at no cost without having to ask us. The only requirement is that if you do use LuaLDAP, then you should give us credit by including the appropriate copyright notice somewhere in your product or its documentation. The LuaLDAP library is designed and implemented by Roberto Ierusalimschy, André Carregal and Tomás Guisasola. The implementation is not derived from licensed software. * * * Copyright © 2003-2007 The Kepler Project. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. lualdap-1.4.0/docs/logo/000077500000000000000000000000001452140135600150275ustar00rootroot00000000000000lualdap-1.4.0/docs/logo/LICENSE000066400000000000000000000013771452140135600160440ustar00rootroot00000000000000Graphic design by Alexandre Nakonechnyj. PostScript programming by the Lua team. This code is hereby placed in the public domain. Permission is hereby granted, without written agreement and without license or royalty fees, to use, copy, and distribute this logo for any purpose, including commercial applications, subject to the following conditions: * The origin of this logo must not be misrepresented; you must not claim that you drew the original logo. We recommend that you give credit to the graphics designer in all printed matter that includes the logo. * The only modification you can make is to adapt the orbiting text to your product name. * The logo can be used in any scale as long as the relative proportions of its elements are maintained. lualdap-1.4.0/docs/logo/lualdap-logo-512x512.png000066400000000000000000001044061452140135600210470ustar00rootroot00000000000000PNG  IHDR{C pHYsaa?itIME&/; IDATxw`[u5aI;$$@(Җ޷.ZRKz[Fᒆ `Nx;KeKx5xɶ$Y_}tsfZ(BԃC    l" p8 ~HP(t:F@ry^vnw |V~v=OT* |>_ B"y4h @ `X~3Ln r{6EkkkaC q8---faaaqEy 222`NRnpGdrr̙3ZF@B$d1 W^0@`܂[t:,NDFќN1 jo߾}, sQ(A$ҘL沁= 򁁁@  "ܱTXX8G ۷o_fffGGj]JZS!999 s&?L&c`ޅH$>Ckjj0:5??3/ѯ^?66ֆ\@`5 !$hkks:61L---ϟxQ-..@*o?n0$)Ng0 |Ad\CCƦZ B""%gM' -N[4 ;vͅ !HRi}}իW#odJ `j~  w8NsaapX,׻^A&ܹ P^^>???99x0tvv2L(t:É`0,,,l,/L&8p E Y0zL,J.HP0Ut%N"L&3P*.k?L޵kסCXL$>Fصk&h4vttl! oohh?6vgق Ba2t:=N}D&UTT\~=Ew&HT*5##Jd.rY,V:{^N$dV >d2TE\P(ٱ2z\.LвT"sNV# ?c O.2L"t:"Hd2b(J$L4|W*gϞP(aECG өTқ Z]'''1]Y `0 œ@i1dydzj,kiTh^4rѾKfyyy+Z@ p\.`0,Er4 $a q:frՖ`0 6>AX,r~>ADSb.D҉mb<H֩xxxeYJW]]]QQ0#T*<}(,5*pttM2!, w7~P*ZBRJ{OM[.-+c|sfz:$S*Yɫ IFimmUttt8{bܶ 0UqPVVP("1"299YPPefRdWjaI [bJL&l,2֏L*YuuΎyl6 fy|||xxxټEqcߏ)ǶzEeUSSs9lD=`r6,& ֽq|v1'f@ O>r> ssdr̫ IrJI$RvvP(dXiii۝,5!}Ąd;vEj===7pÚv|"HR#naIҰLZ,@ F]=9Sc쬾u婘Kw=7sSR)K,)HOO95n{rrrppp%wH$ W\:VWWk4&#\N"nm5  &#;vL&3###r_o=D"b1~r9nfdZKt4 I NMͷ|V|O<1 >}ݵ"cߩzzzppc=_D$UUUbg0bxhhc9h{YW,M&V]j׋ ].OJ>˺v=OX’>ʕ+NS*b@rS̑\=sz{][xǏ?>{}2 Gܲ󫫫\3zTӣP("k``ᬹ$J1 ZVVT*\/[nY45 @QBRTXV^`ZLX6O:L&ŋõW ͉}m䓟][OAq:v+wrL>@J.]Ԁ\$ _vdݮjj`VMh\Ɛ r\.-YYY@ lcӟڟ~_-9vlgUU\ 8B477dC*..טbٳpD 馛_:h4Nju:J]5Ecmu@juf%IX Bv2L'}#nM?~4_s~,B~ LiyhMM 7PPP "]lfX"(3cHzW.xⲲ2vz fT*])l6OMMEȀw&h4Ų"z^0333>>n0^/L޼ ^8=/ dD@pDV\.B֛TOaX`feggG3#t:\U 2T*5//H$QTBynv,8x_dP(T|###eۓv&#JNg-R'ɖ6?r%+h|c"jL.++S*vR)KKKc) VD~pQQњA)$a(*D"QFF*=NIP[ %< `0999[Z=77ltnnn2g9/_pwlY pGzzh4)beqx" |>X4==5ڵ:''f/.W:F$: Ed.+mYELffffAAA~~D"a`pq |~]]ݚ o6xFa@-/ϢRA4M|t:\@ hd')LѣGb1\*\_TFt\z>333RDܜNgddd:ҥ;-_|SЙ3->GLfII Hl|`0lۻ4dÝBIIRSVěbv?v% FdՓtNsy H$#jSKgVVLO4sftf^~}||s B(n>9ݾ=]7yu*ZXX9(}>_ ?%33L9??ZD"qa$֢b G{HNuz/~qa`@~a0sss/a1L"'2 B=@sBnLZZń"r|>_VVVx,KKK A @h4pĄ˿497&f޽,V@ BAQtzmo(r8  BPF.v8}}}n @X\R\߰RTpdpχ?ׯOMMYP(DPJ45w:D*5A6|Hjc쑁=JnGӫ A@>VJR*/ R;<zkӮ Kw%~|3>\CѪ0 \ NDlۆB!L&`YYѣGkjjrrr`' {7 ϟ?uU(֋ljORjC55Hr;aGV;99ÏXǘ#Ĕmc8ΕдZmX&&&b00xgmTlcwi͆Uj`_ B)馛V2jڳgϞ9sfjjj2`^}epЛCzV#M1 KwW-+T@wuׁ  ӧO>s Ǻhm}TlոG$&3M_~dslLC@Jf#G/]@eҥKZvFG^x*K/-v deeaJ8|2mnh,bo喛oy܁@`ddwioo_mr K/5TJS>_W ###c߾}Y2tvvb) XZ`0D0l6%!ayXSSǏiݻwc0V%VG bGPĬM&SSSSww7&+L&߿???.ULL JSb!#***fꎎ]JKK1Zattt/Lzyi 6}Ѳ2 l&@@ޜúQ#- xFFFuuu&S@P^^~5&hKa2&&&3(ZPPsN[Fc<}Z:*O&r҆EaX{g׮]S*"ypA^vmٟ>|orZy^~y:nl̛n>d.[-=x;w.Ҧ?44 JJY|>Ry mT*VkΎ vB(߿c2bضwrrr0`ӳd2{wTWW 6[g"J0AA 'a]-E$߿&vQYc{B0mZB y|`` ##S9e7l),,>#r juvPQ"jC;²m)--=zhuu5nx|%~솆LbN@f@ TDG9p+0Q"[X2sp|||hh(tܜ܂TTT=|>СCǎ+//P(\@hin6lNK ;vɈ;pڵ􂂂|]8̬CQ;" - hݻw[,Lf@{{;J|\.6X@ @9 0Q2?b9\ 1_kk+yfuaw` Z~Y({,` 05ʕ+v-իW=fupR/dr:.۫V[B`0 n@`A.67e墙𿋋i{P" XB@Qp(Jc[qb`2ZmkkÇu:===r ޻wJ)`ZjyaadZ~_Oc bȈK=y<&M$f3lEoaRrZZ,7 U"qΝr}rrR(F:oך mmmK{geeٳ'3335{˭јM&\nt\--fNbd!./z/rE"PfB!6 t2|>^}Sl ƞ={l6?y`PT`EъZY2ffWgs,|Tv}9yy|Lx%-YP( VEYB޽ܹs`a-\exFFF]I"R D6pv{~47g1LNj_~yz%NM1CE%).ffD"`D;h@K B0Bd666G3 6?++[nYvV]V1.]}vRW(ccqɓꔭ/w+( 6YRWSsDó~w ޙt媩YS¥FH񹹹}EahA 0冶~P*Qk'fa"@D=L!rYI@$߶D"Z[-ׄͦ f^pJ "RYYf)f2zry!cǎ~hEkjjjkki@U*lgSN;{+q) \.ޝW^, IDAT'6EA7gDC~~L|lnnn^sѸw5=,k޽Ns1 {PT=OGGQ' LL[[^zz[ ޺@ >@ѣYd/"N (yCv{kkh̿R4;;Jv\Y!(o߾5\.v:;w_u|tz5[qxo ^ ~zGGUTdy$NNH8X-)8,577c<!77w16O$%%%{Ys {{{[[[1ǩTjdSO߷o_NNNR|R뛾regzWOd2q2: .\?roWg.[oD…@,e2ݻ1NW6}!E0p5@ TVVF̟cfpǚ=6jkAXǛ'u'Oܖ}.ъ\$R)¬αcyBa)_t)~QQ 7,-%H铓~ff mAD"Q(t:}y'޷oΝ;T(t/oo_nbxB_(FS)$Rdv q?JKc{TȰ59\.W brvaH'X={;wnY"ٳg3C;5xqWaɿ45Yrmݗ}U"3  Ju4 DN0Lut6]__n/ `pš Hvuňϰ٧16o(~`6~o~>wWWgg p!DV1X.**2b&Jt}@QfEjs_wwhcc#\uUeniiq?l$cǎzNr}dp&###=}Ū?IT ͜<]/G!? pW!YI$"<FnŢ9SI-cJcOil]]]\VUUJfvLp7P(Q*h4T*㥥Ea1D"|L;x}-ܜIGwǬ9:HǏ8 wٟԾx<ٳEUxFFF™(߿?lfH |>?6611၇ȣrK bJRXi$  ,DQtaX%%%k~X,^iL&[ou|˯B\*wqWzOtnw';[g~3WRTWwW ?~"<Կ'LpĻ;v};KngZz~gIP5#j/뮿8 ^g?{?kbق}8 į|`bZl[}}}Pd'(q8`08:: Ņǟv p_s)5W^m|ܶB^WTZV*Jӣ].^TTʢ^.wttMF(ׯR t0쯽v_<퀹 Ogs}P<w#|+^*4%//CTG;_5?%ph4>-\ϳX,f-6`0 b4TjFFF6" \|ya={B!~D6f㏟{m=1 ;SHb1/Njb~gF_-Lض`0rrrdhtow:Ӂ@FӁkrrr1 ,z<2n^hoo*\ZZZ]]loO=TsАڵ '&3B!'?߯鶧%'$DG=-nۏ`0Ri3n̛W\~+(JP7b¿[qR>\(O 1k17W{u}_½ |"q?z;HKKc999D"`0DEn *B"<>|xi9-A?~[ zz&?+rbn"d2Qi)mxxv;/yJKӷ- 2,HD"‚fZLJ^ "l6[deD7x[+Wӟ¬$segS1eAQBQmlA/m쏤H1V 77H$j4f2 .9F B`,HnF8~f|ΟL++H1i99BtҌLꁺ-!"Ȓm,,,T`0p5@)z?fOx;vhhhC?3SOZ ^2CP1jDQBaX&#??+|Omqe^ |ڵ)WAFDv^v L&3##`|>ٳp8G?/$񶷷7WNOaqD&&&a2yKP=V/ˋoL1>ْ,}e%m;9\S! BP"|>>ORQT6z>L&/}R|qlV LnͳXypMO[jttM@4[EjjjpPͿxg睻Ugww*H5x`X_<!??`_ /\|%y@ĉv\kRcesQa`]?isw ,[ou| $įbD߯8uoKd )Bqi'ɪRiLgϞ]ȑ#єV!(+k?z.7墟\M7p>'X֦E=J|XBgVVV}}On VUUm_xn>nByajjŕ+Fʷ/P+Xd|'>g&&[?9\n޽z~nnBJmAJ4FxuA_l+3n{;x`#|>o>p'̃|()&-Ģ"Ia!_C w;<t:,k A"nE322 b?VdܹaK~/\/H"GnO:CR<Ν^3>i:JMtYbdggoI<ڋ  Fd d2D".wk CCo}MM SҗxtSa| R(MMMNdžF_NP ݗ_OYYwk. {[1,)*O.);vlk-i/ϟi8>z붜ٵ;ߩ zzN"JJJP#gb˜@ >IKKL={J̆Fe%?>X]oL&I3XݜGQ\Þ#NDxOMMQT:203O]hCE_xÇ m|T*TB"\1N+*b(E{(ZXXˋ$|%R955eQe0[?~׿O*}^h4L&hCCΘ ޙL&f`E@Tx<-ӧ{xbL7yyƺE^zd䲲~ ,T*099yB7o2?g[XXRi28OTҿ$nJuCCSOYy矟>ysss0kЙt̙Urq ,vzAdď^o}15UV]+1<磏vƉp@ 088M@"|333}}}B!299RtzJd͵D&=ܹ3777_}?0yF:=(A$s}}zxB.<e f\z:Nx|ZNw[Lc2io{ (SHq1s}<{r\MZv0>>fgg7v\333sssFůV|kkk5`ls @6uw; rgwl5I$1kv48uu2<;՗nVT*MOO;6]SSd2Wowtth`0 SSS*x_:Nl~{]266THX|≁Wq]DH$EnH$R[hٹl6:ˇ|>J555vd2Dt WeeeIII"|>oB\{7d" A8f(dojR61etf3l61++ FbL&D@n/kccca/1ܼ E]QԽ{X -:Ͽo4_GGGDXy"R|a L&UU0}}Ɔna7zdvqVw}̙3SSSQΪT5$1_;!'er|x[oqk9?sevVÛ;H(H$dPh%q8X.k4P(wvvաH$Jv|kEL IDATwݵ ܿ+q`lbRMM~[$!H|>?///++`eWPfMOOT*GP(RܵkD"߿?333atzx,S|gw Vtɤjo733o 90I&^Sh4z+̰NR)˝N't:}? WWW'2oARYIyCbYdaMylO23&xƻn:ξwyŋJ2itRRRH߯Vk}6S[ox0 eG=| o4]$^bLP(FFF ?999eeesss$}xR*)FqXTp[/DldDbvqرoy@@ 0==}顡qqr6\}.xR~y  #uMq){!m"ah4Zii-rUd rdw+ge `ְ? R4F 7|wQSSfXgaaa 2::wË9"@hH&ij9aW];srrJ5<<Yn{H/>88vyžo,)8o>J.qYYY"SGGgV~t֝wVxq6Y„ķvΝ;B C*&2'a "aͦWU1XWL0*.DL&s߾} 7`0vؑˣsvR l68LF[jk&h慅D~"}|> T*J*& H_a\ Bygx6ʹnF377P(>lNRx<NGO ?@ Agott)J24>*|uqajk}Qq)qߩFBa?*=RW"\*L@.'ONlw:8#d:;`NODԳMMqx\m@6d~3z!#N3CO0 3w<G@, RRYV)Hc;AI¤:N\ϝ+  q~O{5^(Fh2"R@7 9:6/ad D"LB7fqt`Fg;7j6<Ӷdnn.sFae10QUBWQ'N̎6D"13c5Ͳ%ApؘĉY`YZ r!KhN96xPX0t:288`%lH^W5ƨ^oPp8cEdaSL&ӓ0LpEH#61`:.CZ c|\_*\Z0Q(8K._pWj;`X[&rnK>%L0||SA֍Ra`Յm`v:nTק6 \. ho '''Fc`7Ȉ<5 Ng9{vn>)&5!PD|>?I8j[a۝N'b8++ M}wtLWXO}0`(V^p-+/|A[Q1J l6;*` l? ssssss\.o03ͫ-*lmmN90887lg#6D JY@T*`Vd^S8, H"`&Jq5X`ٳcaYFFfOm581P/`5Egdd୳<yUĄ a)~}ŕ.Z|>k%u5ò3[Je|<\I["&ꁐH$.3~׏6[KO$NbS d \#8۴lw3=G\ro$33 p8#x) Js0aN tաSH, &o`VNAǏN20\ 1, WäV|g''dO845177o05ޫWSls1b``RB\.@ [ D套$ sshp!fyG$ q5FzYH6ɓ35WVhjT*ܜ. fxh@10@~{gUqWxb 鮼n9OP0L4Wđn{T_K럟Wd2a:' )`@|9yRctuM&-bq?~_n3_ JF_fAVjuLMq{y^b"A-HϗWWH]4i2|sA@g|;vTW˘LNmm]vnur#^H$REB0paq=00O?=#&Hw{ A`(6Ug:qD n(:N H$X,.++`6;T*HEΞAX"Hd2bh׫Vxh2p̸\@ U-`#ז .R e`|,cr^h3oX}%[ݎ=(84ʧ)R.^J)}Y @8vb'^c˛lYdY%kZ(#;4#(3g9g99NAx N@,xc6IECl2_. vzcDLn\gu!b ܱp ش@f X(nd;1PLGlMqa3\Bd;w:a b;&GF.\_ԆB* q$v/lm{g  |d@B (zYFg`5 @,f#͆'p9 GL 5"#L&377*@0  Zsϭ[I7(\.3?_TJ60d2I&d2,''qٲ-[mm_~y7ϛѐIȸPr.^1L&HHEU*%VdXhGdJ%T]ݻ7:.Vb.~3663̺u&%&|p-I}&yF2 ͣP(0" ;mV8۶-#< ._1 (.. tQxMJT_Jc]ɡmڔ\Zxq\LD.Dn/ #0g?Aٜ>yj趴LCs7(ܲ4M. 婫H'q6F&/773 ͛ddڰ ={j6>0PQ(.Tňvod2cqY8)mm/[o/l}we/V&sLȐ#61I&hp<z|N"&}}}_|ǔ\ ˌ:8RӍgC EKZZ~}o.)I v T,WWWOԺJ"6aXs]C&Sի"QPgn?q2DZ>້_.s*Ѕh4< PY\.Q(Az~[ou{^z36&='@EQ|F^… 0pD`S04% YY)¹yU*~t Lӿp8N|-QO3Ԡl{4Ig *_H SH1`B/"?h4p )=uwtߟe"Z5V#&$) f \b&:4Wx~deՎB@ɼh}b_2Bxk FPT}}`rJ6 xy؀ncCaH`rYSmmF0\)/W " f (y_^ W47_}L^IѣC`"P5H @YщqqP;02vԤ$IoLLLm)%ECu5J%|  ?vZ$J].#@J8R&]IvN099yd2b1+((X Jspr+BRɗJyJqtwF:Y$ŢI.kd H=j9(Δ;f$)֛ C32pWd2ðPT*4 A@Bn]^AnĉdFCVn`0|U `de%e''z,\8V%DG|.g/Vokk[|@3"3C׬I į׿Nu~?) ECX_3Ύ)AJFRi! 6Czz|=Ae= \龩d2 "t?fyAL&ޞPffBa!H ɡYnwsq,p'@  E~~~HgBt IDATHx< 1@Bxxn-A& aD%r7{{k+N;cm[yϏի8xQ“>wGU*֭q1wC+=bCP Rw."DظQP\ AU~ F"s4FŢUW锗souIxjl |2k *i%o@HRU 544 c,Fafeei7ߍ͆0A$%srBa/ܹo/Ga!$^ X* p(, [D&öl) Errh?'XR$=199^c*Gnspge] =)hn7/<?ڋ/ pС!s0$IW[Zoܰ~bJ>#++%]-M;}*D"aSS7nk§% }Unfy_lhy`嗽[Z ;Y;vt=>0I׭?KsM pNN?O<) /|seb< ESO_" o?00M& v-{~[$FEPWACqb1gejS?@=oj"m8z5EA[4=?ɾҀ:wg\ͦ7C͕"6N~}Qv 'D@t:`88XY7p)g|>칡nnQGzH57kPgV;LZ2w6?՞XW^[C a+TxdvwwtHy6\KT*\.WTJR H$*J%E}5O>iEs:|Dӕ7^ӻWV[+馼+{ts]6=KOW9 ID孧Ni?f5k4<畟ٵk#ԇm_Vѯr\.H¹w<6`oر㯟}_~qŊh_}հr࿿gϺ뮛gd=~}y^pP,&WV 4++^86foͽ$$VkOZ^XnG1[;3եonַ Z+,T< R$r9rb:d;6foPjIihho?bi&6}Qb$ ̼nc~f~S{#pvĄnٜ6A cPd3}N{Ϟ~Puc='wϵ SS\XS6ۤ;]S((FrHv{;;oyI0Ywܱ:gXFCADphZ+&ޟ@,/N-*jG? G3`P \Q':{/,[UZ:CW\,ab65ڵ*CO&RRd))Y`A @>nF=ryATBVKﺫ6^܉oFgЛo1tP`pw&.*ޓ'^|3gL F?-oߡ!D"(a :"-ˁB1a`pg"~;5a+ӟ[,>16f[?xAO7v" Gm6[WWx,0ɲI@쳱_j_ggRE9G[}9UNzg>fGn>ҡmm}6=|7 D nR$.Jwa!A rK2,WMF0^8zT{-KKSe,aM>?~ٿ_`cv.mK]w몫+,+K_Gݥ8M$1]6FJCe9fut\ԅ"'6˟gkxpœubt'.[[[?7:B E]|Rt57v{mmGt}q\3~-Z} EիW''Gl  tGy?ē C칡*#B)OBDޥa~1#{8(p#===?J)-M{"x? t[ǿ抹fH 3}}}#$b Tsss}}P-ޠRɫVTxK DlRHqH\.~?izjvwwkھ> VßI5x4/{WѱVRSv&''D"Vn4 l4?szx.f;z; C?efn0 E?!ŢP. jnkk3 xn3AZ n"f|r<`pYL{eGɁse:\ |uk+ @`5J0'YYYW:;; 1 P(=tMa!z!/~QZ] Sg?RSSy<$ٳN-Ix `xɬr* ق!BB{zzZ-[N&֮]_BG٩lK 3Ry>X7@Tg D ߮xk$.ZC333Q`&W#|>n Nٱk$5rµb?~~A; oT h@\|2kb1p-wݧN2J%!^J.Y,ӧOb̥?@\?LMMMNN_/&4QU H^oooZ[[)\.#cCIN[[А 쳹w A? T*5>>J TVlg666Tڵkx/n}?9,0to^B}}} "(~AO?T*]z5G!`yO<.-b1ז.8E) qo!斀lx<JE=AX,zN*#|[r[er#B& @"D"^ZGGG\.7\:`;?2AxɬېDQ8uT*jnw… RfATENdC"w/ޱcDkh__1JE)NvCS8tn ~7WxLſjJL&JD+.N' DZϯ_nX,׀r%f1@(,dڲ[o 9` "A0 Hq2B9IO?*|A fX}}})"FGG) 7}X܄~8 _{W%'`|f%%%Gctt :Jy&WYSFI^rQ0qqqBdH$ZlqCNTUV*Q8,̏B]uj4j|Ksr&#G>j4 p&K=/##aW67ky+\u߿2+j|"O8Q*]6@c2YhO|ĉ3aCerKEr|M%1q\OD/bl6D")8~}:Fk$EYFYzt\AߞNVT15=zom6C~i\V?sժdEf JJJb\-VE􊊊J٦Z[:{}jܜDJ>|okfffeee,${zرcWb9twv>e^t;[]VP;=h A΃:>t:3=ºP\}Nn:5UCh`  ())͍Em{&a#>}{zuuZNZ AcZ>`0`im;tja CTɹI))2 xр).:;N{ddl`ܻwo; deBj)+@45E5 ###3L]qNp([j/OKKS*B>4`AA>.]JPD =[`+Vx X`(ZPP#5d0vv56O=NxVQTLOW*"RK5СCz>z|||YYB]=00:0`>}Z1+ŜՅʤ$yB`X=' ǫLJJ#cMLッV޽zko|N0tjŲxL n F덝$ Dbjj̙3g*++pUN ih5} ׋0 7/a"#cl6K z=WUUT*& 8[[[Ӊ HJJJMM d $L##cX&M?9Er2cJQrLY,E1%\]ٳ'Nea+WY5N*}}}H$6N0l& ADž ޞzkpжx.]Yrs qq(LED*eKl!(EI FxLض N}: j\$@6Vɓ'[ZZ.'JUUUJ Dou\k^^^EEdV_@` ӧO)tvtt\TjEEEYYx0ŋCiI ܿA_TZVVT*a Vٷo ɋ)DuIDAT-` 'mmmǎs:(fff.ZAbx´4 ьihhhkk+..NMM #GJKh4EEE@c'''B! X,Njmm_ A󳳳Y,J@4v.M R,**GQl@b0ZZZf PԴLX j 3 l :X,MMMD999)))Pr 655]GMMMnn. &;==j%"e2Yssssss@DHVJ@ıl]]]OX,.\(.. X0^ӧ{zzWVX"mll+l6{Æ pfA" @ P'OJ0"DCCC6Dww7`2E"Qvv6Xvez^~D"C FRxsx|F[ D fYvvv^􌌌l@'0f`nX4PMJJϗdpFhd2tttx(233U*0p=wJUTpqB pq!J333j5N+@PV'z^ $$$BxKQgΜ?.Jsrr`ID (v1{왘q.R =rș3gPMMMh4 \?1<<|G&*J"!AFPj5 nvuu͘bzzB;DNSuvv?rM!H$C @v COOO{{BFSUUd2nDjz*ֈq` @!r\.'%%uvvvuulx<F::: !%Iff@ww^t{@&( "^l6|u:tNgZaS.EQX,333GFF:;;ׅP`%ހqـ^ ]]]CCCr\$q0L###CCC}t:]JJ  f0 GFFH$ =>>n2u:h%_N'* ÷su2}BdzX,>f}+El6F  t~/BJJR, BaV\.Pe2bxҥ\.7lvVX,VUT/)JɤRD"H$ 8"##C,ܱxR<(=CbX G{zzZ H$7''''&&,dr8Bp~֚YVkf~0MW^oZ @Xd2LBX,s8NB8\.7>>R BtT*_AP(W/߼B@+C\\˓H$߹6d2Fp8d2`@& rъn7 v… t:=}tKoyyyVV~tbbwd2! ҿo Ql:    YԭIENDB`lualdap-1.4.0/docs/logo/lualdap-logo.ps000066400000000000000000000112721452140135600177560ustar00rootroot00000000000000%!PS-Adobe-2.0 EPSF-2.0 %%Title: LuaLDAP logo %%Creator: lua@tecgraf.puc-rio.br %%CreationDate: Wed Nov 29 19:04:04 EDT 2000 %%BoundingBox: -45 0 1035 1080 %%Pages: 1 %%EndComments %%EndProlog %------------------------------------------------------------------------------ % % Graphic design by Alexandre Nakonechnyj. % PostScript programming by the Lua team. % This code is hereby placed in the public domain. % % Permission is hereby granted, without written agreement and without license % or royalty fees, to use, copy, and distribute this logo for any purpose, % including commercial applications, subject to the following conditions: % % * The origin of this logo must not be misrepresented; you must not % claim that you drew the original logo. We recommend that you give credit % to the graphics designer in all printed matter that includes the logo. % % * The only modification you can make is to adapt the orbiting text to % your product name. % % * The logo can be used in any scale as long as the relative proportions % of its elements are maintained. % %------------------------------------------------------------------------------ /LABEL (LuaLDAP) def %-- DO NOT CHANGE ANYTHING BELOW THIS LINE ------------------------------------ /PLANETCOLOR {0 0 0.5 setrgbcolor} bind def /HOLECOLOR {1.0 setgray} bind def /ORBITCOLOR {0.5 setgray} bind def /LOGOFONT {/Helvetica 0.90} def /LABELFONT {/Helvetica 0.36} def %------------------------------------------------------------------------------ /MOONCOLOR {PLANETCOLOR} bind def /LOGOCOLOR {HOLECOLOR} bind def /LABELCOLOR {ORBITCOLOR} bind def /LABELANGLE 125 def /LOGO (Lua) def /DASHANGLE 10 def /HALFDASHANGLE DASHANGLE 2 div def % moon radius. planet radius is 1. /r 1 2 sqrt 2 div sub def /D {0 360 arc fill} bind def /F {exch findfont exch scalefont setfont} bind def % place it nicely on the paper /RESOLUTION 1024 def RESOLUTION 2 div dup translate RESOLUTION 2 div 2 sqrt div dup scale %-------------------------------------------------------------------- planet -- PLANETCOLOR 0 0 1 D %---------------------------------------------------------------------- hole -- HOLECOLOR 1 2 r mul sub dup r D %---------------------------------------------------------------------- moon -- MOONCOLOR 1 1 r D %---------------------------------------------------------------------- logo -- LOGOCOLOR LOGOFONT F LOGO stringwidth pop 2 div neg -0.5 moveto LOGO show %------------------------------------------------------------------------------ % based on code from Blue Book Program 10, on pages 167--169 % available at ftp://ftp.adobe.com/pub/adobe/displaypostscript/bluebook.shar % str ptsize centerangle radius outsidecircletext -- /outsidecircletext { circtextdict begin /radius exch def /centerangle exch def /ptsize exch def /str exch def gsave str radius ptsize findhalfangle centerangle add rotate str { /charcode exch def ( ) dup 0 charcode put outsideplacechar } forall grestore end } def % string radius ptsize findhalfangle halfangle /findhalfangle { 4 div add exch stringwidth pop 2 div exch 2 mul 3.1415926535 mul div 360 mul } def /circtextdict 16 dict def circtextdict begin /outsideplacechar { /char exch def /halfangle char radius ptsize findhalfangle def gsave halfangle neg rotate radius 0 translate -90 rotate char stringwidth pop 2 div neg 0 moveto char show grestore halfangle 2 mul neg rotate } def end %--------------------------------------------------------------------- label -- LABELFONT F /LABELSIZE LABELFONT exch pop def /LABELRADIUS LABELSIZE 3 div 1 r add sub neg 1.02 mul def /HALFANGLE LABEL LABELRADIUS LABELSIZE findhalfangle HALFDASHANGLE div ceiling HALFDASHANGLE mul def /LABELANGLE 60 LABELANGLE HALFANGLE sub lt { HALFANGLE HALFANGLE DASHANGLE div floor DASHANGLE mul eq {LABELANGLE DASHANGLE div ceiling DASHANGLE mul} {LABELANGLE HALFDASHANGLE sub DASHANGLE div round DASHANGLE mul HALFDASHANGLE add} ifelse } {HALFANGLE 60 add} ifelse def LABELCOLOR LABEL LABELSIZE LABELANGLE LABELRADIUS outsidecircletext %--------------------------------------------------------------------- orbit -- ORBITCOLOR 0.03 setlinewidth [1 r add 3.1415926535 180 div HALFDASHANGLE mul mul] 0 setdash newpath 0 0 1 r add 3 copy 30 LABELANGLE HALFANGLE add arcn stroke 60 LABELANGLE HALFANGLE sub 2 copy lt {arc stroke} {4 {pop} repeat} ifelse %------------------------------------------------------------------ copyright -- /COPYRIGHT (Graphic design by A. Nakonechnyj. Copyright (c) 1998, All rights reserved.) def LABELCOLOR LOGOFONT 32 div F 2 sqrt 0.99 mul dup neg moveto COPYRIGHT 90 rotate %show %---------------------------------------------------------------------- done -- showpage %%Trailer %%EOF lualdap-1.4.0/docs/manual.md000066400000000000000000000251571452140135600157000ustar00rootroot00000000000000 # Introduction LuaLDAP is a simple interface from Lua to an LDAP client, in fact it is a bind to [OpenLDAP](https://www.openldap.org) client or [ADSI](https://docs.microsoft.com/en-us/windows/win32/adsi/about-adsi). LuaLDAP returns a single table (with Lua 5.1, this table is also stored in the global variable named `lualdap`) This table holds the functions used to instantiate an LDAP connection object. A connection object offers methods to perform any operation on the directory such as comparing values, adding new entries, modifying attributes on existing entries, removing entries, and the most common of all: searching. Entries are represented as Lua tables; attributes are its fields. The attribute values can be strings or tables of strings (used to represent multiple values). # Representing attributes Many LDAP operations manage sets of attributes and values. LuaLDAP provides a uniform way of representing them by using Lua tables. The table attributes can be Lua string, a binary string (a string of bits), or table of _n_ values indexed from 1 to _n_. Some operations have different approaches that will be explained as necessary. Here is a simple example: ```lua entry = { an_attribute = "a value", other_attribute = { "first value of other attribute", "another value of other attribute", }, } ``` Attribute names cannot contain the `'\0'` character. # Distinguished names The distinguished name (DN) is the term used to identify an entry on the directory information tree. It is formed by the relative distinguished name (RDN) of the entry and the distinguished name of its parent. LuaLDAP will always use a string to represent the DN of any entry. A more precise definition can be found on the LDAP documentation. A list of some of these resources can be found in [Related documentation](manual.md#related-documentation) section. # Instantiation functions LuaLDAP provides some ways to create a LDAP connection object: ### `lualdap.open_simple (hostname, who, password, usetls, timeout)` Initializes a session with an LDAP server. The argument `hostname` may contain a blank-separated list of hosts to try to connect to, and each host may optionally by of the form _host:port_. The argument `who` should be the [distinguished name](manual.md#distinguished-names) of the entry that has the password to be checked against the third argument, `password`. The optional argument `usetls` is a boolean flag indicating if Transport Layer Security (TLS) should be used. The optional argument `timeout` is the connection timeout in seconds. The precision is microseconds. It also sets a timeout for subsequent network operations. This argument has no effect on Microsoft Windows. Returns a connection object if the operation was successful. In case of error it returns `nil` followed by an error string. ### `lualdap.open (hostname, usetls, timeout)` Open and initialize a connection to a LDAP server (without binding, see method `bind_simple`). The argument `hostname` may contain a blank-separated list of hosts to try to connect to, and each host may optionally by of the form _host:port_. The optional argument `usetls` is a boolean flag indicating if Transport Layer Security (TLS) should be used. The optional argument `timeout` is the connection timeout in seconds. The precision is microseconds. It also sets a timeout for subsequent network operations. This argument has no effect on Microsoft Windows. Returns a connection object if the operation was successful. In case of error it returns `nil` followed by an error string. ### `lualdap.initialize (uri)` **DEPRECATED** in favor of `open` Open and initialize a connection to a server (without binding, see method `bind_simple`). The `uri` parameter may be a comma- or whitespace-separated list of URIs containing only the schema, the host, and the port fields. Returns a connection object if the operation was successful. # Connection objects A connection object offers methods which implement LDAP operations. Almost all of them need a [distinguished name](manual.md#distinguished-names) to identify the entry on which the operation will be executed. These methods execute asynchronous operations and return a function that should be called to obtain the results. The called functions will return `true` indicating the success of the operation. The only exception is the `compare` function which can return either `true` or `false` (as the result of the comparison) on a successful operation. There are two types of errors: **API errors**, such as wrong parameters, absent connection etc.; and **LDAP errors**, such as malformed DN, unknown attribute etc. API errors will raise a Lua error, while LDAP errors will be reported by the function/method returning `nil` plus the error message provided by the OpenLDAP client. A connection object can be created by calling a [Instantiation function](manual.md#instantiation-functions). ## Methods ### `conn:add (distinguished_name, table_of_attributes)` Adds a new entry to the directory with the given attributes and values. ### `conn:bind_simple (who, password)` Bind to the directory. The argument `who` should be the [distinguished name](manual.md#distinguished-names) of the entry that has the password to be checked against the second argument, `password`. Returns the connection object if the operation was successful. In case of error it returns `nil` followed by an error string. ### `conn:close ()` Closes the connection `conn`. Returns `1` in case of success; nothing when already closed. ### `conn:compare (distinguished_name, attribute, value)` Compares a value to an entry. ### `conn:delete (distinguished_name)` Deletes an entry from the directory. ### `conn:modify (distinguished_name, table_of_operations*)` Changes the values of attributes in the given entry. The tables of operations are [tables of attributes](manual.md#representing-attributes) with the value on index `1` indicating the operation to be performed. The valid operations are: - `+` to add the values to the attributes - `-` to delete the values of the attributes - `=` to replace the values of the attributes Any number of tables of operations will be used in a single LDAP modify operation. ### `conn:rename (distinguished_name, new_relative_dn, new_parent, delete_old)` Changes an entry name (i.e. change its [distinguished name](manual.md#distinguished-names)). The optional argument `new_parent` is a [distinguished name](manual.md#distinguished-names), without it only the RDN is changed. The optional argument `delete_old` is an integer. With the default value `0`, old RDN should be retained, otherwise old RDN should be deleted. ### `conn:search (table_of_search_parameters)` Performs a search operation on the directory. The parameters are described below: - `attrs` a string or a list of attribute names to be retrieved (default is to retrieve all attributes). - `attrsonly` a boolean value that must be either `false` (default) if both attribute names and values are to be retrieved, or `true` if only names are wanted. - `base` The [distinguished name](manual.md#distinguished-names) of the entry at which to start the search. - `filter` A string representing the search filter as described in [String Representation of LDAP Search Filters](https://tools.ietf.org/html/rfc4515) - `scope` A string indicating the scope of the search. The valid strings are: `base`, `onelevel` and `subtree`. The empty string (`""`) and `nil` will be treated as the default scope. - `sizelimit` The maximum number of entries to return (default is no limit). - `timeout` The timeout in seconds (default is no timeout). The precision is microseconds. The search method will return a _search iterator_ which is a function that requires no arguments. The search iterator is used to get the search result and will return a string representing the [distinguished name](manual.md#distinguished-names) and a [table of attributes](manual.md#representing-attributes) as returned by the search request. # Example Here is a some sample code that demonstrate the basic use of the library (see also the [Teal type definition](https://github.com/teal-language/teal-types/blob/master/types/lualdap/lualdap.d.tl) of the library). ```lua local lualdap = require"lualdap" local ld = assert(lualdap.open_simple("ldap.server", "mydn=manoeljoaquim,ou=people,dc=ldap,dc=world", "mysecurepassword")) for dn, attribs in ld:search{ base = "ou=people,dc=ldap,dc=world", scope = "subtree" } do io.write("\t[" .. dn .. "]\n") for name, values in pairs(attribs) do io.write("[" .. name .. "] : ") if type(values) == "string" then io.write(values) elseif type(values) == "table" then local n = #values for i = 1, n-1 do io.write(values[i] .. ",") end io.write(values[n]) end io.write("\n") end end ld:add("mydn=newuser,ou=people,dc=ldap,dc=world", { objectClass = { "", "", }, mydn = "newuser", abc = "qwerty", tel = { "123456758", "98765432", }, givenName = "New User", })() ld:modify("mydn=newuser,ou=people,dc=ldp,dc=world", { '=', givenName = "New", cn = "New", sn = "User", }, { '+', o = { "University", "College", }, mail = "newuser@university.edu", }, { '-', abc = "True", tel = "123456758", }, { '+', tel = "13579113", } )() ld:delete("mydn=newuser,ou=people,dc=ldp,dc=world")() ``` # Related documentation - [LDAP: Technical Specification Road Map](https://tools.ietf.org/html/rfc4510) (RFC4510) - [LDAP: The Protocol](https://tools.ietf.org/html/rfc4511) (RFC4511) - [LDAP: Directory Information Models](https://tools.ietf.org/html/rfc4512) (RFC4512) - [LDAP: Authentication Methods and Security Mechanisms](https://tools.ietf.org/html/rfc4513) (RFC4513) - [LDAP: String Representation of Distinguished Names](https://tools.ietf.org/html/rfc4514) (RFC4514) - [LDAP: String Representation of Search Filters](https://tools.ietf.org/html/rfc4515) (RFC4515) - [LDAP: Uniform Resource Locator](https://tools.ietf.org/html/rfc4516) (RFC4516) - [LDAP: Syntaxes and Matching Rules](https://tools.ietf.org/html/rfc4517) (RFC4517) - [LDAP: Internationalized String Preparation](https://tools.ietf.org/html/rfc4518) (RFC4518) - [LDAP: Schema for User Applications](https://tools.ietf.org/html/rfc4519) (RFC4519) - [The C LDAP Application Program Interface](https://www.ietf.org/proceedings/51/I-D/draft-ietf-ldapext-ldap-c-api-05.txt) (draft IETF) - [OpenLDAP API](https://openldap.org/software/man.cgi?query=ldap) - [WinLDAP API](https://docs.microsoft.com/en-us/windows/win32/api/_ldap/) lualdap-1.4.0/docs/news.md000066400000000000000000000074441452140135600153760ustar00rootroot00000000000000# Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] ## [1.4.0] - 2023-11-04 ### Changed * Add optional timeout argument to `open` and `open_simple` ## [1.3.1] - 2023-03-15 ### Fixed * Fix segfault in `search()` with multiple attrs ### Changed * Improve example with `search()` in manual ## [1.3.0] - 2021-06-05 ### Added * a new method `open` which deprecates `initialize` ### Changed * `bind_simple` returns the connection (instead of `true`) * the Lua compatibility (5.1 to 5.4) is done without the compat-5.3 module ## [1.2.6] - 2021-03-17 ### Added * Lua 5.4 compatibility * Updated documentation is available on ### Fixed * Fix case in Makefile when install directory does not exist * WinLDAP variant * issue #10: space-separated list of hostnames doesn't work anymore ### Removed * Dropped the claim that we support OpenLDAP older than 2.3, which was not true since 3597ac91334dbaa912db391f5e9fd7a15a643686 ## [1.2.5] - 2019-01-06 ### Changed * `CPPFLAGS`, `CFLAGS` and `LDFLAGS` can now be overridden on the `make` command line. It is not longer necessary to edit the `config` file. ### Removed * We no longer export a `lualdap` global variable, in accordance with Lua 5.2 module rules (#8) - cf. https://www.lua.org/manual/5.2/manual.html#8.2 * Remove support for Lua 5.0 by including an external file outside the source directory - Support for Lua 5.1 and 5.2 continues through our inclusion of lua-compat-5.3 (see release notes for v1.2.4-rc1) ## [1.2.4] - 2019-01-02 ### Added * Build system additions to accomodate Debian ## [1.2.4-rc1] - 2018-12-22 ### Added * Lua 5.3 compatibility - Backwards compatibility using Kepler Project's [lua-compat-5.3](https://github.com/keplerproject/lua-compat-5.3/) * Support specifying a URI in hostname argument to `open_simple()` ### Changed * Switch to [busted](http://olivinelabs.com/busted/) unit testing framework * Automate building and running unit tests using [CircleCI](http://circleci.com/) - Tests run against [OpenShift's OpenLDAP 2.4.41](https://hub.docker.com/r/openshift/openldap-2441-centos7/) ([source](https://github.com/openshift/openldap/)) * Keep track of unit test coverage using [Codecov](http://codecov.io/) ### Fixed * C89 compatibility * Fix two credentials-related segfaults in `open_simple()` ## [1.2.3] - 2015-04-09 ### Changed * documentation ## [1.2.2] - 2014-07-26 ### Changed * `lualdap_bind_simple()` with OpenLDAP 2.3 API ## [1.2.1] - 2014-06-29 ### Added * from prosody.im, new function `initialize` and new method `bind_simple` ## [1.2.0] - 2014-02-21 ### Added * Lua 5.2 compatibility * OpenLDAP 2.3 compatibility * rockspec ## 1.1.0 - 2007-12-14 ### Added * support ADSI (WinLDAP) (Thanks to Mark Edgar) ## 1.0.1 - 2006-04-04 ## 1.0 - 2005-06-10 ## 1.0-alpha - 2003-12-10 [Unreleased]: https://github.com/lualdap/lualdap/compare/v1.4.0...HEAD [1.4.0]: https://github.com/lualdap/lualdap/compare/v1.3.1...v1.4.0 [1.3.1]: https://github.com/lualdap/lualdap/compare/v1.3.0...v1.3.1 [1.3.0]: https://github.com/lualdap/lualdap/compare/v1.2.6...v1.3.0 [1.2.6]: https://github.com/lualdap/lualdap/compare/v1.2.5...v1.2.6 [1.2.5]: https://github.com/lualdap/lualdap/compare/v1.2.4...v1.2.5 [1.2.4]: https://github.com/lualdap/lualdap/compare/v1.2.4-rc1...v1.2.4 [1.2.4-rc1]: https://github.com/lualdap/lualdap/compare/v1.2.3...v1.2.4-rc1 [1.2.3]: https://github.com/lualdap/lualdap/compare/v1.2.2...v1.2.3 [1.2.2]: https://github.com/lualdap/lualdap/compare/v1.2.1...v1.2.2 [1.2.1]: https://github.com/lualdap/lualdap/compare/v1.2.0...v1.2.1 [1.2.0]: https://github.com/lualdap/lualdap/compare/v1_1_0...v1.2.0 lualdap-1.4.0/mkdocs.yml000066400000000000000000000004631452140135600151450ustar00rootroot00000000000000site_name: LuaLDAP site_description: A Lua interface to the OpenLDAP library site_url: https://lualdap.github.io/lualdap repo_url: https://github.com/lualdap/lualdap nav: - Home: index.md - Manual: manual.md - About: - News: news.md - Contributors: contributors.md - License: license.md theme: mkdocs lualdap-1.4.0/rockspec/000077500000000000000000000000001452140135600147505ustar00rootroot00000000000000lualdap-1.4.0/rockspec/lualdap-1.2.1-1.rockspec000066400000000000000000000013461452140135600207240ustar00rootroot00000000000000package="lualdap" version="1.2.1-1" source = { url = "https://github.com/bdellegrazie/lualdap/archive/v1.2.1.tar.gz", dir = "lualdap-1.2.1", } description = { summary = "Simple interface from Lua to an LDAP Client", detailed = [[ Simple interface from Lua to an LDAP client. ]], homepage = "https://github.com/bdellegrazie/lualdap", license = "MIT" } dependencies = { "lua >= 5.1, < 5.3" } external_dependencies = { LIBLDAP = { header = "ldap.h", library = "ldap", } } build = { type = "builtin", modules = { lualdap = { sources = "src/lualdap.c", libdirs = "$(LIBLDAP_LIBDIR)", incdirs = "$(LIBLDAP_INCDIR)", libraries = "ldap", }, } } lualdap-1.4.0/rockspec/lualdap-1.2.2-1.rockspec000066400000000000000000000013461452140135600207250ustar00rootroot00000000000000package="lualdap" version="1.2.2-1" source = { url = "https://github.com/bdellegrazie/lualdap/archive/v1.2.2.tar.gz", dir = "lualdap-1.2.2", } description = { summary = "Simple interface from Lua to an LDAP Client", detailed = [[ Simple interface from Lua to an LDAP client. ]], homepage = "https://github.com/bdellegrazie/lualdap", license = "MIT" } dependencies = { "lua >= 5.1, < 5.3" } external_dependencies = { LIBLDAP = { header = "ldap.h", library = "ldap", } } build = { type = "builtin", modules = { lualdap = { sources = "src/lualdap.c", libdirs = "$(LIBLDAP_LIBDIR)", incdirs = "$(LIBLDAP_INCDIR)", libraries = "ldap", }, } } lualdap-1.4.0/rockspec/lualdap-1.2.3-1.rockspec000066400000000000000000000013171452140135600207240ustar00rootroot00000000000000package="lualdap" version="1.2.3-1" source = { url = "git://github.com/bdellegrazie/lualdap", tag = "v1.2.3", } description = { summary = "Simple interface from Lua to an LDAP Client", detailed = [[ Simple interface from Lua to an LDAP client. ]], homepage = "https://github.com/bdellegrazie/lualdap", license = "MIT" } dependencies = { "lua >= 5.1, < 5.3" } external_dependencies = { LIBLDAP = { header = "ldap.h", library = "ldap", } } build = { type = "builtin", modules = { lualdap = { sources = {"src/lualdap.c"}, libdirs = {"$(LIBLDAP_LIBDIR)"}, incdirs = {"$(LIBLDAP_INCDIR)"}, libraries = {"ldap"}, }, } } lualdap-1.4.0/rockspec/lualdap-1.2.4-1.rockspec000066400000000000000000000023171452140135600207260ustar00rootroot00000000000000package="lualdap" version="1.2.4.rc1-0" source = { url = "git://github.com/lualdap/lualdap", tag = "v1.2.4-rc1", } description = { summary = "Simple interface from Lua to an LDAP Client", detailed = [[ Simple interface from Lua to an LDAP client. ]], homepage = "https://github.com/bdellegrazie/lualdap", license = "MIT" } dependencies = { "lua >= 5.1", } external_dependencies = { LDAP = { header = "ldap.h", library = "ldap", }, LBER = { header = "lber.h", library = "lber", }, } build = { type = "make", variables = { COVERAGE="$(COVERAGE)", JUNITXML="$(JUNITXML)", }, build_variables = { CFLAGS="$(CFLAGS) -std=c89 -pedantic -Wall -Werror", LIBFLAG="$(LIBFLAG)", LUA_LIBDIR="$(LUA_LIBDIR)", LUA_BINDIR="$(LUA_BINDIR)", LUA_INCDIR="$(LUA_INCDIR)", LUA="$(LUA)", LDAP_LIBDIR="$(LDAP_LIBDIR)", LDAP_INCDIR="$(LDAP_INCDIR)", LBER_LIBDIR="$(LBER_LIBDIR)", LBER_INCDIR="$(LBER_INCDIR)", }, install_variables = { INST_PREFIX="$(PREFIX)", INST_BINDIR="$(BINDIR)", INST_LIBDIR="$(LIBDIR)", INST_LUADIR="$(LUADIR)", INST_CONFDIR="$(CONFDIR)", }, } lualdap-1.4.0/rockspec/lualdap-1.2.4.rc1-0.rockspec000066400000000000000000000023171452140135600214110ustar00rootroot00000000000000package="lualdap" version="1.2.4.rc1-0" source = { url = "git://github.com/lualdap/lualdap", tag = "v1.2.4-rc1", } description = { summary = "Simple interface from Lua to an LDAP Client", detailed = [[ Simple interface from Lua to an LDAP client. ]], homepage = "https://github.com/bdellegrazie/lualdap", license = "MIT" } dependencies = { "lua >= 5.1", } external_dependencies = { LDAP = { header = "ldap.h", library = "ldap", }, LBER = { header = "lber.h", library = "lber", }, } build = { type = "make", variables = { COVERAGE="$(COVERAGE)", JUNITXML="$(JUNITXML)", }, build_variables = { CFLAGS="$(CFLAGS) -std=c89 -pedantic -Wall -Werror", LIBFLAG="$(LIBFLAG)", LUA_LIBDIR="$(LUA_LIBDIR)", LUA_BINDIR="$(LUA_BINDIR)", LUA_INCDIR="$(LUA_INCDIR)", LUA="$(LUA)", LDAP_LIBDIR="$(LDAP_LIBDIR)", LDAP_INCDIR="$(LDAP_INCDIR)", LBER_LIBDIR="$(LBER_LIBDIR)", LBER_INCDIR="$(LBER_INCDIR)", }, install_variables = { INST_PREFIX="$(PREFIX)", INST_BINDIR="$(BINDIR)", INST_LIBDIR="$(LIBDIR)", INST_LUADIR="$(LUADIR)", INST_CONFDIR="$(CONFDIR)", }, } lualdap-1.4.0/rockspec/lualdap-1.2.5-1.rockspec000066400000000000000000000023071452140135600207260ustar00rootroot00000000000000package="lualdap" version="1.2.5-1" source = { url = "git://github.com/lualdap/lualdap", tag = "v1.2.5", } description = { summary = "Simple interface from Lua to an LDAP Client", detailed = [[ Simple interface from Lua to an LDAP client. ]], homepage = "https://github.com/bdellegrazie/lualdap", license = "MIT" } dependencies = { "lua >= 5.1", } external_dependencies = { LDAP = { header = "ldap.h", library = "ldap", }, LBER = { header = "lber.h", library = "lber", }, } build = { type = "make", variables = { COVERAGE="$(COVERAGE)", JUNITXML="$(JUNITXML)", }, build_variables = { CFLAGS="$(CFLAGS) -std=c89 -pedantic -Wall -Werror", LIBFLAG="$(LIBFLAG)", LUA_LIBDIR="$(LUA_LIBDIR)", LUA_BINDIR="$(LUA_BINDIR)", LUA_INCDIR="$(LUA_INCDIR)", LUA="$(LUA)", LDAP_LIBDIR="$(LDAP_LIBDIR)", LDAP_INCDIR="$(LDAP_INCDIR)", LBER_LIBDIR="$(LBER_LIBDIR)", LBER_INCDIR="$(LBER_INCDIR)", }, install_variables = { INST_PREFIX="$(PREFIX)", INST_BINDIR="$(BINDIR)", INST_LIBDIR="$(LIBDIR)", INST_LUADIR="$(LUADIR)", INST_CONFDIR="$(CONFDIR)", }, } lualdap-1.4.0/rockspec/lualdap-1.2.6-1.rockspec000066400000000000000000000027361452140135600207350ustar00rootroot00000000000000package = 'lualdap' version= '1.2.6-1' source = { url = 'git://github.com/lualdap/lualdap', tag = 'v1.2.6', } description = { summary = "A Lua interface to the OpenLDAP library", detailed = [[ LuaLDAP is a simple interface from Lua to an LDAP client, in fact it is a bind to OpenLDAP. It enables a Lua program to connect to an LDAP server; execute any operation (search, add, compare, delete, modify and rename); retrieve entries and references of the search result. ]], license = 'MIT', homepage = 'https://lualdap.github.io/lualdap/', } dependencies = { 'lua >= 5.1' } external_dependencies = { platforms = { unix = { LDAP = { header = 'ldap.h', library = 'ldap', }, }, } } build = { type = 'builtin', modules = { lualdap = { sources = { 'src/lualdap.c' }, }, }, platforms = { unix = { modules = { lualdap = { libdirs = { '$(LDAP_LIBDIR)' }, incdirs = { '$(LDAP_INCDIR)' }, libraries = { 'ldap', 'lber' }, }, }, }, windows = { modules = { lualdap = { defines = { 'WIN32', 'WINLDAP' }, libraries = { 'wldap32' }, }, }, }, }, copy_directories = { 'docs' }, } lualdap-1.4.0/rockspec/lualdap-1.3.0-1.rockspec000066400000000000000000000027361452140135600207300ustar00rootroot00000000000000package = 'lualdap' version= '1.3.0-1' source = { url = 'git://github.com/lualdap/lualdap', tag = 'v1.3.0', } description = { summary = "A Lua interface to the OpenLDAP library", detailed = [[ LuaLDAP is a simple interface from Lua to an LDAP client, in fact it is a bind to OpenLDAP. It enables a Lua program to connect to an LDAP server; execute any operation (search, add, compare, delete, modify and rename); retrieve entries and references of the search result. ]], license = 'MIT', homepage = 'https://lualdap.github.io/lualdap/', } dependencies = { 'lua >= 5.1' } external_dependencies = { platforms = { unix = { LDAP = { header = 'ldap.h', library = 'ldap', }, }, } } build = { type = 'builtin', modules = { lualdap = { sources = { 'src/lualdap.c' }, }, }, platforms = { unix = { modules = { lualdap = { libdirs = { '$(LDAP_LIBDIR)' }, incdirs = { '$(LDAP_INCDIR)' }, libraries = { 'ldap', 'lber' }, }, }, }, windows = { modules = { lualdap = { defines = { 'WIN32', 'WINLDAP' }, libraries = { 'wldap32' }, }, }, }, }, copy_directories = { 'docs' }, } lualdap-1.4.0/rockspec/lualdap-1.3.1-1.rockspec000066400000000000000000000027361452140135600207310ustar00rootroot00000000000000package = 'lualdap' version= '1.3.1-1' source = { url = 'git://github.com/lualdap/lualdap', tag = 'v1.3.1', } description = { summary = "A Lua interface to the OpenLDAP library", detailed = [[ LuaLDAP is a simple interface from Lua to an LDAP client, in fact it is a bind to OpenLDAP. It enables a Lua program to connect to an LDAP server; execute any operation (search, add, compare, delete, modify and rename); retrieve entries and references of the search result. ]], license = 'MIT', homepage = 'https://lualdap.github.io/lualdap/', } dependencies = { 'lua >= 5.1' } external_dependencies = { platforms = { unix = { LDAP = { header = 'ldap.h', library = 'ldap', }, }, } } build = { type = 'builtin', modules = { lualdap = { sources = { 'src/lualdap.c' }, }, }, platforms = { unix = { modules = { lualdap = { libdirs = { '$(LDAP_LIBDIR)' }, incdirs = { '$(LDAP_INCDIR)' }, libraries = { 'ldap', 'lber' }, }, }, }, windows = { modules = { lualdap = { defines = { 'WIN32', 'WINLDAP' }, libraries = { 'wldap32' }, }, }, }, }, copy_directories = { 'docs' }, } lualdap-1.4.0/rockspec/lualdap-1.4.0-1.rockspec000066400000000000000000000027361452140135600207310ustar00rootroot00000000000000package = 'lualdap' version= '1.4.0-1' source = { url = 'git://github.com/lualdap/lualdap', tag = 'v1.4.0', } description = { summary = "A Lua interface to the OpenLDAP library", detailed = [[ LuaLDAP is a simple interface from Lua to an LDAP client, in fact it is a bind to OpenLDAP. It enables a Lua program to connect to an LDAP server; execute any operation (search, add, compare, delete, modify and rename); retrieve entries and references of the search result. ]], license = 'MIT', homepage = 'https://lualdap.github.io/lualdap/', } dependencies = { 'lua >= 5.1' } external_dependencies = { platforms = { unix = { LDAP = { header = 'ldap.h', library = 'ldap', }, }, } } build = { type = 'builtin', modules = { lualdap = { sources = { 'src/lualdap.c' }, }, }, platforms = { unix = { modules = { lualdap = { libdirs = { '$(LDAP_LIBDIR)' }, incdirs = { '$(LDAP_INCDIR)' }, libraries = { 'ldap', 'lber' }, }, }, }, windows = { modules = { lualdap = { defines = { 'WIN32', 'WINLDAP' }, libraries = { 'wldap32' }, }, }, }, }, copy_directories = { 'docs' }, } lualdap-1.4.0/rockspec/lualdap-dev-1.rockspec000066400000000000000000000023101452140135600210330ustar00rootroot00000000000000package="lualdap" version="dev-1" source = { url = "git://github.com/lualdap/lualdap", branch = "master", } description = { summary = "Simple interface from Lua to an LDAP Client", detailed = [[ Simple interface from Lua to an LDAP client. ]], homepage = "https://github.com/bdellegrazie/lualdap", license = "MIT" } dependencies = { "lua >= 5.1", } external_dependencies = { LDAP = { header = "ldap.h", library = "ldap", }, LBER = { header = "lber.h", library = "lber", }, } build = { type = "make", variables = { COVERAGE="$(COVERAGE)", JUNITXML="$(JUNITXML)", }, build_variables = { CFLAGS="$(CFLAGS) -std=c89 -pedantic -Wall -Werror", LIBFLAG="$(LIBFLAG)", LUA_LIBDIR="$(LUA_LIBDIR)", LUA_BINDIR="$(LUA_BINDIR)", LUA_INCDIR="$(LUA_INCDIR)", LUA="$(LUA)", LDAP_LIBDIR="$(LDAP_LIBDIR)", LDAP_INCDIR="$(LDAP_INCDIR)", LBER_LIBDIR="$(LBER_LIBDIR)", LBER_INCDIR="$(LBER_INCDIR)", }, install_variables = { INST_PREFIX="$(PREFIX)", INST_BINDIR="$(BINDIR)", INST_LIBDIR="$(LIBDIR)", INST_LUADIR="$(LUADIR)", INST_CONFDIR="$(CONFDIR)", }, } lualdap-1.4.0/rockspec/lualdap-dev-2.rockspec000066400000000000000000000027401452140135600210430ustar00rootroot00000000000000package = 'lualdap' version = 'dev-2' source = { url = 'git://github.com/lualdap/lualdap', branch = 'master', } description = { summary = "A Lua interface to the OpenLDAP library", detailed = [[ LuaLDAP is a simple interface from Lua to an LDAP client, in fact it is a bind to OpenLDAP. It enables a Lua program to connect to an LDAP server; execute any operation (search, add, compare, delete, modify and rename); retrieve entries and references of the search result. ]], license = 'MIT', homepage = 'https://lualdap.github.io/lualdap/', } dependencies = { 'lua >= 5.1' } external_dependencies = { platforms = { unix = { LDAP = { header = 'ldap.h', library = 'ldap', }, }, } } build = { type = 'builtin', modules = { lualdap = { sources = { 'src/lualdap.c' }, }, }, platforms = { unix = { modules = { lualdap = { libdirs = { '$(LDAP_LIBDIR)' }, incdirs = { '$(LDAP_INCDIR)' }, libraries = { 'ldap', 'lber' }, }, }, }, windows = { modules = { lualdap = { defines = { 'WIN32', 'WINLDAP' }, libraries = { 'wldap32' }, }, }, }, }, copy_directories = { 'docs' }, } lualdap-1.4.0/src/000077500000000000000000000000001452140135600137265ustar00rootroot00000000000000lualdap-1.4.0/src/lualdap.c000066400000000000000000000741471452140135600155310ustar00rootroot00000000000000/* ** LuaLDAP ** See Copyright Notice in license.md */ #include #ifdef WIN32 #include #else #include #endif #ifdef WINLDAP #include "open2winldap.h" #else #include #endif #include #include #if LUA_VERSION_NUM < 502 #define lua_rawlen(L,i) lua_objlen(L, (i)) #define luaL_setmetatable(L,n) \ (luaL_getmetatable(L, n), lua_setmetatable(L, -2)) #define luaL_newlibtable(L,l) \ lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1) #define luaL_newlib(L,l) \ (luaL_newlibtable(L, (l)), luaL_setfuncs(L, (l), 0)) #define luaL_setfuncs(L,l,n) luaL_register(L, NULL, (l)) #endif #ifdef WINLDAPAPI #define timeval l_timeval typedef ULONG ldap_int_t; typedef PCHAR ldap_pchar_t; #else typedef int ldap_int_t; typedef const char * ldap_pchar_t; #endif #define LUALDAP_PREFIX "LuaLDAP: " #define LUALDAP_TABLENAME "lualdap" #define LUALDAP_CONNECTION_METATABLE "LuaLDAP connection" #define LUALDAP_SEARCH_METATABLE "LuaLDAP search" #define LUALDAP_MOD_ADD (LDAP_MOD_ADD | LDAP_MOD_BVALUES) #define LUALDAP_MOD_DEL (LDAP_MOD_DELETE | LDAP_MOD_BVALUES) #define LUALDAP_MOD_REP (LDAP_MOD_REPLACE | LDAP_MOD_BVALUES) #define LUALDAP_NO_OP 0 /* Maximum number of attributes manipulated in an operation */ #ifndef LUALDAP_MAX_ATTRS #define LUALDAP_MAX_ATTRS 100 #endif /* Size of buffer of NULL-terminated arrays of pointers to struct values */ #ifndef LUALDAP_ARRAY_VALUES_SIZE #define LUALDAP_ARRAY_VALUES_SIZE (2 * LUALDAP_MAX_ATTRS) #endif /* Maximum number of values structures */ #ifndef LUALDAP_MAX_VALUES #define LUALDAP_MAX_VALUES (LUALDAP_ARRAY_VALUES_SIZE / 2) #endif /* LDAP connection information */ typedef struct { int version; /* LDAP version */ LDAP *ld; /* LDAP connection */ } conn_data; /* LDAP search context information */ typedef struct { int conn; /* conn_data reference */ int msgid; } search_data; /* LDAP attribute modification structure */ typedef struct { LDAPMod *attrs[LUALDAP_MAX_ATTRS + 1]; LDAPMod mods[LUALDAP_MAX_ATTRS]; int ai; BerValue *values[LUALDAP_ARRAY_VALUES_SIZE]; int vi; BerValue bvals[LUALDAP_MAX_VALUES]; int bi; } attrs_data; int luaopen_lualdap (lua_State *L); /* ** Typical error situation. */ static int faildirect (lua_State *L, const char *errmsg) { lua_pushnil (L); lua_pushstring (L, errmsg); return 2; } /* ** Get a connection object from the first stack position. */ static conn_data *getconnection (lua_State *L) { conn_data *conn = (conn_data *)luaL_checkudata (L, 1, LUALDAP_CONNECTION_METATABLE); luaL_argcheck(L, conn->ld, 1, LUALDAP_PREFIX"LDAP connection is closed"); return conn; } /* ** Get a search object from the first upvalue position. */ static search_data *getsearch (lua_State *L) { /* don't need to check upvalue's integrity */ search_data *search = (search_data *)lua_touserdata (L, lua_upvalueindex (1)); luaL_argcheck (L,search->conn!=LUA_NOREF,1,LUALDAP_PREFIX"LDAP search is closed"); return search; } /* ** Error on option. */ static int option_error (lua_State *L, const char *name, const char *type) { return luaL_error (L, LUALDAP_PREFIX"invalid value on option `%s': %s expected, got %s", name, type, lua_typename (L, lua_type (L, -1))); } /* ** Get the field named name as a string. ** The table MUST be at position 2. */ static const char *strtabparam (lua_State *L, const char *name, char *def) { lua_getfield(L, 2, name); if (lua_isnil (L, -1)) return def; else if (lua_isstring (L, -1)) return lua_tostring (L, -1); else { option_error (L, name, "string"); return NULL; } } /* ** Get the field named name as an integer. ** The table MUST be at position 2. */ static long longtabparam (lua_State *L, const char *name, int def) { lua_getfield(L, 2, name); if (lua_isnil (L, -1)) return def; else if (lua_isnumber (L, -1)) return (long)lua_tointeger (L, -1); else return option_error (L, name, "number"); } /* ** Get the field named name as a double. ** The table MUST be at position 2. */ static double numbertabparam (lua_State *L, const char *name, double def) { lua_getfield(L, 2, name); if (lua_isnil (L, -1)) return def; else if (lua_isnumber (L, -1)) return lua_tonumber (L, -1); else return option_error (L, name, "number"); } /* ** Get the field named name as a boolean. ** The table MUST be at position 2. */ static int booltabparam (lua_State *L, const char *name, int def) { lua_getfield(L, 2, name); if (lua_isnil (L, -1)) return def; else if (lua_isboolean (L, -1)) return lua_toboolean (L, -1); else return option_error (L, name, "boolean"); } /* ** Error on attribute's value. */ static void value_error (lua_State *L, const char *name) { luaL_error (L, LUALDAP_PREFIX"invalid value of attribute `%s' (%s)", name, lua_typename (L, lua_type (L, -1))); } /* ** Initialize attributes structure. */ static void A_init (attrs_data *attrs) { attrs->ai = 0; attrs->attrs[0] = NULL; attrs->vi = 0; attrs->values[0] = NULL; attrs->bi = 0; } /* ** Store the string on top of the stack on the attributes structure. ** Increment the bvals counter. */ static BerValue *A_setbval (lua_State *L, attrs_data *a, const char *n) { size_t len; BerValue *ret = &(a->bvals[a->bi]); if (a->bi >= LUALDAP_MAX_VALUES) { luaL_error (L, LUALDAP_PREFIX"too many values"); return NULL; } else if (!lua_isstring (L, -1)) { value_error (L, n); return NULL; } a->bvals[a->bi].bv_val = (char *)lua_tolstring (L, -1, &len); a->bvals[a->bi].bv_len = len; a->bi++; return ret; } /* ** Store a pointer to the value on top of the stack on the attributes structure. */ static BerValue **A_setval (lua_State *L, attrs_data *a, const char *n) { BerValue **ret = &(a->values[a->vi]); if (a->vi >= LUALDAP_ARRAY_VALUES_SIZE) { luaL_error (L, LUALDAP_PREFIX"too many values"); return NULL; } a->values[a->vi] = A_setbval (L, a, n); a->vi++; return ret; } /* ** Store a NULL pointer on the attributes structure. */ static BerValue **A_nullval (lua_State *L, attrs_data *a) { BerValue **ret = &(a->values[a->vi]); if (a->vi >= LUALDAP_ARRAY_VALUES_SIZE) { luaL_error (L, LUALDAP_PREFIX"too many values"); return NULL; } a->values[a->vi] = NULL; a->vi++; return ret; } /* ** Store the value of an attribute. ** Valid values are: ** true => no values; ** string => one value; or ** table of strings => many values. */ static BerValue **A_tab2val (lua_State *L, attrs_data *a, const char *name) { int tab = lua_gettop (L); BerValue **ret = &(a->values[a->vi]); if (lua_isboolean (L, tab) && (lua_toboolean (L, tab) == 1)) /* true */ return NULL; else if (lua_isstring (L, tab)) /* string */ A_setval (L, a, name); else if (lua_istable (L, tab)) { /* list of strings */ int i; int n = lua_rawlen (L, tab); for (i = 1; i <= n; i++) { lua_rawgeti (L, tab, i); /* push table element */ A_setval (L, a, name); } lua_pop (L, n); } else { value_error (L, name); return NULL; } A_nullval (L, a); return ret; } /* ** Set a modification value (which MUST be on top of the stack). */ static void A_setmod (lua_State *L, attrs_data *a, int op, const char *name) { if (a->ai >= LUALDAP_MAX_ATTRS) { luaL_error (L, LUALDAP_PREFIX"too many attributes"); return; } a->mods[a->ai].mod_op = op; a->mods[a->ai].mod_type = (char *)name; a->mods[a->ai].mod_bvalues = A_tab2val (L, a, name); a->attrs[a->ai] = &a->mods[a->ai]; a->ai++; } /* ** Convert a Lua table into an array of modifications. ** An array of modifications is a NULL-terminated array of LDAPMod's. */ static void A_tab2mod (lua_State *L, attrs_data *a, int tab, int op) { lua_pushnil (L); /* first key for lua_next */ while (lua_next (L, tab) != 0) { /* attribute must be a string and not a number */ if ((!lua_isnumber (L, -2)) && (lua_isstring (L, -2))) A_setmod (L, a, op, lua_tostring (L, -2)); /* pop value and leave last key on the stack as next key for lua_next */ lua_pop (L, 1); } } /* ** Terminate the array of attributes. */ static void A_lastattr (lua_State *L, attrs_data *a) { if (a->ai >= LUALDAP_MAX_ATTRS) { luaL_error (L, LUALDAP_PREFIX"too many attributes"); return; } a->attrs[a->ai] = NULL; a->ai++; } /* ** Get the result message of an operation. ** #1 upvalue == connection ** #2 upvalue == msgid ** #3 upvalue == result code of the message (ADD, DEL etc.) to be received. */ static int result_message (lua_State *L) { struct timeval *timeout = NULL; /* ??? function parameter ??? */ LDAPMessage *res; int rc; conn_data *conn = (conn_data *)lua_touserdata (L, lua_upvalueindex (1)); int msgid = (int)lua_tonumber (L, lua_upvalueindex (2)); /*int res_code = (int)lua_tonumber (L, lua_upvalueindex (3));*/ luaL_argcheck (L, conn->ld, 1, LUALDAP_PREFIX"LDAP connection is closed"); rc = ldap_result (conn->ld, msgid, LDAP_MSG_ONE, timeout, &res); if (rc == 0) return faildirect (L, LUALDAP_PREFIX"result timeout expired"); else if (rc < 0) { ldap_msgfree (res); return faildirect (L, LUALDAP_PREFIX"result error"); } else { int err, ret = 1; char *mdn, *msg; rc = ldap_parse_result (conn->ld, res, &err, &mdn, &msg, NULL, NULL, 1); if (rc != LDAP_SUCCESS) return faildirect (L, ldap_err2string (rc)); switch (err) { case LDAP_SUCCESS: case LDAP_COMPARE_TRUE: lua_pushboolean (L, 1); break; case LDAP_COMPARE_FALSE: lua_pushboolean (L, 0); break; default: lua_pushnil (L); lua_pushliteral (L, LUALDAP_PREFIX); lua_pushstring (L, ldap_err2string(err)); lua_concat (L, 2); if (msg != NULL) { lua_pushliteral (L, " ("); lua_pushstring (L, msg); lua_pushliteral (L, ")"); lua_concat (L, 4); } ret = 2; } ldap_memfree (mdn); ldap_memfree (msg); return ret; } } /* ** Push a function to process the LDAP result. */ static int create_future (lua_State *L, ldap_int_t rc, int conn, ldap_int_t msgid, int code) { if (rc != LDAP_SUCCESS) return faildirect (L, ldap_err2string (rc)); lua_pushvalue (L, conn); /* push connection as #1 upvalue */ lua_pushnumber (L, msgid); /* push msgid as #2 upvalue */ lua_pushnumber (L, code); /* push code as #3 upvalue */ lua_pushcclosure (L, result_message, 3); return 1; } /* ** Unbind from the directory. ** @param #1 LDAP connection. ** @return 1 in case of success; nothing when already closed. */ static int lualdap_close (lua_State *L) { conn_data *conn = (conn_data *)luaL_checkudata (L, 1, LUALDAP_CONNECTION_METATABLE); if (conn->ld == NULL) /* already closed */ return 0; #if defined(LDAP_API_FEATURE_X_OPENLDAP) && LDAP_API_FEATURE_X_OPENLDAP >= 20300 ldap_unbind_ext (conn->ld, NULL, NULL); #else ldap_unbind (conn->ld); #endif conn->ld = NULL; lua_pushnumber (L, 1); return 1; } /* ** Bind to the directory. ** @param #1 LDAP connection. ** @param #2 String with username. ** @param #3 String with password. ** @return LDAP connection on success. */ static int lualdap_bind_simple (lua_State *L) { conn_data *conn = getconnection (L); ldap_pchar_t who = (ldap_pchar_t) luaL_checkstring (L, 2); const char *password = luaL_checkstring (L, 3); int err; #if defined(LDAP_API_FEATURE_X_OPENLDAP) && LDAP_API_FEATURE_X_OPENLDAP >= 20300 struct berval *cred = ber_bvstrdup(password); /* FIXME: According to `man 3 ldap_sasl_bind_s` we should pass `NULL` instead of `who`. */ err = ldap_sasl_bind_s (conn->ld, who, LDAP_SASL_SIMPLE, cred, NULL, NULL, NULL); ber_bvfree(cred); #else err = ldap_bind_s (conn->ld, who, password, LDAP_AUTH_SIMPLE); #endif if (err != LDAP_SUCCESS) return faildirect (L, ldap_err2string (err)); lua_pushvalue (L, 1); return 1; } /* ** Add a new entry to the directory. ** @param #1 LDAP connection. ** @param #2 String with new entry's DN. ** @param #3 Table with new entry's attributes and values. ** @return Function to process the LDAP result. */ static int lualdap_add (lua_State *L) { conn_data *conn = getconnection (L); ldap_pchar_t dn = (ldap_pchar_t) luaL_checkstring (L, 2); attrs_data attrs; ldap_int_t rc, msgid; A_init (&attrs); if (lua_istable (L, 3)) A_tab2mod (L, &attrs, 3, LUALDAP_MOD_ADD); A_lastattr (L, &attrs); rc = ldap_add_ext (conn->ld, dn, attrs.attrs, NULL, NULL, &msgid); return create_future (L, rc, 1, msgid, LDAP_RES_ADD); } /* ** Compare a value against an entry. ** @param #1 LDAP connection. ** @param #2 String with entry's DN. ** @param #3 String with attribute's name. ** @param #4 String with attribute's value. ** @return Function to process the LDAP result. */ static int lualdap_compare (lua_State *L) { conn_data *conn = getconnection (L); ldap_pchar_t dn = (ldap_pchar_t) luaL_checkstring (L, 2); ldap_pchar_t attr = (ldap_pchar_t) luaL_checkstring (L, 3); BerValue bvalue; ldap_int_t rc, msgid; size_t len; bvalue.bv_val = (char *)luaL_checklstring (L, 4, &len); bvalue.bv_len = len; rc = ldap_compare_ext (conn->ld, dn, attr, &bvalue, NULL, NULL, &msgid); return create_future (L, rc, 1, msgid, LDAP_RES_COMPARE); } /* ** Delete an entry. ** @param #1 LDAP connection. ** @param #2 String with entry's DN. ** @return Boolean. */ static int lualdap_delete (lua_State *L) { conn_data *conn = getconnection (L); ldap_pchar_t dn = (ldap_pchar_t) luaL_checkstring (L, 2); ldap_int_t rc, msgid; rc = ldap_delete_ext (conn->ld, dn, NULL, NULL, &msgid); return create_future (L, rc, 1, msgid, LDAP_RES_DELETE); } /* ** Convert a string into an internal LDAP_MOD operation code. */ static int op2code (const char *s) { if (!s) return LUALDAP_NO_OP; switch (*s) { case '+': return LUALDAP_MOD_ADD; case '-': return LUALDAP_MOD_DEL; case '=': return LUALDAP_MOD_REP; default: return LUALDAP_NO_OP; } } /* ** Modify an entry. ** @param #1 LDAP connection. ** @param #2 String with entry's DN. ** @param #3, #4... Tables with modifications to apply. ** @return True on success or nil, error message otherwise. */ static int lualdap_modify (lua_State *L) { conn_data *conn = getconnection (L); ldap_pchar_t dn = (ldap_pchar_t) luaL_checkstring (L, 2); attrs_data attrs; ldap_int_t rc, msgid; int param = 3; A_init (&attrs); while (lua_istable (L, param)) { int op; /* get operation ('+','-','=' operations allowed) */ lua_rawgeti (L, param, 1); op = op2code (lua_tostring (L, -1)); if (op == LUALDAP_NO_OP) return luaL_error (L, LUALDAP_PREFIX"forgotten operation on argument #%d", param); /* get array of attributes and values */ A_tab2mod (L, &attrs, param, op); param++; } A_lastattr (L, &attrs); rc = ldap_modify_ext (conn->ld, dn, attrs.attrs, NULL, NULL, &msgid); return create_future (L, rc, 1, msgid, LDAP_RES_MODIFY); } /* ** Change the distinguished name of an entry. */ static int lualdap_rename (lua_State *L) { conn_data *conn = getconnection (L); ldap_pchar_t dn = (ldap_pchar_t) luaL_checkstring (L, 2); ldap_pchar_t rdn = (ldap_pchar_t) luaL_checkstring (L, 3); ldap_pchar_t par = (ldap_pchar_t) luaL_optlstring (L, 4, NULL, NULL); const int del = luaL_optnumber (L, 5, 0); ldap_int_t msgid; ldap_int_t rc = ldap_rename (conn->ld, dn, rdn, par, del, NULL, NULL, &msgid); return create_future (L, rc, 1, msgid, LDAP_RES_MODDN); } /* ** Push an attribute value (or a table of values) on top of the stack. ** @param L lua_State. ** @param ld LDAP Connection. ** @param entry Current entry. ** @param attr Name of entry's attribute to get values from. ** @return 1 in case of success. */ static int push_values (lua_State *L, LDAP *ld, LDAPMessage *entry, char *attr) { int i, n; BerValue **vals = ldap_get_values_len (ld, entry, attr); n = ldap_count_values_len (vals); if (n == 0) /* no values */ lua_pushboolean (L, 1); else if (n == 1) /* just one value */ lua_pushlstring (L, vals[0]->bv_val, vals[0]->bv_len); else { /* Multiple values */ lua_newtable (L); for (i = 0; i < n; i++) { lua_pushlstring (L, vals[i]->bv_val, vals[i]->bv_len); lua_rawseti (L, -2, i+1); } } ldap_value_free_len (vals); return 1; } /* ** Store entry's attributes and values at the given table. ** @param entry Current entry. ** @param tab Absolute stack index of the table. */ static void set_attribs (lua_State *L, LDAP *ld, LDAPMessage *entry, int tab) { char *attr; BerElement *ber = NULL; for (attr = ldap_first_attribute (ld, entry, &ber); attr != NULL; attr = ldap_next_attribute (ld, entry, ber)) { lua_pushstring (L, attr); push_values (L, ld, entry, attr); lua_rawset (L, tab); /* tab[attr] = vals */ ldap_memfree (attr); } ber_free (ber, 0); /* don't need to test if (ber == NULL) */ } /* ** Get the distinguished name of the given entry and pushes it on the stack. */ static void push_dn (lua_State *L, LDAP *ld, LDAPMessage *entry) { char *dn = ldap_get_dn (ld, entry); lua_pushstring (L, dn); ldap_memfree (dn); } /* ** Release connection reference. */ static void search_close (lua_State *L, search_data *search) { luaL_unref (L, LUA_REGISTRYINDEX, search->conn); search->conn = LUA_NOREF; } /* ** Retrieve next message... ** @return #1 entry's distinguished name. ** @return #2 table with entry's attributes and values. */ static int next_message (lua_State *L) { search_data *search = getsearch (L); conn_data *conn; struct timeval *timeout = NULL; /* ??? function parameter ??? */ LDAPMessage *res; int rc; int ret; lua_rawgeti (L, LUA_REGISTRYINDEX, search->conn); conn = (conn_data *)lua_touserdata (L, -1); /* get connection */ rc = ldap_result (conn->ld, search->msgid, LDAP_MSG_ONE, timeout, &res); if (rc == 0) return faildirect (L, LUALDAP_PREFIX"result timeout expired"); else if (rc == -1) return faildirect (L, LUALDAP_PREFIX"result error"); else if (rc == LDAP_RES_SEARCH_RESULT) { /* last message => nil */ /* close search object to avoid reuse */ search_close (L, search); ret = 0; } else { LDAPMessage *msg = ldap_first_message (conn->ld, res); switch (ldap_msgtype (msg)) { case LDAP_RES_SEARCH_ENTRY: { LDAPMessage *entry = ldap_first_entry (conn->ld, msg); push_dn (L, conn->ld, entry); lua_newtable (L); set_attribs (L, conn->ld, entry, lua_gettop (L)); ret = 2; /* two return values */ break; } /*No reference to LDAP_RES_SEARCH_REFERENCE on MSDN. Maybe there is a replacement to it?*/ #ifdef LDAP_RES_SEARCH_REFERENCE case LDAP_RES_SEARCH_REFERENCE: { LDAPMessage *ref = ldap_first_reference (conn->ld, msg); push_dn (L, conn->ld, ref); /* is this supposed to work? */ lua_pushnil (L); ret = 2; /* two return values */ break; } #endif case LDAP_RES_SEARCH_RESULT: /* close search object to avoid reuse */ search_close (L, search); ret = 0; break; default: ldap_msgfree (res); return luaL_error (L, LUALDAP_PREFIX"error on search result chain"); } } ldap_msgfree (res); return ret; } /* ** Convert a string to one of the possible scopes of the search. */ static int string2scope (lua_State *L, const char *s) { if ((s == NULL) || (*s == '\0')) return LDAP_SCOPE_DEFAULT; switch (*s) { case 'b': return LDAP_SCOPE_BASE; case 'o': return LDAP_SCOPE_ONELEVEL; case 's': return LDAP_SCOPE_SUBTREE; default: return luaL_error (L, LUALDAP_PREFIX"invalid search scope `%s'", s); } } /* ** Close the search object. */ static int lualdap_search_close (lua_State *L) { search_data *search = (search_data *)luaL_checkudata (L, 1, LUALDAP_SEARCH_METATABLE); if (search->conn == LUA_NOREF) return 0; search_close (L, search); lua_pushnumber (L, 1); return 1; } /* ** Create a search object and leaves it on top of the stack. */ static void create_search (lua_State *L, int conn_index, int msgid) { search_data *search = (search_data *)lua_newuserdata (L, sizeof (search_data)); luaL_setmetatable (L, LUALDAP_SEARCH_METATABLE); search->conn = LUA_NOREF; search->msgid = msgid; lua_pushvalue (L, conn_index); search->conn = luaL_ref (L, LUA_REGISTRYINDEX); } /* ** Fill in the attrs array, according to the attrs parameter. */ static void get_attrs_param (lua_State *L, char *attrs[]) { lua_getfield(L, 2, "attrs"); if (lua_isstring (L, -1)) { attrs[0] = (char *)lua_tostring (L, -1); attrs[1] = NULL; } else if (!lua_istable (L, -1)) attrs[0] = NULL; else { int i; int n = lua_rawlen(L, -1); if (LUALDAP_MAX_ATTRS < (n+1)) luaL_error (L, LUALDAP_PREFIX"too many arguments"); luaL_checkstack(L, n, NULL); for (i = 0; i < n; i++) { lua_rawgeti (L, -1, i+1); /* push table element */ if (lua_isstring (L, -1)) { attrs[i] = (char *)lua_tostring (L, -1); lua_pop(L, 1); } else { luaL_error (L, LUALDAP_PREFIX"invalid value #%d", i+1); } } attrs[n] = NULL; } } /* ** Fill in the struct timeval, according to the timeout parameter. */ static struct timeval *get_timeout_param (lua_State *L, struct timeval *st) { double t = numbertabparam (L, "timeout", 0.0); if(t <= 0.0) return NULL; /* No timeout, block */ st->tv_sec = (long)t; st->tv_usec = (long)(1000000.0 * (t - (double)st->tv_sec)); return st; } /* ** Perform a search operation. ** @return #1 Function to iterate over the result entries. ** @return #2 nil. ** @return #3 nil as first entry. ** The search result is defined as an upvalue of the iterator. */ static int lualdap_search (lua_State *L) { conn_data *conn = getconnection (L); ldap_pchar_t base; ldap_pchar_t filter; char *attrs[LUALDAP_MAX_ATTRS]; int scope, attrsonly, msgid, rc, sizelimit; struct timeval st, *timeout; if (!lua_istable (L, 2)) return luaL_error (L, LUALDAP_PREFIX"no search specification"); get_attrs_param (L, attrs); /* get other parameters */ attrsonly = booltabparam (L, "attrsonly", 0); base = (ldap_pchar_t) strtabparam (L, "base", NULL); filter = (ldap_pchar_t) strtabparam (L, "filter", NULL); scope = string2scope (L, strtabparam (L, "scope", NULL)); sizelimit = longtabparam (L, "sizelimit", LDAP_NO_LIMIT); timeout = get_timeout_param (L, &st); rc = ldap_search_ext (conn->ld, base, scope, filter, attrs, attrsonly, NULL, NULL, timeout, sizelimit, &msgid); if (rc != LDAP_SUCCESS) return luaL_error (L, LUALDAP_PREFIX"%s", ldap_err2string (rc)); create_search (L, 1, msgid); lua_pushcclosure (L, next_message, 1); lua_pushvalue(L, 2); return 2; } /* ** Return the name of the object's metatable. ** This function is used by `tostring'. */ static int lualdap_conn_tostring (lua_State *L) { conn_data *conn = luaL_checkudata(L, 1, LUALDAP_CONNECTION_METATABLE); if (conn->ld == NULL) lua_pushfstring (L, "%s (closed)", LUALDAP_CONNECTION_METATABLE); else lua_pushfstring (L, "%s (%p)", LUALDAP_CONNECTION_METATABLE, (void*)conn); return 1; } /* ** Return the name of the object's metatable. ** This function is used by `tostring'. */ static int lualdap_search_tostring (lua_State *L) { search_data *search = luaL_checkudata(L, 1, LUALDAP_SEARCH_METATABLE); if (search->conn == LUA_NOREF) lua_pushfstring (L, "%s (closed)", LUALDAP_SEARCH_METATABLE); else lua_pushfstring (L, "%s (%p)", LUALDAP_SEARCH_METATABLE, (void*)search); return 1; } /* ** Create a metatable. */ static void lualdap_createmeta_conn (lua_State *L) { static const luaL_Reg metamethods[] = { {"__gc", lualdap_close}, {"__tostring", lualdap_conn_tostring}, /* placeholders */ {"__index", NULL}, {"__metatable", NULL}, {NULL, NULL} }; static const luaL_Reg methods[] = { {"close", lualdap_close}, {"bind_simple", lualdap_bind_simple}, {"add", lualdap_add}, {"compare", lualdap_compare}, {"delete", lualdap_delete}, {"modify", lualdap_modify}, {"rename", lualdap_rename}, {"search", lualdap_search}, {NULL, NULL} }; luaL_newmetatable (L, LUALDAP_CONNECTION_METATABLE); luaL_setfuncs(L, metamethods, 0); /* add metamethods to new metatable */ luaL_newlibtable(L, methods); /* create method table */ luaL_setfuncs(L, methods, 0); /* add file methods to method table */ lua_setfield(L, -2, "__index"); /* metatable.__index = method table */ lua_pushliteral(L,LUALDAP_PREFIX"you're not allowed to get this metatable"); lua_setfield (L, -2, "__metatable"); lua_pop(L, 1); /* pop metatable */ } /* ** Create a metatable. */ static void lualdap_createmeta_search (lua_State *L) { static const luaL_Reg metamethods[] = { {"__gc", lualdap_search_close}, {"__tostring", lualdap_search_tostring}, /* placeholders */ {"__metatable", NULL}, {NULL, NULL} }; luaL_newmetatable (L, LUALDAP_SEARCH_METATABLE); luaL_setfuncs(L, metamethods, 0); /* add metamethods to new metatable */ lua_pushliteral(L,LUALDAP_PREFIX"you're not allowed to get this metatable"); lua_setfield (L, -2, "__metatable"); lua_pop(L, 1); /* pop metatable */ } #if !defined(WINLDAP) /* ** Open and initialize a connection to a server (without binding). ** @param #1 String with URI. ** @return #1 Userdata with connection structure. */ static int lualdap_initialize (lua_State *L) { ldap_pchar_t uri = (ldap_pchar_t) luaL_checkstring (L, 1); conn_data *conn = (conn_data *)lua_newuserdata (L, sizeof(conn_data)); int err; int lev=7; /* Initialize */ luaL_setmetatable (L, LUALDAP_CONNECTION_METATABLE); conn->version = 0; #if defined(LDAP_API_FEATURE_X_OPENLDAP) && LDAP_API_FEATURE_X_OPENLDAP >= 20300 err = ldap_initialize (&conn->ld, uri); if (err != LDAP_SUCCESS) return faildirect(L, ldap_err2string(err)); #else # error Unsupported LDAP library version #endif /* Set protocol version */ conn->version = LDAP_VERSION3; if (ldap_set_option (conn->ld, LDAP_OPT_PROTOCOL_VERSION, &conn->version) != LDAP_OPT_SUCCESS) return faildirect(L, LUALDAP_PREFIX"Error setting LDAP version"); ldap_set_option(conn->ld, LDAP_OPT_DEBUG_LEVEL, &lev); return 1; } #endif /* ** Open a connection to a server. ** @param #1 String with hostname. ** @param #2 Boolean indicating if TLS must be used. ** @param #3 Number for connection timeout (optional). ** @return #1 Userdata with connection structure. */ static int lualdap_open (lua_State *L) { ldap_pchar_t host = (ldap_pchar_t) luaL_checkstring (L, 1); int use_tls = lua_toboolean (L, 2); double timeout = lua_tonumber (L, 3); conn_data *conn = (conn_data *)lua_newuserdata (L, sizeof(conn_data)); #if defined(LDAP_API_FEATURE_X_OPENLDAP) && LDAP_API_FEATURE_X_OPENLDAP >= 20300 int err; #endif /* Initialize */ luaL_setmetatable (L, LUALDAP_CONNECTION_METATABLE); conn->version = 0; #if defined(LDAP_API_FEATURE_X_OPENLDAP) && LDAP_API_FEATURE_X_OPENLDAP >= 20300 if (strstr(host, "://") != NULL) { err = ldap_initialize(&conn->ld, host); } else { lua_getglobal (L, "string"); lua_getfield (L, -1, "gsub"); if (!lua_isfunction (L, -1)) return faildirect (L, LUALDAP_PREFIX"string.gsub broken"); lua_pushvalue (L, 1); /* host */ lua_pushstring (L, "(%S+)"); lua_pushstring (L, "ldap://%1"); lua_call (L, 3, 1); /* string.gsub(host, '(%S+)', 'ldap://%1') */ /* ldap_initialize handles a whitespace-separated list of hostnames */ err = ldap_initialize(&conn->ld, lua_tostring (L, -1)); lua_pop(L, 2); } if (err != LDAP_SUCCESS) #else conn->ld = ldap_init (host, LDAP_PORT); if (conn->ld == NULL) #endif return faildirect(L,LUALDAP_PREFIX"Error connecting to server"); /* LDAP_OPT_TIMEOUT and LDAP_OPT_NETWORK_TIMEOUT are not supported by WinLDAP. * WinLDAP does have LDAP_OPT_SEND_TIMEOUT; it is yet to be determined whether * that would work as a connection timeout */ #if !defined(WINLDAP) /* Set timeout (optionally) */ if (timeout > 0.0) { struct timeval optTimeout; optTimeout.tv_sec = (long)timeout; optTimeout.tv_usec = (long)(1000000.0 * (timeout - (double)optTimeout.tv_sec)); if (ldap_set_option (conn->ld, LDAP_OPT_TIMEOUT, &optTimeout) != LDAP_OPT_SUCCESS) return faildirect(L, LUALDAP_PREFIX"Could not set timeout"); if (ldap_set_option (conn->ld, LDAP_OPT_NETWORK_TIMEOUT, &optTimeout) != LDAP_OPT_SUCCESS) return faildirect(L, LUALDAP_PREFIX"Could not set network timeout"); } #endif /* Set protocol version */ conn->version = LDAP_VERSION3; if (ldap_set_option (conn->ld, LDAP_OPT_PROTOCOL_VERSION, &conn->version) != LDAP_OPT_SUCCESS) return faildirect(L, LUALDAP_PREFIX"Error setting LDAP version"); /* Use TLS */ if (use_tls) { int rc = ldap_start_tls_s (conn->ld, NULL, NULL); if (rc != LDAP_SUCCESS) return faildirect (L, ldap_err2string (rc)); } return 1; } /* ** Open and initialize a connection to a server. ** @param #1 String with hostname. ** @param #2 String with username. ** @param #3 String with password. ** @param #4 Boolean indicating if TLS must be used. ** @param #5 Number for connection timeout (optional). ** @return #1 Userdata with connection structure. */ static int lualdap_open_simple (lua_State *L) { ldap_pchar_t host = (ldap_pchar_t) luaL_checkstring (L, 1); ldap_pchar_t who = (ldap_pchar_t) luaL_optstring (L, 2, ""); const char *password = luaL_optstring (L, 3, ""); int use_tls = lua_toboolean (L, 4); double timeout = lua_tonumber (L, 5); /* Open */ lua_pushcfunction (L, lualdap_open); lua_pushstring (L, host); lua_pushboolean (L, use_tls); lua_pushnumber (L, timeout); lua_call (L, 3, 2); if (lua_isnil (L, -2)) { return 2; /* nil, msg */ } else { lua_pop (L, 1); /* keep only the userdata (LDAP connection) */ } /* Bind to a server */ lua_pushcfunction (L, lualdap_bind_simple); lua_pushvalue (L, -2); /* connection */ lua_pushstring (L, who); lua_pushstring (L, password); lua_call (L, 3, 2); if (lua_isnil (L, -2)) { return 2; /* Pass through in case of errors */ } else { lua_pop (L, 2); /* Discard return values from lualdap_bind_simple */ } return 1; } /* ** Assumes the table is on top of the stack. */ static void set_info (lua_State *L) { lua_pushliteral (L, "Copyright (C) 2003-2007 Kepler Project"); lua_setfield (L, -2, "_COPYRIGHT"); lua_pushliteral (L, "LuaLDAP is a simple interface from Lua to an LDAP client"); lua_setfield (L, -2, "_DESCRIPTION"); lua_pushliteral (L, "LuaLDAP 1.4.0"); lua_setfield (L, -2, "_VERSION"); } /* ** Create ldap table and register the open method. */ int luaopen_lualdap (lua_State *L) { static const struct luaL_Reg lualdap[] = { #if !defined(WINLDAP) {"initialize", lualdap_initialize}, #endif {"open", lualdap_open}, {"open_simple", lualdap_open_simple}, /* placeholders */ {"_COPYRIGHT", NULL}, {"_DESCRIPTION", NULL}, {"_VERSION", NULL}, {NULL, NULL}, }; lualdap_createmeta_conn (L); lualdap_createmeta_search (L); luaL_newlib(L, lualdap); /* In Lua 5.2 "modules are not expected to set global variables": https://www.lua.org/manual/5.2/manual.html#8.2 */ #if LUA_VERSION_NUM < 502 lua_pushvalue(L, -1); lua_setglobal(L, LUALDAP_TABLENAME); #endif set_info (L); return 1; } lualdap-1.4.0/src/lualdap.def000066400000000000000000000001311452140135600160230ustar00rootroot00000000000000LIBRARY lualdap.dll DESCRIPTION "LuaLDAP" VERSION 1.4.0.0 EXPORTS luaopen_lualdap lualdap-1.4.0/src/open2winldap.h000066400000000000000000000031021452140135600164750ustar00rootroot00000000000000#include /* For some reason MSDN mentions LDAP_RES_MODDN, but not LDAP_RES_MODRDN. */ #ifndef LDAP_RES_MODDN #define LDAP_RES_MODDN LDAP_RES_MODRDN #endif /* MSDN doesn't mention LDAP_OPT_SUCCESS, it uses LDAP_SUCCESS intead */ #ifndef LDAP_OPT_SUCCESS #define LDAP_OPT_SUCCESS LDAP_SUCCESS #endif /* MSDN doesn't mention LDAP_SCOPE_DEFAULT, so default will be LDAP_SCOPE_SUBTREE */ #ifndef LDAP_SCOPE_DEFAULT #define LDAP_SCOPE_DEFAULT LDAP_SCOPE_SUBTREE #endif /* MSDN doesn't mention this function at all. Unfortunately, LDAPMessage an opaque type. */ #define ldap_msgtype(m) ((m)->lm_msgtype) #define ldap_first_message ldap_first_entry /* The WinLDAP API allows comparisons against either string or binary values */ #undef ldap_compare_ext /* The WinLDAP API uses ULONG seconds instead of a struct timeval. */ #undef ldap_search_ext /* The WinLDAP API has a different number of arguments for this */ #undef ldap_start_tls_s #ifdef UNICODE #define ldap_compare_ext(ld,dn,a,v,sc,cc,msg) \ ldap_compare_extW(ld,dn,a,0,v,sc,cc,msg) #define ldap_search_ext(ld,base,scope,f,a,o,sc,cc,t,s,msg) \ ldap_search_extW(ld,base,scope,f,a,o,sc,cc,(t)?(t)->tv_sec:0,s,msg) #define ldap_start_tls_s(ld,sc,cc) \ ldap_start_tls_sW(ld,0,0,sc,cc) #else #define ldap_compare_ext(ld,dn,a,v,sc,cc,msg) \ ldap_compare_extA(ld,dn,a,0,v,sc,cc,msg) #define ldap_search_ext(ld,base,scope,f,a,o,sc,cc,t,s,msg) \ ldap_search_extA(ld,base,scope,f,a,o,sc,cc,(t)?(t)->tv_sec:0,s,msg) #define ldap_start_tls_s(ld,sc,cc) \ ldap_start_tls_sA(ld,0,0,sc,cc) #endif lualdap-1.4.0/tests.old/000077500000000000000000000000001452140135600150565ustar00rootroot00000000000000lualdap-1.4.0/tests.old/.luacheckrc000066400000000000000000000004111452140135600171570ustar00rootroot00000000000000codes = true globals = { 'lualdap' } ignore = { '211', -- unused variable '213', -- unused loop variable '311', -- value assigned to variable is unused '411', -- variable was previously defined '421', -- shadowing definition of variable } lualdap-1.4.0/tests.old/test.lua000077500000000000000000000330161452140135600165460ustar00rootroot00000000000000#!/usr/bin/env lua --------------------------------------------------------------------- -- LuaLDAP test file. -- This test will create a copy of an existing entry on the -- directory to work on. This new entry will be modified, -- renamed and deleted at the end. -- -- See Copyright Notice in license.md --------------------------------------------------------------------- --[=[ --------------------------------------------------------------------- -- Print attributes. --------------------------------------------------------------------- local function print_attrs (dn, attrs) if not dn then io.write ("nil\n") return end io.write (string.format ("\t[%s]\n", dn)) for name, values in pairs (attrs) do io.write ("["..name.."] : ") local tv = type (values) if tv == "string" then io.write (values) elseif tv == "table" then local n = #values for i = 1, n-1 do io.write (values[i]..",") end io.write (values[n]) end io.write ("\n") end end --]=] --------------------------------------------------------------------- -- clone a table. --------------------------------------------------------------------- local function clone (tab) local new = {} for i, v in pairs (tab) do new[i] = v end return new end --------------------------------------------------------------------- -- checks for a value and throw an error if it is not the expected. --------------------------------------------------------------------- local function assert2 (expected, value, msg) if not msg then msg = '' else msg = tostring(msg)..'\n' end local ret = assert (value == expected, msg.."wrong value (["..tostring(value).."] instead of ".. tostring(expected)..")") io.write('.') return ret end --------------------------------------------------------------------- -- object test. --------------------------------------------------------------------- local function test_object (obj, objmethods) -- checking object type. assert2 ("userdata", type(obj), "incorrect object type") -- trying to get metatable. assert2 ("LuaLDAP: you're not allowed to get this metatable", getmetatable(obj), "error permitting access to object's metatable") -- trying to set metatable. assert2 (false, pcall (setmetatable, obj, {})) -- checking existence of object's methods. for i = 1, #objmethods do local method = obj[objmethods[i]] assert2 ("function", type(method)) assert2 (false, pcall (method), "no 'self' parameter accepted") end return obj end local function CONN_OK (obj, err) if obj == nil then error (err, 2) end return test_object (obj, { "close", "add", "compare", "delete", "modify", "rename", "search", }) end local DN_PAT = "^([^,=]+)%=([^,]+)%,?(.*)$" local HOSTNAME local BASE local WHO local BIND_DN local PASSWORD local LD local CLOSED_LD local DN local ENTRY local NEW local NEW_DN --------------------------------------------------------------------- -- basic checking test. --------------------------------------------------------------------- local function basic_test () local ld = CONN_OK (lualdap.open_simple (HOSTNAME, BIND_DN, PASSWORD)) assert2 (1, ld:close(), "couldn't close connection") -- trying to close without a connection. assert2 (false, pcall (ld.close)) -- trying to close an invalid connection. assert2 (false, pcall (ld.close, io.output())) -- trying to use a closed connection. local _,_,rdn_name,rdn_value = string.find (BASE, DN_PAT) assert2 (false, pcall (ld.compare, ld, BASE, rdn_name, rdn_value), "permitting the use of a closed connection") -- it is ok to close a closed object, but nil is returned instead of 1. assert2 (nil, ld:close()) -- trying to connect to an invalid host. assert2 (nil, lualdap.open_simple ("unknown-server"), "this should be an error") -- reopen the connection. -- first, try using TLS local ok = lualdap.open_simple (HOSTNAME, BIND_DN, PASSWORD, true) if not ok then -- second, try without TLS io.write ("\nWarning! Couldn't connect with TLS. Trying again without it.") ok = lualdap.open_simple (HOSTNAME, BIND_DN, PASSWORD, false) end LD = CONN_OK (ok) CLOSED_LD = ld collectgarbage() end --------------------------------------------------------------------- -- checks return value which should be a function AND also its return value. --------------------------------------------------------------------- local function check_future (ret, method, ...) local ok, f = pcall (method, ...) assert (ok, f) assert2 ("function", type(f)) assert2 (ret, f()) io.write('.') end --------------------------------------------------------------------- -- checking compare operation. --------------------------------------------------------------------- local function compare_test () local _,_,rdn_name,rdn_value = string.find (BASE, DN_PAT) assert (type(rdn_name) == "string", "could not extract RDN name") assert (type(rdn_value) == "string", "could not extract RDN value") -- comparing against the correct value. check_future (true, LD.compare, LD, BASE, rdn_name, rdn_value) -- comparing against a wrong value. check_future (false, LD.compare, LD, BASE, rdn_name, rdn_value..'_') -- comparing against an incorrect attribute name. check_future (nil, LD.compare, LD, BASE, rdn_name..'x', rdn_value) -- comparing on a wrong base. check_future (nil, LD.compare, LD, 'qwerty', rdn_name, rdn_value) -- comparing with a closed connection. assert2 (false, pcall (LD.compare, CLOSED_LD, BASE, rdn_name, rdn_value)) -- comparing with an invalid userdata. assert2 (false, pcall (LD.compare, io.output(), BASE, rdn_name, rdn_value)) end --------------------------------------------------------------------- -- checking basic search operation. --------------------------------------------------------------------- local function search_test_1 () local _,_,rdn = string.find (WHO, "^([^,]+)%,.*$") local iter = LD:search { base = BASE, scope = "onelevel", sizelimit = 1, filter = "("..rdn..")", } assert2 ("function", type(iter)) collectgarbage() CONN_OK (LD) local dn, entry = iter () assert2 ("string", type(dn)) assert2 ("table", type(entry)) collectgarbage() assert2 ("function", type(iter)) CONN_OK (LD) DN, ENTRY = LD:search { base = BASE, scope = "onelevel", sizelimit = 1, filter = "("..rdn..")", }() collectgarbage() assert2 ("string", type(DN)) assert2 ("table", type(ENTRY)) end --------------------------------------------------------------------- -- checking add operation. --------------------------------------------------------------------- local function add_test () -- clone an entry. NEW = clone (ENTRY) local _,_,rdn_name, rdn_value, parent_dn = string.find (DN, DN_PAT) NEW[rdn_name] = rdn_value.."_copy" NEW_DN = string.format ("%s=%s,%s", rdn_name, NEW[rdn_name], parent_dn) -- trying to insert an entry with a wrong connection. assert2 (false, pcall (LD.add, CLOSED_LD, NEW_DN, NEW)) -- trying to insert an entry with an invalid connection. assert2 (false, pcall (LD.add, io.output(), NEW_DN, NEW)) -- trying to insert an entry with a wrong DN. local wrong_dn = string.format ("%s_x=%s,%s", rdn_name, NEW_DN, parent_dn) --assert2 (nil, LD:add (wrong_dn, NEW)) check_future (nil, LD.add, LD, wrong_dn, NEW) -- trying to insert the clone on the LDAP data base. check_future (true, LD.add, LD, NEW_DN, NEW) -- trying to reinsert the clone entry on the directory. check_future (nil, LD.add, LD, NEW_DN, NEW) end --------------------------------------------------------------------- -- checking modify operation. --------------------------------------------------------------------- local function modify_test () -- modifying without connection. assert2 (false, pcall (LD.modify, nil, NEW_DN, {})) -- modifying with a closed connection. assert2 (false, pcall (LD.modify, CLOSED_LD, NEW_DN, {})) -- modifying with an invalid userdata. assert2 (false, pcall (LD.modify, io.output(), NEW_DN, {})) -- checking invalid DN. assert2 (false, pcall (LD.modify, LD, {})) -- no modification to apply. check_future (true, LD.modify, LD, NEW_DN) -- forgotten operation on modifications table. local a_attr, a_value = next (ENTRY) assert2 (false, pcall (LD.modify, LD, NEW_DN, { [a_attr] = "abc"})) -- modifying an unknown entry. local _,_, rdn_name, rdn_value, parent_dn = string.find (NEW_DN, DN_PAT) local new_rdn = rdn_name..'='..rdn_value..'_' local new_dn = string.format ("%s,%s", new_rdn, parent_dn) check_future (nil, LD.modify, LD, new_dn) -- trying to create an undefined attribute. check_future (nil, LD.modify, LD, NEW_DN, {'+', unknown_attribute = 'a'}) end --------------------------------------------------------------------- local function count (tab) local counter = 0 for dn, entry in LD:search (tab) do counter = counter + 1 end return counter end --------------------------------------------------------------------- -- checking advanced search operation. --------------------------------------------------------------------- local function search_test_2 () local _,_,rdn = string.find (WHO, "^([^,]+)%,.*$") local iter = LD:search { base = BASE, scope = "onelevel", sizelimit = 1, filter = "("..rdn..")", } assert2 ("function", type(iter)) collectgarbage () assert2 ("function", type(iter)) local dn, entry = iter () assert2 ("string", type(dn)) assert2 ("table", type(entry)) collectgarbage () assert2 ("function", type(iter)) iter = nil collectgarbage () -- checking no search specification. assert2 (false, pcall (LD.search, LD)) -- checking invalid scope. assert2 (false, pcall (LD.search, LD, { scope = 'BASE', base = BASE, })) -- checking invalid base. check_future (nil, LD.search, LD, { base = "invalid", scope = "base", }) -- checking filter. local _,_, rdn_name, rdn_value, parent_dn = string.find (NEW_DN, DN_PAT) local filter = string.format ("(%s=%s)", rdn_name, rdn_value) assert (count { base = BASE, scope = "subtree", filter = filter, } == 1) -- checking sizelimit. assert (count { base = BASE, scope = "subtree", sizelimit = 1, } == 1) -- checking attrsonly parameter. for dn, entry in LD:search { base = BASE, scope = "subtree", attrsonly = true, } do for attr, value in pairs (entry) do assert (value == true, "attrsonly failed") end end -- checking reuse of search object. local iter = assert (LD:search { base = BASE, scope = "base", }) assert (type(iter) == "function") local dn, e1 = iter() assert (type(dn) == "string") assert (type(e1) == "table") dn, e1 = iter() assert (type(dn) == "nil") assert (type(e1) == "nil") assert2 (false, pcall (iter)) iter = nil -- checking collecting search objects. local dn, entry = LD:search { base = BASE, scope = "base" }() collectgarbage() end --------------------------------------------------------------------- -- checking rename operation. --------------------------------------------------------------------- local function rename_test () local _,_, rdn_name, rdn_value, parent_dn = string.find (NEW_DN, DN_PAT) local new_rdn = rdn_name..'='..rdn_value..'_' local new_dn = string.format ("%s,%s", new_rdn, parent_dn) -- trying to rename with no parent. check_future (true, LD.rename, LD, NEW_DN, new_rdn, nil) -- trying to rename an invalid dn. check_future (nil, LD.rename, LD, NEW_DN, new_rdn, nil) -- trying to rename with the same parent. check_future (true, LD.rename, LD, new_dn, rdn_name..'='..rdn_value, parent_dn) -- trying to rename to an inexistent parent. check_future (nil, LD.rename, LD, NEW_DN, new_rdn, new_dn) -- mal-formed DN. assert2 (false, pcall (LD.rename, LD, "")) -- trying to rename with a closed connection. assert2 (false, pcall (LD.rename, CLOSED_LD, NEW_DN, new_rdn, nil)) -- trying to rename with an invalid connection. assert2 (false, pcall (LD.rename, io.output(), NEW_DN, new_rdn, nil)) end --------------------------------------------------------------------- -- checking delete operation. --------------------------------------------------------------------- local function delete_test () -- trying to delete with a closed connection. assert2 (false, pcall (LD.delete, CLOSED_LD, NEW_DN)) -- trying to delete with an invalid connection. assert2 (false, pcall (LD.delete, io.output(), NEW_DN)) -- trying to delete new entry. check_future (true, LD.delete, LD, NEW_DN) -- trying to delete an already deleted entry. check_future (nil, LD.delete, LD, NEW_DN) -- mal-formed DN. check_future (nil, LD.delete, LD, "") -- no DN. assert2 (false, pcall (LD.delete, LD)) end --------------------------------------------------------------------- -- checking close operation. --------------------------------------------------------------------- local function close_test () assert (LD:close () == 1, "couldn't close connection") end --------------------------------------------------------------------- local tests = { { "basic checking", basic_test }, { "checking compare operation", compare_test }, { "checking basic search operation", search_test_1 }, { "checking add operation", add_test }, { "checking modify operation", modify_test }, { "checking advanced search operation", search_test_2 }, { "checking rename operation", rename_test }, { "checking delete operation", delete_test }, { "closing everything", close_test }, } --------------------------------------------------------------------- -- Main --------------------------------------------------------------------- if #arg < 3 then print (string.format ("Usage %s host[:port] base who [bind_dn [password]]", arg[0])) os.exit() end HOSTNAME = arg[1] BASE = arg[2] WHO = arg[3] BIND_DN = arg[4] PASSWORD = arg[5] lualdap = require"lualdap" assert (type(lualdap)=="table", "couldn't load LDAP library") for i = 1, #tests do local t = tests[i] io.write (t[1].." ...") t[2] () io.write (" OK !\n") end lualdap-1.4.0/tests/000077500000000000000000000000001452140135600143015ustar00rootroot00000000000000lualdap-1.4.0/tests/.luacheckrc000066400000000000000000000001641452140135600164070ustar00rootroot00000000000000codes = true max_line_length = 160 unused = false unused_args = false ignore = { '431', -- shadowing upvalue } lualdap-1.4.0/tests/openshift/000077500000000000000000000000001452140135600163005ustar00rootroot00000000000000lualdap-1.4.0/tests/openshift/setup.sh000077500000000000000000000007451452140135600200050ustar00rootroot00000000000000#!/bin/sh set -e dir=`dirname $0` . $dir/test.env ldapsearch -x -LLL -H $LDAP_URI -b $LDAP_BASE_DN objectClass=organization | grep "dc=example,dc=com" ldapadd -x -H $LDAP_URI -D $LDAP_BIND_DN -w $LDAP_BIND_PASSWORD -f $dir/test.ldif ldappasswd -x -H $LDAP_URI -D $LDAP_BIND_DN -w $LDAP_BIND_PASSWORD -s $LDAP_TEST_PASSWORD $LDAP_TEST_DN ldapsearch -x -LLL -H $LDAP_URI -D $LDAP_TEST_DN -w $LDAP_TEST_PASSWORD -b $LDAP_BASE_DN $LDAP_TEST_SUBJECT memberof | grep "memberOf: cn=group" lualdap-1.4.0/tests/openshift/test.env000066400000000000000000000004301452140135600177660ustar00rootroot00000000000000export LDAP_URI="ldap://localhost/" export LDAP_HOST="localhost" export LDAP_BASE_DN="dc=example,dc=com" export LDAP_BIND_DN="cn=Manager,dc=example,dc=com" export LDAP_BIND_PASSWORD="admin" export LDAP_TEST_DN="cn=person,dc=example,dc=com" export LDAP_TEST_PASSWORD="thepassword" lualdap-1.4.0/tests/openshift/test.ldif000066400000000000000000000003361452140135600201210ustar00rootroot00000000000000dn: cn=person,dc=example,dc=com objectClass: person objectClass: testPerson cn: person sn: person testMemberOf: group dn: cn=group,dc=example,dc=com objectClass: groupOfNames cn: group member: cn=person,dc=example,dc=com lualdap-1.4.0/tests/slapd/000077500000000000000000000000001452140135600154045ustar00rootroot00000000000000lualdap-1.4.0/tests/slapd/run-tests.sh000077500000000000000000000001071452140135600177050ustar00rootroot00000000000000#!/bin/sh tests/slapd/setup.sh . tests/slapd/test.env tests/test.lua lualdap-1.4.0/tests/slapd/setup.sh000077500000000000000000000034421452140135600171060ustar00rootroot00000000000000#!/bin/sh set -ex d=$(readlink -f "$(dirname $0)") . $d/test.env rm -rf "$d/slapd-config" "$d/slapd-data" mkdir "$d/slapd-config" "$d/slapd-data" module_path='/usr/lib/ldap' test -d "$module_path" \ || module_path='/usr/lib/openldap' schema_path='/etc/ldap/schema' test -d "$schema_path" \ || module_path='/etc/openldap/schema' # populate slapd config slapadd -F "$d/slapd-config" -n0 <